0001 function checkModelStruct(model,throwErrors,trimWarnings)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 if nargin<2
0021 throwErrors=true;
0022 end
0023 if nargin<3
0024 trimWarnings=true;
0025 end
0026
0027
0028 if ~isfield(model,'id')
0029 dispEM('The model is missing the "id" field',throwErrors);
0030 end
0031 if ~isfield(model,'description')
0032 dispEM('The model is missing the "description" field',throwErrors);
0033 end
0034 if ~isfield(model,'rxns')
0035 dispEM('The model is missing the "rxns" field',throwErrors);
0036 end
0037 if ~isfield(model,'mets')
0038 dispEM('The model is missing the "mets" field',throwErrors);
0039 end
0040 if ~isfield(model,'S')
0041 dispEM('The model is missing the "S" field',throwErrors);
0042 end
0043 if ~isfield(model,'lb')
0044 dispEM('The model is missing the "lb" field',throwErrors);
0045 end
0046 if ~isfield(model,'ub')
0047 dispEM('The model is missing the "ub" field',throwErrors);
0048 end
0049 if ~isfield(model,'rev')
0050 dispEM('The model is missing the "rev" field',throwErrors);
0051 end
0052 if ~isfield(model,'c')
0053 dispEM('The model is missing the "c" field',throwErrors);
0054 end
0055 if ~isfield(model,'b')
0056 dispEM('The model is missing the "b" field',throwErrors);
0057 end
0058 if ~isfield(model,'comps')
0059 dispEM('The model is missing the "comps" field',throwErrors);
0060 end
0061 if ~isfield(model,'metComps')
0062 dispEM('The model is missing the "metComps" field',throwErrors);
0063 end
0064
0065
0066 if ~ischar(model.id)
0067 dispEM('The "id" field must be a string',throwErrors);
0068 end
0069 if ~ischar(model.description)
0070 dispEM('The "description" field must be a string',throwErrors);
0071 end
0072 if ~iscellstr(model.rxns)
0073 dispEM('The "rxns" field must be a cell array of strings',throwErrors);
0074 end
0075 if ~iscellstr(model.mets)
0076 dispEM('The "mets" field must be a cell array of strings',throwErrors);
0077 end
0078 if ~isnumeric(model.S)
0079 dispEM('The "S" field must be of type "double"',throwErrors);
0080 end
0081 if ~isnumeric(model.lb)
0082 dispEM('The "lb" field must be of type "double"',throwErrors);
0083 end
0084 if ~isnumeric(model.ub)
0085 dispEM('The "ub" field must be of type "double"',throwErrors);
0086 end
0087 if ~isnumeric(model.rev)
0088 dispEM('The "rev" field must be of type "double"',throwErrors);
0089 end
0090 if ~isnumeric(model.c)
0091 dispEM('The "c" field must be of type "double"',throwErrors);
0092 end
0093 if ~isnumeric(model.b)
0094 dispEM('The "b" field must be of type "double"',throwErrors);
0095 end
0096 if ~iscellstr(model.comps)
0097 dispEM('The "comps" field must be a cell array of strings',throwErrors);
0098 end
0099 if ~isnumeric(model.metComps)
0100 dispEM('The "metComps" field must be of type "double"',throwErrors);
0101 end
0102 if isfield(model,'compNames')
0103 if ~iscellstr(model.compNames)
0104 dispEM('The "compNames" field must be a cell array of strings',throwErrors);
0105 end
0106 end
0107 if isfield(model,'compOutside')
0108 if ~iscellstr(model.compOutside)
0109 dispEM('The "compOutside" field must be a cell array of strings',throwErrors);
0110 end
0111 end
0112 if isfield(model,'rxnNames')
0113 if ~iscellstr(model.rxnNames)
0114 dispEM('The "rxnNames" field must be a cell array of strings',throwErrors);
0115 end
0116 end
0117 if isfield(model,'metNames')
0118 if ~iscellstr(model.metNames)
0119 dispEM('The "metNames" field must be a cell array of strings',throwErrors);
0120 end
0121 end
0122 if isfield(model,'genes')
0123 if ~iscellstr(model.genes)
0124 dispEM('The "genes" field must be a cell array of strings',throwErrors);
0125 end
0126 end
0127 if isfield(model,'rxnGeneMat')
0128 if ~isnumeric(model.rxnGeneMat)
0129 dispEM('The "rxnGeneMat" field must be of type "double"',throwErrors);
0130 end
0131 end
0132 if isfield(model,'grRules')
0133 if ~iscellstr(model.grRules)
0134 dispEM('The "grRules" field must be a cell array of strings',throwErrors);
0135 end
0136 end
0137 if isfield(model,'rxnComps')
0138 if ~isnumeric(model.rxnComps)
0139 dispEM('The "rxnComps" field must be of type "double"',throwErrors);
0140 end
0141 end
0142 if isfield(model,'inchis')
0143 if ~iscellstr(model.inchis)
0144 dispEM('The "inchis" field must be a cell array of strings',throwErrors);
0145 end
0146 end
0147 if isfield(model,'metFormulas')
0148 if ~iscellstr(model.metFormulas)
0149 dispEM('The "metFormulas" field must be a cell array of strings',throwErrors);
0150 end
0151 end
0152 if isfield(model,'subSystems')
0153 if ~iscellstr(model.subSystems)
0154 dispEM('The "subSystems" field must be a cell array of strings',throwErrors);
0155 end
0156 end
0157 if isfield(model,'eccodes')
0158 if ~iscellstr(model.eccodes)
0159 dispEM('The "eccodes" field must be a cell array of strings',throwErrors);
0160 end
0161 end
0162 if isfield(model,'unconstrained')
0163 if ~isnumeric(model.unconstrained)
0164 dispEM('The "unconstrained" field must be of type "double"',throwErrors);
0165 end
0166 end
0167
0168
0169 if isempty(model.id)
0170 dispEM('The "id" field cannot be empty',throwErrors);
0171 end
0172 if any(cellfun(@isempty,model.rxns))
0173 dispEM('The model contains empty reaction IDs',throwErrors);
0174 end
0175 if any(cellfun(@isempty,model.mets))
0176 dispEM('The model contains empty metabolite IDs',throwErrors);
0177 end
0178 if any(cellfun(@isempty,model.comps))
0179 dispEM('The model contains empty compartment IDs',throwErrors);
0180 end
0181 dispEM('The following metabolites have empty names:',throwErrors,model.mets(cellfun(@isempty,model.metNames)),trimWarnings);
0182
0183 if isfield(model,'genes')
0184 if any(cellfun(@isempty,model.genes))
0185 dispEM('The model contains empty gene IDs',throwErrors);
0186 end
0187 end
0188
0189
0190 dispEM('Illegal characters in reaction IDs:',throwErrors,model.rxns(illegal(model.rxns,'id')),trimWarnings);
0191 dispEM('Illegal characters in metabolite IDs:',throwErrors,model.mets(illegal(model.mets,'id')),trimWarnings);
0192 dispEM('Illegal characters in compartment IDs:',throwErrors,model.comps(illegal(model.comps,'id')),trimWarnings);
0193
0194
0195 dispEM('The following reaction IDs are duplicates:',throwErrors,model.rxns(duplicates(model.rxns)),trimWarnings);
0196 dispEM('The following metabolite IDs are duplicates:',throwErrors,model.mets(duplicates(model.mets)),trimWarnings);
0197 dispEM('The following compartment IDs are duplicates:',throwErrors,model.comps(duplicates(model.comps)),trimWarnings);
0198 if isfield(model,'genes')
0199 dispEM('The following genes are duplicates:',throwErrors,model.genes(duplicates(model.genes)),trimWarnings);
0200 end
0201 metInComp=strcat(model.metNames,'[',model.comps(model.metComps),']');
0202 dispEM('The following metabolites already exist in the same compartment:',throwErrors,metInComp(duplicates(metInComp)),trimWarnings);
0203
0204
0205 dispEM('The following reactions are empty (no involved metabolites):',false,model.rxns(~any(model.S,1)),trimWarnings);
0206 dispEM('The following metabolites are never used in a reaction:',false,model.mets(~any(model.S,2)),trimWarnings);
0207 if isfield(model,'genes')
0208 dispEM('The following genes are not associated to a reaction:',false,model.genes(~any(model.rxnGeneMat,1)),trimWarnings);
0209 end
0210 I=true(numel(model.comps),1);
0211 I(model.metComps)=false;
0212 dispEM('The following compartments contain no metabolites:',false,model.comps(I),trimWarnings);
0213
0214
0215 dispEM('The following reactions have contradicting bounds:',throwErrors,model.rxns(model.lb>model.ub),trimWarnings);
0216 dispEM('The following reactions have bounds contradicting their reversibility:',throwErrors,model.rxns(model.lb<0 & model.rev==0),trimWarnings);
0217
0218
0219 if isfield(model,'compOutside')
0220 dispEM('The following compartments are in "compOutside" but not in "comps":',throwErrors,setdiff(model.compOutside,[{''};model.comps]),trimWarnings);
0221 end
0222
0223
0224 I=false(numel(model.metNames),1);
0225 for i=1:numel(model.metNames)
0226 index=strfind(model.metNames{i},' ');
0227 if any(index)
0228 if any(str2double(model.metNames{i}(1:index(1)-1)))
0229 I(i)=true;
0230 end
0231 end
0232 end
0233 dispEM('The following metabolite names begin with a number directly followed by space:',throwErrors,model.mets(I),trimWarnings);
0234
0235
0236 if isfield(model,'metFormulas')
0237 [crap, crap, exitFlag]=parseFormulas(model.metFormulas,true,false);
0238 dispEM('The composition for the following metabolites could not be parsed:',false,model.mets(exitFlag==-1),trimWarnings);
0239 end
0240
0241
0242
0243 if isfield(model,'metMiriams')
0244 miriams=containers.Map();
0245 for i=1:numel(model.mets)
0246 if ~isempty(model.metMiriams{i})
0247
0248 for j=1:numel(model.metMiriams{i}.name)
0249
0250 current=strcat(model.metMiriams{i}.name{j},':',model.metMiriams{i}.value{j});
0251 if isKey(miriams,current)
0252 existing=miriams(current);
0253 else
0254 existing=[];
0255 end
0256 miriams(current)=[existing;i];
0257 end
0258 end
0259 end
0260
0261
0262 allMiriams=keys(miriams);
0263
0264 hasMultiple=false(numel(allMiriams),1);
0265 for i=1:numel(allMiriams)
0266 if numel(miriams(allMiriams{i}))>1
0267
0268 if numel(unique(model.metNames(miriams(allMiriams{i}))))>1
0269 hasMultiple(i)=true;
0270 end
0271 end
0272 end
0273
0274
0275 dispEM('The following MIRIAM strings are associated to more than one unique metabolite name:',false,allMiriams(hasMultiple));
0276 end
0277
0278
0279
0280 if isfield(model,'inchis')
0281 inchis=containers.Map();
0282 for i=1:numel(model.mets)
0283 if ~isempty(model.inchis{i})
0284
0285 if isKey(inchis,model.inchis{i})
0286 existing=inchis(model.inchis{i});
0287 else
0288 existing=[];
0289 end
0290 inchis(model.inchis{i})=[existing;i];
0291 end
0292 end
0293
0294
0295 allInchis=keys(inchis);
0296
0297 hasMultiple=false(numel(allInchis),1);
0298 for i=1:numel(allInchis)
0299 if numel(inchis(allInchis{i}))>1
0300
0301 if numel(unique(model.metNames(inchis(allInchis{i}))))>1
0302 hasMultiple(i)=true;
0303 end
0304 end
0305 end
0306
0307
0308 dispEM('The following InChI strings are associated to more than one unique metabolite name:',false,allInchis(hasMultiple));
0309 end
0310 end
0311
0312 function I=duplicates(strings)
0313 I=false(numel(strings),1);
0314 [J K]=unique(strings);
0315 if numel(J)~=numel(strings)
0316 L=1:numel(strings);
0317 L(K)=[];
0318 I(L)=true;
0319 end
0320 end
0321 function I=illegal(strings,type)
0322
0323 if strcmpi(type,'id')
0324
0325 I=cellfun(@any,regexp(strings,'[^a-z_A-Z0-9-]', 'once'));
0326 else
0327
0328 end
0329 end