Repository navigation
Conversation
…s mode - `false = False` -> `first = False`: the first-media flag never cleared, so the database prefilter ran again for every media. Later media now skip the prefilter (prefilter=False) as the else arm intended. They keep passing the caller's target: the else arm passed None, which makes run_gapfilling fall back to self.default_target (an AttributeError when the MSGapfill was built without default_target) and mislabels gf_sensitivity entries. - simultaneous_gapfilling=True looped with `pass` and returned None; it now raises NotImplementedError. - Tests: prefilter only on the first media (run_gapfilling mocked), NotImplementedError, and run_multi_gapfill without default_target matches separate run_gapfilling calls. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.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.
Why this matters in our workflow
We build models with
MSBuilder.build(). Its ATP correction callsrun_multi_gapfillon every ATP medium the coremodel cannot use. That caller passes no
test_conditions, so for us the typo costs only a repeated feasibility LP,and the models do not change. We also plan to gap-fill several growth conditions with ATP tests as
test_conditions. In that case the typo changes the results (below).What happens
msgapfill.pyL298-L321 at 062714b:false = Falseinstead offirst = False. The flag never clears, soevery medium takes the
firstbranch withprefilter=True, and theelsearm (prefilter=False) is dead code.The typo came in with b1e7ff4 (May 2023).
Nonein simultaneous mode.simultaneous_gapfilling=Truerunsfor item in media_list: pass, and thereturnsits inside theelse, so the call returnsNone.The fix
Why later media keep
targetinstead of theelsearm'sNone. Fixing only the typo makes theelsearm live,and two problems follow:
run_gapfilling(target=None)falls back toself.default_target. That attribute exists only when theMSGapfillwas built with
default_target. SoMSGapfill(model, [template]).run_multi_gapfill([m1, m2], target), which workson dev, would raise
AttributeError: 'MSGapfill' object has no attribute 'default_target'.target=None,test_gapfill_databasereads the target name fromstr(gfmodel.objective), which at thatpoint is the gap-fill penalty objective. In a build with only the typo fixed, the
gf_sensitivityattribute got"7*rxn00011_c0"instead of"ATPM_c0"for every medium that could not be gap-filled. Dev itself does not do this,because the
elsearm is dead there.Passing
targetsets the objective that is already set.Results change for callers that pass
test_conditionsWith the fix, the database is filtered once, on the first medium, as the
elsearm intended. Before, it was filteredagain for every medium, which also re-filtered reactions that an earlier pass had restored. So the solutions for
media after the first can differ.
A toy case shows this. Take
e_coli_corewithout CYTBD, NADH16, GLCpts, O2t, PPCK, ME1 and ME2, with ATPM lowerbound 0.
test_conditionsis "ATP stays 0 on an empty medium", and the media are glucose, acetate and succinate, inthat order. Here is the
newset for each medium:run_gapfillingon that medium aloneAcetate loses ME1 and now matches the single-medium run. Succinate is unchanged; on both dev and the branch it keeps a
reaction that the single-medium run does not need.
Inside the package, no code calls
run_multi_gapfillwithtest_conditions. The callers aremsatpcorrection.py:335, which passes none, and a commented-out call atmsgrowthphenotypes.py:607. Chris Henry'sfork moved the same way: its current
run_multi_gapfillfilters once across all media and passes the target for eachmedium. If you would rather filter every medium, the alternative is to drop the
elsearm and always passprefilter.Tests
These are added to
tests/core/test_msgapfill.py, with amedia_acetate_aerobicfixture next tomedia_glucose_aerobic:test_run_multi_gapfill_prefilters_only_first_media: withrun_gapfillingmocked, the first medium is called with(target, prefilter=True)and the second with(target, prefilter=False), and the per-medium minimum objective ispassed through.
test_run_multi_gapfill_simultaneous_not_implemented.test_run_multi_gapfill_matches_single_runs:run_multi_gapfillwithoutdefault_target, on glucose and acetate,gives the same solutions as separate
run_gapfillingcalls. It passes on dev, where theelsearm is dead, and itfails on a typo-only fix.
Against dev's code, 2 failed and 1 passed:
Against the typo-only fix, all 3 failed:
With this PR, all 3 pass.
Full suite (Python 3.10, cobra 0.32.1, CPLEX 22.1.1):
tests/coregoes from 56 to 59 passed, andtests/from 58 to61.
black22.8.0 and the other pre-commit hooks pass.Real-model check
We ran
MSBuilder.build()on two genome-scale builds (E. coli K-12 and a Pantoea strain, from RAST annotations,GramNeg template v7.1 with Core-V6.1, minimal glucose), once on dev and once on this branch. The prefilter in the
ATP-correction step ran 20 and 39 times on dev and once on the branch. Everything else was identical: the final
models (reactions, bounds, GPR logic, stoichiometry), every gap-fill result, the ATP correction outputs, and growth.
Related
reached dev, and it keeps
Noneas the target for later media.🤖 Generated with Claude Code