Skip to contents

Abstract

Short answers to common questions about the input, the settings and the results of scMaSigPro, with links to the vignettes and help pages that answer them in full.

The vignettes are on the package website, https://spriyansh.github.io/scMaSigPro/articles/, and in R with browseVignettes("scMaSigPro"); every function has a help page, such as ?sc.squeeze.

Input

What does scMaSigPro need from a trajectory?

One pseudotime value and one path label per cell, and the raw counts of the cells. as_scmp() takes them as a SingleCellExperiment with two colData() columns, create_scmp() as a count matrix and a data frame. See the Trajectory input vignette and the “Input contract” section of ?assign_paths.

How do I analyse a Monocle3 trajectory?

Take the principal graph, the nearest node of each cell, the root node and the pseudotime from the cell_data_set, turn them into path labels with paths_from_graph() and assign_paths(), and pass the counts and the cell table to create_scmp(). The Trajectory input vignette has the code. Monocle3 itself is not a dependency, as it is not on CRAN or Bioconductor.

What about cells that belong to several paths?

Every cell gets one label. Cells on every path are the root, and cells on some paths are a link, labelled with the names of those paths joined by _links_; assign_paths() makes these labels from lineage weights, such as those of slingshot. Then either analyse each segment as a path of its own, or add the root and the links to the paths that share them with sc.restruct(); the Shared root vignette compares the two.

Raw or normalised counts?

Raw counts. The model is negative binomial, a distribution of counts, and the offset of each bin accounts for its sequencing depth. For values that are not counts, such as log-normalised or scaled data, use family = gaussian() with offset = FALSE in sc.p.vector().

How many cells and bins are enough?

A polynomial of degree d has d + 1 coefficients per path, so each path needs at least d + 1 bins, and a few more leave residual degrees of freedom for the test. plotBinTile() shows the number of cells per bin; bins of very few cells give noisy pseudo-bulk counts, which prune_bins removes and a lower drop_fac avoids.

The paths have different lengths. Does that matter?

Each path is binned along its own range of pseudotime, into a number of bins that depends on its number of cells, and the model compares the paths at the same binned pseudotime, the index of the bin. A path with more bins extends beyond the others; drop_trails = TRUE in sc.squeeze() cuts the longer paths to the binned pseudotime of the shortest, to compare only the stretch they share.

Settings

Which bin rule should I use?

Sturges’ rule, the default, is the rule of the analyses of the article; drop_fac below 1 gives fewer, larger bins, useful for data with many zeros, and split_bins and prune_bins even out the number of cells per bin. The Model and tuning vignette describes every rule and compares them, and ?estBinSize gives their formulas.

Which test should I use for the full model, chi-squared or F?

test = "chisq", the default and the test of maSigPro, treats the estimated dispersion as known; with few bins it calls more genes significant than its level. test = "F" accounts for the estimate and is more conservative. The Model and tuning vignette shows both.

When should I turn the offset off?

When the data are not raw counts, such as normalised or scaled values, and with any link other than the log link, which the offset needs. With raw counts keep it: it corrects for the different numbers of cells, and so depths, of the bins.

How do I fit the genes in parallel?

Pass a BiocParallel backend to sc.p.vector() and sc.t.fit(), such as BPPARAM = BiocParallel::MulticoreParam(4) on Linux and macOS or BPPARAM = BiocParallel::SnowParam(4) on any system, Windows included. The results do not depend on the backend.

Are the results reproducible?

The workflow has no random step except the k-means clustering of sc.cluster.trend(); call set.seed() before it for the same clusters. Every setting a step used is kept in the object (showParams()).

Results

No gene passes. What now?

Check the bins first: too few bins, or bins of very few cells, leave the test little to work with (plotBinTile()). Then the thresholds: p_value of sc.p.vector() is, with the default correction, a false discovery rate, and rsq of sc.filter() a threshold on the fit; scmpResults() reports both values for every gene. On raw counts, turning the offset off can also hide most genes, as the Model and tuning vignette shows.

Why do my results differ from those of version 0.0.4 or the 2024 article?

Version 0.6.0 changed how the bins are made and how the offset is computed, honours the link argument and chooses the reference path in the same way in every locale; each change is listed under “Changes affecting results” in the news. To repeat an earlier analysis exactly, install the version that made it, for example BiocManager::install("BioBam/scMaSigPro@v0.0.4").

I saved an object with an earlier version. Can I still use it?

Yes: run updateObject() on it after readRDS() or load(). The steps stop with “update it with updateObject() first” until then. See help("updateObject,ScMaSigPro-method") and the maSigPro and the ScMaSigPro class vignette.

How do I get the results into my SingleCellExperiment?

scmpToRowData(sce, scmp_ob) writes the columns of scmpResults(), with the prefix scmp_, into the rowData() of sce, matching the genes by name.

How long does an analysis take?

The fits run gene by gene, so the time grows with the number of genes and with the number of bins; the number of cells matters only for the binning. On the 100 genes and 16 bins of splat.sim the whole workflow takes well under a second. A parallel backend fits several genes at a time.

Citing scMaSigPro

citation("scMaSigPro")
#> To cite scMaSigPro in publications use:
#> 
#>   Srivastava P, Benegas Coll M, Götz S, Nueda MJ, Conesa A (2024).
#>   "scMaSigPro: differential expression analysis along single-cell
#>   trajectories." _Bioinformatics_, *40*(7), btae443.
#>   doi:10.1093/bioinformatics/btae443
#>   <https://doi.org/10.1093/bioinformatics/btae443>.
#> 
#> A BibTeX entry for LaTeX users is
#> 
#>   @Article{,
#>     title = {{scMaSigPro}: differential expression analysis along single-cell trajectories},
#>     author = {Priyansh Srivastava and Marta {Benegas Coll} and Stefan Götz and María José Nueda and Ana Conesa},
#>     journal = {Bioinformatics},
#>     year = {2024},
#>     volume = {40},
#>     number = {7},
#>     pages = {btae443},
#>     doi = {10.1093/bioinformatics/btae443},
#>   }

Session information

sessionInfo()
#> R version 4.6.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 24.04.5 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.26.so;  LAPACK version 3.12.0
#> 
#> locale:
#>  [1] LC_CTYPE=C.UTF-8       LC_NUMERIC=C           LC_TIME=C.UTF-8       
#>  [4] LC_COLLATE=C.UTF-8     LC_MONETARY=C.UTF-8    LC_MESSAGES=C.UTF-8   
#>  [7] LC_PAPER=C.UTF-8       LC_NAME=C              LC_ADDRESS=C          
#> [10] LC_TELEPHONE=C         LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C   
#> 
#> time zone: UTC
#> tzcode source: system (glibc)
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] BiocStyle_2.40.0
#> 
#> loaded via a namespace (and not attached):
#>  [1] digest_0.6.39       desc_1.4.3          R6_2.6.1           
#>  [4] bookdown_0.48       fastmap_1.2.0       xfun_0.62          
#>  [7] cachem_1.1.0        knitr_1.52          htmltools_0.5.9    
#> [10] rmarkdown_2.32      lifecycle_1.0.5     cli_3.6.6          
#> [13] sass_0.4.10         pkgdown_2.2.1       textshaping_1.0.5  
#> [16] jquerylib_0.1.4     systemfonts_1.3.2   compiler_4.6.1     
#> [19] tools_4.6.1         ragg_1.5.2          bslib_0.12.0       
#> [22] evaluate_1.0.5      yaml_2.3.12         BiocManager_1.30.27
#> [25] otel_0.2.0          jsonlite_2.0.0      rlang_1.3.0        
#> [28] fs_2.1.0