0001 function [reducedModel, deletedReactions, deletedMetabolites]=simplifyModel(model,...
0002 deleteUnconstrained, deleteDuplicates, deleteZeroInterval, deleteInaccessible, deleteMinMax, groupLinear, constrainReversible, reservedRxns, suppressWarnings)
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<2
0040 deleteUnconstrained=true;
0041 end
0042 if nargin<3
0043 deleteDuplicates=false;
0044 end
0045 if nargin<4
0046 deleteZeroInterval=false;
0047 end
0048 if nargin<5
0049 deleteInaccessible=false;
0050 end
0051 if nargin<6
0052 deleteMinMax=false;
0053 end
0054 if nargin<7
0055 groupLinear=false;
0056 end
0057 if nargin<8
0058 constrainReversible=false;
0059 end
0060 if nargin<9
0061 reservedRxns=[];
0062 else
0063 reservedRxns=convertCharArray(reservedRxns);
0064 end
0065 if nargin<10
0066 suppressWarnings=false;
0067 end
0068
0069 reducedModel=model;
0070 deletedReactions={};
0071 deletedMetabolites={};
0072
0073 if deleteUnconstrained==true
0074 if isfield(reducedModel,'unconstrained')
0075
0076 deletedMetabolites=reducedModel.mets(reducedModel.unconstrained~=0);
0077 reducedModel=removeMets(reducedModel,reducedModel.unconstrained~=0,false,false,false,true);
0078 reducedModel=rmfield(reducedModel,'unconstrained');
0079 end
0080 end
0081
0082 if deleteDuplicates==true
0083
0084
0085
0086 [reducedModel, rxnsToDelete, ~]=contractModel(reducedModel);
0087 deletedReactions=[deletedReactions; rxnsToDelete];
0088 end
0089
0090 if deleteZeroInterval==true
0091
0092 zeroIntervalReactions=and(reducedModel.lb==0,reducedModel.ub==0);
0093
0094 rxnsToDelete=setdiff(reducedModel.rxns(zeroIntervalReactions),reservedRxns);
0095 deletedReactions=[deletedReactions; rxnsToDelete];
0096
0097
0098 reducedModel=removeReactions(reducedModel,rxnsToDelete);
0099
0100
0101 notInUse=sum(reducedModel.S~=0,2)==0;
0102 deletedMetabolites=[deletedMetabolites;reducedModel.mets(notInUse)];
0103
0104
0105 reducedModel=removeMets(reducedModel,notInUse);
0106 end
0107
0108 if deleteInaccessible==true
0109
0110
0111
0112 if isfield(reducedModel,'unconstrained') && suppressWarnings==false
0113 EM='Removing dead-end reactions before removing exchange metabolites';
0114 dispEM(EM,false);
0115 end
0116
0117 while true
0118
0119
0120
0121
0122
0123
0124
0125
0126 in=any(reducedModel.b<0,2);
0127 out=any(reducedModel.b>0,2);
0128 I=speye(numel(reducedModel.mets));
0129 revS=[reducedModel.S,reducedModel.S(:,reducedModel.lb<0)*-1 I(:,in) I(:,out)*-1];
0130
0131 metUsage=sum(abs(revS')>0);
0132 onlyProducts=sum(revS'>0) == metUsage;
0133 onlyReactants=sum(revS'<0) == metUsage;
0134
0135
0136
0137
0138 notInUse=onlyProducts | onlyReactants | (sum(abs(reducedModel.S')>0)<=1 & (~in & ~out)');
0139 deletedRxn=false;
0140 if any(notInUse)
0141
0142 rxnsNotInUse=sum(abs(reducedModel.S(notInUse,:))>0,1)>0;
0143 rxnsToDelete=setdiff(reducedModel.rxns(rxnsNotInUse),reservedRxns);
0144 deletedReactions=[deletedReactions; rxnsToDelete];
0145
0146
0147 reducedModel=removeReactions(reducedModel,rxnsToDelete);
0148
0149
0150
0151 notInUse=sum(reducedModel.S~=0,2)==0;
0152 deletedMetabolites=[deletedMetabolites; reducedModel.mets(notInUse)];
0153 reducedModel=removeMets(reducedModel,notInUse);
0154
0155
0156
0157 if ~isempty(rxnsToDelete)
0158 deletedRxn=true;
0159 end
0160 else
0161 break;
0162 end
0163 if deletedRxn==false
0164 break;
0165 end
0166 end
0167 end
0168
0169 if deleteMinMax==true
0170
0171
0172 I=~haveFlux(reducedModel);
0173
0174
0175 rxnsToDelete=setdiff(reducedModel.rxns(I),reservedRxns);
0176 deletedReactions=[deletedReactions; rxnsToDelete];
0177 reducedModel=removeReactions(reducedModel,rxnsToDelete);
0178
0179
0180 notInUse=sum(reducedModel.S~=0,2)==0;
0181 deletedMetabolites=[deletedMetabolites; reducedModel.mets(notInUse)];
0182 reducedModel=removeMets(reducedModel,notInUse);
0183 end
0184
0185 if constrainReversible==true
0186 revs=find(reducedModel.rev);
0187 [I,J]=getAllowedBounds(reducedModel,revs);
0188
0189 I=abs(I);
0190 J=abs(J);
0191
0192
0193 K=I<10^-10;
0194 L=J<10^-10;
0195
0196
0197 I(K==L)=[];
0198 J(K==L)=[];
0199 revs(K==L)=[];
0200
0201
0202 reducedModel.rev(revs(J>10^-10))=0;
0203 reducedModel.lb(revs(J>10^-10))=0;
0204
0205 toSwitch=revs(I>10^-10);
0206 reducedModel.rev(toSwitch)=0;
0207 reducedModel.ub(toSwitch)=reducedModel.lb(toSwitch)*-1;
0208 reducedModel.lb(toSwitch)=0;
0209 reducedModel.S(:,toSwitch)=reducedModel.S(:,toSwitch).*-1;
0210 reducedModel.c(toSwitch)=reducedModel.c(toSwitch)*-1;
0211 end
0212 if groupLinear==true
0213 if suppressWarnings==false
0214 fprintf('NOTE: You have chosen to group linear reactions. This option does not keep track of gene/reaction associations when reactions are merged. Deleting all gene information\n');
0215 end
0216
0217 reducedModel.genes={};
0218 reducedModel.rxnGeneMat=sparse(numel(reducedModel.rxns),0);
0219 reducedModel.grRules(:)={''};
0220
0221 if isfield(reducedModel,'geneShortNames')
0222 reducedModel.geneShortNames={};
0223 end
0224 if isfield(reducedModel,'proteins')
0225 reducedModel.proteins={};
0226 end
0227 if isfield(reducedModel,'geneMiriams')
0228 reducedModel.geneMiriams={};
0229 end
0230 if isfield(reducedModel,'geneComps')
0231 reducedModel.geneComps=[];
0232 end
0233
0234
0235 irrevModel=convertToIrrev(reducedModel);
0236
0237
0238 while 1
0239
0240
0241
0242 bannedIndexes=getIndexes(irrevModel,reservedRxns,'rxns');
0243
0244
0245
0246 singleNegative=find(sum(irrevModel.S'<0)==1);
0247 singlePositive=find(sum(irrevModel.S'>0)==1);
0248
0249
0250 common=intersect(singleNegative,singlePositive);
0251
0252 mergedSome=false;
0253
0254
0255
0256 for i=1:numel(common)
0257 involvedRxns=find(irrevModel.S(common(i),:));
0258
0259
0260
0261 if numel(involvedRxns)==2 && isempty(intersect(bannedIndexes,involvedRxns))
0262
0263
0264 stoichRatio=abs(irrevModel.S(common(i),involvedRxns(1))/irrevModel.S(common(i),involvedRxns(2)));
0265
0266
0267 irrevModel.S(:,involvedRxns(1))=irrevModel.S(:,involvedRxns(1))+irrevModel.S(:,involvedRxns(2))*stoichRatio;
0268
0269
0270 irrevModel.S(:,involvedRxns(2))=0;
0271
0272
0273
0274 irrevModel.S(common(i),involvedRxns(1))=0;
0275
0276
0277
0278
0279
0280
0281
0282
0283 lb1=irrevModel.lb(involvedRxns(1));
0284 lb2=irrevModel.lb(involvedRxns(2));
0285 ub1=irrevModel.ub(involvedRxns(1));
0286 ub2=irrevModel.ub(involvedRxns(2));
0287
0288 if lb2~=-inf
0289 irrevModel.lb(involvedRxns(1))=max(lb1,lb2/stoichRatio);
0290 end
0291 if ub2~=inf
0292 irrevModel.ub(involvedRxns(1))=min(ub1,ub2/stoichRatio);
0293 end
0294
0295
0296
0297 irrevModel.c(involvedRxns(1))=irrevModel.c(involvedRxns(1))+irrevModel.c(involvedRxns(2))*stoichRatio;
0298
0299
0300 mergedSome=true;
0301 end
0302 end
0303
0304
0305 if mergedSome==false
0306 break;
0307 end
0308
0309
0310 I=find(sum(irrevModel.S~=0)==0);
0311
0312
0313 irrevModel=removeReactions(irrevModel,I);
0314
0315
0316 notInUse=sum(irrevModel.S~=0,2)==0;
0317 irrevModel=removeMets(irrevModel,notInUse);
0318 end
0319
0320 reducedModel=irrevModel;
0321 end
0322 end