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
6 changes: 3 additions & 3 deletions docs/kcat_aggregation.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# kcat aggregation: how far is `max` from `median` on BRENDA?

The bundled BRENDA snapshot ships **both** the per-(ec, substrate,
The BRENDA files (toolbox-assets release `brenda-2026.1-1`) carry **both** the per-(ec, substrate,
organism) max and the per-triple median of all raw measurements that
fell into the triple. They live in the same `kcat.tsv` / `sa.tsv` file
distinguished by an `aggregation` column; `load_brenda_data` splits
Expand All @@ -20,7 +20,7 @@ diffusion-limited filter in `parse_brenda_json`):
- [`scripts/kcat_aggregation_raw.py`](../scripts/kcat_aggregation_raw.py)
walks the raw JSON and answers both questions below.
- [`scripts/kcat_aggregation_compare.py`](../scripts/kcat_aggregation_compare.py)
reads only the bundled TSV (no 710 MB JSON needed) and compares
reads only the BRENDA TSV (no 710 MB JSON needed) and compares
per-EC max-of-max vs median-of-median over the pre-aggregated views.

> **3.4.21.4 (trypsin) is excluded** from these analyses: its BRENDA
Expand Down Expand Up @@ -158,5 +158,5 @@ python scripts/kcat_aggregation_raw.py # raw-JSON, both layers
python scripts/kcat_aggregation_compare.py # snapshot-only, per-EC
```

Raw-JSON takes ~6 min on the bundled snapshot (limited by 710 MB JSON
Raw-JSON takes ~6 min on the BRENDA 2026.1 dump (limited by 710 MB JSON
load via WSL2 /mnt/c); snapshot-only runs in ~10 s.
6 changes: 6 additions & 0 deletions docs/migrating_from_gecko_matlab.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,14 @@ Each row maps a MATLAB function to its geckopy equivalent. The
| `saveKcatSource`, `loadKcatSource` | `save_kcat_source`, `load_kcat_source`, `read_kcat_source` | Kcat source files: one per source, keyed by conventional reaction and enzyme set, the same file format in both tools. `load_kcat_source` maps a file to the current model and reports rows that fit no reaction. **`[Py]`** `read_kcat_source` reads a file without a model; GECKO gives the same in `loadKcatSource`'s `report.header` and `report.records`. |
| `getEcRxnKeys` | `ec_rxn_keys` | Conventional reaction and enzyme set per `ec.rxns` entry. |
| `kcatsFromECTree` | `kcats_from_ec_tree` | EC median of the BRENDA measurement table, shrunk toward the EC's 3- and 2-digit classes (weight n / (n + k)), kept as `data/kcats/ec_tree.tsv`. |
| `kcatsFromHomologs` | `kcats_from_homologs` | Identity-weighted mean of up to 10 measured homologs (DIAMOND, ≥ 40% identity, 80% coverage) on the reaction's substrate, kept as `data/kcats/homologs.tsv`. |
| `extractEnzymeSubstratePairs` | `extract_enzyme_substrate_pairs` | The enzyme–substrate pairs DLKcat and the homolog search use; geckopy also returns `met_id`. |
| `ecTreeEstimate` | `ECTree.estimate` (`geckopy.gather_kcats.ec_tree`) | The EC-tree value for one or more EC numbers. |
| `loadBrendaMeasurements` | `load_brenda_measurements` | The BRENDA measurement table (`measurements.tsv`): wild-type kcats with an EC number, after the outlier screen. |
| `fetchBrendaAsset` | `fetch_brenda_asset` | Downloads (once) the BRENDA files of the toolbox-assets release `brenda-2026.1-1` and returns their folder; used when a project has no `data/brenda`. |
| `convertCustomKcats` | `convert_custom_kcats` | `data/customKcats.tsv` to the curated source file `data/kcats/custom.tsv`, with the kcats `apply_custom_kcats` gives the ecModel. |
| `upgradeEcModel` | `upgrade_ec_model` | Turns GECKO 3 protein usage and pool reactions forward; `load_ec_model` already does this for the files it reads. |
| `upgradeGECKOproject` | `upgrade_project` (`geckopy upgrade`)| Lists, or carries out, the steps from a GECKO 3 project to the GECKO 4 layout. The adapter-class step is MATLAB only. |
| `collectKcats` | `collect_kcats` | Decides one kcat per reaction from the source files, as `[kcat_assignment]` in model_adapter.toml sets (preset `brenda_ec_tree`, the default, `gecko_median` or `gecko_classic`, or stages), without changing the model. Writes `output/<model id>_kcatDecisions.tsv`. |
| `assignKcats` | `assign_kcats` | `collect_kcats`, then sets `ec.kcat` and `ec.source` and applies the kcat constraints; replaces `merge_kcats` → `apply_kcat_list` → `apply_custom_kcats` → `fill_kcats_from_isozymes` → `assign_standard_kcat` → `apply_kcat_constraints`. In place. |
| `updateKcatSources` | `update_kcat_sources` | Gathers the source files the configuration needs that are missing, or outdated against `[kcat_sources.<name>]`; `dry_run` only reports. |
Expand Down
33 changes: 0 additions & 33 deletions hatch_build.py

This file was deleted.

11 changes: 0 additions & 11 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,6 @@ geckopy = "geckopy.cli:main"

[tool.hatch.build.targets.wheel]
packages = ["src/geckopy"]
# kcat.tsv/sa.tsv/mw.tsv/measurements.tsv are shipped xz-compressed instead -- see
# hatch_build.py and src/geckopy/databases/brenda_loader.py.
exclude = [
"src/geckopy/data/brenda/kcat.tsv",
"src/geckopy/data/brenda/sa.tsv",
"src/geckopy/data/brenda/mw.tsv",
"src/geckopy/data/brenda/measurements.tsv",
]

[tool.hatch.build.targets.wheel.hooks.custom]
path = "hatch_build.py"

[tool.pytest.ini_options]
testpaths = ["tests"]
Expand Down
8 changes: 8 additions & 0 deletions src/geckopy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
kcats_from_brenda,
kcats_from_dlkcat,
kcats_from_ec_tree,
kcats_from_homologs,
kcats_from_okp,
load_kcat_source,
merge_dlkcat_and_fuzzy_kcats, # deprecated; alias of merge_kcats
Expand Down Expand Up @@ -161,7 +162,13 @@
save_ec_model,
)

from geckopy.upgrade import convert_custom_kcats, upgrade_ec_model, upgrade_project

__all__ = [
# Upgrades
"convert_custom_kcats",
"upgrade_ec_model",
"upgrade_project",
# Adapter
"ModelAdapter",
"ModelParameters",
Expand Down Expand Up @@ -207,6 +214,7 @@
"kcats_from_brenda",
"kcats_from_dlkcat",
"kcats_from_ec_tree",
"kcats_from_homologs",
"kcats_from_okp",
"load_kcat_source",
"merge_dlkcat_and_fuzzy_kcats", # deprecated; alias of merge_kcats
Expand Down
17 changes: 9 additions & 8 deletions src/geckopy/adapter/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,16 +171,17 @@ def get_brenda_db_folder(self) -> Path:

Prefers `<project_path>/data/brenda/` (consistent with
`get_phyl_dist_path`, and writable on read-only installs), where
`geckopy brenda-refresh` writes. Falls back to the snapshot
bundled with geckopy when the project has no copy, so the
out-of-the-box flow still works. Override to point elsewhere.
`geckopy brenda-refresh` writes. Without a project copy, the files
of geckopy's BRENDA release on toolbox-assets are downloaded once
and cached (see `geckopy.databases.fetch_brenda_asset`). Override
to point elsewhere.
"""
project = self.params.path / "data" / "brenda"
if not project.is_dir():
bundled = Path(__file__).resolve().parent.parent / "data" / "brenda"
if bundled.is_dir():
return bundled
return project
if project.is_dir():
return project
from ..databases import fetch_brenda_asset

return fetch_brenda_asset()

def get_phyl_dist_path(self) -> Path:
"""Return the path to the phylogenetic distance structure file.
Expand Down
7 changes: 4 additions & 3 deletions src/geckopy/adapter/adapterParameters.tsv
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
toml_key matlab_field default description
project_format projectFormat Layout version of the project folder; upgradeGECKOproject and geckopy upgrade write 4
conv_gem convGEM Path to the conventional GEM, relative to the project folder
org_name org_name Scientific name of the organism
sigma sigma 0.5 Average enzyme saturation factor
Expand Down Expand Up @@ -32,10 +33,10 @@ okp.method okp.method "CataPro" OpenKineticsPredictor method
okp.handle_long_sequences okp.handleLongSequences "truncate" How OpenKineticsPredictor handles sequences that are too long
okp.include_similarity_columns okp.includeSimilarityColumns true Return similarity to the method's training data
okp.canonicalize_substrates okp.canonicalizeSubstrates true Canonicalize substrate SMILES before prediction
kcat_assignment.preset Kcat assignment preset: brenda_ec_tree (used when neither preset nor stages are given), gecko_median or gecko_classic
kcat_assignment.preset Kcat assignment preset: brenda_ec_tree (used when neither preset nor stages are given), ec_tree_homologs, ec_tree_okp, okp, gecko_median or gecko_classic
kcat_assignment.isozymes true Fill reactions without a kcat from their isozymes after the stages
kcat_assignment.standard true Give the remaining reactions the standard kcat
kcat_assignment.stage Stages instead of a preset: action, sources, criteria and BRENDA limits ([[kcat_assignment.stage]])
kcat_sources Settings per kcat source file, e.g. [kcat_sources.brenda] aggregation
kcat_assignment.stage Stages instead of a preset: action (select or combine), sources, criteria and BRENDA limits ([[kcat_assignment.stage]])
kcat_sources Settings per kcat source file, e.g. [kcat_sources.brenda] aggregation; [kcat_sources.okp] methods lists the OKP methods of the okp source group
matlab.make_model_anaerobic matlab.makeModelAnaerobic MATLAB function that constrains the ecModel to anaerobic growth
matlab.change_protein_biomass matlab.changeProteinBiomass MATLAB function that changes the protein content of the biomass
19 changes: 13 additions & 6 deletions src/geckopy/adapter/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,19 @@ class MatlabParams(BaseModel):

class KcatStageParams(BaseModel):
"""One ``[[kcat_assignment.stage]]``: decides each reaction that is still
open by the first listed source with a value."""
open, by the first listed source with a value (``select``) or by all
listed sources with a value, weighted by their reliability
(``combine``)."""
model_config = ConfigDict(extra="forbid")

action: Literal["select"] = Field(default="select", description="What the stage does.")
action: Literal["select", "combine"] = Field(default="select", description="What the stage does.")
sources: list[str] = Field(
min_length=1,
description=(
"Source file names (custom, dlkcat, okp_catapro, ...) and the BRENDA tiers "
"Source file names (custom, ec_tree, dlkcat, okp_catapro, ...), the OKP "
"methods of [kcat_sources.okp] as okp, and for select the BRENDA tiers "
"database_exact, database_top and database_bottom, which read brenda.tsv; "
"first listed wins."
"for select the first listed wins."
),
)
criteria: Literal["max", "min", "median", "mean"] = Field(
Expand All @@ -126,7 +129,7 @@ class KcatAssignmentParams(BaseModel):
"""How kcats are assigned from the kcat source files (``collect_kcats``)."""
model_config = ConfigDict(extra="forbid")

preset: Optional[Literal["gecko_classic", "gecko_median", "brenda_ec_tree"]] = Field(
preset: Optional[Literal["brenda_ec_tree", "ec_tree_homologs", "ec_tree_okp", "okp", "gecko_median", "gecko_classic"]] = Field(
default=None,
description=(
"Kcat assignment preset; brenda_ec_tree is used when neither a preset nor "
Expand Down Expand Up @@ -288,7 +291,7 @@ class OkpParams(BaseModel):
default="CataPro",
description=(
"Predictor method: CataPro, CatPred, CatRange, DLKcat, EITLEM, "
"KinForm-H, KinForm-L, OmniESI, OmniESI-O2DENet, TurNuP, UniKP "
"KinForm-H, KinForm-L, OmniESI, OmniESI-O2DENet, TurNup, UniKP "
"(see GET /api/v1/methods/)."
),
)
Expand All @@ -311,6 +314,10 @@ class ModelParameters(BaseModel):
model_config = ConfigDict(extra="forbid")

path: Path = Field(description="Root folder of this ecModel project")
project_format: Optional[int] = Field(
default=None,
description="Layout version of the project folder; geckopy upgrade and upgradeGECKOproject write 4.",
)
conv_gem: Path = Field(description="Path to the conventional GEM SBML file")

org_name: str = Field(description="Scientific name of the organism")
Expand Down
34 changes: 34 additions & 0 deletions src/geckopy/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,30 @@ def cmd_brenda_refresh(args: argparse.Namespace) -> int:
return 0


def cmd_upgrade(args: argparse.Namespace) -> int:
"""List, or with --apply carry out, the steps that bring a GECKO 3
project to the GECKO 4 layout (see :func:`geckopy.upgrade.upgrade_project`)."""
import pandas as pd

from .adapter import ModelAdapter
from .upgrade import upgrade_project
from .utilities.load_ec_model import load_ec_model

ec_model = None
if args.ec_model:
adapter = ModelAdapter.from_folder(args.folder)
ec_model = load_ec_model(Path(args.ec_model).resolve(), adapter=adapter)
report = upgrade_project(args.folder, dry_run=not args.apply, ec_model=ec_model)
if report.empty:
print(f"{args.folder} has the current GECKO 4 layout.")
return 0
with pd.option_context("display.max_colwidth", 120, "display.width", 200):
print(report.to_string(index=False))
if not args.apply and (report["status"] == "to do").any():
print("Run geckopy upgrade with --apply to carry out the steps; originals go to legacy/<date>/.")
return 0


def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(
prog="geckopy", description="Command-line interface for geckopy."
Expand Down Expand Up @@ -190,6 +214,16 @@ def main(argv: list[str] | None = None) -> int:
)
kegg_parser.set_defaults(func=cmd_kegg_download)

upgrade_parser = sub.add_parser(
"upgrade", help="Bring a GECKO 3 project to the GECKO 4 layout (a dry run without --apply)"
)
upgrade_parser.add_argument("folder", help="Project folder")
upgrade_parser.add_argument("--apply", action="store_true", help="Carry out the steps")
upgrade_parser.add_argument(
"--ec-model", help="The full ecModel (YAML) the custom kcats and stored predictions are for",
)
upgrade_parser.set_defaults(func=cmd_upgrade)

args = parser.parse_args(argv)
return args.func(args)

Expand Down
Loading
Loading