bio-spatial-transcriptomics-spatial-deconvolution
Estimate cell type composition in spatial transcriptomics spots using reference-based deconvolution. Use cell2location, RCTD, SPOTlight, or Tangram to infer cell type proportions from scRNA-seq references. Use when estimating cell type composition in spatial spots.
What this skill does
## Version Compatibility
Reference examples tested with: anndata 0.10+, matplotlib 3.8+, numpy 1.26+, pandas 2.2+, scanpy 1.10+
Before using code patterns, verify installed versions match. If versions differ:
- Python: `pip show <package>` then `help(module.function)` to check signatures
If code throws ImportError, AttributeError, or TypeError, introspect the installed
package and adapt the example to match the actual API rather than retrying.
# Spatial Deconvolution
Estimate cell type composition in spatial spots using scRNA-seq references.
## Required Imports
```python
import scanpy as sc
import anndata as ad
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
```
## Overview
Deconvolution estimates cell type proportions in each spatial spot using a reference single-cell dataset. Essential for Visium data where spots contain multiple cells.
## Using cell2location
**Goal:** Estimate cell type abundances per spatial spot using a probabilistic model trained on scRNA-seq reference signatures.
**Approach:** Train a regression model on reference scRNA-seq to extract cell type signatures, then decompose spatial spots using those signatures.
**"Deconvolve my Visium spots into cell types"** -> Train a reference signature model on scRNA-seq, then map cell type abundances to spatial locations using cell2location.
```python
import cell2location
from cell2location.utils.filtering import filter_genes
from cell2location.models import RegressionModel
# Load reference scRNA-seq
adata_ref = sc.read_h5ad('reference_scrna.h5ad')
adata_ref.obs['cell_type'] = adata_ref.obs['cell_type'].astype('category')
# Load spatial data
adata_vis = sc.read_h5ad('spatial_data.h5ad')
# Find shared genes
intersect = np.intersect1d(adata_vis.var_names, adata_ref.var_names)
adata_ref = adata_ref[:, intersect].copy()
adata_vis = adata_vis[:, intersect].copy()
```
## Train Reference Signature Model
**Goal:** Learn cell type gene expression signatures from annotated single-cell reference data.
**Approach:** Filter genes, set up a regression model on the scRNA-seq reference, train it, and export per-cell-type mean expression signatures.
```python
# Select genes for deconvolution
selected = filter_genes(adata_ref, cell_count_cutoff=5, cell_percentage_cutoff2=0.03,
nonz_mean_cutoff=1.12)
adata_ref = adata_ref[:, selected].copy()
# Prepare reference
cell2location.models.RegressionModel.setup_anndata(
adata_ref,
labels_key='cell_type',
)
# Train reference model
mod = RegressionModel(adata_ref)
mod.train(max_epochs=250, use_gpu=True)
# Export reference signatures
adata_ref = mod.export_posterior(adata_ref, sample_kwargs={'num_samples': 1000})
ref_sig = adata_ref.varm['means_per_cluster_mu_fg']
```
## Run Spatial Deconvolution
**Goal:** Decompose each spatial spot into cell type abundances using trained reference signatures.
**Approach:** Set up the Cell2location model with reference signatures and expected cells per spot, then train on the spatial data.
```python
# Ensure spatial data has same genes
adata_vis = adata_vis[:, adata_ref.var_names].copy()
# Setup spatial data
cell2location.models.Cell2location.setup_anndata(adata_vis)
# Train deconvolution model
mod_spatial = cell2location.models.Cell2location(
adata_vis,
cell_state_df=ref_sig,
N_cells_per_location=10, # Expected cells per spot
detection_alpha=20,
)
mod_spatial.train(max_epochs=30000, use_gpu=True)
# Export results
adata_vis = mod_spatial.export_posterior(adata_vis, sample_kwargs={'num_samples': 1000})
```
## Access Deconvolution Results
```python
# Cell type abundances stored in obsm
abundances = adata_vis.obsm['q05_cell_abundance_w_sf']
print(f'Cell types: {abundances.shape[1]}')
# Convert to proportions
proportions = abundances / abundances.sum(axis=1, keepdims=True)
adata_vis.obsm['cell_type_proportions'] = proportions
# Add dominant cell type
cell_types = adata_ref.obs['cell_type'].cat.categories
adata_vis.obs['dominant_cell_type'] = cell_types[proportions.argmax(axis=1)]
```
## Using Tangram (Alternative)
**Goal:** Map single-cell reference data to spatial locations using optimal transport.
**Approach:** Find marker genes from the reference, align single cells to spatial spots using Tangram's mapping algorithm, then project cell type annotations.
```python
import tangram as tg
# Load data
adata_sc = sc.read_h5ad('reference_scrna.h5ad')
adata_sp = sc.read_h5ad('spatial_data.h5ad')
# Preprocess
sc.pp.normalize_total(adata_sc)
sc.pp.log1p(adata_sc)
# Find marker genes
sc.tl.rank_genes_groups(adata_sc, groupby='cell_type', method='wilcoxon')
markers = sc.get.rank_genes_groups_df(adata_sc, group=None)
markers = markers[markers['pvals_adj'] < 0.01].groupby('group').head(100)
marker_genes = markers['names'].unique().tolist()
# Prepare for Tangram
tg.pp_adatas(adata_sc, adata_sp, genes=marker_genes)
# Map single cells to spatial locations
ad_map = tg.map_cells_to_space(
adata_sc,
adata_sp,
mode='clusters',
cluster_label='cell_type',
device='cuda:0',
)
# Get cell type proportions
tg.project_cell_annotations(ad_map, adata_sp, annotation='cell_type')
# Results in adata_sp.obsm['tangram_ct_pred']
```
## Using RCTD (via R)
```python
# RCTD runs in R; use rpy2 for integration
import rpy2.robjects as ro
from rpy2.robjects import pandas2ri
pandas2ri.activate()
# Save data for R
adata_vis.write_h5ad('spatial_for_rctd.h5ad')
adata_ref.write_h5ad('reference_for_rctd.h5ad')
# R code for RCTD
r_code = '''
library(spacexr)
library(Seurat)
# Load data (convert from h5ad first)
# ... R-specific loading code ...
# Create RCTD object
rctd <- create.RCTD(puck, reference, max_cores=4)
rctd <- run_RCTD(rctd, doublet_mode='full')
# Get results
results <- rctd@results
weights <- normalize_weights(results$weights)
'''
```
## Visualize Cell Type Proportions
**Goal:** Display estimated cell type abundances as spatial heatmaps across the tissue.
**Approach:** Plot each cell type's proportion as a separate spatial panel using Scanpy's spatial plot.
```python
# Plot cell type abundances spatially
cell_types_to_plot = ['T_cell', 'Macrophage', 'Epithelial', 'Fibroblast']
fig, axes = plt.subplots(2, 2, figsize=(12, 12))
for ax, ct in zip(axes.flatten(), cell_types_to_plot):
ct_idx = list(adata_ref.obs['cell_type'].cat.categories).index(ct)
adata_vis.obs[f'{ct}_proportion'] = proportions[:, ct_idx]
sc.pl.spatial(adata_vis, color=f'{ct}_proportion', ax=ax, show=False,
title=ct, cmap='Reds', vmin=0, vmax=1)
plt.tight_layout()
plt.savefig('cell_type_proportions.png', dpi=150)
```
## Pie Chart Per Spot (Advanced)
```python
from matplotlib.patches import Wedge
def plot_pie_spatial(adata, proportions, cell_types, spot_size=0.5):
fig, ax = plt.subplots(figsize=(12, 12))
colors = plt.cm.tab20(np.linspace(0, 1, len(cell_types)))
coords = adata.obsm['spatial']
for i in range(adata.n_obs):
x, y = coords[i]
props = proportions[i]
start_angle = 0
for j, prop in enumerate(props):
if prop > 0.01: # Skip tiny proportions
wedge = Wedge((x, y), spot_size * 50, start_angle,
start_angle + prop * 360, color=colors[j])
ax.add_patch(wedge)
start_angle += prop * 360
ax.set_xlim(coords[:, 0].min() - 100, coords[:, 0].max() + 100)
ax.set_ylim(coords[:, 1].min() - 100, coords[:, 1].max() + 100)
ax.set_aspect('equal')
ax.invert_yaxis()
# Legend
handles = [plt.Rectangle((0, 0), 1, 1, color=colors[i]) for i in range(len(cell_types))]
ax.legend(handles, cell_types, loc='upper right')
plt.savefig('pie_chart_spatial.png', dpi=150)
```
## Evaluate Deconvolution Quality
**Goal:** Validate deconvolution results by correlating estimated proportions with known marker gene expression.
**Approach:** For each cell type, compute correlation between its estimaRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.