Skip to main content

bio-crispr-screens-screen-qc

Quality control for pooled CRISPR screens covering library representation, Gini index, log-skew, replicate Pearson and Spearman concordance, essentialome precision-recall AUC against CEGv2 (Hart 2017), Cas9 cut-toxicity diagnostics, copy-number amplicon detection (Aguirre 2016 / Munoz 2016), bottleneck propagation through plasmid pool, infection, selection, and endpoint stages, MOI verification, and DepMap-style screen-quality scoring. Use when assessing screen quality before hit calling, deciding whether to repeat or rescue a screen, diagnosing low-confidence hits, choosing between MAGeCK / BAGEL2 / Chronos based on quality grade, picking a normalization strategy from QC signatures, or evaluating whether an in-vivo screen retained adequate library complexity.

Informations de source

Dépôt
GPTomics/bioSkills
Dernière activité de la source
25 juillet 2026 à 09:16
Langue détectée de SKILL.md
anglais
Étoiles
1 209
Forks
251

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Explorateur de fichiers
3 fichiers

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
bio-crispr-screens-screen-qc
description
Quality control for pooled CRISPR screens covering library representation, Gini index, log-skew, replicate Pearson and Spearman concordance, essentialome precision-recall AUC against CEGv2 (Hart 2017), Cas9 cut-toxicity diagnostics, copy-number amplicon detection (Aguirre 2016 / Munoz 2016), bottleneck propagation through plasmid pool, infection, selection, and endpoint stages, MOI verification, and DepMap-style screen-quality scoring. Use when assessing screen quality before hit calling, deciding whether to repeat or rescue a screen, diagnosing low-confidence hits, choosing between MAGeCK / BAGEL2 / Chronos based on quality grade, picking a normalization strategy from QC signatures, or evaluating whether an in-vivo screen retained adequate library complexity.
tool_type
python
primary_tool
MAGeCK-VISPR
## Version Compatibility Reference examples tested with: MAGeCK 0.5+ (count + VISPR), MAGeCKFlute 2.0+ (R), pandas 2.2+, numpy 1.26+, scikit-learn 1.4+, matplotlib 3.8+, seaborn 0.13+. Before using code patterns, verify installed versions match. If versions differ: - CLI: `mageck --version` then `mageck count --help`; R: `packageVersion('MAGeCKFlute')` - R: `packageVersion('MAGeCKFlute')` then `?BatchRemove` / `?FluteRRA` If code throws ImportError, AttributeError, or TypeError, introspect the installed package and adapt the example to match the actual API rather than retrying. ## CRISPR Screen Quality Control **"Audit my CRISPR screen quality before hit calling"** -> Assess library representation, replicate concordance, depth, drift, and biological signal recovery using DepMap-grade metrics, then decide whether the screen is usable, salvageable, or must be repeated. - Python: `pandas` + `scikit-learn` for Gini, AUC, PCA; `MAGeCKFlute` (R) for one-shot QC dashboard - CLI: `mageck count` writes Gini and mapping stats unconditionally to `<prefix>.countsummary.txt` (`GiniIndex`, `Reads`, `Mapped`, `Percentage`); MAGeCK-VISPR for an interactive dashboard ## QC Stage Hierarchy A pooled screen has six distinct bottlenecks where complexity can collapse. Audit each: | Stage | Metric | Acceptable threshold | Failure consequence | |-------|--------|----------------------|----------------------| | Plasmid pool | Gini, skew, % zero-count guides | Gini <0.1, skew <2 (Joung 2017 states <10), zero <0.5% | Missing guides cannot be screened; dropout indistinguishable from non-coverage | | Day-0 infection | Library coverage, MOI verification | ≥99% guide detection at 500x cells/sgRNA; MOI 0.3 | Founder effects; polyclonality with high MOI | | Selection (puro/blast) | % cells surviving, time-course Gini | 30-40% survival at 5-7 days; Gini drift <0.05 | Selection artifact; fast-growers enriched | | Endpoint | Replicate correlation, depth | Pearson >=0.8 on log-counts (MAGeCK-VISPR floor), Spearman >0.7-0.8, >500 reads/sgRNA (Joung 2017 screening) | Noise dominates; FDR inflates | | Biological signal | CEGv2 PR-AUC, NEGv1 false-positive rate | PR-AUC >0.7 at FDR 5% (community "passing" convention); CEGv2 enrichment in top 1k | Screen lacks essentiality signal; hits not credible | | Copy-number artifact | Amplified-region enrichment, sgRNA-cut-count correlation | No correlation between sgRNA off-target count and depletion | False-positive essentiality at amplicons; ERBB2 in HER2+ etc. | Each metric below quantifies one of these stages. ## Library Representation Metrics **Goal:** Detect dropout, oversaturation, and library bottlenecks at each sequencing stage. **Approach:** Compute per-sample zero-count fraction, low-count fraction (<30 reads, the CRISPRcleanR `ccr.NormfoldChanges` default), and percentile-based skew, then track how these change between plasmid -> Day-0 -> endpoint to localize the bottleneck. ```python import pandas as pd import numpy as np def library_representation(counts_df): '''Per-sample library coverage diagnostics. counts_df: rows = sgRNAs, columns = samples (numeric counts).''' out = pd.DataFrame(index=counts_df.columns) out['n_sgrnas_detected'] = (counts_df > 0).sum() out['pct_zero'] = (counts_df == 0).sum() / len(counts_df) * 100 out['pct_lowcount'] = (counts_df < 30).sum() / len(counts_df) * 100 out['median_count'] = counts_df.median() out['p10_count'] = counts_df.quantile(0.10) out['p90_count'] = counts_df.quantile(0.90) out['skew_ratio'] = out['p90_count'] / out['p10_count'].replace(0, np.nan) return out def stage_specific_thresholds(): '''Stage conventions: Joung 2017 (zero-count, skew) + MAGeCK-VISPR (Gini).''' return { 'plasmid': {'pct_zero_max': 0.5, 'skew_max': 2.0, 'gini_max': 0.10}, # skew 2.0 is a stricter modern convention; Joung 2017 states <10 'day_0': {'pct_zero_max': 1.0, 'skew_max': 2.5, 'gini_max': 0.12}, 'endpoint': {'pct_zero_max': 5.0, 'skew_max': 10.0, 'gini_max': 0.30}, } ``` **Interpretation:** Plasmid pool failing Gini <0.1 indicates synthesis or amplification bias; the screen is unfit for use. Endpoint Gini drifting above 0.30 indicates either heavy biological selection (acceptable for strong-phenotype drug screens) or a bottleneck (must be diagnosed). The Day-0 vs plasmid delta isolates whether the issue arose during infection (cloning is unlikely to lose specific guides between extraction and infection -- the change happens in cells). ## Gini Coefficient **Goal:** Quantify how unevenly reads are distributed across sgRNAs in a single sample. **Approach:** Sort non-zero counts ascending, compute Gini via the cumulative-fraction formula. Compare against stage-specific thresholds. ```python def gini(x): '''Gini coefficient: 0 = perfect equality, 1 = maximal inequality. Uses non-zero counts only; zero-count sgRNAs handled separately by % zero.''' x = np.sort(x[x > 0].astype(float)) if x.size == 0: return np.nan n = x.size cumx = np.cumsum(x) return (n + 1 - 2 * np.sum(cumx) / cumx[-1]) / n ``` **Stage-specific thresholds:** only the plasmid Gini <=0.1 is a published cutoff (MAGeCK-VISPR); the remaining grades are operational convention. | Stage | Excellent | Acceptable | Concerning | Failure | |-------|-----------|------------|------------|---------| | Plasmid pool | <0.10 | <0.15 | 0.15-0.20 | >0.20 | | Day 0 (post-infection) | <0.12 | <0.18 | 0.18-0.25 | >0.25 | | Endpoint (post-selection) | <0.30 | <0.40 | 0.40-0.55 | >0.55 | A Gini that climbs from 0.10 (plasmid) to 0.45 (endpoint) is expected when the screen exerts strong selection (drug, lethal-condition). A Gini that climbs to 0.45 without any biological selection (e.g., a control-vs-control timepoint comparison) indicates technical drift. ## Replicate Concordance **Goal:** Verify that biological/technical replicates agree before testing for between-condition differences. **Approach:** Compute pairwise Pearson on log10(counts+1) (MAGeCK-VISPR convention) and Spearman ρ on raw rank, between every replicate pair within a condition. Flag any pair below the MAGeCK-VISPR floor of 0.8 Pearson on log-scale. ```python def replicate_concordance(counts_df, condition_map): '''condition_map: {condition_name: [sample_col1, sample_col2, ...]}.''' log_counts = np.log10(counts_df + 1) rows = [] for cond, samples in condition_map.items(): if len(samples) < 2: continue for i in range(len(samples)): for j in range(i+1, len(samples)): r_pearson = log_counts[[samples[i], samples[j]]].corr().iloc[0, 1] r_spearman = counts_df[[samples[i], samples[j]]].corr(method='spearman').iloc[0, 1] rows.append({'condition': cond, 'rep1': samples[i], 'rep2': samples[j], 'pearson_log': r_pearson, 'spearman': r_spearman}) return pd.DataFrame(rows) ``` **Thresholds:** 0.8 Pearson is the MAGeCK-VISPR floor; the stricter grades are operational convention. | Metric | Excellent | Acceptable | Failure | |--------|-----------|------------|---------| | Pearson on log10(counts+1) | >0.95 | >0.85 | <0.80 | | Spearman on raw ranks | >0.85 | >0.70 | <0.60 | **When Pearson is high but Spearman is low**, a few outlier sgRNAs are driving correlation (one extreme guide dominates). Inspect the scatterplot; typically caused by PCR jackpotting at a single guide. Hit calling should use a method that ranks (RRA, drugZ) rather than one that fits per-sgRNA fold change directly. ## Essentialome Recovery (CEGv2 PR-AUC) **Goal:** Verify the screen has detectable biological essentiality signal by checking whether known essentials (Hart 2017 CEGv2) drop out faster than known non-essentials (NEGv1). **Approach:** Compute precision-recall AUC where positives are CEGv2 genes and negatives are NEGv1; the screen "passes" if PR-AUC >0.7 (community convention; the CEGv2/NEGv1 sets come from Hart 2017 / Hart 2014). ```python from sklearn.metrics import precision_recall_curve, auc, roc_auc_score def essentialome_recovery(gene_lfc_df, cegv2_set, negv1_set): '''gene_lfc_df: must have ["gene", "lfc"] columns (gene-level mean LFC, negative = depleted). cegv2_set, negv1_set: sets of gene symbols from Hart 2017.''' labeled = gene_lfc_df[gene_lfc_df['gene'].isin(cegv2_set | negv1_set)].copy() labeled['is_essential'] = labeled['gene'].isin(cegv2_set).astype(int) y_score = -labeled['lfc'] # negative LFC = depleted = more essential -> higher score precision, recall, _ = precision_recall_curve(labeled['is_essential'], y_score) return { 'pr_auc': auc(recall, precision), 'roc_auc': roc_auc_score(labeled['is_essential'], y_score), 'n_essential_detected': labeled['is_essential'].sum(), 'n_nonessential_detected': (1 - labeled['is_essential']).sum(), } ``` **Source / threshold:** Hart 2017 *G3* 7:2719 defines CEGv2 (~684 core essentials); NEGv1 (~927 non-essentials) comes from Hart 2014 *Mol Syst Biol* 10:733. Both lists at https://github.com/hart-lab/bagel/blob/master/CEGv2.txt and NEGv1.txt. DepMap convention: PR-AUC >0.7 at FDR 5% is the "passing" threshold; <0.5 means the screen has no essentiality signal and is not interpretable. **When PR-AUC is low despite good Gini and Pearson**: cause is usually one of (a) Cas9 was not selected for before screen start (lots of Cas9-negative cells in the pool diluting signal), (b) puromycin selection truncated too aggressively (over-bottleneck), (c) the timepoint is too early (need 14-21 days for KO + decay + selection to manifest). Each has a different remediation. ## Copy-Number Amplicon Bias Diagnostic **Goal:** Detect the Aguirre 2016 / Munoz 2016 copy-number artifact where sgRNAs targeting amplified loci appear "essential" purely from DNA-damage burden. **Approach:** Bin genes by copy number (if known from matched WGS/SNP-array) and check whether mean LFC correlates with CN. Alternatively, count off-target cut sites per sgRNA and check correlation with depletion -- amplified loci share many identical cut sites. ```python def cn_bias_diagnostic(gene_lfc_df, cn_df): '''cn_df: per-gene copy number (from WGS/SNP-array/matched ASCAT). Tests whether amplified genes show systematically lower LFC.''' merged = gene_lfc_df.merge(cn_df, on='gene') bins = pd.qcut(merged['copy_number'], q=5, duplicates='drop') bin_lfc = merged.groupby(bins, observed=True)['lfc'].agg(['mean', 'median', 'std', 'count']) from scipy.stats import spearmanr rho, p = spearmanr(merged['copy_number'], merged['lfc']) return {'cn_vs_lfc_rho': rho, 'cn_vs_lfc_p': p, 'amplified_mean_lfc': merged[merged['copy_number'] > 4]['lfc'].mean(), 'diploid_mean_lfc': merged[(merged['copy_number'] >= 1.5) & (merged['copy_number'] <= 2.5)]['lfc'].mean(), 'per_bin': bin_lfc} ``` **Interpretation:** A Spearman ρ < -0.1 between copy number and LFC indicates copy-number artifact. The diagnostic threshold is conservative -- Aguirre 2016 showed the effect scales with copy number and with the number of cut sites per sgRNA. Remediation: use CRISPRcleanR, CERES, or Chronos (see [[copy-number-correction]]) before hit calling. ## Sequencing Depth Audit **Goal:** Verify that sequencing depth is sufficient to resolve fold changes at the smallest interesting effect size. **Approach:** Compute reads/sgRNA per sample and the coefficient of variation (CV) of total reads across samples. Compare against Joung 2017's >100 reads/sgRNA for plasmid QC and >500 for screening, or MAGeCK-VISPR's 300x. ```python def depth_audit(counts_df): '''Verify depth: Joung 2017 recommends >100 reads/sgRNA for plasmid QC and >500 for screening; MAGeCK-VISPR uses 300x.''' total = counts_df.sum() n_sgrnas = len(counts_df) depth = total / n_sgrnas cv = total.std() / total.mean() return pd.DataFrame({'total_reads': total, 'reads_per_sgrna': depth, 'depth_grade': np.where(depth < 100, 'FAIL', np.where(depth < 300, 'CAUTION', np.where(depth < 500, 'OK', 'EXCELLENT')))}).assign(across_sample_cv=cv) # 100 = Joung 2017 plasmid-QC floor; 300 = MAGeCK-VISPR; 500 = Joung 2017 screening ``` **CV interpretation:** CV >0.5 across samples in total reads indicates demultiplexing imbalance or library-pooling error; even if individual samples pass depth thresholds, the relative count is then biased. ## MOI Verification **Goal:** Confirm that infection occurred at MOI 0.3-0.5 so that ≤1 sgRNA/cell predominates. **Approach:** From titration plate (control wells with serial-diluted virus), compute infection efficiency, then verify by qPCR of integrated proviral copy number in the screen pool. | MOI | P(≥1 sgRNA/cell) | P(≥2 sgRNAs/cell) | Cells with 2+ guides as fraction of infected |
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub