R/utils.R

Defines functions .checkPythonDependencies .isTensorFlow .isPython .isConda listToDDLS listToDDLSDNN DigitalDLSorterTheme plotTrainingHistory loadTrainedModelFromH5 saveTrainedModelAsH5 .barPlot preparingToSave showProbPlot getProbMatrix

Documented in getProbMatrix listToDDLS listToDDLSDNN loadTrainedModelFromH5 plotTrainingHistory preparingToSave saveTrainedModelAsH5 showProbPlot

#' @importFrom ggplot2 theme_bw
#' @importFrom reticulate conda_binary py_available py_module_available conda_install
#' @importFrom utils compareVersion
#' @importFrom tensorflow install_tensorflow
NULL

#' Getter function for the cell composition matrix
#'
#' Getter function for the cell composition matrix. This function allows to
#' access to the cell composition matrix of simulated training or test
#' pseudo-bulk RNA-Seq data.
#'
#' @param object \code{\linkS4class{DigitalDLSorter}} object with
#'   \code{prob.cell.types} slot.
#' @param type.data Subset of data to e shown: \code{train} or \code{test}.
#'
#' @return A matrix object with the desired cell proportion matrix.
#'
#' @export
#'
#' @seealso \code{\link{generateBulkCellMatrix}}
#'
#'   
getProbMatrix <- function(object, type.data) {
  if (!is(object, "DigitalDLSorter")) {
    stop("Provided object is not a DigitalDLSorter object")
  } else if (!any(type.data == c("train", "test"))) {
    stop("'type.data' argument must be 'train' or 'test'")
  } else if (is.null(prob.cell.types(object))) {
    stop("'prob.cell.types' slot is empty")
  } else if (is.null(prob.cell.types(object, type.data))) {
    stop(paste("No", type.data, "data in 'prob.cell.types' slot"))
  } 
  return(prob.cell.types(object, type.data)@prob.matrix)
}

#' Show distribution plots of the cell proportions generated by
#' \code{\link{generateBulkCellMatrix}}
#'
#' Show distribution plots of the cell proportions generated by
#' \code{\link{generateBulkCellMatrix}}. These frequencies will determine the
#' proportion of different cell types used during the simulation of pseudo-bulk
#' RNA-Seq samples. There are 6 subsets of proportions generated by different
#' approaches that can be visualized in three ways: box plots, violin plots and
#' lines plots. You can also plot the probabilities based on the number of
#' different cell types present in the samples by setting \code{type.plot =
#' 'nCellTypes'}.
#'
#' These plots are only for diagnostic purposes. This is the reason because they
#' are generated without any parameter introduced by the user.
#'
#' @param object \code{\linkS4class{DigitalDLSorter}} object with
#'   \code{prob.cell.types} slot with \code{plot} slot.
#' @param type.data Subset of data to show: \code{train} or \code{test}.
#' @param set Integer determining which of the 6 different subsets to display.
#' @param type.plot Character determining which type of visualization to
#'   display. It can be \code{'boxplot'}, \code{'violinplot'}, \code{'linesplot'} or
#'   \code{'ncelltypes'}. See Description for more information.
#'
#' @return A ggplot object.
#'
#' @export
#'
#' @seealso \code{\link{generateBulkCellMatrix}}
#'
#' @examples
#' # simulating data
#' set.seed(123) # reproducibility
#' sce <- SingleCellExperiment::SingleCellExperiment(
#'   assays = list(
#'     counts = matrix(
#'       rpois(100, lambda = 5), nrow = 40, ncol = 30, 
#'       dimnames = list(paste0("Gene", seq(40)), paste0("RHC", seq(30)))
#'     )
#'   ),
#'   colData = data.frame(
#'     Cell_ID = paste0("RHC", seq(30)),
#'     Cell_Type = sample(x = paste0("CellType", seq(4)), size = 30, 
#'                        replace = TRUE)
#'   ),
#'   rowData = data.frame(
#'     Gene_ID = paste0("Gene", seq(40))
#'   )
#' )
#' DDLS <- loadSCProfiles(
#'   single.cell.data = sce,
#'   cell.ID.column = "Cell_ID",
#'   gene.ID.column = "Gene_ID"
#' )
#' probMatrix <- data.frame(
#'   Cell_Type = paste0("CellType", seq(4)),
#'   from = c(1, 1, 1, 30),
#'   to = c(15, 15, 50, 70)
#' )
#' DDLS <- generateBulkCellMatrix(
#'   object = DDLS,
#'   cell.ID.column = "Cell_ID",
#'   cell.type.column = "Cell_Type",
#'   prob.design = probMatrix,
#'   num.bulk.samples = 60
#' )
#' lapply(
#'   X = 1:6, FUN = function(x) {
#'       showProbPlot(
#'         DDLS,
#'         type.data = "train",
#'         set = x,
#'         type.plot = "boxplot"
#'       )
#'     }
#'   )
#'   
showProbPlot <- function(
  object,
  type.data,
  set,
  type.plot = "boxplot"
) {
  if (!is(object, "DigitalDLSorter")) {
    stop("Provided object is not a DigitalDLSorter object")
  } else if (is.null(object@prob.cell.types) || 
             (length(object@prob.cell.types) == 0)) {
    stop("'prob.cell.types' slot is empty")
  } else if (!any(type.data == c("train", "test"))) {
    stop("'type.data' argument must be 'train' or 'test'")
  } else if (length(object@prob.cell.types[[type.data]]) == 0) {
    stop(paste0("ProbMatrixCellTypes object does not have plots (", type.data, " data)"))
  } else if (set < 1 || set > 6) {
    stop("'set' argument must be an integer between 1 and 6")
  } else if (!any(type.plot == c("violinplot", "boxplot", "linesplot", "ncelltypes"))) {
    stop("'type.plot' argument must be one of the next options: 'violinplot', ", 
         "'boxplot', 'linesplot' or 'ncelltypes'")
  }
  return(prob.cell.types(object, type.data)@plots[[set]][[type.plot]])
}

#' Prepare \code{\linkS4class{DigitalDLSorter}} object to be saved as an RDA
#' file
#'
#' Prepare a \code{\linkS4class{DigitalDLSorter}} object that has a
#' \code{\linkS4class{DigitalDLSorterDNN}} object with a trained DNN model.
#' \code{keras} models cannot be stored natively as R objects (e.g. RData or RDS
#' files). By saving the structure as a JSON-like character object and the
#' weights as a list, it is possible to retrieve the model and make predictions.
#' \strong{Note:} with this option, the state of optimizer is not saved, only
#' the architecture and weights.
#'
#' It is possible to save the entire model as an HDF5 file with the
#' \code{\link{saveTrainedModelAsH5}} function and to load it into a
#' \code{\linkS4class{DigitalDLSorter}} object with the
#' \code{\link{loadTrainedModelFromH5}} function.
#'
#' It is also possible to save a \code{\linkS4class{DigitalDLSorter}} object as
#' an RDS file with the \code{saveRDS} function without any preparation.
#'
#' @param object \code{\linkS4class{DigitalDLSorter}} object with the
#'   \code{trained.data} slot.
#'
#' @return A \code{\linkS4class{DigitalDLSorter}} or
#'   \code{\linkS4class{DigitalDLSorterDNN}} object with its trained keras model
#'   transformed from a \code{keras.engine.sequential.Sequential} class into a
#'   \code{list} with the architecture as a JSON-like character object and the
#'   weights as a list.
#'
#' @export
#'
#' @seealso \code{\link{saveRDS}} \code{\link{saveTrainedModelAsH5}}
#'   
preparingToSave <- function(
  object
) {
  # check if python dependencies are covered
  .checkPythonDependencies(alert = "error")
  if (!is(object, "DigitalDLSorter") && !is(object, "DigitalDLSorterDNN")) {
    stop("Provided object is not a DigitalDLSorter object")
  }
  if (is.null(trained.model(object))) {
    stop("Provided object has not a DigitalDLSorterDNN object. It is not necessary ",
            "to prepare this object to save it to disk")
  } else if (length(trained.model(object)@model) == 0) {
    stop("Provided object has not a trained DNN model. It is not necessary ",
            "to prepare the object to save it to disk")
  }
  if (!is(trained.model(object)@model, "list")) 
    trained.model(object) <- .saveModelToJSON(trained.model(object))
  return(object)
}

# core of barplots of deconvolution results
.barPlot <- function(
  data,
  colors,
  color.line = NA,
  x.label = "Bulk samples",
  rm.x.text = FALSE,
  title = "Results of deconvolution",
  legend.title = "Cell types",
  angle = 90,
  theme = NULL
) {
  df.res <- reshape2::melt(data * 100, value.name = "Proportion")
  p <- ggplot(
    data = df.res, aes(
      x = .data[["Var1"]], y = .data[["Proportion"]], fill = .data[["Var2"]]
    )
  ) + geom_bar(stat = "identity", color = color.line) + theme
  if (!missing(colors) && !is.null(colors)) {
    if (length(colors) < length(unique(df.res$Var2)))
      stop("Number of provided colors is not enough for the number of cell types")
  } else {
    colors <- default.colors()
  }
  p <- p + scale_fill_manual(values = colors) + DigitalDLSorterTheme()
  if (is.null(x.label)) {
    p <- p + theme(axis.title.x = element_blank())
  } else {
    p <- p + xlab(x.label)
  }
  p <- p + ggtitle(title) + ggplot2::labs(fill = legend.title) + theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    axis.title = element_text(size = 12),
    axis.text.x = element_text(angle = angle, hjust = 1, vjust = 0.5),
    legend.title = element_text(face = "bold")
  )
  if (rm.x.text) {
    p <- p + theme(axis.ticks.x = element_blank(),
                   axis.text.x = element_blank())
  }
  return(p)
}

################################################################################
####################### Utils functions related to DNN #########################
################################################################################

#' Save a trained \code{\linkS4class{DigitalDLSorter}} Deep Neural Network model
#' to disk as an HDF5 file
#'
#' Save a trained \code{\linkS4class{DigitalDLSorter}} Deep Neural Network model
#' to disk as an HDF5 file. Note that this function does not save the
#' \code{\linkS4class{DigitalDLSorterDNN}} object, but the trained keras model.
#' This is the alternative to the \code{\link{saveRDS}} and
#' \code{\link{preparingToSave}} functions if you want to keep the state of the
#' optimizer.
#'
#' @param object \code{\linkS4class{DigitalDLSorter}} object with
#'   \code{trained.model} slot.
#' @param file.path Valid file path where to save the model to.
#' @param overwrite Overwrite file if it already exists.
#'
#' @return No return value, saves a keras DNN trained model as HDF5 file on
#'   disk.
#'
#' @export
#'
#' @seealso \code{\link{trainDigitalDLSorterModel}}
#'   \code{\link{loadTrainedModelFromH5}}
#'   
saveTrainedModelAsH5 <- function(
  object,
  file.path,
  overwrite = FALSE
) {
  # check if python dependencies are covered
  .checkPythonDependencies(alert = "error")
  if (!is(object, "DigitalDLSorter")) {
    stop("Provided object is not a DigitalDLSorter object")
  } else if (is.null(trained.model(object))) {
    stop("'trained.model' slot is empty")
  } else if (length(trained.model(object)@model) == 0) {
    stop("There is not a model to save on disk. First, train a model with ",
         "'trainDigitalDLSorterModel' function")
  }
  if (file.exists(file.path)) {
    if (overwrite) {
      message(paste(file.path, "file already exists. Since 'overwrite' argument is",
                    "TRUE, it will be overwritten"))
    } else {
      stop(paste(file.path, "file already exists"))
    }
  }
  if (is(trained.model(object)@model, "list")) {
    warning(paste(
      "Trained model is not a keras object, but a R list with",
      "architecture of network and weights. The R object will be",
      "compiled and saved as HDF5 file, but the optimizer state",
      "will not be saved\n\n"
    ))
    model <- .loadModelFromJSON(trained.model(object))
    model <- model(model)
  } else {
    model <- trained.model(object)@model
  }
  tryCatch(
    expr = {
      save_model_hdf5(
        object = model, filepath = file.path,
        overwrite = overwrite, include_optimizer = TRUE
      )
    }, 
    error = function(cond) {
      message(paste("\nProblem during saving", file.path))
      stop(cond)
    }
  )
}

#' Load from an HDF5 file a trained Deep Neural Network model into a
#' \code{\linkS4class{DigitalDLSorter}} object
#'
#' Load from an HDF5 file a trained Deep Neural Network model into a
#' \code{\linkS4class{DigitalDLSorter}} object. Note that HDF5 file must be a
#' valid trained model (\pkg{keras} object).
#'
#' @param object \code{\linkS4class{DigitalDLSorter}} object with
#'   \code{trained.model} slot.
#' @param file.path Valid file path where the model are stored.
#' @param reset.slot Deletes \code{trained.slot} if it already exists. A new
#'   \code{\link{DigitalDLSorterDNN}} object will be formed, but will not
#'   contain other slots (\code{FALSE} by default).
#'
#' @return \code{\linkS4class{DigitalDLSorter}} object with \code{trained.model}
#'   slot with the new keras DNN model incorporated.
#'
#' @export
#'
#' @seealso \code{\link{trainDigitalDLSorterModel}}
#'   \code{\link{deconvDigitalDLSorterObj}} \code{\link{saveTrainedModelAsH5}}
#'   
loadTrainedModelFromH5 <- function(
  object,
  file.path,
  reset.slot = FALSE
) {
  # check if python dependencies are covered
  .checkPythonDependencies(alert = "error")
  if (!is(object, "DigitalDLSorter")) {
    stop("Provided object is not a DigitalDLSorter object")
  } else if (!file.exists(file.path)) {
    stop(paste(file.path, "file does not exist. Please, provide a valid file path"))
  }
  if (!is.null(trained.model(object))) {
    slot.exists <- TRUE
    message("'trained.model' slot is not empty:")
    if (reset.slot) {
      message("  'reset.slot' is TRUE, 'trained.model' slot will be restart")
    } else {
      message("  'reset.slot' is FALSE, just 'model' slot of DigitalDLSorterDNN",
              "object will be overwritten")
    }
  } else {
    slot.exists <- FALSE
  }
  tryCatch(
    expr = {
      loaded.model <- load_model_hdf5(filepath = file.path, compile = FALSE)
    }, 
    error = function(cond) {
      message(paste("\n", file.path, "file provided is not a valid Keras model:"))
      stop(cond)
    }
  )
  if (!slot.exists) {
    model <- new(Class = "DigitalDLSorterDNN",
                 model = loaded.model)
  } else {
    if (reset.slot) {
      model <- new(Class = "DigitalDLSorterDNN",
                   model = loaded.model)
    } else {
      model(object@trained.model) <- loaded.model
      return(object)
    }
  }
  trained.model(object) <- model
  return(object)
}

#' Plot training history of a trained DigitalDLSorter Deep Neural Network model
#'
#' Plot training history of a trained DigitalDLSorter Deep Neural Network model.
#'
#' @param object \code{\linkS4class{DigitalDLSorter}} object with
#'   \code{trained.model} slot.
#' @param title Title of plot.
#' @param metrics Metrics to be plotted. If \code{NULL} (by default), all
#'   metrics available in the \code{\linkS4class{DigitalDLSorterDNN}} object
#'   will be plotted.
#'
#' @return A ggplot object with the progression of the selected metrics during
#'   training.
#'
#' @export
#'
#' @seealso \code{\link{trainDigitalDLSorterModel}}
#'   \code{\link{deconvDigitalDLSorterObj}}
#'   
plotTrainingHistory <- function(
  object,
  title = "History of metrics during training",
  metrics = NULL
) {
  # check if python dependencies are covered
  .checkPythonDependencies(alert = "error")
  if (!is(object, "DigitalDLSorter")) {
    stop("Provided object is not of DigitalDLSorter class")
  } else if (is.null(trained.model(object))) {
    stop("'trained.model' slot is empty")
  } else if (is.null(trained.model(object)@training.history)) {
    stop("There is no training history in provided object")
  }
  if (!is.null(metrics)) {
    if (!all(metrics %in% names(trained.model(object)@training.history$metrics))) {
      stop("None of the given metrics are in the provided object")
    }
  }
  plot(
    trained.model(object)@training.history,
    metrics = metrics, method = "ggplot2"
  ) + ggtitle(title) + DigitalDLSorterTheme()
}

# custom ggplot2 theme
DigitalDLSorterTheme <- function() {
  digitalTheme <- ggplot2::theme_bw() + theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    legend.title = element_text(face = "bold")
  )
}

################################################################################
##################### Functions to transform list into DDLS ####################
################################################################################

#' Transform DigitalDLSorterDNN-like list into an actual DigitalDLSorterDNN
#' object
#'
#' Transform DigitalDLSorterDNN-like list into an actual
#' \code{DigitalDLSorterDNN} object. This function allows to use pre-trained
#' models in the \pkg{digitalDLSorteR} package. These models are stored in the
#' digitalDLSorteRmodels package.
#'
#' @param listTo A list in which each element must correspond to each slot of an
#'   \code{DigitalDLSorterDNN} object. The names must be the same as the slot
#'   names.
#'
#' @return \code{DigitalDLSorterDNN} object with the data provided in the
#'   original list.
#'
#' @export
#'
#' @seealso \code{\link{listToDDLS}}
#' 
listToDDLSDNN <- function(listTo) {
  if (any(!names(listTo) %in% c(
    "model", "training.history", "test.metrics", "test.pred", 
    "cell.types", "features", "test.deconv.metrics"
  ))) {
    stop("The list provided is not valid to create a DigitalDLSorterDNN object")
  }
  return(
    digitalDLSorteR::DigitalDLSorterDNN(
      model = listTo$model,
      training.history = listTo$training.history,
      test.metrics = listTo$test.metrics, 
      test.pred = listTo$test.pred,
      cell.types = listTo$cell.types, 
      features = listTo$features,
      test.deconv.metrics = listTo$test.deconv.metrics
    )
  )
}

#' Transform DigitalDLSorter-like list into an actual DigitalDLSorterDNN object
#'
#' Transform DigitalDLSorter-like list into an actual \code{DigitalDLSorter}
#' object. This function allows to generate the examples and the vignettes of
#' \pkg{digitalDLSorteR} package as these are the data used. These data are
#' stored in the digitalDLSorteRdata package.
#'
#' @param listTo A list in which each element must correspond to each slot of an
#'   \code{DigitalDLSorter} object. The names must be the same as the slot
#'   names.
#'
#' @return \code{DigitalDLSorter} object the data provided in the original list.
#'
#' @export
#'
#' @seealso \code{\link{listToDDLSDNN}}
#'   
listToDDLS <- function(listTo) {
  if (any(!names(listTo) %in% c(
    "single.cell.real", "zinb.params", "single.cell.simul", 
    "prob.cell.types", "bulk.simul", "trained.model", "deconv.data", 
    "deconv.results", "project", "version"
  ))) {
    stop("The list provided is not valid to create a DigitalDLSorter object")
  }
  # for prob.cell.types slot: ProbMatrixCellTypes 
  if (is.null(listTo$prob.cell.types)){
    prob.cell.types <- NULL
  } else if (is(listTo$prob.cell.types, "list")) {
    prob.cell.types <- list(
      train = ProbMatrixCellTypes(
        prob.matrix = listTo$prob.cell.types$train$prob.matrix,
        cell.names = listTo$prob.cell.types$train$cell.names,
        set.list = listTo$prob.cell.types$train$set.list,
        set = listTo$prob.cell.types$train$set,
        plots = listTo$prob.cell.types$train$plots,
        type.data = listTo$prob.cell.types$train$type.data
      ),
      test = ProbMatrixCellTypes(
        prob.matrix = listTo$prob.cell.types$test$prob.matrix,
        cell.names = listTo$prob.cell.types$test$cell.names,
        set.list = listTo$prob.cell.types$test$set.list,
        set = listTo$prob.cell.types$test$set,
        plots = listTo$prob.cell.types$test$plots,
        type.data = listTo$prob.cell.types$test$type.data
      )
    )
  }
  # for trained.model slot: DigitalDLSorterDNN
  if (is.null(listTo$trained.model)){
    trained.model <- NULL
  } else if (is(listTo$trained.model, "list")) {
    trained.model <- listToDDLSDNN(listTo$trained.model)
  }
  return(
    DigitalDLSorter(
      single.cell.real = listTo$single.cell.real,
      zinb.params = listTo$zinb.params,
      single.cell.simul = listTo$single.cell.simul,
      prob.cell.types = prob.cell.types,
      bulk.simul = listTo$bulk.simul,
      trained.model = trained.model,
      deconv.data = listTo$deconv.data,
      deconv.results = listTo$deconv.results,
      project = listTo$project,
      version = listTo$version
    )
  )
}

################################################################################
############################# Python dependencies ##############################
################################################################################

.isConda <- function() {
  conda <- tryCatch(
    reticulate::conda_binary("auto"), error = function(e) NULL
  )
  !is.null(conda)
}

.isPython <- function() {
  tryCatch(
    expr = reticulate::py_available(initialize = TRUE), 
    error = function(e) FALSE
  )
}

.isTensorFlow <- function() {
  tfAvailable <- reticulate::py_module_available("tensorflow")
  if (tfAvailable) {
    tfVersion <- tensorflow::tf$`__version__`
    tfAvailable <- utils::compareVersion("2.2", tfVersion) <= 0
  }
  return(tfAvailable)
}

# alert parameter: c("none", "error", "warn", "message", "startup")
.checkPythonDependencies <- function(
  alert = "error"
) {
  # turn off reticulate autoconfigure
  ac_flag <- Sys.getenv("RETICULATE_AUTOCONFIGURE")
  on.exit(Sys.setenv(RETICULATE_AUTOCONFIGURE = ac_flag))
  Sys.setenv(RETICULATE_AUTOCONFIGURE = FALSE)
  dependencies <- c(python = .isPython(), tf = .isTensorFlow())
  if (!all(dependencies)) {
    messageT <- c(
      "There is no a Python interpreter with all the digitalDLSorteR \
        dependencies covered available. Please, look at \
        https://diegommcc.github.io/digitalDLSorteR/articles/kerasIssues.html \
        or see ?installPythonDepend"
    )
    warningT <- c(
      "There is no a Python interpreter with all the digitalDLSorteR \
        dependencies covered available. Please, look at \
        https://diegommcc.github.io/digitalDLSorteR/articles/kerasIssues.html \
        or see ?installPythonDepend"
    )
    errorT <- c(
      "There is no a Python interpreter with all the digitalDLSorteR \
        dependencies covered available. Please, look at \
        https://diegommcc.github.io/digitalDLSorteR/articles/kerasIssues.html \
        or see ?installPythonDepend"
    )
    switch(
      alert,
      error = stop(errorT, call. = FALSE),
      warn = warning(warningT, call. = FALSE),
      message = message(messageT),
      startup = packageStartupMessage(messageT),
      none = NULL
    )
  }
  return(invisible(all(dependencies)))
}

#' Install Python dependencies for digitalDLSorteR
#'
#' This is a helper function to install Python dependencies needed: a Python
#' interpreter with TensorFlow Python library and its dependencies. It is
#' performed using the \pkg{reticulate} package and the installer of the
#' \pkg{tensorflow} R package. The available options are virtual or conda
#' environments. The new environment is called digitaldlsorter-env. In any case,
#' this installation can be manually done as it is explained in
#' \url{https://diegommcc.github.io/digitalDLSorteR/articles/kerasIssues.html},
#' but we recommend using this function.
#'
#' This function is intended to make easier the installation of the requirements
#' needed to use \pkg{digitalDLSorteR}. It will automatically install Miniconda
#' (if wanted, see Parameters) and create an environment called
#' 'digitaldlsorter-env'. If you want to use other python/conda environment, see
#' \code{?tensorflow::use_condaenv} and/or the vignettes.
#'
#' @param conda Path to a conda executable. Use \code{"auto"} (by default)
#'   allows \pkg{reticulate} to automatically find an appropriate conda binary.
#' @param install.conda Boolean indicating if install miniconda automatically
#'   using \pkg{reticulate}. If \code{TRUE}, \code{conda} argument is ignored.
#'   \code{FALSE} by default.
#' @param miniconda.path If \code{install.conda} is \code{TRUE}, you can set the
#'   path where miniconda will be installed. If \code{NULL}, conda will find
#'   automatically the proper place.
#'
#' @return No return value, called for side effects: installation of conda
#'   environment with a Python interpreter and Tensorflow
#'
#' @export
#'
#' @examples
#' \dontrun{
#' notesInstallation <- installTFpython(
#'   method = "auto", conda = "auto", install.conda = TRUE
#' )
#' }
#' 
installTFpython <- function(
  conda = "auto",
  install.conda = FALSE,
  miniconda.path = NULL
) {
  if ((!.isConda())) {
    if (!install.conda) {
      stop("No miniconda detected, but 'install.conda' is FALSE. Please, set ", 
           "'install.conda = TRUE' to install miniconda." )
    }
    message("=== No miniconda detected, installing through the reticulate R package")
    if (is.null(miniconda.path)) {
      miniconda.path <- reticulate::miniconda_path()
    }
    status1 <- tryCatch(
      reticulate::install_miniconda(path = miniconda.path), 
      error = function(e) {
        return(TRUE)
      }
    )
    if (isTRUE(status1)) {
      stop(
        "Error during the installation. Please see the website of the ",
        "package and/or the vignettes for more details",
        call. = FALSE
      )
    }
  }
  dirConda <- reticulate::conda_binary("auto")
  message("\n=== Creating digitaldlsorter-env environment")
  status2 <- tryCatch(
    reticulate::conda_create(
      envname = "digitaldlsorter-env", 
      packages = "python==3.7.11"
    ), 
    error = function(e) {
      return(TRUE)
    }
  )
  if (isTRUE(status2)) {
    stop(
      "Error during the installation. Please see the website of the ",
      "package and/or the vignettes for more details",
      call. = FALSE
    )
  }
  message("\n=== Installing tensorflow in digitaldlsorter-env environment")
  status3 <- tryCatch(
    tensorflow::install_tensorflow(
      version = "2.5-cpu", 
      method = "conda", 
      conda = dirConda, 
      envname = "digitaldlsorter-env"
    ), 
    error = function(e) {
      return(TRUE)
    }
  )
  if (isTRUE(status3)) {
    stop(
      "Error during the installation. Please see the website of the ",
      "package and/or the vignettes for more details",
      call. = FALSE
    )
  }
  message("Installation complete!")
  message(c("Restart R and load digitalDLSorteR. If you find any problem, \
         see ?tensorflow::use_condaenv and kerasIssues.Rmd vignette"))
}

Try the digitalDLSorteR package in your browser

Any scripts or data that you put into this service are public.

digitalDLSorteR documentation built on Oct. 5, 2022, 9:05 a.m.