Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Statistical testing for differentially abundant proteins between conditions. Covers limma and MSstats workflows with multiple testing correction. Use when identifying proteins with significant abundance changes between experimental groups.
.claude/skills/bio-proteomics-differential-abundance/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✗ | = Same ✗ | — | — |
| case-04 | ✗→✗ | = Same ✗ | — | — |
| case-05 | ✗→✗ | = Same ✗ | — | — |
| case-06 | ✗→✗ | = Same ✗ | — | — |
| case-07 | ✗→✗ | = Same ✗ | — | — |
Reference examples tested with: R stats (base), ggplot2 3.5+, limma 3.58+, numpy 1.26+, pandas 2.2+, scipy 1.12+, statsmodels 0.14+
Before using code patterns, verify installed versions match. If versions differ:
pip show <package> then help(module.function) to check signaturespackageVersion('<pkg>') then ?function_name to verify parametersIf code throws ImportError, AttributeError, or TypeError, introspect the installed package and adapt the example to match the actual API rather than retrying.
"Find differentially abundant proteins between my conditions" → Perform statistical testing on quantified protein intensities to identify proteins with significant abundance changes between experimental groups.
MSstats::groupComparison() for feature-level mixed modelslimma::eBayes() for empirical Bayes moderated t-tests on protein-level datascipy.stats.ttest_ind() with statsmodels FDR correctionGoal: Identify differentially abundant proteins between experimental conditions using feature-level mixed models or moderated t-tests.
Approach: Define contrast matrices for pairwise comparisons, run MSstats groupComparison (or limma eBayes for protein-level data), then filter results by adjusted p-value and log2 fold change thresholds.
rlibrary(MSstats) # After dataProcess() comparison_matrix <- matrix(c(1, -1, 0, 0, 1, 0, -1, 0, 0, 1, -1, 0), nrow = 3, byrow = TRUE) rownames(comparison_matrix) <- c('Treatment1-Control', 'Treatment2-Control', 'Treatment1-Treatment2') colnames(comparison_matrix) <- c('Control', 'Treatment1', 'Treatment2', 'Treatment3') results <- groupComparison(contrast.matrix = comparison_matrix, data = processed) # Significant proteins sig_proteins <- results$ComparisonResult[results$ComparisonResult$adj.pvalue < 0.05 & abs(results$ComparisonResult$log2FC) > 1, ]
rlibrary(limma) # Log2 intensities matrix (proteins x samples) design <- model.matrix(~ 0 + condition, data = sample_info) colnames(design) <- levels(sample_info$condition) fit <- lmFit(protein_matrix, design) contrast_matrix <- makeContrasts(Treatment - Control, levels = design) fit2 <- contrasts.fit(fit, contrast_matrix) fit2 <- eBayes(fit2) results <- topTable(fit2, number = Inf, adjust.method = 'BH') sig_results <- results[results$adj.P.Val < 0.05 & abs(results$logFC) > 1, ]
rlibrary(QFeatures) library(proDA) # proDA handles missing values probabilistically fit <- proDA(protein_matrix, design = ~ condition, data = sample_info) # Test differential abundance results <- test_diff(fit, contrast = 'conditionTreatment') results$adj_pval <- p.adjust(results$pval, method = 'BH') sig_results <- results[results$adj_pval < 0.05 & abs(results$diff) > 1, ]
pythonimport pandas as pd import numpy as np from scipy import stats from statsmodels.stats.multitest import multipletests def differential_test(intensities, group1_cols, group2_cols): results = [] for protein in intensities.index: g1 = intensities.loc[protein, group1_cols].dropna() g2 = intensities.loc[protein, group2_cols].dropna() if len(g1) >= 2 and len(g2) >= 2: stat, pval = stats.ttest_ind(g1, g2) log2fc = g2.mean() - g1.mean() results.append({'protein': protein, 'log2FC': log2fc, 'pvalue': pval}) df = pd.DataFrame(results) df['adj_pvalue'] = multipletests(df['pvalue'], method='fdr_bh')[1] return df # Significance thresholds sig = results[(results['adj_pvalue'] < 0.05) & (abs(results['log2FC']) > 1)]
r# Volcano plot library(ggplot2) ggplot(results, aes(x = log2FC, y = -log10(adj.P.Val))) + geom_point(aes(color = significant), alpha = 0.6) + geom_hline(yintercept = -log10(0.05), linetype = 'dashed') + geom_vline(xintercept = c(-1, 1), linetype = 'dashed') + scale_color_manual(values = c('grey', 'red')) + theme_minimal()
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
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. 22 cases were attempted. The headline lift of -100 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.