Repository navigation
fix: quote YAML 1.1 booleans, fix replaceMets, and align task lists, gene pruning and YAML floats with raven-toolbox - #11
Merged
Conversation
needsQuote now quotes y, n, yes, no, on and off in any case, which YAML 1.1 loaders such as PyYAML read as booleans. This matches the quoting of write_yaml_model in raven-toolbox (CompMetEng/raven-toolbox#178). #10
Contributor
Function test results432 tests 425 ✅ 1m 57s ⏱️ Results for commit 875e45b. ♻️ This comment has been updated with latest results. |
…es header case, keeps empty CHANGED bounds as NaN
… read back exactly
… that is left By name, replaceMets deletes the replacement's row and keeps the renamed replaced metabolite. The ids it passed to the final contractModel call (repMetIds) were captured from the replacement only, so after the deletion none of them was found, repIdx was empty and contractModel(model,'mets',[]) checked every reaction. Duplicate reactions that do not involve the merged metabolite were merged as well. repMetIds now also holds the id of the replaced metabolite, so the restriction follows whichever of the two rows survives, and an empty list no longer reaches contractModel. Tests: unrelated duplicate reactions survive a merge by name and by id, and the new duplicate is still contracted.
edkerk
added a commit
to CompMetEng/raven-gecko-parity
that referenced
this pull request
Oct 21, 2026
New scenarios: remove_low_score_genes_ties_smallyeast, task_list_edge_cases and yaml_float_digits_smallyeast. The task-list scenarios compare an empty CHANGED bound as NaN. Ledger notes for replaceMets, removeLowScoreGenes, parseTaskList, checkTasks, writeYAMLmodel, exportForGit and isDnfGrRule now say what CompMetEng/RAVEN#11 and CompMetEng/raven-toolbox#181 change.
edkerk
added a commit
to CompMetEng/raven-gecko-parity
that referenced
this pull request
Oct 21, 2026
…otes for the parity decisions (#139) * fix: name the solver of min_nr_fluxes_toy instead of requesting scip The MATLAB side called setRavenSolver('scip'), which RAVEN supports on Linux only if SCIP was compiled by hand, so the scenario ended in ERROR (no result from matlab) in every nightly. It now takes matlab_solver and python_solver from scenario.yml (gurobi, as in task_checking_smallyeast) and restores the previous RAVEN solver afterwards. * doc: record the differences confirmed on MATLAB in the ledger notes The first MATLAB batch on a cluster (RAVEN 79a7d8c, 2026-10-21) confirmed differences between RAVEN and raven-toolbox that the notes did not state or stated wrongly: replaceMets (a RAVEN bug, not replicated exactly), removeLowScoreGenes (the tie-break is alphabetical, not random), parseTaskList, checkTasks, writeYAMLmodel, exportForGit and isDnfGrRule. Only the notes of these seven rows change. * Add scenarios for the parity decisions and update the ledger notes New scenarios: remove_low_score_genes_ties_smallyeast, task_list_edge_cases and yaml_float_digits_smallyeast. The task-list scenarios compare an empty CHANGED bound as NaN. Ledger notes for replaceMets, removeLowScoreGenes, parseTaskList, checkTasks, writeYAMLmodel, exportForGit and isDnfGrRule now say what CompMetEng/RAVEN#11 and CompMetEng/raven-toolbox#181 change.
edkerk
added a commit
that referenced
this pull request
Nov 1, 2026
* Report solver time limits instead of infeasible problems (SysBioChalmers/RAVEN#749) * solver: report a solver time limit through res.hitTimeLimit optimizeProb now translates the time-limit status of the solver it just called into a single logical field on res, so callers can tell a time out apart from an infeasible problem without knowing which solver ran. The statuses differ per solver and the same code can mean different things: 5 is optimal to glpk but the time limit to scip, so the translation happens where the solver is still known. For the "cobra" option the solver that COBRA dispatched to is looked up, since COBRA passes its status through. getMinNrFluxes uses this to report exitFlag -2 again. Gurobi is the case that matters most: on a MILP that hits the time limit with an incumbent solution, optimizeProb reports it as optimal, so the returned solution would otherwise be presented as the minimal set of fluxes when it may use more than the minimum. * solver: use the normalized time-limit flag in the ftINIT and INIT paths runINIT and ftINITInternalAlg tested res.origStat for gurobi's TIME_LIMIT string, so with any other solver a time limit was reported as "The problem is infeasible". ftINITFillGapsMILP inferred the time limit from a feasible but non-optimal status, which never fires for gurobi, since optimizeProb presents a MILP solution found before the limit as optimal. All three now read res.hitTimeLimit. The exit codes are lined up across getMinNrFluxes and ftINITFillGapsMILP: -1 means nothing usable came back, -2 means a solution came back that is not proven optimal. ftINITFillGapsForAllTasks depends on that split, as it marks a task failed on -1 but keeps the solution on -2. getMinNrFluxes therefore keeps returning -1 when the time limit is reached before any solution is found, and both functions now warn there, so the time limit is not reported as an infeasible problem. Original-commit: SysBioChalmers/RAVEN@9079e54 * doc: regenerate HTML documentation for af06821 [skip ci] Original-commit: SysBioChalmers/RAVEN@104a6e8 * Move HPA parsers and scoreModel into INIT/ (SysBioChalmers/RAVEN#750) parseHPA, parseHPArna, and scoreModel are contextualization inputs consumed only by ftINIT/tINIT, not general-purpose omics utilities; omics/ held nothing else and is now gone. - `omics/parseHPA.m`, `omics/parseHPArna.m`, `omics/scoreModel.m`: moved to `INIT/`. - `testing/function_tests/tOmics.m`: folded into `tINIT.m`; the `parseHPA`/`parseHPArna` tests moved over, the `scoreModel` smoke test dropped as a duplicate of `tINIT.m`'s own `scoreModelRuns`. - `INIT/tINIT/README.md`, `docs/v3_review.md`: folder references updated. Original-commit: SysBioChalmers/RAVEN@4430754 * doc: regenerate HTML documentation for 90dc76b [skip ci] Original-commit: SysBioChalmers/RAVEN@7efb0dc * writeYAMLmodel: nest ec-rxns enzymes; printOrange: print \n as line break (SysBioChalmers/RAVEN#751) * writeYAMLmodel: nest ec-rxns enzyme entries under their "enzymes" key Each ec-rxns entry writes its enzymes as an !!omap under "- enzymes", but the enzyme lines were written at the same indentation as that key. readYAMLmodel does not look at indentation and reads them back, but a YAML parser sees an empty "enzymes" mapping followed by sibling keys: ruamel.yaml, as used by raven-toolbox and geckopy, fails with "'ScalarNode' object has no attribute 'flow_style'", so no ecModel saved by GECKO 4 could be opened in Python. The lines are now indented two spaces deeper, like the metabolite coefficients under "- metabolites". Tested by re-saving the GECKO full_ecModel tutorial's stage-2 ecModel: RAVEN reads it back with identical rxnEnzMat and kcat, and geckopy now loads it (4834 ec reactions, same maximum growth as in MATLAB). * printOrange: print "\n" as a line break printOrange prints its text with fprintf('%s',...) so that a "%" in model text is not read as a format directive. That also stopped "\n" from being expanded, and every caller that ends a message or breaks a line with "\n" printed a literal backslash-n instead: 15 calls in RAVEN and 17 in GECKO, including GECKO 4's backward-compatibility notice. printOrange now turns "\n" into a line break; no other escape sequence or format directive is interpreted. Original-commit: SysBioChalmers/RAVEN@29bcc55 * doc: regenerate HTML documentation for 17be63f [skip ci] Original-commit: SysBioChalmers/RAVEN@083dccc * feat: complexPolicy, keepGeneFree and preserveNotes in getModelFromHomology, and no repeated genes (SysBioChalmers/RAVEN#757) complexPolicy decides what happens to an and-linked subunit without an ortholog (flag, keep, drop), keepGeneFree also transfers template reactions without a grRule, and preserveNotes keeps the template's rxnNotes, rxnReferences and rxnConfidenceScores. A gene that several template genes map to appears once in a grRule, and the draft no longer carries the templates' version, date and description. Matches get_model_from_homology in raven-toolbox. Original-commit: SysBioChalmers/RAVEN@5b5b1ee * doc: regenerate HTML documentation for 687271f [skip ci] Original-commit: SysBioChalmers/RAVEN@f07802c * fix: prefix whole gene ids in grRules in addIdentifierPrefix (SysBioChalmers/RAVEN#758) * fix: prefix whole gene ids in grRules in addIdentifierPrefix Gene ids with a dash, dot or colon (5-HT1A) got a prefix at every word start in grRules but one prefix in model.genes, so exportModel failed on models with such genes. * Update documentation Original-commit: SysBioChalmers/RAVEN@63ca4cb * doc: regenerate HTML documentation for d7db8b1 [skip ci] Original-commit: SysBioChalmers/RAVEN@00bbd23 * refactor: reorganize repository into src/, tests/, docs/ and tutorials/ Original-commit: SysBioChalmers/RAVEN@50b47d1 * refactor: organize external/software Original-commit: SysBioChalmers/RAVEN@cf4f303 * fix: set path after reorg to external directory Original-commit: SysBioChalmers/RAVEN@2677d51 * Point repository, documentation and version-check links to CompMetEng (#6) * doc: regenerate HTML documentation for 743c2dd [skip ci] * doc: regenerate HTML documentation for 204a3d0 [skip ci] * fix: reject gene ids that split in grRules in getModelFromHomology (#3) New-organism gene ids become gene ids of the draft model, and grRules are split at whitespace and parentheses, and by COBRA also at "|" and "&". UniProt FASTA headers such as sp|P33284|HXK_KLULA passed through and broke the draft downstream. getModelFromHomology now raises an error naming the offending ids, as raven-toolbox does. Original-commit: SysBioChalmers/RAVEN@48b3c52 * doc: regenerate HTML documentation for ba60895 [skip ci] * feat: hitsFromSuppOrth and runSuppOrth for SuppOrth consensus orthologs (#4) hitsFromSuppOrth reads suppOrth.tsv into a blastStructure for getModelFromHomology, in both directions, with filters on support, predictors, identity and e-value, and mapping of protein ids to gene ids. runSuppOrth runs the suppOrth command and reads its output. Matches hits_from_supporth and run_supporth in raven-toolbox. Original-commit: SysBioChalmers/RAVEN@fb7df09 * doc: regenerate HTML documentation for 27da412 [skip ci] * Download assets from CompMetEng/toolbox-assets with fetchToolboxAsset (#5) raven-data moved to CompMetEng/toolbox-assets, which holds the downloadable assets of RAVEN, raven-toolbox, GECKO and geckopy. fetchRavenDataAsset is renamed fetchToolboxAsset and downloads from the new repository; every caller and reference is updated. Original-commit: SysBioChalmers/RAVEN@f50baf2 * doc: regenerate HTML documentation for e44fcf0 [skip ci] * Fixes from the RAVEN 3 Guide review (#7) * fix: use the population std for the reporterMetabolites background The closed-form background correction assumes genes drawn with replacement from the scored-gene pool, which needs the population standard deviation. Scores now match raven-toolbox. The help states that results are sorted by Z-score and that P-values are one-sided. * fix: pass a sparse constraint matrix from sampleChebyshevCenter Gurobi rejects a dense model.A, so randomSampling with method 'chrr' failed whenever Gurobi was the RAVEN solver. * fix: return all-blocked from haveFlux when no reaction survives simplification When every reaction is a dead end, simplifyModel removes them all and the LP has an empty constraint matrix, which GLPK rejects. * fix: refuse a biomass balance that would make the balancing component negative scaleBiomassFraction rescales the balancing component so the biomass total becomes 1 g/gDW. A required fraction of zero or less inverted the balancing pseudoreaction without notice; it now raises an error, as does a balancing component with no current fraction. The help states that the total becomes 1 g/gDW. * feat: solve MILPs with the bundled GLPK optimizeProb no longer refuses a MILP when 'glpk' is the RAVEN solver. The bundled GLPK MEX supports integer variables and gives the same answers as Gurobi on the gap-filling and minimal-medium problems of the guide models. A RAVEN:glpkMILP warning recommends Gurobi for larger problems. The GLPK branch uses the default time limit for MILPs and reports a mipgap, as the Gurobi and SCIP branches do. MILPs through the COBRA Toolbox's GLPK interface are still refused. The help of setRavenSolver, gapFillMILP, fillGaps and getMinimalMedium states the solver behaviour; getMinimalMedium also states that the returned medium need not be unique. * fix: raise a clear error for an ambiguous name[comp] in getIndexes A metaboliteName[comp] that matches more than one metabolite ended in an unexplained assignment error. The error now names the matching metabolites. * docs: correct the help of six functions - randomSampling: the random-objective description applies to 'randomObjective' only, not to the default ACHR. - checkTasks: the model's own exchange reactions are not closed. - findGeneDeletions: details 2 means the solve failed, not that the deletion is lethal. - checkSolution: it reads an optimizeProb result, not a Mosek one. - assignSBOterms: where the terms are stored and how to read them. - haveFlux: the test uses the current bounds. * fix: read folded YAML scalars whose continuation starts with a dash readYAMLmodel treated any indented line starting with '-' as a list item, so a wrapped name continuing with '-epoxidizing)' was reported as an unknown entry. Only a dash followed by a space, or a lone dash, starts a list item. This made the kegg118 reference model unreadable and with it getKEGGModelForOrganism. * fix: read curation tables by header and curate existing entities fully curateModelFromTables read its tables by column position, so a metabolite table without an inchi column wrote its notes over the InChIs. Columns are now found by header name, in any order, and optional columns can be left out. Every supplied field is written to existing metabolites, genes and reactions as well as to new ones, including metNotes and rxnReferences, which were never written to existing entities; a field the model lacks is created. MIRIAM columns of the reaction table are taken from the columns after the core fields rather than from a fixed position, and grRules are matched to the right existing reaction when existing and new reactions are mixed. * docs: state how haveFlux treats a dead-end reaction with a forced flux * fix: keep the lower bound of unreversed reaction candidates in gapFillMILP Every draft reaction with lb >= 0 is a reversal candidate, and its lower bound was relaxed to -bigM with a coupling that only kept the flux non-negative while the reaction was not reversed. A forced flux such as a maintenance requirement (lb > 0) was therefore dropped, and the MILP could report a repair, or no repair, that does not reach the growth floor in the returned model. The coupling now keeps the original lower bound unless the reaction is reversed. * fix: create rxnNotes in getKEGGModelForOrganism when the reference model has none The kegg118 reference model has no reaction notes, so readYAMLmodel returns no rxnNotes field and adding the provenance note failed. * fix: correct a typo in the curateModelFromTables overwrite warning * gapFillMILP adds database reactions only; gapReport stops on an infeasible model gapFillMILP no longer reverses draft reactions: the draft keeps its bounds and the MILP minimises the number of added reactions. The reversedRxns output and the weights parameter are removed. gapReport raises RAVEN:infeasibleModel when the model is infeasible under its own bounds or with its boundary closed, naming the forced-flux reactions. * doc: regenerate HTML documentation for 2c6f9b8 [skip ci] * Check toolbox-assets downloads against the manifest checksums (#9) fetchToolboxAsset downloads to a .part file, checks it against the SHA-256 that the toolbox-assets manifest (manifest-v3) lists for its URL, and deletes it with an error when it differs. An asset the manifest does not list, or a manifest that cannot be read, gives a warning. The issue link points to CompMetEng/RAVEN. * doc: regenerate HTML documentation for caef029 [skip ci] * Follow-ups from the RAVEN 3 Guide review (#8) - optimizeProb solves MILPs with the COBRA Toolbox's GLPK as well, with the same RAVEN:glpkMILP warning as the bundled GLPK; getMinNrFluxes no longer refuses it. - scaleBiomassFraction takes a targetTotal for the balanced biomass total. - gapReport always reports the metabolites produced or consumed with the boundary closed, closing the reactions getExchangeRxns returns when the model has no unconstrained field, and stops when that closed model is infeasible. - MILP tests run on the bundled GLPK when neither Gurobi nor SCIP is available. - CONTRIBUTING, the documentation workflow and docs/v3_review.md refer to develop and RAVEN 3; the asset download error points to CompMetEng. * doc: regenerate HTML documentation for 4be3d6a [skip ci] * fix: quote YAML 1.1 booleans, fix replaceMets, and align task lists, gene pruning and YAML floats with raven-toolbox (#11) * fix: quote YAML 1.1 booleans such as NO in writeYAMLmodel needsQuote now quotes y, n, yes, no, on and off in any case, which YAML 1.1 loaders such as PyYAML read as booleans. This matches the quoting of write_yaml_model in raven-toolbox (CompMetEng/raven-toolbox#178). #10 * fix: removeLowScoreGenes keeps the first gene in the rule on a tie * fix: parseTaskList reads false/0 flags as false, trims ; lists, ignores header case, keeps empty CHANGED bounds as NaN * feat: checkTasks warns when a task metabolite matches several model metabolites * test: use a duplicate that leaves the task feasible * fix: writeYAMLmodel writes non-integers with the shortest digits that read back exactly * test: keep lb below ub in the float round-trip test * fix: restrict the contractModel call in replaceMets to the metabolite that is left By name, replaceMets deletes the replacement's row and keeps the renamed replaced metabolite. The ids it passed to the final contractModel call (repMetIds) were captured from the replacement only, so after the deletion none of them was found, repIdx was empty and contractModel(model,'mets',[]) checked every reaction. Duplicate reactions that do not involve the merged metabolite were merged as well. repMetIds now also holds the id of the replaced metabolite, so the restriction follows whichever of the two rows survives, and an empty list no longer reaches contractModel. Tests: unrelated duplicate reactions survive a merge by name and by id, and the new duplicate is still contracted. * doc: regenerate HTML documentation for beadbc0 [skip ci] * fix: read notes maps in readYAMLmodel (#12) * fix: readYAMLmodel reads notes maps into the note text cobrapy and raven-toolbox write other tools' notes on metabolites and reactions as a map under notes. readYAMLmodel stopped with 'Unknown entry' on them; it now reads each entry into metNotes or rxnNotes. * fix: read notes-map lines by indentation, not by key A key in a notes map named like an entry field (id, name, annotation) was read as that field, and list values in the map lost their items. * doc: regenerate HTML documentation for 0406546 [skip ci] * fix: align RAVEN with raven-toolbox (parity review) (#13) * exportForGit: lossless txt table, no main-branch check The txt table is headed 'Rxn id' (the column holds identifiers), writes lower bound, upper bound and objective coefficient with the digits needed to read them back instead of two decimals, and pads no field. The mainBranchFlag option is removed together with its check of the toolbox branch. * Align gapFillMILP bigM, getModelFromHomology and generateNewIds gapFillMILP couples with finite reaction bounds and uses bigM only for infinite ones, getModelFromHomology no longer fails when a preferred order removes no gene, and generateNewIds takes the numerically largest id. * parseTaskList: separate default columns, comment rows, orphan rows, numeric check, no .xls Each absent optional column gets its own empty spare column, so the bounds default to 0 and 1000 and the comments stay empty. Leading rows that start with a non-empty cell are removed before the header row is read. Rows before the first task id are skipped with a warning. A bound that is not a number raises RAVEN:badInput. The old binary .xls format raises RAVEN:badInput with the advice to save as .xlsx or tab-delimited .txt. * setGAM, scaleBiomassPseudoreaction: refuse a missing NGAM reaction or proton metabolite Both errors are raised before the model is changed. * reporterMetabolites: corrected score 0 when the background standard deviation is 0 * ftINIT: remove genes of removed reactions from the output model * sortModel: keep reaction directions unless sortReversible is requested * reporterMetabolites: treat rounding-level background spread as zero * setGAM: check a given NGAM reaction also without a value * parseTaskList: ignore empty rows, report file rows, read numbers typed as text * exportForGit: keep the mainBranchFlag option in its position Calls such as exportForGit(model,prefix,path,formats,'',false) and (...,false,false) keep their meaning. The check of the toolbox branch is as before. * Round 2 review fixes: reporterMetabolites spread rule, numeric text in task lists, empty NGAM reaction reporterMetabolites tests the spread of the Z-scores instead of sigma. parseTaskList accepts only plain numbers in numeric columns and states how its row number is counted. setGAM treats an empty ngamRxn as not given. * sampleACHR: project step directions onto the null space of S The running centre carried the rounding error of S*v into every later step, so the residual grew exponentially with the number of steps (up to 9 at 100 steps between samples). Directions are projected onto a null-space basis computed once. * Tests: exportForGit flag position and refusal, parseTaskList refused text; branch error identifier * reporterMetabolites: take the moments on shifted Z-scores; parseTaskList: refuse NaN outside the bounds of changed reactions * sampleACHR: correct towards S*v = 0 through a sparse factor over the free reactions, keep steps inside the bounds * reporterMetabolites: take the moments on Z-scores shifted by their mean * sampleACHR: warn when the samples keep a residual; tests for the fixed-reaction step, the correction interval, the relative direction tolerance and the final clip * reporterMetabolites: refuse P-values outside [0,1]; drop metabolites without a score from all result fields by one mask * prepINITModel refuses repeated task ids; curateModelFromTables: overwriteWithEmpty option and empty bound cells count as not given * setGAM refuses ngamValue without ngamRxn; generateNewIds counts only finite integer suffixes; exportForGit validates its logical flags * exportForGit creates the output folder, with missing parents, also when subDirs is false * Fix round after review: rev cells true/false, complex bounds refused, blank MIRIAM and gene rule cells count as empty, strict overwriteWithEmpty, generateNewIds below 2^53, prepINITModel task id checks * tCuration: shorter test name, quoted blank cells * Table cells are read without evaluating text; blank-only cells count as empty; overwriteWithEmpty needs a real value; empty task ids are reported separately; generateNewIds counts integers below 2^52 * curateModelFromTables: a NaN charge cell counts as not given * curateModelFromTables reads only plain decimal numbers, Inf, NaN and true/false (no commas, hex or expressions), also in the index and coefficient columns; a NaN confidence score counts as not given; exportForGit flags must be real * curateModelFromTables: a charge must be a finite whole number, a rev 0, 1, true or false, and a coefficient row with content needs a coefficient; help text states the per-column meaning of empty cells * curateModelFromTables: a rxnIdx must be a whole number of at least 1 * curateModelFromTables: rxnIdx test without a NaN row in the info table * curateModelFromTables: rows with values need a rxnIdx, the reaction tables must match exactly by index value, true and false only in lb, ub and rev, finite non-zero coefficients, RAVEN:badInput for file and column errors, empty overwriteWithEmpty means the default * curateModelFromTables: a malformed gene rule raises RAVEN:badInput; the help states how a lower bound above the upper bound is handled * curateModelFromTables: a gene id listed more than once in genesInfo raises RAVEN:badInput * curateModelFromTables: gene rules are written in the standard format before they are applied, so every spelling that parseGrRule reads is accepted * curateModelFromTables: a repeated rxnIdx in rxnsInfo raises; spaces inside the quotes of a header cell are ignored * tCuration: pass the metabolite table positionally in the padded header test * prepINITModel: repeated and empty task ids are accepted; parseTaskList help states that ids may repeat * tTasks: checkTasks reports tasks with a repeated id one by one * fix: keep each subsystem with its reaction when readYAMLmodel flattens them (#14) * fix: keep each subsystem with its reaction when readYAMLmodel flattens them A reaction without a subsystem held an empty entry in model.subSystems, and flattening the entries with [model.subSystems{:}] dropped the empty ones, so the vector was shorter than model.rxns and every subsystem after a gap sat on the wrong reaction. A reaction without a subsystem now gets an empty entry first, and the entries are flattened one by one, so model.subSystems keeps one entry per reaction. * test: check the subsystems that readYAMLmodel returns against checkModelStruct, for single and several subsystems per reaction * doc: regenerate HTML documentation for c37ceff [skip ci] * fix: align RAVEN with raven-toolbox (parity review, round 3) (#15) * ftINIT: resolveTies takes each step's fluxes from a least-total-flux solution After the id-rank phase, a further phase holds the on/off state and minimises the summed absolute flux, so the direction and magnitude at which the next step forces a reaction do not depend on the solver's vertex. * ftINIT: the resolveTies minimal-flux phase stops at a 1e-6 relative or absolute gap * ftINIT: resolveTies fixes equal-total-flux directions by id rank and ranks a merged reaction by its smallest original id * ftINIT: the resolveTies direction phase starts from the minimal-flux solution * mergeCompartments: keep the id of the copy in s or the one that sorts first The merged metabolite was the first copy in model order, so its id depended on the metabolite order of the model. It is now the copy already in compartment s, if any, otherwise the copy whose id sorts first, the rule raven-toolbox's merge_compartments applies. * mergeLinear: number groups by their first reaction Group numbers followed the order in which the reactions were merged. They are now 1, 2, ... in the order of the first reaction of each group in origRxnIds, the numbering raven-toolbox's merge_linear uses. * grRuleToDNF: help states the parseGrRule grammar and the RAVEN:badGrRule error; tUtils tests operator spellings and malformed rules * gapFillTopological: help states that the default targets are every metabolite of the objective reaction; tGapfilling tests the default targets * gapFillTopological: the no-objective error is RAVEN:badInput Without targets and without an objective reaction the function raised an error without identifier, which tGapfilling could only test as any MException. It now raises RAVEN:badInput, which the help states and tGapfilling tests. * tUtils: grRuleToDNF splits words at the characters isspace counts char(28) and char(8195) separate words; char(133), char(160), char(8199) and char(8239), for which isspace is false, are part of a word. * CHANGELOG: Unreleased section for mergeCompartments and mergeLinear * CHANGELOG: Unreleased section for grRuleToDNF and gapFillTopological * mergeLinear: a reaction flipped in a later pass is marked reversed by its id flipRxn indexed groupIds and reversedRxns, which follow origRxnIds, with the index of the reduced model, so after the first pass it marked the reaction at the same original index instead of the flipped one. * removeGenes: help states that genes no remaining reaction uses are removed * removeGenes: help states that nothing changes when no requested gene is in the model * tINIT: ftINIT ranks a merged reaction by the smallest original id of its group * tINIT: the paths of the rank-key test model are reversible, as prepINITModel needs * ftINITInternalAlg: resolveTies skips the tie-break after a time-limited primary solve and gives phases 2a and 2b half of TimeLimit * tINIT: resolveTies runs no tie-break phase after a time-limited primary solve * prepINITModel: prepData carries reversedRxns of mergeLinear * ftINIT: resolveTies orients a merged reaction as its smallest member and skips the flux phases in the last step * tINIT: resolveTies follows rxnOrientation, pinFluxes skips the flux phases, prepData carries reversedRxns * simplifyModel: constrainReversible changes nothing on a model without a reversible reaction * tINIT: prepINITModel runs on a model without a reversible reaction * ftINITInternalAlg: help and comments of pinFluxes name the phases it skips * ftINIT: resolveTies keeps the orientation of each merged reaction as written Phase 2d of ftINITInternalAlg weights the backward flux by the rank key only, a turned-on reaction with zero flux is forced forward in the next step, and prepData has no reversedRxns field. ftINITInternalAlg takes pinFluxes as its 15th argument. tINIT checks that ftINIT passes pinFluxes false in the last step only. * CHANGELOG: ftINITInternalAlg arguments rankKeys and pinFluxes, phase names of the tie-resolution warning * doc: regenerate HTML documentation for c1c8bb7 [skip ci] * Rewrite the help blocks under the documentation prose rules (#16) * doc: rewrite the help blocks under the documentation prose rules The help blocks state behaviour in impersonal, present-tense sentences with British spelling, without emphasis, history or slash alternatives. Code is unchanged; the sections that `docs/scripts/gen_api_pages.py` parses are kept, and `reverseRxns`, `gapFillMILP`, `gapFillFastLP` and `gapFillTopological` use the RAVEN 3 help structure. Statements that differed from the code are corrected, among them: - `simplifyModel` `deleteDuplicates` keeps the first occurrence; bounds and objective are merged by `contractModel`. - `removeBadRxns` raises an error for a supplied `refModel`; `removeGenes` leaves a gene that only occurs in a rule part of a removed gene. - `addRxns` and `changeRxns`: new metabolites take annotation from a same-name metabolite through `addMets`; ids are generated with prefix `m_`; `model.annotation`, `model.comps` and `setParam` are the names the code uses. - `replaceMets`: `removedRxns` and `idxDuplRxns` are never assigned. - `setExchangeBounds` raises an error when `compNames` or `metComps` is missing with `mediaOnly`. - `getModelFromHomology`: `maxE` is strict, `preserveNotes` does not touch `rxnReferences`, `mapNewGenesToOld` applies at strictness 2. - `getKEGGModelForOrganism`: `dataDir`, `outDir`, `maxPhylDist` and `cutOff` follow the code. - `getMinNrFluxes`: `params` is used; the large flux is `max(5 x largest LP flux, 1000)` for `irrev`. - `randomSampling`, `getFluxZ`, `getMinimalMedium`, `haveFlux`, `runProductionEnvelope`, `traceFluxPath`, `ftINIT`, `ftINITInternalAlg`, `rescaleModelForINIT`, `scoreModel`, `checkRaven` and others: definitions of options and outputs follow the code. * docs: changelog entry for the documentation rewrite * doc: regenerate HTML documentation for 1b742df [skip ci] * fix: four bugs found while rewriting the help blocks, corrected examples and comments (#17) - `renameModelGenes` reads the gene table from a file path (the file name was passed to `%s` as a table). - `getIndexes` with type `metnames` and `returnLogical` true raises `RAVEN:badInput` (each name can match several metabolites). - `checkProduction` returns a model with excretion reactions only when `checkNeededForProduction` is true. - `findGeneDeletions` returns `grRatioMuts` with one entry per gene pair for double deletions. - `checkRaven` names the offline bundle `RAVEN-<tag>-full.zip`. The examples of `gapReport`, `fitTasks`, `printFluxes` and `predictLocalization` use the documented arguments. The comments of `simplifyModel`, `setExchangeBounds`, `closeModel` and `ftINIT` state the current behaviour, and the help of `getModelFromKEGG` states which reactions the keep options retain. Each fix has a function test. * doc: regenerate HTML documentation for 68a6e60 [skip ci] * writeYAMLmodel: write no enzymes entry for an ec reaction without enzymes (#18) The enzymes header with nothing under it is not valid YAML. readYAMLmodel reads a missing entry, and the two forms written earlier, as a reaction without enzymes. * doc: regenerate HTML documentation for b3ff589 [skip ci] * CHANGELOG: name 2.11.4 as the last 2.x release * doc: README with the documentation links and the RAVEN logo for dark mode (#19) * Add GNU GPL v3 license file Added the GNU General Public License version 3 to the project. * Delete LICENSE.md * Prepare 3.0.0b2 release (#20) Version 3.0.0b2 and the changelog of the changes since 3.0.0b1. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: ae-tafur <ae.tafur@hotmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #10.
YAML booleans
src/io/writeYAMLmodel.mneedsQuote:NO,yes,onand the other YAML 1.1 booleans (y,n,yes,no,on,offin any case) were written unquoted, so a YAML 1.1 loader such as PyYAML read nitric oxide'sname: NOasFalse. They are quoted, astrueandfalsealready were. raven-toolbox quotes the same set since fix: four writer, task and gene-pruning problems from #178 raven-toolbox#179.[Yy][Ee][Ss]) instead of(?i), which in MATLAB would also make the numeric alternatives case-insensitive and quote values such as0X1Fthat raven-toolbox leaves plain.replaceMets bug
replaceMetscalledcontractModelon the whole model, so it also merged unrelated metabolites that happened to share a name or id. The call is now restricted to the metabolite that is left, and skipped when nothing is left to contract.tManipulation: by name and by id leave unrelated duplicates alone, and by name still contracts the new duplicate. Without the fixreplaceMetsByNameLeavesUnrelatedDuplicatesAlonefails; with it all pass.Parity decisions from the RAVEN vs raven-toolbox review
Each item has a test. The Python side is CompMetEng/raven-toolbox#181.
writeYAMLmodel: non-integers are written with the shortest digits that read back exactly (15 to 17 significant digits), so 1/3 is0.3333333333333333and not0.333333333333333. Python writes the same.removeLowScoreGenes: when all isozymes are negative and tied, the gene listed first in the rule is kept, not the alphabetically first one. Surviving genes keep rule order. The docstring no longer says the tie is random.parseTaskList:SHOULD FAILandPRINT FLUXread0,falseandno(any case) as false.;lists are trimmed and empty items dropped.CHANGED LBorCHANGED UBis NaN, meaning the bound is left unchanged.checkTasksandfitTasksskip NaN bounds. Before, an empty bound left the bound arrays shorter than the list of changed reactions.checkTasks: warns when a task metabolite matches several model metabolites (only the first is constrained; raven-toolbox constrains all and warns too).Checks
Run in MATLAB R2024b with GLPK on head
875e45b(cluster batch 2026-10-21, results in CompMetEng/raven-gecko-parity, branchhpc-results/2026-10-21, folderfollow-up/pr11/):tTasks7/7,tIO24/24,tManipulation85/85,tINIT31/31,tSyntax1/1, none failed or incomplete. The scenariosremove_low_score_genes_smallyeast,replace_metabolite_toy,task_checking_smallyeast,task_list_parsingandyaml_roundtrip_smallyeastMATCH against Python seeds 0, 1 and 2.Not checked: other MATLAB versions and solvers (Gurobi, SCIP).