% To check and fix ATP cycles
% read the model
model = readCbModel('filename');
% make a copy of the model
model2 = model;
% find all exchange reactions
rxnEx = findExcRxns(model2);
rxnExId = model2.rxns(rxnEx);
% shut down all uptake reactions (LB = 0)
model2 = changeRxnBounds(model2, rxnExId, 0, 'l');
% make sure no positive lower bound or negative upper bound
model2.ub(model2.ub < 0) = 0;
% ATP maintenance reaction (ATP + H2O -> ADP + PI + H, usually called ATPM in BiGG format)
rxnATPMid = 'ATPM';
% Or may need to find the ATPM reaction
metATPM = findMetIDs(model,{'atp[c]','adp[c]','pi[c]','h[c]','h2o[c]'});
metATPMlogic = false(numel(model.mets),1);
metATPMlogic(metATPM) = true;
% reaction that involves only these metabolites is the ATPM
rxnATPM = find(all(model.S(metATPMlogic, :), 1) & ~any(model.S(~metATPMlogic, :), 1));
rxnATPMid = model.rxns(rxnATPM);
% set a lower bound for ATPM
model2 = changeRxnBounds(model, rxnATPMid, 1, 'l');
% no objective function. Just want to check if the model is feasible
model2.c(:) = 0;
%%%%%%%% With this setting, a sound model should be infeasible because when there is no uptake, the model should have no way to generate ATP %%%%%%%% to satisfy the ATP maintenance requirement.
%%%%%%%% Add the fixes here and re-solve the model until the model is infeasible (sol.stat == 0)
%%%%%%%% E.g., make some reactions irreversible, fix proton symport/antiport, correct wrong stoichiometries
% solve the model ('one' to minimize the sum of absolute fluxes for easier interpretation)
sol = optimizeCbModel(model2, 'max', 'one');
if sol.stat == 1
% feasible, meaning that there are internal ATP cycles making ATP to
% satisfy the ATPM requirement. Check the cycles
surfNet(model2, model2.rxns(sol.x ~= 0), 0, sol.x, 1, 0)
% Find out what does not make sense in this solution. Then add the fixes to above and re-solve
else
fprintf('No ATP cycles\n')
end