Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

* `geckopy.__version__` is the installed version of geckopy.
* `cma` is a required dependency of geckopy and the extra `evotune` is removed. `import geckopy` imports `cma`.
* `enzyme_usage` reports `measured_protein`, `demanded_protein` and `demand_ratio`, the usage of the enzymes with a measured concentration divided by their measured concentrations, and the same restricted to enzymes with a usage above 1e-7 mg/gDCW (`measured_protein_active`, `demand_ratio_active`). `report_enzyme_usage` carries `demand_ratio` and `demand_ratio_active`. GECKO's `getEnzymeUsage` and `reportEnzymeUsage` give the same values.
* `enzyme_usage` reports `measured_protein`, `demanded_protein` and `demand_ratio`, the usage of the enzymes with a measured concentration divided by their measured concentrations, and the same restricted to enzymes with a usage above 1e-7 mg/gDCW (`measured_protein_active`, `demand_ratio_active`). `report_enzyme_usage` reports `demand_ratio` and `demand_ratio_active`. GECKO's `getEnzymeUsage` and `reportEnzymeUsage` give the same values.
* geckopy is licensed under the GNU General Public License v3 (GPL-3.0), as RAVEN and raven-toolbox. `LICENSE`, the `license` field and the classifier of `pyproject.toml`, and the README state it. Releases up to 4.0.0b2 were published under the MIT licence.
* `load_prot_data` takes `zeros_as_measured`: by default an abundance of 0 is read as not measured (NaN) before any filter, also with `filter_data=False`, so the mean of a protein with a zero replicate leaves the zeros out; with `True` a 0 counts as a measured replicate, is kept in the mean and is exempt from `min_val` and `cut_lowest`, as GECKO's `loadProtData` option `zerosAsMeasured`.
* `get_isozyme_coverage` reports the isozyme groups of `model.ec.rxns` that have both a measured and an unmeasured entry, and the enzymes that `zero_unmeasured_isozymes` can limit, as GECKO's `getIsozymeCoverage`.
Expand Down
16 changes: 8 additions & 8 deletions docs/evotune_kcat_tuning.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ fructose NaN 0.338 NaN -1000 ... 1
`Ptot` is measured protein content (`NaN` if not measured), each
`<met> (<rxn>)` column is a measured or fixed flux for that exchange
reaction, `evotuneRMSEweight` scales how much that row counts toward
the RMSE (usually `1`), and `source` is free text carried through for
the RMSE (usually `1`), and `source` is free text kept unchanged for
your own bookkeeping. `evotuneZeroExch.tsv` is simpler -- a `Rxns`
header, then one reaction ID per line.

Expand Down Expand Up @@ -110,7 +110,7 @@ What each knob means:
before it moves that kcat far. `custom` (curated by hand) at 0.1 is
three times more trusted than an unlabelled prediction at 0.3. This
is the one section with no universal default -- your model's own
source labels decide it.
source labels determine it.
- **`max_growth_weight`** (default `1.0`). The combined score is
`(rmse_flux + w * rmse_max_growth) / (w + 1)`. At `2`, growth-rate
error counts double against flux error -- useful when growth rate is
Expand All @@ -130,7 +130,7 @@ What each knob means:
`sigma0_log` and of the objective itself --
`tune_prior_penalty_weight` runs a candidate sweep and reports fit
cost against cross-seed reproducibility so it doesn't have to be
picked blind (see its docstring; it costs one full tuning run per
chosen without information (see its docstring; it costs one full tuning run per
candidate per seed, so treat it as an occasional calibration step,
not part of routine tuning).
- **`tie_isozymes`** (default `true`). Several ecModel reactions are
Expand Down Expand Up @@ -163,10 +163,10 @@ no tuning happens yet. The result is a table, one row per kcat or tied
group, ranked by that leverage weighted by trust: the reaction ID, how
many isozyme copies it covers, its source group, its current value,
its leverage, and `cum_leverage_share` -- the running fraction of
total leverage carried by this row and every row above it. The top
total leverage accounted for by this row and every row above it. The top
rows are what a curator should look at first, independent of whether
you ever run a tuning search: on ecYeastGEM, a handful of kcats
routinely carry the majority of what any tuning run could achieve, and
routinely account for the majority of what any tuning run could achieve, and
they tend to be implausible database values rather than genuine
biology.

Expand Down Expand Up @@ -222,7 +222,7 @@ come back in input order, and looking odd is all you get. `coverage`
(a share of flagged leverage) or `top` (a row count) then truncates the
report: on ecYeastGEM, tightening the checks themselves does not work
half as well as this does, since `coverage=0.8` cuts 2575 unfiltered
rows to 33, and the first row alone carries half.
rows to 33, and the first row alone accounts for half.

## Step 5: Tune

Expand All @@ -247,7 +247,7 @@ or an absolute leverage value, so the same setting means a comparable
thing on a different model. Pass `tunable_mask` directly instead if
you want to fix the set yourself.

`model` is mutated in place: on return, every tunable kcat carries the
`model` is mutated in place: on return, every tunable kcat has the
best value CMA-ES found, and the model's kcat constraints are already
applied -- nothing further is needed before simulating or saving it.
Beyond `target_impact_share`, the only other knobs are `popsize`
Expand Down Expand Up @@ -286,7 +286,7 @@ Before trusting a tuned kcat, check more than the final RMSE:
tools for this: `n_changed`, `fold_change`, `source_movement`.
2. **Impact share** -- `parsimony.impact_share` reports what fraction
of the total achievable improvement the changed kcats actually
carry, distinguishing "few, large, and consequential" from mere
account for, distinguishing "few, large, and consequential" from mere
sparsity. This is a different, unweighted quantity from
`screen_kcat_leverage`'s trust-weighted `cum_leverage_share`.
3. **Reproducibility.** Rerun with a different `seed`. Large
Expand Down
10 changes: 5 additions & 5 deletions docs/future_improvements.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,20 @@ fast, and so we have a list of things to retest when we upgrade.
kernels.** Even a trivial 2-worker pool with a `lambda x: x*2`
task hangs forever — no error, no timeout. The original plan for
parallel `ec_fva` called for `spawn` because it's the only context
available on Windows. Workaround: pick the context based on the
available on Windows. Workaround: select the context based on the
platform — `fork` on POSIX (which is also faster, no module
re-import), `spawn` on Windows. See `geckopy.utilities.ec_fva.ec_fva`.

- **`ruamel.yaml`'s `ScalarInt` / `ScalarFloat` leak out of cobra
YAML loads.** After loading a YAML model with cobra, attributes
like `Metabolite.charge` are ruamel scalar types (subclasses of
int/float that carry YAML formatting metadata). The ruamel
int/float that have YAML formatting metadata). The ruamel
safe-dumper has no representer for them, so writing the model
back out fails with `RepresenterError: cannot represent an
object: 0`. Workaround: walk the assembled document and coerce
everything to plain Python primitives just before writing. See
`geckopy.utilities.save_ec_model._to_native`. This bites any
YAML-to-YAML round-trip of a cobra-loaded model.
`geckopy.utilities.save_ec_model._to_native`. This affects any
write of a cobra-loaded model back to YAML.

## Deferred migrations

Expand Down Expand Up @@ -131,7 +131,7 @@ Notable items:
org-SA (output rank 5) BEFORE any-organism-no-substrate-kcat
(output rank 4). When both are available for a reaction, MATLAB
returns the org-SA result and reports its origin as 5, even though
the docstring's origin ranking implies origin 4 should win. Either
the docstring's origin ranking implies origin 4 should be kept. Either
swap the search order so any-no-subs-kcat is tried before org-SA,
or update the docstring to match the search order. geckopy
replicates the current MATLAB behavior, both within one EC number
Expand Down
8 changes: 4 additions & 4 deletions docs/gecko_light_status.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ encode the protein cost of that catalysis. There are two ways:
single shared protein pool. Each catalysed cobra reaction gets one
extra stoichiometric coefficient `MW_sum / (kcat * 3600)` against
that pool. Isozymes are not split into separate cobra reactions;
instead `apply_kcat_constraints` picks the lowest-cost isozyme
instead `apply_kcat_constraints` selects the lowest-cost isozyme
(smallest `MW_sum / kcat`) for each reaction and writes that one
coefficient. The LP stays roughly the same size as the starting GEM.
The trade-off is that you can no longer answer per-enzyme questions
Expand Down Expand Up @@ -55,7 +55,7 @@ isn't checked out next to geckopy.
| | Full | Light |
|---|---|---|
| Isozyme expansion | reactions split, one copy per isozyme with a `_EXP_<N>` suffix | cobra reactions stay singular |
| `ec.rxns` | one entry per (reaction, isozyme) pair; ids match the cobra reactions exactly | duplicate entries per isozyme; ids carry a `###_` counter prefix (e.g. `001_R2`, `002_R2`) |
| `ec.rxns` | one entry per (reaction, isozyme) pair; ids match the cobra reactions exactly | duplicate entries per isozyme; ids have a `###_` counter prefix (e.g. `001_R2`, `002_R2`) |
| Per-enzyme pseudo-metabolite `prot_<id>` | yes | no |
| Per-enzyme usage reaction `usage_prot_<id>` | yes | no |
| Shared protein pool | yes | yes (single global cost applied directly to each catalysed reaction's stoichiometry) |
Expand All @@ -66,11 +66,11 @@ isn't checked out next to geckopy.
|---|---|
| `src/geckopy/ec_model/make_ec_model.py` | dispatches stage 5 (isozyme split) and stages 9/11 (per-enzyme prot mets + usage rxns) off; calls `allocate_ec_and_coupling_light` instead of the full stages 6/8 |
| `src/geckopy/ec_model/pipeline/populate_ec.py` | `allocate_ec_and_coupling_light` builds `ec.rxns` (one row per isozyme with the `###_` prefix) and `ec.rxn_enz_mat` in one pass; `split_light_rxn_id` is the inverse |
| `src/geckopy/ec_model/pipeline/apply_kcat.py` | `_apply_kcat_constraints_light` groups ec rows by cobra reaction, picks the lowest-cost isozyme, writes `-MW_sum / (kcat * 3600)` as the `prot_pool` coefficient; same clear-then-write idempotency contract as full |
| `src/geckopy/ec_model/pipeline/apply_kcat.py` | `_apply_kcat_constraints_light` groups ec rows by cobra reaction, selects the lowest-cost isozyme, writes `-MW_sum / (kcat * 3600)` as the `prot_pool` coefficient; same clear-then-write idempotency contract as full |
| `src/geckopy/ec_model/pipeline/set_kcat.py` | the `###_` prefix is part of the id in a light model: `001_R2` matches that one row and a bare cobra id such as `R2` matches nothing |
| `src/geckopy/ec_model/enzyme.py` | `Enzyme.reactions` strips the prefix and dedupes; `Enzyme.mw` setter passes ec.rxns ids (not cobra ids) to `apply_kcat_constraints`; `_repr_html_` catches the light NotImplementedError |
| `src/geckopy/gather_kcats/fuzzy_kcat_matching.py` | strips the `###_` prefix for cobra lookups |
| `src/geckopy/gather_kcats/get_standard_kcat.py` | `_ec_rxn_to_cobra_id` handles both forms |
| `src/geckopy/gather_kcats/get_standard_kcat.py` | `_ec_rxn_to_cobra_id` accepts both forms |

Tests covering the light path:

Expand Down
10 changes: 5 additions & 5 deletions docs/internal/brenda_refresh_plan.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# BRENDA database refresh plan

> **Historical planning doc.** The implementation diverged in May 2026:
> the snapshot now ships **both** max and median per (ec, substrate,
> the snapshot now includes **both** max and median per (ec, substrate,
> organism) triple in long-format `kcat.tsv` / `sa.tsv` (not just max
> in `max_kcat.tsv` etc.). See [kcat_aggregation.md](kcat_aggregation.md)
> for the current schema and rationale.
Expand Down Expand Up @@ -285,7 +285,7 @@ tests/

- One-off: `geckopy brenda-refresh` -> three new TSVs in
`src/geckopy/data/brenda/`.
- Spot-check against the 2018 files: pick 5 well-studied ECs
- Spot-check against the 2018 files: select 5 well-studied ECs
(`1.1.1.1`, `2.7.1.40`, `3.4.21.1`, `4.2.1.1`, `1.11.1.6`),
diff max-kcat per organism, sanity-check the order of magnitude.
- Copy the three files into [GECKO/databases/](../../GECKO/databases/)
Expand Down Expand Up @@ -339,15 +339,15 @@ tests/

## Attribution

The TSV header carries `CC BY 4.0`; add a one-paragraph
The TSV header contains `CC BY 4.0`; add a one-paragraph
attribution to [README.md](../README.md) crediting BRENDA
(citation: Chang et al., Nucleic Acids Res., latest annual update)
and linking to <https://www.brenda-enzymes.org>.

## Rollout

1. Land this PR. Refresh once on commit, ship the new TSVs in the
geckopy repo, ship the one-line `loadBRENDAdata.m` patch upstream
1. Land this PR. Refresh once on commit, include the new TSVs in the
geckopy repo, submit the one-line `loadBRENDAdata.m` patch upstream
to GECKO.
2. Future refreshes: re-run `geckopy brenda-refresh` when BRENDA
publishes a new release (announcement on
Expand Down
30 changes: 0 additions & 30 deletions docs/internal/code_review.md

This file was deleted.

Loading
Loading