Skip to content

Keep gathered kcats as kcat source files, one per source - #64

Merged
edkerk merged 1 commit into
developfrom
feat/kcat-source-files
Oct 17, 2026
Merged

edkerk merged 1 commit into
developfrom
feat/kcat-source-files

Conversation

@edkerk

@edkerk edkerk commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

Gathered kcats are kept in the project as kcat source files, one per source: data/kcats/<source>.tsv. Rows are keyed by conventional reaction and enzyme set, not by model.ec.rxns, so a file stays valid when the ecModel is rebuilt and applies to full and light models alike. GECKO reads and writes the same files (SysBioChalmers/GECKO#488). This is step K1 of the plan in CompMetEng/raven-gecko-parity#134.

Gathering, one function per source

Function Gathers Notes
kcats_from_brenda Fuzzy BRENDA matching Options aggregation, force_wildcard_level, ec_rxns. It loads the BRENDA data and KEGG distances from the adapter unless brenda and phyl_dist are given, and passes the adapter on to fuzzy_kcat_matching (new adapter argument)
kcats_from_dlkcat DLKcat With run=True it writes the input and runs the Docker image; otherwise it reads an earlier output. A run records the reactions it covered in data/DLKcat_run.txt
kcats_from_okp One OpenKineticsPredictor method See below; returns (kcat_list, done)

OKP jobs per method

  • Each method keeps its own job in data/OKP_job_<method>.txt and its own result in data/OKP_output_<method>.csv; the file is okp_<method>.tsv.
  • Without a job for the method, it submits one. With a job, it fetches the result straight into the method's file, and writes the source file once the job is done.
  • The job file records which job its stored result came from. use_stored=True only uses a result of the current job, and resubmit=True removes the earlier result.
  • A result that fetch_open_kinetics_predictor stored by itself (data/OKP_output.csv) is taken over only when its job is for the method and its predictions are labelled with that method.
  • fetch_open_kinetics_predictor gets an out_file argument for this.

Writing, for all three

  • Each writes its file by default and returns the kcat list. save=False writes nothing; save_as names another file.
  • The file name and the curated guard are checked before gathering starts.
  • A subset (ec_rxns) that replaces the file logs a warning.

File functions

  • save_kcat_source(model, kcat_list, name) writes any kcat list:

    • UTF-8, LF line endings on every platform, rows sorted by every column;
    • a header with source, generator, settings (compact JSON with sorted keys and the same number text as GECKO), data version, kind and time;
    • rows with a kcat that is not a positive finite number, and rows of reactions without enzymes, are left out.

    It never writes custom.tsv, or a file whose header says kind: curated or source: custom, in any case.

  • read_kcat_source(path) reads a file without a model:

    • a byte-order mark and CRLF are fine;
    • comments and blank lines are skipped;
    • fields a spreadsheet wrapped in quotes are unwrapped;
    • numbers must be plain ASCII decimals, so 5,5 reads as missing;
    • a row with extra fields, or a duplicate or reserved column name, is an error.
  • load_kcat_source(model, name) maps rows to model.ec: by reaction and enzyme set, by enzyme set only, or by reaction only. It reports, with the file's line number:

    • rows with an invalid kcat;
    • rows that fit no reaction;
    • rows that match at least half of an enzyme set (partial matches, not applied).
  • ec_rxn_keys(model) gives the conventional reaction and enzyme set of every model.ec reaction.

All are exported from geckopy and geckopy.gather_kcats; docs/migrating_from_gecko_matlab.md lists them with their GECKO names.

Limit: for nested gene rules such as A and (B or C), the light model splits enzymes differently from the full model, so a file written from one may fit the other only partly; the unmatched rows are reported.

Tests: tests/test_kcat_sources.py:

  • keys;
  • round trips;
  • full ↔ light files;
  • matching rules;
  • reactions without enzymes;
  • the curated guard, including quoted lines and key case;
  • invalid, infinite and non-ASCII numbers;
  • the parameter JSON (the same text GECKO's test expects);
  • row order;
  • the shared fixture file that GECKO's tests read too;
  • OKP: two methods with jobs in flight, one fetched while the other is read from storage; a resubmit; ec_rxns without a new job.

The full suite passes (1,476 passed; develop has 1,447).

The functions that combine the source files into ec.kcat (collect_kcats, assign_kcats, update_kcat_sources) follow in K2.

Gathered kcats are written to data/kcats/<source>.tsv in the project,
keyed by conventional reaction and enzyme set rather than model.ec.rxns,
so a file stays valid when the ecModel is rebuilt and applies to full and
light models alike. GECKO reads and writes the same files.

- kcats_from_brenda, kcats_from_dlkcat and kcats_from_okp gather one source
  each, with that source's own options, and write its file. OKP keeps a
  job and a result per method, and only uses a stored result of the
  current job.
- save_kcat_source writes any kcat list; read_kcat_source reads a file;
  load_kcat_source maps a file to a model and reports rows with an invalid
  kcat, rows that fit no reaction, and rows that match only part of an
  enzyme set.
- ec_rxn_keys gives the conventional reaction and enzyme set of every
  model.ec reaction.
- fuzzy_kcat_matching takes an explicit adapter, and
  fetch_open_kinetics_predictor the file to store the result in.
@edkerk
edkerk force-pushed the feat/kcat-source-files branch from b2dbe52 to 9d04f8e Compare October 16, 2026 10:47
@edkerk
edkerk merged commit a2db645 into develop Oct 17, 2026
5 checks passed
@edkerk
edkerk deleted the feat/kcat-source-files branch October 17, 2026 06:29
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