R/ich_predict.R

Defines functions ich_predict

Documented in ich_predict

#' @title Predict ICH Images
#' @description This function will take the data.frame of predictors and
#' predict the ICH voxels from the model chosen.
#'
#' @param df \code{\link{data.frame}} of predictors.  If \code{multiplier}
#' column does not exist, then \code{\link{ich_candidate_voxels}} will
#' be called
#' @param nim object of class \code{\link{nifti}}, from
#' \code{\link{make_predictors}}
#' @param model model to use for prediction,
#' either the random forest (rf) or logistic
#' @param verbose Print diagnostic output
#' @param native Should native-space predictions be given?
#' @param native_img object of class \code{\link{nifti}}, which
#' is the dimensions of the native image
#' @param transformlist Transforms list for the transformations back to native space.
#' NOTE: these will be inverted.
#' @param interpolator Interpolator for the transformation back to native space
#' @param native_thresh Threshold for re-thresholding binary mask after
#' interpolation
#' @param shiny Should shiny progress be called?
#' @param model_list list of model objects, used mainly for retraining
#' but only expert use.
#' @param smoothed_cutoffs A list with an element
#' \code{mod.dice.coef}, only expert use.
#' @param outfile filename for output file.
#' We write the smoothed, thresholded image.  If \code{native = TRUE},
#' then the file will be native space, otherwise in registered
#' space
#' @param ... Additional options passsed to \code{\link{ich_preprocess}}
#'
#' @return List of output registered and native space
#' prediction/probability images
#' @importFrom neurobase remake_img
#' @importFrom extrantsr ants_bwlabel
#' @import randomForest
#' @seealso \code{\link{ich_candidate_voxels}}
#' @export
ich_predict = function(df,
                       nim,
                       model = c("rf", "logistic", "big_rf"),
                       verbose = TRUE,
                       native = TRUE,
                       native_img = NULL,
                       transformlist = NULL,
                       interpolator = NULL,
                       native_thresh = 0.5,
                       shiny = FALSE,
                       model_list = NULL,
                       smoothed_cutoffs = NULL,
                       outfile = NULL,
                       ...) {

  # if (!have_matlab()) {
  #   stop("MATLAB Path not defined!")
  # }

  if (is.null(outfile)) {
    outfile = tempfile(fileext = ".nii.gz")
  }
  cn = colnames(df)
  if (!("multiplier" %in% cn)) {
    df$multiplier = ich_candidate_voxels(df)
  }
  df$Y = NULL
  cc = complete.cases(df)
  if (!all(cc)) {
    warning("NAs or missing in DF, removing")
    for (icn in seq(ncol(df))) {
      x = df[, icn]
      if (!(class(x) %in% c("factor", "character"))) {
        x[ !is.finite(x) ] = 0
      }
      df[, icn] = x
    }
  }
  msg = "# Making Prediction"
  if (verbose) {
    message(msg)
  }
  if (shiny) {
    shiny::incProgress(message = msg)
  }
  env = as.environment("package:ichseg")

  # Getting modlist for model and cutoff
  if (is.null(model_list)) {
    modlist.name = paste0(model, "_modlist")
    modlist = env[[modlist.name]]
  } else {
    modlist = model_list
  }
  mod = modlist$mod
  cutoff = modlist$mod.dice.coef[1, "cutoff"]

  rm(list = c("modlist"))

  # Getting smoothed cutoff
  if (is.null(smoothed_cutoffs)) {
    smoothed_name = paste0("smoothed_", model, "_cutoffs")
    scutoffs = env[[smoothed_name]]
  } else {
    scutoffs = smoothed_cutoffs
  }

  smoothed_cutoff = scutoffs$mod.dice.coef[1, "cutoff"]
  rm(list = c("scutoffs", "smoothed_name"))

  p = switch(model,
             rf = predict(mod,
                          newdata = df[ df$multiplier, ],
                          type = "prob")[, "1"],
             big_rf = predict(mod,
                              newdata = df[ df$multiplier, ],
                              type = "prob")[, "1"],
             logistic = predict(mod,
                                df[ df$multiplier, ],
                                type = "response"))
  msg = "# Making Prediction Image"
  if (verbose) {
    message(msg)
  }
  nim = check_nifti(nim)
  mult_img = niftiarr(nim, df$multiplier)

  # p = predict(mod, df[ df$multiplier, ], type = "response")
  pimg = remake_img(p,
                    nim,
                    mult_img)

  mask = niftiarr(nim, df$mask)
  pimg = mask_img(pimg, mask)
  msg = "# Smoothing Image"
  if (verbose) {
    message(msg)
  }
  sm.pimg  = mean_image(pimg,
                        nvoxels = 1,
                        verbose = verbose)
  sm.pimg[abs(sm.pimg) <
            .Machine$double.eps ^ 0.5 ] = 0
  sm.pimg = niftiarr(nim, sm.pimg)
  sm.pimg[is.na(sm.pimg)] = 0


  sm.pred = sm.pimg > smoothed_cutoff
  pred = pimg > cutoff

  msg = "# Connected Components"
  if (verbose) {
    message(msg)
  }
  # cc = spm_bwlabel(pred, k = 100)
  # scc = spm_bwlabel(sm.pred, k = 100)
  cc = ants_bwlabel(img = pred, k = 100, binary = TRUE)
  scc = ants_bwlabel(img = sm.pred, k = 100, binary = TRUE)

  ##############################################################
  # Back to Native Space!
  ##############################################################
  res = list(
    prediction_image = cc,
    smoothed_prediction_image = scc,
    probability_image = pimg,
    smoothed_probability_image = sm.pimg)

  ##############################################################
  # Inverted!
  ##############################################################
  native_res = NULL
  if (native) {
    msg = "# Projecting back to Native Space"
    if (verbose) {
      message(msg)
    }
    stopifnot(!is.null(interpolator))
    stopifnot(!is.null(transformlist))
    native_res = lapply(res, function(x){
      ants_apply_transforms(fixed = native_img,
                            moving = x,
                            transformlist = transformlist,
                            interpolator = interpolator,
                            whichtoinvert = c(1)
      )
    })
    native_res$smoothed_prediction_image = neurobase::datatyper(
      native_res$smoothed_prediction_image > native_thresh
    )
    native_res$prediction_image = neurobase::datatyper(
      native_res$prediction_image > native_thresh
    )
    writenii(native_res$smoothed_prediction_image, outfile)
  } else {
    writenii(res$smoothed_prediction_image, outfile)
  }
  res$cutoff = cutoff
  res$smoothed_cutoff = smoothed_cutoff

  L = list(registered_prediction = res)
  L$native_prediction = native_res
  L$outfile = outfile
  return(L)
}
neuroconductor-devel/ichseg documentation built on Sept. 5, 2019, 8:01 p.m.