Skip to content

Phase 2: proteomics reading, filtering and unit conversion - #4

Merged
edkerk merged 1 commit into
feat/py-phase1-skeletonfrom
feat/py-phase2-data
Sep 25, 2026
Merged

edkerk merged 1 commit into
feat/py-phase1-skeletonfrom
feat/py-phase2-data

Conversation

@edkerk

@edkerk edkerk commented Sep 19, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #3 — review that one first; this diff is only the new data layer.

What changed

  • src/overflow/proteomics.py — reading, the replicate quality filter,
    mmol/gDW → mg/gDW conversion, the f-factor and the protein-content
    rescaling.
  • data/uniprot.tsv — vendored molecular masses (GECKO develop4,
    same commit as the models), covering all 2928 measured proteins.
  • tests/test_proteomics.py — 31 tests.

The filter is checked against MATLAB's own output, not just described

filter_ProtData reports mean + 1.96·SD, not the replicate mean — easy
to get wrong, and invisible afterwards. The legacy
results/modelGeneration/modifiedEnzymes_*.txt files record the abundances
the MATLAB run carried forward, so they pin the filter exactly:

  • CN4: all 7 entries match to 1e-12 relative. CN4 flexibilized nothing
    before integration, so every entry is raw filter output.
  • The other conditions match exactly where the minimum-usage pass did not
    intervene, and are strictly higher in the legacy file where it did — the
    test asserts that direction, so a filter that drifted downward would fail.

Two data issues found

  1. P61830 is on two rows (the duplicated histone, one row per gene) with
    identical values. The reader collapses it and raises if duplicated rows ever
    disagree, rather than letting pandas return a DataFrame where a Series was
    expected.
  2. A missing replicate drops the protein. MATLAB's std propagates NaN, so
    such a row can never pass the variability test — the 2/3 presence check
    above it only ever fires on explicit zeros. Substituting 0 for NaN, which is
    the natural Python reading, would keep those proteins with a downward-biased
    abundance. Ported faithfully and tested.

Filter output

Condition kept removed measured mass [mg/gDW] Ptot [mg/gDW] Ptot rescaled
CN4 2107 28.0% 418 500 0.5725
CN22 2116 27.7% 429 550 0.5890
CN38 2190 25.2% 269 330 0.3524
CN75 2147 26.7% 220 270 0.2958
hGR 2004 31.6% 294 410 0.4448

Measured mass lands at 72–86% of the stated protein content, which is what a
correct unit conversion should look like. A test brackets this per condition,
so a unit slip fails loudly rather than propagating into enzyme constraints.

Deliberate fidelity choices

  • The rescaling Ptot * sumPfilt/sumP is a molar ratio in the original, not
    a mass ratio, and is ported as such. Because the filter reports
    mean + 1.96·SD, the kept fraction exceeds one and the protein content
    scales upwards — visible in the table above. Preserved rather than
    "corrected".
  • The f-factor is taken from the unfiltered means, as in the original, which
    covers more proteins than the filtered set. A test asserts it agrees with
    geckopy's calculate_f_factor to 1e-12.

filter_prot_data ports GECKO 2's filter_ProtData: a protein is kept when
it is detected in two thirds of the replicates and its relative standard
deviation is below 1, and is represented by mean + 1.96 SD rather than by
its mean. A protein with a missing replicate is dropped, because its
spread cannot be evaluated.

Abundances are converted from mmol/gDW to mg/gDW with UniProt molecular
masses, which covers every measured protein and removes the mean-mass
fallback the MATLAB implementation used for proteins outside the model.

P61830 is listed once per gene of the duplicated histone; the reader
collapses it and fails if the rows ever disagree.
@edkerk
edkerk merged commit 319dc07 into feat/py-phase1-skeleton Sep 25, 2026
3 checks passed
@edkerk
edkerk deleted the feat/py-phase2-data branch September 25, 2026 10:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant