API reference¶
Top-level conveniences (import proteoform_regions as pfr) plus the module
reference. Every public function is deterministic given its inputs; stochastic
entry points take an explicit seed (default 42 = the paper's values).
Package¶
proteoform_regions
¶
proteoform-regions.
Proteoform-aware region inference and detection-bias quantification from bottom-up proteomics peptide tables.
This package is the software implementation of the pipeline described in "Basic-peptide depletion and precursor masking in bottom-up proteomics" (Saadat et al., 2026). Modules:
schema-- canonical evidence schema, confidence tiers, pI classificationguard-- preview-input guards + sha256 manifest verificationphyschem-- pI / MW / net-charge engine (multiple pK models) + benchmarksdigest-- in-silico tryptic digestion + digestion-matched backgroundsregions-- single-linkage detected-region stitching (gap rule)parsers-- search-engine peptide-table adapters + registrystudy-- StudyConfig / cohort YAMLharmonize-- stage 1 orchestration (downloads + adapters + concat)mapping-- UniProt accession mapping + protein propertiesstats-- detection-bias models (permutation null, OR meta-analysis)pipeline-- end-to-end orchestration (map/compute/stitch/bias + run)cli-- command-line interface
FileSpec(name, url=None, sha256=None)
dataclass
¶
One raw result file belonging to a study.
name is the local filename under <data_dir>/<accession>/; url
is the retrieval source (omitted for locally-curated files); sha256
pins the expected content when known.
RunReport(out_dir, stages, artifacts=dict(), counts=dict(), parameters=dict(), generated='', proteoform_regions_version='')
dataclass
¶
Run provenance: executed stages, artifacts, row counts, parameters.
StudyConfig(dataset_accession, adapter, study_id=None, study_year='2026', parser_family=None, sample_type='', disease_context='', assay_type='LC-MS/MS', acquisition_mode='', search_engine='', representative_file_arm='primary result file', representative_file_species='Homo sapiens', publication_doi=None, files=list(), build_usi=None, extract_protein_names=True, drop_zero_intensities=False, psm_count_zero_as_none=False)
dataclass
¶
Declarative description of one dataset's peptide-evidence extraction.
build_background(protein_sequences, max_missed=2, min_len=7, max_len=60)
¶
Digestion-matched tryptic background over {accession: sequence} (S3).
Same digest protocol and same physicochemical columns as the detected peptides, so the RQ2 comparison is digestion-matched by construction.
Source code in src/proteoform_regions/pipeline.py
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | |
compute_features(evidence, mapping, proteins, calculator='bjellqvist')
¶
Peptide feature table over exactly-mapped rows (S3 feature engine).
calculator selects the peptide pI engine: bjellqvist (Biopython,
the paper's primary) or an HH table name (hh_rodwell_emboss_lineage /
hh_lehninger) for the named sensitivity analysis. Net charge at pH 7.4
always uses the Rodwell/EMBOSS HH table, as in the source.
Source code in src/proteoform_regions/pipeline.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | |
ensure_downloads(studies, data_dir, timeout=600.0)
¶
Fetch missing raw files (skip-if-exists, one retry) and return a manifest.
Source code in src/proteoform_regions/harmonize.py
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | |
load_cohort(path)
¶
Load a cohort file: a YAML list of study dicts, or a dict with 'studies'.
Source code in src/proteoform_regions/study.py
122 123 124 125 126 127 128 129 | |
map_to_uniprot(evidence, cache_dir='data/raw/uniprot_cache', snapshot_date='20260917', offline=False)
¶
Full S2 stage: normalize -> resolve -> map. Returns (mapping, proteins).
proteins carries per-protein properties (precursor pI/MW via the same
Biopython engine as peptide features); mapping carries per-row tiers,
contaminant and degeneracy flags.
Source code in src/proteoform_regions/mapping.py
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | |
normalize_accessions(raw_value)
¶
Split a raw accession field into [(base_accession, isoform_suffix), ...].
Handles fasta sp|P02768|ALBU_HUMAN prefixes, ;/,
separated groups, -2 isoform suffixes, and drops CON_/REV_
tokens. Verbatim from the publication's S2 (cell 4).
Source code in src/proteoform_regions/mapping.py
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | |
parse_study(config, data_dir)
¶
Run a study's adapter over its files; returns (canonical rows, stats).
Source code in src/proteoform_regions/parsers/__init__.py
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | |
quantify_bias(features, background, seed=st.SEED, b_perm=st.B_PERM, b_boot=st.B_BOOT, run_rq1=True)
¶
Detection-bias quantification on feature + background tables (S8).
RQ2: per-study basic-vs-rest OR (Woolf, unconditional 0.5) against each study's digestion-matched parent-protein background; inverse-variance fixed effect; DerSimonian-Laird random effects; leave-one-study-out envelope. RQ1: per-protein divergence permutation null (seed-aware).
Set run_rq1=False to skip the permutation null (it dominates runtime
on paper-scale tables: ~5,400 proteins x B=2,000 draws).
Source code in src/proteoform_regions/pipeline.py
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | |
run(studies, out_dir, stages='all', data_dir='data/raw/peptide_tables', download=True, uniprot_cache='data/raw/uniprot_cache', snapshot_date='20260917', offline=False, calculator='bjellqvist', max_missed=2, gap=REGION_GAP_AA, terminal_fraction=TERMINAL_FRACTION, min_peptides=MIN_REGION_PEPTIDES, seed=st.SEED, b_perm=st.B_PERM, b_boot=st.B_BOOT, run_rq1=True)
¶
Execute pipeline stages over a cohort, writing paper-vocabulary artifacts.
studies is a cohort YAML path or a list of StudyConfig. Artifacts
land in out_dir under the paper's data/processed/ filenames; every
run closes by writing a sha256 manifest (manifest.sha256) over its own
outputs plus a machine-readable run_report.json.
Source code in src/proteoform_regions/pipeline.py
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 | |
stitch_regions(features, mapping, precursor_sequences=None, gap=REGION_GAP_AA, terminal_fraction=TERMINAL_FRACTION, min_peptides=MIN_REGION_PEPTIDES)
¶
Detected-region inference (S4 walk): position spans -> stitched regions.
Start positions come from the mapping table (first exact-substring hit);
rows without exact mapping never reach this stage. precursor_sequences
(e.g. from the UniProt snapshot) enables region sequence / region pI/MW
columns; without it they stay null (positions and tiers are unaffected).
Source code in src/proteoform_regions/pipeline.py
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | |
Study configuration¶
proteoform_regions.study.StudyConfig(dataset_accession, adapter, study_id=None, study_year='2026', parser_family=None, sample_type='', disease_context='', assay_type='LC-MS/MS', acquisition_mode='', search_engine='', representative_file_arm='primary result file', representative_file_species='Homo sapiens', publication_doi=None, files=list(), build_usi=None, extract_protein_names=True, drop_zero_intensities=False, psm_count_zero_as_none=False)
dataclass
¶
Declarative description of one dataset's peptide-evidence extraction.
proteoform_regions.study.FileSpec(name, url=None, sha256=None)
dataclass
¶
One raw result file belonging to a study.
name is the local filename under <data_dir>/<accession>/; url
is the retrieval source (omitted for locally-curated files); sha256
pins the expected content when known.
Harmonize (stage 1)¶
proteoform_regions.harmonize
¶
Stage 1: harmonize heterogeneous peptide tables into the canonical evidence schema.
harmonize is a pure function over study configs + cached raw files: it
downloads missing files (retry-once policy, failures documented never
fabricated - the paper's S1 ensure_downloads semantics), runs each study's
adapter, and concatenates canonical-schema rows. Write-out is the caller's
job (see pipeline / cli).
ensure_downloads(studies, data_dir, timeout=600.0)
¶
Fetch missing raw files (skip-if-exists, one retry) and return a manifest.
Source code in src/proteoform_regions/harmonize.py
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | |
harmonize(studies, data_dir, download=True, extraction_date=None)
¶
Harmonize a cohort; returns (evidence DataFrame, run stats DataFrame).
The evidence frame carries exactly the 44 canonical columns; the stats frame records per-study row counts and adapter-reported counters.
Source code in src/proteoform_regions/harmonize.py
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | |
Mapping (stage 2)¶
proteoform_regions.mapping
¶
Stage 2: UniProt accession mapping and protein properties.
Logic extracted from the source publication's S2 (uniprot_mapping.ipynb):
normalize_accessionssp|/tr| prefixes, semicolon groups, isoform suffixes, CON_/REV_ drops - verbatimensure_uniprot_entrieschunked UniProtKB REST stream with per-chunk cache + dated snapshot, retry-once, 0.6 s politeness - verbatim semantics, snapshot path parameterized (no cwd-relative hack)entry_properties/contaminant_flagprotein metadata + the four contaminant rules (TRYPSIN/KERATIN/BSA/IG_CHAIN)map_peptidesexact-substring peptide->protein mapping with explicit failure tiers and NO silent drops (join-QC philosophy, review B9 part 1)
Contaminants are flagged, never dropped; degenerate peptides (one sequence mapping to >1 protein) are flagged per row for downstream ambiguity rules.
Verbatim-bug pin (divergence #32). entry_properties's reviewed
flag reproduces the publication's entryType.endswith("Swiss-Prot")
check, which is always False for real entries ("UniProtKB reviewed
(Swiss-Prot)" ends with a paren). The frozen properties table therefore
carries reviewed=False on all 5,777 rows; the package preserves this
exactly for parity (pinned by test) - use entry_type directly if you
need the review status.
contaminant_flag(accession, protein_name)
¶
First matching contaminant rule over "
Source code in src/proteoform_regions/mapping.py
193 194 195 196 197 198 199 | |
ensure_uniprot_entries(base_accessions, cache_dir='data/raw/uniprot_cache', snapshot_date='20260917', chunk_size=100, politeness_seconds=0.6, offline=False)
¶
Resolve base accessions against UniProtKB with cache + snapshot pinning.
Resolution order per chunk: dated snapshot -> per-chunk sha1-keyed cache ->
live REST (skipped when offline). The merged snapshot is (re)written so
later runs are network-free - the paper's reproducible-snapshot semantics.
Source code in src/proteoform_regions/mapping.py
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | |
entry_properties(entry)
¶
Canonical sequence, gene/name, entryType, organism, version - verbatim S2.
Source code in src/proteoform_regions/mapping.py
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | |
fetch_uniprot_chunk(accessions, timeout=120.0, retries=2)
¶
GET one UniProtKB stream chunk (accession:A OR accession:B ...).
Retry-once; a hard failure returns None (documented, never fabricated).
Source code in src/proteoform_regions/mapping.py
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | |
load_snapshot(cache_dir, snapshot_date)
¶
Load a dated snapshot as {primaryAccession: entry}; {} when absent.
Source code in src/proteoform_regions/mapping.py
126 127 128 129 130 131 | |
map_peptides(evidence, entries)
¶
Exact-substring peptide->protein mapping with explicit tiers (no silent drops).
Tiers: exact_unique / exact_multi_position on success; failures are
no_accession_in_row / accession_unmapped_in_uniprot /
not_found_in_group_sequences. Also flags isoform-suffixed rows,
contaminant hits, and degenerate peptides (sequence mapping to >1 protein).
Source code in src/proteoform_regions/mapping.py
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | |
map_to_uniprot(evidence, cache_dir='data/raw/uniprot_cache', snapshot_date='20260917', offline=False)
¶
Full S2 stage: normalize -> resolve -> map. Returns (mapping, proteins).
proteins carries per-protein properties (precursor pI/MW via the same
Biopython engine as peptide features); mapping carries per-row tiers,
contaminant and degeneracy flags.
Source code in src/proteoform_regions/mapping.py
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | |
normalize_accessions(raw_value)
¶
Split a raw accession field into [(base_accession, isoform_suffix), ...].
Handles fasta sp|P02768|ALBU_HUMAN prefixes, ;/,
separated groups, -2 isoform suffixes, and drops CON_/REV_
tokens. Verbatim from the publication's S2 (cell 4).
Source code in src/proteoform_regions/mapping.py
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | |
protein_properties_table(entries)
¶
Per-protein properties + contaminant flag + precursor pI/MW (Biopython).
Source code in src/proteoform_regions/mapping.py
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | |
Pipeline stages (3a/3b/4/8 + orchestration)¶
proteoform_regions.pipeline
¶
End-to-end orchestration: harmonize -> map -> compute -> stitch -> bias.
Each stage function is a thin, faithful composition of the stage modules
(the publication's S2-S4, S8 notebook flows), so run() reproduces the
paper's pipeline as one call:
map_to_uniprot(stage 2) accession mapping + protein propertiescompute_features(stage 3a) peptide physicochemical feature tablebuild_background(stage 3b) digestion-matched tryptic backgroundstitch_regions(stage 4) single-linkage detected-region inferencequantify_bias(stage 8) RQ1 permutation + RQ2 OR meta-analysisrunstage-selected execution + artifact writing + sha256 run manifest
Every artifact filename matches the paper's data/processed/ vocabulary;
every stochastic knob (seed, B_perm, B_boot) is a parameter with the paper's
defaults.
RunReport(out_dir, stages, artifacts=dict(), counts=dict(), parameters=dict(), generated='', proteoform_regions_version='')
dataclass
¶
Run provenance: executed stages, artifacts, row counts, parameters.
build_background(protein_sequences, max_missed=2, min_len=7, max_len=60)
¶
Digestion-matched tryptic background over {accession: sequence} (S3).
Same digest protocol and same physicochemical columns as the detected peptides, so the RQ2 comparison is digestion-matched by construction.
Source code in src/proteoform_regions/pipeline.py
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | |
compute_features(evidence, mapping, proteins, calculator='bjellqvist')
¶
Peptide feature table over exactly-mapped rows (S3 feature engine).
calculator selects the peptide pI engine: bjellqvist (Biopython,
the paper's primary) or an HH table name (hh_rodwell_emboss_lineage /
hh_lehninger) for the named sensitivity analysis. Net charge at pH 7.4
always uses the Rodwell/EMBOSS HH table, as in the source.
Source code in src/proteoform_regions/pipeline.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | |
quantify_bias(features, background, seed=st.SEED, b_perm=st.B_PERM, b_boot=st.B_BOOT, run_rq1=True)
¶
Detection-bias quantification on feature + background tables (S8).
RQ2: per-study basic-vs-rest OR (Woolf, unconditional 0.5) against each study's digestion-matched parent-protein background; inverse-variance fixed effect; DerSimonian-Laird random effects; leave-one-study-out envelope. RQ1: per-protein divergence permutation null (seed-aware).
Set run_rq1=False to skip the permutation null (it dominates runtime
on paper-scale tables: ~5,400 proteins x B=2,000 draws).
Source code in src/proteoform_regions/pipeline.py
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | |
run(studies, out_dir, stages='all', data_dir='data/raw/peptide_tables', download=True, uniprot_cache='data/raw/uniprot_cache', snapshot_date='20260917', offline=False, calculator='bjellqvist', max_missed=2, gap=REGION_GAP_AA, terminal_fraction=TERMINAL_FRACTION, min_peptides=MIN_REGION_PEPTIDES, seed=st.SEED, b_perm=st.B_PERM, b_boot=st.B_BOOT, run_rq1=True)
¶
Execute pipeline stages over a cohort, writing paper-vocabulary artifacts.
studies is a cohort YAML path or a list of StudyConfig. Artifacts
land in out_dir under the paper's data/processed/ filenames; every
run closes by writing a sha256 manifest (manifest.sha256) over its own
outputs plus a machine-readable run_report.json.
Source code in src/proteoform_regions/pipeline.py
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 | |
stitch_regions(features, mapping, precursor_sequences=None, gap=REGION_GAP_AA, terminal_fraction=TERMINAL_FRACTION, min_peptides=MIN_REGION_PEPTIDES)
¶
Detected-region inference (S4 walk): position spans -> stitched regions.
Start positions come from the mapping table (first exact-substring hit);
rows without exact mapping never reach this stage. precursor_sequences
(e.g. from the UniProt snapshot) enables region sequence / region pI/MW
columns; without it they stay null (positions and tiers are unaffected).
Source code in src/proteoform_regions/pipeline.py
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | |
Statistics¶
proteoform_regions.stats
¶
Detection-bias statistical models (Supplementary Methods Modules 4-6).
Pure, seed-aware functions extracted verbatim from the source publication's S5 (descriptive), S8 (inferential), and charge-state (J4) layers:
bh_qBenjamini-Hochberg q-valuesor_2x2/study_or2x2 OR with Woolf SE (UNCONDITIONAL max(x, 0.5) zero-cell correction on every cell)fe_summaryinverse-variance fixed effect + Q + I2dl_random_effectsDerSimonian-Laird tau2 / RE summaryloo_envelopeleave-one-study-out FE enveloperq1_permutationdigestion-matched per-protein permutation null (WITH replacement, B=2000, seed 42; two-stage global p via resampling null medians)bootstrap_class_shares/enrichment_with_cidescriptive CIstheoretical_charge_ph26KRH+N-term protonation proxy (charge-state tests)
bh_q(pvals)
¶
Benjamini-Hochberg q-values (step-up, monotone via reverse cummin).
Source code in src/proteoform_regions/stats.py
43 44 45 46 47 48 49 50 51 52 53 | |
bootstrap_class_shares(labels, n=2000, seed=SEED)
¶
Bootstrap percentile CIs for class shares of a label array (S5).
Source code in src/proteoform_regions/stats.py
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | |
dl_random_effects(table)
¶
DerSimonian-Laird random-effects summary (reported at k=10 per freeze spec).
Source code in src/proteoform_regions/stats.py
108 109 110 111 112 113 114 115 116 117 118 119 120 | |
enrichment_with_ci(detected_labels, background_labels, n=2000, seed=SEED)
¶
Enrichment (detected share / background share) with multinomial bootstrap CIs (S5).
Source code in src/proteoform_regions/stats.py
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | |
fe_summary(table)
¶
Inverse-variance fixed effect over a per-study OR table.
Requires columns log_or and se. Returns (mu, se, p, Q, I2).
Source code in src/proteoform_regions/stats.py
92 93 94 95 96 97 98 99 100 101 102 103 104 105 | |
loo_envelope(table, by='dataset_accession')
¶
Leave-one-study-out FE summary ORs -> (min, max) envelope (OR scale).
Source code in src/proteoform_regions/stats.py
123 124 125 126 127 128 129 130 | |
or_2x2(a, b, c, d)
¶
(log OR, Woolf SE) for detected-vs-background x basic-vs-rest.
a=detect&basic, b=detect&rest, c=bg&basic, d=bg&rest.
Zero-cell correction is UNCONDITIONAL: max(x, 0.5) on every cell always
(always-on Haldane-Anscombe; simpler than the conditional variant).
Source code in src/proteoform_regions/stats.py
56 57 58 59 60 61 62 63 64 65 66 | |
rq1_permutation(features, background, seed=SEED, b_perm=B_PERM, b_boot=B_BOOT, min_unique=2)
¶
H1/RQ1: per-protein median peptide-pI divergence vs digestion-matched null.
features needs (dataset_accession, mapped_accession, peptide_sequence,
peptide_pi, precursor_pi); background needs (accession, peptide_pi).
Sampling is WITH replacement from each protein's tryptic background
(multinomial bootstrap); the global null resamples the SET of per-protein
null medians. Returns observed statistic, two-sided global p, 95% null CI,
and the per-protein table with BH q.
Edge case (published): proteins with fewer background peptides than detected peptides are SKIPPED (documented absence, not corrected).
Source code in src/proteoform_regions/stats.py
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | |
study_or(det_classes, bg_classes, target='basic')
¶
Per-study OR dictionary from class label arrays.
Source code in src/proteoform_regions/stats.py
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | |
theoretical_charge_ph26(seq)
¶
Dominant-charge proxy at acidic LC pH (~2.6): count(K)+count(R)+count(H)+1 (N-term).
Upper-bound proxy; ESI charge-state distributions typically peak lower.
Source code in src/proteoform_regions/stats.py
254 255 256 257 258 259 | |
Physicochemical engine¶
proteoform_regions.physchem
¶
pI / MW / net-charge engine with multiple pK models.
Primary calculator: Biopython IsoelectricPoint (Bjellqvist pK set, with
residue-specific terminal pKas). Sensitivity calculators: vectorized 60-iteration
bisection over Henderson-Hasselbalch charge with the pyteomics Rodwell/EMBOSS and
Lehninger pK tables.
Extraction note: the notebook version configured the Henderson-Hasselbalch model
through module globals (hh_pi_configure); here the pK table is an explicit
argument. Float operations are unchanged - equivalence against the original
global-state implementation is pinned by tests/test_physchem.py (reference
implementation comparison). Golden values from the publication's frozen ExPASy
benchmark (16 sequences) live in tests/data/physchem_golden.csv.
biopython_mw(sequence)
¶
Molecular weight: Biopython average-isotopic mass (X->A replacement before calculation).
Source code in src/proteoform_regions/physchem.py
133 134 135 | |
biopython_pi(sequence)
¶
Primary pI calculator: Biopython IsoelectricPoint (Bjellqvist; X->A).
Source code in src/proteoform_regions/physchem.py
128 129 130 | |
charge_at_ph(sequences, ph=7.4, table='hh_rodwell_emboss_lineage')
¶
Net charge per unique sequence at ph (paper default: pH 7.4, Rodwell lineage).
Source code in src/proteoform_regions/physchem.py
115 116 117 118 119 120 121 122 123 124 125 | |
classify_pi(value)
¶
Pre-specified pI classification: acidic < 7.0 <= near_neutral < 7.5 <= basic.
Returns None for None/NaN input (the S3 variant of the paper's helper, which had the most defensive NaN handling of the four notebook copies).
Source code in src/proteoform_regions/schema.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | |
count_matrix(sequences)
¶
Per-ionizable-residue count vectors for a list of sequences (verbatim).
Source code in src/proteoform_regions/physchem.py
66 67 68 69 | |
fetch_expasy(sequence, timeout=60.0, retries=2)
¶
Theoretical pI/MW from live ExPASy ProtParam (network; benchmark use only).
Returns (pi, mw) floats or (None, None) on failure. Marked network-reliant: tests that use it are skipped in offline CI.
Source code in src/proteoform_regions/physchem.py
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
gravy(seq)
¶
Mean Kyte-Doolittle hydropathicity over recognized residues (None if empty).
Source code in src/proteoform_regions/physchem.py
143 144 145 146 | |
hh_charge(ph, counts, table='hh_rodwell_emboss_lineage')
¶
Net charge at ph from residue-count vectors under a pK table.
table may be a PK_TABLES key or a {'n_term','c_term','side'} dict
(the notebook's global-state configuration becomes an argument).
Source code in src/proteoform_regions/physchem.py
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | |
hh_pi_batch(sequences, table='hh_rodwell_emboss_lineage', iterations=60)
¶
Vectorized bisection pI for all sequences with the given pK table.
60 iterations of bisection on [0, 14]; convergence implicit (~14/2**60). Sign convention: pI is where charge crosses from positive (low pH) to non-positive (high pH).
Source code in src/proteoform_regions/physchem.py
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | |
peptide_features(seq)
¶
Composition features (verbatim): length, acidic/basic fractions, Cys/Met, tryptic-terminus flag, missed-cleavage count from internal KR|not-P sites.
Source code in src/proteoform_regions/physchem.py
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | |
pi_for_calculator(sequences, calculator='bjellqvist')
¶
pI per sequence under a named calculator: 'bjellqvist' (Biopython primary) or any PK_TABLES key ('hh_rodwell_emboss_lineage', 'hh_lehninger').
Source code in src/proteoform_regions/physchem.py
205 206 207 208 209 210 211 212 | |
Regions¶
proteoform_regions.regions
¶
Single-linkage detected-region stitching from peptide evidence.
Algorithm (Supplementary Methods Module 3 of the source publication):
- Sort peptide spans by start position (tuple sort: start, end, then payload).
- Walk spans in order; join a span to the current cluster when
next.start - last_member.end <= gap(paper defaultgap = 25). - Region bounds are
min(member starts)..max(member ends); the region sequence is the contiguous precursor slice between the bounds (unobserved intermediate residues included). - A region with fewer than 2 distinct member peptide sequences stays
peptide_only; >= 2 isregion_supported; a numerically consistent MW constraint window upgrades tofragment_constrained(ANL-020).
Exact-semantics note (pinned by tests). The gap check uses the END OF THE
LAST-APPENDED MEMBER, not the running maximum end of the cluster. Because spans
are sorted by start, a later-starting nested span (smaller end) becomes the
reference end for the next comparison, which can SPLIT a span that textbook
running-max single linkage would join. This is the published algorithm's exact
behavior ("D1 last-member-end"); it is intentionally preserved, not normalized.
The join condition next.start - last.end <= 25 corresponds to at most 24
unobserved residues between the last member and the next span.
confidence_label(n_unique_sequences, region_mw=None, constraint_window=None, min_peptides=MIN_REGION_PEPTIDES)
¶
Tiered region confidence with ANL-020 MW-window gating.
Returns (label, mw_constraint_applied):
peptide_only: fewer thanmin_peptidesdistinct sequences, OR an available numeric window that the region MW violates (an out-of-window region cannot exceed the evidence of its peptides).region_supported: >=min_peptidessequences and no numeric window.fragment_constrained: >=min_peptidessequences and MW inside the window.
The paper's pilots exposed no numeric windows, so every pilot region is
peptide_only/region_supported with mw_constraint_applied=False - the
unreachable path is exercised only by tests.
Source code in src/proteoform_regions/regions.py
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | |
region_bounds(cluster)
¶
(min member start, max member end) -> 1-based inclusive region bounds.
Source code in src/proteoform_regions/regions.py
73 74 75 | |
region_physchem(sequence)
¶
(pI, MW) of a region sequence (X->A; None inputs -> (None, None)).
Source code in src/proteoform_regions/regions.py
129 130 131 132 133 134 | |
region_record(study, accession, cluster, precursor_length, precursor_pi=None, precursor_mw=None, gene_name=None, precursor_sequence='', gap=REGION_GAP_AA, terminal_fraction=TERMINAL_FRACTION, min_peptides=MIN_REGION_PEPTIDES, constraint_window=None, extra_flags=None)
¶
Build one canonical region row (S4 column set) from a stitched cluster.
cluster spans are (start, end, sequence, peptide_pi, row_id) tuples, as
produced by the paper's S4 walk. extra_flags carries RQ3 UniProt-feature
flags when a feature index is supplied upstream.
Source code in src/proteoform_regions/regions.py
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | |
region_sequence(precursor_sequence, region_start, region_end)
¶
Contiguous precursor slice covering the region (1-based inclusive bounds).
Source code in src/proteoform_regions/regions.py
122 123 124 125 126 | |
stitch_spans(spans, gap=REGION_GAP_AA)
¶
Cluster sorted-by-start spans into regions via the paper's exact loop.
Each span is a tuple whose first two elements are (start, end); remaining elements are carried through untouched (the paper carries (sequence, peptide_pi, row_id)). Tuples are sorted exactly as the notebook does (lexicographic), so input order does not matter - determinism is total.
Source code in src/proteoform_regions/regions.py
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | |
terminal_flags(region_start, region_end, precursor_length, terminal_fraction=TERMINAL_FRACTION)
¶
(n_terminal_inclusive, c_terminal_inclusive) per the 10% rule.
Source code in src/proteoform_regions/regions.py
78 79 80 81 82 83 84 85 86 87 88 | |