diff --git a/DESCRIPTION b/DESCRIPTION index 9be2503..e6520c1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: rMIDAS Title: Multiple Imputation with Denoising Autoencoders -Version: 0.4.1 +Version: 0.4.2 Authors@R: c( person(given = "Thomas", family = "Robinson", @@ -19,18 +19,11 @@ Authors@R: c( Description: A tool for multiply imputing missing data using 'MIDAS', a deep learning method based on denoising autoencoder neural networks. This algorithm offers significant accuracy and efficiency advantages over other multiple imputation strategies, particularly when applied to large datasets with complex features. Alongside interfacing with 'Python' to run the core algorithm, this package contains functions for processing data before and after model training, running imputation model diagnostics, generating multiple completed datasets, and estimating regression models on these datasets. Encoding: UTF-8 Roxygen: list(markdown = TRUE) -RoxygenNote: 7.1.1 -Depends: - R (>= 3.6.0), - data.table, - mltools, - reticulate -Imports: -Suggests: - testthat, - knitr, - rmarkdown -SystemRequirements: Python (>= 3.7.0) +RoxygenNote: 7.2.3 +Depends: R (>= 3.6.0), data.table, mltools, reticulate +Imports: rappdirs +Suggests: testthat, knitr, rmarkdown +SystemRequirements: Python (>= 3.6.0) VignetteBuilder: knitr License: Apache License (>= 2.0) URL: https://github.com/MIDASverse/rMIDAS diff --git a/NAMESPACE b/NAMESPACE index 9eafd49..c031a50 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -6,9 +6,11 @@ export(col_minmax) export(combine) export(complete) export(convert) +export(delete_rMIDAS_env) export(midas_setup) export(na_to_nan) export(overimpute) +export(reset_rMIDAS_env) export(set_python_env) export(train) export(undo_minmax) diff --git a/R/delete_env.R b/R/delete_env.R new file mode 100644 index 0000000..434de43 --- /dev/null +++ b/R/delete_env.R @@ -0,0 +1,40 @@ +#' Delete the rMIDAS Environment and Configuration +#' +#' Deletes both the virtual environment and the configuration file for the rMIDAS package. +#' After deletion, it is necessary to restart the R session and then load the rMIDAS package once more. +#' This will trigger the setup process again. +#' +#' @name delete_rMIDAS_env +#' @aliases delete_rMIDAS_env +#' @return A message indicating the completion of the deletion process. +#' @export + +delete_rMIDAS_env <- function() { + + if (requireNamespace("rappdirs", quietly = TRUE)) { + config_dir <- rappdirs::user_config_dir(appname = "rMIDAS") + config_file <- file.path(config_dir, ".rMIDAS_config") + + virtual_env_dir <- rappdirs::user_data_dir(appname = "rMIDAS") + virtual_env_name <- file.path(virtual_env_dir, "rMIDAS_env_auto_setup") + + } else { + stop("The 'rappdirs' package is required to determine the directories. Please install it.") + } + + if (dir.exists(virtual_env_name)) { + unlink(virtual_env_name, recursive = TRUE) + message("rMIDAS virtual environment deleted successfully.") + } else { + message("rMIDAS virtual environment not found.") + } + + if (file.exists(config_file)) { + file.remove(config_file) + message("rMIDAS configuration file deleted successfully.") + } else { + message("rMIDAS configuration file not found.") + } + + message("Please restart the R session and then load rMIDAS to set up the environment again.") +} \ No newline at end of file diff --git a/R/reset_env.R b/R/reset_env.R new file mode 100644 index 0000000..fbb7cee --- /dev/null +++ b/R/reset_env.R @@ -0,0 +1,32 @@ +#' Reset the rMIDAS Environment Configuration +#' +#' Resets the configuration for the rMIDAS package by deleting the configuration file. +#' Once the configuration is reset, it is necessary to restart the R session +#' and then load the rMIDAS package once more. +#' +#' @name reset_rMIDAS_env +#' @aliases reset_rMIDAS_env +#' @return A message indicating the completion of the reset process. +#' @export + +reset_rMIDAS_env <- function() { + # Use rappdirs to get the appropriate user configuration directory + if (requireNamespace("rappdirs", quietly = TRUE)) { + config_dir <- rappdirs::user_config_dir(appname = "rMIDAS") + config_file <- file.path(config_dir, ".rMIDAS_config") + } else { + stop("The 'rappdirs' package is required to determine the configuration directory. Please install it.") + } + + if (!file.exists(config_file)) { + stop("rMIDAS config file doesn't exist.") + } + + # Option 1: Delete the entire config file. + file.remove(config_file) + + # OR Option 2: Overwrite the config file with a default or empty value. + # writeLines("", con = config_file) + + message("rMIDAS configuration reset. Please restart the R session and then load rMIDAS again.") +} \ No newline at end of file diff --git a/R/zzz.R b/R/zzz.R index 7b70c3b..26a5928 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -3,61 +3,94 @@ options("python_custom" = NULL) options("python_initialised" = NULL) - if (!interactive()) { - user_input <- "n" - packageStartupMessage("rMIDAS is loaded but its environment and dependencies are not set up automatically. \n Please read https://github.com/MIDASverse/rMIDAS for additional help on how to set up and configure your environment.") + if (requireNamespace("rappdirs", quietly = TRUE)) { + config_dir <- rappdirs::user_config_dir(appname = "rMIDAS") + if (!dir.exists(config_dir)) { + dir.create(config_dir, recursive = TRUE) + } + config_file <- file.path(config_dir, ".rMIDAS_config") + + virtual_env_dir <- rappdirs::user_data_dir(appname = "rMIDAS") + if (!dir.exists(virtual_env_dir)) { + dir.create(virtual_env_dir, recursive = TRUE) + } } else { - user_input <- readline("Do you want rMIDAS to automatically set up a Python environment and its dependencies? Enter 'y' for Yes, or any other key for No : \n") - } - if(tolower(user_input) != "y") { - packageStartupMessage("rMIDAS is loaded but its environment and dependencies are not set up automatically.\n Please read https://github.com/MIDASverse/rMIDAS for additional help on how to set up and configure your environment.") + stop("The 'rappdirs' package is required for rMIDAS. Please install it.") } - if (tolower(user_input) == "y") { - if (!requireNamespace("reticulate", quietly = TRUE)) { - install.packages("reticulate") + + if (!file.exists(config_file)) { + if (!interactive()) { + user_input <- "n" + packageStartupMessage("rMIDAS is loaded. In headless mode its environment and dependencies need to be set up manually. Please read https://github.com/MIDASverse/rMIDAS for additional help on how to set up and configure your environment.") + packageStartupMessage("If you want to change your Python environment use 'reset_rMIDAS_env()' to reset your configuration. After resetting, you'll need to restart the R session and run 'library(rMIDAS)' again.") + } else { + user_input <- readline("Do you want rMIDAS to automatically set up a Python environment and its dependencies? Enter 'y' for Yes, or any other key for No : \n") + writeLines(user_input, con = config_file) + if(tolower(user_input) != "y") {packageStartupMessage("rMIDAS is loaded but its environment and dependencies are not set up automatically. Please read https://github.com/MIDASverse/rMIDAS for additional help on how to set up and configure your environment.")} + if(tolower(user_input) == "y") {packageStartupMessage("rMIDAS is being set up automatically.")} } - - library(reticulate) - conda_env_name <- "rMIDAS_env" - - if (!conda_env_name %in% reticulate::conda_list()$name) { - reticulate::conda_create(envname = conda_env_name) + } else { + user_input <- readLines(con = config_file)[1] + if(tolower(user_input) != "y") { + packageStartupMessage("\n \n","rMIDAS is loaded. Please read https://github.com/MIDASverse/rMIDAS for additional help on how to set up and configure your environment. If you want to use a different Python environment use 'reset_rMIDAS_env()' to reset the your configuration. After resetting, you'll need to restart the R session and run 'library(rMIDAS)' again.\n") + writeLines(user_input, con = config_file) } - - reticulate::use_condaenv(conda_env_name, required = TRUE) - - python_version <- reticulate::py_config()$version - python_version_numeric <- as.numeric(python_version) - python_version_major <- floor(python_version_numeric) - python_version_minor <- floor(python_version_numeric * 10) %% 10 - - requirements_txt <- "numpy>=1.5 + } + + if (tolower(user_input) == "y") { + Sys.setenv(WORKON_HOME = virtual_env_dir) + virtual_env_name <- "rMIDAS_env_auto_setup" + if (virtual_env_name %in% reticulate::virtualenv_list()) { + reticulate::use_virtualenv(virtual_env_name, required = TRUE) + } else { + current_version <- reticulate::py_discover_config()$version + matched_version <- NULL + if (grepl("^3\\.(6|7|8|9|10).*|^3\\.(6|7|8|9|10)-dev$", current_version)) { + matched_version <- current_version + } else { + matched_version <- "3.8.17" + reticulate::install_python(version = matched_version, force = TRUE) + } + reticulate::virtualenv_create(envname = virtual_env_name, python_version = matched_version) + reticulate::use_virtualenv(virtual_env_name, required = TRUE) + python_version <- reticulate::py_discover_config()$version + version_components <- strsplit(python_version, "\\.")[[1]] + python_version_major <- as.numeric(version_components[1]) + python_version_minor <- as.numeric(version_components[2]) + + requirements_txt <- "numpy>=1.5 scikit-learn matplotlib pandas>=0.19 -tensorflow_addons<0.20 +tensorflow_addons<0.20.0 statsmodels scipy " - - if (python_version_major == "3" && as.integer(python_version_minor) >= 8 && as.integer(python_version_minor) < 11) { - if (Sys.info()["sysname"] == "Darwin" && Sys.info()["machine"] == "arm64") { - requirements_txt <- paste0(requirements_txt, "tensorflow-macos<2.12.0") + + if (python_version_major == 3 && as.integer(python_version_minor) >= 8 && as.integer(python_version_minor) < 11) { + if (Sys.info()["sysname"] == "Darwin" && Sys.info()["machine"] == "arm64") { + requirements_txt <- paste0(requirements_txt, "tensorflow-macos<2.12.0") + } else { + requirements_txt <- paste0(requirements_txt, "tensorflow<2.12.0") + } } else { - requirements_txt <- paste0(requirements_txt, "tensorflow<2.12.0") - } - } else { - if (Sys.info()["sysname"] == "Darwin" && Sys.info()["machine"] == "arm64") { - requirements_txt <- paste0(requirements_txt, "tensorflow-macos>=1.10") - } else { - requirements_txt <- paste0(requirements_txt, "tensorflow>=1.10") + if (Sys.info()["sysname"] == "Darwin" && Sys.info()["machine"] == "arm64") { + requirements_txt <- paste0(requirements_txt, "tensorflow-macos>=1.10") + } else { + requirements_txt <- paste0(requirements_txt, "tensorflow>=1.10") + } } + + requirements_file <- tempfile(fileext = ".txt") + writeLines(requirements_txt, requirements_file) + + reticulate::py_install(envname = virtual_env_name, pip = TRUE, packages = c("-r", requirements_file)) + reticulate::py_config() + reticulate::use_virtualenv(virtual_env_name, required = TRUE) + packageStartupMessage("rMIDAS has been automatically set up.") + #.rs.restartR() } - - requirements_file <- tempfile(fileext = ".txt") - writeLines(requirements_txt, requirements_file) - - reticulate::conda_install(envname = conda_env_name, packages = NULL, pip = TRUE, pip_options = c("-r", requirements_file)) + packageStartupMessage("rMIDAS is loaded. Please read https://github.com/MIDASverse/rMIDAS for additional help on how to set up and configure your environment. If you want to change your Python environment use 'reset_rMIDAS_env()' to reset your configuration. After resetting, you'll need to restart the R session and run 'library(rMIDAS)' again.") } } @@ -71,6 +104,6 @@ scipy ) } -.onUnload <- function(libpath) { - # No action necessary -} +.onDetach <- function(libpath) { + # Nothing +} \ No newline at end of file diff --git a/man/delete_rMIDAS_env.Rd b/man/delete_rMIDAS_env.Rd new file mode 100644 index 0000000..2217825 --- /dev/null +++ b/man/delete_rMIDAS_env.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/delete_env.R +\name{delete_rMIDAS_env} +\alias{delete_rMIDAS_env} +\title{Delete the rMIDAS Environment and Configuration} +\usage{ +delete_rMIDAS_env() +} +\value{ +A message indicating the completion of the deletion process. +} +\description{ +Deletes both the virtual environment and the configuration file for the rMIDAS package. +After deletion, it is necessary to restart the R session and then load the rMIDAS package once more. +This will trigger the setup process again. +} diff --git a/man/reset_rMIDAS_env.Rd b/man/reset_rMIDAS_env.Rd new file mode 100644 index 0000000..edf043d --- /dev/null +++ b/man/reset_rMIDAS_env.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/reset_env.R +\name{reset_rMIDAS_env} +\alias{reset_rMIDAS_env} +\title{Reset the rMIDAS Environment Configuration} +\usage{ +reset_rMIDAS_env() +} +\value{ +A message indicating the completion of the reset process. +} +\description{ +Resets the configuration for the rMIDAS package by deleting the configuration file. +Once the configuration is reset, it is necessary to restart the R session +and then load the rMIDAS package once more. +}