diff --git a/core/checkModelStruct.m b/core/checkModelStruct.m
index 7526d590..1ba21cb0 100755
--- a/core/checkModelStruct.m
+++ b/core/checkModelStruct.m
@@ -120,6 +120,21 @@ function checkModelStruct(model,throwErrors,trimWarnings)
EM='The "grRules" field must be a cell array of strings';
dispEM(EM,throwErrors);
end
+ if ~isfield(model,'genes')
+ EM='If "grRules" field exists, the model should also contain a "genes" field';
+ dispEM(EM,throwErrors);
+ else
+ geneList = strjoin(model.grRules);
+ geneList = regexp(geneList,' |)|(|and|or','split'); % Remove all grRule punctuation
+ geneList = geneList(~cellfun(@isempty,geneList)); % Remove spaces and empty genes
+ geneList = setdiff(unique(geneList),model.genes);
+ if ~isempty(geneList)
+ problemGrRules = model.rxns(contains(model.grRules,geneList));
+ problemGrRules = strjoin(problemGrRules(:),'; ');
+ EM=['The reaction(s) "' problemGrRules '" contain the following genes in its "grRules" field, but these are not in the "genes" field:'];
+ dispEM(EM,throwErrors,geneList);
+ end
+ end
end
if isfield(model,'rxnComps')
if ~isnumeric(model.rxnComps)
@@ -262,7 +277,10 @@ function checkModelStruct(model,throwErrors,trimWarnings)
EM='The following reactions have contradicting bounds:';
dispEM(EM,throwErrors,model.rxns(model.lb>model.ub),trimWarnings);
EM='The following reactions have bounds contradicting their reversibility:';
-dispEM(EM,throwErrors,model.rxns(model.lb<0 & model.rev==0),trimWarnings);
+contradictBound = (model.lb < 0 & model.ub > 0 & model.rev==0) | ... % Reversible bounds, irreversible label
+ (model.lb < 0 & model.ub <= 0 & model.rev==1) | ... % Negative bounds, reversible label
+ (model.lb >= 0 & model.ub > 0 & model.rev==1); % Positive bounds, reversible label
+dispEM(EM,throwErrors,model.rxns(contradictBound),trimWarnings);
%Multiple or no objective functions not allowed in SBML L3V1 FBCv2
if numel(find(model.c))>1
diff --git a/core/constructS.m b/core/constructS.m
index 87ac8c89..5412cf24 100755
--- a/core/constructS.m
+++ b/core/constructS.m
@@ -152,7 +152,8 @@
strjoin(unique(metsToS(~metsPresent)),', ')],'')
else
missingMet = find(~metsPresent);
- missingMet = char(strcat(metsToS(missingMet),' (reaction:',rxns(rxnsToS(missingMet)),')\n'));
+ missingMet = strcat(metsToS(missingMet),' (reaction:',rxns(rxnsToS(missingMet)),')\n');
+ missingMet = strjoin(missingMet,'');
error(['Could not find the following metabolites (reaction indicated) in the metabolite list: \n' ...
missingMet '%s'],'');
end
diff --git a/core/getExchangeRxns.m b/core/getExchangeRxns.m
index 459bc095..6433a4e6 100755
--- a/core/getExchangeRxns.m
+++ b/core/getExchangeRxns.m
@@ -1,47 +1,82 @@
function [exchangeRxns, exchangeRxnsIndexes]=getExchangeRxns(model,reactionType)
% getExchangeRxns
-% Retrieves the exchange reactions from a model
+% Retrieves the exchange reactions from a model. Exchange reactions are
+% identified by having either no substrates or products.
%
+% Input:
% model a model structure
-% reactionType retrieve all reactions ('both'), only production
-% ('out'), or only consumption ('in') (optional, default
-% 'both')
+% reactionType which exchange reactions should be returned
+% 'all' all reactions, irrespective of reaction
+% bounds
+% 'uptake' reactions with bounds that imply that
+% only uptake are allowed. Reaction
+% direction, upper and lower bounds are
+% all considered
+% 'excrete' reactions with bounds that imply that
+% only excretion are allowed. Reaction
+% direction, upper and lower bounds are
+% all considered
+% 'reverse' reactions with non-zero upper and lower
+% bounds that imply that both uptake and
+% excretion are allowed
+% 'blocked' reactions that have zero upper and lower
+% bounds, not allowing any flux
+% 'in' reactions where the boundary metabolite
+% is the substrate of the reaction, a
+% positive flux value would imply uptake,
+% but reaction bounds are not considered
+% 'out' reactions where the boundary metabolite
+% is the substrate of the reaction, a
+% positive flux value would imply uptake,
+% but reaction bounds are not considered.
%
+% Output:
% exchangeRxns cell array with the IDs of the exchange reactions
% exchangeRxnsIndexes vector with the indexes of the exchange reactions
%
-% Exchange reactions are defined as reactions which involve only products
-% or only reactants. If the unconstrained field is present, then that is
-% used instead.
+% Note:
+% The union of 'in' and 'out' equals 'all'. Also, the union of 'uptake',
+% 'excrete', 'reverse' and 'blocked' equals all.
%
% Usage: [exchangeRxns,exchangeRxnsIndexes]=getExchangeRxns(model,reactionType)
if nargin<2
- reactionType='both';
+ reactionType='all';
else
reactionType=char(reactionType);
end
-hasNoProducts=sparse(numel(model.rxns),1);
-hasNoReactants=sparse(numel(model.rxns),1);
-
-if isfield(model,'unconstrained')
- if strcmpi(reactionType,'both') || strcmpi(reactionType,'out')
- [~, I]=find(model.S(model.unconstrained~=0,:)>0);
- hasNoProducts(I)=true;
- end
- if strcmpi(reactionType,'both') || strcmpi(reactionType,'in')
- [~, I]=find(model.S(model.unconstrained~=0,:)<0);
- hasNoReactants(I)=true;
- end
+% Find exchange reactions
+if isfield(model, 'unconstrained')
+ [~, I]=find(model.S(model.unconstrained~=0,:)>0);
+ hasNoProd(I)=true;
+ [~, I]=find(model.S(model.unconstrained~=0,:)<0);
+ hasNoSubs(I)=true;
else
- if strcmpi(reactionType,'both') || strcmpi(reactionType,'out')
- hasNoProducts=sum((model.S>0))==0;
- end
- if strcmpi(reactionType,'both') || strcmpi(reactionType,'in')
- hasNoReactants=sum((model.S<0))==0;
- end
+ hasNoProd = transpose(find(sum(model.S>0)==0));
+ hasNoSubs = transpose(find(sum(model.S<0)==0));
+end
+allExch = [hasNoProd; hasNoSubs];
+
+switch reactionType
+ case {'both','all'} % For legacy reasons, 'both' is also allowed
+ exchangeRxnsIndexes = allExch;
+ case 'in'
+ exchangeRxnsIndexes = hasNoSubs;
+ case 'out'
+ exchangeRxnsIndexes = hasNoProd;
+ case 'blocked'
+ exchangeRxnsIndexes = allExch(model.lb(allExch) == 0 & model.ub(allExch) == 0);
+ case 'reverse'
+ exchangeRxnsIndexes = allExch(model.lb(allExch) < 0 & model.ub(allExch) > 0);
+ case 'uptake'
+ exchangeRxnsIndexes = allExch([(model.lb(hasNoSubs) >= 0 & model.ub(hasNoSubs) > 0); ...
+ (model.lb(hasNoProd) < 0 & model.ub(hasNoProd) <= 0)]);
+ case 'excrete'
+ exchangeRxnsIndexes = allExch([(model.lb(hasNoSubs) < 0 & model.ub(hasNoSubs) <= 0); ...
+ (model.lb(hasNoProd) >= 0 & model.ub(hasNoProd) > 0)]);
+ otherwise
+ error('Invalid reactionType specified')
end
-exchangeRxnsIndexes=find(hasNoProducts(:) | hasNoReactants(:));
-exchangeRxns=model.rxns(exchangeRxnsIndexes);
+exchangeRxns = model.rxns(exchangeRxnsIndexes);
end
diff --git a/doc/core/checkModelStruct.html b/doc/core/checkModelStruct.html
index 2b49a88b..7cc327fe 100644
--- a/doc/core/checkModelStruct.html
+++ b/doc/core/checkModelStruct.html
@@ -179,305 +179,323 @@
SOURCE CODE 'The "grRules" field must be a cell array of strings';
0121 dispEM(EM,throwErrors);
0122 end
-0123 end
-0124 if isfield(model,'rxnComps')
-0125 if ~isnumeric(model.rxnComps)
-0126 EM='The "rxnComps" field must be of type "double"';
-0127 dispEM(EM,throwErrors);
-0128 end
-0129 end
-0130 if isfield(model,'inchis')
-0131 if ~iscellstr(model.inchis)
-0132 EM='The "inchis" field must be a cell array of strings';
-0133 dispEM(EM,throwErrors);
-0134 end
-0135 end
-0136 if isfield(model,'metSmiles')
-0137 if ~iscellstr(model.metSmiles)
-0138 EM='The "metSmiles" field must be a cell array of strings';
-0139 dispEM(EM,throwErrors);
-0140 end
-0141 end
-0142 if isfield(model,'metFormulas')
-0143 if ~iscellstr(model.metFormulas)
-0144 EM='The "metFormulas" field must be a cell array of strings';
-0145 dispEM(EM,throwErrors);
-0146 end
-0147 end
-0148 if isfield(model,'metCharges')
-0149 if ~isnumeric(model.metCharges)
-0150 EM='The "metCharges" field must be a double';
-0151 dispEM(EM,throwErrors);
-0152 end
-0153 end
-0154 if isfield(model,'metDeltaG')
-0155 if ~isnumeric(model.metDeltaG)
-0156 EM='The "metDeltaG" field must be a double';
-0157 dispEM(EM,throwErrors);
-0158 end
-0159 end
-0160 if isfield(model,'subSystems')
-0161 for i=1:numel(model.subSystems)
-0162 if ~iscell(model.subSystems{i,1})
-0163 EM='The "subSystems" field must be a cell array';
-0164 dispEM(EM,throwErrors);
-0165 end
-0166 end
-0167 end
-0168 if isfield(model,'eccodes')
-0169 if ~iscellstr(model.eccodes)
-0170 EM='The "eccodes" field must be a cell array of strings';
-0171 dispEM(EM,throwErrors);
-0172 end
-0173 end
-0174 if isfield(model,'unconstrained')
-0175 if ~isnumeric(model.unconstrained)
-0176 EM='The "unconstrained" field must be of type "double"';
-0177 dispEM(EM,throwErrors);
-0178 end
-0179 end
-0180 if isfield(model,'rxnNotes')
-0181 if ~iscellstr(model.rxnNotes)
-0182 EM='The "rxnNotes" field must be a cell array of strings';
-0183 dispEM(EM,throwErrors);
-0184 end
-0185 end
-0186 if isfield(model,'rxnReferences')
-0187 if ~iscellstr(model.rxnReferences)
-0188 EM='The "rxnReferences" field must be a cell array of strings';
-0189 dispEM(EM,throwErrors);
-0190 end
-0191 end
-0192 if isfield(model,'rxnConfidenceScores')
-0193 if ~isnumeric(model.rxnConfidenceScores)
-0194 EM='The "rxnConfidenceScores" field must be a double';
-0195 dispEM(EM,throwErrors);
-0196 end
-0197 end
-0198 if isfield(model,'rxnDeltaG')
-0199 if ~isnumeric(model.rxnDeltaG)
-0200 EM='The "rxnDeltaG" field must be a double';
-0201 dispEM(EM,throwErrors);
-0202 end
-0203 end
-0204
-0205
-0206 if isempty(model.id)
-0207 EM='The "id" field cannot be empty';
-0208 dispEM(EM,throwErrors);
-0209 end
-0210 if any(cellfun(@isempty,model.rxns))
-0211 EM='The model contains empty reaction IDs';
-0212 dispEM(EM,throwErrors);
-0213 end
-0214 if any(cellfun(@isempty,model.mets))
-0215 EM='The model contains empty metabolite IDs';
-0216 dispEM(EM,throwErrors);
-0217 end
-0218 if any(cellfun(@isempty,model.comps))
-0219 EM='The model contains empty compartment IDs';
-0220 dispEM(EM,throwErrors);
-0221 end
-0222 EM='The following metabolites have empty names:';
-0223 dispEM(EM,throwErrors,model.mets(cellfun(@isempty,model.metNames)),trimWarnings);
-0224
-0225 if isfield(model,'genes')
-0226 if any(cellfun(@isempty,model.genes))
-0227 EM='The model contains empty gene IDs';
-0228 dispEM(EM,throwErrors);
-0229 end
-0230 end
-0231
-0232
-0233 EM='The following reaction IDs are duplicates:';
-0234 dispEM(EM,throwErrors,model.rxns(duplicates(model.rxns)),trimWarnings);
-0235 EM='The following metabolite IDs are duplicates:';
-0236 dispEM(EM,throwErrors,model.mets(duplicates(model.mets)),trimWarnings);
-0237 EM='The following compartment IDs are duplicates:';
-0238 dispEM(EM,throwErrors,model.comps(duplicates(model.comps)),trimWarnings);
-0239 if isfield(model,'genes')
-0240 EM='The following genes are duplicates:';
-0241 dispEM(EM,throwErrors,model.genes(duplicates(model.genes)),trimWarnings);
-0242 end
-0243 metInComp=strcat(model.metNames,'[',model.comps(model.metComps),']');
-0244 EM='The following metabolites already exist in the same compartment:';
-0245 dispEM(EM,throwErrors,metInComp(duplicates(metInComp)),trimWarnings);
+0123 if ~isfield(model,'genes')
+0124 EM='If "grRules" field exists, the model should also contain a "genes" field';
+0125 dispEM(EM,throwErrors);
+0126 else
+0127 geneList = strjoin(model.grRules);
+0128 geneList = regexp(geneList,' |)|(|and|or','split');
+0129 geneList = geneList(~cellfun(@isempty,geneList));
+0130 geneList = setdiff(unique(geneList),model.genes);
+0131 if ~isempty(geneList)
+0132 problemGrRules = model.rxns(contains(model.grRules,geneList));
+0133 problemGrRules = strjoin(problemGrRules(:),'; ');
+0134 EM=['The reaction(s) "' problemGrRules '" contain the following genes in its "grRules" field, but these are not in the "genes" field:'];
+0135 dispEM(EM,throwErrors,geneList);
+0136 end
+0137 end
+0138 end
+0139 if isfield(model,'rxnComps')
+0140 if ~isnumeric(model.rxnComps)
+0141 EM='The "rxnComps" field must be of type "double"';
+0142 dispEM(EM,throwErrors);
+0143 end
+0144 end
+0145 if isfield(model,'inchis')
+0146 if ~iscellstr(model.inchis)
+0147 EM='The "inchis" field must be a cell array of strings';
+0148 dispEM(EM,throwErrors);
+0149 end
+0150 end
+0151 if isfield(model,'metSmiles')
+0152 if ~iscellstr(model.metSmiles)
+0153 EM='The "metSmiles" field must be a cell array of strings';
+0154 dispEM(EM,throwErrors);
+0155 end
+0156 end
+0157 if isfield(model,'metFormulas')
+0158 if ~iscellstr(model.metFormulas)
+0159 EM='The "metFormulas" field must be a cell array of strings';
+0160 dispEM(EM,throwErrors);
+0161 end
+0162 end
+0163 if isfield(model,'metCharges')
+0164 if ~isnumeric(model.metCharges)
+0165 EM='The "metCharges" field must be a double';
+0166 dispEM(EM,throwErrors);
+0167 end
+0168 end
+0169 if isfield(model,'metDeltaG')
+0170 if ~isnumeric(model.metDeltaG)
+0171 EM='The "metDeltaG" field must be a double';
+0172 dispEM(EM,throwErrors);
+0173 end
+0174 end
+0175 if isfield(model,'subSystems')
+0176 for i=1:numel(model.subSystems)
+0177 if ~iscell(model.subSystems{i,1})
+0178 EM='The "subSystems" field must be a cell array';
+0179 dispEM(EM,throwErrors);
+0180 end
+0181 end
+0182 end
+0183 if isfield(model,'eccodes')
+0184 if ~iscellstr(model.eccodes)
+0185 EM='The "eccodes" field must be a cell array of strings';
+0186 dispEM(EM,throwErrors);
+0187 end
+0188 end
+0189 if isfield(model,'unconstrained')
+0190 if ~isnumeric(model.unconstrained)
+0191 EM='The "unconstrained" field must be of type "double"';
+0192 dispEM(EM,throwErrors);
+0193 end
+0194 end
+0195 if isfield(model,'rxnNotes')
+0196 if ~iscellstr(model.rxnNotes)
+0197 EM='The "rxnNotes" field must be a cell array of strings';
+0198 dispEM(EM,throwErrors);
+0199 end
+0200 end
+0201 if isfield(model,'rxnReferences')
+0202 if ~iscellstr(model.rxnReferences)
+0203 EM='The "rxnReferences" field must be a cell array of strings';
+0204 dispEM(EM,throwErrors);
+0205 end
+0206 end
+0207 if isfield(model,'rxnConfidenceScores')
+0208 if ~isnumeric(model.rxnConfidenceScores)
+0209 EM='The "rxnConfidenceScores" field must be a double';
+0210 dispEM(EM,throwErrors);
+0211 end
+0212 end
+0213 if isfield(model,'rxnDeltaG')
+0214 if ~isnumeric(model.rxnDeltaG)
+0215 EM='The "rxnDeltaG" field must be a double';
+0216 dispEM(EM,throwErrors);
+0217 end
+0218 end
+0219
+0220
+0221 if isempty(model.id)
+0222 EM='The "id" field cannot be empty';
+0223 dispEM(EM,throwErrors);
+0224 end
+0225 if any(cellfun(@isempty,model.rxns))
+0226 EM='The model contains empty reaction IDs';
+0227 dispEM(EM,throwErrors);
+0228 end
+0229 if any(cellfun(@isempty,model.mets))
+0230 EM='The model contains empty metabolite IDs';
+0231 dispEM(EM,throwErrors);
+0232 end
+0233 if any(cellfun(@isempty,model.comps))
+0234 EM='The model contains empty compartment IDs';
+0235 dispEM(EM,throwErrors);
+0236 end
+0237 EM='The following metabolites have empty names:';
+0238 dispEM(EM,throwErrors,model.mets(cellfun(@isempty,model.metNames)),trimWarnings);
+0239
+0240 if isfield(model,'genes')
+0241 if any(cellfun(@isempty,model.genes))
+0242 EM='The model contains empty gene IDs';
+0243 dispEM(EM,throwErrors);
+0244 end
+0245 end
0246
-0247
-0248 EM='The following reactions are empty (no involved metabolites):';
-0249 dispEM(EM,false,model.rxns(~any(model.S,1)),trimWarnings);
-0250 EM='The following metabolites are never used in a reaction:';
-0251 dispEM(EM,false,model.mets(~any(model.S,2)),trimWarnings);
-0252 if isfield(model,'genes')
-0253 EM='The following genes are not associated to a reaction:';
-0254 dispEM(EM,false,model.genes(~any(model.rxnGeneMat,1)),trimWarnings);
-0255 end
-0256 I=true(numel(model.comps),1);
-0257 I(model.metComps)=false;
-0258 EM='The following compartments contain no metabolites:';
-0259 dispEM(EM,false,model.comps(I),trimWarnings);
-0260
-0261
-0262 EM='The following reactions have contradicting bounds:';
-0263 dispEM(EM,throwErrors,model.rxns(model.lb>model.ub),trimWarnings);
-0264 EM='The following reactions have bounds contradicting their reversibility:';
-0265 dispEM(EM,throwErrors,model.rxns(model.lb<0 & model.rev==0),trimWarnings);
-0266
-0267
-0268 if numel(find(model.c))>1
-0269 EM='Multiple objective functions found. This might be intended, but results in FBCv2 non-compliant SBML file when exported';
-0270 dispEM(EM,false,model.rxns(find(model.c)),trimWarnings);
-0271 elseif ~any(model.c)
-0272 EM='No objective function found. This might be intended, but results in FBCv2 non-compliant SBML file when exported';
-0273 dispEM(EM,false);
-0274 end
-0275
-0276 EM='The following reactions have contradicting bounds:';
-0277 dispEM(EM,throwErrors,model.rxns(model.lb>model.ub),trimWarnings);
-0278
-0279
-0280 if isfield(model,'compOutside')
-0281 EM='The following compartments are in "compOutside" but not in "comps":';
-0282 dispEM(EM,throwErrors,setdiff(model.compOutside,[{''};model.comps]),trimWarnings);
-0283 end
+0247
+0248 EM='The following reaction IDs are duplicates:';
+0249 dispEM(EM,throwErrors,model.rxns(duplicates(model.rxns)),trimWarnings);
+0250 EM='The following metabolite IDs are duplicates:';
+0251 dispEM(EM,throwErrors,model.mets(duplicates(model.mets)),trimWarnings);
+0252 EM='The following compartment IDs are duplicates:';
+0253 dispEM(EM,throwErrors,model.comps(duplicates(model.comps)),trimWarnings);
+0254 if isfield(model,'genes')
+0255 EM='The following genes are duplicates:';
+0256 dispEM(EM,throwErrors,model.genes(duplicates(model.genes)),trimWarnings);
+0257 end
+0258 metInComp=strcat(model.metNames,'[',model.comps(model.metComps),']');
+0259 EM='The following metabolites already exist in the same compartment:';
+0260 dispEM(EM,throwErrors,metInComp(duplicates(metInComp)),trimWarnings);
+0261
+0262
+0263 EM='The following reactions are empty (no involved metabolites):';
+0264 dispEM(EM,false,model.rxns(~any(model.S,1)),trimWarnings);
+0265 EM='The following metabolites are never used in a reaction:';
+0266 dispEM(EM,false,model.mets(~any(model.S,2)),trimWarnings);
+0267 if isfield(model,'genes')
+0268 EM='The following genes are not associated to a reaction:';
+0269 dispEM(EM,false,model.genes(~any(model.rxnGeneMat,1)),trimWarnings);
+0270 end
+0271 I=true(numel(model.comps),1);
+0272 I(model.metComps)=false;
+0273 EM='The following compartments contain no metabolites:';
+0274 dispEM(EM,false,model.comps(I),trimWarnings);
+0275
+0276
+0277 EM='The following reactions have contradicting bounds:';
+0278 dispEM(EM,throwErrors,model.rxns(model.lb>model.ub),trimWarnings);
+0279 EM='The following reactions have bounds contradicting their reversibility:';
+0280 contradictBound = (model.lb < 0 & model.ub > 0 & model.rev==0) | ...
+0281 (model.lb < 0 & model.ub <= 0 & model.rev==1) | ...
+0282 (model.lb >= 0 & model.ub > 0 & model.rev==1);
+0283 dispEM(EM,throwErrors,model.rxns(contradictBound),trimWarnings);
0284
-0285
-0286 I=false(numel(model.metNames),1);
-0287 for i=1:numel(model.metNames)
-0288 index=strfind(model.metNames{i},' ');
-0289 if any(index)
-0290 if any(str2double(model.metNames{i}(1:index(1)-1)))
-0291 I(i)=true;
-0292 end
-0293 end
-0294 end
-0295 EM='The following metabolite IDs begin with a number directly followed by space:';
-0296 dispEM(EM,throwErrors,model.mets(I),trimWarnings);
-0297
-0298
-0299 if isfield(model,'metFormulas')
-0300 [~, ~, exitFlag]=parseFormulas(model.metFormulas,true,false);
-0301 EM='The composition for the following metabolites could not be parsed:';
-0302 dispEM(EM,false,model.mets(exitFlag==-1),trimWarnings);
-0303 end
-0304
-0305
-0306
-0307 if isfield(model,'metMiriams')
-0308 miriams=containers.Map();
-0309 for i=1:numel(model.mets)
-0310 if ~isempty(model.metMiriams{i})
-0311
-0312 for j=1:numel(model.metMiriams{i}.name)
-0313
-0314 current=strcat(model.metMiriams{i}.name{j},'/',model.metMiriams{i}.value{j});
-0315 if isKey(miriams,current)
-0316 existing=miriams(current);
-0317 else
-0318 existing=[];
-0319 end
-0320 miriams(current)=[existing;i];
-0321 end
-0322 end
-0323 end
-0324
-0325
-0326 allMiriams=keys(miriams);
-0327
-0328 hasMultiple=false(numel(allMiriams),1);
-0329 for i=1:numel(allMiriams)
-0330 if numel(miriams(allMiriams{i}))>1
-0331
-0332 if numel(unique(model.metNames(miriams(allMiriams{i}))))>1
-0333 if ~regexp(allMiriams{i},'^sbo\/SBO:')
-0334 hasMultiple(i)=true;
-0335 end
-0336 end
-0337 end
-0338 end
-0339
-0340
-0341 EM='The following MIRIAM strings are associated to more than one unique metabolite name:';
-0342 dispEM(EM,false,allMiriams(hasMultiple),trimWarnings);
-0343 end
-0344
-0345
-0346
-0347 if isfield(model,'inchis')
-0348 inchis=containers.Map();
-0349 for i=1:numel(model.mets)
-0350 if ~isempty(model.inchis{i})
-0351
-0352 if isKey(inchis,model.inchis{i})
-0353 existing=inchis(model.inchis{i});
-0354 else
-0355 existing=[];
-0356 end
-0357 inchis(model.inchis{i})=[existing;i];
-0358 end
-0359 end
-0360
-0361
-0362 allInchis=keys(inchis);
-0363
-0364 hasMultiple=false(numel(allInchis),1);
-0365 for i=1:numel(allInchis)
-0366 if numel(inchis(allInchis{i}))>1
-0367
-0368 if numel(unique(model.metNames(inchis(allInchis{i}))))>1
-0369 hasMultiple(i)=true;
-0370 end
-0371 end
-0372 end
-0373
-0374
-0375 EM='The following InChI strings are associated to more than one unique metabolite name:';
-0376 dispEM(EM,false,allInchis(hasMultiple),trimWarnings);
-0377 end
-0378
-0379
-0380
-0381
-0382
-0383
-0384
-0385
-0386
-0387
-0388
-0389
-0390
-0391
-0392
-0393
-0394
-0395
-0396
-0397
-0398
-0399
-0400
-0401
-0402
-0403
-0404
-0405
-0406
-0407
-0408
-0409
-0410
-0411 end
-0412
-0413 function I=duplicates(strings)
-0414 I=false(numel(strings),1);
-0415 [J, K]=unique(strings);
-0416 if numel(J)~=numel(strings)
-0417 L=1:numel(strings);
-0418 L(K)=[];
-0419 I(L)=true;
-0420 end
-0421 end
+0285
+0286 if numel(find(model.c))>1
+0287 EM='Multiple objective functions found. This might be intended, but results in FBCv2 non-compliant SBML file when exported';
+0288 dispEM(EM,false,model.rxns(find(model.c)),trimWarnings);
+0289 elseif ~any(model.c)
+0290 EM='No objective function found. This might be intended, but results in FBCv2 non-compliant SBML file when exported';
+0291 dispEM(EM,false);
+0292 end
+0293
+0294 EM='The following reactions have contradicting bounds:';
+0295 dispEM(EM,throwErrors,model.rxns(model.lb>model.ub),trimWarnings);
+0296
+0297
+0298 if isfield(model,'compOutside')
+0299 EM='The following compartments are in "compOutside" but not in "comps":';
+0300 dispEM(EM,throwErrors,setdiff(model.compOutside,[{''};model.comps]),trimWarnings);
+0301 end
+0302
+0303
+0304 I=false(numel(model.metNames),1);
+0305 for i=1:numel(model.metNames)
+0306 index=strfind(model.metNames{i},' ');
+0307 if any(index)
+0308 if any(str2double(model.metNames{i}(1:index(1)-1)))
+0309 I(i)=true;
+0310 end
+0311 end
+0312 end
+0313 EM='The following metabolite IDs begin with a number directly followed by space:';
+0314 dispEM(EM,throwErrors,model.mets(I),trimWarnings);
+0315
+0316
+0317 if isfield(model,'metFormulas')
+0318 [~, ~, exitFlag]=parseFormulas(model.metFormulas,true,false);
+0319 EM='The composition for the following metabolites could not be parsed:';
+0320 dispEM(EM,false,model.mets(exitFlag==-1),trimWarnings);
+0321 end
+0322
+0323
+0324
+0325 if isfield(model,'metMiriams')
+0326 miriams=containers.Map();
+0327 for i=1:numel(model.mets)
+0328 if ~isempty(model.metMiriams{i})
+0329
+0330 for j=1:numel(model.metMiriams{i}.name)
+0331
+0332 current=strcat(model.metMiriams{i}.name{j},'/',model.metMiriams{i}.value{j});
+0333 if isKey(miriams,current)
+0334 existing=miriams(current);
+0335 else
+0336 existing=[];
+0337 end
+0338 miriams(current)=[existing;i];
+0339 end
+0340 end
+0341 end
+0342
+0343
+0344 allMiriams=keys(miriams);
+0345
+0346 hasMultiple=false(numel(allMiriams),1);
+0347 for i=1:numel(allMiriams)
+0348 if numel(miriams(allMiriams{i}))>1
+0349
+0350 if numel(unique(model.metNames(miriams(allMiriams{i}))))>1
+0351 if ~regexp(allMiriams{i},'^sbo\/SBO:')
+0352 hasMultiple(i)=true;
+0353 end
+0354 end
+0355 end
+0356 end
+0357
+0358
+0359 EM='The following MIRIAM strings are associated to more than one unique metabolite name:';
+0360 dispEM(EM,false,allMiriams(hasMultiple),trimWarnings);
+0361 end
+0362
+0363
+0364
+0365 if isfield(model,'inchis')
+0366 inchis=containers.Map();
+0367 for i=1:numel(model.mets)
+0368 if ~isempty(model.inchis{i})
+0369
+0370 if isKey(inchis,model.inchis{i})
+0371 existing=inchis(model.inchis{i});
+0372 else
+0373 existing=[];
+0374 end
+0375 inchis(model.inchis{i})=[existing;i];
+0376 end
+0377 end
+0378
+0379
+0380 allInchis=keys(inchis);
+0381
+0382 hasMultiple=false(numel(allInchis),1);
+0383 for i=1:numel(allInchis)
+0384 if numel(inchis(allInchis{i}))>1
+0385
+0386 if numel(unique(model.metNames(inchis(allInchis{i}))))>1
+0387 hasMultiple(i)=true;
+0388 end
+0389 end
+0390 end
+0391
+0392
+0393 EM='The following InChI strings are associated to more than one unique metabolite name:';
+0394 dispEM(EM,false,allInchis(hasMultiple),trimWarnings);
+0395 end
+0396
+0397
+0398
+0399
+0400
+0401
+0402
+0403
+0404
+0405
+0406
+0407
+0408
+0409
+0410
+0411
+0412
+0413
+0414
+0415
+0416
+0417
+0418
+0419
+0420
+0421
+0422
+0423
+0424
+0425
+0426
+0427
+0428
+0429 end
+0430
+0431 function I=duplicates(strings)
+0432 I=false(numel(strings),1);
+0433 [J, K]=unique(strings);
+0434 if numel(J)~=numel(strings)
+0435 L=1:numel(strings);
+0436 L(K)=[];
+0437 I(L)=true;
+0438 end
+0439 end
Generated by m2html © 2005