agentsclimarketplace

Clinical modeling workflows

Skill Pavel-Kravchenko/Bioinformatics/Skills/clinical-modeling-workflows

208 bioinformatics skills for Claude Code — NGS, single-cell, metagenomics, structural biology, algorithms, AI for science

Install
npx -y skills add Pavel-Kravchenko/Bioinformatics --skill clinical-modeling-workflows

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Classify variants via ACMG/AMP + CADD/REVEL/SpliceAI; dock ligands with AutoDock Vina; set up GROMACS MD; run Scanpy scRNA-seq QC/clustering. Use for variant classification, docking, MD setup, or scRNA-seq.

SKILL.md

11.7 KB, as published. Nobody here has run it

Clinical Modeling Workflows

When to Use

  • Classifying germline/somatic variants for clinical reporting under ACMG/AMP guidelines
  • Deciding whether an in silico predictor score (CADD, REVEL, SpliceAI, AlphaMissense) counts as PP3/BP4 evidence
  • Virtual screening or pose scoring with AutoDock Vina
  • Setting up or troubleshooting a GROMACS MD simulation (solvation, equilibration, production)
  • Single-cell RNA-seq QC, clustering, and cell-type annotation with Scanpy/AnnData

Version Compatibility

  • Python ≥3.10, scanpy ≥1.10, anndata ≥0.10
  • AutoDock Vina ≥1.2 (new scoring function; Vina 1.1 syntax differs slightly)
  • GROMACS ≥2023
  • ACMG/AMP rules per Richards et al. 2015 (Table 5); thresholds below reflect commonly used defaults, not a single canonical cutoff

Prerequisites

  • pip install scanpy pandas numpy requests (requests only needed for live ClinVar/NCBI queries)
  • AutoDock Vina + MGLTools (prepare_receptor4.py, prepare_ligand4.py) or Meeko for PDBQT prep
  • GROMACS built with the force field you intend to use (e.g. AMBER99SB-ILDN)
  • Familiarity with VCF/variant annotation (see bio-applied-variant-calling-and-snp-analysis) and PDB structure files (see bio-applied-structural-methods)

ACMG/AMP Variant Classification

Pathogenic (P) > Likely Pathogenic (LP) > VUS > Likely Benign (LB) > Benign (B)

StrengthPathogenic codesKey triggers
Very StrongPVS1Null variant (nonsense/frameshift/splice) in a LoF-mechanism disease gene
StrongPS1-PS4Same AA change as established pathogenic; confirmed de novo; damaging functional assay; prevalence in affected >> controls
ModeratePM1-PM6Mutational hotspot; absent from population databases; in-frame indel; assumed de novo; novel missense at a known pathogenic residue
SupportingPP1-PP5Co-segregation with disease; PP3 computational evidence; phenotype specific for the gene
Stand-alone benignBA1MAF > 5% in any general population
Strong benignBS1-BS4Frequency greater than expected for disorder; observed in healthy adult; benign functional study; lack of segregation
Supporting benignBP1-BP7Missense in gene where only truncating cause disease; in silico benign (BP4); synonymous with no predicted splice effect (BP7)

In Silico Predictors (for PP3 / BP4)

ToolRangeDamaging threshold
SIFT0-1 (lower = damaging)< 0.05
PolyPhen-20-1 (higher = damaging)> 0.908 probably damaging; > 0.446 possibly damaging
CADD (Phred)higher = worse≥ 20 (top 1%); ≥ 25 (top 0.3%)
REVEL0-1> 0.75 likely pathogenic
AlphaMissense0-1> 0.564 likely pathogenic; < 0.34 likely benign
SpliceAI (delta score)0-1> 0.2 suggestive; > 0.5 high confidence

Per current ClinGen SVI recommendations, require concordance across multiple orthogonal tools (not a single one) before applying PP3/BP4 — a common convention is ≥4 of 5 tools agreeing.

gnomAD constraint: pLI > 0.9 = haploinsufficient/LoF-intolerant; LOEUF < 0.35 = strong LoF constraint; missense o/e < 0.5 = missense-constrained. ClinVar review status: **** expert panel/practice guideline, *** multiple submitters no conflicts, * single submitter.

Goal: turn a list of ACMG criteria codes into a final classification. Approach: count codes by strength/direction, then apply the Richards 2015 Table 5 combining rules (benign rules checked first since BA1 short-circuits everything else).

from collections import Counter

CRITERIA_STRENGTH = {
    'PVS1': 'very_strong',
    'PS1': 'strong', 'PS2': 'strong', 'PS3': 'strong', 'PS4': 'strong',
    'PM1': 'moderate', 'PM2': 'moderate', 'PM3': 'moderate',
    'PM4': 'moderate', 'PM5': 'moderate', 'PM6': 'moderate',
    'PP1': 'supporting', 'PP2': 'supporting', 'PP3': 'supporting',
    'PP4': 'supporting', 'PP5': 'supporting',
    'BA1': 'stand_alone',
    'BS1': 'strong', 'BS2': 'strong', 'BS3': 'strong', 'BS4': 'strong',
    'BP1': 'supporting', 'BP2': 'supporting', 'BP3': 'supporting',
    'BP4': 'supporting', 'BP5': 'supporting', 'BP6': 'supporting', 'BP7': 'supporting',
}


def classify_variant(criteria: list[str]) -> str:
    """Classify a variant from ACMG/AMP criteria codes (Richards et al. 2015, Table 5).

    Args:
        criteria: e.g. ['PVS1', 'PM2', 'PP3']
    Returns:
        One of 'Pathogenic', 'Likely Pathogenic', 'VUS', 'Likely Benign', 'Benign'.
    """
    path = [c for c in criteria if c.startswith(('PVS', 'PS', 'PM', 'PP'))]
    benign = [c for c in criteria if c.startswith(('BA', 'BS', 'BP'))]
    strength = Counter(CRITERIA_STRENGTH.get(c) for c in path)
    bstrength = Counter(CRITERIA_STRENGTH.get(c) for c in benign)
    pvs, ps, pm, pp = (strength[s] for s in ('very_strong', 'strong', 'moderate', 'supporting'))
    ba, bs, bp = bstrength['stand_alone'], bstrength['strong'], bstrength['supporting']

    if ba >= 1 or bs >= 2:
        return 'Benign'
    if (bs >= 1 and bp >= 1) or bp >= 2:
        return 'Likely Benign'

    if pvs >= 1 and (ps >= 1 or pm >= 2 or (pm >= 1 and pp >= 1) or pp >= 2):
        return 'Pathogenic'
    if ps >= 2:
        return 'Pathogenic'
    if ps >= 1 and (pm >= 3 or (pm >= 2 and pp >= 2) or (pm >= 1 and pp >= 4)):
        return 'Pathogenic'

    if pvs >= 1 and pm >= 1:
        return 'Likely Pathogenic'
    if ps >= 1 and 1 <= pm <= 2:
        return 'Likely Pathogenic'
    if ps >= 1 and pp >= 2:
        return 'Likely Pathogenic'
    if pm >= 3 or (pm >= 2 and pp >= 2) or (pm >= 1 and pp >= 4):
        return 'Likely Pathogenic'
    if pvs >= 1:  # pragmatic convention (e.g. InterVar); not stated verbatim in Table 5
        return 'Likely Pathogenic'

    return 'VUS'


assert classify_variant(['PVS1', 'PM2']) == 'Likely Pathogenic'
assert classify_variant(['PVS1', 'PS1']) == 'Pathogenic'
assert classify_variant(['BA1']) == 'Benign'
assert classify_variant(['PM2', 'PP3']) == 'VUS'

Molecular Docking (AutoDock Vina)

prepare_receptor4.py -r protein.pdb -o receptor.pdbqt
prepare_ligand4.py -l ligand.mol2 -o ligand.pdbqt
vina --receptor receptor.pdbqt --ligand ligand.pdbqt \
     --config config.txt --out output.pdbqt
# config.txt: center_x/y/z, size_x/y/z define the search box (Å)
# Scores in kcal/mol -- more negative = stronger predicted binding

Force field energy: E_total = E_bond + E_angle + E_dihedral + E_electrostatic + E_vdW. Common FFs: AMBER (proteins/nucleic acids), CHARMM (proteins/lipids), OPLS-AA (small organics) — never mix parameters across FFs.

Goal: parse a Vina log/output table into a DataFrame for ranking and plotting. Approach: split the fixed-width text block, coerce columns, then sort by affinity.

import pandas as pd


def parse_vina_output(text: str) -> pd.DataFrame:
    """Parse AutoDock Vina docking output into a DataFrame.

    Args:
        text: raw stdout/log from `vina`, containing the 'mode | affinity | rmsd' table.
    Returns:
        DataFrame with columns mode, affinity_kcal_mol, rmsd_lb, rmsd_ub.
    """
    rows = []
    for line in text.strip().split('\n'):
        line = line.strip()
        if line and line[0].isdigit():
            parts = line.split()
            rows.append({
                'mode': int(parts[0]),
                'affinity_kcal_mol': float(parts[1]),
                'rmsd_lb': float(parts[2]),
                'rmsd_ub': float(parts[3]),
            })
    return pd.DataFrame(rows)


vina_output = """mode |   affinity | dist from best mode
     | (kcal/mol) | rmsd l.b.| rmsd u.b.
-----+------------+----------+----------
   1       -8.7      0.000      0.000
   2       -8.3      1.245      2.187
   3       -7.9      2.056      4.321
"""
hits = parse_vina_output(vina_output)
best = hits.loc[hits['affinity_kcal_mol'].idxmin()]
assert best['mode'] == 1

GROMACS MD Workflow

gmx pdb2gmx -f protein.pdb -o protein.gro -water tip3p -ff amber99sb-ildn
gmx editconf -f protein.gro -o box.gro -c -d 1.0 -bt dodecahedron
gmx solvate -cp box.gro -cs spc216.gro -o solvated.gro -p topol.top
# Then: add ions (gmx genion) -> energy minimization (em.mdp) ->
#       NVT equilibration -> NPT equilibration -> production MD (md.mdp)

Analysis: gmx rms (RMSD), gmx rmsf (per-residue fluctuation), gmx gyrate (radius of gyration), gmx hbond (hydrogen bonds).

Homology model quality: >50% sequence identity = reliable; 30-50% = reasonable; <30% = twilight zone. AlphaFold pLDDT: >90 high confidence; 70-90 moderate; <50 likely disordered — always energy-minimize a model before MD.

Scanpy Single-Cell Pipeline

Goal: go from a raw 10x count matrix to QC-filtered, clustered, annotated cell types. Approach: filter → normalize → find HVGs (saving raw first) → PCA/neighbors/UMAP → Leiden clustering → marker-gene-based annotation.

import scanpy as sc

adata = sc.read_10x_mtx('filtered_feature_bc_matrix/')  # or sc.datasets.pbmc3k()

# QC: flag mitochondrial genes, compute metrics, filter
adata.var['mt'] = adata.var_names.str.startswith('MT-')
sc.pp.calculate_qc_metrics(adata, qc_vars=['mt'], inplace=True)
sc.pp.filter_cells(adata, min_genes=200)
sc.pp.filter_genes(adata, min_cells=3)
adata = adata[adata.obs.pct_counts_mt < 20]

# Normalize -> log -> HVG -> snapshot raw -> scale
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata)
sc.pp.highly_variable_genes(adata, min_mean=0.0125, max_mean=3, min_disp=0.5)
adata.raw = adata                              # save unscaled data before subsetting
adata = adata[:, adata.var.highly_variable]
sc.pp.scale(adata, max_value=10)

# Dimensionality reduction + clustering
sc.tl.pca(adata, svd_solver='arpack', n_comps=50)
sc.pp.neighbors(adata, n_neighbors=15, n_pcs=40)
sc.tl.umap(adata)
sc.tl.leiden(adata, resolution=0.5, flavor='igraph', n_iterations=2)  # 0.2 coarse - 2.0 fine

# Marker genes + manual annotation
sc.tl.rank_genes_groups(adata, 'leiden', method='wilcoxon')
cluster_annotations = {'0': 'CD4+ T cells', '1': 'CD14+ Monocytes'}
adata.obs['cell_type'] = adata.obs['leiden'].map(cluster_annotations)

Pitfalls

  • ACMG: BA1 alone is stand-alone benign — no pathogenic evidence overrides it. VUS is the correct default when evidence is insufficient or conflicting.
  • Variant predictors: no single tool is authoritative for PP3/BP4; require concordance across multiple orthogonal tools.
  • gnomAD frequency: use population-specific max MAF (popmax), not global AF; recessive disorders tolerate higher carrier frequency than dominant ones.
  • Force fields: never mix parameters from different FFs; always energy-minimize before starting MD.
  • Docking scores: reliable for ranking poses of the same ligand; not reliable for cross-ligand ranking without rescoring (e.g. MM-GBSA).
  • Scanpy adata.raw: must be set before HVG subsetting — rank_genes_groups and DE tools read from the raw, unscaled data.
  • Leiden resolution: default 1.0 tends to over-split PBMC-like data; 0.3-0.6 typically yields interpretable major cell types. Use flavor='igraph' (current scanpy default going forward) for speed and determinism.

See Also

  • bio-applied-clinical-genomics — VCF annotation pipelines and ClinVar/gnomAD lookups feeding ACMG scoring
  • bio-applied-variant-calling-and-snp-analysis — upstream variant calling before classification
  • bio-applied-docking — deeper AutoDock Vina / docking workflow patterns
  • bio-applied-single-cell-scanpy — advanced Scanpy/AnnData QC, integration, and annotation patterns

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.