Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Single-cell clustering (Leiden, Louvain, scICE, GMM), batch correction (Harmony, scVI, BBKNN, Combat), topic modeling, and cNMF in OmicVerse.
.claude/skills/itamarzand88-single-cell-clustering-and-batch-correction-with-omicverse/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 30% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 23% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 16% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 42% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 14% | 0% |
<!-- source: omicverse-single-cell-clustering — https://raw.githubusercontent.com/omicverse/omicverse/master/.claude/skills/single-clustering/SKILL.md -->
This skill distills the single-cell tutorials t_cluster.ipynb and t_single_batch.ipynb. Use it when a user wants to preprocess an AnnData object, explore clustering alternatives (Leiden, Louvain, scICE, GMM, topic/cNMF models), and evaluate or harmonise batches with omicverse utilities.
omicverse as ov, scanpy as sc, and plotting helpers (scvelo as scv when using dentate gyrus demo data).ov.plot_set() or ov.utils.ov_plot_set() so figures adopt omicverse styling before embedding plots.scv.datasets.dentategyrus(); for integration, read provided .h5ad files via ov.read() and set adata.obs['batch'] identifiers for each cohort.adata.X = adata.X.astype(np.int64) when required for QC steps.ov.pp.qc(adata, tresh={'mito_perc': 0.2, 'nUMIs': 500, 'detected_genes': 250}, batch_key='batch') to drop low-quality cells and inspect summary statistics per batch.adata.write_h5ad(...)) so users can resume from clean checkpoints.ov.pp.preprocess(adata, mode='shiftlog|pearson', n_HVGs=3000, batch_key=None) to normalise, log-transform, and flag highly variable genes; assign adata.raw = adata and subset to adata.var.highly_variable_features for downstream modelling.ov.pp.scale(adata)) and compute PCA scores with ov.pp.pca(adata, layer='scaled', n_pcs=50). Encourage reviewing variance explained via ov.utils.plot_pca_variance_ratio(adata).sc.pp.neighbors(adata, n_neighbors=15, n_pcs=50, use_rep='scaled|original|X_pca') or ov.pp.neighbors(...).ov.utils.cluster(adata, method='leiden'|'louvain', resolution=1), ov.single.leiden(adata, resolution=1.0), or ov.pp.leiden(adata, resolution=1); remind users that resolution tunes granularity.python # Before clustering: check neighbors graph exists if 'neighbors' not in adata.uns: if 'X_pca' in adata.obsm: ov.pp.neighbors(adata, n_neighbors=15, use_rep='X_pca') else: raise ValueError("PCA must be computed before neighbors graph")
# Before plotting by cluster: check clustering was performed if 'leiden' not in adata.obs: ov.single.leiden(adata, resolution=1.0)
ov.pl.embedding(adata, basis='X_umap', color=['clusters','leiden'], frameon='small', wspace=0.5) and confirm cluster separation. Always check that columns in color= parameter exist in adata.obs before plotting.model = ov.utils.cluster(adata, method='scICE', use_rep='scaled|original|X_pca', resolution_range=(4,20), n_boot=50, n_steps=11) and inspect stability via model.plot_ic(figsize=(6,4)) before selecting model.best_k groups.ov.utils.cluster(..., method='GMM', n_components=21, covariance_type='full', tol=1e-9, max_iter=1000) for model-based assignments.LDA_obj = ov.utils.LDA_topic(...), review LDA_obj.plot_topic_contributions(6), derive cluster calls with LDA_obj.predicted(k) and optionally refine using LDA_obj.get_results_rfc(...).cnmf_obj = ov.single.cNMF(... components=np.arange(5,11), n_iter=20, num_highvar_genes=2000, output_dir=...), factorise (factorize, combine), select K via k_selection_plot, and propagate usage scores back with cnmf_obj.get_results(...) and cnmf_obj.get_results_rfc(...).adjusted_rand_score(adata.obs['clusters'], adata.obs['leiden']) and report metrics for each method (Leiden, Louvain, GMM, LDA variants, cNMF models) to justify chosen parameters.ov.utils.mde(...) to create MDE projections from different latent spaces (adata.obsm["scaled|original|X_pca"], harmonised embeddings, topic compositions) and plot via ov.pl.embedding(..., color=['batch','cell_type']) or ov.pl.embedding for consistent review of cluster/batch mixing.ov.single.batch_correction(adata, batch_key='batch', methods='harmony'|'combat'|'scanorama'|'scVI'|'CellANOVA', n_pcs=50, ...) sequentially to generate harmonised embeddings stored in adata.obsm (X_harmony, X_combat, X_scanorama, X_scVI, X_cellanova). For scVI, mention latent size (n_latent=30) and gene_likelihood="nb"; for CellANOVA define control pools via control_dict.ov.utils.mde and visualise batch vs cell_type to check mixing and conservation.adata.write_h5ad('neurips2021_batch_all.h5ad', compression='gzip')) and reload when necessary.scib_metrics.benchmark.Benchmarker with embeddings list (["X_pca", "X_combat", "X_harmony", "X_cellanova", "X_scanorama", "X_mira_topic", "X_mira_feature", "X_scVI"]) to compute batch-vs-biology trade-offs via bm.benchmark() and summarise with bm.plot_results_table(min_max_scale=False).adata.raw captures the unscaled log-normalised matrix before subsetting to HVGs.use_rep='scaled|original|X_pca' strings exist in adata.obsm prior to clustering; rerun preprocessing if missing.n_iter, components, or latent dimensions for smaller datasets.'neighbors' in adata.unsadata.obsclusters."batch and cell_type, and benchmark the embeddings."t_cluster.ipynbt_single_batch.ipynbreference.md| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 17,669 | 15,663 | -11% | 1 | 1 | 0% | 4,652 | 6,069 | +30% | 0 | 0 | — |
case-02 | fail→pass | 19,260 | 13,168 | -32% | 1 | 1 | 0% | 4,654 | 5,712 | +23% | 0 | 0 | — |
case-03 | fail→pass | 18,902 | 11,335 | -40% | 1 | 1 | 0% | 4,525 | 5,239 | +16% | 0 | 0 | — |
case-04 | fail→pass | 8,112 | 3,407 | -58% | 1 | 1 | 0% | 2,071 | 2,948 | +42% | 0 | 0 | — |
case-05 | fail→pass | 10,995 | 4,095 | -63% | 1 | 1 | 0% | 2,729 | 3,104 | +14% | 0 | 0 | — |
case-06 | fail→pass | 6,934 | 2,322 | -67% | 1 | 1 | 0% | 1,579 | 2,717 | +72% | 0 | 0 | — |
case-07 | pass→pass | 7,095 | 4,081 | -42% | 1 | 1 | 0% | 1,589 | 3,105 | +95% | 0 | 0 | — |
case-08 | fail→pass | 10,846 | 6,418 | -41% | 1 | 1 | 0% | 2,607 | 3,666 | +41% | 0 | 0 | — |
case-09 | fail→pass | 10,564 | 5,596 | -47% | 1 | 1 | 0% | 2,385 | 3,435 | +44% | 0 | 0 | — |
case-10 | fail→pass | 11,863 | 5,692 | -52% | 1 | 1 | 0% | 2,664 | 3,461 | +30% | 0 | 0 | — |
case-11 | pass→pass | 11,141 | 3,687 | -67% | 1 | 1 | 0% | 2,224 | 2,974 | +34% | 0 | 0 | — |
case-12 | fail→pass | 10,278 | 5,509 | -46% | 1 | 1 | 0% | 2,208 | 3,327 | +51% | 0 | 0 | — |
case-21 | fail→fail | 13,404 | 13,212 | -1% | 1 | 1 | 0% | 2,971 | 4,993 | +68% | 0 | 0 | — |
case-13 | pass→pass | 6,295 | 5,597 | -11% | 1 | 1 | 0% | 1,374 | 3,537 | +157% | 0 | 0 | — |
case-14 | pass→pass | 9,972 | 7,949 | -20% | 1 | 1 | 0% | 2,297 | 4,146 | +80% | 0 | 0 | — |
case-15 | pass→pass | 9,974 | 5,677 | -43% | 1 | 1 | 0% | 2,455 | 3,635 | +48% | 0 | 0 | — |
case-16 | pass→pass | 5,827 | 2,599 | -55% | 1 | 1 | 0% | 1,375 | 2,737 | +99% | 0 | 0 | — |
case-17 | pass→pass | 9,096 | 1,752 | -81% | 1 | 1 | 0% | 1,784 | 2,520 | +41% | 0 | 0 | — |
case-18 | pass→pass | 2,492 | 2,172 | -13% | 1 | 1 | 0% | 508 | 2,608 | +413% | 0 | 0 | — |
case-19 | fail→pass | 7,954 | 3,799 | -52% | 1 | 1 | 0% | 1,739 | 3,014 | +73% | 0 | 0 | — |
case-20 | pass→pass | 8,258 | 4,201 | -49% | 1 | 1 | 0% | 2,062 | 3,141 | +52% | 0 | 0 | — |
case-22 | fail→fail | 13,702 | 13,360 | -2% | 1 | 1 | 0% | 2,911 | 5,057 | +74% | 0 | 0 | — |
case-23 | fail→fail | 9,731 | 11,119 | +14% | 1 | 1 | 0% | 2,625 | 4,979 | +90% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +48 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.