Initialization (Python)#
raven-toolbox objects in raven_toolbox.init.
Functions#
Function |
Summary |
|---|---|
Classify reactions into the ftINIT |
|
Add minimum-cost reference reactions so every task is feasible in |
|
Run the full ftINIT pipeline on prepData and return the context-specific model. |
|
Result of |
|
Gene scores from RNA-seq/array expression, RAVEN's |
|
Return the step schedule for a named ftINIT |
|
Sum original reaction scores over merged groups (RAVEN |
|
Numeric gene scores from HPA levels for one |
|
Tidy HPA proteomics data: one row per (gene, tissue, cell type). |
|
Tidy HPA RNA-seq data: one row per (gene, tissue) with TPM. |
|
One ftINIT MILP step. |
|
Merge linearly-dependent reactions; return |
|
Parse an HPA proteomics dump ( |
|
Parse an HPA RNA-seq dump. |
|
Build |
|
One-time ftINIT preprocessing of a template model (RAVEN |
|
Reaction-category id sets (RAVEN's |
|
Remove negative-scoring genes from GPRs (RAVEN |
|
Compress each reaction's stoichiometric dynamic range. |
|
Numeric gene scores from HPA RNA-seq TPM for one |
|
Run the single-step ftINIT MILP and return the extracted model. |
|
Score each reaction from per-gene scores via its GPR ( |
|
Result of |
Reference#
classify_reactions#
classify_reactions(model: cobra.Model, *, ext_comp: str='e', spontaneous: Iterable[str]=(), custom: Iterable[str]=())
Classify reactions into the ftINIT toIgnore categories (prepINITModel).
ext_comp is the extracellular compartment. spontaneous/custom are
reaction-id lists. A reaction is "GPR-less" when its gene rule is empty.
fill_tasks#
fill_tasks(model: cobra.Model, reference_model: cobra.Model, tasks: Iterable[Task], *, rxn_scores: Mapping[str, float] | None=None, time_limit: float | None=_FILL_TIME_LIMIT, seed: int=_FILL_SEED, resolve_ties: bool=False, mutate_in_place: bool=False, verbose: bool=False)
Add minimum-cost reference reactions so every task is feasible in model.
Port of RAVEN fitTasks with gapFillMode 'preMerged' (ftINIT's mode): task by
task, if a task is infeasible in the (growing) model, _gap_fill_task finds the
minimum-cost set of reference
reactions that restores it and they are added, carrying forward so later tasks see the
earlier additions. reference_model supplies the candidates (its reactions not yet in
the model, excluding exchange/boundary reactions); rxn_scores (original reaction id →
score) sets each candidate's cost as −min(score, −0.1) (missing → cost 1).
should_fail tasks are ignored. Each gap-fill MILP is single-threaded with a fixed
seed and bounded by time_limit (RAVEN's 300 s). resolve_ties (opt-in) pins the
degenerate min-cost fill to the fewest, lowest-id reactions so the added set does not
depend on the solver seed/version — see _resolve_ties_fill. At genome scale its
own phases can themselves exhaust time_limit; when that happens the (still-adopted)
incumbent is an unproven tie-break and a warning is raised, same as the main extraction.
Boundary reactions are closed while testing/solving each task, so task inputs and outputs
come solely from the task's ranged metabolite bounds (RAVEN gap-fills the exchange-free
model). The returned model keeps its boundary reactions. Tasks that could not be filled
are returned in failed_tasks and raised as a warning — a non-empty list means the
context model cannot perform those tasks, which callers should not ignore silently.
mutate_in_place (default False) skips the initial model.copy() and gap-fills
model directly, returning it as TaskFillResult.model. Copying a genome-scale,
Gurobi-backed model is itself expensive (see _gap_fill_task's docstring for the
same lesson applied to reference_model), so a caller that already holds a disposable
copy it will not use again — raven_toolbox.init.ftinit, whose own out is
exactly that — should pass mutate_in_place=True to avoid paying for a second one.
Leave it False (the default) whenever the caller still needs model afterward.
verbose prints one line per task (added count and running total, matching RAVEN
fitTasks's per-task report), silent by default.
ftinit#
ftinit(prep, rxn_scores: Mapping[str, float], *, gene_scores: Mapping[str, float] | None=None, series: str='1+1', steps=None, fill_gaps: bool=True, metabolomics: Iterable[str] | None=None, prod_weight: float=0.5, force_on: float=_FORCE_ON, big_m: float=_BIG_M, mip_gap: float | None=None, mip_gap_abs: float | None=10.0, time_limit: float | None=None, prove_abs_gap: float | None=None, resolve_ties: bool=False, seed: int=_EXTRACT_SEED, threads: int=_EXTRACT_THREADS, feas_tol: float=_EXTRACT_TOL, opt_tol: float=_EXTRACT_TOL, int_feas_tol: float=_EXTRACT_TOL, presolve: int=_EXTRACT_PRESOLVE, verbose: bool=False)
Run the full ftINIT pipeline on prepData and return the context-specific model.
prep is a raven_toolbox.init.PrepData. rxn_scores maps original
reaction id → score (e.g. from score_reactions_from_genes on the template).
series selects which staged schedule to run — see get_init_steps for
what each option changes (default '1+1'); pass steps directly to use a
custom schedule instead. Each step regroups scores under its ignore_mask, fixes
the reactions turned on by earlier steps as essential (in their flux direction), and
solves run_ftinit on the merged model. Reactions never turned on (and not
essential or left-in) are removed from the reference model; exchange reactions are
always kept (RAVEN re-adds them).
If fill_gaps and prep carries tasks, reactions are added back so every task
is feasible (raven_toolbox.init.fill_tasks). If gene_scores is given,
negative-scoring genes are pruned from the GPRs at the end
(raven_toolbox.init.remove_low_score_genes).
Essential reactions are forced to carry force_on (default 0.1) of flux in the
forced direction. On genome-scale models a stricter regime is needed (the previous
step's actual carried flux instead of a flat 0.1) — exposed via per-reaction
essential_force on run_ftinit.
metabolomics is a list of detected metabolite names (case-insensitive,
prep.ref_model metabolite names — matched and unioned across every metabolite
sharing that name, e.g. the same compound in several compartments). Each is resolved
once, before the step loop, into its producer reactions (translated through the
merge groups so the resolution survives the linear merge collapsing them into
combined reactions) and rewarded prod_weight in every step's objective when any
producer is on — see run_ftinit's own metabolomics/prod_weight
docstring for the MILP mechanics and its one caveat (the bonus checks a producer is
"on", not that the metabolite is verifiably net-produced through it). A name that
matches no metabolite in prep.ref_model warns rather than silently doing nothing.
Ported from RAVEN 3's ftINITInternalAlg. The big_m=100 default relies on the
model being rescaled first, not on a per-reaction cap — see the INIT parameter calibration study <https://github.com/CompMetEng/raven-docs/blob/main/docs/parameter-tuning/studies/init-param-calibration.md>_.
mip_gap/time_limit are forwarded to each run_ftinit solve. On
genome-scale models they are essential for tractability — see the INIT parameter calibration study <https://github.com/CompMetEng/raven-docs/blob/main/docs/parameter-tuning/studies/init-param-calibration.md>_
on raven-docs for the calibration table.
resolve_ties and prove_abs_gap (both opt-in, default off → exact RAVEN
behaviour) reduce the arbitrariness of the degenerate MILP's tie-break, yielding a more
parsimonious and more reproducible extracted model. They do not make the model
biologically more accurate: the alternative optima they choose among are equally
consistent with the expression data, so this only pins which optimum is returned. It
reduces the fragility of the MILP, not its correctness:
resolve_tiesadds a lexicographic phase 2 that selects the sparsest (then lowest-id) optimum, so the degenerate choice is pinned rather than left to the solver — applied both to each extraction step and to the task gap-fill.prove_abs_gapreplaces the loose relative-gap escalation with a single solve per step proven to this fixed absolute gap, so the kept-set objective is optimal at any scale — not an arbitrary within-gap incumbent. Try 1.0: on Human-GEM/DLD1 the escalation returns a solution 2.0 below the optimum at the first stage and 4.0 below at the second (351 kept reactions instead of 349), while every value in 1.0-2.0 proves the true optimum at ~2.4x the runtime. Tighter values are counter-productive — 0.5 and below stop being provable within the time limit and return the same model anyway.
seed (RAVEN's 1234), threads (RAVEN's 1) and the solver tolerances
feas_tol/opt_tol/int_feas_tol/presolve (RAVEN's 1e-9 and 2) are
forwarded to every step; see run_ftinit for what they trade off. Neither
seed nor threads makes the extraction stable
under small input changes, which is a separate property — see the ftINIT reproducibility study <https://github.com/CompMetEng/raven-docs/blob/main/docs/parameter-tuning/studies/ftinit-determinism.md>_
on raven-docs. Measured there on Human-GEM/DLD1: resolve_ties makes repeated builds
at a fixed seed identical and halves the seed-to-seed spread in predicted essential
genes (16 → 8 flips); its own tie-break phases can exhaust time_limit at genome
scale, in which case it reduces rather than eliminates that spread and raises a
warning. Baseline and resolve_ties on identical inputs already differ by ~10% of
essential-gene calls, both fully score-optimal — when comparing models before and
after a curation, apply the edit to the extracted model as a control, not only to the
template.
verbose prints one line per staged step and forwards to fill_tasks for
per-task gap-fill progress (matching RAVEN ftINIT's console report); silent by
default.
A stability-anchoring parameter (reference_reactions, biasing a re-extraction
toward a prior build's reaction choices) was implemented and tested against a real
curation here; it helped on one cell line and caused a 5x increase in spurious
essential-gene drift on another, traced to a network-topology regime swap the
reference-matching objective cannot see coming, and was removed. See the
reference_reactions postmortem <https://github.com/CompMetEng/raven-docs/blob/main/docs/parameter-tuning/studies/ftinit-reference-reactions.md>_
on raven-docs for the full account.
FtInitResult#
Result of run_ftinit.
gene_scores_from_expression#
gene_scores_from_expression(expression: Mapping[str, float], reference: Mapping[str, float] | float, *, factor: float=5.0, max_score: float=10.0, min_score: float=-5.0)
Gene scores from RNA-seq/array expression, RAVEN's 5·ln(level/reference).
This is tINIT's usual entry point (RNA-seq is the common case; single-cell and
HPA are alternative upstream sources). reference is either a per-gene
reference level (e.g. the cross-sample mean) or a single threshold for all genes:
a gene expressed above its reference scores positive, below it negative. The
score is clamped to [min_score, max_score]; non-positive level/reference (and
missing reference) → min_score (RAVEN maps these NaNs to -5).
get_init_steps#
get_init_steps(series: str='1+1', *, mets_to_ignore: Sequence[str]=())
Return the step schedule for a named ftINIT series (RAVEN getINITSteps).
'1+1' (default, step 1+2 merged), '2+1' (3-step), '1+0'/'2+0'
(skip the final GPR-less step), 'full' (single MILP). mets_to_ignore are
metabolite names removed from the stoichiometry in each step (e.g. H2O, H+).
group_rxn_scores#
group_rxn_scores(reduced_model: cobra.Model, orig_scores: Mapping[str, float], orig_rxn_ids: list[str], group_ids: list[int], to_zero: Iterable[str]=())
Sum original reaction scores over merged groups (RAVEN groupRxnScores).
orig_scores maps original reaction id → score; to_zero are reactions to
drop from the problem (the toIgnore masks) — their score becomes 0. Genuine
zeros and groups cancelling to zero become 0.01 so the MILP never sees an exactly
zero score. Returns {reduced_reaction_id: score}.
hpa_gene_scores#
hpa_gene_scores(hpa: HPAData, tissue: str, celltype: str | None=None, *, level_scores: Mapping[str, float] | None=None, multiple_celltype: str='best')
Numeric gene scores from HPA levels for one tissue (optionally one celltype).
Maps HPA's categorical levels to numbers via level_scores (default
HPA_LEVEL_SCORES). Genes absent from the tissue, or whose level is not in the
score table, are omitted from the output (downstream
score_reactions_from_genes will then fall back to no_gene_score for any
reaction whose genes are all absent).
When several cell types per tissue carry the gene, multiple_celltype chooses
between "best" (max score, RAVEN default) and "average" (mean across cell types).
HPAData#
Tidy HPA proteomics data: one row per (gene, tissue, cell type).
df columns: gene_id, gene_name, tissue, celltype, level,
reliability. level is the categorical string from HPA; map it to numbers via
hpa_gene_scores (or pass a custom level_scores).
HPARnaData#
Tidy HPA RNA-seq data: one row per (gene, tissue) with TPM.
df columns: gene_id, gene_name, tissue, tpm.
InitStep#
One ftINIT MILP step.
merge_linear#
merge_linear(model: cobra.Model, no_merge: Iterable[str]=())
Merge linearly-dependent reactions; return (reduced, orig_ids, group_ids, reversed).
no_merge reaction ids are never merged. The reduced model carries no genes
(merging makes GPRs meaningless); scores are remapped with
group_rxn_scores.
parse_hpa#
parse_hpa(path: str | Path)
Parse an HPA proteomics dump (normal_tissue.tsv; version ≥17 format).
Expected columns (any reasonable delimiter; HPA ships tab-separated):
Gene Gene name Tissue Cell type Level Reliability. Returns an
HPAData with one row per (gene, tissue, cell type).
parse_hpa_rna#
parse_hpa_rna(path: str | Path)
Parse an HPA RNA-seq dump.
Accepts the canonical ≥v17 tidy layout (Gene Gene name Tissue TPM, one row per
gene × tissue) or the older wide layout with one TPM column per tissue
(Gene Gene name TissueA TissueB ...) — the latter is melted into the same
tidy shape.
prep_init_model#
prep_init_model(template: cobra.Model, tasks: Iterable[Task] | None=None, *, ext_comp: str='e', spontaneous: Iterable[str]=(), custom: Iterable[str]=(), essential_cache_path=None, simplify: bool=True, scale: bool=True, verbose: bool=False, processes: int=1)
Build PrepData from a template model — the once-per-template work shared
by every ftINIT sample on this model.
With tasks, discovers the task-essential reactions (kept regardless of score),
orients them irreversibly in their required direction, and drops tasks that are
infeasible. Then classifies reactions into the omics-independent categories, linearly
merges, and (unless scale=False) rescales the merged model's stoichiometry
(rescale_for_init) so a single MILP big-M is valid across all reactions —
without this, genome-scale ftINIT is infeasible / intractable. simplify=False
skips RAVEN's dead-end/FVA-blocked removal and reversibility-tightening passes,
leaving a larger merged model that may reach a different extraction optimum.
essential_cache_path makes the (slow, genome-scale) essential-reaction discovery
resumable across interruptions — see find_task_essential_reactions.
Task-essential discovery runs with close_boundaries=True, matching RAVEN's
prepINITModel (which calls closeModel first), rather than
find_task_essential_reactions's own additive default — see the comment at the
call site for why the two callers differ.
verbose prints one line per phase (matching prepINITModel's numbered steps in
spirit) plus per-task progress during essential-reaction discovery; silent by default.
processes (default 1) parallelises task-essential discovery across tasks — see
find_task_essential_reactions. It does not affect the two simplify_model
passes below; those parallelise via cobra's own cobra.Configuration().processes
(set that separately if you want them faster too).
PrepData#
One-time ftINIT preprocessing of a template model (RAVEN prepData).
Built once per template, reused across samples. min_model is the merged model
the MILP runs on; orig_rxn_ids/group_ids map its reactions back to the
ref_model (the simplified, pre-merge reference). essential_rxns are in
merged ids and pre-oriented irreversibly (so the MILP forces flux forward).
masks is on ref_model (= original) ids.
ReactionMasks#
Reaction-category id sets (RAVEN's toIgnore*), in 8-bit-pattern order.
ignored(pattern) returns the union of the categories whose bit is set — the
reactions held out of (left untouched by) that MILP step.
remove_low_score_genes#
remove_low_score_genes(model: cobra.Model, gene_scores: Mapping[str, float], *, isozyme_scoring: str='max', complex_scoring: str='min', tied_reactions: list[str] | None=None)
Remove negative-scoring genes from GPRs (RAVEN removeLowScoreGenes).
Genes joined by OR are alternatives: the negative-scoring ones are removed, and when all alternatives are negative the least-negative one is kept. Genes joined by AND are subunits of a complex and are not removed individually.
Parameters
model: cobra.ModelThe model to prune. It is not changed.
gene_scores: Mapping[str, float]Gene id to score. Genes absent from it are unscored and never removed.
isozyme_scoring, complex_scoring: strHow the scores of OR alternatives and of complex subunits are aggregated (
"max"and"min"by default).tied_reactions: list of str, optionalWhen a list is given, the ids of the reactions in which an OR rule with only negative alternatives was cut to one of several alternatives with the same best score are appended to it, once per reaction. In such a rule the first of the tied alternatives in the rule is kept, so the result depends on the order of the rule. RAVEN keeps the first one too (CompMetEng/RAVEN#11); before that it kept the alphabetically first.
Returns
tuple of (cobra.Model, list of str)The pruned copy of the model, and the sorted ids of the genes removed from every rule they were in, and thus from the model.
rescale_for_init#
rescale_for_init(model: cobra.Model, max_stoich_diff: float=25.0)
Compress each reaction's stoichiometric dynamic range.
Large spreads in stoichiometric coefficients (e.g. a biomass/pool reaction with
coefficients from 1e-3 to 1e2) force correspondingly extreme flux magnitudes, so no
single MILP big-M fits all reactions. RAVEN, per reaction: caps every |coeff| at
max_stoich_diff × min|coeff| (keeping signs), then scales the whole reaction so its
mean |coeff| is 1. Bounds are reset to ±1000 afterwards. Modifies model in
place; only the merged MILP model is scaled (the final output maps back to the
unscaled ref_model by reaction id, so reaction selection is unaffected).
rna_gene_scores#
rna_gene_scores(rna: HPARnaData, tissue: str, *, reference: Mapping[str, float] | float | None=None, factor: float=5.0, max_score: float=10.0, min_score: float=-5.0)
Numeric gene scores from HPA RNA-seq TPM for one tissue.
Thin wrapper over raven_toolbox.init.score.gene_scores_from_expression (the same
5·ln(TPM/reference)-clamped scoring used elsewhere): selects the tissue, derives
a reference if none is given (per-gene mean TPM across all tissues — RAVEN's default
for arrayData.threshold), and returns {gene_id: score}.
factor scales how fast the score moves away from 0 as TPM diverges from
reference; max_score/min_score clamp the result to that range.
run_ftinit#
run_ftinit(model: cobra.Model, rxn_scores: Mapping[str, float] | None=None, *, essential_rxns: Iterable[str] | None=None, essential_directions: Mapping[str, int] | None=None, essential_force: Mapping[str, float] | None=None, allow_excretion: bool=False, rem_pos_rev: bool=False, ignore_mets: Iterable[str]=(), force_on: float=_FORCE_ON, force_on_ess: float=_FORCE_ON, big_m: float=_BIG_M, mip_gap: float | None=None, mip_gap_abs: float | None=None, time_limit: float | None=None, prove_abs_gap: float | None=None, resolve_ties: bool=False, metabolomics: Mapping[str, Iterable[str]] | None=None, prod_weight: float=0.5, seed: int=_EXTRACT_SEED, threads: int=_EXTRACT_THREADS, feas_tol: float=_EXTRACT_TOL, opt_tol: float=_EXTRACT_TOL, int_feas_tol: float=_EXTRACT_TOL, presolve: int=_EXTRACT_PRESOLVE)
Run the single-step ftINIT MILP and return the extracted model.
rxn_scores maps reaction id → score (default 0 → reaction left free in the
model, not scored or removable). essential_rxns are forced to carry flux
(≥ force_on_ess, overridable per reaction via essential_force);
essential_directions maps an essential reaction id to +1 (forward) or
-1 (reverse) for the forced direction (default forward). ignore_mets are
metabolite names whose mass balance is dropped (RAVEN's per-step "simple
metabolite" removal, e.g. H2O/H+). See the module docstring for the formulation.
This is the single-step variant; the staged schedule
(raven_toolbox.init.ftinit) calls it per step.
mip_gap / time_limit: the default None uses the solver's own
defaults (Gurobi: MIPGap≈1e-4, no time cap), which is fine for a single step
— solve time here is dominated by model construction, so a tight gap is
nearly free (measured on genome-scale Human-GEM, see the INIT parameter calibration study <https://github.com/CompMetEng/raven-docs/blob/main/docs/parameter-tuning/studies/init-param-calibration.md>_
on raven-docs). For the genome-scale staged
schedule (raven_toolbox.init.ftinit), an essential-forced step can
run away without a cap (one severely-degraded case ran >75 min unbounded);
set time_limit ≈120-600 s/step, and loosen mip_gap to 0.01 (or
0.005) for a ~37% speedup at ≥0.99 Jaccard vs. the tight-gap model.
prove_abs_gap, when set, proves the solve to this fixed absolute objective
gap instead of a relative mip_gap/mip_gap_abs — see the prove_abs_gap
parameter of ftinit for when to use it (recommended value: 1.0).
resolve_ties (opt-in, default off to preserve RAVEN parity) resolves the MILP's
degeneracy deterministically: after the score optimum is found, a lexicographic
phase 2 holds the objective and minimises the id-ordered count of "on" reactions, so
the kept set is the sparsest optimum found, independent of solver seed/version,
instead of an arbitrary tie-break. At genome scale the phase-2 solves themselves can
exhaust time_limit; when that happens the (still-adopted) incumbent is an
unproven tie-break and a warning is raised. The tie-break is skipped when the primary
solve itself stops at time_limit, since there is then no proven optimum to hold.
See _resolve_ties.
metabolomics (already in this model's id space — ftinit resolves a
caller-facing metabolite-name list into this once) maps a detected-metabolite label
to the set of reaction ids that produce it. A metabolite's mon indicator
(continuous, [0, 1]) is capped by the sum of its producers' own indicators and
contributes prod_weight to the objective when any producer is on — the reward
for keeping (or bringing back) a reaction the data itself scored badly, purely
because it makes a detected metabolite producible. A producer with score 0 is
pulled into the problem (given a continuous indicator, contributing nothing itself)
so it has something for mon to reference; a negative-score producer's indicator
gets an added flux floor (mirroring what a positive reaction already has), so "on"
means the reaction genuinely carries flux, not merely that it is permitted to. A
detected metabolite is dropped silently if any of its producers is already in
essential_rxns — it will be produced regardless (RAVEN
ftINITInternalAlg.m:106-111). This does not verify the metabolite is actually
net-produced through that specific reaction, only that the reaction is "on"; a
reaction whose real network role is consumption can still earn the bonus if it ends
up carrying flux in reverse (RAVEN's own documented trade-off — the rest of the
network's mass balance is trusted to make the "on" flag meaningful).
prod_weight is the per-metabolite reward in metabolomics's mon terms
(RAVEN's ftINITInternalAlg default when unset; ftINIT.m itself calls it with
5). Unused when metabolomics is not given.
seed is Gurobi's Seed parameter (RAVEN's 1234). The MILP is degenerate, so the
seed picks which of many equal-score optima the solver returns; varying it is the cheap
way to probe how much of a result rests on the tie-break rather than on the data.
feas_tol, opt_tol and int_feas_tol are Gurobi's FeasibilityTol,
OptimalityTol and IntFeasTol (RAVEN's 1e-9 each, Gurobi's minimum; Gurobi's own
defaults are 1e-6, 1e-6 and 1e-5), and presolve is Gurobi's Presolve (RAVEN's 2).
They are RAVEN parity settings: they steer which optimal vertex the degenerate MILP lands
on and how binaries round at the 0.5 on/off cut. An "off" binary may sit at up to
int_feas_tol and still permit flux up to big_m * int_feas_tol, so relaxing
int_feas_tol loosens the on/off gate in proportion to big_m. Their effect on
runtime and on the extracted model has not been benchmarked; leave them at the defaults
unless you are measuring that.
threads is Gurobi's Threads (RAVEN's 1). Raising it speeds the solve but
forfeits reproducibility: multi-threaded Gurobi races between equal optima, so two
runs of the same input can return different reaction sets. Left at 1 unless a caller
knowingly trades determinism for speed. Measured to have no effect on the swing
between different seeds (raising it is not a substitute for resolve_ties) — see the
ftINIT reproducibility study <https://github.com/CompMetEng/raven-docs/blob/main/docs/parameter-tuning/studies/ftinit-determinism.md>_
on raven-docs.
score_reactions_from_genes#
score_reactions_from_genes(model: cobra.Model, gene_scores: Mapping[str, float], *, isozyme_scoring: str='max', complex_scoring: str='min', no_gene_score: float=-2.0)
Score each reaction from per-gene scores via its GPR ({reaction_id: score}).
Isozymes (GPR OR) are combined with isozyme_scoring (default max);
complex subunits (AND) with complex_scoring (default min). A reaction
with no genes, or whose genes are all missing from gene_scores, gets
no_gene_score (default -2).
TaskFillResult#
Result of fill_tasks: the gap-filled model and what was added.