From d062e949fad0dce2833c801ef60b56076a63e126 Mon Sep 17 00:00:00 2001 From: Eduard Kerkhoven Date: Sun, 1 Nov 2026 18:18:04 +0100 Subject: [PATCH 1/2] chore: prepare 3.0.0b2, version and changelog --- CHANGELOG.md | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- version.txt | 2 +- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f980b75f..684c9503 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,25 @@ # Changelog -## Unreleased +## 3.0.0b2 — 2026-11-01 + +Second beta toward 3.0. Changes below are relative to 3.0.0b1. + +### Repository layout and downloads + +* The MATLAB code is in `src/` (was: folders in the repository root), the tests in `tests/` (was: `testing/`), the generated help pages in `docs/html/` (was: `doc/`), and the tutorials in `tutorials/` with data under `tutorials/data/{models,omics,sequences}` (was: `tutorial/`). The external software is in `src/external` (was: `src/software`). `checkRaven`, `downloadRavenBinaries`, `getBlast`, `getDiamond`, `getKEGGModelForOrganism`, `optimizeProb`, `setRavenSolver` and `updateDocumentation` use the new paths. This matters for code that adds RAVEN folders to the path or addresses binaries by path. +* `parseHPA`, `parseHPArna` and `scoreModel` are in `INIT/` (was: `omics/`, which no longer exists). `tOmics.m` is merged into `tINIT.m`. +* `fetchToolboxAsset` replaces `fetchRavenDataAsset`, and assets are downloaded from `CompMetEng/toolbox-assets` (was: raven-data). `downloadRavenBinaries`, the KEGG functions, `getPhylDist` and `checkRaven` use it. +* `fetchToolboxAsset` downloads to a `.part` file and checks the SHA-256 sum listed in the `manifest-v3` of toolbox-assets. A mismatch deletes the file and raises an error; an asset that the manifest does not list, or a manifest that cannot be read, gives a warning. +* The repository, documentation and version-check links point to `CompMetEng`. ### I/O * `writeYAMLmodel` writes an ec reaction without enzymes (a row of zeros in `model.ec.rxnEnzMat`) with no `enzymes` entry (was: `- enzymes: !!omap` with nothing under it, which is not valid YAML). `readYAMLmodel` reads a missing `enzymes` entry as a reaction without enzymes, and still reads `- enzymes: !!omap` with no entries and `- enzymes: !!omap []` from files written earlier. +* `readYAMLmodel` reads notes maps (as written by cobrapy and raven-toolbox) into `metNotes` and `rxnNotes` (was: the error "Unknown entry"), reads folded scalars whose continuation starts with `-`, and keeps one `model.subSystems` entry per reaction (was: empty entries were dropped, so later subsystems sat on the wrong reaction). +* `writeYAMLmodel` writes the enzymes of each `ec-rxns` entry indented under `- enzymes` (was: at the indentation of the key, which ruamel.yaml could not read), quotes the YAML 1.1 booleans (`y`, `n`, `yes`, `no`, `on`, `off` in any case), and writes non-integers with the shortest digits that read back exactly. `printOrange` prints `\n` as a line break. +* `exportForGit`: the txt table is headed `Rxn id`, writes bounds and objective with the digits needed to read them back and pads no field. The output folder is created with its parents also when `subDirs` is false, and the logical flags are validated. + ### Manipulation * `mergeCompartments`: a merged metabolite is the copy already in compartment `s`, if any, @@ -86,6 +100,39 @@ `RAVEN--full.zip` bundle attached to each release for an offline install (was: "the `*-binaries` RAVEN release"). +### Homology and curation + +* `getModelFromHomology` has the options `complexPolicy` (`flag`, `keep` or `drop`: how a reaction is treated when an `and`-linked subunit has no ortholog), `keepGeneFree` (reactions of the template without a grRule are transferred) and `preserveNotes` (`rxnNotes`, `rxnReferences` and `rxnConfidenceScores` are kept). A gene that several template genes reach appears once per grRule. The draft no longer carries the version, date and description of the templates. It no longer fails when a preferred order removes no gene. +* `getModelFromHomology` raises an error that names the gene ids of the new organism that split in a grRule (whitespace, parentheses, `|` or `&`, for example the UniProt id `sp|P33284|HXK_KLULA`) (was: the ids were accepted). +* New: `hitsFromSuppOrth` reads a `suppOrth.tsv` into a blast structure for `getModelFromHomology`, in both directions, with filters on support, predictors, identity and E-value. `runSuppOrth` runs the `suppOrth` command and reads its output. +* `curateModelFromTables` reads the tables by header name in any order, with optional columns, and writes every supplied field to existing entities (`metNotes` and `rxnReferences` were never written). The MIRIAM columns follow the core columns, and grRules go to the right reaction when existing and new reactions are mixed. The option `overwriteWithEmpty` is new, an empty cell counts as not given, and the input is validated: a file, column, gene-rule or repeated-id error raises `RAVEN:badInput`. +* `scaleBiomassFraction` raises an error when the required fraction is 0 or less, or when the balancing component has no current fraction (was: the fractions were silently inverted). The new argument `targetTotal` sets the balanced total of the biomass. +* `setGAM` and `scaleBiomassPseudoreaction` raise an error before the model changes when the NGAM reaction or the proton metabolite is missing. `setGAM` refuses `ngamValue` without `ngamRxn`, and an empty `ngamRxn` counts as not given. +* `sortModel` keeps the directions of the reactions unless `sortReversible` is requested. `generateNewIds` takes the numerically largest id and counts only finite integer suffixes. +* `replaceMets`: the final `contractModel` call is restricted to the surviving metabolite (was: unrelated duplicate reactions were merged as well). +* `addIdentifierPrefix` prefixes whole gene ids in grRules (was: an id with a dash, dot or colon, for example `5-HT1A`, got a prefix at every word start, so `exportModel` failed). +* `getIndexes` with an ambiguous `name[comp]` raises an error that names the matching metabolites. +* `gapFillMILP` keeps the lower bound of unreversed candidate reactions. +* `gapReport` always reports the metabolites that are produced or consumed with the boundary closed. It closes the reactions of `getExchangeRxns` when the model has no `unconstrained` field, and stops when the closed model is infeasible. + +### Solvers + +* `optimizeProb` returns the logical `res.hitTimeLimit` for every solver. `getMinNrFluxes`, `ftINITFillGapsMILP`, `runINIT` and `ftINITInternalAlg` report a time limit as such, with a warning (was: every solver except Gurobi reported "The problem is infeasible"). The exit code -1 means that no usable solution came back, and -2 means a solution that is not proven optimal. +* The MILPs of `gapFillMILP`, `fillGaps`, `getMinimalMedium` and `getMinNrFluxes` run on the bundled GLPK and on the GLPK of the COBRA Toolbox, with a `RAVEN:glpkMILP` warning (was: refused). + +### Sampling and reporting + +* `reporterMetabolites` uses the population standard deviation for the background, sorts the results by Z-score and reports one-sided P-values, which gives the numbers of raven-toolbox (was: scores differed). The score is 0 when the spread of the background is 0 or at rounding level, P-values outside [0, 1] are refused, and metabolites without a score are dropped from all result fields. +* `sampleChebyshevCenter` and `randomSampling` pass a sparse matrix, so the method `'chrr'` works with Gurobi. +* `sampleACHR` projects the directions onto the null space of S and keeps the steps within the bounds. It warns when the samples keep a residual (was: the residual of `S*v` grew exponentially, up to 9 after 100 steps). +* `haveFlux` returns all reactions as blocked when the simplification removes every reaction (was: a GLPK error on an empty matrix). + +### Tasks + +* `parseTaskList` reads `false` and `0` as false, trims `;` lists, ignores the case of headers, keeps empty CHANGED bounds as `NaN`, and has separate spare columns, so that bounds default to 0 and 1000. Comment rows and orphan rows are skipped with a warning, a non-numeric bound raises `RAVEN:badInput`, and a binary `.xls` file is refused with `RAVEN:badInput` (save it as `.xlsx` or `.txt`). +* `checkTasks` warns when a task metabolite matches several model metabolites. `removeLowScoreGenes` keeps the first gene of the rule on a tie. +* `ftINIT` removes the genes of removed reactions from the output. + ### Documentation * Help blocks of 176 files are rewritten in impersonal, present-tense wording with British spelling; the code is unchanged. Statements that differed from the code are corrected, for example `simplifyModel` `deleteDuplicates` (first occurrence kept), `removeBadRxns` `refModel`, `replaceMets` outputs, `getMinNrFluxes` `params`, `checkRaven` `developMode` and the `downloadRavenBinaries` offline bundle. `reverseRxns` has the RAVEN 3 help structure. diff --git a/version.txt b/version.txt index a1513ac3..274c38c1 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -3.0.0b1 \ No newline at end of file +3.0.0b2 \ No newline at end of file From 0b8c2eb94e844c948bd6d851863d68e815b916d4 Mon Sep 17 00:00:00 2001 From: Eduard Kerkhoven Date: Sun, 1 Nov 2026 21:12:09 +0100 Subject: [PATCH 2/2] CHANGELOG: corrections, breaking changes and missing entries for 3.0.0b2 --- CHANGELOG.md | 58 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 684c9503..423aec56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,19 +4,28 @@ Second beta toward 3.0. Changes below are relative to 3.0.0b1. +### Breaking changes + +* The folder layout changed (see Repository layout and downloads); code that adds RAVEN folders to the path or addresses binaries by path needs the new paths. +* `fetchRavenDataAsset` is replaced by `fetchToolboxAsset`. +* `gapFillMILP` returns `[addedRxns, newModel, exitFlag]` and has no `weights` option. +* `sortModel` keeps the directions of the reactions unless `sortReversible` is requested (was: it sorted them by default). +* `parseTaskList` refuses a binary `.xls` file. +* `gapReport`, `scaleBiomassFraction`, `getModelFromHomology` and `getIndexes` raise errors in cases they accepted before (see below). + ### Repository layout and downloads -* The MATLAB code is in `src/` (was: folders in the repository root), the tests in `tests/` (was: `testing/`), the generated help pages in `docs/html/` (was: `doc/`), and the tutorials in `tutorials/` with data under `tutorials/data/{models,omics,sequences}` (was: `tutorial/`). The external software is in `src/external` (was: `src/software`). `checkRaven`, `downloadRavenBinaries`, `getBlast`, `getDiamond`, `getKEGGModelForOrganism`, `optimizeProb`, `setRavenSolver` and `updateDocumentation` use the new paths. This matters for code that adds RAVEN folders to the path or addresses binaries by path. -* `parseHPA`, `parseHPArna` and `scoreModel` are in `INIT/` (was: `omics/`, which no longer exists). `tOmics.m` is merged into `tINIT.m`. -* `fetchToolboxAsset` replaces `fetchRavenDataAsset`, and assets are downloaded from `CompMetEng/toolbox-assets` (was: raven-data). `downloadRavenBinaries`, the KEGG functions, `getPhylDist` and `checkRaven` use it. +* The MATLAB code is in `src/` (was: folders in the repository root), the tests in `tests/` (was: `testing/`), the generated help pages in `docs/html/` (was: `doc/`), the readme files in `docs/readme/`, the logo in `img/` (was: `RAVEN.png`), and the tutorials in `tutorials/` with data under `tutorials/data` (was: `tutorial/`). The external software is in `src/external` (was: `software/`). `checkRaven`, `downloadRavenBinaries`, `getBlast`, `getDiamond`, `getKEGGModelForOrganism`, `optimizeProb`, `setRavenSolver` and `updateDocumentation` use the new paths. +* `parseHPA`, `parseHPArna` and `scoreModel` are in `INIT/` (was: `omics/`, which is removed). `tOmics.m` is merged into `tINIT.m`. +* `fetchToolboxAsset` replaces `fetchRavenDataAsset`, and assets are downloaded from `CompMetEng/toolbox-assets` (was: raven-data). `downloadRavenBinaries`, `buildGlobalKEGGModel`, `getKEGGModelForOrganism`, `getModelFromKEGG`, `getPhylDist`, `keggDataVersion` and `checkRaven` use it. * `fetchToolboxAsset` downloads to a `.part` file and checks the SHA-256 sum listed in the `manifest-v3` of toolbox-assets. A mismatch deletes the file and raises an error; an asset that the manifest does not list, or a manifest that cannot be read, gives a warning. * The repository, documentation and version-check links point to `CompMetEng`. ### I/O -* `writeYAMLmodel` writes an ec reaction without enzymes (a row of zeros in `model.ec.rxnEnzMat`) with no `enzymes` entry (was: `- enzymes: !!omap` with nothing under it, which is not valid YAML). `readYAMLmodel` reads a missing `enzymes` entry as a reaction without enzymes, and still reads `- enzymes: !!omap` with no entries and `- enzymes: !!omap []` from files written earlier. - +* `writeYAMLmodel` writes an ec reaction without enzymes (a row of zeros in `model.ec.rxnEnzMat`) with no `enzymes` entry (was: `- enzymes: !!omap` with nothing under it, which is not valid YAML). `readYAMLmodel` reads a missing `enzymes` entry as a reaction without enzymes, and reads `- enzymes: !!omap` with no entries and `- enzymes: !!omap []` from files written by earlier versions. * `readYAMLmodel` reads notes maps (as written by cobrapy and raven-toolbox) into `metNotes` and `rxnNotes` (was: the error "Unknown entry"), reads folded scalars whose continuation starts with `-`, and keeps one `model.subSystems` entry per reaction (was: empty entries were dropped, so later subsystems sat on the wrong reaction). +* `exportForGit` raises `RAVEN:notMainBranch` when a RAVEN checkout is on a branch other than `main` or `master`. * `writeYAMLmodel` writes the enzymes of each `ec-rxns` entry indented under `- enzymes` (was: at the indentation of the key, which ruamel.yaml could not read), quotes the YAML 1.1 booleans (`y`, `n`, `yes`, `no`, `on`, `off` in any case), and writes non-integers with the shortest digits that read back exactly. `printOrange` prints `\n` as a line break. * `exportForGit`: the txt table is headed `Rxn id`, writes bounds and objective with the digits needed to read them back and pads no field. The output folder is created with its parents also when `subDirs` is false, and the logical flags are validated. @@ -65,13 +74,13 @@ Second beta toward 3.0. Changes below are relative to 3.0.0b1. * `ftINIT` with `resolveTies`: each main-extraction step takes its fluxes from the least-total-flux solution for the tie-broken on/off state, so the direction and magnitude - at which the next step forces a reaction no longer depend on the solver's vertex. + at which the next step forces a reaction do not depend on the solver's vertex. That phase stops at a relative or absolute gap of 1e-6. * `ftINIT` with `resolveTies`: among the least-total-flux solutions, each main-extraction step takes its fluxes from the one with the least id-rank-weighted backward flux, so the direction of a flux that carries the same total either way no longer depends on the solver. The id-rank phases rank a merged reaction by the smallest original reaction id in - its group, so they no longer depend on which member names it. + its group, so they do not depend on which member names it. * `ftINITInternalAlg` with `resolveTies`: when the primary solve stops at the time limit, the tie-break phases are skipped and the primary solution is kept, as in raven-toolbox (was: the phases ran on the unproven incumbent). The count and id-rank phases get half of @@ -95,41 +104,40 @@ Second beta toward 3.0. Changes below are relative to 3.0.0b1. * `grRuleToDNF`: help states the grammar it reads, that of `parseGrRule` (`and`/`or` in any case, `&`, `&&`, `|`, `||`, operators as whole words, so `G1&G2` is one gene id), and that a malformed rule raises `RAVEN:badGrRule`. - -* `checkRaven`: when the binaries cannot be downloaded, the message names the - `RAVEN--full.zip` bundle attached to each release for an offline install (was: - "the `*-binaries` RAVEN release"). +* `checkRaven`: when the binaries cannot be downloaded, the message names the `RAVEN--full.zip` bundle attached to each release for an offline install (was: "the `*-binaries` RAVEN release"). ### Homology and curation -* `getModelFromHomology` has the options `complexPolicy` (`flag`, `keep` or `drop`: how a reaction is treated when an `and`-linked subunit has no ortholog), `keepGeneFree` (reactions of the template without a grRule are transferred) and `preserveNotes` (`rxnNotes`, `rxnReferences` and `rxnConfidenceScores` are kept). A gene that several template genes reach appears once per grRule. The draft no longer carries the version, date and description of the templates. It no longer fails when a preferred order removes no gene. +* `getModelFromHomology` has the options `complexPolicy` (`flag`, `keep` or `drop`: how a reaction is treated when an `and`-linked subunit has no ortholog), `keepGeneFree` (reactions of the template without a grRule are transferred) and `preserveNotes` (`rxnNotes` and `rxnConfidenceScores` of the template are kept; `rxnReferences` are always kept). A gene that several template genes reach appears once per grRule. The draft has no version, date or description, and the descriptive annotation of the template is not copied (was: those of the templates). A preferred order that removes no gene is accepted (was: an error). * `getModelFromHomology` raises an error that names the gene ids of the new organism that split in a grRule (whitespace, parentheses, `|` or `&`, for example the UniProt id `sp|P33284|HXK_KLULA`) (was: the ids were accepted). -* New: `hitsFromSuppOrth` reads a `suppOrth.tsv` into a blast structure for `getModelFromHomology`, in both directions, with filters on support, predictors, identity and E-value. `runSuppOrth` runs the `suppOrth` command and reads its output. -* `curateModelFromTables` reads the tables by header name in any order, with optional columns, and writes every supplied field to existing entities (`metNotes` and `rxnReferences` were never written). The MIRIAM columns follow the core columns, and grRules go to the right reaction when existing and new reactions are mixed. The option `overwriteWithEmpty` is new, an empty cell counts as not given, and the input is validated: a file, column, gene-rule or repeated-id error raises `RAVEN:badInput`. -* `scaleBiomassFraction` raises an error when the required fraction is 0 or less, or when the balancing component has no current fraction (was: the fractions were silently inverted). The new argument `targetTotal` sets the balanced total of the biomass. -* `setGAM` and `scaleBiomassPseudoreaction` raise an error before the model changes when the NGAM reaction or the proton metabolite is missing. `setGAM` refuses `ngamValue` without `ngamRxn`, and an empty `ngamRxn` counts as not given. -* `sortModel` keeps the directions of the reactions unless `sortReversible` is requested. `generateNewIds` takes the numerically largest id and counts only finite integer suffixes. +* New: `hitsFromSuppOrth` reads a `suppOrth.tsv` into a blast structure for `getModelFromHomology`, in both directions, with filters on support, predictors, identity and E-value and the option `proteinToGene` for a protein to gene mapping. `runSuppOrth` runs the `suppOrth` command and reads its output. +* `curateModelFromTables` reads the tables by header name in any order, with optional columns, and writes every supplied field to existing entities (was: `metNotes` and `rxnReferences` were not written). The MIRIAM columns follow the core columns, and grRules go to the right reaction when existing and new reactions are mixed. An empty grRules, lb, ub or rev cell leaves the existing value; the new option `overwriteWithEmpty` (default `true`) decides whether other empty cells clear a field. Cells are read without evaluating text: numeric cells accept plain decimals, `Inf` and `NaN`, and lb, ub and rev accept `true` and `false`; commas, hexadecimal numbers and expressions raise `RAVEN:badInput`. A file, column, gene-rule or repeated-id error raises `RAVEN:badInput`. +* `scaleBiomassFraction` raises an error when the balancing component would get a fraction of 0 or less (was: the balancing pseudoreaction was inverted), when it has no current fraction (was: balancing was skipped) or when it is not a component of the biomass. The new argument `targetTotal` sets the balanced total of the biomass. +* `setGAM` and `scaleBiomassPseudoreaction` raise an error before the model changes: `setGAM` when the NGAM reaction is missing and `scaleBiomassPseudoreaction` when the proton metabolite is missing. `setGAM` refuses `ngamValue` without `ngamRxn`, and an empty `ngamRxn` counts as not given. +* `sortModel` keeps the directions of the reactions unless `sortReversible` is requested (was: the default sorted them). `generateNewIds` takes the numerically largest id and counts only finite integer suffixes. * `replaceMets`: the final `contractModel` call is restricted to the surviving metabolite (was: unrelated duplicate reactions were merged as well). * `addIdentifierPrefix` prefixes whole gene ids in grRules (was: an id with a dash, dot or colon, for example `5-HT1A`, got a prefix at every word start, so `exportModel` failed). * `getIndexes` with an ambiguous `name[comp]` raises an error that names the matching metabolites. -* `gapFillMILP` keeps the lower bound of unreversed candidate reactions. -* `gapReport` always reports the metabolites that are produced or consumed with the boundary closed. It closes the reactions of `getExchangeRxns` when the model has no `unconstrained` field, and stops when the closed model is infeasible. +* `gapFillMILP` adds database reactions only and does not reverse draft reactions, which keep their bounds. The second output `reversedRxns` and the option `weights` are removed. `bigM` replaces infinite bounds of universal reactions; a finite bound is used as it is (was: bounds capped at `bigM`). +* `prepINITModel` raises `RAVEN:badInput` when the task structure has no `id` field or a non-text id. +* `getKEGGModelForOrganism` works with the kegg118 reference model, which has no `rxnNotes` (was: an error when adding the provenance note). +* `gapReport` reports the metabolites that are produced or consumed with the boundary closed for every model (was: only for models with an `unconstrained` field). It closes the reactions of `getExchangeRxns` when the model has no `unconstrained` field, and stops with `RAVEN:infeasibleModel` when the model is infeasible under its own bounds or with its boundary closed, for example with a forced ATP maintenance flux. ### Solvers -* `optimizeProb` returns the logical `res.hitTimeLimit` for every solver. `getMinNrFluxes`, `ftINITFillGapsMILP`, `runINIT` and `ftINITInternalAlg` report a time limit as such, with a warning (was: every solver except Gurobi reported "The problem is infeasible"). The exit code -1 means that no usable solution came back, and -2 means a solution that is not proven optimal. -* The MILPs of `gapFillMILP`, `fillGaps`, `getMinimalMedium` and `getMinNrFluxes` run on the bundled GLPK and on the GLPK of the COBRA Toolbox, with a `RAVEN:glpkMILP` warning (was: refused). +* `optimizeProb` returns the logical `res.hitTimeLimit` for every solver. `runINIT` and `ftINITInternalAlg` raise "Time limit reached without finding a solution" (was: "The problem is infeasible" with every solver except Gurobi). `getMinNrFluxes` returns exit code -2 for a solution that is not proven optimal at the time limit (was: 1 with Gurobi), and -1 with a warning when no solution came back. +* `optimizeProb` solves MILPs, including those of `gapFillMILP`, `fillGaps`, `getMinimalMedium`, `getMinNrFluxes`, `ftINIT` and `runINIT`, with the bundled GLPK and on the GLPK of the COBRA Toolbox, with a `RAVEN:glpkMILP` warning (was: refused). ### Sampling and reporting -* `reporterMetabolites` uses the population standard deviation for the background, sorts the results by Z-score and reports one-sided P-values, which gives the numbers of raven-toolbox (was: scores differed). The score is 0 when the spread of the background is 0 or at rounding level, P-values outside [0, 1] are refused, and metabolites without a score are dropped from all result fields. -* `sampleChebyshevCenter` and `randomSampling` pass a sparse matrix, so the method `'chrr'` works with Gurobi. -* `sampleACHR` projects the directions onto the null space of S and keeps the steps within the bounds. It warns when the samples keep a residual (was: the residual of `S*v` grew exponentially, up to 9 after 100 steps). +* `reporterMetabolites` uses the population standard deviation for the background, which gives the scores of raven-toolbox (was: the sample standard deviation). The score is 0 when the spread of the background is 0 or at rounding level, P-values outside [0, 1] are refused, and metabolites without a score are dropped from all result fields. +* `sampleChebyshevCenter` passes a sparse constraint matrix, so `randomSampling` with the method `'chrr'` works with Gurobi (was: Gurobi rejected the dense matrix). +* `sampleACHR` corrects the flux vectors towards `S*v = 0` every few steps and before each sample, and keeps them within the bounds. It raises the warning `sampleACHR:steadyStateNotRestored` when a sample keeps a residual above 1e-9 relative (was: the residual of `S*v` grew exponentially, up to 9 after 100 steps). * `haveFlux` returns all reactions as blocked when the simplification removes every reaction (was: a GLPK error on an empty matrix). ### Tasks -* `parseTaskList` reads `false` and `0` as false, trims `;` lists, ignores the case of headers, keeps empty CHANGED bounds as `NaN`, and has separate spare columns, so that bounds default to 0 and 1000. Comment rows and orphan rows are skipped with a warning, a non-numeric bound raises `RAVEN:badInput`, and a binary `.xls` file is refused with `RAVEN:badInput` (save it as `.xlsx` or `.txt`). +* `parseTaskList` reads `false` and `0` as false, trims `;` lists, ignores the case of headers, keeps empty CHANGED bounds as `NaN`, and reads `no` as false. `fitTasks` leaves a bound unchanged when the CHANGED LB or UB is `NaN`. An absent IN LB, IN UB, OUT LB or OUT UB column gives the default bounds 0 and 1000. Comment rows and orphan rows are skipped with a warning, a non-numeric bound raises `RAVEN:badInput`, and a binary `.xls` file is refused with `RAVEN:badInput` (save it as `.xlsx` or `.txt`). * `checkTasks` warns when a task metabolite matches several model metabolites. `removeLowScoreGenes` keeps the first gene of the rule on a tie. * `ftINIT` removes the genes of removed reactions from the output.