Open oxinabox opened 1 week ago
Hi! Thanks for the detailed reproducer, this indeed looks weird.
If I get it right, the reaction that gets gapfilled is the ATP maintenance or something similar? If that is so, it gets gapfilled literally because it is constrainted to strictly nonzero flux, and if you wouldn't include it in the fill, it would have a zero value in the model, making the model infeasible. This is the outcome of how the problem is encoded into a MILP, and of the fact that original bounds in the universal reactions are retained.
If the above is the case: maintenance pseudoreactions should not be included in universal reactions (they are more like extra constraints encoded as reactions), and removing them will solve the issue.
I recall we have this removal of ATPM in at least one of the examples. If it is not in the gapfilling one, we should certainly add it there. Maybe together with a mild warning about this possible issue.
If the reason is different then please do elaborate, because that would be very weird.
PS re why cobrapy works: they might either auto-ignore these reactions, or use a different encoding into MILP that also selectively ignores the constraints, or fix/remove the bounds. Will have a look.
This is indeed ATPM. It is mentioned removing it in example but no details as to why. Maybe we need to add those details to the docs or have a function or a fag to remove this kind automatically?
automated cleaning is kinda desirable so I'll continue with this within a greater scope of #81
I was showing someone that if you give gapfilling a model that is feasible already, even if you change the objective to be something that can be improved by knocking in some genes, it still won't say to insert them. To do this i found 10 genes i could KO that would decrease CO2 production, and then set objective to maximise CO2 production (which is kinda nonsense to do but anyway) and ran gap-filling to my surprise it actually decided to fill in something. But it wasn't even something I had knocked out (though it was something that had fixed bounds, so knocking in an extra copy accelerates it)
In contrast, when I run this exact same investigation in Cobrapy (I can provide code for that if you want) this does not occur and as expected it return an empty set.
There may be some interaction with having basically identical model and universal model, as I did not see this when i used metanetx 's largest universal model (which probably has this reaction).
Minimal code example to reproduce the problem
using my fav yeast-9: https://raw.githubusercontent.com/SysBioChalmers/yeast-GEM/refs/heads/main/model/yeast-GEM.xml
Expected result
It should not try and fill anything, because the model is already feasible
Actual behavior
It tries to fill 1 reaction
you can see which with:
The extra surprising thing is it didn't even put in one i deleted. It put in one that was already there, and which doesn't have a gene associated