# An introduction to BASiCStan

# Outline

This package implements alternative inference methods for BASiCS. The original package uses adaptive Metropolis within Gibbs sampling, while BASiCStan uses Stan to enable the use of maximum a posteriori estimation, variational inference, and Hamiltonian Monte Carlo. These each have advantages for different use cases.

# Use

To use `BASiCStan`, we can first use `BASICS_MockSCE()` to generate an toy example dataset. We will also set a seed for reproducibility.

    suppressPackageStartupMessages(library("BASiCStan"))
    set.seed(42)
    sce <- BASiCS_MockSCE()

The interface for running MCMC using BASiCS and using alternative inference methods using Stan is very similar. It is worth noting that the joint prior between mean and over-dispersion parameters, corresponding to `Regression = TRUE`, is the only supported mode in `BASiCStan()`.

    amwg_fit <- BASiCS_MCMC(
        sce,
        N = 200,
        Thin = 10,
        Burn = 100,
        Regression = TRUE
    )
    #> altExp 'spike-ins' is assumed to contain spike-in genes.
    #> see help(altExp) for details.
    #> Running with spikes BASiCS sampler (regression case) ...
    #> -------------------------------------------------------------
    #> MCMC running time
    #> -------------------------------------------------------------
    #> user: 0.275
    #> system: 0.001
    #> elapsed: 0.276
    #> -------------------------------------------------------------
    #> Output
    #> -------------------------------------------------------------
    #> -------------------------------------------------------------
    #> BASiCS version 2.25.0 :
    #> vertical integration (spikes case)
    #> -------------------------------------------------------------
    stan_fit <- BASiCStan(sce, Method = "sampling", iter = 10)
    #> Warning in .local(x, ...): 'normalizeCounts' is deprecated.
    #> Use 'scrapper::normalizeCounts' instead.
    #> See help("Deprecated")
    #> Warning: There were 5 divergent transitions after warmup. See
    #> https://mc-stan.org/misc/warnings.html#divergent-transitions-after-warmup
    #> to find out why this is a problem and how to eliminate them.
    #> Warning: Examine the pairs() plot to diagnose sampling problems

The output of `BASiCStan()` is an object of class `BASiCS_Chain`, similar to the output of `BASiCS_MCMC()`. Therefore, you could use these as you would an object generated using Metropolis within Gibbs sampling. For example, we can plot the relationship between mean and over-dispersion estimated using the joint regression prior:

    BASiCS_ShowFit(amwg_fit)

    BASiCS_ShowFit(stan_fit)

# Stan MCMC diagnostics

Using Stan has advantages outside of the variety of inference engines available. By returning a Stan object that we can later convert to a `BASiCS_Chain` object, we can leverage an even broader set of functionality. For example, Stan has the ability to easily generate MCMC diagnostics using simple functions. For example, `summary()` outputs a number of useful per-chain and across-chain diagnostics:

    stan_obj <- BASiCStan(sce, ReturnBASiCS = FALSE, Method = "sampling", iter = 10)
    #> Warning in .local(x, ...): 'normalizeCounts' is deprecated.
    #> Use 'scrapper::normalizeCounts' instead.
    #> See help("Deprecated")
    #>
    #> SAMPLING FOR MODEL 'basics_regression' NOW (CHAIN 1).
    #> Chain 1:
    #> Chain 1: Gradient evaluation took 0.002012 seconds
    #> Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 20.12 seconds.
    #> Chain 1: Adjust your expectations accordingly!
    #> Chain 1:
    #> Chain 1:
    #> Chain 1: WARNING: No variance estimation is
    #> Chain 1:          performed for num_warmup < 20
    #> Chain 1:
    #> Chain 1: Iteration: 1 / 10 [ 10%]  (Warmup)
    #> Chain 1: Iteration: 2 / 10 [ 20%]  (Warmup)
    #> Chain 1: Iteration: 3 / 10 [ 30%]  (Warmup)
    #> Chain 1: Iteration: 4 / 10 [ 40%]  (Warmup)
    #> Chain 1: Iteration: 5 / 10 [ 50%]  (Warmup)
    #> Chain 1: Iteration: 6 / 10 [ 60%]  (Sampling)
    #> Chain 1: Iteration: 7 / 10 [ 70%]  (Sampling)
    #> Chain 1: Iteration: 8 / 10 [ 80%]  (Sampling)
    #> Chain 1: Iteration: 9 / 10 [ 90%]  (Sampling)
    #> Chain 1: Iteration: 10 / 10 [100%]  (Sampling)
    #> Chain 1:
    #> Chain 1:  Elapsed Time: 0.032 seconds (Warm-up)
    #> Chain 1:                0.019 seconds (Sampling)
    #> Chain 1:                0.051 seconds (Total)
    #> Chain 1:
    #> Warning: There were 5 divergent transitions after warmup. See
    #> https://mc-stan.org/misc/warnings.html#divergent-transitions-after-warmup
    #> to find out why this is a problem and how to eliminate them.
    #> Warning: Examine the pairs() plot to diagnose sampling problems
    head(summary(stan_obj)$summary)
    #>               mean se_mean sd     2.5%      25%      50%      75%    97.5%
    #> log_mu[1] 3.098420     NaN  0 3.098420 3.098420 3.098420 3.098420 3.098420
    #> log_mu[2] 1.058489     NaN  0 1.058489 1.058489 1.058489 1.058489 1.058489
    #> log_mu[3] 2.107672     NaN  0 2.107672 2.107672 2.107672 2.107672 2.107672
    #> log_mu[4] 2.245089     NaN  0 2.245089 2.245089 2.245089 2.245089 2.245089
    #> log_mu[5] 2.002693     NaN  0 2.002693 2.002693 2.002693 2.002693 2.002693
    #> log_mu[6] 1.457520     NaN  0 1.457520 1.457520 1.457520 1.457520 1.457520
    #>           n_eff Rhat
    #> log_mu[1]   NaN  NaN
    #> log_mu[2]   NaN  NaN
    #> log_mu[3]   NaN  NaN
    #> log_mu[4]   NaN  NaN
    #> log_mu[5]   NaN  NaN
    #> log_mu[6]   NaN  NaN

We can then convert this object to a `BASiCS_Chain` and carry on a workflow as before:

    Stan2BASiCS(stan_obj)
    #> An object of class BASiCS_Chain
    #>  5 MCMC samples.
    #>  Dataset contains 100 biological genes and 100 cells (2 batches).
    #>  Object stored using BASiCS version:  2.25.0
    #>  Parameters:  mu delta s nu theta epsilon phi beta

# Session info

    sessionInfo()
    #> R version 4.6.1 (2026-06-24)
    #> Platform: x86_64-pc-linux-gnu
    #> Running under: Ubuntu 26.04 LTS
    #>
    #> Matrix products: default
    #> BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
    #> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.32.so;  LAPACK version 3.12.0
    #>
    #> locale:
    #>  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C
    #>  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8
    #>  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8
    #>  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C
    #>  [9] LC_ADDRESS=C               LC_TELEPHONE=C
    #> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
    #>
    #> time zone: Etc/UTC
    #> tzcode source: system (glibc)
    #>
    #> attached base packages:
    #> [1] stats4    stats     graphics  grDevices utils     datasets  methods
    #> [8] base
    #>
    #> other attached packages:
    #>  [1] BASiCStan_1.15.1            rstan_2.32.7
    #>  [3] StanHeaders_2.32.10         BASiCS_2.25.0
    #>  [5] SingleCellExperiment_1.35.1 SummarizedExperiment_1.43.0
    #>  [7] Biobase_2.73.1              GenomicRanges_1.65.0
    #>  [9] Seqinfo_1.3.0               IRanges_2.47.2
    #> [11] S4Vectors_0.51.5            BiocGenerics_0.59.8
    #> [13] generics_0.1.4              MatrixGenerics_1.25.0
    #> [15] matrixStats_1.5.0           rmarkdown_2.31
    #>
    #> loaded via a namespace (and not attached):
    #>  [1] gridExtra_2.3.1           inline_0.3.21
    #>  [3] rlang_1.2.0               magrittr_2.0.5
    #>  [5] otel_0.2.0                compiler_4.6.1
    #>  [7] DelayedMatrixStats_1.35.0 loo_2.10.0
    #>  [9] vctrs_0.7.3               pkgconfig_2.0.3
    #> [11] fastmap_1.2.0             backports_1.5.1
    #> [13] XVector_0.53.0            labeling_0.4.3
    #> [15] scuttle_1.23.1            promises_1.5.0
    #> [17] xfun_0.59                 bluster_1.23.0
    #> [19] cachem_1.1.0              beachmat_2.29.0
    #> [21] jsonlite_2.0.0            later_1.4.8
    #> [23] DelayedArray_0.39.3       BiocParallel_1.47.0
    #> [25] irlba_2.3.7               parallel_4.6.1
    #> [27] cluster_2.1.8.2           R6_2.6.1
    #> [29] bslib_0.11.0              RColorBrewer_1.1-3
    #> [31] limma_3.69.2              jquerylib_0.1.4
    #> [33] Rcpp_1.1.1-1.1            assertthat_0.2.1
    #> [35] knitr_1.51                splines_4.6.1
    #> [37] httpuv_1.6.17             Matrix_1.7-5
    #> [39] igraph_2.3.3              abind_1.4-8
    #> [41] yaml_2.3.12               viridis_0.6.5
    #> [43] codetools_0.2-20          miniUI_0.1.2
    #> [45] curl_7.1.0                pkgbuild_1.4.8
    #> [47] lattice_0.22-9            tibble_3.3.1
    #> [49] withr_3.0.3               shiny_1.14.0
    #> [51] S7_0.2.2                  posterior_1.7.0
    #> [53] coda_0.19-4.1             evaluate_1.0.5
    #> [55] RcppParallel_5.1.11-2     pillar_1.11.1
    #> [57] tensorA_0.36.2.1          checkmate_2.3.4
    #> [59] distributional_0.8.1      ggplot2_4.0.3
    #> [61] sparseMatrixStats_1.25.0  rstantools_2.6.0
    #> [63] scales_1.4.0              xtable_1.8-8
    #> [65] glue_1.8.1                metapod_1.21.0
    #> [67] maketools_1.3.2           tools_4.6.1
    #> [69] hexbin_1.28.5             BiocNeighbors_2.7.2
    #> [71] sys_3.4.3                 ScaledMatrix_1.21.0
    #> [73] locfit_1.5-9.12           buildtools_1.0.0
    #> [75] scran_1.41.1              cowplot_1.2.0
    #> [77] grid_4.6.1                QuickJSR_1.10.0
    #> [79] edgeR_4.11.4              BiocSingular_1.29.0
    #> [81] cli_3.6.6                 rsvd_1.0.5
    #> [83] S4Arrays_1.13.0           viridisLite_0.4.3
    #> [85] V8_8.2.0                  glmGamPoi_1.25.1
    #> [87] gtable_0.3.6              sass_0.4.10
    #> [89] digest_0.6.39             SparseArray_1.13.2
    #> [91] dqrng_0.4.1               farver_2.1.2
    #> [93] htmltools_0.5.9           lifecycle_1.0.5
    #> [95] statmod_1.5.2             mime_0.13
    #> [97] ggExtra_0.11.0            MASS_7.3-65