Skip to content
Merged
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
9 changes: 3 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,13 @@ justifying a jump to 4.x. This is the first release published to PyPI.

* New: `kcat_tuning.evotune` fits `ec.kcat` to measured growth rates and
exchange fluxes with CMA-ES (`screen_kcat_leverage`, `select_tunable_mask`,
`cmaes_kcat_tuning`, `tune_prior_penalty_weight`), replacing the earlier
ABC-SMC approach. `EvotuneResult.corrections()` reports a tuning run as a
`cmaes_kcat_tuning`, `tune_prior_penalty_weight`). `EvotuneResult.corrections()` reports a tuning run as a
ranked table of what changed and why, rather than a raw kcat vector. Gated
behind the new `evotune` extra.
* New: `gather_kcats.review.review_assignment` flags kcat-assignment
problems (repeated values, EC-maximum fallback, implausible magnitude)
worth curating before a tuning run.
* `kcat_sensitivity_analysis` renamed to `kcat_tuning`, with the CMA-ES
subpackage named `evotune` rather than `bayesian` — the shipped method is
CMA-ES, not Bayesian inference.
* `kcat_sensitivity_analysis` renamed to `kcat_tuning`.
* `flexibilize_enz_concs`: the post-loop refinement now uses MATLAB's soft
±0.25% growth band instead of pinning to `exp_growth` exactly, matching
`flexibilizeEnzConcs.m`.
Expand Down Expand Up @@ -311,7 +308,7 @@ ecModel build is ported; the yeast-GEM tutorial runs end-to-end.
dedup, Complex Portal sub-complex classification, downloader hardening,
NaN-aware kcat overwrite, non-fatal DLKcat unknown-substrate handling,
`ec_fseof`/`pfba_enzymes` feasibility checks, OKP GET retries, current
PubChem SMILES property, perf hoists, BayesianParams length validation,
PubChem SMILES property, perf hoists, tuning-parameter length validation,
robust BRENDA protein lookup.
* Code review hardening — adapter decoupling: adapter-free read/inspect of
ecModels; per-parameter overrides decouple analysis functions from the
Expand Down
57 changes: 0 additions & 57 deletions docs/cmaes_vs_abc_smc.md

This file was deleted.

5 changes: 0 additions & 5 deletions docs/evotune_kcat_tuning.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,3 @@ climbing rather than reading every row. This is the tuning-time
counterpart to `review_assignment` in Step 4: that flags kcats worth
curating *before* a run; this reports which ones the run actually
changed, and how much each change is worth trusting.

## Where to go from here

- `docs/cmaes_vs_abc_smc.md` -- why this method is CMA-ES rather than
the ABC-SMC sampler used elsewhere for the same problem.
2 changes: 1 addition & 1 deletion docs/internal/ravenpy_split_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ template generator, organism metadata) carrying an ec-specific *payload*.
`org_name`, `c_source`, `bio_rxn`, and the data-source sub-schemas `KeggParams`,
`UniprotParams`, `ComplexParams`.
- **ec-specific → geckopy**: `sigma`, `p_tot`, `f`, `gr_exp`, `enzyme_comp`, and the
`BayesianParams` / `OkpParams` (kcat tuning / prediction) sub-schemas.
`EvotuneParams` / `OkpParams` (kcat tuning / prediction) sub-schemas.

Cleanest design: a `ravenpy` base adapter/params, subclassed in geckopy to add the
enzyme parameters. This also fixes a coupling smell flagged in the code review — many
Expand Down
7 changes: 1 addition & 6 deletions docs/migrating_from_gecko_matlab.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,7 @@ Each row maps a MATLAB function to its geckopy equivalent. The
| `sigmaFitter` | `fit_sigma` | **`[3→4]`** Returns the model fitted to the **optimal** sigma (GECKO 3 returned the last trial value, sigma = 1.0). **`[Py]`** Renamed; `sigma_fitter` kept as deprecated alias. Returns a `SigmaFitterResult`. |
| `findMaxValue` | `find_max_value` | **`[3→4]`** Wildcard EC branch matches real codes. |
| `truncateValues` | `truncate_values` | — |
| *(none)* | `kcat_tuning.evotune.cmaes_kcat_tuning` + helpers | **`[Py]`** Fits kcats to experimental flux/growth data with CMA-ES rather than MATLAB's ABC-SMC `bayesianSensitivityTuning`; see [evotune_kcat_tuning.md](evotune_kcat_tuning.md) and [cmaes_vs_abc_smc.md](cmaes_vs_abc_smc.md). |
| `bayesianSensitivityTuning` + helpers | *(not ported)* | MATLAB's ABC-SMC sampler itself is not ported; geckopy uses CMA-ES instead (see above). |
| `cmaesKcatTuning` + helpers | `kcat_tuning.evotune.cmaes_kcat_tuning` + helpers | Fits kcats to experimental flux/growth data with CMA-ES; see [evotune_kcat_tuning.md](evotune_kcat_tuning.md). |

### 5.5 Limit proteins (`src/geckomat/limit_proteins`)

Expand Down Expand Up @@ -448,10 +447,6 @@ for the MATLAB-side items the port surfaced.

### Not yet in geckopy

- **ABC-SMC kcat tuning** (`bayesianSensitivityTuning` + helpers).
geckopy fits kcats to experimental data with CMA-ES instead; see
[evotune_kcat_tuning.md](evotune_kcat_tuning.md) and
[cmaes_vs_abc_smc.md](cmaes_vs_abc_smc.md).
- **`plotEcFVA`** — Python users plot from the `ec_fva` DataFrame
with matplotlib / seaborn directly.

Expand Down
4 changes: 2 additions & 2 deletions src/geckopy/adapter/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

``KeggParams``, ``UniprotParams``, ``ComplexParams``, and the core fields
of ``ModelParameters`` mirror the ``obj.params.*`` fields set in GECKO
MATLAB's adapter template. ``BayesianParams`` and ``OkpParams`` are
geckopy-only extensions with no MATLAB equivalent.
MATLAB's adapter template. ``EvotuneParams`` holds the evotune settings; ``OkpParams`` is a
geckopy-only extension with no MATLAB equivalent.

Ported from GECKO MATLAB: src/geckomat/model_adapter/adapterTemplate.m.
"""
Expand Down
33 changes: 10 additions & 23 deletions src/geckopy/kcat_tuning/evotune/data.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,15 @@
"""Load experimental data for evotune (CMA-ES) kcat tuning.

Ported from GECKO MATLAB:
src/geckomat/kcat_sensitivity_analysis/Bayesian/loadBayesianData.m.

MATLAB's ``loadBayesianData`` loads ``bayesianFluxData.tsv`` and
``bayesianMaxGrowth.tsv`` (renamed here to ``evotuneFluxData.tsv`` and
``evotuneMaxGrowth.tsv``) through the *same* ``loadFluxData`` parser used
for regular flux data (verified against ``develop4``'s current source,
not assumed) -- both files share the identical
``Condition Ptot grRate <met> (<rxn>) ... evotuneRMSEweight source``
column layout. geckopy already has that parser as
:func:`~geckopy.databases.flux_data.load_flux_data`, so both files reuse
it unchanged; only ``evotuneZeroExch.tsv`` (a single ``Rxns`` id column)
needs a loader of its own.

Unlike MATLAB -- which treats a missing/unreadable file as `[]` via a
try/catch inside ``loadFluxData`` -- all three files are treated
uniformly here as optional: a missing file yields ``None`` (or an empty
list for ``zero_flux``), never an exception. This also sidesteps a bug
flagged in the MATLAB review (``REVIEW.md`` #3): there, only the
``fluxData`` field was null-guarded before ``.biomass`` was attached,
while ``maxGrate`` wasn't, so a missing ``evotuneMaxGrowth.tsv`` there
silently produced a struct with just a ``.biomass`` field instead of a
clean "absent" signal.
The flux and max-growth files, ``evotuneFluxData.tsv`` and
``evotuneMaxGrowth.tsv``, share the column layout
``Condition Ptot grRate <met> (<rxn>) ... evotuneRMSEweight source`` with
regular flux data, so both reuse
:func:`~geckopy.databases.flux_data.load_flux_data` unchanged; only
``evotuneZeroExch.tsv`` (a single ``Rxns`` id column) needs a loader of
its own.

All three files are optional: a missing file yields ``None`` (or an empty
list for ``zero_flux``), never an exception.
"""
from __future__ import annotations

Expand Down
46 changes: 14 additions & 32 deletions src/geckopy/kcat_tuning/evotune/distance.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,18 @@
"""Carbon- and condition-weighted RMSE distance for evotune kcat tuning.

Ported from GECKO MATLAB:
src/geckomat/kcat_sensitivity_analysis/Bayesian/abc_max.m (the
``rmsecal`` helper's RMSE half; verified against ``develop4``'s
current source). :mod:`.simulate` does the FBA half -- this module is
pure numpy (plus one small model-reading helper for the carbon
weights) so the RMSE math is directly testable against hand-computed
expected values, no ``EcModel``/FBA involved.

Two MATLAB behaviours are intentionally *not* ported, per
``REVIEW.md``'s findings against ``develop4``:

- ``addCarbonNum.m`` matches the biomass reaction by the literal name
``'growth'`` (REVIEW.md #4) -- silently a no-op for any adapter that
doesn't use that exact name. Here the caller passes the real
``bio_rxn_id`` explicitly (``adapter.params.bio_rxn``) instead.
- ``rmsecal`` recomputes ``ismember(data.conds, data.exchMets)`` (and
its validation) on every inner-loop iteration despite it not
depending on the loop variable (REVIEW.md, low severity) --
:func:`dataset_rmse` builds its reaction-id-to-column lookup once.

One quirk *is* ported deliberately, because it changes what the RMSE
actually measures: MATLAB's ``ecModel.excarbon(ecModel.excarbon == 0)
= 1`` clamps *every* zero-carbon exchange metabolite (O2, water, ...)
up to a carbon weight of 1, not 0 -- so those reactions' flux
mismatches still count toward the RMSE at unit weight rather than
being silently zeroed out of it. See :func:`compute_excarbon`.
:mod:`.simulate` does the FBA half; this module is pure numpy (plus one
small model-reading helper for the carbon weights) so the RMSE math is
directly testable against hand-computed expected values, no
``EcModel``/FBA involved.

The biomass reaction is passed explicitly as ``bio_rxn_id``
(``adapter.params.bio_rxn``) rather than matched by a literal name, and
:func:`dataset_rmse` builds its reaction-id-to-column lookup once.

Every zero-carbon exchange metabolite (O2, water, ...) is clamped up to
a carbon weight of 1, not 0, so those reactions' flux mismatches still
count toward the RMSE at unit weight rather than being zeroed out of it.
See :func:`compute_excarbon`.
"""
from __future__ import annotations

Expand Down Expand Up @@ -193,7 +180,7 @@ def evotune_distance(
penalty: float = INFEASIBLE_PENALTY,
max_growth_weight: float = 1.0,
) -> tuple[float, dict[str, np.ndarray]]:
"""Combine both datasets' RMSE into one score, per ``abc_max.m``.
"""Combine both datasets' RMSE into one score.

``flux_sims`` must be given (non-``None``) iff ``evotune_data.flux_data``
is not ``None``, and likewise for ``max_grate_sims`` /
Expand All @@ -211,11 +198,6 @@ def evotune_distance(
the max-growth set is where the carbon-source diversity lives,
while 30 of the 33 flux conditions are glucose.

This is deliberately not MATLAB's convention. ``abc_max.m``
applies ``weights = [maxGrowthWeight, 1]`` to
``[rmse_flux, rmse_maxGrate]``, so there the same field scales
the *flux* term. **A run reproducing MATLAB must pass 0.5
here** to match its ``maxGrowthWeight = 2``.

Returns
-------
Expand Down
5 changes: 0 additions & 5 deletions src/geckopy/kcat_tuning/evotune/priors.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
"""Source classification and prior widths for evotune kcat tuning.

Ported from GECKO MATLAB:
src/geckomat/kcat_sensitivity_analysis/Bayesian/bayesianSensitivityTuning.m
(the ``kcatSourceIdx``/``sigma0log`` construction). Verified against
``develop4``'s current source.
"""
from __future__ import annotations

Expand Down
8 changes: 1 addition & 7 deletions src/geckopy/kcat_tuning/evotune/simulate.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
"""FBA simulation half of the evotune kcat tuning distance function.

Ported from GECKO MATLAB:
src/geckomat/kcat_sensitivity_analysis/Bayesian/abc_max.m (the
``rmsecal`` helper's simulate-and-measure loop). Verified against
``develop4``'s current source, not the (superseded, per its own
``REVIEW.md``) ``fix/bayesianTuning`` branch.

This module only does the FBA half: given an already kcat-constrained
``EcModel`` and one :class:`~geckopy.databases.flux_data.FluxData`
dataset (either ``evotune_data.flux_data`` or ``evotune_data.max_grate``),
Expand Down Expand Up @@ -54,7 +48,7 @@ def simulate_evotune_dataset(
) -> list[ConditionSimResult]:
"""Simulate every condition in one tuning dataset.

Mirrors ``abc_max.m``'s ``rmsecal`` FBA half:
The steps are:

1. Every exchange reaction that appears as a *condition name*
anywhere in ``flux_data.conds`` (matched by name against
Expand Down
5 changes: 1 addition & 4 deletions tests/test_evotune_simulate_distance.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,10 +398,7 @@ def test_evotune_distance_combines_both_datasets(tmp_path):

def test_evotune_distance_max_growth_weight_scales_the_max_growth_term(tmp_path):
"""``max_growth_weight`` scales the max-growth term, so 2 makes the
eight max-growth conditions count double against the 33 flux ones.

MATLAB's ``abc_max.m`` weights the flux term with the same field,
so reproducing its ``maxGrowthWeight = 2`` needs 0.5 here."""
eight max-growth conditions count double against the 33 flux ones."""
adapter = _adapter(tmp_path)
model = _build_toy(adapter)
flux_data = _flux_data(ethanol_grrate=20.0)
Expand Down
8 changes: 2 additions & 6 deletions tutorials/full_ecModel/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,12 +258,8 @@
f"final growth rate: {final_growth:.4f}")

# %% [markdown]
# Note: `bayesianSensitivityTuning` (the ABC-SMC variant introduced
# in GECKO 3.3.0) is not ported; geckopy fits kcats to experimental
# data with CMA-ES instead (see docs/evotune_kcat_tuning.md),
# not wired into this protocol walkthrough. The MATLAB tutorial also
# skips it here; the maintained ecYeastGEM in the yeast-GEM repository
# uses it instead.
# Note: fitting kcats to experimental data with CMA-ES (see
# docs/evotune_kcat_tuning.md) is not part of this protocol walkthrough.

# %% [markdown]
# **STEP 45-51** Curate kcat values based on the tuning result.
Expand Down
Loading