• Preface
    • 0.1 Mainline Map
    • 0.2 How This Book Is Organized
    • 0.3 Reading Paths
    • 0.4 Example Conventions
  • I How sclet Thinks: State, Provenance, and Navigation
  • 1 State-Aware Analysis Contract
    • 1.1 What is the State Contract?
    • 1.2 Macro View: Status()
    • 1.3 Digging Deeper: get_analysis_context()
    • 1.4 Named State Records and Typed Accessors
    • 1.5 Memory Safety and Sparse Data
    • 1.6 Manual Overrides: Layers and Default APIs
  • 2 Automation & Provenance Logs
    • 2.1 The One-Liner Pipeline
    • 2.2 The Provenance Log (CommandLog)
    • 2.3 Writing Methods for You: PipelineSummary
  • II From Data to Discovery: Analysis Mainlines
  • 3 Data Ingress and Object Interoperability
    • 3.1 Seurat and SCE Conversion
    • 3.2 AnnData (h5ad)
  • 4 Recommended usage
    • 4.1 For end users
    • 4.2 For pipeline authors
  • 5 Developer design notes
    • 5.1 Core object contract
    • 5.2 How to add a new analysis function
    • 5.3 Implementation rules for contributors
    • 5.4 What should be tested
  • 6 Core Single-Cell Workflow
    • 6.1 Read 10X data
    • 6.2 QC
    • 6.3 Ambient RNA and doublet cleanup
    • 6.4 Variable features
    • 6.5 Zero-preserving imputation
    • 6.6 Dimensional reduction
    • 6.7 Clustering
    • 6.8 UMAP
    • 6.9 Find Markers
      • 6.9.1 Marker gene information
    • 6.10 Cell cluster annotation
    • 6.11 Automatic Annotation (SingleR)
  • 7 Integration and Batch Correction
    • 7.1 Load datasets
    • 7.2 Preprocess
    • 7.3 Integration Workflow
    • 7.4 Clustering
    • 7.5 Visualization
    • 7.6 Pseudobulk Differential Expression
    • 7.7 Running scVI on a GPU
      • 7.7.1 The default is CPU
      • 7.7.2 Asking for the card
      • 7.7.3 What it costs the first time
      • 7.7.4 Check before you commit to a long run
  • 8 Cell Identity and Reference Mapping
    • 8.1 Manual annotation
    • 8.2 Automatic annotation
    • 8.3 Reference mapping mainline workflow
      • 8.3.1 Lightweight Reference Mapping (KNN)
      • 8.3.2 Run SingleR with sclet
      • 8.3.3 Reference mapping workflow
      • 8.3.4 Symphony Atlas Mapping
      • 8.3.5 State-aware SingleR provenance
      • 8.3.6 Annotate with SingleR result
      • 8.3.7 Comparison with manual annotation result
  • 9 Cell Fate and Dynamic Processes
    • 9.1 Trajectory mainline workflow
      • 9.1.1 Lineage plot
      • 9.1.2 Pseudotime plot
      • 9.1.3 Expression trends in different cell trajectories
      • 9.1.4 Heatmap
    • 9.2 Diffusion Map for complex trajectories
      • 9.2.1 Example data
      • 9.2.2 Run velocity analysis
      • 9.2.3 Visualize velocity-based trajectory
    • 9.3 CellRank: Advanced Fate Mapping
      • 9.3.1 Run CellRank
    • 9.4 Already have RegVelo results? Wiring them into CellRank
    • 9.5 Workflow shell for velocity and fate
    • 9.6 Is it real or a smoke screen? Diagnosing the velocity-fate chain
      • 9.6.1 Reading the CellRank summary
      • 9.6.2 Does velocity actually explain fate?
      • 9.6.3 Auditing the whole chain in one place
    • 9.7 Velocity Latent Time
  • 10 Program, Regulon, and Mechanistic Interpretation
    • 10.1 Gene set scoring and pathway activity
    • 10.2 Multi-Backend Scoring in One Click
    • 10.3 Program mainline workflow
    • 10.4 Reading and Visualizing Results
    • 10.5 Advanced Pathway Discovery (altExp and RunKEGG)
    • 10.6 SCENIC regulon inference
    • 10.7 Environment and Data Preparation
    • 10.8 One-Click Inference and Scoring
    • 10.9 Result Retrieval and State Awareness
    • 10.10 Visualizing Regulon Activity
    • 10.11 Unified GRN Entry: RunGRN()
    • 10.12 Unified Program Access: get_program() / has_program()
    • 10.13 Program Activity Dotplot: plot_program_dotplot()
  • 11 Differential Analysis and Functional Interpretation
    • 11.1 Differential expression and pseudobulk testing
    • 11.2 Standard Single-Cell DE
      • 11.2.1 The “What does this gene even do?” Problem
    • 11.3 The Gold Standard: Pseudobulk Analysis
      • 11.3.1 Step 1: Aggregate Expression
      • 11.3.2 Step 2: Pseudobulk DE with DESeq2
    • 11.4 Functional enrichment on top of differential results
    • 11.5 GO Enrichment
    • 11.6 KEGG Enrichment
  • 12 Cell-Cell Communication and Microenvironment Interaction
    • 12.1 Input
    • 12.2 Running CCI
    • 12.3 Using Alternative Backends (CellPhoneDB & NicheNet)
      • 12.3.1 CellPhoneDB
      • 12.3.2 NicheNet
    • 12.4 Visualization
  • 13 An explicit id: the auto-generated visualization collides with the
  • 14 Enhanced Visualization chapter.
    • 14.0.1 Legacy CellChat Visualization
  • 15 State Priority and Perturbation Sensitivity
    • 15.1 Perturbation Priority
      • 15.1.1 What the object has to satisfy
      • 15.1.2 The direct call
      • 15.1.3 Reading the result back
    • 15.2 Rare Cell Detection
    • 15.3 The Workflow Shell
    • 15.4 The AI Layer: run_rare_cell_detection
      • 15.4.1 The ordering rule that costs a run to learn
      • 15.4.2 Why the whole thing is not executed through a plan
    • 15.5 What Fits Nearby
    • 15.6 Current Recommendation
    • 15.7 What Is Not Here Yet
  • 16 Spatial Context and Niche Analysis
    • 16.1 Spatial Mainline Workflow
    • 16.2 High-Resolution Spatial Deconvolution: Cell2location
    • 16.3 Spatial Colocalization with SVP
    • 16.4 Spatial Niche Detection with SVP LISA
    • 16.5 Inspecting Spatial Results Across Layers
    • 16.6 In-Silico Gene Perturbation: CellOracle
  • 17 Multimodal Expansion
    • 17.1 The Two States: Attached and Registered
    • 17.2 Detecting and Registering
    • 17.3 One-Step Registration
    • 17.4 The AI Layer
    • 17.5 What Is Not Here Yet
    • 17.6 What to Do Today
  • III Specialized Techniques and Reference
  • 18 Enhanced Visualization
    • 18.1 Loading data
    • 18.2 Dimensionality Reduction Plots
      • 18.2.1 CellDimPlot
      • 18.2.2 FeatureDimPlot
    • 18.3 Expression Heatmaps
    • 18.4 Cell Statistics
    • 18.5 Module-Specific Visualization
      • 18.5.1 Trajectory and Fate
      • 18.5.2 Program and Regulon Activity
      • 18.5.3 Perturbation Priority
      • 18.5.4 Spatial Analysis
      • 18.5.5 Cell-Cell Communication
      • 18.5.6 Reference Mapping
  • 19 An explicit id: the auto-generated reference-mapping collides with the
  • 20 Cell Identity and Reference Mapping chapter.
  • 21 Metacells with SuperCell
    • 21.1 RunSuperCell
    • 21.2 Estimate SuperCell Purity
  • 22 Milo: Differential Abundance
    • 22.1 Requirements
    • 22.2 Two-group DA (GLM)
    • 22.3 Multi-contrast testing
    • 22.4 GLMM (random intercept)
    • 22.5 Refit after dropping separated neighbourhoods
  • 23 Phenotype Association
    • 23.1 A practical pattern
    • 23.2 What gets recorded
  • 24 Interactive Data Exploration
    • 24.1 Launch Explorer
    • 24.2 Customization
  • 25 SVP: Gene Set Activity in Spatial and Single-Cell Data
    • 25.1 runSGSA
    • 25.2 runLISA
    • 25.3 runLOCALBV
  • IV AI-Assisted Analysis
  • 26 AI in One Call
    • 26.1 What you need first
    • 26.2 The one call
      • 26.2.1 What came back, and what it means
    • 26.3 What just happened
    • 26.4 The three other calls you will meet
      • 26.4.1 Ask it something, without running anything
      • 26.4.2 The same run with the switches visible
      • 26.4.3 Read a finished round back
    • 26.5 When it refuses
    • 26.6 What to read next
  • 27 AI Foundations: State, Actions, and the Ledger
    • 27.1 The problem: a script is a decision you cannot re-examine
    • 27.2 The AIAction contract
    • 27.3 The registry only exposes what this object can actually run
    • 27.4 The ledger is the only authority
  • 28 Driving sclet from an External Agent
    • 28.1 Read the skills first
    • 28.2 A complete run
      • 28.2.1 1. What can run on this object?
      • 28.2.2 2. Read the ledger, and bind the plan to it
      • 28.2.3 3. Write the plan
      • 28.2.4 4. Validate — and read the errors
      • 28.2.5 5. Dry-run, then execute
      • 28.2.6 6. Read what the ledger now says
    • 28.3 Advancing in rounds
    • 28.4 What you can do that a model cannot
    • 28.5 The plan you ran is a graph, and it outlives the session
    • 28.6 Resuming across processes
    • 28.7 Things not to attempt
  • 29 The In-Package Assistant
    • 29.1 Requirements
    • 29.2 An object to ask about
    • 29.3 AIPlanAnalysis: ask for a plan
      • 29.3.1 The registry has to match the goal
    • 29.4 RunAIAnalysis: plan, preview, ask, execute in one call
    • 29.5 Free-form questions with sclet_copilot
    • 29.6 Cross-chain auditing
    • 29.7 A plan does not replace the workflow functions
    • 29.8 What the planner can and cannot see
    • 29.9 What the package will not do
  • 30 Evidence Governance: Claims, Results, and Reports
    • 30.1 Evidence nodes
    • 30.2 The claim ceiling
    • 30.3 What may leave the object: the privacy line
    • 30.4 Recording results
    • 30.5 RenderAIReport: the report checks itself
    • 30.6 The failure this whole layer is against
  • References

sclet: A State-Aware Single-Cell and Spatial Transcriptomics Toolkit

4 Recommended usage

sclet is still centered on SingleCellExperiment. The recommended way to use the package is to treat the SCE object as the single source of truth, and then apply sclet analysis functions on top for common analysis steps.

4.1 For end users

The shortest recommended workflow is to use the standard pipeline entry point:

library(sclet)

# Run the full standard pipeline
sce <- RunStandardPipeline(sce)

# Print a structured summary of the analysis steps
PipelineSummary(sce)

Under the hood, RunStandardPipeline sequentially calls:

sce <- NormalizeData(sce)
sce <- FindVariableFeatures(sce)
sce <- ScaleData(sce)
sce <- RunPCA(sce)
sce <- FindNeighbors(sce)
sce <- FindClusters(sce)
sce <- RunUMAP(sce)

If scrapper is installed, FindVariableFeatures(sce, method = "scrapper") is also supported as an optional HVG backend. sclet still writes the result back into the same HVG state and rowData, so downstream code continues to use VariableFeatures() in the usual way.

Because scrapper is an optional dependency, users need to install it explicitly if they want this backend instead of the default scran path.

In current sclet, user-facing analysis verbs are standardized on the Run* style. Use RunPCA(), RunMilo(), and RunCellChat() as the recommended public API.

The other important convention is that sclet now distinguishes between:

  • a physical assay, which is where the matrix is actually stored in the SCE object
  • a logical layer, which is the user-facing expression view that downstream analysis functions consume

For example, after normalization and scaling, a typical object may expose:

  • counts
  • logcounts
  • scaled

and DefaultLayer(object) tells you which one is currently recommended for downstream use.

For interactive exploration, it is better to rely on the state-aware accessors instead of reaching directly into object internals:

  • DefaultAssay(), DefaultLayer(), DefaultReduction(), DefaultGraph(), and ActiveIdent() expose the current active view.
  • Layers() and LayerData() expose the available expression layers and their matrices.
  • CommandLog() shows which analysis functions have been applied.
  • PipelineSummary() gives a clear textual report of the executed pipeline steps.
  • Status() gives a quick user-facing snapshot of the current object state.
  • get_hvg(), get_graph(), get_milo(), get_trajectory(), get_cellchat(), get_integration(), get_annotation(), and get_mapping() expose structured analysis records.
  • get_analysis_context() gives a lightweight summary of the current active view plus the active integration/annotation/mapping and other analysis records.
  • has_*() helpers are the preferred way to check whether an analysis result is available.

You can also use the integrated plotting functions that automatically consume the active state:

# Plot the active dimensional reduction colored by active identity
CellDimPlot(sce)

# Plot feature expression on the active dimensional reduction
FeatureDimPlot(sce, features = c("GeneA", "GeneB"))

# Plot a grouped heatmap of features across cell identities
GroupHeatmap(sce, features = c("GeneA", "GeneB", "GeneC"))

# Plot cell statistics (e.g., proportion of clusters across conditions)
CellStatPlot(sce, split.by = "Condition")

sclet supports robust annotation and reference mapping:

# Full annotation via SingleR
sce <- RunSingleR(sce, ref = ref_dataset, labels = ref_dataset$CellType)

# Lightweight label transfer via KNN in shared feature space
sce <- RunKNNPredict(sce, ref = ref_dataset, labels = "CellType", k = 5)

# Visualize query and reference cells in the same reduction space
ProjectionPlot(query = sce, ref = ref_dataset, reduction = "UMAP")

This means the recommended mental model is simple: keep one SCE object, run the sclet analysis functions in sequence, and inspect state through the exported accessors instead of through ad hoc metadata fields.

In practical terms:

  • use RunPCA(layer = "scaled") if you want PCA to be built explicitly from the scaled layer
  • use FindMarkers() without an explicit assay/layer if you want it to follow the current layer logic, with safe fallback away from scaled
  • use RunSingleR() and RunCellChat() without manual matrix extraction when the current DefaultLayer() already reflects the desired biological view
  • after BatchRemover(), use get_integration() and DefaultLayer() to understand which corrected view is currently active
  • after RunSingleR(), use get_annotation() to inspect the annotation record, and get_mapping() to inspect the corresponding reference-mapping record
  • use Status() when you want the shortest high-level snapshot of the current object state before drilling into specific accessors
  • use get_analysis_context() when you want one compact snapshot of the current layer/reduction/graph/ident combination together with the active analysis records
  • after RunSuperCell(), use get_supercell() to inspect the returned metacell object’s aggregation record and parent-child provenance
  • after RunCellChat(), use get_cellchat() to inspect the active communication record, or pass id = ... when you keep multiple CellChat runs
  • after RunMilo(), use get_milo() to inspect the active DA record, or pass id = ... when you keep multiple Milo runs

When analysis is performed on top of a corrected layer, downstream states now carry that provenance forward. In other words, PCA, graph construction, clustering, and UMAP can all record that they depend on the active integration state rather than behaving like disconnected one-off steps.

For multi-sample workflows, the provenance chain can now start even earlier: sce_merge() stores a merged_inputs integration record, and the subsequent BatchRemover() state can point back to that merge step.

4.2 For pipeline authors

If you are writing a reusable script or package around sclet, prefer patterns that are stable under future extension:

  • Pass the SCE object through each step and return the updated object explicitly.
  • Prefer exported entry points such as RunPCA() and RunUMAP() over calling lower-level functions directly when sclet already provides them.
  • Read results through accessors (get_*, has_*, Default*, ActiveIdent, Layers, LayerData) instead of assuming a fixed metadata layout.
  • If old metadata still needs to be read while migrating historical objects, keep that logic centralized in shared internal helpers instead of re-implementing direct metadata(...) reads in multiple accessors.
  • When using RunCellChat(), request return = "sce" or return = "both" if downstream code needs the updated SCE with recorded analysis state.
  • When a module can produce multiple records of the same type, give each run a stable name and read it back through get_* (id = ...) instead of assuming only one result exists.