0001 function [outModel, addedRxns]=fitTasks(model,refModel,inputFile,printOutput,rxnScores,taskStructure)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 if nargin<4
0040 printOutput=true;
0041 end
0042 if nargin<5
0043 rxnScores=ones(numel(refModel.rxns),1)*-1;
0044 end
0045 if isempty(rxnScores)
0046 rxnScores=ones(numel(refModel.rxns),1)*-1;
0047 end
0048 if nargin<6
0049 taskStructure=[];
0050 end
0051
0052 if isempty(taskStructure) && ~isfile(inputFile)
0053 error('Task file %s cannot be found',string(inputFile));
0054 end
0055
0056 if strcmpi(model.id,refModel.id)
0057 fprintf('NOTE: The model and reference model have the same IDs. The ID for the reference model was set to "refModel" in order to keep track of the origin of reactions.\n');
0058 refModel.id='refModel';
0059 end
0060
0061 if any(rxnScores>=0)
0062 EM='Only negative values are allowed in rxnScores';
0063 dispEM(EM);
0064 end
0065
0066
0067 model.b=zeros(numel(model.mets),2);
0068 modelMets=upper(strcat(model.metNames,'[',model.comps(model.metComps),']'));
0069
0070
0071 largeModelMets=upper(strcat(refModel.metNames,'[',refModel.comps(refModel.metComps),']'));
0072
0073 if ~isfield(model,'unconstrained')
0074 EM='Exchange metabolites should normally not be removed from the model when using checkTasks. Inputs and outputs are defined in the task file instead. Use importModel(file,false) to import a model with exchange metabolites remaining';
0075 dispEM(EM,false);
0076 end
0077
0078 if isempty(taskStructure)
0079 taskStructure=parseTaskList(inputFile);
0080 end
0081
0082 tModel=model;
0083 addedRxns=false(numel(refModel.rxns),numel(taskStructure));
0084 supressWarnings=false;
0085 nAdded=0;
0086 for i=1:numel(taskStructure)
0087 if ~taskStructure(i).shouldFail
0088
0089 if ~isempty(taskStructure(i).inputs)
0090 [I, J]=ismember(upper(taskStructure(i).inputs),modelMets);
0091 K=ismember(upper(taskStructure(i).inputs),'ALLMETS');
0092 L=~cellfun('isempty',strfind(upper(taskStructure(i).inputs),'ALLMETSIN'));
0093
0094
0095 goodMets=I|K|L;
0096 if ~all(goodMets)
0097
0098
0099 [found, metMatch]=ismember(upper(taskStructure(i).inputs(~goodMets)),largeModelMets);
0100 if ~all(found)
0101 EM=['Could not find all inputs in "[' taskStructure(i).id '] ' taskStructure(i).description '" in either model'];
0102 disp(EM);
0103 else
0104
0105 met.metNames=refModel.metNames(metMatch);
0106 met.compartments=refModel.comps(refModel.metComps(metMatch));
0107
0108
0109
0110 model=addMets(model,met);
0111 tModel=addMets(tModel,met);
0112 modelMets=[modelMets;upper(taskStructure(i).inputs(~goodMets))];
0113 end
0114
0115
0116
0117
0118 I(~goodMets)=true;
0119 J(~goodMets)=numel(modelMets)-numel(metMatch)+1:numel(modelMets);
0120 end
0121 if numel(J(I))~=numel(unique(J(I)))
0122 EM=['The constraints on some input(s) in "[' taskStructure(i).id '] ' taskStructure(i).description '" are defined more than one time'];
0123 dispEM(EM);
0124 end
0125
0126 if any(K)
0127
0128
0129
0130 if K(1)==0
0131 EM=['ALLMETS is used as an input in "[' taskStructure(i).id '] ' taskStructure(i).description '" but it it not the first metabolite in the list. Constraints defined for the metabolites before it will be over-written'];
0132 dispEM(EM,false);
0133 end
0134
0135
0136 tModel.b(:,1)=taskStructure(i).UBin(find(K,1))*-1;
0137 end
0138
0139 if any(L)
0140 L=find(L);
0141 for j=1:numel(L)
0142
0143 compartment=upper(taskStructure(i).inputs{L(j)}(11:end-1));
0144
0145 C=find(ismember(upper(model.comps),compartment));
0146 if any(C)
0147
0148 tModel.b(model.metComps==C,1)=taskStructure(i).UBin(L(j))*-1;
0149 else
0150 EM=['The compartment defined for ALLMETSIN in "[' taskStructure(i).id '] ' taskStructure(i).description '" does not exist'];
0151 dispEM(EM);
0152 end
0153 end
0154 end
0155
0156 if any(J(I))
0157 tModel.b(J(I),1)=taskStructure(i).UBin(I)*-1;
0158 tModel.b(J(I),2)=taskStructure(i).LBin(I)*-1;
0159 end
0160 end
0161
0162 if ~isempty(taskStructure(i).outputs)
0163 [I, J]=ismember(upper(taskStructure(i).outputs),modelMets);
0164 K=ismember(upper(taskStructure(i).outputs),'ALLMETS');
0165 L=~cellfun('isempty',strfind(upper(taskStructure(i).outputs),'ALLMETSIN'));
0166
0167
0168 goodMets=I|K|L;
0169 if ~all(goodMets)
0170
0171
0172 [found, metMatch]=ismember(upper(taskStructure(i).outputs(~goodMets)),largeModelMets);
0173 if ~all(found)
0174 EM=['Could not find all outputs in "[' taskStructure(i).id '] ' taskStructure(i).description '" in either model'];
0175 dispEM(EM);
0176 else
0177
0178 met.metNames=refModel.metNames(metMatch);
0179 met.compartments=refModel.comps(refModel.metComps(metMatch));
0180
0181
0182
0183 model=addMets(model,met);
0184 tModel=addMets(tModel,met);
0185 modelMets=[modelMets;upper(taskStructure(i).outputs(~goodMets))];
0186 end
0187
0188
0189
0190
0191 I(~goodMets)=true;
0192 J(~goodMets)=numel(modelMets)-numel(metMatch)+1:numel(modelMets);
0193 end
0194 if numel(J(I))~=numel(unique(J(I)))
0195 EM=['The constraints on some output(s) in "[' taskStructure(i).id '] ' taskStructure(i).description '" are defined more than one time'];
0196 dispEM(EM);
0197 end
0198
0199 if any(K)
0200
0201
0202
0203 if K(1)==0
0204 EM=['ALLMETS is used as an output in "[' taskStructure(i).id '] ' taskStructure(i).description '" but it it not the first metabolite in the list. Constraints defined for the metabolites before it will be over-written'];
0205 dispEM(EM,false);
0206 end
0207
0208
0209 tModel.b(:,2)=taskStructure(i).UBout(find(K,1));
0210 end
0211
0212 if any(L)
0213 L=find(L);
0214 for j=1:numel(L)
0215
0216 compartment=upper(taskStructure(i).outputs{L(j)}(11:end-1));
0217
0218 C=find(ismember(upper(model.comps),compartment));
0219 if any(C)
0220
0221 tModel.b(model.metComps==C,2)=taskStructure(i).UBout(L(j));
0222 else
0223 EM=['The compartment defined for ALLMETSIN in "[' taskStructure(i).id '] ' taskStructure(i).description '" does not exist'];
0224 dispEM(EM);
0225 end
0226 end
0227 end
0228
0229 if any(J(I))
0230
0231
0232
0233 J = J(I);
0234 I = find(I);
0235 nonzero_LBin = tModel.b(J,2) < 0;
0236 nonzero_LBout = taskStructure(i).LBout(I) > 0;
0237 if any(nonzero_LBin & nonzero_LBout)
0238 EM=['The IN LB and OUT LB in "[' taskStructure(i).id '] ' taskStructure(i).description '" cannot be nonzero for the same metabolite'];
0239 dispEM(EM);
0240 end
0241 tModel.b(J(nonzero_LBout),1)=taskStructure(i).LBout(I(nonzero_LBout));
0242 tModel.b(J,2)=taskStructure(i).UBout(I);
0243 end
0244 end
0245
0246
0247 if ~isempty(taskStructure(i).equations)
0248 rxn.equations=taskStructure(i).equations;
0249 rxn.lb=taskStructure(i).LBequ;
0250 rxn.ub=taskStructure(i).UBequ;
0251 rxn.rxns=strcat({'TEMPORARY_'},num2str((1:numel(taskStructure(i).equations))'));
0252 tModel=addRxns(tModel,rxn,3);
0253 end
0254
0255 if ~isempty(taskStructure(i).changed)
0256 tModel=setParam(tModel,'lb',taskStructure(i).changed,taskStructure(i).LBrxn);
0257 tModel=setParam(tModel,'ub',taskStructure(i).changed,taskStructure(i).UBrxn);
0258 end
0259
0260
0261 sol=solveLP(tModel);
0262 if isempty(sol.x)
0263
0264 failed=false;
0265 try
0266 [~, ~, newRxns, newModel, exitFlag]=fillGaps(tModel,refModel,false,true,supressWarnings,rxnScores);
0267 if exitFlag==-2
0268 EM=['"[' taskStructure(i).id '] ' taskStructure(i).description '" was aborted before reaching optimality.\n'];
0269 dispEM(EM,false);
0270 end
0271 catch
0272 EM=['"[' taskStructure(i).id '] ' taskStructure(i).description '" could not be performed for any set of reactions\n'];
0273 dispEM(EM,false);
0274 failed=true;
0275 end
0276 if failed==false
0277 if ~isempty(newRxns)
0278 nAdded=nAdded+numel(newRxns);
0279
0280
0281
0282
0283 model=mergeModels({model,removeReactions(newModel,setdiff(newModel.rxns,newRxns),true,true)},'metNames',true);
0284
0285
0286 addedRxns(ismember(refModel.rxns,newRxns),i)=true;
0287 end
0288 if printOutput==true
0289 fprintf(['[' taskStructure(i).id '] ' taskStructure(i).description ': Added ' num2str(numel(newRxns)) ' reaction(s), ' num2str(nAdded) ' reactions added in total\n']);
0290 end
0291 end
0292 else
0293 if printOutput==true
0294 fprintf(['[' taskStructure(i).id '] ' taskStructure(i).description ': Added 0 reaction(s), ' num2str(nAdded) ' reactions added in total\n']);
0295 end
0296 end
0297 supressWarnings=true;
0298
0299
0300 if taskStructure(i).printFluxes && printOutput
0301 if ~isempty(sol.x)
0302 sol=solveLP(tModel,1);
0303 printFluxes(tModel,sol.x,false,10^-5,[],'%rxnID (%eqn):%flux\n');
0304 fprintf('\n');
0305 else
0306
0307
0308 if failed==false
0309 sol=solveLP(newModel,1);
0310 printFluxes(newModel,sol.x,false,10^-5,[],'%rxnID (%eqn):%flux\n');
0311 fprintf('\n');
0312 end
0313 end
0314 end
0315
0316 tModel=model;
0317
0318
0319 modelMets=upper(strcat(model.metNames,'[',model.comps(model.metComps),']'));
0320 else
0321 EM=['"[' taskStructure(i).id '] ' taskStructure(i).description '" is set as SHOULD FAIL. Such tasks cannot be modelled using this approach and the task is therefore ignored\n'];
0322 dispEM(EM,false);
0323 end
0324 end
0325 model.b(:,2) = [];
0326 outModel=model;
0327 end