SpatialAgent_N2_DEEPAGENT / spatialagent /skill /mapping_validation.md
jkkkkyuedtrt's picture
Upload 381 files
bd52a47 verified
|
Raw
History Blame Contribute Delete
6.23 kB
# Tangram Mapping Validation
Validate and troubleshoot Tangram spatial mappings using cross-validation, diagnostic plots, and quality metrics.
## Why Validate?
- Ensure mapping is biologically meaningful
- Identify problematic genes or cell types
- Compare different mapping strategies
- Build confidence before downstream analysis
---
## Validation Approaches
1. **Training score analysis**: How well do training genes match?
2. **Test gene prediction**: Can we predict held-out genes?
3. **Cross-validation**: Systematic holdout testing
4. **Biological validation**: Do patterns match known biology?
---
## Step 1: Basic Quality Check
After running `tangram_map_cells`, check training scores:
```python
import scanpy as sc
import tangram as tg
ad_map = sc.read_h5ad("experiments/tangram_mapping.h5ad")
# Training gene scores
train_df = ad_map.uns["train_genes_df"]
print(f"Average training score: {train_df['train_score'].mean():.3f}")
print(f"Median training score: {train_df['train_score'].median():.3f}")
# Score distribution
print("\nScore distribution:")
print(train_df['train_score'].describe())
# Top and bottom genes
print("\nTop 10 genes:")
print(train_df.head(10))
print("\nBottom 10 genes:")
print(train_df.tail(10))
```
**Interpretation**:
- Average > 0.7: Good mapping
- Average 0.5-0.7: Moderate, may need tuning
- Average < 0.5: Poor, check data compatibility
---
## Step 2: Training Diagnostic Plots
**Tool**: `tangram_evaluate`
Or manually generate plots:
```python
import tangram as tg
import matplotlib.pyplot as plt
# 4-panel diagnostic plot
tg.plot_training_scores(ad_map, bins=20, alpha=0.5)
plt.savefig("training_diagnostics.png", dpi=150, bbox_inches="tight")
```
**Panels explained**:
1. **Score histogram**: Distribution of gene scores
2. **Score vs SC sparsity**: Low sparsity genes should score high
3. **Score vs SP sparsity**: Sparse spatial genes often score low
4. **Score vs sparsity diff**: Large diff = dropout mismatch
---
## Step 3: Test Gene Evaluation
Project genes and evaluate predictions:
```python
# Project genes
ad_ge = tg.project_genes(ad_map, adata_sc)
ad_ge.write_h5ad("experiments/tangram_projected.h5ad")
# Compare with spatial data
df_genes = tg.compare_spatial_geneexp(ad_ge, adata_sp, adata_sc)
# Separate training and test
train_genes = df_genes[df_genes["is_training"] == True]
test_genes = df_genes[df_genes["is_training"] == False]
print(f"Training genes: {len(train_genes)}, avg score: {train_genes['score'].mean():.3f}")
print(f"Test genes: {len(test_genes)}, avg score: {test_genes['score'].mean():.3f}")
```
---
## Step 4: AUC Evaluation
The AUC metric captures overall prediction quality:
```python
# Compute AUC
metrics, coords = tg.eval_metric(df_genes)
print(f"AUC score: {metrics['auc_score']:.3f}")
# Plot AUC curve
tg.plot_auc(df_genes)
plt.savefig("auc_curve.png", dpi=150)
```
**Interpretation**:
- AUC > 0.6: Good prediction on test genes
- AUC 0.4-0.6: Moderate
- AUC < 0.4: Poor, mapping may not generalize
---
## Step 5: Cross-Validation (Optional)
For rigorous validation, use leave-one-out or k-fold CV:
```python
# Leave-one-out CV (slow but thorough)
cv_dict = tg.cross_val(
adata_sc,
adata_sp,
cluster_label="cell_type",
mode="clusters",
cv_mode="loo", # or "10fold"
num_epochs=500,
device="cuda:0",
verbose=True,
)
print(f"CV avg train score: {cv_dict['avg_train_score']:.3f}")
print(f"CV avg test score: {cv_dict['avg_test_score']:.3f}")
```
---
## Step 6: Biological Validation
Check that mapped cell types match expected patterns:
```python
import scanpy as sc
import matplotlib.pyplot as plt
adata_sp = sc.read_h5ad("experiments/tangram_annotated.h5ad")
# Known spatial patterns to verify
# Example: T cells should be in lymphoid regions
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
cell_types = ['T cells', 'B cells', 'Macrophages',
'Epithelial', 'Fibroblasts', 'Endothelial']
for ax, ct in zip(axes.flat, cell_types):
if ct in adata_sp.obsm["tangram_ct_pred"].columns:
adata_sp.obs["_tmp"] = adata_sp.obsm["tangram_ct_pred"][ct]
sc.pl.spatial(adata_sp, color="_tmp", ax=ax, show=False, title=ct)
del adata_sp.obs["_tmp"]
plt.tight_layout()
plt.savefig("celltype_validation.png", dpi=150)
```
---
## Troubleshooting Low Scores
### Problem: Low training scores
**Causes**:
- Few shared genes between datasets
- Different normalization
- Batch effects
**Solutions**:
```python
# Check gene overlap
sc_genes = set(adata_sc.var_names.str.lower())
sp_genes = set(adata_sp.var_names.str.lower())
overlap = sc_genes & sp_genes
print(f"Shared genes: {len(overlap)}")
# Ensure same normalization
print(f"SC max: {adata_sc.X.max():.2f}")
print(f"SP max: {adata_sp.X.max():.2f}")
```
### Problem: Good training but poor test scores
**Causes**:
- Overfitting to training genes
- Training genes not representative
**Solutions**:
- Use more diverse training genes
- Increase regularization (lambda_r)
- Try `mode="clusters"` for smoother mapping
### Problem: Some cell types poorly mapped
**Causes**:
- Cell type not in spatial region
- Few marker genes for that type
**Solutions**:
- Check cell type abundance in spatial data
- Add more markers for underperforming types
---
## Comparing Mapping Strategies
Test different approaches:
```python
results = []
# Strategy 1: Cells mode
ad_map1 = tg.map_cells_to_space(adata_sc, adata_sp, mode="cells", num_epochs=500)
score1 = ad_map1.uns["train_genes_df"]["train_score"].mean()
results.append(("cells", score1))
# Strategy 2: Clusters mode
ad_map2 = tg.map_cells_to_space(adata_sc, adata_sp, mode="clusters",
cluster_label="cell_type", num_epochs=500)
score2 = ad_map2.uns["train_genes_df"]["train_score"].mean()
results.append(("clusters", score2))
# Compare
for mode, score in results:
print(f"{mode}: {score:.3f}")
```
---
## Quality Checklist
Before using mapping results:
- [ ] Average training score > 0.7
- [ ] AUC score > 0.5
- [ ] Top genes include expected markers
- [ ] Cell type patterns match known biology
- [ ] No obvious artifacts in spatial plots
- [ ] Sparsity analysis shows expected dropout pattern