spatial-condition
Compare experimental conditions in spatial transcriptomics data using pseudobulk differential expression with method-aware PyDESeq2 or Wilcoxon testing and explicit replicate handling.
SKILL.mdSkills/spatial/spatial-condition/SKILL.md
GitHub⚖️ Spatial Condition
You are Spatial Condition, the condition-comparison skill for OmicsClaw. Your role is to compare treatment groups, disease states, or experimental conditions in spatial transcriptomics data using replicate-aware pseudobulk statistics rather than spot-level pseudoreplication.
Why This Exists
- Without it: users often compare conditions with cell/spot-level Wilcoxon tests, which inflates significance by treating technical observations as independent biological replicates.
- With it: OmicsClaw aggregates counts to sample-level pseudobulk profiles
and applies either a proper negative-binomial GLM (
pydeseq2) or an explicit Wilcoxon fallback. - Why OmicsClaw: it standardizes design-column validation, replicate checks, method-specific tuning hints, and reproducible outputs across spatial condition-comparison workflows.
Core Capabilities
- Pseudobulk aggregation: sums raw counts per sample x cluster.
- PyDESeq2 (default): negative-binomial GLM on pseudobulk counts using official PyDESeq2 controls.
- Wilcoxon fallback: pseudobulk rank-sum testing on log-CPM transformed profiles for lower-replicate or fallback scenarios.
- Per-cluster contrasts: runs condition comparisons within each cluster to find context-specific responses.
- Replicate-aware filtering: skips contrasts that do not satisfy the configured sample-count threshold.
- Standard Python gallery: emits a recipe-driven condition-comparison
gallery with overview, diagnostic, supporting, and uncertainty panels backed
by the shared
skills/spatial/_lib/vizlayer. - Figure-ready exports: writes
figure_data/CSVs plus a gallery manifest so downstream tools can restyle the same analysis without recomputing DE. - Structured outputs: exports global DE table, per-cluster contrast summaries, skipped-contrast reasons, figures, and reproducibility commands.
Input Formats
| Format | Extension | Required Fields | Example |
|---|---|---|---|
| AnnData (preprocessed) | .h5ad |
layers["counts"] or raw, obs[condition_key], obs[sample_key] |
multi_sample.h5ad |
| Demo | n/a | --demo flag |
Runs spatial-preprocess demo then injects synthetic conditions / replicate IDs |
Input Matrix Convention
This skill has a multi-step pipeline with different statistical assumptions:
| Component | Input Matrix | Rationale |
|---|---|---|
| Pseudobulk aggregation | adata.layers["counts"] (raw) |
Sum aggregation requires raw integer-like counts; summing log values is invalid |
| PyDESeq2 | pseudobulk raw integer counts | PyDESeq2 models counts with a negative-binomial GLM |
| Wilcoxon | pseudobulk raw counts internally transformed to CPM/log-space | OmicsClaw computes the transformation inside the wrapper before rank testing |
Core principle: pseudobulk always starts from raw counts, then the DE method operates on the aggregated matrix.
Data layout requirement:
adata.layers["counts"] = adata.X.copy() # before normalize_total + log1p
adata.X = lognorm_expr # after normalize_total + log1p
adata.obs["condition"] = condition_labels # e.g. "treated" / "control"
adata.obs["sample_id"] = sample_labels # biological replicate IDs
If layers["counts"] is missing, OmicsClaw falls back to adata.raw or
adata.X with a warning.
Workflow
- Validate: check condition / sample columns and verify each sample maps to exactly one condition.
- Aggregate: create pseudobulk matrices per sample x cluster from raw counts.
- Filter: drop low-count genes and skip contrasts with too few biological replicates.
- Test:
pydeseq2: fit NB GLM per cluster/contrastwilcoxon: run rank-sum test on transformed pseudobulk profiles
- Render the standard gallery: build the OmicsClaw narrative gallery with design-context, diagnostic burden, supporting summaries, and uncertainty panels.
- Export figure-ready data: write
figure_data/*.csvandfigure_data/manifest.jsonfor downstream customization. - Report and export: write
report.md,result.json,processed.h5ad, figures, tables, and reproducibility helpers.
Visualization Contract
OmicsClaw treats spatial-condition visualization as a two-layer system:
- Python standard gallery: the canonical result layer. This is the default output users should inspect first.
- R customization layer: an optional styling and publication layer that
reads
figure_data/and does not recompute pseudobulk DE.
The standard gallery is declared as a recipe instead of hard-coded if/else
plot branches. Current gallery roles include:
overview: condition labels on tissue and a global pseudobulk volcanodiagnostic: cluster-level DE burden projected onto spatial and UMAP viewssupporting: per-contrast significant-gene counts and per-cluster burdenuncertainty: adjusted p-value distributions, sample support, and skipped-contrast summaries when applicable
CLI Reference
# PyDESeq2 default run
oc run spatial-condition \
--input <data.h5ad> --output <dir> \
--condition-key condition --sample-key sample_id
# PyDESeq2 with explicit cluster labels and tuning
oc run spatial-condition \
--input <data.h5ad> --method pydeseq2 \
--condition-key condition --sample-key sample_id --cluster-key leiden \
--reference-condition control \
--min-counts-per-gene 10 --min-samples-per-condition 2 \
--pydeseq2-fit-type parametric \
--pydeseq2-size-factors-fit-type ratio \
--pydeseq2-alpha 0.05 --pydeseq2-n-cpus 1 \
--output <dir>
# Wilcoxon fallback mode
oc run spatial-condition \
--input <data.h5ad> --method wilcoxon \
--condition-key condition --sample-key sample_id \
--reference-condition control \
--wilcoxon-alternative two-sided \
--output <dir>
# Demo mode
oc run spatial-condition --demo --output /tmp/cond_demo
# Direct script entrypoint
python skills/spatial/spatial-condition/spatial_condition.py \
--input <data.h5ad> --method pydeseq2 --output <dir>
Every successful standard OmicsClaw wrapper run, including oc run and
conversational skill execution, also writes a top-level README.md and
reproducibility/analysis_notebook.ipynb to make the output directory easier
to inspect and rerun.
Example Queries
- "Compare healthy vs disease slices with pseudobulk statistics"
- "Find treatment-responsive genes per spatial cluster"
- "Run a Wilcoxon fallback because I only have two replicates per condition"
Algorithm / Methodology
PyDESeq2 (default)
- Input: pseudobulk raw integer counts built from sample x cluster aggregation
- Design: OmicsClaw fits
~ conditionusing officialDeseqDataSet(...)controls - Testing: OmicsClaw uses
DeseqStats(...)with explicitcontrast=["condition", other, reference] - Outputs: reports
base_mean,log2fc,stat,pvalue, and adjustedpvalue_adj
Core tuning flags:
--reference-condition: defines the sign direction of the contrast--cluster-key: chooses the cluster partition for per-cluster pseudobulk--min-counts-per-gene: wrapper-level gene filter before DE testing--min-samples-per-condition: wrapper-level replicate gate--pydeseq2-fit-type: official PyDESeq2 dispersion fit mode--pydeseq2-size-factors-fit-type: official normalization size-factor mode--pydeseq2-refit-cooks: whether Cook's outlier refitting is enabled--pydeseq2-alpha: official target FDR used byDeseqStats--pydeseq2-cooks-filter: whether Cook's filtering is applied in result extraction--pydeseq2-independent-filter: whether independent filtering is applied in result extraction--pydeseq2-n-cpus: CPU count passed to PyDESeq2
Wilcoxon
- Input: pseudobulk raw counts
- Transformation: OmicsClaw computes CPM/log-transformed profiles inside the wrapper
- Testing:
scipy.stats.ranksums()is used on per-gene transformed values - Outputs: reports a pseudobulk-derived
log2fc, Wilcoxon statistic, rawpvalue, and BH-adjustedpvalue_adj
Core tuning flags:
--reference-condition: defines the sign direction of the contrast--cluster-key: chooses the cluster partition for per-cluster pseudobulk--min-counts-per-gene: wrapper-level gene filter before DE testing--min-samples-per-condition: minimum replicate count before a contrast is attempted--wilcoxon-alternative: official SciPy alternative hypothesis
Output Structure
output_directory/
├── README.md
├── report.md
├── result.json
├── processed.h5ad
├── figures/
│ ├── condition_spatial_context.png
│ ├── pseudobulk_volcano.png
│ ├── condition_effect_burden_spatial.png
│ ├── condition_effect_burden_umap.png
│ ├── condition_de_barplot.png
│ ├── cluster_de_burden.png
│ ├── condition_pvalue_distribution.png
│ ├── sample_counts_by_condition.png
│ └── manifest.json
├── figure_data/
│ ├── pseudobulk_de.csv
│ ├── pseudobulk_volcano_points.csv
│ ├── per_cluster_summary.csv
│ ├── skipped_contrasts.csv
│ ├── cluster_de_metrics.csv
│ ├── top_de_genes.csv
│ ├── sample_counts_by_condition.csv
│ ├── condition_run_summary.csv
│ ├── condition_spatial_points.csv
│ ├── condition_umap_points.csv # when UMAP is available
│ └── manifest.json
├── tables/
│ ├── pseudobulk_de.csv
│ ├── per_cluster_summary.csv
│ └── skipped_contrasts.csv
└── reproducibility/
├── analysis_notebook.ipynb
├── commands.sh
├── requirements.txt
└── r_visualization.sh
README.md and reproducibility/analysis_notebook.ipynb are generated by the
standard OmicsClaw wrapper. Direct script execution usually produces the
skill-native outputs plus reproducibility/commands.sh.
The bundled optional R templates live under:
skills/spatial/spatial-condition/r_visualization/
├── README.md
└── condition_publication_template.R
Dependencies
Required:
scanpyscipy
Optional:
pydeseq2for proper negative-binomial GLM inference
Optional (R):
ggplot2
Safety
- Local-first: all processing remains local.
- No pseudoreplication: do not interpret spot-level observations as biological replicates.
- Reference transparency: always state which condition is the reference before interpreting log2 fold changes.
- Replicate caution: fewer than 3 samples per condition is workable but materially less stable.
Integration with Orchestrator
Trigger conditions:
- condition comparison
- pseudobulk
- PyDESeq2 / DESeq2
- treatment vs control
Chaining partners:
spatial-preprocessfor counts preservation and baseline clusteringspatial-enrichmentfor pathway analysis on DE genesspatial-genesfor comparing treatment-responsive genes to SVG programs