Proteomics Analysis Toolkit
A Python toolkit for analyzing mass spectrometry-based proteomics data, supporting both Skyline CSV and PRISM parquet workflows.
Features
Core Analysis Modules
- data_import: Load Skyline CSV, PRISM parquet, or DIA-NN
pg_matrix.tsvdata, handle batch suffixes, manage sample metadata - preprocessing: Protein identifier parsing, sample classification, data quality assessment
- normalization: Seven normalization methods (median, VSN, quantile, MAD, z-score, RLR, LOESS)
- statistical_analysis: Differential protein analysis — t-tests, Wilcoxon, Mann-Whitney, mixed-effects, moderated linear model with empirical-Bayes variance shrinkage (by default limma-trend with peptide count at protein level and limma-trend otherwise; global / DEqMS)
- visualization: Publication-ready plots — volcano, PCA, box plots, heatmaps, correlation, trajectories, bi-clustered sample clustermaps, UMAP, PCA loadings
- enrichment: Gene set enrichment via Enrichr API
- temporal_clustering: K-means clustering of temporal protein trends
- classification: Binary classification with cross-validation, SHAP interpretability, multi-class permutation importance; recursive feature elimination with cross-validation, per-feature stability selection, and a permutation null (
run_rfecv_stability) - regression: Nested cross-validated ElasticNet regression for continuous outcomes, with per-feature stability selection and a permutation null (
run_elasticnet_regression) - marker_discovery: Descriptive marker-discovery metrics and silhouette-driven k-means clustering for low-n designs
- multivariate: PERMANOVA variance partitioning on sample-by-sample distance matrices
- validation: Metadata/data consistency checking with diagnostic reports
- export: Standardized result export with timestamped configs
Installation
With uv (recommended)
uv is a fast Python package and project
manager. Install it once with:
curl -LsSf https://astral.sh/uv/install.sh | sh
Then, from a clone of this repository:
git clone https://github.com/uw-maccosslab/proteomics-toolkit.git
cd proteomics-toolkit
uv sync # creates .venv and installs runtime deps from uv.lock
uv sync --extra dev # also installs pytest + pytest-cov for running tests
uv sync --extra umap # also installs umap-learn for plot_umap
# Run commands inside the managed venv
uv run pytest tests/ -v
uv run python -c "import proteomics_toolkit as ptk; print(ptk.__version__)"
Or add it to an existing uv-managed project:
uv add proteomics-toolkit
uv add 'proteomics-toolkit[umap]' # with optional UMAP support
With pip
# Install from PyPI
pip install proteomics-toolkit
# With optional UMAP support (for plot_umap)
pip install proteomics-toolkit[umap]
# Install from GitHub (latest development version)
pip install git+https://github.com/uw-maccosslab/proteomics-toolkit.git
# For development (editable install from local clone)
git clone https://github.com/uw-maccosslab/proteomics-toolkit.git
cd proteomics-toolkit
pip install -e '.[dev]'
Quick Start
PRISM Workflow (recommended for batch-corrected data)
import proteomics_toolkit as ptk
import pandas as pd
# 1. Load PRISM data
protein_data, metadata, sample_cols = ptk.load_prism_data(
'PRISM-Output/corrected_proteins.parquet',
'PRISM-Output/sample_metadata.csv',
)
# 2. Map batch-suffixed column names to short replicate IDs
col_map = ptk.strip_batch_suffix(sample_cols) # {full_col: short_name}
short_to_col = {v: k for k, v in col_map.items()}
# 3. Build sample metadata dict (keys = full PRISM column names)
meta_dict = {}
for _, row in metadata.iterrows():
full_col = short_to_col.get(row['Replicate'])
if full_col:
meta_dict[full_col] = row.to_dict()
# 4. Build annotation + sample data for stats
annot = protein_data[[
'leading_protein', 'leading_description', 'leading_gene_name',
'leading_uniprot_id', 'leading_name'
]].copy()
annot.columns = ['Protein', 'Description', 'Protein Gene', 'UniProt_Accession', 'UniProt_Entry_Name']
data = pd.concat([annot.reset_index(drop=True),
protein_data[sample_cols].reset_index(drop=True)], axis=1)
data.index = data['Protein'] # accession as index
# 5. Statistical analysis
config = ptk.StatisticalConfig()
config.analysis_type = 'unpaired'
config.statistical_test_method = 'welch_t'
config.group_column = 'Group'
config.group_labels = ['Control', 'Treatment'] # [reference, study]
config.correction_method = 'fdr_bh'
config.p_value_threshold = 0.05
config.fold_change_threshold = 1.0
config.log_transform_before_stats = True
config.validate()
results = ptk.run_comprehensive_statistical_analysis(
data, meta_dict, config, protein_annotations=annot
)
# 6. Visualization
ptk.plot_volcano(results, fc_threshold=1.0, gene_column='Protein Gene', label_top_n=15)
ptk.display_analysis_summary(results, config)
# 7. Enrichment
enrich_config = ptk.EnrichmentConfig(
enrichr_libraries=['GO_Biological_Process_2023', 'KEGG_2021_Human'],
pvalue_cutoff=0.05,
)
enrich = ptk.run_differential_enrichment(
results, gene_column='Protein Gene', logfc_column='logFC',
pvalue_column='adj.P.Val', config=enrich_config,
)
Skyline CSV Workflow
# 1. Load data
protein_data, metadata, peptide_data = ptk.load_skyline_data(
protein_file='protein_quant.csv',
metadata_file='metadata.csv',
)
# 2. Process sample names
sample_columns = ptk.data_import.identify_sample_columns(protein_data, metadata)
cleaned_names = ptk.clean_sample_names(sample_columns)
# 3. Parse annotations and filter
processed_data = ptk.parse_protein_identifiers(protein_data)
# 4. Normalize (skip for PRISM — already normalized)
normalized = ptk.median_normalize(processed_data, sample_columns=list(cleaned_names.values()))
# 5. QC plots
ptk.plot_box_plot(normalized, list(cleaned_names.values()), sample_metadata)
ptk.plot_pca(normalized, list(cleaned_names.values()), sample_metadata)
Statistical Analysis
All statistical analyses use StatisticalConfig + run_comprehensive_statistical_analysis().
Unpaired comparison (two independent groups)
config = ptk.StatisticalConfig()
config.analysis_type = 'unpaired'
# Options: 'welch_t', 'mann_whitney', 'moderated_linear_model'
config.statistical_test_method = 'welch_t'
config.group_column = 'Group'
config.group_labels = ['Control', 'Treatment']
config.log_transform_before_stats = 'auto'
config.validate()
results = ptk.run_comprehensive_statistical_analysis(
data, sample_metadata, config, protein_annotations=annot
)
For small sample sizes, prefer empirical Bayes variance shrinkage: set
config.statistical_test_method = 'moderated_linear_model' and choose a
config.moderation prior, by the names Skyline-PRISM uses. Left unset it is
chosen by level: 'limma-trend-intensity-n-peptides' (limma-trend with the
protein's peptide count as a second covariate) for protein-level data with an
n_peptides column, as PRISM output has, and 'limma-trend' (limma's
eBayes(trend=TRUE)) otherwise, including at peptide level. Or name one:
those two, 'global' (one global prior), or 'peptide-count' (DEqMS,
protein-level only).
'intensity-trend', the default until 26.9.0, is deprecated: it is
calibrated on average but tilted by intensity. See
docs/06-statistical-analysis.md
for details.
Paired comparison (before/after per subject)
config = ptk.StatisticalConfig()
config.analysis_type = 'paired'
config.statistical_test_method = 'paired_t'
config.subject_column = 'Subject'
config.paired_column = 'Condition'
config.paired_label1 = 'Before'
config.paired_label2 = 'After'
config.group_column = 'Condition'
config.group_labels = ['Before', 'After']
config.validate()
Mixed-effects model (repeated measures)
config = ptk.StatisticalConfig()
config.analysis_type = 'paired'
config.statistical_test_method = 'mixed_effects'
config.subject_column = 'Subject'
config.paired_column = 'Visit'
config.paired_label1 = 'Baseline'
config.paired_label2 = 'Follow-up'
config.group_column = 'Treatment'
config.group_labels = ['Placebo', 'Drug']
config.interaction_terms = ['Treatment', 'Visit']
config.validate()
Output columns: Protein, logFC, P.Value, adj.P.Val, AveExpr, t, Protein Gene, Description, UniProt_Accession, Gene
Enrichment
Enrichment results use these column names (not the Enrichr web-UI names):
| Column | Description |
|---|---|
Term |
Pathway / GO term name |
P_Value |
Unadjusted p-value |
Adj_P_Value |
BH-adjusted p-value |
Z_Score |
Enrichr z-score |
Combined_Score |
log(p) × z — used for ranking |
Genes |
Semicolon-separated gene list |
N_Genes |
Number of overlapping genes |
Library |
Source Enrichr library |
Dependencies
- pandas >= 1.3.0
- numpy >= 1.21.0
- scipy >= 1.7.0
- matplotlib >= 3.4.0
- seaborn >= 0.11.0
- scikit-learn >= 1.0.0
- statsmodels >= 0.12.0
- requests >= 2.25.0 (for Enrichr API)
- pyarrow >= 8.0.0 (for PRISM parquet files)
Module Reference
data_import.py
load_skyline_data()— Load Skyline protein/peptide CSVs + metadataload_prism_data()— Load PRISM protein parquet + metadataload_prism_peptide_data()— Load PRISM peptide parquetload_diann_data()— Load DIA-NNreport.pg_matrix.tsvprotein-group matrixload_fasta_sequences()— Parse a FASTA file into{accession -> sequence}identify_sample_columns()— Auto-detect sample columnsclean_sample_names()— Remove common prefixes/suffixesdetect_batch_suffix()— Detect PRISM__@__batch suffixstrip_batch_suffix()— Map batch-suffixed names → short namescreate_sample_column_mapping()— Map data columns to metadata sample namesmatch_samples_to_metadata()— Link samples to metadata rowsBATCH_SUFFIX_DELIMITER— Constant:"__@__"
preprocessing.py
parse_protein_identifiers()— Extract UniProt accessions and databasesparse_gene_and_description()— Parse gene names from descriptionsclassify_samples()— Classify samples into groups / controls with color assignmentapply_systematic_color_scheme()— Generate consistent group colorscreate_standard_data_structure()— Build standard 5-column annotation + sample layoutassess_data_completeness()— Evaluate missing data patternsfilter_proteins_by_completeness()— Remove proteins below detection thresholdcalculate_group_colors()— Generate group color mappingidentify_annotation_columns()— Auto-detect annotation vs sample columns
normalization.py
median_normalize()— Median-based normalization (preserves original scale)vsn_normalize()— Variance Stabilizing Normalization (arcsinh-transformed)quantile_normalize()— Force identical distributionsmad_normalize()— Median absolute deviation normalizationz_score_normalize()— Standardize to mean=0, sd=1rlr_normalize()— Robust linear regression (log2-transformed)loess_normalize()— LOESS intensity-dependent (log2-transformed)handle_negative_values()— Handle negative values from VSNanalyze_negative_values()— Analyze negative value patternscalculate_normalization_stats()— Evaluate normalization effectiveness
statistical_analysis.py
StatisticalConfig— Configuration class (zero-arg constructor, set attributes individually)run_comprehensive_statistical_analysis()— Main analysis entry point (dispatches bystatistical_test_method)run_moderated_linear_model()— Per-feature linear model with empirical-Bayes variance moderation (moderationunset - chosen by level - or'limma-trend-intensity-n-peptides'(protein level only) /'limma-trend'/'global'/'peptide-count', or the deprecated'intensity-peptide-trend'/'intensity-trend'; Skyline-PRISM's names); supports covariate adjustment foranalysis_type='unpaired'get_intensity_trend_points()— Recover the per-(feature, group) diagnostic points DataFrame from a moderatedintensity-trendresults objectcompute_paired_fold_changes()— Build a per-subject fold-change matrix for paired designs (used as input to the classification module)display_analysis_summary()— Print/return summary of resultsrun_statistical_analysis()— Backward-compatible wrapper
visualization.py
plot_box_plot()— Sample intensity distributions by groupplot_volcano()— Volcano plot with labeled top hitsplot_pca()— PCA with group coloring, optional log-transformplot_pca_loadings()— PCA loadings biplot with top-N protein labelsplot_umap()— UMAP projection of samples colored by metadata group (requires[umap]extra)plot_comparative_pca()— Compare PCA across normalization methodsplot_normalization_comparison()— Before/after normalization QCplot_missing_value_heatmap()— Missing-value pattern across samples x featuresplot_identifications_per_sample()— Bar plot of #features identified per sampleplot_intensity_distributions()— Density overlay of intensity per sampleplot_cv_distribution()— CV distribution across all samples (or by group)plot_sample_correlation_heatmap()— Full correlation matrixplot_sample_correlation_triangular_heatmap()— Lower-triangle correlationplot_control_correlation()— Control sample correlation with optional clusteringplot_control_correlation_analysis()— Multi-panel control QCplot_control_group_correlation_analysis()— Group-wise control QCplot_individual_control_pool_analysis()— Individual control analysisplot_control_cv_distribution()— CV distribution for control samplesplot_grouped_heatmap()— Heatmap for any grouped dataplot_sample_clustermap()— Bi-clustered heatmap of samples x features with optional group color barplot_grouped_trajectories()— Line plots for temporal/dose-response dataplot_protein_profile()— Single protein expression profileplot_peptide_coverage_map()— Peptide positions along a protein sequence with optional coloring by abundance / fold-changeplot_variance_vs_intensity()— Diagnostic for the deprecated intensity-trend moderation priors (intensity-trendandintensity-peptide-trend)plot_variance_vs_peptide_count()— Diagnostic for the DEqMS moderation prior
enrichment.py
EnrichmentConfig— Configuration dataclass (libraries, thresholds, API settings)query_enrichr()— Query Enrichr API with a gene listparse_enrichr_results()— Parse raw results into a tidy DataFramerun_enrichment_analysis()— Complete enrichment on a gene listrun_enrichment_by_group()— Enrichment for each group in a DataFramerun_differential_enrichment()— Split by up/down-regulated, run enrichment on eachplot_enrichment_barplot()— Horizontal bar plot by Combined Scoreplot_enrichment_comparison()— Dot plot comparing enrichment across groupsget_available_libraries()— List common Enrichr librariesmerge_enrichment_results()— Merge multiple enrichment DataFrames
temporal_clustering.py
TemporalClusteringConfig— Configuration dataclassrun_temporal_analysis()— Complete pipeline: clustering → visualization → enrichmentcalculate_temporal_means()— Mean abundance per timepoint across subjectscluster_temporal_trends()— K-means or hierarchical clusteringname_clusters_by_pattern()— Assign descriptive cluster namesclassify_trend_pattern()— Classify individual protein trendsmerge_with_statistics()— Merge temporal data with statistical resultsfilter_significant_proteins()— Filter to significant proteinsrun_enrichment_by_cluster()— Enrichment per clusterplot_cluster_heatmap()— Cluster-organized heatmapplot_cluster_parallel_coordinates()— Parallel coordinate plots
classification.py
run_binary_classification()— Binary classification with feature selection and cross-validation; returns CV metrics, ROC data, and (withreturn_model=True) the fitted pipelinerun_rfecv_stability()— Recursive feature elimination with cross-validation under an honest outer CV; returns held-out AUC, per-feature selection frequency, consensus signature, and a permutation nullplot_selection_frequency()— Lollipop plot of the most stable features fromrun_rfecv_stabilityselect_features_by_mad()— Unsupervised feature ranking by MAD across subjects (the leakage-free default selector)compute_shap_values()—shap.TreeExplainerwrapper for RandomForest / XGBoost binary classifiers; collapses to the 2-D positive-class slice (requires[shap]extra)plot_shap_summary()— SHAP beeswarm or bar summary for the top features (requires[shap]extra)relabel_features_with_genes()— Map pipeline-internal feature IDs (e.g. PRISMPG####) to gene symbols for plot labels and importance tables, with fallback to the original IDmulticlass_feature_importance()— Multi-class RF / XGBoost permutation importance with bootstrap stability scores, for descriptive marker discovery in low-replication designsplot_fold_change_pca()— PCA of per-subject fold-changes by groupplot_roc_curve()— ROC curve from a single classification result (with per-fold mean +/- SD band)plot_roc_comparison()— Overlay ROC curves from multiple methods
regression.py
run_elasticnet_regression()— Nested cross-validated ElasticNet regression for continuous outcomes under an honest outer CV; returns held-out R2/RMSE/Spearman, per-feature selection frequency, consensus signature, and a permutation nullplot_regression_scatter()— Predicted-vs-true scatter plot fromrun_elasticnet_regression, with a 1:1 reference line and R2/Spearman/permutation-p annotated
marker_discovery.py
method_specificity_score()— Per-(protein, group) descriptive marker score: group mean, distance from the second-best group (delta_top), specificity vs across-group median, and rankinter_vs_intra_group_variance()— Per-protein ratio of variance across group means to mean within-group variance; descriptive complement to ANOVA when n per group is too smallcluster_proteins_kmeans()— K-means clustering of proteins over samples with silhouette-driven k selection; supports per-protein z-score for shape-based clustering
multivariate.py
permanova()— Anderson 2001 PERMANOVA on a sample-by-sample distance matrix with label permutation for significance; supports euclidean, braycurtis, cosine, correlation, and cityblock metrics
validation.py
validate_metadata_data_consistency()— Check metadata matches data columnsenhanced_sample_processing()— Sample processing with validationgenerate_sample_matching_diagnostic_report()— Detailed mismatch diagnosticsSampleMatchingError— Exception for sample matching failuresControlSampleError— Exception for control sample configuration issues
export.py
export_complete_analysis()— Full export: data + config + resultsexport_analysis_results()— Export normalized data + differential resultsexport_timestamped_config()— Save analysis config with timestampcreate_config_dict_from_notebook_vars()— Build config dict from notebook variablesexport_significant_proteins_summary()— Export significant results summaryexport_results()— General-purpose result export
See Also
- User Guide -- Index of topic-focused recipe pages under
docs/ - Tutorial notebook -- End-to-end workflow on the bundled example dataset
- CLAUDE.md — Project conventions and data prep patterns
Metadata
Release files for proteomics-toolkit 26.9.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| proteomics_toolkit-26.9.0.tar.gz | 276.5 kB | With provenance | Details for proteomics_toolkit-26.9.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| proteomics_toolkit-26.9.0-py3-none-any.whl | Python 3 | none | any | Details for proteomics_toolkit-26.9.0-py3-none-any.whl |
Total release size: 502.6 kB
Release files / proteomics_toolkit-26.9.0.tar.gz
| Download URL | proteomics_toolkit-26.9.0.tar.gz |
|---|---|
| Size | 276.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e152d2ea03ce5072dc1419d7361b92497816a17ea894c79fb987982c84345436
|
|
BLAKE2b-256 checksum How to use checksums |
b371283e2e3afcc9705fbb89a74a37ca59a9abc7d36ddfc2c0dd41bf3f82d2c7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logRelease files / proteomics_toolkit-26.9.0-py3-none-any.whl
| Download URL | proteomics_toolkit-26.9.0-py3-none-any.whl |
|---|---|
| Size | 226.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e6c7b6a5d51f4c1cc8cb716b137de7de9182b1bc2e3a45d46d50ad5f53a22d5f
|
|
BLAKE2b-256 checksum How to use checksums |
2e9ad4929b2c9ec0446303804b26db301d450b586eeaed4135e73ef8c9ec992e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logSecurity for proteomics-toolkit 26.9.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for proteomics_toolkit-26.9.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.