Repository navigation
Releases: CompMetEng/raven-toolbox
Release list
raven-toolbox 3.0.0b1
First beta toward 3.0, matching the upcoming MATLAB RAVEN 3.0 beta.
- keep
ftinit()as the only extraction pipeline. analysis.compare_fluxesreplacesfollow_changed— acompareFluxesport, following RAVEN
droppingfollowChanged/followFluxes/mapCompartments.comparison.compare_modelsgained EC-code / metabolite-name / equation overlap matrices,
folded fromcompareRxnsGenesMetsComps.- New:
curation.rename_model_genes, ported fromrenameModelGenes. - New:
curation.get_gene_data,download_genome_data,process_protein_fasta_file— the
genome-data cluster. - New:
manipulation.replace_metabolite, ported fromreplaceMets. - New:
gapfilling.find_leak_metabolite, ported fromfindLeakMetabolite. - New:
manipulation.remove_bad_reactions, ported fromremoveBadRxns. - New:
gapfilling.gap_report, ported fromgapReport. - New:
analysis.trace_flux_path, ported fromtraceFluxPath. - New:
analysis.get_flux_z/analyze_sampling, ported fromgetFluxZ/analyzeSampling. - New:
analysis.fit_parameters, ported fromfitParameters. - New:
utils.guess_composition, ported fromguessComposition. - New:
analysis.walk_fluxes/FluxWalker, ported fromwalkFluxes. - New:
analysis.get_min_nr_fluxes, ported fromgetMinNrFluxes. - New:
utils.generate_new_ids, ported fromgenerateNewIds. init.ftinitimplements the metabolomics production-bonus (metabolomics=,prod_weight=).init.ftinitreproducibility parameters renamed:strict_gap/canonicalare now
prove_abs_gap/resolve_ties, with corrected determinism numbers.- ftINIT task gap-filling now edits the reference model in place instead of copying it — ~23%
faster on a genome-scale extraction. - Fixed three ftINIT/task-essential bugs: a task-essential boundary default, a checkpoint
file-handle leak, and a non-finite tie-break objective. manipulation.close_modelboundary-reaction detection is now structural, matching RAVEN.manipulation.convert_to_irreversiblenow splits exchange reactions too, carries a negative
objective coefficient onto the reverse reaction, and gained an optionalrxnsrestriction.conditions.apply_conditionraises on unknown charge during charge balancing instead of
silently miscalculating.annotation.load_delta_g_csvnow always records CSV values literally, matchingdeltaGCSV.manipulation.remove_dead_end_reactionsdead-end detection is now bounds-blind, matching RAVEN.analysis.get_min_nr_fluxesno longer crashes withGurobiErrorreading fluxes from an
infeasible solve.analysis.fseofgained an explicitmin_targetscan-floor override.- Fixed six redundant-calculation hot spots:
merge_linear, batchedadd_reactionscallers,
analyse_topology,trace_flux_path,remove_dead_end_reactions,find_task_essential_reactions. random_samplingandfill_gaps_fast_lpparallelized withProcessPool.io.write_yaml_modelfixed: an infinite/NaN bound wrote as a bare word instead of the YAML
token;sort_ids=Truedropped the!!omaptag oncompartments; unknownmetaDatafields
are now preserved on write; emptygene_reaction_ruleis now dropped.read_yaml_modeltreats
a null genes/reactions/metabolites key as empty.- Parameter defaults measured and unified: BLAST/DIAMOND/HMMER threading, homology
min_align_len/evalue,get_init_model.allow_excretion. - Removed
io.export_model_to_sif— a mislabeled port of a MATLAB function that never existed.
raven-toolbox 0.4.0
A raven-gecko-parity cross-validation harness went live this release and immediately paid for itself:
six behavioural divergences from MATLAB RAVEN closed (task checking, condition application, duplicate-
reaction contraction, Excel export, ΔG loading, reaction creation), the YAML writer brought to byte-parity
with writeYAMLmodel.m, and BLAST/homology defaults matched to RAVEN's own. Also: deterministic
compartment placement, confidence-score interoperability (Thiele-Palsson, ECO), a new set_exchange_bounds
port, and merge_compartments promoted to public API and fixed.
-
convert_to_irreversiblenow carries the reaction's annotations, subsystem and notes onto the
_REVreaction. MATLAB'sconvertToIrrevcopies the per-reaction fields (eccodes,rxnMiriams,
subSystems,rxnNotes, ...) across when it splits a reversible reaction; the Python port copied only
the name and the gene rule. Downstream that silently cost the reverse reaction its EC code — in geckopy,
fill_eccodes_from_gemreturned''for every_REVreaction, fuzzy BRENDA matching then found no
kcat, and the reverse direction ended up unconstrained. -
Opt-in deterministic ftINIT extraction:
ftinit(..., strict_gap=True, canonical=True). The extraction
MILP is highly degenerate — many reaction subsets reach the same score optimum — soThreads=1+ a fixed
Seedmake the solver's choice reproducible but not unique: a different Gurobi version or platform
lands on a different optimum. Two new keyword flags, both default off so existing behaviour is
unchanged, pin it instead.strict_gapproves each step to a fixed absolute gap (0.05, below the 0.1
reaction-score granularity) in a single solve, replacing RAVEN's relative-gap escalation, whose final
near-zero-objective run otherwise accepts an arbitrary within-gap incumbent.canonicaladds a
lexicographic phase 2 over the removable reactions — hold the score objective at its optimum, minimise the
count of kept reactions, then their summed id rank — selecting the sparsest, lowest-id optimum instead of a
solver tie-break; it applies to both each extraction step and the task gap-fill (fill_tasks(..., canonical=True)). A solve that ends at the time limit with no incumbent now raises a clear error (or, for
the canonical phase, falls back to the primary optimum) rather than an opaqueAttributeErroron a null
primal. These are a reproducibility/parsimony tool, not an accuracy or a gene-essentiality fix: on
Human-GEM/DLD1 they cut the reaction-level seed-swing 125 → 34 but worsened essential-gene determinism
(5 → 19 flips) at a 3–7× build-time cost, because the sparser model is more sensitive to the residual
transport degeneracy. For reproducible essentiality, pin the solver stack instead. Measurements and the
full trade-off: docs/studies/ftinit_determinism.md. -
assign_compartmentsgap-fill: a reliable flux-based fill instead of cobra's MILP. The
universal-DB gap-fill inlocalization.certifyno longer callscobra.flux_analysis.gapfill, whose
indicator MILP, at genome scale, fails to find a valid fill in the majority of cases even when the
exact reaction that restores growth is present in the universal (it returns an incumbent its own
validation rejects, and raises rather than offering a fill). The replacement adds the candidates on a
working copy, holds biomass at the floor, runs pFBA, and returns the flux-carrying additions — sorted,
so the result does not depend on which co-optimal vertex the solver picked. A plain LP cannot have the
MILP's failure mode: a returned set is a real flux solution that reaches the floor. On single-reaction
knockout-recovery (remove an essential reaction, fill from a universal that contains it), recall is
60/60 — the exact reaction each time — vs cobra's 45 %; on realistic incomplete drafts (12% of
internal reactions dropped, many simultaneous gaps) it restores growth 12/12 vs cobra's 0/12. The universal must share the draft's
metabolite namespace: candidates are matched by id, as cobra's gapfill required, and a mismatch now
warns instead of returning[]silently. The set is flux-parsimonious (pFBA) but not guaranteed
reaction-count-minimal; the caller re-certifies with a real FBA, so no false certificate is possible. -
Deterministic, score-aligned reaction placement in
assign_compartments. The placement master
maximises a gene-localisation objective that never mentions the per-reaction placement variable, so
each reaction's compartment was a free co-optimum: the pinned solver returned it reproducibly but
arbitrarily, and reaction agreement with curated yeast-GEM was only 52.8 % (an earlier un-pinned
build happened to land ~72 %). A lexicographic second pass now fixes the gene layout to the primary
optimum, then places each reaction in the compartment its own enzymes are predicted to occupy — the
summed DeepLoc score of the reaction's genes, with a smalldefault_compartmentprior so genes-free
and score-tied reactions fall there deterministically. Yeast reaction agreement rises to 72.5 %
(1408/1943) and now rests on the localisation evidence rather than a solver tie-break; gene agreement
is unchanged (88.7 %, 716/807 — the gene layout is untouched); coherent placement fragments fewer
metabolites, so it adds fewer transports (1001 → 967); growth and blocked-fraction are unchanged;
the second solve is warm-started and adds ~4 s. Reproducible run-to-run (identical placement across
independent runs). -
diff_modelscompares grRules as logic, not text. The GPR check now DNF-expands each rule (via the
existingmanipulation.gpr_to_dnf), sorts the genes within each isozyme clause and sorts the clauses, so
operand order no longer registers as a difference:a and b==b and aanda or b==b or a. The
previous heuristic only lowercased and collapsed whitespace, so it flagged logically identical rules that
differed only in operand order. This bringsdiff_modelsin line with MATLAB RAVEN'sdiffModels
(RAVEN #686); a rule cobra cannot parse falls back to
the old string comparison, so malformed rules are still compared rather than silently equated. -
load_delta_g_csvdefaults to stamping every matched value literally, matchingdeltaGCSV
(raven-gecko-parity#16). An earlier change taught the loader to treat the ΔG side-car tables' "no
measurement" sentinel (10000000, matching yeast-GEM's owncheckrxnDirection.m) as missing rather than
a real value, defaulting to skip it. RAVEN'sdeltaGCSVhas no sentinel concept at all and stores
whatever the CSV says, verbatim, so the two implementations disagreed about whether an entity had a value
on record. The default is now literal stamping, matching RAVEN; the sentinel-skipping behaviour remains
available by passing the keyword-onlymissing_value=DELTA_G_MISSINGexplicitly. -
Wire the confidence facets together.
confidence.annotate_confidence(model, proposal=..., scores=...)
runs every applicable scorer in one call and returns{facet: reactions_scored}—equationand
gene_associationneed only the model,localizationruns only when a proposal and its scores are given
(skipped, not failed, otherwise).curation_prioritynow drops a placement a curator has settled with
mark_curatedfrom the review queue (newinclude_curated=False), so a settled reaction stops
resurfacing;include_curated=Truekeeps it. The no-SBO-terms warning now names its remedy,
raven_toolbox.annotation.add_sbo_terms(model). -
Confidence facets mapped onto the field's standard vocabulary. New
thiele_palsson_score(reaction)
derives the Thiele & Palsson 2010 reconstruction confidence score (0–4) from thegene_association
facet's evidencebasis(gpr+literature→ 3,gpr→ 2,no-gpr→ 1); every ECO evidence id used
(ECO:0000044,ECO:0000015,ECO:0000002) was checked against EBI's OLS. Cross-model validation on
Human-GEM, iYali and panAsp/pAo confirmed theequationfacet's bands are calibrated rather than
yeast-GEM-fixture artefacts (two of its three bands fire on the other models too). -
manipulation.merge_compartments/copy_to_compartmentare now public API, andmerge_compartments
no longer breaks growth. Both functions existed inmanipulation/compartments.pybut were never
imported intomanipulation/__init__.py, so neither was reachable as documented despitemigration.md
listing both as ported. Exporting them also surfaced two silent defects: any reaction left with a single
metabolite after merging was dropped — including reactions that already had one metabolite before
merging, i.e. every exchange reaction — and the merged model's objective was never carried over, so a
flattened model silently optimised to0.0. Both now match RAVEN'smergeCompartments: single-metabolite
reactions are recorded before the merge and excluded from deletion, and the objective (with its direction)
is copied onto the rebuilt model, raising a warning rather than returning a zero-objective model if every
objective-carrying reaction genuinely was removed. -
Six behavioural divergences from MATLAB RAVEN closed, found by the new
raven-gecko-parity
cross-validation harness:check_tasks/find_task_essential_reactionsnow default to RAVENcheckTasks' additive boundary
semantics (close_boundaries=False): a task is checked by relaxing metabolite balance for its declared
inputs/outputs, not by closing every exchange first. A task the model can already satisfy through its
own open boundary, without naming it, now agrees with RAVEN's feasible verdict instead of reporting
...
raven-toolbox 0.3.0
Compartment localisation and per-reaction confidence tracking, new gap-filling and flux-sampling
algorithms, ftINIT parity with RAVEN, and KEGG artefact hosting moved to the dedicated raven-data
repository.
export_for_gitcan pin the MATLAB.matvariable name. New keyword-onlyvarname, forwarded
tosave_matlab_model, so a repository that expects a specific struct name (Human-GEM expects
humanGEM) no longer has to write the.matitself. DefaultNonekeeps cobra's own fallback (the
model id), so existing callers are unaffected.- ftINIT now matches RAVEN's model preparation, solver parameters, and gap schedule. A line-by-line
review against RAVEN'sftINIT/prepINITModelfound the formulation faithfully ported, with the
real divergences concentrated in model simplification and solver/gap handling.prep_init_modelruns
both RAVEN simplifications inprepINITModelorder and broadens the exchange mask to RAVEN
getExchangeRxns' one-sided rule (any reaction with no products or no substrates) — previously only
the topological dead-end pass ran, leaving a ~10 % larger model.ftinitadopts RAVENoptimizeProb
solver parameters (Threads=1for a deterministic MILP incumbent,Presolve=2,1e-9feasibility /
optimality / integrality tolerances), nudges tiny reaction scores off zero, forces permanent essential
reactions atmin(0.99*|carried flux|, force_on)while tracking carried flux across steps, and
escalates the MIP gap per step (RAVENMILPParams/AbsMIPGaps). Newmanipulation.simplify_model
mirrors RAVEN'ssimplifyModelboolean-flag interface, addingremove_zero_interval_reactions
(deleteZeroInterval) andremove_no_flux_reactions(FVA-blocked removal,deleteMinMax).
Task-essential discovery follows RAVENcheckTasks, and task gap-fill followsftINITFillGaps. On
Human-GEM / DLD1 the prep model now matches RAVEN's sizes (ref_model10240 against RAVEN's ~10198;
mergedmin_model6959 against ~6917 — previously 11532 / 8252).allow_excretiondeliberately keeps
S*v >= 0, matching the flag's name and classic INIT rather than RAVEN'scsense 'L'; it is unused in
the default'1+1'schedule and documented inline. - Structural confidence facets:
equationandgene_association.confidencegains
score_equation_confidence(mass & charge balance, formula completeness) and
score_gene_association_confidence(GPR presence + literature corroboration), plus the public
equation_exempt/gene_association_exemptpredicates andfacet_summary. Two rules govern every
score, both forced byoverall = min(facets): a facet that does not apply to a reaction is not
written at all (an exchange reaction is imbalanced by construction, so writing1.0would make 469
never-checked yeast-GEM reactions indistinguishable from the 3617 verified ones), and0.0always means
evidence contradicts the model — never evidence is missing, which keepsoverall == 0.0a usable
filter. Exemptions are SBO-driven, never name-driven: a\bgrowth\bregex would silence the chemistry
check on "non-growth associated maintenance reaction". Validated on yeast-GEM, where the gene rubric
recovers the model's own curator-assignedConfidence Level(99.9% / 91.5% / 95.3% per band) without
ever reading it.mark_curatednow takes afacet, andclear_confidenceis exported
(design). - Fix
get_elemental_balancecrashing on an unparseable formula. A parenthesised polymer such as
(C5H8)n(glycogen, starch) makes cobra'sMetabolite.elementsreturnNone, which
check_mass_balance()turns into aValueError— so the shipped helper raised part-way through a model
instead of reporting it. A present-but-uninterpretable formula is nowunknown, which is what the
function's own contract already promised. - Fix
score_localization_confidencevetoing reactions it could not measure. A reaction whose genes are
absent from the score table was written0.0/connectivity, which underoverall = min(facets)vetoed
the whole reaction on the strength of a missing input rather than of evidence. It now abstains; a gene
that is scored but scores zero at the assigned compartment still earns a real0.0. - Fix gap-fill materialisation landing on the wrong compartment metabolite.
apply_assignment's_add_universal_reactionmatched a universal candidate's metabolite ids
verbatim against the target model instead of resolving them through the same base-id/compartment
lookup_move_reactionalready uses for relocated reactions. Wherever a draft's non-default-
compartment species only exist because a relocated reaction created them (any id scheme other
than the universal database's own), the gap-fill reaction silently materialised as a disconnected
island: the assignment's own solved objective already accounted for the correct shared node, only
the applied model was wrong. Fixed with a regression test
(test_gapfill_reuses_relocated_compartment_metabolite). - Evidence-aware transport scoring (first increment). New
localization.transport_evidenceturns
per-gene transporter evidence into the per-metabolitetransport_costmapping the assignment MILPs
already accept, so a transport is cheap when a transporter gene supports it (right substrate, right
membrane) and pays the full prior otherwise:evidence_aware_transport_cost
(cost = base·(1−evidence)),annotate_transporters(bring-your-own annotation table), and
TransporterAnnotation. Carrier-general and organism-agnostic; thehmmsearch(Pfam) /diamond
(TCDB) annotation back-ends are the next increment
(plan). - Consolidated
assign_compartmentsinto raven-toolbox. The functionality-constrained
compartment-assignment MILP — biomass/growth floor + flux gating + optional gap-fill + sound
reaction-level multi-localisation — moves from the standaloneedkerk/assignCompartmentsrepo into
localization/(asassign_compartments/apply_assignment/AssignmentProposal), coexisting with
the score-drivenpredict_localization(design). The
MATLAB port is tracked in MATLAB back-ports. - CarveFungi assignment head-to-head on its own MILP. Ran CarveFungi's own
minmax_reduction
carve-MILP (CPLEX, unmodified) with our transport-minimising term swapped into its objective, on its
real universal-DB candidate set + DeepLoc-injected scores
(study,scripts/run_carvefungi_cplex.py;
scripts/benchmark_carvefungi_milp.pyis a Gurobi re-implementation for the formulation study).
Adversarially verified (which caught and fixed a compartment-id parsing bug). Findings: adding our
transport cost yields ~1.6× fewer inter-compartment transports per reaction (41% fewer) at no
detectable assignment-accuracy cost (86.0% vs 85.5% recall; 93% identical placements). The carve's
MILP formulation is hard — neither CPLEX nor a tighter Gurobi port proves optimality — so these are
deterministic, time-budget-stable near-optimal incumbents, reported with their gaps. Also surfaced
that CarveFungi's shipped yeast localisation file is inert (RefSeq vs ORF id mismatch). - Head-to-head vs RAVEN predictLocalization + CarveFungi positioning. Benchmarked the
deterministic compartment-assignment MILP against RAVEN's stochasticpredictLocalizationon
identical yeast-GEM + DeepLoc inputs (study,
scripts/compare_predictlocalization.py+scripts/run_predictlocalization.m): on the common gene
set the MILP is ~7 pp more accurate (83.9% vs 76.8%), deterministic (vs 35% of genes flipping
between SA runs), and faster (90 s vs a multi-minute budget). Also a source-level
analysis of CarveFungi, the contemporary
carve-a-universal-model method, showing how our transport-minimising assignment differs. - Curation triage for localisation. Added
triage_localization— an optional companion to
compartment assignment that ranks the genes/reactions whose localisation is shakiest (low DeepLoc
confidence, borderline top-two margin, multi-source disagreement, no evidence, low-trust
compartment, multi-localised), each with a plain-English reason, so a curator knows where to look.
Returns aReviewReport.load_deeplocgainedkeep_raw_confidence=TrueandLocalizationScores
araw_confidencefield (per-gene normalisation otherwise discards the confidence the triage needs). - Finetuned localisation hyperparameters on the slow yeast run. Refreshed the triage
DEEPLOC_COMPARTMENT_TRUSTtable from the slow (ProtT5) data (mitochondrion 0.67 → 0.86,mmnow
trustworthy via the validated split, Golgi 0.23 → 0.01) and re-validated themin_confidencegate
(0.7 → 88.3% corroboration, 80% kept) andmembrane_threshold(0.50 is inside the optimal plateau)
in a new finetuning study
(scripts/finetune_localization_yeast.py). - Cross-species DeepLoc benchmark. Generalised the predictor benchmark to any curated model
(scripts/benchmark_deeploc.py --species {yeast,aracore,icre1355}, a per-species compartment
config) and added independent non-yeast eukaryotes. DeepLoc 2.1 generalises across kingdoms — the
chloroplast is recovered in both Arabidopsis
(AraCore, 80.3% overall, plastid 89.9%) and the
green alga Chlamydomonas (iCre1355, plastid 78%,
though algal cytosol/mito are poor on an auto-generated model). A gene-level
Human-GEM control
(`scripts/benchmark_deepl...
v0.2.0
0.2.0 — 2026-06-14
Project rename plus KEGG-reconstruction and CI improvements.
- Project renamed
raven-python→raven-toolbox. The import package is now
raven_toolbox(wasraven_python) and the repository moved to
SysBioChalmers/raven-toolbox. Update imports and anyraven-pythongit/URL
references accordingly. (#34) - De-novo KEGG query uses
hmmsearchinstead ofhmmscan.
get_kegg_model_from_sequencesnow runs onehmmsearchover the concatenated KO
library (-Zset to the profile count, so E-values and KO assignments are identical
to the previoushmmscanpath) — the faster, more parallel search direction.
ensure_kegg_hmm_libraryno longer runshmmpress(just gunzips); the published
.hmm.gzartefact is unchanged. (#32) - Domain-mode
get_kegg_model_for_organism_from_artefactsauto-resolves the
taxonomy artefact from the artefact directory, so"prokaryotes"/
"eukaryotes"no longer require an explicittaxonomy=path. (#31) - Test data no longer ships real KEGG records. The on-disk
tests/data/kegg_dumpis replaced by a session fixture that generates a fully
fictional KEGG-format dump at runtime, so no KEGG-derived data is redistributed. (#33) - Removed the visualization stub and the
[visualization]extra — an
unimplemented placeholder. (#30) - CI on Node 24 —
actions/checkout@v5,actions/setup-python@v6. (#35)
raven-python 0.1.0a1 — first alpha
First alpha release of raven-python — the Python counterpart of the RAVEN Toolbox 2, built on cobrapy. Released under the MIT license.
What's included
- De-novo reconstruction — KEGG and protein homology (BLAST / DIAMOND).
- Context-specific modeling — tINIT / ftINIT, with task-aware gap-filling and the linear-merge MILP reduction.
- Metabolic-task validation, connectivity gap-filling, HPA omics ingestion.
- Sub-cellular localisation (MILP), N-model comparison, reporter metabolites, FSEOF, flux sampling.
- I/O — cobra-standard YAML (+ GECKO
ec-*fields), SIF, RAVEN-style Excel export.
Validated against MATLAB RAVEN on Human-GEM (5 Hart2015 cell lines, Jaccard 0.975–0.980).
Not yet implemented
- Visualization (
plotting/) - Metabolomics-based scoring in tINIT / ftINIT
- Published binary release ZIPs (BLAST / DIAMOND / HMMER)
- Published KEGG data-artefact releases
MetaCyc-based reconstruction and dynamic FBA are intentionally out of scope.
Install
pip install "git+https://github.com/SysBioChalmers/raven-python.git@v0.1.0a1"Requires Python ≥ 3.11. Genome-scale (f)tINIT currently needs Gurobi; smaller work runs on GLPK.
See the README and docs/ for details.
raven-python 0.1.0
First published KEGG artefacts (kegg116).
Now available through https://github.com/SysBioChalmers/raven-data