OmicVerse Single-Cell scTour Trajectory
Goal
Run the sctour branch of ov.single.TrajInfer on a raw-count AnnData and capture the trainer-produced pseudotime, latent space, and vector field. Keep this separate from the lighter graph-based trajectory skill because it has a different dependency and compute profile.
Quick Workflow
- Inspect the input
AnnData and confirm raw UMI counts are available in .X.
- Preserve or restore counts into
.X before the sctour call.
- Instantiate
ov.single.TrajInfer(...) with the plotting basis, groupby, and any existing representation you want to preserve for downstream plots.
- Run
TrajInfer.inference(method='sctour', **trainer_kwargs).
- Validate that pseudotime, latent coordinates, and vector-field outputs were written.
- For lineage topology, draw the unified trajectory backbone with
ov.pl.trajectory(adata, method='sctour', ...) or overlay on a custom UMAP with ov.pl.trajectory_overlay(adata, ax=ax, method='sctour') — same visual grammar shared with the other trajectory skills (commit 4f28ab6).
- Summarize branch structure with
ov.pl.branch_streamplot(adata, group_key=..., pseudotime_key='sctour_pseudotime').
- Fit marker trends with the shared GAM stack:
ov.single.dynamic_features(adata, genes=..., pseudotime='sctour_pseudotime') → ov.pl.dynamic_trends(...); many-gene panels via ov.pl.dynamic_heatmap(...).
- Only invert or rescale pseudotime after fit when that direction change is biologically justified for the dataset.
Interface Summary
Fitting
ov.single.TrajInfer(...) is still the public entrypoint.
TrajInfer.inference(method='sctour', **kwargs) dispatches the sctour branch.
- In the current wrapper source, the branch internally calls
sct.train.Trainer(self.adata, loss_mode='nb', **kwargs).
- The wrapper then calls
tnode.train(), stores adata.obs['sctour_pseudotime'] = tnode.get_time(), stores adata.obsm['X_TNODE'] from tnode.get_latentsp(alpha_z=0.5, alpha_predz=0.5), and stores adata.obsm['X_VF'] from tnode.get_vector_field(...).
Visualisation (shared with other trajectory skills)
ov.pl.trajectory(adata, method='sctour', basis='X_umap', color=...) — unified trajectory plot.
ov.pl.trajectory_overlay(adata, ax=ax, method='sctour') — overlay backbone on existing embedding.
ov.pl.branch_streamplot(adata, group_key=..., pseudotime_key='sctour_pseudotime', show=False) — river-style view.
ov.single.dynamic_features(adata, genes=..., pseudotime='sctour_pseudotime', ...) + ov.pl.dynamic_trends(...) — per-gene GAM curves.
ov.pl.dynamic_heatmap(adata, pseudotime='sctour_pseudotime', var_names=..., ...) — many-gene panel.
Read references/source-grounding.md before adding more interface-specific detail.
Boundary
- Keep
sctour separate from the shared diffusion_map / slingshot / palantir skill.
- Do not fold preprocessing or clustering into this skill unless the real request is upstream data preparation; hand off to the preprocessing skill first.
- Do not use this skill when the user only wants DPT pseudotime, lineage curves, or Palantir fate probabilities; use the trajectory-inference skill instead.
Stage Selection
- Use this skill only when the requested branch is explicitly
method='sctour' or when the user asks for scTour latent-space or vector-field outputs.
- Keep the notebook's
alpha_recon_lec and alpha_recon_lode values as branch examples, not universal defaults.
- Treat the wrapper's fixed
loss_mode='nb' as part of the current execution path; if a different loss mode is needed, inspect the underlying sctour package before changing the workflow.
Input Contract
- Start from
AnnData.
- Ensure raw UMI counts are present in
.X for the default negative-binomial loss path.
- Preserve a plotting basis such as
X_umap only if you want to overlay sctour_pseudotime later.
- Preserve cluster annotations only if you need grouped plots or interpretation after training.
Minimal Execution Pattern
import omicverse as ov
traj = ov.single.TrajInfer(
adata,
basis="X_umap",
use_rep="X_pca",
groupby="clusters",
)
traj.inference(
method="sctour",
alpha_recon_lec=0.5,
alpha_recon_lode=0.5,
)
# Optional notebook-specific direction flip only if biologically justified.
adata.obs["sctour_pseudotime"] = 1 - adata.obs["sctour_pseudotime"]
# Unified trajectory plots
ov.pl.trajectory(adata, method="sctour", basis="X_umap", color="clusters")
fig, ax = ov.plt.subplots(figsize=(4, 4))
ov.pl.embedding(adata, basis="X_umap", color="clusters", ax=ax, show=False)
ov.pl.trajectory_overlay(adata, ax=ax, method="sctour")
# Branch streamplot + marker dynamics on sctour_pseudotime
ov.pl.branch_streamplot(
adata, group_key="clusters", pseudotime_key="sctour_pseudotime", show=False,
)
res = ov.single.dynamic_features(
adata, genes=["Pdx1", "Ins1", "Gcg"],
pseudotime="sctour_pseudotime", store_raw=True, raw_obs_keys=["clusters"],
)
ov.pl.dynamic_trends(res, genes=["Pdx1", "Ins1", "Gcg"],
add_point=True, point_color_by="clusters")
Constraints
- Keep raw counts in
.X before training; the wrapper hardcodes loss_mode='nb'.
- Treat the notebook's pseudotime inversion as optional and dataset-specific.
- This branch depends on the external
sctour package and was not fully executable in the current local environment.
- Do not promise GPU use or full-scale training unless the runtime and dependency stack are confirmed.
Validation
- Confirm
adata.obs['sctour_pseudotime'] exists after the fit.
- Confirm
adata.obsm['X_TNODE'] exists after the fit.
- Confirm
adata.obsm['X_VF'] exists after the fit.
- If you invert pseudotime, record that postprocessing step explicitly.
- If the environment cannot import
sctour, treat the branch as source-grounded but not empirically reproduced.
Resource Map
- Read
references/source-notebook-map.md to see why sctour was split out from the shared trajectory skill.
- Read
references/source-grounding.md for the current wrapper behavior and stored output keys.
- Read
references/compatibility.md for dependency and validation limitations.
1---2name: omicverse-single-cell-sctour-trajectory3description: Run the OmicVerse sctour trajectory branch on raw-count single-cell AnnData. Use when adapting the scTour part of an OmicVerse trajectory notebook, or when you need sctour pseudotime, latent space, or vector-field outputs instead of the diffusion_map, slingshot, or palantir branches.4---56# OmicVerse Single-Cell scTour Trajectory78## Goal910Run the `sctour` branch of `ov.single.TrajInfer` on a raw-count `AnnData` and capture the trainer-produced pseudotime, latent space, and vector field. Keep this separate from the lighter graph-based trajectory skill because it has a different dependency and compute profile.1112## Quick Workflow13141. Inspect the input `AnnData` and confirm raw UMI counts are available in `.X`.152. Preserve or restore counts into `.X` before the `sctour` call.163. Instantiate `ov.single.TrajInfer(...)` with the plotting `basis`, `groupby`, and any existing representation you want to preserve for downstream plots.174. Run `TrajInfer.inference(method='sctour', **trainer_kwargs)`.185. Validate that pseudotime, latent coordinates, and vector-field outputs were written.196. For lineage topology, draw the unified trajectory backbone with `ov.pl.trajectory(adata, method='sctour', ...)` or overlay on a custom UMAP with `ov.pl.trajectory_overlay(adata, ax=ax, method='sctour')` — same visual grammar shared with the other trajectory skills (commit `4f28ab6`).207. Summarize branch structure with `ov.pl.branch_streamplot(adata, group_key=..., pseudotime_key='sctour_pseudotime')`.218. Fit marker trends with the shared GAM stack: `ov.single.dynamic_features(adata, genes=..., pseudotime='sctour_pseudotime')` → `ov.pl.dynamic_trends(...)`; many-gene panels via `ov.pl.dynamic_heatmap(...)`.229. Only invert or rescale pseudotime after fit when that direction change is biologically justified for the dataset.2324## Interface Summary2526**Fitting**2728- `ov.single.TrajInfer(...)` is still the public entrypoint.29- `TrajInfer.inference(method='sctour', **kwargs)` dispatches the `sctour` branch.30- In the current wrapper source, the branch internally calls `sct.train.Trainer(self.adata, loss_mode='nb', **kwargs)`.31- The wrapper then calls `tnode.train()`, stores `adata.obs['sctour_pseudotime'] = tnode.get_time()`, stores `adata.obsm['X_TNODE']` from `tnode.get_latentsp(alpha_z=0.5, alpha_predz=0.5)`, and stores `adata.obsm['X_VF']` from `tnode.get_vector_field(...)`.3233**Visualisation (shared with other trajectory skills)**3435- `ov.pl.trajectory(adata, method='sctour', basis='X_umap', color=...)` — unified trajectory plot.36- `ov.pl.trajectory_overlay(adata, ax=ax, method='sctour')` — overlay backbone on existing embedding.37- `ov.pl.branch_streamplot(adata, group_key=..., pseudotime_key='sctour_pseudotime', show=False)` — river-style view.38- `ov.single.dynamic_features(adata, genes=..., pseudotime='sctour_pseudotime', ...)` + `ov.pl.dynamic_trends(...)` — per-gene GAM curves.39- `ov.pl.dynamic_heatmap(adata, pseudotime='sctour_pseudotime', var_names=..., ...)` — many-gene panel.4041Read `references/source-grounding.md` before adding more interface-specific detail.4243## Boundary4445- Keep `sctour` separate from the shared `diffusion_map` / `slingshot` / `palantir` skill.46- Do not fold preprocessing or clustering into this skill unless the real request is upstream data preparation; hand off to the preprocessing skill first.47- Do not use this skill when the user only wants DPT pseudotime, lineage curves, or Palantir fate probabilities; use the trajectory-inference skill instead.4849## Stage Selection5051- Use this skill only when the requested branch is explicitly `method='sctour'` or when the user asks for scTour latent-space or vector-field outputs.52- Keep the notebook's `alpha_recon_lec` and `alpha_recon_lode` values as branch examples, not universal defaults.53- Treat the wrapper's fixed `loss_mode='nb'` as part of the current execution path; if a different loss mode is needed, inspect the underlying `sctour` package before changing the workflow.5455## Input Contract5657- Start from `AnnData`.58- Ensure raw UMI counts are present in `.X` for the default negative-binomial loss path.59- Preserve a plotting basis such as `X_umap` only if you want to overlay `sctour_pseudotime` later.60- Preserve cluster annotations only if you need grouped plots or interpretation after training.6162## Minimal Execution Pattern6364```python65import omicverse as ov6667traj = ov.single.TrajInfer(68 adata,69 basis="X_umap",70 use_rep="X_pca",71 groupby="clusters",72)73traj.inference(74 method="sctour",75 alpha_recon_lec=0.5,76 alpha_recon_lode=0.5,77)7879# Optional notebook-specific direction flip only if biologically justified.80adata.obs["sctour_pseudotime"] = 1 - adata.obs["sctour_pseudotime"]8182# Unified trajectory plots83ov.pl.trajectory(adata, method="sctour", basis="X_umap", color="clusters")8485fig, ax = ov.plt.subplots(figsize=(4, 4))86ov.pl.embedding(adata, basis="X_umap", color="clusters", ax=ax, show=False)87ov.pl.trajectory_overlay(adata, ax=ax, method="sctour")8889# Branch streamplot + marker dynamics on sctour_pseudotime90ov.pl.branch_streamplot(91 adata, group_key="clusters", pseudotime_key="sctour_pseudotime", show=False,92)93res = ov.single.dynamic_features(94 adata, genes=["Pdx1", "Ins1", "Gcg"],95 pseudotime="sctour_pseudotime", store_raw=True, raw_obs_keys=["clusters"],96)97ov.pl.dynamic_trends(res, genes=["Pdx1", "Ins1", "Gcg"],98 add_point=True, point_color_by="clusters")99```100101## Constraints102103- Keep raw counts in `.X` before training; the wrapper hardcodes `loss_mode='nb'`.104- Treat the notebook's pseudotime inversion as optional and dataset-specific.105- This branch depends on the external `sctour` package and was not fully executable in the current local environment.106- Do not promise GPU use or full-scale training unless the runtime and dependency stack are confirmed.107108## Validation109110- Confirm `adata.obs['sctour_pseudotime']` exists after the fit.111- Confirm `adata.obsm['X_TNODE']` exists after the fit.112- Confirm `adata.obsm['X_VF']` exists after the fit.113- If you invert pseudotime, record that postprocessing step explicitly.114- If the environment cannot import `sctour`, treat the branch as source-grounded but not empirically reproduced.115116## Resource Map117118- Read `references/source-notebook-map.md` to see why `sctour` was split out from the shared trajectory skill.119- Read `references/source-grounding.md` for the current wrapper behavior and stored output keys.120- Read `references/compatibility.md` for dependency and validation limitations.