Skip to content

Commit

Permalink
* Added option to restart R + run library(greta) after installation (
Browse files Browse the repository at this point in the history
…greta-dev#523)

* Added installation deps object, `greta_python_deps()` to help simplify specifying package versions (greta-dev#664)
* removed `method` and `conda` arguments from `install_greta_deps()` as they
  were not used.
* removed `manual` option in `install_greta_deps()`
* added default 5 minute timer to installation processes
  • Loading branch information
njtierney committed Aug 6, 2024
1 parent 7db171e commit 7b9eb5c
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 77 deletions.
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ S3method(plot,greta_model)
S3method(print,greta_array)
S3method(print,greta_mcmc_list)
S3method(print,greta_model)
S3method(print,greta_python_deps)
S3method(print,initials)
S3method(print,optimiser)
S3method(print,sampler)
Expand Down Expand Up @@ -201,6 +202,7 @@ export(greta_notes_conda_install_output)
export(greta_notes_install_miniconda_error)
export(greta_notes_install_miniconda_output)
export(greta_notes_tf_num_error)
export(greta_python_deps)
export(greta_sitrep)
export(hmc)
export(hypergeometric)
Expand Down
11 changes: 11 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ The following optimisers are removed, as they are no longer supported by Tensorf
* `cobyla()`
* `slsqp()`

## Installation revamp

This release provides a few improvements to installation in greta. It should now provide more information about installation progress, and be more robust. The intention is, it should _just work_, and if it doesn't fail gracefully with some useful advice on problem solving.

* Added option to restart R + run `library(greta)` after installation (#523)
* Added installation deps object, `greta_python_deps()` to help simplify specifying package versions (#664)
* removed `method` and `conda` arguments from `install_greta_deps()` as they
were not used.
* removed `manual` option in `install_greta_deps()`
* added default 5 minute timer to installation processes

## Minor

* `greta_sitrep()` now checks for minimum versions of software, instead of exact versions. It requires at least Python version 3.8, TensorFlow 2.8.0, and Tensorflow Probability 0.14.0.
Expand Down
16 changes: 9 additions & 7 deletions R/greta_create_conda_env.R
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
greta_create_conda_env <- function(timeout) {

options(warning.length = 2000)
greta_create_conda_env <- function(timeout = 5,
python_deps = greta_python_deps()) {

stdout_file <- create_temp_file("out-greta-conda")
stderr_file <- create_temp_file("err-greta-conda")

callr_conda_create <- callr::r_process_options(
func = function() {
func = function(python_version) {
reticulate::conda_create(
envname = "greta-env-tf2",
python_version = "3.10"
python_version = python_version
)
},
args = list(python_version = python_deps$python_version),
stdout = stdout_file,
stderr = stderr_file
)
Expand All @@ -21,8 +21,10 @@ greta_create_conda_env <- function(timeout) {
stdout_file = stdout_file,
stderr_file = stderr_file,
timeout = timeout,
cli_start_msg = "Creating 'greta-env-tf2' conda environment using python \\
v3.8, this may take a minute",
cli_start_msg = glue::glue(
"Creating 'greta-env-tf2' conda environment using python \\
v{python_deps$python_version}, this may take a minute"
),
cli_end_msg = "greta-env-tf2 environment created!"
)

Expand Down
2 changes: 1 addition & 1 deletion R/greta_install_miniconda.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
greta_install_miniconda <- function(timeout) {
greta_install_miniconda <- function(timeout = 5) {

stdout_file <- create_temp_file("out-miniconda")
stderr_file <- create_temp_file("err-miniconda")
Expand Down
39 changes: 26 additions & 13 deletions R/greta_install_python_deps.R
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
greta_install_python_deps <- function(timeout) {
greta_install_python_deps <- function(timeout = 5,
python_deps = greta_python_deps()) {

stdout_file <- create_temp_file("out-python-deps")
stderr_file <- create_temp_file("err-python-deps")

callr_conda_install <- callr::r_process_options(
func = function() {
func = function(python_deps) {
cli::cli_progress_step(
msg = "Installing TF (v{python_deps$tf_version})",
msg_done = "Installed TF (v{python_deps$tf_version})!",
msg_failed = "Error installing TF (v{python_deps$tf_version})"
)
tensorflow::install_tensorflow(
version = "2.15.0",
version = python_deps$tf_version,
envname = "greta-env-tf2",
method = "conda"
)
reticulate::py_install(packages = "tensorflow-probability==0.23.0",
pip = TRUE,
envname = "greta-env-tf2",
method = "conda")
# reticulate::py_install(packages = "keras==2.11.0",
# pip = TRUE,
# envname = "greta-env-tf2",
# method = "conda")
dep_tfp <- glue::glue("tensorflow-probability=={python_deps$tfp_version}")
cli::cli_progress_step(
msg = "Installing TFP (v{python_deps$tfp_version})",
msg_done = "Installed TFP (v{python_deps$tfp_version})!",
msg_failed = "Error installing TFP (v{python_deps$tfp_version})"
)
reticulate::py_install(
packages = dep_tfp,
pip = TRUE,
envname = "greta-env-tf2",
method = "conda"
)
},
args = list(python_deps = python_deps),
stdout = stdout_file,
stderr = stderr_file
)
Expand All @@ -28,8 +39,10 @@ greta_install_python_deps <- function(timeout) {
timeout = timeout,
stdout_file = stdout_file,
stderr_file = stderr_file,
cli_start_msg = "Installing python modules into 'greta-env-tf2' conda \\
environment, this may take a few minutes",
cli_start_msg = glue::glue(
"Installing python modules into 'greta-env-tf2' conda environment, \\
this may take a few minutes"
),
cli_end_msg = "Python modules installed!"
)

Expand Down
127 changes: 84 additions & 43 deletions R/install_greta_deps.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,12 @@
#' virtual or conda environment, named "greta-env-tf2". Note that "virtualenv"
#' is not available on Windows.
#'
#' @param method Installation method ("virtualenv" or "conda")
#' @param conda The path to a `conda` executable. Use `"auto"` to allow
#' `reticulate` to automatically find an appropriate `conda` binary. See
#' **Finding Conda** for more details.
#' @param python_deps object created with `greta_python_deps()` where you
#' specify python, TF, and TFP versions.
#'
#' @param timeout maximum time in minutes until the installation for each
#' installation component times out and exits. Default is 5 minutes per
#' installation component.
#' @param manual logical. Skip the fancy installation and just run:
#' ```
#' reticulate::py_install(
#' packages = c(
#' 'numpy',
#' 'tensorflow',
#' 'tensorflow-probability'
#' ),
#' pip = TRUE
#' )
#' ```
#' @param restart character. Restart R after installation? Default is "ask".
#' Other options are, "force", and "no". Using "force" will will force a
#' restart after installation. Using "no" will not restart. Note that this
Expand Down Expand Up @@ -69,13 +57,13 @@
#' @importFrom callr r_process
#' @importFrom cli cli_alert_success
#' @importFrom cli cli_ul
install_greta_deps <- function(method = c("auto", "virtualenv", "conda"),
conda = "auto",
install_greta_deps <- function(python_deps = greta_python_deps(),
timeout = 5,
manual = FALSE,
restart = c("ask", "force", "no"),
...) {

check_greta_python_deps(python_deps)

restart <- rlang::arg_match(
arg = restart,
values = c("ask", "force", "no")
Expand All @@ -84,35 +72,26 @@ install_greta_deps <- function(method = c("auto", "virtualenv", "conda"),
# set warning message length
options(warning.length = 2000)

if (manual) {
reticulate::py_install(
packages = c(
'numpy',
'tensorflow==2.15',
'tensorflow-probability==0.23.0',
"keras==2.15.0"
),
envname = "greta-env-tf2",
pip = TRUE
)
} else if (!manual) {

# install miniconda if needed
if (!have_conda()) {
greta_install_miniconda(timeout)
}

if (!have_greta_conda_env()) {
greta_create_conda_env(timeout)
}

greta_install_python_deps(timeout)
# install miniconda if needed
if (!have_conda()) {
greta_install_miniconda(timeout)
}

if (!have_greta_conda_env()) {
greta_create_conda_env(
timeout = timeout,
python_deps = python_deps
)
}

cli_alert_success("Installation of {.pkg greta} dependencies is complete!")
greta_install_python_deps(
timeout = timeout,
python_deps = python_deps
)

cli_alert_success("Installation of {.pkg greta} dependencies is complete!")

restart_or_not(restart)
restart_or_not(restart)

}

Expand Down Expand Up @@ -160,3 +139,65 @@ restart_or_not <- function(restart){
}

}

## TODO
## Add a way to pass this along to a custom simpler python installer function
## A la:
# reticulate::py_install(
# packages = c(
# 'numpy',
# 'tensorflow==2.15',
# 'tensorflow-probability==0.23.0',
# "keras==2.15.0"
# ),
# envname = "greta-env-tf2",
# pip = TRUE
# )

#' Specify python dependencies for greta
#'
#' A helper function for specifying versions of Tensorflow (TF), Tensorflow Probability (TFP), and Python.
#'
#' @param tf_version Character. Tensorflow (TF) version in format major.minor.patch. Default is "2.15.0".
#' @param tfp_version Character.Tensorflow probability (TFP) version major.minor.patch. Default is "0.23.0".
#' @param python_version Character. Ptyhon version in format major.minor.patch. Default is "3.10".
#'
#' @return list of dependencies
#' @export
#'
#' @examples
#' greta_python_deps()
greta_python_deps <- function(tf_version = "2.15.0",
tfp_version = "0.23.0",
python_version = "3.10"){

deps_list <- list(
tf_version = tf_version,
tfp_version = tfp_version,
python_version = python_version
)

structure(
deps_list,
class = "greta_python_deps"
)

}

check_greta_python_deps <- function(deps) {
if (!inherits(deps, "greta_python_deps")) {
cli::cli_abort("{.arg deps} must be created by {.fun greta_python_deps}.")
}
}

#' Print method for greta python deps
#'
#' @param x greta python deps
#' @param ... extra args, not used
#' @export
print.greta_python_deps <- function(x, ...){
cli::cli_h1("{.pkg greta} Python dependency spec:")
cli::cli_li("{.pkg TF} Version: {.val {x$tf_version}}")
cli::cli_li("{.pkg TFP} Version: {.val {x$tfp_version}}")
cli::cli_li("{.pkg Python} Version: {.val {x$python_version}}")
}
1 change: 0 additions & 1 deletion R/new_install_process.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ new_install_process <- function(callr_process,
stderr_file = NULL,
cli_start_msg = NULL,
cli_end_msg = NULL){
options(warning.length = 2000)
cli::cli_process_start(cli_start_msg)
# convert max timeout from milliseconds into minutes
timeout_minutes <- timeout * 1000 * 60
Expand Down
2 changes: 1 addition & 1 deletion R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,7 @@ other_install_fail_msg <- function(error_passed){
)
}

timeout_install_msg <- function(timeout, py_error = NULL){
timeout_install_msg <- function(timeout = 5, py_error = NULL){
msg <- c(
"Stopping as installation of {.pkg greta} dependencies took longer than \\
{timeout} minutes",
Expand Down
28 changes: 28 additions & 0 deletions man/greta_python_deps.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 3 additions & 11 deletions man/install_greta_deps.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions man/print.greta_python_deps.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 7b9eb5c

Please sign in to comment.