|
| 1 | +#' Greta Situation Report |
| 2 | +#' |
| 3 | +#' This checks if Python, Tensorflow, Tensorflow Probability, and the greta |
| 4 | +#' conda environment are available, and also loads and initialises python |
| 5 | +#' |
| 6 | +#' @param verbosity character. How verbose the output of the situation report. |
| 7 | +#' Possible options: "minimal" (default), "detailed", and "quiet". "Minimal" |
| 8 | +#' provides just information in python version, tensorflow version, |
| 9 | +#' tensorflow proability, and whether greta conda environment is available. |
| 10 | +#' "Quiet" presents no information, but prepares greta to be used. "Detailed" |
| 11 | +#' gives information on the version and path for R, greta, python, |
| 12 | +#' tensorflow, tensorflow probability, the greta conda environment, and a |
| 13 | +#' statement on greta usability. |
| 14 | +#' @return Message on greta situation report. See "verbsoity" parameter details |
| 15 | +#' above for more information. |
| 16 | +#' @export |
| 17 | +#' |
| 18 | +#' @examples |
| 19 | +#' \dontrun{ |
| 20 | +#' greta_sitrep() |
| 21 | +#' } |
| 22 | +greta_sitrep <- function(verbosity = c("minimal", "detailed", "quiet")){ |
| 23 | + |
| 24 | + verbosity <- rlang::arg_match( |
| 25 | + arg = verbosity, |
| 26 | + values = c("minimal", "detailed", "quiet"), |
| 27 | + error_arg = "verbosity" |
| 28 | + ) |
| 29 | + |
| 30 | + switch( |
| 31 | + verbosity, |
| 32 | + minimal = minimal_sitrep(), |
| 33 | + detailed = detailed_sitrep(), |
| 34 | + quiet = quiet_sitrep() |
| 35 | + ) |
| 36 | + |
| 37 | + |
| 38 | +} |
| 39 | + |
| 40 | +check_if_python_available <- function(){ |
| 41 | + check_if_software_available( |
| 42 | + software_available = have_python(), |
| 43 | + version = reticulate::py_version(), |
| 44 | + software_name = "python" |
| 45 | + ) |
| 46 | +} |
| 47 | + |
| 48 | +check_if_tf_available <- function(){ |
| 49 | + check_if_software_available( |
| 50 | + software_available = have_tf(), |
| 51 | + version = version_tf(), |
| 52 | + software_name = "TensorFlow" |
| 53 | + ) |
| 54 | +} |
| 55 | + |
| 56 | +check_if_tfp_available <- function(){ |
| 57 | + check_if_software_available( |
| 58 | + software_available = have_tfp(), |
| 59 | + version = version_tfp(), |
| 60 | + software_name = "TensorFlow Probability" |
| 61 | + ) |
| 62 | +} |
| 63 | + |
| 64 | +check_if_greta_conda_env_available <- function(){ |
| 65 | + check_if_software_available(software_available = have_greta_conda_env(), |
| 66 | + software_name = "greta conda environment") |
| 67 | + |
| 68 | +} |
| 69 | + |
| 70 | +software_availability <- function(){ |
| 71 | + software_available <- c( |
| 72 | + python = have_python(), |
| 73 | + tf = have_tf(), |
| 74 | + tfp = have_tfp(), |
| 75 | + greta_env = have_greta_conda_env() |
| 76 | + ) |
| 77 | + software_available |
| 78 | +} |
| 79 | + |
| 80 | + |
| 81 | +get_current_ideal_deps <- function(){ |
| 82 | + |
| 83 | + software_version <- data.frame( |
| 84 | + software = c( |
| 85 | + "python", |
| 86 | + "tfp", |
| 87 | + "tf" |
| 88 | + ), |
| 89 | + current = c( |
| 90 | + paste0(reticulate::py_version()), |
| 91 | + paste0(version_tf()), |
| 92 | + paste0(version_tfp()) |
| 93 | + ), |
| 94 | + # versions must be at least this version |
| 95 | + ideal = c( |
| 96 | + "3.8", |
| 97 | + "2.15.0", |
| 98 | + "0.23.0" |
| 99 | + ) |
| 100 | + ) |
| 101 | + |
| 102 | + software_version$match <- c( |
| 103 | + compareVersion(software_version$current[1], software_version$ideal[1]) >= 0, |
| 104 | + compareVersion(software_version$current[2], software_version$ideal[2]) >= 0, |
| 105 | + compareVersion(software_version$current[3], software_version$ideal[3]) >= 0 |
| 106 | + ) |
| 107 | + |
| 108 | + software_version |
| 109 | + |
| 110 | +} |
| 111 | + |
| 112 | +check_greta_ready_to_use <- function(software_available){ |
| 113 | + |
| 114 | + if (!all(software_available)) { |
| 115 | + check_tf_version("warn") |
| 116 | + } else if (all(software_available)) { |
| 117 | + software_version <- get_current_ideal_deps() |
| 118 | + |
| 119 | + if (all(software_version$match)){ |
| 120 | + check_tf_version("none") |
| 121 | + cli::cli_alert_info("{.pkg greta} is ready to use!", |
| 122 | + wrap = TRUE) |
| 123 | + } else { |
| 124 | + check_tf_version("warn") |
| 125 | + } |
| 126 | + |
| 127 | + } |
| 128 | + |
| 129 | +} |
| 130 | + |
| 131 | + |
| 132 | +minimal_sitrep <- function(){ |
| 133 | + |
| 134 | + check_if_python_available() |
| 135 | + check_if_tf_available() |
| 136 | + check_if_tfp_available() |
| 137 | + check_if_greta_conda_env_available() |
| 138 | + |
| 139 | + software_available <- software_availability() |
| 140 | + |
| 141 | + check_greta_ready_to_use(software_available) |
| 142 | + |
| 143 | +} |
| 144 | + |
| 145 | +detailed_sitrep <- function(){ |
| 146 | + |
| 147 | + config_info <- reticulate::py_config() |
| 148 | + |
| 149 | + cli::cli_h1("R") |
| 150 | + cli::cli_ul("version: {.val {getRversion()}}") |
| 151 | + cli::cli_ul("path: {R.home()}") |
| 152 | + cli::cli_h1("{.pkg greta}") |
| 153 | + cli::cli_ul("version: {.val {packageVersion('greta')}}") |
| 154 | + cli::cli_ul("path: {.val {find.package('greta')}}") |
| 155 | + |
| 156 | + cli::cli_h1("{.pkg python}") |
| 157 | + check_if_python_available() |
| 158 | + cli::cli_ul("path: {.val {find.package('greta')}}") |
| 159 | + cli::cli_ul("path: {.val {reticulate::miniconda_path()}}") |
| 160 | + |
| 161 | + cli::cli_h1("{.pkg TensorFlow}") |
| 162 | + check_if_tf_available() |
| 163 | + cli::cli_ul("R path: {.path {find.package('tensorflow')}}") |
| 164 | + cli::cli_ul("python path: {.val {find.package('greta')}}") |
| 165 | + |
| 166 | + cli::cli_h1("{.pkg TensorFlow Probability}") |
| 167 | + check_if_tfp_available() |
| 168 | + cli::cli_ul("R path: {.path {find.package('tensorflow')}}") |
| 169 | + cli::cli_ul("python path: {.val {find.package('greta')}}") |
| 170 | + |
| 171 | + cli::cli_h1("{.pkg greta conda environment}") |
| 172 | + check_if_greta_conda_env_available() |
| 173 | + show_greta_conda_env_path() |
| 174 | + |
| 175 | + software_available <- software_availability() |
| 176 | + |
| 177 | + check_greta_ready_to_use(software_available) |
| 178 | + |
| 179 | +} |
| 180 | + |
| 181 | +quiet_sitrep <- function(){ |
| 182 | + |
| 183 | + suppressMessages({ |
| 184 | + |
| 185 | + software_available <- software_availability() |
| 186 | + |
| 187 | + check_greta_ready_to_use(software_available) |
| 188 | + }) |
| 189 | + |
| 190 | +} |
| 191 | + |
| 192 | +check_if_software_available <- function(software_available, |
| 193 | + version = NULL, |
| 194 | + ideal_version = NULL, |
| 195 | + software_name){ |
| 196 | + |
| 197 | + cli::cli_process_start("checking if {.pkg {software_name}} available") |
| 198 | + # if the software is detected |
| 199 | + |
| 200 | + if (!software_available) { |
| 201 | + cli::cli_process_failed( |
| 202 | + msg_failed = "{.pkg {software_name}} not available" |
| 203 | + ) |
| 204 | + } |
| 205 | + |
| 206 | + if (software_available) { |
| 207 | + |
| 208 | + if (is.null(ideal_version) & !is.null(version)){ |
| 209 | + cli::cli_process_done( |
| 210 | + msg_done = "{.pkg {software_name}} (v{version}) available" |
| 211 | + ) |
| 212 | + } |
| 213 | + |
| 214 | + # if it has a version and ideal version |
| 215 | + has_ideal_version <- !is.null(version) & !is.null(ideal_version) |
| 216 | + if (has_ideal_version){ |
| 217 | + version_chr <- paste0(version) |
| 218 | + version_match <- compareVersion(version_chr, ideal_version) == 0 |
| 219 | + |
| 220 | + if (version_match){ |
| 221 | + cli::cli_process_done( |
| 222 | + msg_done = "{.pkg {software_name}} (v{version}) available" |
| 223 | + ) |
| 224 | + } |
| 225 | + if (!version_match){ |
| 226 | + cli::cli_process_failed( |
| 227 | + msg_failed = "{.pkg {software_name}} available, \\ |
| 228 | + however {.strong {ideal_version}} is needed and \\ |
| 229 | + {.strong {version}} was detected" |
| 230 | + ) |
| 231 | + } |
| 232 | + # if there is no version for the software |
| 233 | + } else if (is.null(version)){ |
| 234 | + cli::cli_process_done( |
| 235 | + msg_done = "{.pkg {software_name}} available" |
| 236 | + ) |
| 237 | + } |
| 238 | + } |
| 239 | +} |
| 240 | + |
| 241 | +compare_version_vec <- Vectorize( |
| 242 | + FUN = compareVersion, |
| 243 | + vectorize.args = "b", |
| 244 | + SIMPLIFY = TRUE |
| 245 | +) |
| 246 | + |
| 247 | +# find out whether the usr has conda installed and visible |
| 248 | +#' @importFrom reticulate conda_binary |
| 249 | +have_conda <- function() { |
| 250 | + conda_bin <- tryCatch(reticulate::conda_binary("auto"), |
| 251 | + error = function(e) NULL |
| 252 | + ) |
| 253 | + !is.null(conda_bin) |
| 254 | +} |
| 255 | + |
| 256 | +#' @importFrom reticulate py_available |
| 257 | +have_python <- function() { |
| 258 | + tryCatch( |
| 259 | + expr = reticulate::py_available(initialize = TRUE), |
| 260 | + error = function(e) FALSE |
| 261 | + ) |
| 262 | +} |
| 263 | + |
| 264 | +#' @importFrom reticulate py_module_available |
| 265 | +have_tfp <- function() { |
| 266 | + is_tfp_available <- reticulate::py_module_available("tensorflow_probability") |
| 267 | + |
| 268 | + if (is_tfp_available) { |
| 269 | + |
| 270 | + pkg <- reticulate::import("pkg_resources") |
| 271 | + tfp_version <- pkg$get_distribution("tensorflow_probability")$version |
| 272 | + is_tfp_available <- utils::compareVersion("0.15.0", tfp_version) <= 0 |
| 273 | + |
| 274 | + } |
| 275 | + |
| 276 | + return(is_tfp_available) |
| 277 | + |
| 278 | +} |
| 279 | + |
| 280 | +#' @importFrom reticulate py_module_available |
| 281 | +have_tf <- function() { |
| 282 | + is_tf_available <- reticulate::py_module_available("tensorflow") |
| 283 | + |
| 284 | + if (is_tf_available) { |
| 285 | + |
| 286 | + tf_version <- suppressMessages(tf$`__version__`) |
| 287 | + is_tf_available <- utils::compareVersion("2.9.0", tf_version) <= 0 |
| 288 | + |
| 289 | + } |
| 290 | + |
| 291 | + return(is_tf_available) |
| 292 | + |
| 293 | +} |
| 294 | + |
| 295 | +version_tf <- function(){ |
| 296 | + if (have_tf()) { |
| 297 | + tf$`__version__` |
| 298 | + } else { |
| 299 | + NULL |
| 300 | + } |
| 301 | +} |
| 302 | + |
| 303 | +version_tfp <- function(){ |
| 304 | + if (have_tfp()) { |
| 305 | + tfp$`__version__` |
| 306 | + } else { |
| 307 | + NULL |
| 308 | + } |
| 309 | +} |
0 commit comments