diff --git a/DESCRIPTION b/DESCRIPTION index 911f634f8..f7f37f8cc 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -36,29 +36,29 @@ Depends: R (>= 4.0) Imports: ape (>= 5.6), cli (>= 3.0), - cluster, fastmap, fastmatch (>= 1.1.3), - fs, - future, PlotTools, - promises, - protoclust, Rcpp, Rdpack (>= 0.7), Rogue (> 2.0.0), - shiny (>= 1.6.0), - shinyjs, stats, stringi, TreeDist (>= 2.6.3), TreeTools (>= 1.16), Suggests: + cluster, + fs, + future, knitr, phangorn (>= 2.2.1), + promises, + protoclust, Quartet, readxl, rmarkdown, + shiny (>= 1.6.0), + shinyjs, shinytest, spelling, testthat, diff --git a/NAMESPACE b/NAMESPACE index 79e40d690..bcd152bec 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -205,18 +205,10 @@ importFrom(cli,cli_h1) importFrom(cli,cli_progress_bar) importFrom(cli,cli_progress_done) importFrom(cli,cli_progress_update) -importFrom(cluster,pam) -importFrom(cluster,silhouette) importFrom(fastmap,fastmap) importFrom(fastmatch,"%fin%") importFrom(fastmatch,fmatch) -importFrom(fs,path_sanitize) -importFrom(future,future) importFrom(graphics,par) -importFrom(promises,future_promise) -importFrom(protoclust,protoclust) -importFrom(shiny,runApp) -importFrom(shinyjs,useShinyjs) importFrom(stats,as.dist) importFrom(stats,cutree) importFrom(stats,median) diff --git a/R/ClusterStrings.R b/R/ClusterStrings.R index 1ee081e7d..43953f206 100644 --- a/R/ClusterStrings.R +++ b/R/ClusterStrings.R @@ -18,8 +18,6 @@ #' paste0("AnotherCluster_", letters[1:6]))) #' @template MRS #' @importFrom utils adist -#' @importFrom cluster pam silhouette -#' @importFrom protoclust protoclust #' @importFrom stats as.dist cutree #' @family utility functions #' @export @@ -28,6 +26,9 @@ ClusterStrings <- function (x, maxCluster = 12) { stop("`maxCluster` must be at least two.") } + .InstallSuggestedPackage("cluster") + .InstallSuggestedPackage("protoclust") + if (length(unique(x)) < maxCluster) { nom <- unique(x) structure(match(x, nom), "med" = nom) @@ -42,19 +43,19 @@ ClusterStrings <- function (x, maxCluster = 12) { kInc <- 1 / (nMethodsChecked * nK) pamClusters <- lapply(possibleClusters, function (k) { - pam(dists, k = k) + cluster::pam(dists, k = k) }) pamSils <- vapply(pamClusters, function (pamCluster) { - mean(silhouette(pamCluster)[, 3]) + mean(cluster::silhouette(pamCluster)[, 3]) }, double(1)) bestPam <- which.max(pamSils) pamSil <- pamSils[bestPam] pamCluster <- pamClusters[[bestPam]][["clustering"]] - hTree <- protoclust(as.dist(dists)) + hTree <- protoclust::protoclust(as.dist(dists)) hClusters <- lapply(possibleClusters, function (k) cutree(hTree, k = k)) hSils <- vapply(hClusters, function (hCluster) { - mean(silhouette(hCluster, dists)[, 3]) + mean(cluster::silhouette(hCluster, dists)[, 3]) }, double(1)) bestH <- which.max(hSils) hSil <- hSils[bestH] diff --git a/R/MaximizeParsimony.R b/R/MaximizeParsimony.R index ef6d237cc..218cf9165 100644 --- a/R/MaximizeParsimony.R +++ b/R/MaximizeParsimony.R @@ -999,17 +999,9 @@ Resample <- function(dataset, tree, method = "jack", proportion = 2 / 3, #' Launch tree search graphical user interface #' #' @rdname MaximizeParsimony -#' @importFrom cluster pam silhouette -#' @importFrom future future -#' @importFrom PlotTools SpectrumLegend -#' @importFrom promises future_promise -#' @importFrom protoclust protoclust -#' @importFrom Rogue ColByStability -#' @importFrom shiny runApp -#' @importFrom shinyjs useShinyjs -#' @importFrom TreeDist ClusteringInfoDistance #' @export EasyTrees <- function () {#nocov start + .InstallSuggestedPackage("shinyjs") shiny::runApp(system.file("Parsimony", package = "TreeSearch")) } diff --git a/R/TaxonInfluence.R b/R/TaxonInfluence.R index 51397ddfc..f27956775 100644 --- a/R/TaxonInfluence.R +++ b/R/TaxonInfluence.R @@ -106,7 +106,6 @@ #' @family tree scoring #' @importFrom ape read.nexus write.nexus #' @importFrom cli cli_alert_info cli_h1 -#' @importFrom fs path_sanitize #' @importFrom stats weighted.mean #' @importFrom TreeDist ClusteringInfoDistance #' @encoding UTF-8 @@ -122,6 +121,7 @@ TaxonInfluence <- function( ... ) { if (!is.null(savePath)) { + .InstallSuggestedPackage("fs") saveDir <- dirname(paste0(savePath, "taxon_name")) if (!dir.exists(saveDir)) { dir.create(saveDir, recursive = TRUE) @@ -153,9 +153,13 @@ TaxonInfluence <- function( # Return: vapply(names(dataset), function(leaf) { - leafFile <- paste0(savePath, path_sanitize(leaf), ".nex") + leafFile <- if (!is.null(savePath)) { + paste0(savePath, fs::path_sanitize(leaf), ".nex") + } else { + NULL + } - result <- if (useCache && file.exists(leafFile)) { + result <- if (useCache && !is.null(leafFile) && file.exists(leafFile)) { if (verbosity > 1) { cli_alert_info(paste("Seeking cache: ", leafFile)) } diff --git a/R/TreeSearch_utilities.R b/R/TreeSearch_utilities.R index 0945cfe59..63abfe6f2 100644 --- a/R/TreeSearch_utilities.R +++ b/R/TreeSearch_utilities.R @@ -11,3 +11,28 @@ EmptyPhyDat <- function(tree) { #' @rdname TreeSearch #' @export DoNothing <- function(x = NULL) {x} + +# Helper function to install suggested packages with user prompt +.InstallSuggestedPackage <- function(package) { + if (!requireNamespace(package, quietly = TRUE)) { + if (interactive()) { + message("Package '", package, "' is required but not installed.") + response <- readline(prompt = paste0("Install ", package, "? (y/n): ")) + if (tolower(trimws(response)) == "y") { + install.packages(package) + if (!requireNamespace(package, quietly = TRUE)) { + stop("Failed to install package '", package, "'", call. = FALSE) + } + } else { + stop("Package '", package, "' is required. ", + "Install it with: install.packages('", package, "')", + call. = FALSE) + } + } else { + stop("Package '", package, "' is required. ", + "Install it with: install.packages('", package, "')", + call. = FALSE) + } + } +} + diff --git a/tests/testthat/test-ClusterStrings.R b/tests/testthat/test-ClusterStrings.R index 6efef66e8..cc356d7bb 100644 --- a/tests/testthat/test-ClusterStrings.R +++ b/tests/testthat/test-ClusterStrings.R @@ -1,4 +1,7 @@ test_that("ClusterStrings() works", { + skip_if_not_installed("cluster") + skip_if_not_installed("protoclust") + x <- rep(letters[1:6], 1:6) expect_equal(ClusterStrings(x), structure(rep(1:6, 1:6), "med" = letters[1:6])) diff --git a/tests/testthat/test-TaxonInfluence.R b/tests/testthat/test-TaxonInfluence.R index 6a605ead5..9ec779104 100644 --- a/tests/testthat/test-TaxonInfluence.R +++ b/tests/testthat/test-TaxonInfluence.R @@ -23,6 +23,8 @@ test_that("TaxonInfluence() works", { }) test_that("TaxonInfluence() saves intermediate trees", { + skip_if_not_installed("fs") + library("TreeTools") # for phyDat manipulation data("congreveLamsdellMatrices", package = "TreeSearch") set.seed(0)