0001 function exportModel(model,fileName,toCOBRA,supressWarnings)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 if nargin<3
0019 toCOBRA=false;
0020 end
0021 if nargin<4
0022 supressWarnings=false;
0023 end
0024
0025
0026
0027 if ~isfield(model,'unconstrained')
0028 if supressWarnings==false
0029 dispEM('There is no unconstrained field in the model structure. This means that no metabolites are considered exchange metabolites',false);
0030 end
0031 model.unconstrained=zeros(numel(model.mets),1);
0032 end
0033
0034
0035 if supressWarnings==false
0036 checkModelStruct(model,false);
0037 end
0038
0039
0040 model=cleanBadCharsInModel(model);
0041
0042
0043 if ~isfield(model,'geneComps') && isfield(model,'genes')
0044 if supressWarnings==false
0045 dispEM('There are no compartments specified for genes. All genes will be assigned to the first compartment. This is because the SBML structure requires all elements to be assigned to a compartment',false);
0046 end
0047 model.geneComps=ones(numel(model.genes),1);
0048 end
0049
0050
0051 tempF=tempname();
0052
0053
0054 fid = fopen(tempF,'w');
0055
0056
0057 if toCOBRA==false
0058 intro=['<?xml version="1.0" encoding="UTF-8" ?>'...
0059 '<sbml xmlns="http://www.sbml.org/sbml/level2/version3" level="2" version="3">'...
0060 '<model metaid="metaid_' model.id '" id="' model.id '" name="' model.description '">'];
0061 if isfield(model,'annotation')
0062 if isfield(model.annotation,'note')
0063 intro=[intro '<notes><body xmlns="http://www.w3.org/1999/xhtml">' model.annotation.note '</body></notes>\n'];
0064 end
0065 else
0066 intro=[intro '<notes><body xmlns="http://www.w3.org/1999/xhtml">This file was generated using the exportModel function in RAVEN Toolbox</body></notes>\n'];
0067 end
0068 intro=[intro '<annotation>'...
0069 '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:vCard="http://www.w3.org/2001/vcard-rdf/3.0#" xmlns:bqbiol="http://biomodels.net/biology-qualifiers/" xmlns:bqmodel="http://biomodels.net/model-qualifiers/">'...
0070 '<rdf:Description rdf:about="#metaid_' model.id '">'];
0071 if isfield(model,'annotation')
0072 nameString='';
0073 if isfield(model.annotation,'givenName')
0074 if ~isempty(model.annotation.givenName)
0075 nameString=['<vCard:Given>' model.annotation.givenName '</vCard:Given>'];
0076 end
0077 end
0078 if isfield(model.annotation,'familyName')
0079 if ~isempty(model.annotation.familyName)
0080 nameString=[nameString '<vCard:Family>' model.annotation.familyName '</vCard:Family>'];
0081 end
0082 end
0083 email='';
0084 if isfield(model.annotation,'email')
0085 if ~isempty(model.annotation.email)
0086 email=['<vCard:EMAIL>' model.annotation.email '</vCard:EMAIL>'];
0087 end
0088 end
0089 org='';
0090 if isfield(model.annotation,'organization')
0091 if ~isempty(model.annotation.organization)
0092 org=['<vCard:ORG><vCard:Orgname>' model.annotation.organization '</vCard:Orgname></vCard:ORG>'];
0093 end
0094 end
0095 if ~isempty(nameString) || ~isempty(email) || ~isempty(org)
0096 intro=[intro '<dc:creator rdf:parseType="Resource"><rdf:Bag><rdf:li rdf:parseType="Resource">'];
0097 if ~isempty(nameString)
0098 intro=[intro '<vCard:N rdf:parseType="Resource">' nameString '</vCard:N>'];
0099 end
0100 intro=[intro email org '</rdf:li></rdf:Bag></dc:creator>'];
0101 end
0102 end
0103 intro=[intro '<dcterms:created rdf:parseType="Resource">'...
0104 '<dcterms:W3CDTF>' datestr(now,'yyyy-mm-ddTHH:MM:SSZ') '</dcterms:W3CDTF>'...
0105 '</dcterms:created>'...
0106 '<dcterms:modified rdf:parseType="Resource">'...
0107 '<dcterms:W3CDTF>' datestr(now,'yyyy-mm-ddTHH:MM:SSZ') '</dcterms:W3CDTF>'...
0108 '</dcterms:modified>'];
0109
0110 if isfield(model,'annotation')
0111 if isfield(model.annotation,'taxonomy')
0112 intro=[intro '<bqbiol:is><rdf:Bag><rdf:li rdf:resource="urn:miriam:' model.annotation.taxonomy '" /></rdf:Bag></bqbiol:is>'];
0113 end
0114 end
0115 intro=[intro '</rdf:Description>'...
0116 '</rdf:RDF>'...
0117 '</annotation>'];
0118 else
0119 intro=['<?xml version="1.0" encoding="UTF-8"?><sbml xmlns="http://www.sbml.org/sbml/level2" level="2" version="1" xmlns:html="http://www.w3.org/1999/xhtml"><model id="' model.id '" name="' model.description '">'];
0120 if isfield(model,'annotation')
0121 if isfield(model.annotation,'note')
0122 intro=[intro '<notes><body xmlns="http://www.w3.org/1999/xhtml">' model.annotation.note '</body></notes>\n'];
0123 end
0124 end
0125 end
0126
0127 intro=[intro '<listOfUnitDefinitions>'...
0128 '<unitDefinition id="mmol_per_gDW_per_hr">'...
0129 '<listOfUnits>'...
0130 '<unit kind="mole" scale="-3"/>'...
0131 '<unit kind="second" multiplier="0.00027778" exponent="-1"/>'...
0132 '</listOfUnits>'...
0133 '</unitDefinition>'...
0134 '</listOfUnitDefinitions>'...
0135 '<listOfCompartments>'];
0136
0137
0138 fprintf(fid,intro);
0139
0140
0141 for i=1:numel(model.comps)
0142
0143 if isfield(model, 'compOutside')
0144 if ~isempty(model.compOutside{i})
0145 append=[' outside="C_' model.compOutside{i} '" spatialDimensions="3"'];
0146 else
0147 append=' spatialDimensions="3"';
0148 end
0149 else
0150 append=' spatialDimensions="3"';
0151 end
0152
0153 if toCOBRA==false
0154 fprintf(fid,['<compartment metaid="metaid_C_' model.comps{i} '" id="C_' model.comps{i} '" name="' model.compNames{i} '"' append ' size="1" sboTerm="SBO:0000290">']);
0155
0156
0157 if isfield(model,'compMiriams')
0158 miriamString=getMiriam(model.compMiriams{i});
0159 else
0160 miriamString=[];
0161 end
0162
0163 if ~isempty(miriamString)
0164 compinfo=['<annotation><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms='...
0165 '"http://purl.org/dc/terms/" xmlns:vCard="http://www.w3.org/2001/vcard-rdf/3.0#" xmlns:bqbiol="http://biomodels.net/biology-qualifiers/" '...
0166 'xmlns:bqmodel="http://biomodels.net/model-qualifiers/"><rdf:Description rdf:about="#metaid_C_' model.comps{i} '">'...
0167 '<bqbiol:is><rdf:Bag>' miriamString '</rdf:Bag></bqbiol:is>'...
0168 '</rdf:Description></rdf:RDF></annotation></compartment>'];
0169 else
0170 compinfo='</compartment>\n';
0171 end
0172 fprintf(fid,compinfo);
0173 else
0174 fprintf(fid,['<compartment id="C_' model.comps{i} '" name="' model.compNames{i} '"' append '></compartment>']);
0175 end
0176 end
0177
0178 intro='</listOfCompartments><listOfSpecies>';
0179 fprintf(fid,intro);
0180
0181
0182 for i=1:numel(model.mets)
0183 if model.unconstrained(i)
0184 unbounded='true';
0185 else
0186 unbounded='false';
0187 end
0188
0189 if toCOBRA==false
0190 toprint=['<species metaid="metaid_M_' model.mets{i} '" id="M_' model.mets{i} '" name="' model.metNames{i} '" compartment="C_' model.comps{model.metComps(i)} '" initialAmount="0" boundaryCondition="' unbounded '" sboTerm="SBO:0000299">'];
0191 else
0192
0193 if isfield(model,'metFormulas')
0194 if ~isempty(model.metFormulas(i))
0195 append=['_' model.metFormulas{i}];
0196 else
0197 append='_';
0198 end
0199 else
0200 append='_';
0201 end
0202 toprint=['<species id="M_' model.mets{i} '" name="' model.metNames{i} append '" compartment="C_' model.comps{model.metComps(i)} '" initialAmount="0" boundaryCondition="' unbounded '">'];
0203 end
0204
0205
0206 if toCOBRA==false
0207 if isfield(model,'metFormulas')
0208
0209
0210 hasInchi=false;
0211 if isfield(model,'inchis')
0212 if ~isempty(model.inchis{i})
0213 hasInchi=true;
0214 end
0215 end
0216
0217 if ~isempty(model.metFormulas{i}) && hasInchi==false
0218 toprint=[toprint '<notes><body xmlns="http://www.w3.org/1999/xhtml"><p>FORMULA: ' model.metFormulas{i} '</p></body></notes>'];
0219 end
0220 end
0221 if isfield(model,'metMiriams')
0222 miriamString=getMiriam(model.metMiriams{i});
0223 else
0224 miriamString='';
0225 end
0226
0227 if isfield(model,'inchis')
0228 if ~isempty(model.inchis{i})
0229 isInchi=true;
0230 else
0231 isInchi=false;
0232 end
0233 else
0234 isInchi=false;
0235 end
0236
0237 if any(miriamString) || isInchi==true
0238 toprint=[toprint '<annotation>'];
0239
0240
0241 if isInchi==true
0242 toprint=[toprint '<in:inchi xmlns:in="http://biomodels.net/inchi" metaid="metaid_M_' model.mets{i} '_inchi">InChI=' model.inchis{i} '</in:inchi>'];
0243 end
0244
0245 toprint=[toprint '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" '...
0246 'xmlns:vCard="http://www.w3.org/2001/vcard-rdf/3.0#" xmlns:bqbiol="http://biomodels.net/biology-qualifiers/" xmlns:bqmodel="http://biomodels.net/model-qualifiers/">'...
0247 '<rdf:Description rdf:about="#metaid_M_' model.mets{i} '">'...
0248 '<bqbiol:is>'...
0249 '<rdf:Bag>'];
0250 if isInchi==true
0251 toprint=[toprint '<rdf:li rdf:resource="#metaid_M_' model.mets{i} '_inchi" />'];
0252 end
0253
0254
0255 toprint=[toprint miriamString '</rdf:Bag></bqbiol:is></rdf:Description></rdf:RDF></annotation>'];
0256 end
0257 end
0258 toprint=[toprint '</species>\n'];
0259 fprintf(fid,toprint);
0260 end
0261
0262
0263 if toCOBRA==false
0264
0265 if isfield(model,'genes')
0266 for i=1:numel(model.genes)
0267 toprint=['<species metaid="metaid_E_' int2str(i) '" id="E_' int2str(i) '" name="' model.genes{i} '" compartment="C_' model.comps{model.geneComps(i)} '" initialAmount="0" sboTerm="SBO:0000014">'];
0268
0269
0270 if isfield(model,'geneShortNames')
0271 if ~isempty(model.geneShortNames{i})
0272 toprint=[toprint '<notes><body xmlns="http://www.w3.org/1999/xhtml"><p>SHORT NAME: ' model.geneShortNames{i} '</p></body></notes>'];
0273 end
0274 end
0275
0276 if isfield(model,'geneMiriams')
0277 miriamString=getMiriam(model.geneMiriams{i});
0278 else
0279 miriamString=[];
0280 end
0281
0282 if ~isempty(miriamString)
0283 toprint=[toprint '<annotation><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" '...
0284 'xmlns:dcterms="http://purl.org/dc/terms/" xmlns:vCard="http://www.w3.org/2001/vcard-rdf/3.0#" xmlns:bqbiol="http://biomodels.net/biology-qualifiers/" '...
0285 'xmlns:bqmodel="http://biomodels.net/model-qualifiers/"><rdf:Description rdf:about="#metaid_E_' int2str(i) '"><bqbiol:is><rdf:Bag>'...
0286 miriamString '</rdf:Bag></bqbiol:is></rdf:Description></rdf:RDF></annotation>'];
0287 end
0288
0289 toprint=[toprint '</species>\n'];
0290 fprintf(fid,toprint);
0291 end
0292
0293
0294
0295 geneComplexes={};
0296 if isfield(model,'grRules')
0297
0298 uniqueRules=unique(model.grRules);
0299 I=cellfun(@any,strfind(uniqueRules,' and '));
0300 uniqueRules(~I)=[];
0301 uniqueRules=strrep(uniqueRules,'(','');
0302 uniqueRules=strrep(uniqueRules,')','');
0303 uniqueRules=strrep(uniqueRules,' and ',':');
0304 for i=1:numel(uniqueRules)
0305 genes=regexp(uniqueRules(i),' or ','split');
0306 genes=genes{1}(:);
0307
0308 I=cellfun(@any,strfind(genes,':'));
0309 geneComplexes=[geneComplexes;genes(I)];
0310 end
0311 end
0312 geneComplexes=unique(geneComplexes);
0313
0314
0315
0316
0317 for i=1:numel(geneComplexes)
0318
0319
0320 fprintf(fid,['<species metaid="metaid_Cx_' int2str(i) '" id="Cx_' int2str(i) '" name="' geneComplexes{i} '" compartment="C_' model.comps{1} '" initialAmount="0" sboTerm="SBO:0000014"></species>\n']);
0321 end
0322 end
0323 end
0324
0325
0326 fprintf(fid,'</listOfSpecies>');
0327
0328
0329 fprintf(fid,'<listOfReactions>');
0330
0331 if toCOBRA==false
0332 if isfield(model,'grRules')
0333
0334 model.grRules=strrep(model.grRules,'(','');
0335 model.grRules=strrep(model.grRules,')','');
0336 model.grRules=strrep(model.grRules,' and ',':');
0337 end
0338 end
0339
0340 for i=1:length(model.rxns)
0341
0342 reversible='false';
0343 if model.rev(i)==1
0344 reversible='true';
0345 end
0346
0347 if isfield(model,'subSystems')
0348 subsystem=model.subSystems{i};
0349 else
0350 subsystem=[];
0351 end
0352 if isfield(model,'rxnComps')
0353 rxnComps=model.comps{model.rxnComps(i)};
0354 else
0355 rxnComps=[];
0356 end
0357 if isfield(model,'eccodes')
0358 eccode=model.eccodes{i};
0359 else
0360 eccode=[];
0361 end
0362
0363 if toCOBRA==false
0364 fprintf(fid,['<reaction metaid="metaid_R_' model.rxns{i} '" id="R_' model.rxns{i} '" name="' model.rxnNames{i} '" reversible="' reversible '" sboTerm="SBO:0000176">']);
0365
0366 if ~isempty(subsystem) || ~isempty(rxnComps)
0367 toPrint='';
0368 if ~isempty(subsystem)
0369 toPrint=[toPrint '<p>SUBSYSTEM: ' subsystem '</p>'];
0370 end
0371
0372
0373 if ~isempty(rxnComps)
0374 toPrint=[toPrint '<p>COMPARTMENT: ' rxnComps '</p>'];
0375 end
0376 fprintf(fid,['<notes><body xmlns="http://www.w3.org/1999/xhtml">' toPrint '</body></notes>']);
0377 end
0378
0379
0380 if isfield(model,'rxnMiriams')
0381 miriamString=getMiriam(model.rxnMiriams{i});
0382 else
0383 miriamString=[];
0384 end
0385
0386
0387 if any(eccode)
0388
0389 eccodes=regexp(eccode,';','split');
0390 for j=1:numel(eccodes)
0391 miriamString=[miriamString '<rdf:li rdf:resource="urn:miriam:ec-code:' eccodes{j} '"/>'];
0392 end
0393 end
0394
0395 if ~isempty(miriamString)
0396 fprintf(fid,['<annotation><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" '...
0397 'xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" '...
0398 'xmlns:vCard="http://www.w3.org/2001/vcard-rdf/3.0#" xmlns:bqbiol="http://biomodels.net/biology-qualifiers/" '...
0399 'xmlns:bqmodel="http://biomodels.net/model-qualifiers/">'...
0400 '<rdf:Description rdf:about="#metaid_R_' model.rxns{i} '">'...
0401 '<bqbiol:is>'...
0402 '<rdf:Bag>'...
0403 miriamString...
0404 '</rdf:Bag>'...
0405 '</bqbiol:is>'...
0406 '</rdf:Description>'...
0407 '</rdf:RDF>'...
0408 '</annotation>']);
0409 end
0410 else
0411 if isfield(model,'grRules')
0412 grRules=model.grRules{i};
0413 else
0414 grRules=[];
0415 end
0416
0417
0418 fprintf(fid,['<reaction id="R_' model.rxns{i} '" name="' model.rxnNames{i} '" reversible="' reversible '">']);
0419
0420 fprintf(fid,'<notes>');
0421 if any(grRules)
0422 fprintf(fid,['<html:p>GENE_ASSOCIATION: ' grRules '</html:p>']);
0423 end
0424 if any(subsystem)
0425 fprintf(fid,['<html:p>SUBSYSTEM: ' subsystem '</html:p>']);
0426 end
0427 if any(eccode)
0428 fprintf(fid,['<html:p>PROTEIN_CLASS: ' eccode '</html:p>']);
0429 end
0430 fprintf(fid,'</notes>');
0431 end
0432
0433
0434 compounds=model.S(:,i);
0435 reactants=find(compounds<0);
0436 products=find(compounds>0);
0437
0438 if any(reactants)
0439 fprintf(fid,'<listOfReactants>');
0440 for j=1:length(reactants)
0441 tempmetname=model.mets{reactants(j)};
0442 fprintf(fid,['<speciesReference species="M_' tempmetname '" stoichiometry="' num2str(-1*compounds(reactants(j))) '"/>']);
0443 end
0444
0445 fprintf(fid,'</listOfReactants>');
0446 end
0447 if any(products)
0448 fprintf(fid,'<listOfProducts>');
0449 for j=1:length(products)
0450 tempmetname=model.mets{products(j)};
0451 fprintf(fid,['<speciesReference species="M_' tempmetname '" stoichiometry="' num2str(compounds(products(j))) '"></speciesReference>']);
0452 end
0453 fprintf(fid,'</listOfProducts>');
0454 end
0455 if toCOBRA==false
0456 if isfield(model,'genes') && isfield(model,'grRules')
0457 if ~isempty(model.grRules{i})
0458 genes=regexp(model.grRules(i),' or ','split');
0459 genes=genes{1}(:);
0460
0461 complexes=cellfun(@any,strfind(genes,':'));
0462 [I normalGenes]=ismember(genes(~complexes),model.genes);
0463 normalGenes(~I)=[];
0464 [I complexGenes]=ismember(genes(complexes),geneComplexes);
0465 complexGenes(~I)=[];
0466 toPrint='';
0467 for j=1:numel(normalGenes)
0468 toPrint=[toPrint '<modifierSpeciesReference species="E_' num2str(normalGenes(j)) '" />'];
0469 end
0470 for j=1:numel(complexGenes)
0471 toPrint=[toPrint '<modifierSpeciesReference species="Cx_' num2str(complexGenes(j)) '" />'];
0472 end
0473 fprintf(fid,['<listOfModifiers>' toPrint '</listOfModifiers>']);
0474 end
0475 end
0476 end
0477
0478
0479
0480
0481
0482
0483
0484 if toCOBRA==false
0485 fprintf(fid,'<kineticLaw><math xmlns="http://www.w3.org/1998/Math/MathML"><ci>FLUX_VALUE</ci></math><listOfParameters>');
0486 fprintf(fid,['<parameter id="LB_R_' model.rxns{i} '" name="LOWER_BOUND" value="' sprintf('%15.8f',model.lb(i)) '" units="mmol_per_gDW_per_hr"/><parameter id="UB_R_' model.rxns{i} '" name="UPPER_BOUND" value="' sprintf('%15.8f',model.ub(i)) '" units="mmol_per_gDW_per_hr"/><parameter id="OBJ_R_' model.rxns{i} '" name="OBJECTIVE_COEFFICIENT" value="' sprintf('%15.8f',model.c(i)) '" units="dimensionless"/><parameter id="FLUX_VALUE" value="0.00000000" units="mmol_per_gDW_per_hr"/>']);
0487 else
0488 fprintf(fid,'<kineticLaw><math xmlns="http://www.w3.org/1998/Math/MathML"><apply><ci> LOWER_BOUND </ci><ci> UPPER_BOUND </ci><ci> OBJECTIVE_COEFFICIENT </ci></apply></math><listOfParameters>');
0489 fprintf(fid,['<parameter id="LOWER_BOUND" value="' sprintf('%15.8f',model.lb(i)) '"/><parameter id="UPPER_BOUND" value="' sprintf('%15.8f',model.ub(i)) '"/><parameter id="OBJECTIVE_COEFFICIENT" value="' sprintf('%15.8f',model.c(i)) '"/>']);
0490 end
0491 fprintf(fid,'</listOfParameters></kineticLaw>');
0492 fprintf(fid,'</reaction>\n');
0493 end
0494
0495
0496 outro='</listOfReactions></model></sbml>';
0497 fprintf(fid,outro);
0498
0499 fclose(fid);
0500
0501
0502 delete(fileName);
0503 movefile(tempF,fileName);
0504 end
0505
0506 function miriamString=getMiriam(miriamStruct)
0507
0508
0509
0510
0511 miriamString='';
0512 if isfield(miriamStruct,'name')
0513 for i=1:numel(miriamStruct.name)
0514 miriamString=[miriamString '<rdf:li rdf:resource="urn:miriam:' miriamStruct.name{i} ':' miriamStruct.value{i} '"/>'];
0515 end
0516 end
0517 end