From 4da2d0b7f7e502eee9c7cde9aceea6bd5c5b81c4 Mon Sep 17 00:00:00 2001 From: Eduard Kerkhoven Date: Wed, 28 Oct 2026 15:40:11 +0100 Subject: [PATCH 1/4] ci: test on Python 3.14 and 3.15 --- .github/workflows/test.yml | 2 +- pyproject.toml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ef078fc..8a3ce8d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,7 +21,7 @@ jobs: # Full Python range on Linux; a single Python on macOS/Windows to catch # OS-specific issues at low runner cost. os: [ubuntu-latest] - python-version: ["3.11", "3.12", "3.13"] + python-version: ["3.11", "3.12", "3.13", "3.14", "3.15"] include: - { os: macos-latest, python-version: "3.12" } - { os: windows-latest, python-version: "3.12" } diff --git a/pyproject.toml b/pyproject.toml index bbaa3f3..444468e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,8 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Programming Language :: Python :: 3.15", "Topic :: Scientific/Engineering :: Bio-Informatics", ] dependencies = [ From 554ea301d8fc2086383ce5de4aa6dc55b282ed9d Mon Sep 17 00:00:00 2001 From: Eduard Kerkhoven Date: Wed, 28 Oct 2026 15:47:24 +0100 Subject: [PATCH 2/4] ci: install GLPK headers for the Python 3.15 swiglpk source build --- .github/workflows/test.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8a3ce8d..fb6df95 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,6 +35,11 @@ jobs: cache: pip cache-dependency-path: pyproject.toml + # swiglpk (a cobra/optlang dependency) publishes no Python 3.15 wheel, so pip + # builds it from source, which needs the GLPK headers and SWIG. + - name: Install GLPK build dependencies + if: matrix.python-version == '3.15' + run: sudo apt-get update && sudo apt-get install -y libglpk-dev swig - name: Install run: pip install -e ".[dev,evotune]" From b5489555f629b98252de03357f0bffeef452380d Mon Sep 17 00:00:00 2001 From: Eduard Kerkhoven Date: Fri, 30 Oct 2026 17:14:35 +0100 Subject: [PATCH 3/4] Remove the references to the retired Bayesian kcat tuning (#73) --- CHANGELOG.md | 9 ++-- docs/cmaes_vs_abc_smc.md | 57 --------------------- docs/evotune_kcat_tuning.md | 5 -- docs/internal/ravenpy_split_report.md | 2 +- docs/migrating_from_gecko_matlab.md | 7 +-- src/geckopy/adapter/params.py | 4 +- src/geckopy/kcat_tuning/evotune/data.py | 33 ++++-------- src/geckopy/kcat_tuning/evotune/distance.py | 46 +++++------------ src/geckopy/kcat_tuning/evotune/priors.py | 5 -- src/geckopy/kcat_tuning/evotune/simulate.py | 8 +-- tests/test_evotune_simulate_distance.py | 5 +- tutorials/full_ecModel/protocol.py | 8 +-- 12 files changed, 35 insertions(+), 154 deletions(-) delete mode 100644 docs/cmaes_vs_abc_smc.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 58ac5b7..018c85a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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`. @@ -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 diff --git a/docs/cmaes_vs_abc_smc.md b/docs/cmaes_vs_abc_smc.md deleted file mode 100644 index 7fbe57c..0000000 --- a/docs/cmaes_vs_abc_smc.md +++ /dev/null @@ -1,57 +0,0 @@ -# Why this package tunes kcats with CMA-ES, not ABC-SMC - -DLKcat's own Bayesian approach to kcat tuning implements ABC-SMC -(Approximate Bayesian Computation, Sequential Monte Carlo) -- -[SysBioChalmers/DLKcat/BayesianApproach](https://github.com/SysBioChalmers/DLKcat/tree/master/BayesianApproach). -geckopy's `kcat_tuning.evotune` module ported that -approach faithfully and tested it side by side with a plain optimiser, -CMA-ES, on the same objective, the same screened parameter set, and -the same experimental data (ecYeastGEM, 41 conditions). CMA-ES won on -every criterion that was checked, so it is what this package ships. - -## What ABC-SMC does, and why that's the wrong tool here - -ABC-SMC is a sampler: each generation it draws a batch of candidate -kcat vectors from a proposal distribution, scores them, and keeps the -best fraction to seed the next generation's proposals. That machinery --- a posterior approximation, a sample schedule, truncation selection --- earns its keep when the goal is a *distribution* over plausible -parameter values, and the model is cheap enough to sample densely -across the whole parameter space. - -Once a screen has reduced the problem to the kcats the data can -actually inform (a few dozen to a few hundred, out of thousands), that -premise stops holding. There's no longer a broad space to sample -across, and each evaluation is expensive (an FBA solve per condition). -At that point the problem is a direct search for the best-fitting -vector -- exactly what an optimiser is for, and exactly what ABC-SMC -is not. - -## What the comparison showed - -Same model, same 112-parameter screen, same objective, three seeds -each: - -| | distance | spread across seeds | -|---|---|---| -| ABC-SMC | 0.9156 | +/- 0.0549 | -| **CMA-ES** | **0.7974** | **+/- 0.0048** | - -CMA-ES fits better by 3.7 standard errors, with a spread more than ten -times tighter. The gap isn't just fit quality -- it's whether an -individual tuned kcat means anything. Both methods leave most kcats on -flat directions the data can't pin down, but ABC-SMC's posterior -sampling wanders across the whole flat region: across three ABC-SMC -seeds, lanosterol synthase (the single highest-leverage kcat in the -model) took values of 0.338, 20.3, and 0.0781 1/s -- a 260-fold spread, -at distances differing by 0.009. A number that unstable cannot be -reported as a finding. - -CMA-ES doesn't remove flat directions -- nothing can, they're a -property of the data, not the search method -- but a direct optimiser -converges to one point per flat direction instead of sampling across -it, and `prior_penalty_weight` (a Tikhonov-style penalty on moving away -from the prior, weighted by how much each source is trusted) picks out -which point: see `docs/evotune_kcat_tuning.md` for how that combines -with `screen_kcat_leverage`/`select_tunable_mask` into the method this -package actually recommends. diff --git a/docs/evotune_kcat_tuning.md b/docs/evotune_kcat_tuning.md index 94a6a40..f8305e6 100644 --- a/docs/evotune_kcat_tuning.md +++ b/docs/evotune_kcat_tuning.md @@ -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. diff --git a/docs/internal/ravenpy_split_report.md b/docs/internal/ravenpy_split_report.md index da832b9..15f9ca0 100644 --- a/docs/internal/ravenpy_split_report.md +++ b/docs/internal/ravenpy_split_report.md @@ -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 diff --git a/docs/migrating_from_gecko_matlab.md b/docs/migrating_from_gecko_matlab.md index 2683fd7..053d64f 100644 --- a/docs/migrating_from_gecko_matlab.md +++ b/docs/migrating_from_gecko_matlab.md @@ -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`) @@ -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. diff --git a/src/geckopy/adapter/params.py b/src/geckopy/adapter/params.py index becd688..3db7ae8 100644 --- a/src/geckopy/adapter/params.py +++ b/src/geckopy/adapter/params.py @@ -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. """ diff --git a/src/geckopy/kcat_tuning/evotune/data.py b/src/geckopy/kcat_tuning/evotune/data.py index 6ecf36c..75d03ec 100644 --- a/src/geckopy/kcat_tuning/evotune/data.py +++ b/src/geckopy/kcat_tuning/evotune/data.py @@ -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 () ... 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 () ... 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 diff --git a/src/geckopy/kcat_tuning/evotune/distance.py b/src/geckopy/kcat_tuning/evotune/distance.py index 410935f..f6cc757 100644 --- a/src/geckopy/kcat_tuning/evotune/distance.py +++ b/src/geckopy/kcat_tuning/evotune/distance.py @@ -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 @@ -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`` / @@ -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 ------- diff --git a/src/geckopy/kcat_tuning/evotune/priors.py b/src/geckopy/kcat_tuning/evotune/priors.py index 19f1e61..caeb082 100644 --- a/src/geckopy/kcat_tuning/evotune/priors.py +++ b/src/geckopy/kcat_tuning/evotune/priors.py @@ -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 diff --git a/src/geckopy/kcat_tuning/evotune/simulate.py b/src/geckopy/kcat_tuning/evotune/simulate.py index 0117c06..d9b40bd 100644 --- a/src/geckopy/kcat_tuning/evotune/simulate.py +++ b/src/geckopy/kcat_tuning/evotune/simulate.py @@ -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``), @@ -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 diff --git a/tests/test_evotune_simulate_distance.py b/tests/test_evotune_simulate_distance.py index bef6404..08f2161 100644 --- a/tests/test_evotune_simulate_distance.py +++ b/tests/test_evotune_simulate_distance.py @@ -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) diff --git a/tutorials/full_ecModel/protocol.py b/tutorials/full_ecModel/protocol.py index 99e6649..eec6b13 100644 --- a/tutorials/full_ecModel/protocol.py +++ b/tutorials/full_ecModel/protocol.py @@ -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. From 576ea9f6f83e8612479647a8afba83c7de18df87 Mon Sep 17 00:00:00 2001 From: Eduard Kerkhoven Date: Mon, 2 Nov 2026 22:24:26 +0100 Subject: [PATCH 4/4] Fix the ruff findings: unused imports, an unused variable, a lambda assignment and a missing final newline --- examples/ecTestGEM/adapter.py | 2 +- src/geckopy/gather_kcats/kcat_assignment.py | 4 +++- src/geckopy/gather_kcats/kcat_sources.py | 1 - tests/test_adapter.py | 1 - tests/test_conc_control_coeffs_shadow.py | 1 - tests/test_parity_fixes_g1a.py | 1 - tests/test_review_fixes_r1p.py | 1 - 7 files changed, 4 insertions(+), 7 deletions(-) diff --git a/examples/ecTestGEM/adapter.py b/examples/ecTestGEM/adapter.py index 13d2ef4..b914e97 100644 --- a/examples/ecTestGEM/adapter.py +++ b/examples/ecTestGEM/adapter.py @@ -21,4 +21,4 @@ def get_spontaneous_reactions(self, model: "cobra.Model") -> list[str]: # reordering by cobrapy's SBML parser. if "R4" in {r.id for r in model.reactions}: return ["R4"] - return [] \ No newline at end of file + return [] diff --git a/src/geckopy/gather_kcats/kcat_assignment.py b/src/geckopy/gather_kcats/kcat_assignment.py index 99aa80a..ad6108e 100644 --- a/src/geckopy/gather_kcats/kcat_assignment.py +++ b/src/geckopy/gather_kcats/kcat_assignment.py @@ -416,7 +416,9 @@ def _okp_method(name: str, wanted: dict[str, Any]) -> str: def _same(a: Any, b: Any) -> bool: - norm = (lambda v: v.lower() if isinstance(v, str) else (int(v) if isinstance(v, bool) else v)) + def norm(v: Any) -> Any: + return v.lower() if isinstance(v, str) else (int(v) if isinstance(v, bool) else v) + return norm(a) == norm(b) diff --git a/src/geckopy/gather_kcats/kcat_sources.py b/src/geckopy/gather_kcats/kcat_sources.py index f3437b1..eba88db 100644 --- a/src/geckopy/gather_kcats/kcat_sources.py +++ b/src/geckopy/gather_kcats/kcat_sources.py @@ -15,7 +15,6 @@ """ from __future__ import annotations -import json import logging import math import re diff --git a/tests/test_adapter.py b/tests/test_adapter.py index 13d4537..e61723a 100644 --- a/tests/test_adapter.py +++ b/tests/test_adapter.py @@ -217,7 +217,6 @@ def _schema_leaves(model_cls, prefix=""): from pydantic import BaseModel leaves = {} - instance = model_cls.model_construct() for name, field in model_cls.model_fields.items(): key = f"{prefix}{name}" annotation = field.annotation diff --git a/tests/test_conc_control_coeffs_shadow.py b/tests/test_conc_control_coeffs_shadow.py index 2eca72e..a1da508 100644 --- a/tests/test_conc_control_coeffs_shadow.py +++ b/tests/test_conc_control_coeffs_shadow.py @@ -8,7 +8,6 @@ import sys from types import SimpleNamespace -import numpy as np import pytest from geckopy.limit_proteins import get_conc_control_coeffs diff --git a/tests/test_parity_fixes_g1a.py b/tests/test_parity_fixes_g1a.py index 4a1a5b6..5b92eb2 100644 --- a/tests/test_parity_fixes_g1a.py +++ b/tests/test_parity_fixes_g1a.py @@ -1,7 +1,6 @@ """Behaviour that follows GECKO: truncate_values ties, the detail text of a kcat source file, and the defaults of fill_kcats_from_isozymes.""" import numpy as np -import pandas as pd import pytest from geckopy.ec_model.pipeline import fill_kcats_from_isozymes, set_kcat_for_reactions diff --git a/tests/test_review_fixes_r1p.py b/tests/test_review_fixes_r1p.py index 43203b4..f3a13b2 100644 --- a/tests/test_review_fixes_r1p.py +++ b/tests/test_review_fixes_r1p.py @@ -1,5 +1,4 @@ """Edge cases of get_conc_control_coeffs, fit_sigma and the docstring of fill_kcats_from_isozymes.""" -import numpy as np import pytest from geckopy.kcat_tuning import fit_sigma