diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index 3f52e87..1a50a4e 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -70,11 +70,12 @@ jobs: extra-packages: | any::rcmdcheck any::tidyverse + any::devtools needs: check - name: Check package uses: r-lib/actions/check-r-package@v2 with: - error-on: "\"error\"" + error-on: '"error"' upload-snapshots: true - build_args: "c(\"--no-manual\",\"--compact-vignettes=gs+qpdf\")" + build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index f036fa5..9d848d5 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -6,7 +6,7 @@ on: - main - develop release: - types: [ published ] + types: [published] workflow_dispatch: name: pkgdown.yaml diff --git a/.github/workflows/pr-commands.yaml b/.github/workflows/pr-commands.yaml index d305d28..bb4ba33 100644 --- a/.github/workflows/pr-commands.yaml +++ b/.github/workflows/pr-commands.yaml @@ -2,7 +2,7 @@ # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help on: issue_comment: - types: [ created ] + types: [created] name: pr-commands.yaml diff --git a/.github/workflows/render-rmarkdown.yaml b/.github/workflows/render-rmarkdown.yaml index 725b537..946de01 100644 --- a/.github/workflows/render-rmarkdown.yaml +++ b/.github/workflows/render-rmarkdown.yaml @@ -2,9 +2,9 @@ # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help on: pull_request: - branches: [ main ] + branches: [main] release: - types: [ published ] + types: [published] workflow_dispatch: name: render-rmarkdown.yaml diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml index 9f59b8a..52a4b0e 100644 --- a/.github/workflows/test-coverage.yaml +++ b/.github/workflows/test-coverage.yaml @@ -1,7 +1,6 @@ # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help on: - pull_request: branches: - main diff --git a/DESCRIPTION b/DESCRIPTION index a54712a..ebd7d99 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: BRCore -Title: Unified Framework for Identification and Ecological Interpretation of Microbial Data from Bioenergy Research Centers -Version: 2.0.4.9000 +Title: A Unified Framework for Identification and Ecological Interpretation of Microbial Data from Bioenergy Research Centers +Version: 2.0.7.9000 Authors@R: c( person("Bolívar", "Aponte Rolón", email = "bolaponte@pm.me", @@ -28,11 +28,9 @@ Authors@R: c( role = c("cph", "fnd")) ) Description: A unified framework for identification and ecological interpretation of core microbiomes across time and space, enhancing robustness and reproducibility in microbiome data analysis. 'BRCore' implements the workflow proposed by Shade and Stopnisek (2019) and incorporates additional rarefaction steps. The proposed workflow aims to identify persistent microbiomes using abundance-occupancy distributions and neutral community model fitting. For more details on abundance-occupancy distributions see Shade A, Stopnisek N (2019) , for neutral models, see Sloan et al. (2006) and Burns et al. (2015) . -License: MIT + file LICENSE -Encoding: UTF-8 -Language: en-US -Roxygen: list(markdown = TRUE) -RoxygenNote: 7.3.3 +Depends: + R (>= 4.4) +biocViews: Imports: cli (>= 3.6.5), dplyr (>= 1.1.4), @@ -42,24 +40,25 @@ Imports: Hmisc (>= 5.2.4), magrittr (>= 2.0.4), minpack.lm (>= 1.2.4), - phyloseq (>= 1.54.0), + phyloseq, rlang (>= 1.1.6), scales (>= 1.4.0), - stats4 (>= 4.5.2), + stats4, tibble (>= 3.3.0), tidyr (>= 1.3.1), vegan (>= 2.7.2) Suggests: - devtools (>= 2.4.5), - here (>= 1.0.1), knitr (>= 1.50), rmarkdown (>= 2.30), testthat (>= 3.2.3), tidyverse (>= 2.0.0), viridis (>= 0.6.5) +License: MIT + file LICENSE +Encoding: UTF-8 +Language: en-US +Roxygen: list(markdown = TRUE) +RoxygenNote: 7.3.3 Config/testthat/edition: 3 -Depends: - R (>= 4.4) LazyData: true VignetteBuilder: knitr URL: https://github.com/germs-lab/BRCore, https://www.germslab.org/BRCore/ diff --git a/NEWS.md b/NEWS.md index bf6468e..6f00635 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,8 +1,34 @@ # BRCore (development version) -* Fixes to quote 'BRCore' in DESCRIPTION and typo fix of `sncm.fit` in _pkgdown.yaml + +# BRCore 2.0.7 +2026-05-19 + +* [a43bc71](https://github.com/germs-lab/BRCore/commit/a43bc71d779c5b1b11b1291056570c6e00124212) Typo and instructions fixes to README and DESCRIPTION files. + +# BRCore 2.0.5 +2026-05-18 + +## Bug Fixes + +* Relaxed version requirements for `phyloseq` and `stats4` to improve compatibility. + +* [5ba7a7c](https://github.com/germs-lab/BRCore/commit/5ba7a7c3067a2044c34aee812795dc427869eb4b) Added `biocViews` field to DESCRIPTION to allow installation of Bioconductor dependencies via `install.packages()`. +* [40d79e4](https://github.com/germs-lab/BRCore/commit/40d79e448c632f590e4e52cbf16537496b29529f) Fixes to quote 'BRCore' in DESCRIPTION and typo fix of `sncm.fit` in _pkgdown.yaml + +## Refactoring + +* [95a42db](https://github.com/germs-lab/BRCore/commit/95a42db482675450157ec2099a658e0ce538901c) `sncm.fit()`: replaced `suppressWarnings()` with targeted warning capture via new internal helper `.internal_warn_sncm()`. +* [46eff6f](https://github.com/germs-lab/BRCore/commit/46eff6fb691fd370e5b3723e285bb3882760d742) `plot_neutral_model()`: refined plot axis styling and formatted y-axis as percent. Resized box annotation. +* [b275861](https://github.com/germs-lab/BRCore/commit/b275861e8434204d66dc4962d10499488d738513) Removed redundant `data("bcse")` calls from examples and README vignette. + +## Documentation + +* [46ef2ba](https://github.com/germs-lab/BRCore/commit/46ef2ba1ebb006736f9b86bfa7b06f3adca40f49) Updated vignette output. +* [b275861](https://github.com/germs-lab/BRCore/commit/b275861e8434204d66dc4962d10499488d738513) Removed deprecated `num_iter` parameter from README examples. +* Reordered DESCRIPTION fields. # BRCore 2.0.4 -Date: 2026-04-30 +2026-04-30 * Fixes to documentation: * DOI links updated to correct format @@ -13,7 +39,7 @@ Date: 2026-04-30 * New APA 7th edition style for references # BRCore 2.0.2 -Date: 2026-04-28 +2026-04-28 * Fixes to vignette and function documentation prior to CRAN submission. * Removed "multiple rarefaction" concept from documentation. @@ -21,12 +47,12 @@ Date: 2026-04-28 * Cleaned NAMESPACE and DESCRIPTION. # BRCore 2.0.1 -Date: 2026-04-25 +2026-04-25 * Resubmission to CRAN to address auto-check issues on Debian and Windows. # BRCore 2.0.0 -Date: 2026-04-24 +2026-04-24 ## Breaking Changes @@ -68,7 +94,7 @@ Date: 2026-04-24 @jibarozzo @Gian77 # BRCore 1.0.2 -Date: 2026-02-25 +2026-02-25 ## Bug Fixes diff --git a/R/add_rarefaction_metrics.R b/R/add_rarefaction_metrics.R index b9c6cd9..4fa262f 100644 --- a/R/add_rarefaction_metrics.R +++ b/R/add_rarefaction_metrics.R @@ -35,8 +35,6 @@ #' library(phyloseq) #' library(BRCore) #' -#' data("bcse", package = "BRCore") -#' #' # Adding metrics to a "phyloseq" object #' bcse_metrics <- add_rarefaction_metrics(data = bcse) #' sample_data(bcse_metrics)|> diff --git a/R/brcore_theme.R b/R/brcore_theme.R index a9c32f4..52d73fa 100644 --- a/R/brcore_theme.R +++ b/R/brcore_theme.R @@ -78,7 +78,7 @@ # Axes ---- axis.title = element_text( size = base_size, - face = "bold", + face = "plain", colour = "black" ), axis.text = element_text( diff --git a/R/identify_core.R b/R/identify_core.R index 59fa9b6..38a5170 100644 --- a/R/identify_core.R +++ b/R/identify_core.R @@ -101,9 +101,6 @@ #' \donttest{ #' library(BRCore) #' -#' data("switchgrass", package = "BRCore") -#' data("bcse", package = "BRCore") -#' #' # With rarefied data #' res <- identify_core( #' physeq_obj = switchgrass, diff --git a/R/multi_rarefy.R b/R/multi_rarefy.R index eef9e4a..18d8599 100644 --- a/R/multi_rarefy.R +++ b/R/multi_rarefy.R @@ -28,7 +28,7 @@ #' #' @examples #' library(BRCore) -#' data("bcse", package = "BRCore") +#' #' #' # Example rarefaction (single iteration, single core to keep examples fast) #' otu_table_rare <- multi_rarefy( diff --git a/R/plot_identified_core.R b/R/plot_identified_core.R index eb7990b..15d4dbd 100644 --- a/R/plot_identified_core.R +++ b/R/plot_identified_core.R @@ -69,12 +69,12 @@ plot_identified_core <- function( prop_range <- max_prop - min_prop # Dynamic y positions for labels - elbow_y <- min_prop + 0.15 * prop_range + elbow_y <- min_prop + 0.1 * prop_range lastCall_y <- min_prop + 0.35 * prop_range # Adjust x position for labels if too close to edges elbow_x_offset <- ifelse( - elbow < max_rank * 0.1, + elbow < max_rank * 1.2, elbow + max_rank * 0.02, elbow - max_rank * 0.02 ) @@ -86,7 +86,7 @@ plot_identified_core <- function( # Base plot p <- ggplot(new_data, aes(x = rank_num, y = proportionBC)) + - geom_point(size = 1.5, alpha = 0.7) + + geom_point(size = 2, alpha = 0.7) + geom_vline( xintercept = elbow, linetype = "dashed", @@ -162,9 +162,10 @@ plot_identified_core <- function( " OTUs)" ), x = "Ranked OTUs", - y = "% Bray-Curtis similarity" + y = "Bray-Curtis similarity" ) + .brcore_theme() + + scale_y_continuous(labels = scales::label_percent(accuracy = 1)) + scale_x_continuous(breaks = seq(0, max(new_data$rank_num), by = 5)) return(list( diff --git a/R/plot_neutral_model.R b/R/plot_neutral_model.R index 0c01c00..167af65 100644 --- a/R/plot_neutral_model.R +++ b/R/plot_neutral_model.R @@ -205,7 +205,7 @@ plot_neutral_model <- function(fit_result) { parse = TRUE, hjust = 1, vjust = -0.75, - size = 3, + size = 4.5, fill = "white", alpha = 0.9, lineheight = 1.05 @@ -214,7 +214,8 @@ plot_neutral_model <- function(fit_result) { title = "Neutral model", x = "Log10(mean abundance)", y = "Occupancy" - ) + ) + + scale_y_continuous(labels = scales::label_percent(accuracy = 1)) # change legend shape to avoid confusion with the scatter points. p <- p + guides( diff --git a/R/plot_rarefaction_metrics.R b/R/plot_rarefaction_metrics.R index bb1f95a..805009b 100644 --- a/R/plot_rarefaction_metrics.R +++ b/R/plot_rarefaction_metrics.R @@ -15,8 +15,6 @@ #' library(phyloseq) #' library(BRCore) #' -#' data("bcse", package = "BRCore") -#' #' # Add rarefaction metrics to the phyloseq object #' bcse_metrics <- add_rarefaction_metrics(bcse) #' diff --git a/R/plot_variance_propagation.R b/R/plot_variance_propagation.R index f55b23b..e3b5082 100644 --- a/R/plot_variance_propagation.R +++ b/R/plot_variance_propagation.R @@ -23,7 +23,6 @@ #' library(phyloseq) #' library(BRCore) #' # Example comparing hill q=1 between Poplar and Switchgrass plots -#' data("bcse", package = "BRCore") #' bcse_filt <- bcse |> #' subset_samples(Crop %in% c("Poplar", "Switchgrass")) #' diff --git a/R/sncm.fit.R b/R/sncm.fit.R index 5c83810..edf690b 100644 --- a/R/sncm.fit.R +++ b/R/sncm.fit.R @@ -70,7 +70,6 @@ #' @importFrom minpack.lm nlsLM #' @importFrom Hmisc binconf #' @importFrom stats4 mle -#' @importFrom stats pbeta #' #' @export sncm.fit <- function(spp, pool = NULL, stats = TRUE, taxon = NULL) { @@ -108,19 +107,39 @@ sncm.fit <- function(spp, pool = NULL, stats = TRUE, taxon = NULL) { d <- 1 / N ## Fit model parameter m (or Nm) using Non-linear least squares (NLS) + warned_nls_pbeta <- FALSE m.fit <- minpack.lm::nlsLM( - freq ~ stats::pbeta(d, N * m * p, N * m * (1 - p), lower.tail = FALSE), + freq ~ .internal_warn_sncm( + \() stats::pbeta(d, N * m * p, N * m * (1 - p), lower.tail = FALSE), + message = "NLS `stats::pbeta()` produced a warning during fitting", + warned = warned_nls_pbeta, + warn_setter = function() warned_nls_pbeta <<- TRUE + ), start = list(m = 0.1) ) m.ci <- stats::confint(m.fit, "m", level = 0.95) ## Fit neutral model parameter m (or Nm) using Maximum likelihood estimation (MLE) - sncm.LL <- function(m, sigma) { - R <- freq - - stats::pbeta(d, N * m * p, N * m * (1 - p), lower.tail = FALSE) - R <- suppressWarnings(stats::dnorm(R, 0, sigma)) - -base::sum(base::log(R)) - } + sncm.LL <- local({ + warned_pbeta <- FALSE + warned_dnorm <- FALSE + function(m, sigma) { + R <- freq - + .internal_warn_sncm( + \() stats::pbeta(d, N * m * p, N * m * (1 - p), lower.tail = FALSE), + message = "SNCM `stats::pbeta()` produced a warning during MLE", + warned = warned_pbeta, + warn_setter = function() warned_pbeta <<- TRUE + ) + R <- .internal_warn_sncm( + \() stats::dnorm(R, 0, sigma), + message = "SNCM `stats::dnorm()` produced a warning during MLE", + warned = warned_dnorm, + warn_setter = function() warned_dnorm <<- TRUE + ) + -base::sum(base::log(R)) + } + }) m.mle <- stats4::mle( sncm.LL, start = list(m = 0.1, sigma = 0.1), @@ -132,12 +151,21 @@ sncm.fit <- function(spp, pool = NULL, stats = TRUE, taxon = NULL) { bic.fit <- stats::BIC(m.mle) ## Calculate goodness-of-fit (R-squared and Root Mean Squared Error) - freq.pred <- stats::pbeta( - d, - N * stats::coef(m.fit) * p, - N * stats::coef(m.fit) * (1 - p), - lower.tail = FALSE + warned_goodns_pbeta <- FALSE + freq.pred <- .internal_warn_sncm( + \() { + stats::pbeta( + d, + N * stats::coef(m.fit) * p, + N * stats::coef(m.fit) * (1 - p), + lower.tail = FALSE + ) + }, + message = "SNCM `stats::pbeta()` produced a warning during goodness-of-fit calculation", + warned = warned_goodns_pbeta, + warn_setter = function() warned_goodns_pbeta <<- TRUE ) + Rsqr <- 1 - (base::sum((freq - freq.pred)^2)) / (base::sum((freq - base::mean(freq))^2)) @@ -154,11 +182,19 @@ sncm.fit <- function(spp, pool = NULL, stats = TRUE, taxon = NULL) { ) ## Calculate AIC for binomial model - bino.LL <- function(mu, sigma) { - R <- freq - stats::pbinom(d, N.int, p, lower.tail = FALSE) - R <- suppressWarnings(stats::dnorm(R, mu, sigma)) - -base::sum(base::log(R)) - } + bino.LL <- local({ + warned_dnorm <- FALSE + function(mu, sigma) { + R <- freq - stats::pbinom(d, N.int, p, lower.tail = FALSE) + R <- .internal_warn_sncm( + \() stats::dnorm(R, mu, sigma), + message = "Binomial model `stats::dnorm()` produced a warning during MLE", + warned = warned_dnorm, + warn_setter = function() warned_dnorm <<- TRUE + ) + -base::sum(base::log(R)) + } + }) bino.mle <- stats4::mle( bino.LL, start = list(mu = 0, sigma = 0.1), @@ -186,11 +222,19 @@ sncm.fit <- function(spp, pool = NULL, stats = TRUE, taxon = NULL) { ) ## Calculate AIC for Poisson model - pois.LL <- function(mu, sigma) { - R <- freq - stats::ppois(d, N * p, lower.tail = FALSE) - R <- suppressWarnings(stats::dnorm(R, mu, sigma)) - -base::sum(base::log(R)) - } + pois.LL <- local({ + warned_dnorm <- FALSE + function(mu, sigma) { + R <- freq - stats::ppois(d, N * p, lower.tail = FALSE) + R <- .internal_warn_sncm( + \() stats::dnorm(R, mu, sigma), + message = "Poisson model `stats::dnorm()` produced a warning during MLE", + warned = warned_dnorm, + warn_setter = function() warned_dnorm <<- TRUE + ) + -base::sum(base::log(R)) + } + }) pois.mle <- stats4::mle( pois.LL, start = list(mu = 0, sigma = 0.1), diff --git a/R/utils-internal_warn_sncm.R b/R/utils-internal_warn_sncm.R new file mode 100644 index 0000000..6cf64c1 --- /dev/null +++ b/R/utils-internal_warn_sncm.R @@ -0,0 +1,31 @@ +#' Internal warning handler for sncm.fit likelihood functions +#' +#' Wraps a function call with a `withCallingHandlers()` that captures warnings +#' and re-emits them via `cli::cli_warn()`. Deduplicates repeated warnings +#' across optimizer iterations using an external flag and setter. +#' +#' @param fun A zero-argument function (lambda) to evaluate. +#' @param message A string prefix for the warning message. +#' @param warned Logical flag indicating whether a warning has already fired. +#' @param warn_setter A zero-argument function that sets the external `warned` +#' flag to `TRUE` via `<<-`. +#' +#' @return The result of `fun()`. +#' @keywords internal +.internal_warn_sncm <- function( + fun, + message = NULL, + warned = FALSE, + warn_setter = NULL +) { + withCallingHandlers( + fun(), + warning = function(w) { + if (!warned) { + cli::cli_warn("{message}: {conditionMessage(w)}") + if (!is.null(warn_setter)) warn_setter() + } + invokeRestart("muffleWarning") + } + ) +} diff --git a/README.Rmd b/README.Rmd index c127331..2c7d6cf 100644 --- a/README.Rmd +++ b/README.Rmd @@ -51,15 +51,18 @@ BRCore provides tools for: ## Installation -Install the latest *stable* version of BRCore from CRAN with: +### *Stable* version from CRAN with: ```{r} install.packages("BRCore") -``` -Install the *development* version of BRCore from GitHub with: +# or if using with `renv`: +renv::init(bioconductor = TRUE) +renv::install("BRCore") +``` +***NOTE:*** *If using `install.packages()` in an `renv` project, `renv` will intercept the call. Run `renv::init(bioconductor = TRUE)` first to ensure Bioconductor dependencies can be resolved and installed.* -Install the *development* version of BRCore from GitHub with: +### *Development* version from GitHub with: ```{r} # install.packages("pak") pak::pak("germs-lab/BRCore") @@ -73,9 +76,6 @@ pak::pak("germs-lab/BRCore") library(BRCore) library(phyloseq) -# Load example data -data("bcse", package = "BRCore") - # Add rarefaction metrics bcse_metrics <- add_rarefaction_metrics(data = bcse) @@ -89,9 +89,10 @@ bcse_rarefied_list <- multi_rarefy( # Update phyloseq object with rarefied data bcse_rare_single <- update_otu_table( - physeq_obj = bcse, - rarefied_otus = bcse_rarefied_list, - iteration = 2) # Your preffered iteration can be used here + physeq_obj = bcse, + rarefied_otus = bcse_rarefied_list, + iteration = 2 +) # Your preffered iteration can be used here # Identify core microbiome @@ -106,12 +107,11 @@ bcse_core <- identify_core( # With multiple iterations of rarefaction bcse_core_multi <- identify_core( - physeq_obj = bcse, - rarefied_list = bcse_rarefied_list + physeq_obj = bcse, + rarefied_list = bcse_rarefied_list, priority_var = "Crop", increase_value = 0.02, depth_level = 1000, - num_iter = 10, seed = 2134 ) diff --git a/README.md b/README.md index ec24332..9f74129 100644 --- a/README.md +++ b/README.md @@ -51,15 +51,21 @@ curves, and core distributions ## Installation -Install the latest *stable* version of BRCore from CRAN with: +### *Stable* version from CRAN with: ``` r install.packages("BRCore") + +# or if using with `renv`: +renv::init(bioconductor = TRUE) +renv::install("BRCore") ``` -Install the *development* version of BRCore from GitHub with: +***NOTE:*** *If using `install.packages()` in an `renv` project, `renv` +will intercept the call. Run `renv::init(bioconductor = TRUE)` first to +ensure Bioconductor dependencies can be resolved and installed.* -Install the *development* version of BRCore from GitHub with: +### *Development* version from GitHub with: ``` r # install.packages("pak") @@ -74,9 +80,6 @@ pak::pak("germs-lab/BRCore") library(BRCore) library(phyloseq) -# Load example data -data("bcse", package = "BRCore") - # Add rarefaction metrics bcse_metrics <- add_rarefaction_metrics(data = bcse) @@ -90,9 +93,10 @@ bcse_rarefied_list <- multi_rarefy( # Update phyloseq object with rarefied data bcse_rare_single <- update_otu_table( - physeq_obj = bcse, - rarefied_otus = bcse_rarefied_list, - iteration = 2) # Your preffered iteration can be used here + physeq_obj = bcse, + rarefied_otus = bcse_rarefied_list, + iteration = 2 +) # Your preffered iteration can be used here # Identify core microbiome @@ -107,12 +111,11 @@ bcse_core <- identify_core( # With multiple iterations of rarefaction bcse_core_multi <- identify_core( - physeq_obj = bcse, - rarefied_list = bcse_rarefied_list + physeq_obj = bcse, + rarefied_list = bcse_rarefied_list, priority_var = "Crop", increase_value = 0.02, depth_level = 1000, - num_iter = 10, seed = 2134 ) diff --git a/cran-comments.md b/cran-comments.md index 83ac0a7..a0ded3f 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,51 +1,34 @@ -## Resubmission notes (v2.0.4) +## v2.0.7 -This is a resubmission. Previous submissions: +### Resubmission notes -- v2.0.3: Passed auto-checks: authors found error in `scnm.fit()` and retracted by maintainer. -- v2.0.2: Passed auto-checks; requested resubmission by manual inspection -- v2.0.1: Passed auto-checks; retracted by maintainer due to typos -- v2.0.0: Rejected by CRAN auto-check service +* Fixed invalid URLs in NEWS.md for v2.0.6 CRAN submission. -**The following issues from v2.0.3 were resolved:** +### R CMD check results -1. Adding `suppressWarnings()` around `stats::dnorm()` calls in `scnm.fit()` to handle warnings previously suppressed by `options(warn=-1)` used a debugging phase. +0 errors | 0 warnings | 3 notes -2. **DOI** links in the documentation were updated to use the correct format (``). -3. Minor typos and formatting issues in the documentation were corrected. -4. Examples were unwrapped from `\dontrun` and `\donttest`. Only example for `identify_core()` remains wrapped due to long execution time (> 5s). - 6. An appropriate example for `scnm.fit()` was included. +### Fixes +* Relaxed version requirements for `phyloseq` and `stats4` to improve compatibility and avoid +CRAN error in `r-oldrel-macos-x86_64`. -### R CMD check results - -0 errors | 0 warnings | 3 notes ### Notes 1. **CRAN incoming feasibility**: - - `New submission`: Expected for new submission or re-submission. - `Running aspell failed`: The `aspell` English dictionary is unavailable in the local check environment (`/usr/lib/aspell-0.60/en_US`). This is a local environment issue and does not affect the package. -2. **Checking for future file timestamps**: Unable to verify current time. This is a - local environment issue and does not affect the package. +2. **Examples with CPU (user + system) or elapsed time > 5s** + user system elapsed + update_otu_table 5.01 0.034 5.055 3. **HTML version of manual**: `V8` package unavailable in the local check environment, skipping math rendering check. This is a local environment issue. ---- - -### win-builder notes -The win-builder (r-devel-windows-x86_64) reported errors for missing packages -(`stringi`, `jsonlite`, `xfun`, `Formula`). These are indirect dependencies of -declared imports (`phyloseq`, `Hmisc`, `knitr`) that were absent in the -win-builder guest environment. The CRAN incoming checks on both Windows and -Debian passed with only NOTEs, confirming these are not direct imports in -package code. - diff --git a/man/add_rarefaction_metrics.Rd b/man/add_rarefaction_metrics.Rd index f9c6397..16a9882 100644 --- a/man/add_rarefaction_metrics.Rd +++ b/man/add_rarefaction_metrics.Rd @@ -42,8 +42,6 @@ that appear only once. library(phyloseq) library(BRCore) -data("bcse", package = "BRCore") - # Adding metrics to a "phyloseq" object bcse_metrics <- add_rarefaction_metrics(data = bcse) sample_data(bcse_metrics)|> diff --git a/man/dot-internal_warn_sncm.Rd b/man/dot-internal_warn_sncm.Rd new file mode 100644 index 0000000..a0e246f --- /dev/null +++ b/man/dot-internal_warn_sncm.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils-internal_warn_sncm.R +\name{.internal_warn_sncm} +\alias{.internal_warn_sncm} +\title{Internal warning handler for sncm.fit likelihood functions} +\usage{ +.internal_warn_sncm(fun, message = NULL, warned = FALSE, warn_setter = NULL) +} +\arguments{ +\item{fun}{A zero-argument function (lambda) to evaluate.} + +\item{message}{A string prefix for the warning message.} + +\item{warned}{Logical flag indicating whether a warning has already fired.} + +\item{warn_setter}{A zero-argument function that sets the external \code{warned} +flag to \code{TRUE} via \verb{<<-}.} +} +\value{ +The result of \code{fun()}. +} +\description{ +Wraps a function call with a \code{withCallingHandlers()} that captures warnings +and re-emits them via \code{cli::cli_warn()}. Deduplicates repeated warnings +across optimizer iterations using an external flag and setter. +} +\keyword{internal} diff --git a/man/identify_core.Rd b/man/identify_core.Rd index 8c19819..eb20c30 100644 --- a/man/identify_core.Rd +++ b/man/identify_core.Rd @@ -125,9 +125,6 @@ and \pkg{vegan}. \donttest{ library(BRCore) -data("switchgrass", package = "BRCore") -data("bcse", package = "BRCore") - # With rarefied data res <- identify_core( physeq_obj = switchgrass, diff --git a/man/multi_rarefy.Rd b/man/multi_rarefy.Rd index 664f520..73197a1 100644 --- a/man/multi_rarefy.Rd +++ b/man/multi_rarefy.Rd @@ -43,7 +43,7 @@ specified \code{depth_level} are discarded. } \examples{ library(BRCore) -data("bcse", package = "BRCore") + # Example rarefaction (single iteration, single core to keep examples fast) otu_table_rare <- multi_rarefy( diff --git a/man/plot_rarefaction_metrics.Rd b/man/plot_rarefaction_metrics.Rd index 3658186..00b5357 100644 --- a/man/plot_rarefaction_metrics.Rd +++ b/man/plot_rarefaction_metrics.Rd @@ -22,8 +22,6 @@ Good's coverage, and outlier behavior based on a data frame or a library(phyloseq) library(BRCore) -data("bcse", package = "BRCore") - # Add rarefaction metrics to the phyloseq object bcse_metrics <- add_rarefaction_metrics(bcse) diff --git a/man/plot_variance_propagation.Rd b/man/plot_variance_propagation.Rd index 4c28ee6..62e8b17 100644 --- a/man/plot_variance_propagation.Rd +++ b/man/plot_variance_propagation.Rd @@ -41,7 +41,6 @@ This function evaluate the variance between rarefaction iterations from \code{mu library(phyloseq) library(BRCore) # Example comparing hill q=1 between Poplar and Switchgrass plots -data("bcse", package = "BRCore") bcse_filt <- bcse |> subset_samples(Crop \%in\% c("Poplar", "Switchgrass")) diff --git a/tests/testthat/setup.R b/tests/testthat/setup.R index 7d4a0c1..1153828 100644 --- a/tests/testthat/setup.R +++ b/tests/testthat/setup.R @@ -5,6 +5,16 @@ rda_path <- test_path("test_sets/test_vignette_data.rda") # Only regenerate if the .rda is missing or if running on CI is_check <- nzchar(Sys.getenv("_R_CHECK_PACKAGE_NAME_")) is_not_cran <- identical(Sys.getenv("NOT_CRAN"), "true") +is_ci <- nzchar(Sys.getenv("CI")) + +needs <- c("devtools", "phyloseq", "tidyverse", "viridis") +can_regenerate <- all(vapply( + needs, + requireNamespace, + logical(1), + quietly = TRUE +)) + # Does not regenerate on CRAN or during R CMD check, but does regenerate during devtools::test() if the .rda is missing if (is_not_cran && !is_check) { @@ -14,7 +24,7 @@ if (is_not_cran && !is_check) { } # Regenerate test data if running on CI -if (nzchar(Sys.getenv("CI"))) { +if (is_ci && can_regenerate) { rda_path <- file.path( tempdir(), test_path("test_sets/test_vignette_data.rda") diff --git a/vignettes/BRCore-vignette.R b/vignettes/BRCore-vignette.R index 97cc046..30328b6 100644 --- a/vignettes/BRCore-vignette.R +++ b/vignettes/BRCore-vignette.R @@ -1,4 +1,4 @@ -## ----chunk setup, include = FALSE----------------------------------------------------------------------------------------------------------------------- +## ----chunk setup, include = FALSE------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>", @@ -35,7 +35,7 @@ options(cli.progress_show_after = Inf) # Disable progress bar for cleaner output ## text-align: justify; ## } -## ----load libraries, echo=TRUE-------------------------------------------------------------------------------------------------------------------------- +## ----load libraries, echo=FALSE--------------------------------------------------- invisible( lapply( c("BRCore", "phyloseq", "tidyverse", "viridis"), @@ -45,12 +45,11 @@ invisible( ) -## ----load bcse, echo=TRUE------------------------------------------------------------------------------------------------------------------------------- -data("bcse", package = "BRCore") +## ----load bcse, echo=TRUE--------------------------------------------------------- str(bcse) -## ----calculate metrics, echo=TRUE----------------------------------------------------------------------------------------------------------------------- +## ----calculate metrics, echo=TRUE------------------------------------------------- bcse_metrics <- add_rarefaction_metrics(data = bcse) bcse_metrics @@ -60,7 +59,7 @@ rarefaction_plot <- plot_rarefaction_metrics(bcse_metrics) print(rarefaction_plot) -## ----rarefy bcse, echo=TRUE----------------------------------------------------------------------------------------------------------------------------- +## ----rarefy bcse, echo=TRUE------------------------------------------------------- bcse_rarefied_list <- multi_rarefy( physeq_obj = bcse, @@ -71,7 +70,7 @@ bcse_rarefied_list <- ) -## ----verify success rarefaction, echo=TRUE-------------------------------------------------------------------------------------------------------------- +## ----verify success rarefaction, echo=TRUE---------------------------------------- class(bcse_rarefied_list) str(bcse_rarefied_list[[1]], list.len = 10) # Dimensions of iteration #1 @@ -87,7 +86,7 @@ rarefaction_variance_plot <- plot_variance_propagation( print(rarefaction_variance_plot) -## ----update_otu_table, echo=TRUE------------------------------------------------------------------------------------------------------------------------ +## ----update_otu_table, echo=TRUE-------------------------------------------------- bcse_rare_single <- update_otu_table( physeq_obj = bcse, rarefied_otus = bcse_rarefied_list, @@ -95,7 +94,7 @@ bcse_rare_single <- update_otu_table( ) -## ----identify_core, echo=TRUE--------------------------------------------------------------------------------------------------------------------------- +## ----identify_core, echo=TRUE----------------------------------------------------- bcse_core_multi <- identify_core( physeq_obj = bcse, rarefied_list = bcse_rarefied_list, @@ -114,7 +113,7 @@ bcse_core_multi <- identify_core( # seed = 2134 # ) -## ----check the identified core, echo=TRUE--------------------------------------------------------------------------------------------------------------- +## ----check the identified core, echo=TRUE----------------------------------------- str(bcse_core_multi) @@ -131,7 +130,7 @@ bcse_identified_core <- plot_identified_core( print(bcse_identified_core$plot_identified_core) -## ----plot abundance occupany and increase core set, echo=TRUE------------------------------------------------------------------------------------------- +## ----plot abundance occupany and increase core set, echo=TRUE--------------------- ## ----fig4_plot_increase, echo=TRUE, fig.cap="Figure 4: Abundance-occupancy distribution for the 'bcse' dataset. The core ASV/OTUs identified by the last 2% increase method are highlighted in red."---- plot_abund_occ_increase <- plot_abundance_occupancy( @@ -162,7 +161,7 @@ plot_core_dist_bar <- plot_core_distribution( print(plot_core_dist_bar) -## ----plot_type line------------------------------------------------------------------------------------------------------------------------------------- +## ----plot_type line--------------------------------------------------------------- ## ----fig7_plot_type_line, echo=TRUE, fig.width=7, fig.height=10, fig.cap="Figure 7: Occupancy of core ASV/OTUs across the 'Crop' variable. Each point represents the average occupancy of core ASV/OTUs in samples belonging to each level of the 'Crop' variable. A line plot is better than a bar plot but still not ideal for this many variable levels."---- plot_core_dist_line <- plot_core_distribution( @@ -174,7 +173,7 @@ plot_core_dist_line <- plot_core_distribution( print(plot_core_dist_line) -## ----reorder variable levels, echo=TRUE----------------------------------------------------------------------------------------------------------------- +## ----reorder variable levels, echo=TRUE------------------------------------------- bcse_core_multi$metadata <- bcse_core_multi$metadata %>% mutate( Crop = recode( @@ -208,7 +207,7 @@ bcse_core_multi$metadata <- bcse_core_multi$metadata %>% ) -## ----plot_type heatmap---------------------------------------------------------------------------------------------------------------------------------- +## ----plot_type heatmap------------------------------------------------------------ ## ----fig8_plot_type_heatmap, echo=TRUE, fig.cap="Figure 8: Occupancy of core ASV/OTUs across the 'Crop' variable. Each cell represents the average occupancy of core ASV/OTUs in samples belonging to each level of the 'Crop' variable. A heatmap is more compact and shows well enough the average occupancy across samples in each variable level."---- plot_core_dist_heatmap <- plot_core_distribution( @@ -222,7 +221,7 @@ plot_core_dist_heatmap <- plot_core_distribution( print(plot_core_dist_heatmap) -## ----fit neutral model, echo=TRUE----------------------------------------------------------------------------------------------------------------------- +## ----fit neutral model, echo=TRUE------------------------------------------------- bcse_core_multi_neutral_fit <- fit_neutral_model( otu_table = bcse_core_multi$otu_table, core_set = bcse_core_multi$increase_core, @@ -230,7 +229,7 @@ bcse_core_multi_neutral_fit <- fit_neutral_model( ) -## ----neutral fit result, echo=TRUE---------------------------------------------------------------------------------------------------------------------- +## ----neutral fit result, echo=TRUE------------------------------------------------ str(bcse_core_multi_neutral_fit) @@ -240,7 +239,7 @@ plot_bcse_neutral_fit <- plot_neutral_model(bcse_core_multi_neutral_fit) print(plot_bcse_neutral_fit) -## ----supplemental_info, echo=TRUE----------------------------------------------------------------------------------------------------------------------- +## ----supplemental_info, echo=TRUE------------------------------------------------- bcse_core_single_iter1 <- identify_core( physeq_obj = bcse_updated_rare, priority_var = "Crop", diff --git a/vignettes/BRCore-vignette.Rmd b/vignettes/BRCore-vignette.Rmd index 0452231..aa4bf94 100644 --- a/vignettes/BRCore-vignette.Rmd +++ b/vignettes/BRCore-vignette.Rmd @@ -1,7 +1,7 @@ --- title: "Introduction to BRCore" author: "By Bolívar Aponte Rolón and Gian Maria Niccolò Benucci" -date: "Last modified: 28 April, 2026" +date: "Last modified: 18 May, 2026" output: rmarkdown::html_vignette: toc: true @@ -66,7 +66,6 @@ in contrast to the other three. ``` r -data("bcse", package = "BRCore") str(bcse) #> Formal class 'phyloseq' [package "phyloseq"] with 5 slots #> ..@ otu_table:Formal class 'otu_table' [package "phyloseq"] with 2 slots @@ -103,7 +102,7 @@ str(bcse) #> .. .. .. .. ..@ xp_list :List of 1 #> .. .. .. .. .. ..$ : #> .. .. .. .. ..@ .link_to_cached_object_list:List of 1 -#> .. .. .. .. .. ..$ : +#> .. .. .. .. .. ..$ : #> .. .. ..@ ranges :Formal class 'GroupedIRanges' [package "XVector"] with 7 slots #> .. .. .. .. ..@ group : int [1:2861] 1 1 1 1 1 1 1 1 1 1 ... #> .. .. .. .. ..@ start : int [1:2861] 106501 2501 63001 36751 501 19251 14251 37751 3751 8501 ... @@ -151,8 +150,14 @@ bcse_metrics ``` r rarefaction_plot <- plot_rarefaction_metrics(bcse_metrics) #> ℹ Processing 50 samples -#> ℹ Generating rarefaction diagnostic plots ✔ Rarefaction diagnostic plots generated successfully -#> ℹ Generating rarefaction diagnostic plots ✔ Generating rarefaction diagnostic plots [1.2s] +#> +ℹ Generating rarefaction diagnostic plots + + +✔ Rarefaction diagnostic plots generated successfully +#> ℹ Generating rarefaction diagnostic plots + +✔ Generating rarefaction diagnostic plots [1s] print(rarefaction_plot) ``` @@ -194,7 +199,7 @@ bcse_rarefied_list <- set_seed = 7642 ) #> -#> ── Rarefaction iterations starting... ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────── +#> ── Rarefaction iterations starting... ────────────────────────────────────────────── #> #> ── Input Validation ── #> @@ -274,7 +279,7 @@ rarefaction_variance_plot <- plot_variance_propagation( ) #> ✔ Input phyloseq object is valid! #> -#> ── Rarefaction Variance Propagation Visualization ──────────────────────────────────────────────────────────────────────────────────────────────────────── +#> ── Rarefaction Variance Propagation Visualization ────────────────────────────────── #> ℹ Hill number order selected, q= 0 #> ℹ Number of rarefaction iterations, n_iter= 3 #> ℹ Comparison plot generated! @@ -348,7 +353,7 @@ bcse_core_multi <- identify_core( #> ℹ Using provided `rarefied_list` (3 iterations). #> ✔ Core prioritizing variable: Crop #> ℹ Ranked by Rank only -#> ℹ Ranking OTUs based on BC dissimilarity, starting at 2026-04-28 12:10:58.310505 +#> ℹ Ranking OTUs based on BC dissimilarity, starting at 2026-05-18 15:17:06.698128 #> ✔ Elbow method identified 7 core OTUs #> ✔ % increase method identified 30 core OTUs #> ✔ Analysis complete! @@ -638,11 +643,22 @@ bcse_core_multi_neutral_fit <- fit_neutral_model( abundance_occupancy = bcse_core_multi$abundance_occupancy ) #> Waiting for profiling to be done... +#> Warning: SNCM `stats::pbeta()` produced a warning during MLE: NaNs produced +#> Warning: Binomial model `stats::dnorm()` produced a warning during MLE: NaNs +#> produced +#> Warning: Poisson model `stats::dnorm()` produced a warning during MLE: NaNs +#> produced #> ℹ Neutral model fitting: #> • Average individuals per community (N): 40276.38 #> • Binomial model using rounded N: 40276 #> • Poisson model using N: 40276.38 -#> • Maximum likelihood estimation using N: 40276.38, and starting parameters: mu = 0, sigma = 0.1 +#> • Maximum likelihood estimation using N: 40276.38, and starting parameters: mu = 0, +#> sigma = 0.1 +#> Warning: SNCM `stats::pbeta()` produced a warning during MLE: NaNs produced +#> Warning: Binomial model `stats::dnorm()` produced a warning during MLE: NaNs +#> produced +#> Warning: Poisson model `stats::dnorm()` produced a warning during MLE: NaNs +#> produced #> ✔ Model fitting complete! ``` diff --git a/vignettes/BRCore-vignette.Rmd.orig b/vignettes/BRCore-vignette.Rmd.orig index c9bf7b3..028f0dc 100644 --- a/vignettes/BRCore-vignette.Rmd.orig +++ b/vignettes/BRCore-vignette.Rmd.orig @@ -56,7 +56,7 @@ p.caption { ## Load R libraries -```{r load libraries, echo=TRUE} +```{r load libraries, echo=FALSE} invisible( lapply( c("BRCore", "phyloseq", "tidyverse", "viridis"), @@ -74,7 +74,6 @@ from @Haan2023Contrasting. Here we are going to use `bcse` since it is not raref in contrast to the other three. ```{r load bcse, echo=TRUE} -data("bcse", package = "BRCore") str(bcse) ``` diff --git a/vignettes/images/fig1_plot_metrics-1.png b/vignettes/images/fig1_plot_metrics-1.png index 95e177c..891a187 100644 Binary files a/vignettes/images/fig1_plot_metrics-1.png and b/vignettes/images/fig1_plot_metrics-1.png differ diff --git a/vignettes/images/fig2_rarefaction_variance-1.png b/vignettes/images/fig2_rarefaction_variance-1.png index 098ac22..fa4e2ee 100644 Binary files a/vignettes/images/fig2_rarefaction_variance-1.png and b/vignettes/images/fig2_rarefaction_variance-1.png differ diff --git a/vignettes/images/fig3_identified_core-1.png b/vignettes/images/fig3_identified_core-1.png index 5f48fef..573d59b 100644 Binary files a/vignettes/images/fig3_identified_core-1.png and b/vignettes/images/fig3_identified_core-1.png differ diff --git a/vignettes/images/fig4_plot_increase-1.png b/vignettes/images/fig4_plot_increase-1.png index 4f10853..57bf5cf 100644 Binary files a/vignettes/images/fig4_plot_increase-1.png and b/vignettes/images/fig4_plot_increase-1.png differ diff --git a/vignettes/images/fig5_plot_elbow-1.png b/vignettes/images/fig5_plot_elbow-1.png index d9e21c7..334886d 100644 Binary files a/vignettes/images/fig5_plot_elbow-1.png and b/vignettes/images/fig5_plot_elbow-1.png differ diff --git a/vignettes/images/fig6_plot_type_bar-1.png b/vignettes/images/fig6_plot_type_bar-1.png index 62ab77b..643a48b 100644 Binary files a/vignettes/images/fig6_plot_type_bar-1.png and b/vignettes/images/fig6_plot_type_bar-1.png differ diff --git a/vignettes/images/fig7_plot_type_line-1.png b/vignettes/images/fig7_plot_type_line-1.png index c80aba8..6f3aec8 100644 Binary files a/vignettes/images/fig7_plot_type_line-1.png and b/vignettes/images/fig7_plot_type_line-1.png differ diff --git a/vignettes/images/fig8_plot_type_heatmap-1.png b/vignettes/images/fig8_plot_type_heatmap-1.png index 2cefbc8..6bd16fd 100644 Binary files a/vignettes/images/fig8_plot_type_heatmap-1.png and b/vignettes/images/fig8_plot_type_heatmap-1.png differ diff --git a/vignettes/images/fig9_plot_neutral_fit-1.png b/vignettes/images/fig9_plot_neutral_fit-1.png index 3f87ea9..9c55e18 100644 Binary files a/vignettes/images/fig9_plot_neutral_fit-1.png and b/vignettes/images/fig9_plot_neutral_fit-1.png differ