0001 function [reducedModel, removedRxns, indexedDuplicateRxns]=contractModel(model,distReverse,mets)
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 if nargin<2
0031 distReverse=true;
0032 end
0033
0034
0035
0036 modelS=sortModel(model);
0037
0038
0039 if distReverse
0040 x=[modelS.S; model.rev']';
0041 else
0042 x=modelS.S';
0043 end
0044 if nargin>2
0045 toCheck = getIndexes(model,mets,'mets');
0046 [~, toCheck] = find(modelS.S(toCheck,:));
0047 x = [x, (1:size(x,1))'];
0048 x(toCheck,end) = 0;
0049 end
0050
0051 [~,I,J] = unique(x,'rows','first');
0052
0053
0054 indexedDuplicateRxns=cell(numel(model.rxns),1);
0055 indexedDuplicateRxns(:)={''};
0056
0057 duplicateRxns=setdiff(1:numel(model.rxns),I);
0058 mergeTo=I(J(duplicateRxns));
0059
0060 mergedRxns=unique(mergeTo);
0061
0062
0063
0064
0065 for i=1:numel(mergedRxns)
0066 duplRxn=transpose([mergedRxns(i),duplicateRxns(mergeTo==mergedRxns(i))]);
0067 if numel(unique(model.lb(duplRxn)))>1
0068 EM=['Duplicates of reaction ' model.rxns{mergedRxns(i)} ' have different lower bound. Uses the most negative/smallest lower bound'];
0069 dispEM(EM,false);
0070 model.lb(mergedRxns(i))=min(model.lb(duplRxn));
0071 end
0072 if numel(unique(model.ub(duplRxn)))>1
0073 EM=['Duplicates of reaction ' model.rxns{mergedRxns(i)} ' have different upper bound. Uses the most positive/largest upper bound'];
0074 dispEM(EM,false);
0075 model.ub(mergedRxns(i))=max(model.ub(duplRxn));
0076 end
0077 if numel(unique(model.c(duplRxn)))>1
0078 EM=['Duplicates of reaction ' model.rxns{mergedRxns(i)} ' has a different objective function coefficient. Uses the largest coefficient'];
0079 dispEM(EM,false);
0080 model.c(mergedRxns(i))=max(model.c(duplRxn));
0081 end
0082 if isfield(model,'grRules') && any(~isempty(model.grRules(duplRxn)))
0083 rules=model.grRules(duplRxn);
0084 allRules={};
0085 for j=1:numel(rules)
0086 rules{j}=ignoreORinComplex(rules{j});
0087 allRules=[allRules regexp(rules{j},' or ','split')];
0088 end
0089 allRules=unique(allRules);
0090 allRules=strrep(allRules,'__OR__',' or ');
0091 andRules=contains(allRules,' and ');
0092 allRules(andRules)=strcat('(',allRules(andRules),')');
0093 if numel(allRules)==1
0094 model.grRules{mergedRxns(i)}=allRules{1};
0095 else
0096 model.grRules{mergedRxns(i)}=strjoin(allRules,' or ');
0097 end
0098 end
0099 if isfield(model,'eccodes') && any(~isempty(model.eccodes(duplRxn)))
0100 codes=model.eccodes(duplRxn);
0101 allCodes={};
0102 for j=1:numel(codes)
0103 allCodes=[allCodes regexp(codes{j},';','split')];
0104 end
0105 allCodes=unique(allCodes);
0106 if numel(allCodes)==1
0107 model.eccodes{mergedRxns(i)}=allCodes{1};
0108 else
0109 model.eccodes{mergedRxns(i)}=strjoin(allCodes,';');
0110 end
0111 end
0112
0113 if numel(duplRxn)==2
0114 indexedDuplicateRxns{duplRxn(1)}=model.rxns{duplRxn(2)};
0115 else
0116 indexedDuplicateRxns{duplRxn(1)}=strjoin(model.rxns(duplRxn(2:end)),';');
0117 end
0118
0119
0120 if all(~cellfun(@isempty,regexp(model.rxns(duplRxn),'_EXP_\d+$')))
0121 model.rxns(duplRxn(1))=regexprep(model.rxns(duplRxn(1)),'_EXP_\d+$','');
0122 end
0123 end
0124
0125
0126 reducedModel=removeReactions(model,duplicateRxns);
0127 removedRxns=model.rxns(duplicateRxns);
0128 [~, index]=ismember(reducedModel.rxns,model.rxns);
0129 indexedDuplicateRxns=indexedDuplicateRxns(index);
0130
0131 if isfield(reducedModel,'rxnGeneMat')
0132
0133 [grRules,rxnGeneMat] = standardizeGrRules(reducedModel,true);
0134 reducedModel.grRules = grRules;
0135 reducedModel.rxnGeneMat = rxnGeneMat;
0136 end
0137 end
0138
0139 function grRule = ignoreORinComplex(grRule)
0140
0141
0142 grRule=['(' grRule ')'];
0143 brOpen=strfind(grRule,'(');
0144 brClose=strfind(grRule,')');
0145 andPos=strfind(grRule,' and ');
0146
0147 stillCapturing = 0;
0148 for i=1:numel(andPos)
0149 searchPos = andPos(i);
0150 while stillCapturing == 0
0151 closestOpen = brOpen(max(find(brOpen<searchPos)));
0152 inbetweenClose = brClose(brClose<searchPos & brClose>closestOpen);
0153 if ~isempty(inbetweenClose)
0154 searchPos=max(inbetweenClose);
0155 else
0156 stillCapturing = 1;
0157 beginPos = closestOpen;
0158 end
0159 end
0160 stillCapturing = 0;
0161 searchPos = andPos(i);
0162 while stillCapturing == 0
0163 closestClose = brClose(min(find(brClose>searchPos)));
0164 inbetweenOpen = brOpen(brOpen>searchPos & brOpen<closestOpen);
0165 if ~isempty(inbetweenOpen)
0166 searchPos=min(closestClose);
0167 else
0168 stillCapturing = 1;
0169 endPos = closestClose;
0170 end
0171 end
0172 replacePart=regexprep(grRule(beginPos:endPos),' or ','__OR__');
0173 grRule=strrep(grRule,grRule(beginPos:endPos),replacePart);
0174 end
0175 grRule=grRule(2:end-1);
0176 end