diff --git a/.gitattributes b/.gitattributes index a1f0cebc..012b630f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,7 +3,8 @@ # Use MATLAB style diff *.m text diff=matlab # Mark as binary to prevent EOL changes. Also no need to track -mafft-linux*/* binary +mafft.bat binary +mafft/ binary # Files/folders that should not be included when downloading repo as ZIP .gitattributes export-ignore .gitignore export-ignore diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 888c2aba..cad0bcf5 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -7,22 +7,24 @@ jobs: runs-on: self-hosted steps: + - name: Checkout + uses: actions/checkout@v2 - - name: Checkout - uses: actions/checkout@v2 + - name: Run tests + id: matlab-test + run: | + TEST_RESULTS=$(/usr/local/bin/matlab -nodisplay -nosplash -nodesktop -r "addpath(genpath('.')); cd('testing/unit_tests'); runtests(struct2table(dir('*.m')).name); exit;") + PARSED_RESULTS=$(echo $TEST_RESULTS | awk -F'com\\.' '{ n = split($2, v, "(___+)|(===+)|(---+)"); for (i = 0; ++i <= n;) { print v[i] } }') + PARSED_RESULTS="${PARSED_RESULTS//'%'/'%25'}" + PARSED_RESULTS="${PARSED_RESULTS//$'\n'/'%0A'}" + PARSED_RESULTS="${PARSED_RESULTS//$'\r'/'%0D'}" + echo ::set-output name=results::$PARSED_RESULTS - - name: Run tests - id: matlab-test - run: | - TEST_RESULTS=$(/usr/local/bin/matlab -nodisplay -nosplash -nodesktop -r "addpath(genpath('.')); cd('testing/unit_tests'); runtests(struct2table(dir('*.m')).name); exit;") - PARSED_RESULTS=$(echo $TEST_RESULTS | awk -F'.com.' '{ n = split($2, v, "__________"); for (i = 0; ++i <= n;) { print v[i] } }') - echo ::set-output name=results::$PARSED_RESULTS - - - name: Post comment - uses: NejcZdovc/comment-pr@v1 - with: - file: "testing-comment.md" - env: - GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} - TEST_RESULTS: ${{steps.matlab-test.outputs.results}} - GH_ACTION_RUN: ${{github.run_id}} \ No newline at end of file + - name: Post comment + uses: NejcZdovc/comment-pr@v1 + with: + file: "testing-comment.md" + env: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + TEST_RESULTS: ${{steps.matlab-test.outputs.results}} + GH_ACTION_RUN: ${{github.run_id}} diff --git a/INIT/getINITModel.m b/INIT/getINITModel.m index 1a944403..c4f54a13 100755 --- a/INIT/getINITModel.m +++ b/INIT/getINITModel.m @@ -109,6 +109,8 @@ if nargin<3 celltype=[]; +else + celltype=char(celltype); end if nargin<4 hpaData=[]; @@ -121,6 +123,8 @@ end if nargin<7 taskFile=[]; +else + taskFile=char(taskFile); end if nargin<8 || isempty(useScoresForTasks) useScoresForTasks=true; diff --git a/INIT/runINIT.m b/INIT/runINIT.m index 3f71bf03..b35b180e 100755 --- a/INIT/runINIT.m +++ b/INIT/runINIT.m @@ -67,24 +67,17 @@ if isempty(rxnScores) rxnScores=zeros(numel(model.rxns),1); end -if nargin<3 +if nargin<3 || isempty(presentMets) presentMets={}; +else + presentMets=convertCharArray(presentMets); end -if isempty(presentMets) - presentMets={}; -end -presentMets=presentMets(:); -if nargin<4 - essentialRxns={}; -end -if isempty(essentialRxns) +if nargin<4 || isempty(essentialRxns) essentialRxns={}; +else + essentialRxns=convertCharArray(essentialRxns); end -essentialRxns=essentialRxns(:); -if nargin<5 - prodWeight=0.5; -end -if isempty(prodWeight) +if nargin<5 || isempty(prodWeight) prodWeight=0.5; end if nargin<6 diff --git a/core/FSEOF.m b/core/FSEOF.m index fc5abbc3..cc575e7e 100755 --- a/core/FSEOF.m +++ b/core/FSEOF.m @@ -23,6 +23,9 @@ % % Usage: targets=FSEOF(model,biomassRxn,targetRxn,iterations,coefficient,outputFile) +biomassRxn=char(biomassRxn); +targetRxn=char(targetRxn); + if nargin<4 iterations=10; coefficient=0.9; @@ -96,6 +99,7 @@ %Generating output formatSpec='%s\t%s\t%s\t%s\t%s\t%s\t%s\n'; if output == 1 %Output to a file + outputFile=char(outputFile); fid=fopen(outputFile,'w'); fprintf(fid,formatSpec,'Slope','rowID','Enzyme ID','Enzyme Name','Subsystems','Direction','Gr Rule'); else %Output to screen diff --git a/core/addExchangeRxns.m b/core/addExchangeRxns.m index 9fc40c2e..660b08bf 100755 --- a/core/addExchangeRxns.m +++ b/core/addExchangeRxns.m @@ -23,11 +23,14 @@ if nargin<3 mets=model.mets; +elseif ~islogical(mets) && ~isnumeric(mets) + mets=convertCharArray(mets); end -reactionType=upper(reactionType); J=getIndexes(model,mets,'mets',false); mets=model.mets(J); +reactionType=char(upper(reactionType)); + %Production is positive for OUT and BOTH if strcmp(reactionType,'IN') I=speye(numel(model.mets)); diff --git a/core/addGenesRaven.m b/core/addGenesRaven.m index 26059125..b853ce36 100755 --- a/core/addGenesRaven.m +++ b/core/addGenesRaven.m @@ -32,11 +32,8 @@ if ~isfield(genesToAdd,'genes') EM='genes is a required field in genesToAdd'; dispEM(EM); -end - -if ~iscellstr(genesToAdd.genes) - EM='genesToAdd.genes must be a cell array of strings'; - dispEM(EM); +else + genesToAdd.genes=convertCharArray(genesToAdd.genes); end %Number of genes @@ -68,14 +65,11 @@ %Some more checks and if they pass then add each field to the structure if isfield(genesToAdd,'geneShortNames') + genesToAdd.geneShortNames=convertCharArray(genesToAdd.geneShortNames); if numel(genesToAdd.geneShortNames)~=nGenes EM='genesToAdd.geneShortNames must have the same number of elements as genesToAdd.genes'; dispEM(EM); end - if ~iscellstr(genesToAdd.geneShortNames) - EM='genesToAdd.geneShortNames must be a cell array of strings'; - dispEM(EM); - end %Add empty field if it doesn't exist if ~isfield(newModel,'geneShortNames') newModel.geneShortNames=largeFiller; diff --git a/core/addMets.m b/core/addMets.m index 303ddd23..223776f8 100755 --- a/core/addMets.m +++ b/core/addMets.m @@ -58,6 +58,8 @@ end if nargin<4 prefix='m_'; +else + prefix=char(prefix); end newModel=model; @@ -69,35 +71,19 @@ %Check some stuff regarding the required fields if ~isfield(metsToAdd,'mets') metsToAdd.mets=generateNewIds(newModel,'mets',prefix,numel(metsToAdd.metNames)); +else + metsToAdd.mets=convertCharArray(metsToAdd.mets); end if ~isfield(metsToAdd,'metNames') metsToAdd.metNames=metsToAdd.mets; +else + metsToAdd.metNames=convertCharArray(metsToAdd.metNames); end if ~isfield(metsToAdd,'compartments') EM='compartments is a required field in metsToAdd'; dispEM(EM); -end -if ischar(metsToAdd.mets) - metsToAdd.mets={metsToAdd.mets}; -elseif ~iscellstr(metsToAdd.mets) - EM='metsToAdd.mets must be a cell array of strings'; - dispEM(EM); -end -if ischar(metsToAdd.metNames) - metsToAdd.metNames={metsToAdd.metNames}; -elseif ~iscellstr(metsToAdd.metNames) - EM='metsToAdd.metNames must be a cell array of strings'; - dispEM(EM); -end -if ~iscellstr(metsToAdd.compartments) - if ischar(metsToAdd.compartments) - temp=cell(numel(metsToAdd.mets),1); - temp(:)={metsToAdd.compartments}; - metsToAdd.compartments=temp; - else - EM='metsToAdd.compartments must be a cell array of strings'; - dispEM(EM); - end +else + metsToAdd.compartments=convertCharArray(metsToAdd.compartments); end %Number of metabolites @@ -193,14 +179,11 @@ end if isfield(metsToAdd,'inchis') + metsToAdd.inchis=convertCharArray(metsToAdd.inchis); if numel(metsToAdd.inchis)~=nMets EM='metsToAdd.inchis must have the same number of elements as metsToAdd.mets'; dispEM(EM); end - if ~iscellstr(metsToAdd.inchis) - EM='metsToAdd.inchis must be a cell array of strings'; - dispEM(EM); - end %Add empty field if it doesn't exist if ~isfield(newModel,'inchis') newModel.inchis=largeFiller; @@ -214,14 +197,11 @@ end if isfield(metsToAdd,'metFormulas') + metsToAdd.metFormulas=convertCharArray(metsToAdd.metFormulas); if numel(metsToAdd.metFormulas)~=nMets EM='metsToAdd.metFormulas must have the same number of elements as metsToAdd.mets'; dispEM(EM); end - if ~iscellstr(metsToAdd.metFormulas) - EM='metsToAdd.metFormulas must be a cell array of strings'; - dispEM(EM); - end %Add empty field if it doesn't exist if ~isfield(newModel,'metFormulas') newModel.metFormulas=largeFiller; @@ -243,6 +223,9 @@ EM='metsToAdd.metCharges must be of type "double"'; dispEM(EM); end + if ~isfield(newModel,'metCharges') + newModel.metCharges=NaN(numel(largeFiller),1); + end newModel.metCharges=[newModel.metCharges;metsToAdd.metCharges(:)]; else %Add default @@ -252,19 +235,16 @@ end if isfield(metsToAdd,'metNotes') + metsToAdd.metNotes=convertCharArray(metsToAdd.metNotes); if numel(metsToAdd.metNotes)~=nMets EM='metsToAdd.metNotes must have the same number of elements as metsToAdd.mets'; dispEM(EM); end - if ~iscellstr(metsToAdd.metNotes) - EM='metsToAdd.metNotes must be a cell array of strings'; - dispEM(EM); - end %Add empty field if it doesn't exist if ~isfield(newModel,'metNotes') newModel.metNotes=largeFiller; end - newModel.metNotes=[newModel.inchis;metsToAdd.metNotes(:)]; + newModel.metNotes=[newModel.metNotes;metsToAdd.metNotes(:)]; else %Add empty strings if structure is in model if isfield(newModel,'metNotes') @@ -326,16 +306,3 @@ end end end - -%For getting the numerical form of metabolite ids on the form "m1". -function I=getInteger(s) -%Checks if a string is on the form "m1" and if so returns the value of the -%integer -I=0; -if strcmpi(s(1),'m') - t=str2double(s(2:end)); - if ~isnan(t) && ~isempty(t) - I=t; - end -end -end diff --git a/core/addRxns.m b/core/addRxns.m index 6240fe3b..05172dfa 100755 --- a/core/addRxns.m +++ b/core/addRxns.m @@ -103,16 +103,20 @@ if nargin<4 compartment=[]; +else + compartment=char(compartment); end if nargin<5 allowNewMets=false; +elseif ~islogical(allowNewMets) + allowNewMets=char(allowNewMets); end if nargin<6 allowNewGenes=false; end if allowNewGenes & isfield(rxnsToAdd,'grRules') - genesToAdd.genes = strjoin(rxnsToAdd.grRules); + genesToAdd.genes = strjoin(convertCharArray(rxnsToAdd.grRules)); genesToAdd.genes = regexp(genesToAdd.genes,' |)|(|and|or','split'); % Remove all grRule punctuation genesToAdd.genes = genesToAdd.genes(~cellfun(@isempty,genesToAdd.genes)); % Remove spaces and empty genes genesToAdd.genes = setdiff(unique(genesToAdd.genes),model.genes); % Only keep new genes @@ -147,10 +151,7 @@ end if eqnType==2 || (eqnType==1 && allowNewMets==true) - if ~ischar(compartment) - EM='compartment must be a string'; - dispEM(EM); - end + compartment=char(compartment); if ~ismember(compartment,model.comps) EM='compartment must match one of the compartments in model.comps'; dispEM(EM); @@ -160,7 +161,8 @@ if ~isfield(rxnsToAdd,'rxns') EM='rxns is a required field in rxnsToAdd'; dispEM(EM); -elseif iscell(rxnsToAdd.rxns) +else + rxnsToAdd.rxns=convertCharArray(rxnsToAdd.rxns); %To fit with some later printing rxnsToAdd.rxns=rxnsToAdd.rxns(:); end @@ -174,30 +176,16 @@ dispEM(EM); end -if ~iscellstr(rxnsToAdd.rxns) && ~ischar(rxnsToAdd.rxns) - %It could also be a string, but it's not encouraged - EM='rxnsToAdd.rxns must be a cell array of strings'; - dispEM(EM); -else - rxnsToAdd.rxns=cellstr(rxnsToAdd.rxns); -end - %Normal case: equations provided if isfield(rxnsToAdd,'equations') - if ~iscellstr(rxnsToAdd.equations) && ~ischar(rxnsToAdd.equations) - %It could also be a string, but it's not encouraged - EM='rxnsToAdd.equations must be a cell array of strings'; - dispEM(EM); - else - rxnsToAdd.equations=cellstr(rxnsToAdd.equations); - end - + rxnsToAdd.equations=convertCharArray(rxnsToAdd.equations); + %Alternative case: mets+stoichiometry provided else %In the case of 1 rxn added (array of strings + vector), transform to %cells of length=1: if iscellstr(rxnsToAdd.mets) - rxnsToAdd.mets = {rxnsToAdd.mets}; + rxnsToAdd.mets={rxnsToAdd.mets}; end if isnumeric(rxnsToAdd.stoichCoeffs) rxnsToAdd.stoichCoeffs = {rxnsToAdd.stoichCoeffs}; @@ -257,6 +245,7 @@ newModel.rxns=[newModel.rxns;rxnsToAdd.rxns(:)]; if isfield(rxnsToAdd,'rxnNames') + rxnsToAdd.rxnNames=convertCharArray(rxnsToAdd.rxnNames); if numel(rxnsToAdd.rxnNames)~=nRxns EM='rxnsToAdd.rxnNames must have the same number of elements as rxnsToAdd.rxns'; dispEM(EM); @@ -312,7 +301,7 @@ end %Fill with standard if it doesn't exist if ~isfield(newModel,'ub') - newModel.ub=repmat(newUb,nOldrxns,1); + newModel.ub=repmat(newUb,nOldRxns,1); end newModel.ub=[newModel.ub;rxnsToAdd.ub(:)]; else @@ -340,6 +329,7 @@ end if isfield(rxnsToAdd,'eccodes') + rxnsToAdd.eccodes=convertCharArray(rxnsToAdd.eccodes); if numel(rxnsToAdd.eccodes)~=nRxns EM='rxnsToAdd.eccodes must have the same number of elements as rxnsToAdd.rxns'; dispEM(EM); @@ -414,6 +404,7 @@ end end if isfield(rxnsToAdd,'grRules') + rxnsToAdd.grRules=convertCharArray(rxnsToAdd.grRules); if numel(rxnsToAdd.grRules)~=nRxns EM='rxnsToAdd.grRules must have the same number of elements as rxnsToAdd.rxns'; dispEM(EM); @@ -431,6 +422,7 @@ end if isfield(rxnsToAdd,'rxnFrom') + rxnsToAdd.rxnFrom=convertCharArray(rxnsToAdd.rxnFrom); if numel(rxnsToAdd.rxnFrom)~=nRxns EM='rxnsToAdd.rxnFrom must have the same number of elements as rxnsToAdd.rxns'; dispEM(EM); @@ -448,6 +440,7 @@ end if isfield(rxnsToAdd,'rxnNotes') + rxnsToAdd.rxnNotes=convertCharArray(rxnsToAdd.rxnNotes); if numel(rxnsToAdd.rxnNotes)~=nRxns EM='rxnsToAdd.rxnNotes must have the same number of elements as rxnsToAdd.rxns'; dispEM(EM); @@ -465,6 +458,7 @@ end if isfield(rxnsToAdd,'rxnReferences') + rxnsToAdd.rxnReferences=convertCharArray(rxnsToAdd.rxnReferences); if numel(rxnsToAdd.rxnReferences)~=nRxns EM='rxnsToAdd.rxnReferences must have the same number of elements as rxnsToAdd.rxns'; dispEM(EM); @@ -482,6 +476,7 @@ end if isfield(rxnsToAdd,'pwys') + rxnsToAdd.pwys=convertCharArray(rxnsToAdd.pwys); if numel(rxnsToAdd.pwys)~=nRxns EM='rxnsToAdd.pwys must have the same number of elements as rxnsToAdd.rxns'; dispEM(EM); diff --git a/core/addRxnsGenesMets.m b/core/addRxnsGenesMets.m index cdada989..ff452e1a 100755 --- a/core/addRxnsGenesMets.m +++ b/core/addRxnsGenesMets.m @@ -5,8 +5,8 @@ % % model draft model where reactions should be copied to % sourceModel model where reactions and metabolites are sourced from -% rxns cell array with reaction IDs (from source model) -% string allowed if only one reaction is added +% rxns cell array with reaction IDs (from source model). Can also +% be string if only one reaction is added % addGene three options: % false no genes are annotated to the new reactions % true grRules ared copied from the sourceModel and @@ -16,10 +16,12 @@ % array, and any new genes are added when % required % (opt, default false) -% rxnNote string explaining why reactions were copied to model, -% is included as newModel.rxnNotes (opt, default +% rxnNote cell array with strings explaining why reactions were copied +% to the model, to be included as newModel.rxnNotes. Can also +% be string if same rxnNotes should be added for each new +% reaction, or only one reaction is to be added (opt, default % 'Added via addRxnsAndMets()') -% confidence double specifying confidence score for all reactions. +% confidence integer specifying confidence score for all reactions. % 4: biochemical data: direct evidence from enzymes % assays % 3: genetic data: knockout/-in or overexpression @@ -45,19 +47,21 @@ if nargin<6 confidence=0; end +rxns=convertCharArray(rxns); if nargin<5 - rxnNote='Added via addRxnsGenesMets()'; + rxnNote={'Added via addRxnsGenesMets()'}; +else + rxnNote=convertCharArray(rxnNote); + if numel(rxnNote)==1 && numel(rxns)>1 + rxnNoteArray=cell(numel(rxns),1); + rxnNoteArray{:}=rxnNote; + rxnNote=rxnNoteArray; + end end if nargin<4 addGene=false; end -%If the supplied object is a character array, then convert it to a cell -%array -if ischar(rxns) - rxns={rxns}; -end - % Obtain indexes of reactions in source model [notNewRxn,oldRxn]=ismember(rxns,model.rxns); rxns=rxns(~notNewRxn); @@ -150,8 +154,7 @@ rxnToAdd.rxns=sourceModel.rxns(rxnIdx); rxnToAdd.lb=sourceModel.lb(rxnIdx); rxnToAdd.ub=sourceModel.ub(rxnIdx); -rxnToAdd.rxnNotes=cell(1,numel(rxnToAdd.rxns)); -rxnToAdd.rxnNotes(:)={rxnNote}; +rxnToAdd.rxnNotes(:)=rxnNote(~notNewRxn); rxnToAdd.rxnConfidenceScores=NaN(1,numel(rxnToAdd.rxns)); if ~isnumeric(confidence) EM='confidence score must be numeric'; diff --git a/core/addTransport.m b/core/addTransport.m index dcf9f69a..a97aa836 100755 --- a/core/addTransport.m +++ b/core/addTransport.m @@ -25,18 +25,14 @@ % Usage: [model, addedRxns]=addTransport(model,fromComp,toComps,metNames,... % isRev,onlyToExisting,prefix) -if iscell(fromComp) - fromComp=fromComp{1}; -end +fromComp=char(fromComp); [I, fromID]=ismember(model.comps,fromComp); fromID=find(fromID); if sum(I)~=1 EM='fromComps must have exactly one match in model.comps'; dispEM(EM); end -if ischar(toComps) - toComps={toComps}; -end +toComps=convertCharArray(toComps); [I, toIDs]=ismember(toComps,model.comps); if ~all(I) EM='All compartments in toComps must have a match in model.comps'; @@ -45,12 +41,11 @@ if nargin<4 %Find all metabolites in fromComp metNames=model.metNames(model.metComps==fromID); -end - -%If an empty set was given -if isempty(metNames) +elseif isempty(metNames) %Find all metabolites in fromComp metNames=model.metNames(ismember(model.metComps,model.comps(fromID))); +else + metNames=convertCharArray(metNames); end if nargin<5 @@ -61,12 +56,11 @@ end if nargin<7 prefix='tr_'; +else + prefix=char(prefix); end %Check that the names are unique -if ischar(metNames) - metNames={metNames}; -end if numel(unique(metNames))~=numel(metNames) dispEM('Not all metabolite names are unique'); end diff --git a/core/buildEquation.m b/core/buildEquation.m index e3741da7..a4a20563 100755 --- a/core/buildEquation.m +++ b/core/buildEquation.m @@ -2,7 +2,7 @@ % buildEquation % Construct single equation string for a given reaction % -% mets string array with metabolites involved in the reaction. +% mets cell array with metabolites involved in the reaction. % stoichCoeffs vector with corresponding stoichiometric coeffs. % isrev logical indicating if the reaction is or not % reversible. @@ -11,12 +11,7 @@ % % Usage: equationString=buildEquation(mets,stoichCoeffs,isrev) -if ~iscellstr(mets) && ~ischar(mets) - EM = 'mets must be a cell array of strings'; - dispEM(EM); -else - mets = cellstr(mets); -end +mets=convertCharArray(mets); if ~isnumeric(stoichCoeffs) EM = 'stoichCoeffs must be a numeric vector'; dispEM(EM); diff --git a/core/canConsume.m b/core/canConsume.m index a8da0f2b..931d0e21 100755 --- a/core/canConsume.m +++ b/core/canConsume.m @@ -15,6 +15,8 @@ if nargin<2 mets=model.mets; +elseif ~islogical(mets) && ~isnumeric(mets) + mets=convertCharArray(mets); end [model, rxns]=addExchangeRxns(model,'in',mets); diff --git a/core/canProduce.m b/core/canProduce.m index dda218f3..1472f5b1 100755 --- a/core/canProduce.m +++ b/core/canProduce.m @@ -16,6 +16,8 @@ if nargin<2 mets=model.mets; +elseif ~islogical(mets) && ~isnumeric(mets) + mets=convertCharArray(mets); end [model, rxns]=addExchangeRxns(model,'out',mets); diff --git a/core/changeGrRules.m b/core/changeGrRules.m index 33545e98..15ceea91 100755 --- a/core/changeGrRules.m +++ b/core/changeGrRules.m @@ -20,13 +20,8 @@ replace=true; end -if isstr(rxns) - rxns={rxns}; -end - -if isstr(grRules) - grRules={grRules}; -end +rxns=convertCharArray(rxns); +grRules=convertCharArray(grRules); if ~(numel(grRules)==numel(rxns)) error('Number of rxns and grRules should be identical') diff --git a/core/changeRxns.m b/core/changeRxns.m index d40b0ec0..e4b068cc 100755 --- a/core/changeRxns.m +++ b/core/changeRxns.m @@ -64,12 +64,9 @@ allowNewMets=false; end -if ischar(rxns) - rxns={rxns}; -end -if ischar(equations) - equations={equations}; -end +rxns=convertCharArray(rxns); +equations=convertCharArray(equations); +compartment=char(compartment); %Find the indexes of the reactions and throw an error if they aren't all %found diff --git a/core/checkProduction.m b/core/checkProduction.m index f8416868..1f49002c 100755 --- a/core/checkProduction.m +++ b/core/checkProduction.m @@ -48,6 +48,8 @@ if nargin<3 excretionFromCompartments=model.comps; +else + excretionFromCompartments=convertCharArray(excretionFromCompartments); end if nargin<4 diff --git a/core/checkRxn.m b/core/checkRxn.m index 3503ab3c..4632e400 100755 --- a/core/checkRxn.m +++ b/core/checkRxn.m @@ -5,7 +5,7 @@ % reactions which cannot have flux % % model a model structure -% rxn the id of the reaction to check +% rxn the id of one reaction to check % cutoff minimal flux for successful production/consumption (opt, % default 10^-7) % revDir true if the reaction should be reversed (opt, default @@ -22,10 +22,7 @@ % % Usage: report=checkRxn(model,rxn,cutoff,revDir,printReport) -%Convert to cell string -if ischar(rxn) - rxn={rxn}; -end +rxn=char(rxn); if nargin<3 cutoff=10^-7; end diff --git a/core/compareMultipleModels.m b/core/compareMultipleModels.m index 3e6ea8b5..a13d84f1 100755 --- a/core/compareMultipleModels.m +++ b/core/compareMultipleModels.m @@ -41,6 +41,11 @@ % Usage: compStruct=compareMultipleModels(models,printResults,... % plotResults,groupVector,funcCompare,taskFile); +%% Stats toolbox required +if ~(exist('mdscale.m','file') && exist('pdist.m','file') && exist('squareform.m','file') && exist('tsne.m','file')) + error('The MATLAB Statistics and Machine Learning Toolbox is required for this function') +end + %% Set up input defaults if nargin < 2 || isempty(printResults) printResults=false; @@ -62,6 +67,8 @@ end if nargin < 6 taskFile = []; +else + taskFile=char(taskFile); end if numel(models) <= 1 EM = 'Cannot compare only one model. Use printModelStats if you want a summary of a model'; @@ -182,16 +189,14 @@ proj_coords = tsne(double(binary_matrix'),'Distance','hamming','NumDimensions',3); % 3D compStruct.structCompMap = proj_coords; axis_labels = {'tSNE 1';'tSNE 2';'tSNE 3'}; - fprintf('*** Done \n\n') -else - fprintf('\nWARNING: Could not complete full structural comparison because the function \n') - fprintf(' "tsne" does not exist in your Matlab version. \n') - fprintf(' Using MDS to project data instead of tSNE. \n') - fprintf(' Please upgrade to Matlab 2017b or higher for full functionality. \n\n') +else % Seems odd to use mdscale if tsne is not found, as both are + % distributed with stats toolbox. If tsne is not present, then also + % mdscale is missing. Anyway, will leave this for now. [proj_coords,stress,disparities] = mdscale(pdist(double(binary_matrix'),'hamming'),3); compStruct.structCompMap = proj_coords; axis_labels = {'MDS 1';'MDS 2';'MDS 3'}; end +fprintf('*** Done \n\n') % plot structure comparison results if plotResults == true diff --git a/core/constructEquations.m b/core/constructEquations.m index 8acdb53a..8672ac8c 100755 --- a/core/constructEquations.m +++ b/core/constructEquations.m @@ -34,8 +34,10 @@ % Usage: equationStrings=constructEquations(model,rxns,useComps,... % sortRevRxns,sortMetNames,useMetID,useFormula,useRevField) -if nargin<2 +if nargin<2 || isempty(rxns) rxns=model.rxns; +elseif ~islogical(rxns) && ~isnumeric(rxns) + rxns=convertCharArray(rxns); end if nargin<3 useComps=true; @@ -55,9 +57,6 @@ if nargin<8 useRevField=true; end -if isempty(rxns) && nargin>2 - rxns=model.rxns; -end %Sort reversible equations if sortRevRxns==true diff --git a/core/constructS.m b/core/constructS.m index d6b5699c..6cf79943 100755 --- a/core/constructS.m +++ b/core/constructS.m @@ -22,6 +22,14 @@ % % Usage: [S, mets, badRxns, reversible]=constructS(equations,mets) +equations=convertCharArray(equations); +switch nargin + case 2 + mets=convertCharArray(mets); + case 3 + rxns=convertCharArray(rxns); +end + badRxns=false(numel(equations),1); %Check that no equations are too short to have reversibility data diff --git a/core/consumeSomething.m b/core/consumeSomething.m index e363b2bf..b7c4d181 100755 --- a/core/consumeSomething.m +++ b/core/consumeSomething.m @@ -42,6 +42,8 @@ if nargin<2 ignoreMets=[]; +elseif ~islogical(ignoreMets) && ~isnumeric(ignoreMets) + ignoreMets=convertCharArray(ignoreMets); end if nargin<3 isNames=false; diff --git a/core/convertCharArray.m b/core/convertCharArray.m new file mode 100644 index 00000000..40d97877 --- /dev/null +++ b/core/convertCharArray.m @@ -0,0 +1,27 @@ +function inputConverted = convertCharArray(funcInput) +%convertCharArray +% Converts input to make sure it is a cell array of character vectors. +% String arrays are transformed into character vectors, and if only one +% character vector is given. Output is always a cell array, also if only +% one character vector is given as input. +% +% Input: +% funcInput function input that should be checked +% +% Output: +% inputConverted cell array of character vectors +% + +if ~isempty(funcInput) + if ischar(funcInput) || isstring(funcInput) + inputConverted = {char(funcInput)}; + elseif ~iscell(funcInput) && ~(all(cellfun(@ischar, funcInput)) || all(cellfun(@isstring, funcInput))) + error([inputname(1) ' should be a (cell array of) character vector(s)']) + else + inputConverted = cellstr(funcInput); + end +else + inputConverted=[]; +end +end + diff --git a/core/convertToIrrev.m b/core/convertToIrrev.m index aae1e62f..5cb353d7 100755 --- a/core/convertToIrrev.m +++ b/core/convertToIrrev.m @@ -16,6 +16,7 @@ if nargin<2 I=true(numel(model.rxns),1); else + rxns=convertCharArray(rxns); I=getIndexes(model,rxns,'rxns',true); end diff --git a/core/copyToComps.m b/core/copyToComps.m index c5ae846d..fb54ecc4 100755 --- a/core/copyToComps.m +++ b/core/copyToComps.m @@ -27,16 +27,22 @@ if nargin<3 rxns=model.rxns; +elseif ~islogical(rxns) && ~isnumeric(rxns) + rxns=convertCharArray(rxns); end if nargin<4 deleteOriginal=false; end if nargin<5 compNames=toComps; +else + compNames=convertCharArray(compNames); end if nargin<6 compOutside=cell(numel(toComps),1); compOutside(:)={''}; +else + compOutside=convertCharArray(compOutside); end originalID=model.id; @@ -46,7 +52,7 @@ for i=1:numel(toComps) %Check if the compartment exists, otherwise add it - [I J]=ismember(toComps(i),model.comps); + [I,J]=ismember(toComps(i),model.comps); if I==false model.comps=[model.comps;toComps(i)]; model.compNames=[model.compNames;compNames(i)]; @@ -78,6 +84,10 @@ model=mergeModels({model;modelToAdd},'metNames'); end +model=rmfield(model,'rxnFrom'); +model=rmfield(model,'metFrom'); +model=rmfield(model,'geneFrom'); + if deleteOriginal==true model=removeReactions(model,rxns,true,true,true); %Also delete unused compartments end diff --git a/core/dispEM.m b/core/dispEM.m index 36f297d3..43d28183 100755 --- a/core/dispEM.m +++ b/core/dispEM.m @@ -21,8 +21,8 @@ function dispEM(string,throwErrors,toList,trimWarnings) toList=[]; elseif isempty(toList) return; -elseif ~iscell(toList) - toList={toList}; +else + toList=convertCharArray(toList); end if nargin<4 trimWarnings=true; diff --git a/core/findGeneDeletions.m b/core/findGeneDeletions.m index 96f6fbe8..8d049542 100755 --- a/core/findGeneDeletions.m +++ b/core/findGeneDeletions.m @@ -50,6 +50,8 @@ if nargin<5 oeFactor=10; end +testType=char(testType); +analysisType=char(analysisType); %Check that the test type is correct if ~strcmpi(testType,'sgd') && ~strcmpi(testType,'dgd') && ~strcmpi(testType,'sgo') && ~strcmpi(testType,'dgo') diff --git a/core/findRAVENroot.m b/core/findRAVENroot.m new file mode 100644 index 00000000..b8f6f3c0 --- /dev/null +++ b/core/findRAVENroot.m @@ -0,0 +1,27 @@ +function [ravenPath, prevDir] = findRAVENroot() +% findRAVENroot +% Finds the root of the RAVEN directory, by searching for the path to +% RAVEN2.png. Can also record the current directory, in case a function will +% use the ravenPath to navigate to a precise folder, and it should return to +% the previous directory afterwards. See e.g. optimizeProb calling glpk. + +ST=dbstack('-completenames'); +prevDir = pwd(); +if length(ST)>1 + ravenPath=ST(2).file; % In case findRAVENroot is run via another function +else + ravenPath=ST(1).file; +end +rootFound = 0; +while rootFound == 0 + isRoot = exist(fullfile(ravenPath,'RAVEN2.png'),'file'); + if isRoot == 2 + rootFound = 1; + else + ravenPathOld = ravenPath; + ravenPath = fileparts(ravenPath); + if strcmp(ravenPathOld,ravenPath) + error('Cannot find the RAVEN root directory. Make sure you have not removed the RAVEN2.png file from your RAVEN installation.') + end + end +end \ No newline at end of file diff --git a/core/fitParameters.m b/core/fitParameters.m index b25a203a..a72334cd 100755 --- a/core/fitParameters.m +++ b/core/fitParameters.m @@ -3,7 +3,8 @@ % Fits parameters such as maintenance ATP by quadratic programming % % model a model structure -% xRxns cell array with the IDs of the reactions that will be fixed for each data point +% xRxns cell array with the IDs of the reactions that will be +% fixed for each data point % xValues matrix with the corresponding values for each % xRxns (columns are reactions) % rxnsToFit cell array with the IDs of reactions that will be fitted to @@ -47,6 +48,9 @@ plotFitting=false; end +xRxns=convertCharArray(xRxns); +rxnsToFit=convertCharArray(rxnsToFit); + %Find the indexes of reactions that will be fitted [I, rxnsToFitIndexes]=ismember(rxnsToFit,model.rxns); diff --git a/core/followChanged.m b/core/followChanged.m index a8c9b4d5..fd64f1ac 100755 --- a/core/followChanged.m +++ b/core/followChanged.m @@ -32,6 +32,8 @@ function followChanged(model,fluxesA,fluxesB, cutOffChange, cutOffFlux, cutOffDi end if nargin<7 metaboliteList=[]; +else + metaboliteList=convertCharArray(metaboliteList); end %If a metabolite list is to be used, then find all the reactions involving diff --git a/core/generateNewIds.m b/core/generateNewIds.m index 58e4911f..ea58afd5 100755 --- a/core/generateNewIds.m +++ b/core/generateNewIds.m @@ -16,6 +16,8 @@ % % Usage: newIds=generateNewIds(model,type,prefix,quantity,numLength) % +type=char(type); +prefix=char(prefix); if type=='rxns' existingIds=model.rxns; diff --git a/core/getAllRxnsFromGenes.m b/core/getAllRxnsFromGenes.m index 4e2bb35d..10471e74 100755 --- a/core/getAllRxnsFromGenes.m +++ b/core/getAllRxnsFromGenes.m @@ -15,10 +15,8 @@ % % Usage: allRxns=getAllRxnsFromGenes(model,rxns) -%If the supplied object is a character array, then convert it to a cell -%array -if ischar(rxns) - rxns={rxns}; +if ~islogical(rxns) && ~isnumeric(rxns) + rxns=convertCharArray(rxns); end rxnIdx=getIndexes(model,rxns,'rxns'); diff --git a/core/getAllowedBounds.m b/core/getAllowedBounds.m index b837d1da..de72a5b0 100755 --- a/core/getAllowedBounds.m +++ b/core/getAllowedBounds.m @@ -18,7 +18,8 @@ if nargin<2 rxns=1:numel(model.rxns); -else +elseif ~islogical(rxns) && ~isnumeric(rxns) + rxns=convertCharArray(rxns); rxns=getIndexes(model,rxns, 'rxns'); end diff --git a/core/getElementalBalance.m b/core/getElementalBalance.m index 84acd258..abe3832e 100755 --- a/core/getElementalBalance.m +++ b/core/getElementalBalance.m @@ -28,6 +28,8 @@ if nargin<2 rxns=[]; +elseif ~islogical(rxns) && ~isnumeric(rxns) + rxns=convertCharArray(rxns); end if nargin<3 diff --git a/core/getEssentialRxns.m b/core/getEssentialRxns.m index 631a7af4..db478802 100755 --- a/core/getEssentialRxns.m +++ b/core/getEssentialRxns.m @@ -16,6 +16,8 @@ if nargin<2 ignoreRxns={}; +else + ignoreRxns=convertCharArray(ignoreRxns); end %Too make sure that it doesn't try to optimize for something @@ -31,7 +33,7 @@ %Check which reactions have flux. Only those can be essential. This is not %the smallest list of reactions, but it's a fast way -rxnsToCheck=setdiff(model.rxns(abs(sol.x)>10^-8),ignoreRxns); +rxnsToCheck=setdiff(model.rxns(abs(sol.x)>10^-12),ignoreRxns); nToCheck=numel(rxnsToCheck); minimize=true; while 1 diff --git a/core/getExchangeRxns.m b/core/getExchangeRxns.m index 86b01492..5d47b60d 100755 --- a/core/getExchangeRxns.m +++ b/core/getExchangeRxns.m @@ -18,6 +18,8 @@ if nargin<2 reactionType='both'; +else + reactionType=char(reactionType); end hasNoProducts=sparse(numel(model.rxns),1); diff --git a/core/getIndexes.m b/core/getIndexes.m index fb2c418f..53b31606 100755 --- a/core/getIndexes.m +++ b/core/getIndexes.m @@ -24,11 +24,10 @@ returnLogical=false; end -%If the supplied object is a character array, then convert it to a cell -%array -if ischar(objects) - objects={objects}; +if ~islogical(objects) && ~isnumeric(objects) + objects=convertCharArray(objects); end +type=char(type); indexes=[]; @@ -79,7 +78,7 @@ elseif ~isempty(index) indexes(i)=index; else - error(['Could not find object ' objects{i} ' in the model']); + error(['Could not find object ''' objects{i} ''' in the model']); end end else diff --git a/core/getMetsInComp.m b/core/getMetsInComp.m index 9ef1ec61..ae6580ed 100755 --- a/core/getMetsInComp.m +++ b/core/getMetsInComp.m @@ -10,9 +10,7 @@ % % Usage: [I, metNames]=getMetsInComp(model,comp) -if ischar(comp) - comp={comp}; -end +comp=char(comp); J=find(ismember(upper(model.comps),upper(comp))); diff --git a/core/getMinNrFluxes.m b/core/getMinNrFluxes.m index bc920701..25deba8c 100755 --- a/core/getMinNrFluxes.m +++ b/core/getMinNrFluxes.m @@ -27,20 +27,14 @@ % % Usage: [x,I,exitFlag]=getMinNrFluxes(model, toMinimize, params, scores) -% glpk solver as implemented by COBRA does not work well for MILP. -global CBT_MILP_SOLVER -if strcmp(getpref('RAVEN','solver'),'cobra') && strcmp(CBT_MILP_SOLVER,'glpk') - dispEM('The current solver is set to ''cobra'', while in COBRA the MILP solver has been set to ''glpk''. The COBRA implementation of glpk is not well suitable for solving MILPs. Please install the Gurobi or an alternative MILP solver.',true); -end - exitFlag=1; if nargin<2 toMinimize=model.rxns; +elseif ~islogical(toMinimize) && ~isnumeric(toMinimize) + toMinimize=convertCharArray(toMinimize); else - if ~iscell(toMinimize) - toMinimize=model.rxns(toMinimize); - end + toMinimize=model.rxns(toMinimize); end %For passing parameters to the solver @@ -127,8 +121,7 @@ prob.lb = [prob.blx; prob.blc]; prob.ub = [prob.bux; prob.buc]; prob.osense=1; -prob.csense=char(zeros(size(prob.a,1),1)); -prob.csense(:)='E'; +prob.csense=repmat('E', 1, size(prob.a,1),1); prob.b=zeros(size(prob.a,1), 1); %Use the output from the linear solution as starting point. Only the values @@ -136,8 +129,9 @@ prob.sol.int.xx=zeros(numel(prob.c),1); prob.sol.int.xx(prob.ints.sub(sol.x(indexes)>10^-12))=1; prob.x0=[]; -prob.vartype=repmat('C', 1, size(prob.A,2)); -prob.vartype(prob.ints.sub) = 'B'; +prob.vartype=repmat('C', size(prob.A,2), 1); +prob.vartype(prob.ints.sub) = 'I'; % with .lb = 0 and .ub = 1, they are binary +% integers (glpk in octave only allows 'continuous' or '', not 'binary') prob=rmfield(prob,{'blx','bux','blc','buc'}); % Optimize the problem diff --git a/core/getModelFromHomology.m b/core/getModelFromHomology.m index 76119130..56c098fe 100755 --- a/core/getModelFromHomology.m +++ b/core/getModelFromHomology.m @@ -69,8 +69,12 @@ hitGenes.oldGenes = []; % collect the old genes from the template model (organism) hitGenes.newGenes = []; % collect the new genes of the draft model (target organism) +getModelFor=char(getModelFor); + if nargin<4 preferredOrder=[]; +else + preferredOrder=convertCharArray(preferredOrder); end if nargin<5 strictness=1; @@ -91,8 +95,6 @@ mapNewGenesToOld=true; end -preferredOrder=preferredOrder(:); - if isfield(models,'S') models={models}; end diff --git a/core/getRxnsInComp.m b/core/getRxnsInComp.m index 2cbd903f..98da6aea 100755 --- a/core/getRxnsInComp.m +++ b/core/getRxnsInComp.m @@ -13,9 +13,7 @@ % % Usage: [I, rxnNames]=getRxnsInComp(model,comp,includePartial) -if ischar(comp) - comp={comp}; -end +comp=char(comp); if nargin<3 includePartial=false; end diff --git a/core/haveFlux.m b/core/haveFlux.m index 57de806d..4b6477e3 100755 --- a/core/haveFlux.m +++ b/core/haveFlux.m @@ -27,6 +27,8 @@ end if nargin<3 rxns=model.rxns; +elseif ~islogical(rxns) && ~isnumeric(rxns) + rxns=convertCharArray(rxns); end %This is since we're maximizing for the sum of fluxes, which isn't possible @@ -49,7 +51,9 @@ %Maximize for all fluxes first in order to get fewer rxns to test smallModel.c=ones(numel(smallModel.c),1); sol=solveLP(smallModel); -J(abs(sol.x(mixIndexes))>cutOff)=true; +if ~isempty(sol.x) + J(abs(sol.x(mixIndexes))>cutOff)=true; +end %Loop through and maximize then minimize each rxn if it doesn't already %have a flux diff --git a/core/makeSomething.m b/core/makeSomething.m index 3c1cb6ab..71ce9eb4 100755 --- a/core/makeSomething.m +++ b/core/makeSomething.m @@ -44,6 +44,8 @@ if nargin<2 ignoreMets=[]; +elseif ~islogical(ignoreMets) && ~isnumeric(ignoreMets) + ignoreMets=convertCharArray(ignoreMets); end if nargin<3 isNames=false; diff --git a/core/mergeModels.m b/core/mergeModels.m index b118e820..fece8065 100755 --- a/core/mergeModels.m +++ b/core/mergeModels.m @@ -1,6 +1,9 @@ function model=mergeModels(models,metParam,supressWarnings) % mergeModels -% Merges models into one model structure. +% Merges models into one model structure. Reactions are added without any +% checks, so duplicate reactions might appear. Metabolites are matched by +% their name and compartment (metaboliteName[comp]), while genes are +% matched by their name. % % models a cell array with model structures % metParam string specifying whether to refer to metabolite name @@ -23,6 +26,8 @@ if nargin<2 metParam='metNames'; +else + metParam=char(metParam); end if nargin<3 @@ -43,16 +48,6 @@ model.geneFrom(:)={models{1}.id}; end -if isfield(model,'subSystems') - hasDeletedSubSystem=false; -else - if supressWarnings==false - EM='Cannot add subsystems since the existing model has no subsystems info. All reactions must have a subsystem for this to be included'; - dispEM(EM,false); - end - hasDeletedSubSystem=true; -end - if isfield(model,'equations') model=rmfield(model,'equations'); end @@ -93,16 +88,21 @@ model.c=[model.c;models{i}.c]; model.rev=[model.rev;models{i}.rev]; - if hasDeletedSubSystem==false - if isfield(models{i},'subSystems') + if isfield(models{i},'subSystems') + if isfield(model,'subSystems') model.subSystems=[model.subSystems;models{i}.subSystems]; else - if supressWarnings==false - EM='Cannot add subsystems since the existing model has no subsystems info. All reactions must have a subsystem for this to be included. Deleting subSystems field'; - dispEM(EM,false); - end - hasDeletedSubSystem=true; - model=rmfield(model,'subSystems'); + emptySubSystem=cell(numel(model.rxns)-numel(models{i}.rxns),1); + emptySubSystem(:)={''}; + emptySubSystem=cellfun(@(x) cell(0,0),emptySubSystem,'UniformOutput',false); + model.subSystems=[emptySubSystem;models{i}.subSystems]; + end + else + if isfield(model,'subSystems') + emptySubSystem=cell(numel(models{i}.rxns),1); + emptySubSystem(:)={''}; + emptySubSystem=cellfun(@(x) cell(0,0),emptySubSystem,'UniformOutput',false); + model.subSystems=[model.subSystems;emptySubSystem]; end end diff --git a/core/permuteModel.m b/core/permuteModel.m index 23a06cea..fc672bec 100755 --- a/core/permuteModel.m +++ b/core/permuteModel.m @@ -15,7 +15,7 @@ % Usage: newModel=permuteModel(model, indexes, type) newModel=model; -indexes=indexes(:); +type=char(type); switch type case 'rxns' diff --git a/core/predictLocalization.m b/core/predictLocalization.m index 283dad71..cd28bd7d 100755 --- a/core/predictLocalization.m +++ b/core/predictLocalization.m @@ -92,6 +92,7 @@ dispEM(EM,false); end +defaultCompartment=char(defaultCompartment); I=ismember(defaultCompartment,GSS.compartments); if I==false EM='defaultCompartment not found in GSS'; diff --git a/core/printFluxes.m b/core/printFluxes.m index cbd2bddc..e0929655 100755 --- a/core/printFluxes.m +++ b/core/printFluxes.m @@ -32,7 +32,7 @@ function printFluxes(model, fluxes, onlyExchange, cutOffFlux, outputFile,outputS % hand sides are lumped % % Usage: printFluxes(model, fluxes, onlyExchange, cutOffFlux, -% outputFile,outputString) +% outputFile,outputString,metaboliteList) if nargin<3 onlyExchange=true; @@ -47,19 +47,21 @@ function printFluxes(model, fluxes, onlyExchange, cutOffFlux, outputFile,outputS fid=1; else if ~isempty(outputFile) + outputFile=char(outputFile); fid=fopen(outputFile,'w'); else fid=1; end end -if nargin<6 - outputString='%rxnID\t(%rxnName):\t%flux\n'; -end -if isempty(outputString) +if nargin<6 || isempty(outputString) outputString='%rxnID\t(%rxnName):\t%flux\n'; +else + outputString=char(outputString); end if nargin<7 metaboliteList={}; +else + metaboliteList=convertCharArray(metaboliteList); end if numel(fluxes)~=numel(model.rxns) EM='The number of fluxes and the number of reactions must be the same'; diff --git a/core/printModel.m b/core/printModel.m index 3080ceff..c05fe4eb 100755 --- a/core/printModel.m +++ b/core/printModel.m @@ -35,23 +35,25 @@ function printModel(model,rxnList,outputString,outputFile,metaboliteList) % % Usage: printModel(model,rxnList,outputString,outputFile,metaboliteList) -if nargin<2 +if nargin<2 || isempty(rxnList) rxnList=model.rxns; +elseif ~islogical(rxnList) && ~isnumeric(rxnList) + rxnList=convertCharArray(rxnList); end -if isempty(rxnList) - rxnList=model.rxns; -end -if nargin<3 - outputString='%rxnID (%rxnName)\n\t%eqn [%lower %upper]\n'; -end -if isempty(outputString) +if nargin<3 || isempty(outputString) outputString='%rxnID (%rxnName)\n\t%eqn [%lower %upper]\n'; +else + outputString=char(outputString); end if nargin<4 outputFile=[]; +else + outputFile=char(outputFile); end if nargin<5 metaboliteList=[]; +else + metaboliteList=convertCharArray(metaboliteList); end I=getIndexes(model,rxnList,'rxns',true)*1.00; %To convert it to "fluxes" diff --git a/core/removeBadRxns.m b/core/removeBadRxns.m index 81ff6f59..0aaceed9 100755 --- a/core/removeBadRxns.m +++ b/core/removeBadRxns.m @@ -74,12 +74,16 @@ end if nargin<3 ignoreMets=[]; +elseif ~islogical(ignoreMets) && ~isnumeric(ignoreMets) + ignoreMets=convertCharArray(ignoreMets); end if nargin<4 isNames=false; end if nargin<5 balanceElements={'C';'P';'S';'N';'O'}; +else + balanceElements=convertCharArray(balanceElements); end if nargin<6 refModel=[]; @@ -167,7 +171,7 @@ %If there are unbalanced rxns then delete one of them and iterate if any(I) - rxnToRemove=I(randsample(numel(I),1)); + rxnToRemove=I(randperm(numel(I),1)); else %If there are no unbalanced rxns in the solution if rxnRules==1 @@ -187,7 +191,7 @@ %If there are any such reactions, remove one of them and %iterate if any(I) - rxnToRemove=I(randsample(numel(I),1)); + rxnToRemove=I(randperm(numel(I),1)); else if rxnRules==2 %This happens when all reactions used are balanced @@ -218,7 +222,7 @@ end end I=find(abs(solution)>10^-8); - rxnToRemove=I(randsample(numel(I),1)); + rxnToRemove=I(randperm(numel(I),1)); end end end diff --git a/core/removeGenes.m b/core/removeGenes.m index d797b6b6..4071e040 100755 --- a/core/removeGenes.m +++ b/core/removeGenes.m @@ -37,8 +37,8 @@ end reducedModel = model; %Only remove genes that are actually in the model -try - ischar(genesToRemove{1}); +if ~islogical(genesToRemove) || ~isnumeric(genesToRemove) + genesToRemove=convertCharArray(genesToRemove); genesToRemove=genesToRemove(ismember(genesToRemove,model.genes)); end if ~isempty(genesToRemove) diff --git a/core/removeMets.m b/core/removeMets.m index 67d92819..1961e493 100755 --- a/core/removeMets.m +++ b/core/removeMets.m @@ -22,9 +22,8 @@ % % Usage: reducedModel=removeMets(model,metsToRemove,isNames,... % removeUnusedRxns,removeUnusedGenes,removeUnusedComps) - -if ischar(metsToRemove) - metsToRemove={metsToRemove}; +if ~islogical(metsToRemove) && ~isnumeric(metsToRemove) + metsToRemove=convertCharArray(metsToRemove); end if nargin<3 @@ -43,16 +42,9 @@ removeUnusedComps=false; end -if isNames==true - %Check that metsToRemove is a cell array - if iscellstr(metsToRemove)==false - if ischar(metsToRemove) - metsToRemove={metsToRemove}; - else - EM='Must supply a cell array of strings if isNames=true'; - dispEM(EM); - end - end +%Check that metsToRemove is a cell array +if isNames==true && ~iscell(metsToRemove) + error('Must supply a cell array of strings if isNames=true'); end reducedModel=model; diff --git a/core/removeReactions.m b/core/removeReactions.m index c0d8615e..59b6c6e5 100755 --- a/core/removeReactions.m +++ b/core/removeReactions.m @@ -27,9 +27,8 @@ if nargin<5 removeUnusedComps=false; end - -if ischar(rxnsToRemove) - rxnsToRemove={rxnsToRemove}; +if ~islogical(rxnsToRemove) && ~isnumeric(rxnsToRemove) + rxnsToRemove=convertCharArray(rxnsToRemove); end reducedModel=model; diff --git a/core/replaceMets.m b/core/replaceMets.m index a50444d2..00f003a3 100755 --- a/core/replaceMets.m +++ b/core/replaceMets.m @@ -17,6 +17,9 @@ % % Usage: model=replaceMets(model,metabolite,replacement,verbose) +metabolite=char(metabolite); +replacement=char(replacement); + if nargin<4 verbose=false; end @@ -26,15 +29,13 @@ % possible. repIdx = find(strcmp(replacement,model.metNames)); if isempty(repIdx) - EM='The replacement metabolite name cannot be found in the model.' - dispEM(EM,true); + error('The replacement metabolite name cannot be found in the model.'); end % Change name and information from metabolite to replacement metabolite metIdx = find(strcmp(metabolite,model.metNames)); if isempty(metIdx) - EM='The to-be-replaced metabolite name cannot be found in the model.' - dispEM(EM,true); + error('The to-be-replaced metabolite name cannot be found in the model.'); end if verbose==true fprintf('\n\nThe following reactions contain the replaced metabolite as reactant:\n') @@ -68,9 +69,11 @@ idxDelete=[]; for i = 1:length(repIdx) metCompsNidx=find(strcmp(metCompsN(repIdx(i)), metCompsN)); - if gt(length(metCompsNidx),1) % If more than 1 metabolite matches - model.S(metCompsNidx(1),:) = model.S(metCompsNidx(1),:) + model.S(metCompsNidx(2:end),:); - idxDelete=[idxDelete; metCompsNidx(2:end)]; % Make list of metabolite IDs to delete + if length(metCompsNidx)>1 + for j = 2:length(metCompsNidx) + model.S(metCompsNidx(1),:) = model.S(metCompsNidx(1),:) + model.S(metCompsNidx(j),:); + idxDelete=[idxDelete; metCompsNidx(j)]; % Make list of metabolite IDs to delete + end end end diff --git a/core/reporterMetabolites.m b/core/reporterMetabolites.m index f43199b4..9e4b08ea 100755 --- a/core/reporterMetabolites.m +++ b/core/reporterMetabolites.m @@ -39,6 +39,7 @@ % Usage: repMets=reporterMetabolites(model,genes,genePValues,printResults,... % outputFile,geneFoldChanges) +genes=convertCharArray(genes); if nargin<4 printResults=false; end diff --git a/core/setExchangeBounds.m b/core/setExchangeBounds.m index 4613f1be..c2631da1 100755 --- a/core/setExchangeBounds.m +++ b/core/setExchangeBounds.m @@ -50,8 +50,8 @@ % handle input arguments if nargin < 2 mets = []; -elseif ischar(mets) - mets = {mets}; % in case only one metabolite is provided as a string +elseif ~islogical(mets) || ~isnumeric(mets) + mets=convertCharArray(mets); end if nargin < 3 || isempty(lb) @@ -186,8 +186,8 @@ [metInd,rxnInd] = find(model_temp.S(exchMetInd,exchRxnInd) ~= 0); % check for any metabolites that are exchanged in more than one reaction -tbl = tabulate(metInd); -repeatedInds = tbl(:,2) > 1; +[tbl,i,~] = unique(metInd,'first'); +repeatedInds = find(not(ismember(1:numel(tbl),i))); multiMetInd = exchMetInd(metInd(repeatedInds)); if ~isempty(multiMetInd) fprintf('WARNING: The following metabolites are involved in more than one exchange reaction:\n'); diff --git a/core/setParam.m b/core/setParam.m index 532c71d2..b7816c23 100755 --- a/core/setParam.m +++ b/core/setParam.m @@ -23,29 +23,22 @@ % % Usage: model=setParam(model, paramType, rxnList, params) +paramType=convertCharArray(paramType); if ~isempty(setdiff(paramType,{'lb';'ub';'eq';'obj';'rev';'var'})) EM=['Incorrect parameter type: "' paramType '"']; dispEM(EM); end -%Allow to set several parameters to the same value -if numel(rxnList)~=numel(params) && numel(params)~=1 - EM='The number of parameter values and the number of reactions must be the same'; - dispEM(EM); -end - if isnumeric(rxnList) || islogical(rxnList) rxnList=model.rxns(rxnList); -elseif ischar(rxnList) - rxnList={rxnList}; +else + rxnList=convertCharArray(rxnList); end -if ischar(paramType) - paramType={paramType}; -end - -if isnumeric(params) - params=[params]; +%Allow to set several parameters to the same value +if numel(rxnList)~=numel(params) && numel(params)~=1 + EM='The number of parameter values and the number of reactions must be the same'; + dispEM(EM); end if length(rxnList)>1 diff --git a/core/simplifyModel.m b/core/simplifyModel.m index be3d97b8..bf970416 100755 --- a/core/simplifyModel.m +++ b/core/simplifyModel.m @@ -59,6 +59,8 @@ end if nargin<9 reservedRxns=[]; +else + reservedRxns=convertCharArray(reservedRxns); end if nargin<10 suppressWarnings=false; diff --git a/core/sortModel.m b/core/sortModel.m index d8d21e5d..bc6b7548 100755 --- a/core/sortModel.m +++ b/core/sortModel.m @@ -73,7 +73,7 @@ end end subsystemsUnique=unique(subsystemsUnique); - for i=1:numel(subsystems) + for i=1:numel(subsystemsUnique) %Get all reactions for that subsystem rxns=find(~cellfun(@isempty,regexp(subsystemsConcatenated,subsystemsUnique(i)))); diff --git a/doc/INIT/getINITModel.html b/doc/INIT/getINITModel.html index f0c1ac98..15549864 100644 --- a/doc/INIT/getINITModel.html +++ b/doc/INIT/getINITModel.html @@ -261,354 +261,358 @@

SOURCE CODE ^if nargin<3 0111 celltype=[]; -0112 end -0113 if nargin<4 -0114 hpaData=[]; -0115 end -0116 if nargin<5 -0117 arrayData=[]; -0118 end -0119 if nargin<6 -0120 metabolomicsData=[]; -0121 end -0122 if nargin<7 -0123 taskFile=[]; -0124 end -0125 if nargin<8 || isempty(useScoresForTasks) -0126 useScoresForTasks=true; -0127 end -0128 if nargin<9 || isempty(printReport) -0129 printReport=true; -0130 end -0131 if nargin<10 -0132 taskStructure=[]; -0133 end -0134 if nargin<11 -0135 params=[]; -0136 end -0137 if nargin<12 -0138 paramsFT=[]; -0139 end -0140 -0141 %Check that the model is in the closed form -0142 if ~isfield(refModel,'unconstrained') -0143 EM='Exchange metabolites should normally not be removed from the model when using getINITModel. Use importModel(file,false) to import a model with exchange metabolites remaining (see the documentation for details)'; -0144 dispEM(EM); -0145 end -0146 -0147 %Create the task structure if not supplied -0148 if any(taskFile) && isempty(taskStructure) -0149 taskStructure=parseTaskList(taskFile); -0150 end -0151 -0152 -0153 % sc-tINIT to identify confidence levels of gene expression -0154 if ~isempty(arrayData) && isfield(arrayData,'singleCells') -0155 if arrayData.singleCells == 1 -0156 % Check to ensure cell type is defined -0157 if ~isfield(arrayData,'celltypes') -0158 dispEM('arrayData must contain cell type information if sc-tINIT is to be used','false'); -0159 end -0160 if ~ismember(upper(celltype),upper(arrayData.celltypes)) -0161 dispEM('The cell type name does not match'); -0162 end -0163 -0164 % Analyze only cell type of interest -0165 J= strcmpi(arrayData.celltypes,celltype); -0166 -0167 % Analyze only genes included in the reference model -0168 I=ismember(arrayData.genes,refModel.genes); -0169 -0170 % Convert expression data to population fractions -0171 binary_levels = arrayData.levels(I,J)~=0; % Classify each gene as detected (1) or not (0) in each cell -0172 cell_count_levels = sum(binary_levels,2); % Number of cells expressing each transcript -0173 cell_frac_levels = cell_count_levels/size(binary_levels,2); % Number of cells expressing each transcript -0174 -0175 % Bin cell_frac_counts manually -0176 x = 0:.01:1; -0177 for(i = 1:length(x)) -0178 cell_frac_count(i) = sum(round(cell_frac_levels,2)==x(i)); -0179 end -0180 -0181 % Fit four beta distributions -0182 cell_frac_count(cell_frac_count==0) = NaN; % Remove zeros from optimization -0183 cell_frac_count(1) = NaN; % Remove non-expressed genes from optimization -0184 x_lim = 1; % Somewhat arbitrary parameter to fit left tail of distr. -0185 myfun = @(par) nansum((cell_frac_count(1:find(x>=x_lim,1)) - ... -0186 abs(par(1))*betapdf(x(1:find(x>=x_lim,1)),abs(par(2)),abs(par(3))) - ... -0187 abs(par(4))*betapdf(x(1:find(x>=x_lim,1)),abs(par(5)),abs(par(6))) - ... -0188 abs(par(7))*betapdf(x(1:find(x>=x_lim,1)),abs(par(8)),abs(par(9))) - ... -0189 abs(par(10))*betapdf(x(1:find(x>=x_lim,1)),abs(par(11)),abs(par(12)))).^2); -0190 -0191 par0 = [4,2,100,7,2,30,7,5,20,5,15,20]; -0192 opts = optimset('Display','off'); -0193 [par,f_val] = fminsearch(myfun,par0,opts); -0194 par = abs(par); -0195 -0196 % Plot results -0197 if (isfield(arrayData,'plotResults')) -0198 if arrayData.plotResults == true -0199 figure(); hold on; plot(x,cell_frac_count,'ko','MarkerSize',5); -0200 plot(x,abs(par(1))*betapdf(x,abs(par(2)),abs(par(3))),'b-','LineWidth',1) -0201 plot(x,abs(par(4))*betapdf(x,abs(par(5)),abs(par(6))),'b-','LineWidth',1) -0202 plot(x,abs(par(7))*betapdf(x,abs(par(8)),abs(par(9))),'b-','LineWidth',1) -0203 plot(x,abs(par(10))*betapdf(x,abs(par(11)),abs(par(12))),'b-','LineWidth',1) -0204 plot(x,abs(par(1))*betapdf(x,abs(par(2)),abs(par(3))) + ... -0205 abs(par(4))*betapdf(x,abs(par(5)),abs(par(6))) + ... -0206 abs(par(7))*betapdf(x,abs(par(8)),abs(par(9))) + ... -0207 abs(par(10))*betapdf(x,abs(par(11)),abs(par(12))),'-','Color',[.5 .5 .5],'LineWidth',2) -0208 xlabel('Expression Probability');ylabel('# of genes');set(gca,'FontSize',14,'LineWidth',1.25); -0209 title('Expression prediction','FontSize',18,'FontWeight','bold') -0210 end -0211 end -0212 -0213 % Score genes based on population expression (p = .05) -0214 exprs_cutoff_1 = find(cdf('beta',x,par(2),par(3)) >.95,1)-1; % Find index of no confidence genes -0215 exprs_cutoff_2 = find(cdf('beta',x,par(5),par(6)) >.95,1)-1; % Find index of low confidence genes -0216 exprs_cutoff_3 = find(cdf('beta',x,par(8),par(9)) >.95,1)-1; % Find index of low confidence genes -0217 exprs_cutoffs = sort([exprs_cutoff_1,exprs_cutoff_2,exprs_cutoff_3]); -0218 gene_scores = cell_frac_levels*0; -0219 gene_scores(cell_frac_levels <= x(exprs_cutoffs(1))) = 4; % Not detected -0220 gene_scores(logical((cell_frac_levels >= x(exprs_cutoffs(1))).*(cell_frac_levels < x(exprs_cutoffs(2))))) = 3; % Low detection -0221 gene_scores(logical((cell_frac_levels >= x(exprs_cutoffs(2))).*(cell_frac_levels < x(exprs_cutoffs(3))))) = 2; % Medium detection -0222 gene_scores(cell_frac_levels > x(exprs_cutoffs(3))) = 1; % High detection -0223 -0224 % Replace hpaData with singleCellData -0225 if printReport==true -0226 dispEM('Single cell data is not currently compatible with HPA data. \n Replacing hpaData with single cell-based scoring.',false); -0227 end -0228 hpaData.genes = arrayData.genes; -0229 hpaData.tissues = arrayData.tissues; -0230 hpaData.celltypes = arrayData.celltypes; -0231 hpaData.levels = [{'High'},{'Medium'},{'Low'},{'None'}]; -0232 hpaData.gene2Level = zeros(length(arrayData.genes),length(arrayData.celltypes)); -0233 for i = 1:length(find(J)) -0234 find_var = find(J,i); -0235 hpaData.gene2Level(I,find_var(end)) = gene_scores; -0236 end -0237 -0238 % Remove arrayData from the analysis (Might be a bad idea) -0239 clear arrayData -0240 arrayData=[]; -0241 end -0242 end -0243 -0244 -0245 if printReport==true -0246 if any(celltype) -0247 fprintf(['***Generating model for: ' tissue ' - ' celltype '\n']); -0248 else -0249 fprintf(['***Generating model for: ' tissue '\n']); -0250 end -0251 if ~isempty(hpaData) -0252 fprintf('-Using HPA data\n'); -0253 end -0254 if ~isempty(arrayData) -0255 fprintf('-Using array data\n'); -0256 end -0257 if ~isempty(metabolomicsData) -0258 fprintf('-Using metabolomics data\n'); -0259 end -0260 if ~isempty(taskFile) || ~isempty(taskStructure) -0261 fprintf('-Using metabolic tasks\n'); -0262 end -0263 fprintf('\n'); -0264 -0265 printScores(refModel,'Reference model statistics',hpaData,arrayData,tissue,celltype); -0266 end -0267 -0268 %Remove dead-end reactions to speed up the optimization and to -0269 %differentiate between reactions removed by INIT and those that are -0270 %dead-end -0271 [~, deletedDeadEndRxns]=simplifyModel(refModel,true,false,true,true,true); -0272 cModel=removeReactions(refModel,deletedDeadEndRxns,false,true); -0273 -0274 %Store the connected model like this to keep track of stuff -0275 if printReport==true -0276 printScores(cModel,'Pruned model statistics',hpaData,arrayData,tissue,celltype); -0277 end -0278 -0279 %If tasks have been defined, then go through them and get essential -0280 %reactions -0281 if ~isempty(taskStructure) -0282 [taskReport, essentialRxnMat]=checkTasks(cModel,[],printReport,true,true,taskStructure); -0283 -0284 essentialRxnsForTasks=cModel.rxns(any(essentialRxnMat,2)); -0285 -0286 %Remove tasks that cannot be performed -0287 taskStructure(taskReport.ok==false)=[]; -0288 if printReport==true -0289 printScores(removeReactions(cModel,setdiff(cModel.rxns,essentialRxnsForTasks),true,true),'Reactions essential for tasks',hpaData,arrayData,tissue,celltype); -0290 end -0291 else -0292 essentialRxnsForTasks={}; -0293 end -0294 -0295 %Score the connected model -0296 [rxnScores, geneScores]=scoreModel(cModel,hpaData,arrayData,tissue,celltype); -0297 -0298 %Run the INIT algorithm. The exchange reactions that are used in the final -0299 %reactions will be open, which doesn't fit with the last step. Therefore -0300 %delete reactions from the original model instead of taking the output. The -0301 %default implementation does not constrain reversible reactions to only -0302 %carry flux in one direction. Runs without the constraints on reversibility -0303 %and with all output allowed. This is to reduce the complexity of the -0304 %problem. -0305 [~, deletedRxnsInINIT, metProduction]=runINIT(simplifyModel(cModel),rxnScores,metabolomicsData,essentialRxnsForTasks,0,true,false,params); -0306 initModel=removeReactions(cModel,deletedRxnsInINIT,true,true); -0307 if printReport==true -0308 printScores(initModel,'INIT model statistics',hpaData,arrayData,tissue,celltype); -0309 printScores(removeReactions(cModel,setdiff(cModel.rxns,deletedRxnsInINIT),true,true),'Reactions deleted by INIT',hpaData,arrayData,tissue,celltype); -0310 end -0311 -0312 %The full model has exchange reactions in it. fitTasks calls on fillGaps, -0313 %which automatically removes exchange metabolites (because it assumes that -0314 %the reactions are constrained when appropriate). In this case the -0315 %uptakes/outputs are retrieved from the task sheet instead. To prevent -0316 %exchange reactions being used to fill gaps, they are delete from the -0317 %reference model here. -0318 initModel.id='INITModel'; -0319 -0320 %If gaps in the model should be filled using a task list -0321 if ~isempty(taskStructure) -0322 %Remove exchange reactions and reactions already included in the INIT -0323 %model -0324 refModelNoExc=removeReactions(refModel,union(initModel.rxns,getExchangeRxns(refModel)),true,true); -0325 -0326 %At this stage the model is fully connected and most of the genes with -0327 %good scores should have been included. The final gap-filling should -0328 %take the scores of the genes into account, so that "rather bad" -0329 %reactions are preferred to "very bad" reactions. However, reactions -0330 %with positive scores will be included even if they are not connected -0331 %in the current formulation. Therefore, such reactions will have to be -0332 %assigned a small negative score instead. -0333 if useScoresForTasks==true -0334 refRxnScores=scoreModel(refModelNoExc,hpaData,arrayData,tissue,celltype); -0335 [outModel, addedRxnMat]=fitTasks(initModel,refModelNoExc,[],true,min(refRxnScores,-0.1),taskStructure,paramsFT); -0336 else -0337 [outModel, addedRxnMat]=fitTasks(initModel,refModelNoExc,[],true,[],taskStructure,paramsFT); -0338 end -0339 if printReport==true -0340 printScores(outModel,'Functional model statistics',hpaData,arrayData,tissue,celltype); -0341 printScores(removeReactions(outModel,intersect(outModel.rxns,initModel.rxns),true,true),'Reactions added to perform the tasks',hpaData,arrayData,tissue,celltype); +0112 else +0113 celltype=char(celltype); +0114 end +0115 if nargin<4 +0116 hpaData=[]; +0117 end +0118 if nargin<5 +0119 arrayData=[]; +0120 end +0121 if nargin<6 +0122 metabolomicsData=[]; +0123 end +0124 if nargin<7 +0125 taskFile=[]; +0126 else +0127 taskFile=char(taskFile); +0128 end +0129 if nargin<8 || isempty(useScoresForTasks) +0130 useScoresForTasks=true; +0131 end +0132 if nargin<9 || isempty(printReport) +0133 printReport=true; +0134 end +0135 if nargin<10 +0136 taskStructure=[]; +0137 end +0138 if nargin<11 +0139 params=[]; +0140 end +0141 if nargin<12 +0142 paramsFT=[]; +0143 end +0144 +0145 %Check that the model is in the closed form +0146 if ~isfield(refModel,'unconstrained') +0147 EM='Exchange metabolites should normally not be removed from the model when using getINITModel. Use importModel(file,false) to import a model with exchange metabolites remaining (see the documentation for details)'; +0148 dispEM(EM); +0149 end +0150 +0151 %Create the task structure if not supplied +0152 if any(taskFile) && isempty(taskStructure) +0153 taskStructure=parseTaskList(taskFile); +0154 end +0155 +0156 +0157 % sc-tINIT to identify confidence levels of gene expression +0158 if ~isempty(arrayData) && isfield(arrayData,'singleCells') +0159 if arrayData.singleCells == 1 +0160 % Check to ensure cell type is defined +0161 if ~isfield(arrayData,'celltypes') +0162 dispEM('arrayData must contain cell type information if sc-tINIT is to be used','false'); +0163 end +0164 if ~ismember(upper(celltype),upper(arrayData.celltypes)) +0165 dispEM('The cell type name does not match'); +0166 end +0167 +0168 % Analyze only cell type of interest +0169 J= strcmpi(arrayData.celltypes,celltype); +0170 +0171 % Analyze only genes included in the reference model +0172 I=ismember(arrayData.genes,refModel.genes); +0173 +0174 % Convert expression data to population fractions +0175 binary_levels = arrayData.levels(I,J)~=0; % Classify each gene as detected (1) or not (0) in each cell +0176 cell_count_levels = sum(binary_levels,2); % Number of cells expressing each transcript +0177 cell_frac_levels = cell_count_levels/size(binary_levels,2); % Number of cells expressing each transcript +0178 +0179 % Bin cell_frac_counts manually +0180 x = 0:.01:1; +0181 for(i = 1:length(x)) +0182 cell_frac_count(i) = sum(round(cell_frac_levels,2)==x(i)); +0183 end +0184 +0185 % Fit four beta distributions +0186 cell_frac_count(cell_frac_count==0) = NaN; % Remove zeros from optimization +0187 cell_frac_count(1) = NaN; % Remove non-expressed genes from optimization +0188 x_lim = 1; % Somewhat arbitrary parameter to fit left tail of distr. +0189 myfun = @(par) nansum((cell_frac_count(1:find(x>=x_lim,1)) - ... +0190 abs(par(1))*betapdf(x(1:find(x>=x_lim,1)),abs(par(2)),abs(par(3))) - ... +0191 abs(par(4))*betapdf(x(1:find(x>=x_lim,1)),abs(par(5)),abs(par(6))) - ... +0192 abs(par(7))*betapdf(x(1:find(x>=x_lim,1)),abs(par(8)),abs(par(9))) - ... +0193 abs(par(10))*betapdf(x(1:find(x>=x_lim,1)),abs(par(11)),abs(par(12)))).^2); +0194 +0195 par0 = [4,2,100,7,2,30,7,5,20,5,15,20]; +0196 opts = optimset('Display','off'); +0197 [par,f_val] = fminsearch(myfun,par0,opts); +0198 par = abs(par); +0199 +0200 % Plot results +0201 if (isfield(arrayData,'plotResults')) +0202 if arrayData.plotResults == true +0203 figure(); hold on; plot(x,cell_frac_count,'ko','MarkerSize',5); +0204 plot(x,abs(par(1))*betapdf(x,abs(par(2)),abs(par(3))),'b-','LineWidth',1) +0205 plot(x,abs(par(4))*betapdf(x,abs(par(5)),abs(par(6))),'b-','LineWidth',1) +0206 plot(x,abs(par(7))*betapdf(x,abs(par(8)),abs(par(9))),'b-','LineWidth',1) +0207 plot(x,abs(par(10))*betapdf(x,abs(par(11)),abs(par(12))),'b-','LineWidth',1) +0208 plot(x,abs(par(1))*betapdf(x,abs(par(2)),abs(par(3))) + ... +0209 abs(par(4))*betapdf(x,abs(par(5)),abs(par(6))) + ... +0210 abs(par(7))*betapdf(x,abs(par(8)),abs(par(9))) + ... +0211 abs(par(10))*betapdf(x,abs(par(11)),abs(par(12))),'-','Color',[.5 .5 .5],'LineWidth',2) +0212 xlabel('Expression Probability');ylabel('# of genes');set(gca,'FontSize',14,'LineWidth',1.25); +0213 title('Expression prediction','FontSize',18,'FontWeight','bold') +0214 end +0215 end +0216 +0217 % Score genes based on population expression (p = .05) +0218 exprs_cutoff_1 = find(cdf('beta',x,par(2),par(3)) >.95,1)-1; % Find index of no confidence genes +0219 exprs_cutoff_2 = find(cdf('beta',x,par(5),par(6)) >.95,1)-1; % Find index of low confidence genes +0220 exprs_cutoff_3 = find(cdf('beta',x,par(8),par(9)) >.95,1)-1; % Find index of low confidence genes +0221 exprs_cutoffs = sort([exprs_cutoff_1,exprs_cutoff_2,exprs_cutoff_3]); +0222 gene_scores = cell_frac_levels*0; +0223 gene_scores(cell_frac_levels <= x(exprs_cutoffs(1))) = 4; % Not detected +0224 gene_scores(logical((cell_frac_levels >= x(exprs_cutoffs(1))).*(cell_frac_levels < x(exprs_cutoffs(2))))) = 3; % Low detection +0225 gene_scores(logical((cell_frac_levels >= x(exprs_cutoffs(2))).*(cell_frac_levels < x(exprs_cutoffs(3))))) = 2; % Medium detection +0226 gene_scores(cell_frac_levels > x(exprs_cutoffs(3))) = 1; % High detection +0227 +0228 % Replace hpaData with singleCellData +0229 if printReport==true +0230 dispEM('Single cell data is not currently compatible with HPA data. \n Replacing hpaData with single cell-based scoring.',false); +0231 end +0232 hpaData.genes = arrayData.genes; +0233 hpaData.tissues = arrayData.tissues; +0234 hpaData.celltypes = arrayData.celltypes; +0235 hpaData.levels = [{'High'},{'Medium'},{'Low'},{'None'}]; +0236 hpaData.gene2Level = zeros(length(arrayData.genes),length(arrayData.celltypes)); +0237 for i = 1:length(find(J)) +0238 find_var = find(J,i); +0239 hpaData.gene2Level(I,find_var(end)) = gene_scores; +0240 end +0241 +0242 % Remove arrayData from the analysis (Might be a bad idea) +0243 clear arrayData +0244 arrayData=[]; +0245 end +0246 end +0247 +0248 +0249 if printReport==true +0250 if any(celltype) +0251 fprintf(['***Generating model for: ' tissue ' - ' celltype '\n']); +0252 else +0253 fprintf(['***Generating model for: ' tissue '\n']); +0254 end +0255 if ~isempty(hpaData) +0256 fprintf('-Using HPA data\n'); +0257 end +0258 if ~isempty(arrayData) +0259 fprintf('-Using array data\n'); +0260 end +0261 if ~isempty(metabolomicsData) +0262 fprintf('-Using metabolomics data\n'); +0263 end +0264 if ~isempty(taskFile) || ~isempty(taskStructure) +0265 fprintf('-Using metabolic tasks\n'); +0266 end +0267 fprintf('\n'); +0268 +0269 printScores(refModel,'Reference model statistics',hpaData,arrayData,tissue,celltype); +0270 end +0271 +0272 %Remove dead-end reactions to speed up the optimization and to +0273 %differentiate between reactions removed by INIT and those that are +0274 %dead-end +0275 [~, deletedDeadEndRxns]=simplifyModel(refModel,true,false,true,true,true); +0276 cModel=removeReactions(refModel,deletedDeadEndRxns,false,true); +0277 +0278 %Store the connected model like this to keep track of stuff +0279 if printReport==true +0280 printScores(cModel,'Pruned model statistics',hpaData,arrayData,tissue,celltype); +0281 end +0282 +0283 %If tasks have been defined, then go through them and get essential +0284 %reactions +0285 if ~isempty(taskStructure) +0286 [taskReport, essentialRxnMat]=checkTasks(cModel,[],printReport,true,true,taskStructure); +0287 +0288 essentialRxnsForTasks=cModel.rxns(any(essentialRxnMat,2)); +0289 +0290 %Remove tasks that cannot be performed +0291 taskStructure(taskReport.ok==false)=[]; +0292 if printReport==true +0293 printScores(removeReactions(cModel,setdiff(cModel.rxns,essentialRxnsForTasks),true,true),'Reactions essential for tasks',hpaData,arrayData,tissue,celltype); +0294 end +0295 else +0296 essentialRxnsForTasks={}; +0297 end +0298 +0299 %Score the connected model +0300 [rxnScores, geneScores]=scoreModel(cModel,hpaData,arrayData,tissue,celltype); +0301 +0302 %Run the INIT algorithm. The exchange reactions that are used in the final +0303 %reactions will be open, which doesn't fit with the last step. Therefore +0304 %delete reactions from the original model instead of taking the output. The +0305 %default implementation does not constrain reversible reactions to only +0306 %carry flux in one direction. Runs without the constraints on reversibility +0307 %and with all output allowed. This is to reduce the complexity of the +0308 %problem. +0309 [~, deletedRxnsInINIT, metProduction]=runINIT(simplifyModel(cModel),rxnScores,metabolomicsData,essentialRxnsForTasks,0,true,false,params); +0310 initModel=removeReactions(cModel,deletedRxnsInINIT,true,true); +0311 if printReport==true +0312 printScores(initModel,'INIT model statistics',hpaData,arrayData,tissue,celltype); +0313 printScores(removeReactions(cModel,setdiff(cModel.rxns,deletedRxnsInINIT),true,true),'Reactions deleted by INIT',hpaData,arrayData,tissue,celltype); +0314 end +0315 +0316 %The full model has exchange reactions in it. fitTasks calls on fillGaps, +0317 %which automatically removes exchange metabolites (because it assumes that +0318 %the reactions are constrained when appropriate). In this case the +0319 %uptakes/outputs are retrieved from the task sheet instead. To prevent +0320 %exchange reactions being used to fill gaps, they are delete from the +0321 %reference model here. +0322 initModel.id='INITModel'; +0323 +0324 %If gaps in the model should be filled using a task list +0325 if ~isempty(taskStructure) +0326 %Remove exchange reactions and reactions already included in the INIT +0327 %model +0328 refModelNoExc=removeReactions(refModel,union(initModel.rxns,getExchangeRxns(refModel)),true,true); +0329 +0330 %At this stage the model is fully connected and most of the genes with +0331 %good scores should have been included. The final gap-filling should +0332 %take the scores of the genes into account, so that "rather bad" +0333 %reactions are preferred to "very bad" reactions. However, reactions +0334 %with positive scores will be included even if they are not connected +0335 %in the current formulation. Therefore, such reactions will have to be +0336 %assigned a small negative score instead. +0337 if useScoresForTasks==true +0338 refRxnScores=scoreModel(refModelNoExc,hpaData,arrayData,tissue,celltype); +0339 [outModel, addedRxnMat]=fitTasks(initModel,refModelNoExc,[],true,min(refRxnScores,-0.1),taskStructure,paramsFT); +0340 else +0341 [outModel, addedRxnMat]=fitTasks(initModel,refModelNoExc,[],true,[],taskStructure,paramsFT); 0342 end -0343 -0344 addedRxnsForTasks=refModelNoExc.rxns(any(addedRxnMat,2)); -0345 else -0346 outModel=initModel; -0347 addedRxnMat=[]; -0348 addedRxnsForTasks={}; -0349 end -0350 -0351 %The model can now perform all the tasks defined in the task list. The -0352 %algorithm cannot deal with gene-complexes at the moment. It is therefore -0353 %ok to remove bad genes from a reaction (as long as at least one gene is -0354 %kept) -0355 model=outModel; -0356 -0357 [~, I]=ismember(model.genes,cModel.genes); %All should be found -0358 %This is a little weird way to make sure that only one bad gene is included -0359 %if there are no good ones (since all -Inf==max(-Inf)) -0360 geneScores(isinf(geneScores))=-1000+rand(sum(isinf(geneScores)),1); -0361 -0362 model.grRules(:)={''}; -0363 for i=1:numel(model.rxns) -0364 ids=find(model.rxnGeneMat(i,:)); -0365 if numel(ids)>1 -0366 scores=geneScores(I(ids)); -0367 %Only keep the positive ones if possible -0368 model.rxnGeneMat(i,ids(~(scores>0 | scores==max(scores))))=0; -0369 end -0370 %Rewrite the grRules to be only OR -0371 if isfield(model,'grRules') -0372 J=find(model.rxnGeneMat(i,:)); -0373 for j=1:numel(J) -0374 model.grRules{i}=[model.grRules{i} '(' model.genes{J(j)} ')']; -0375 if j<numel(J) -0376 model.grRules{i}=[model.grRules{i} ' or ']; -0377 end -0378 end -0379 end -0380 end -0381 -0382 %Find all genes that are not used and delete them -0383 I=sum(model.rxnGeneMat)==0; -0384 model.genes(I)=[]; -0385 model.rxnGeneMat(:,I)=[]; -0386 if isfield(model,'geneShortNames') -0387 model.geneShortNames(I)=[]; -0388 end -0389 if isfield(model,'geneMiriams') -0390 model.geneMiriams(I)=[]; -0391 end -0392 if isfield(model,'geneFrom') -0393 model.geneFrom(I)=[]; -0394 end -0395 if isfield(model,'geneComps') -0396 model.geneComps(I)=[]; -0397 end -0398 -0399 %At this stage the model will contain some exchange reactions but probably -0400 %not all (and maybe zero). This can be inconvenient, so all exchange -0401 %reactions from the reference model are added, except for those which -0402 %involve metabolites that are not in the model. -0403 -0404 %First delete and included exchange reactions in order to prevent the order -0405 %from changing -0406 model=removeReactions(model,getExchangeRxns(model)); +0343 if printReport==true +0344 printScores(outModel,'Functional model statistics',hpaData,arrayData,tissue,celltype); +0345 printScores(removeReactions(outModel,intersect(outModel.rxns,initModel.rxns),true,true),'Reactions added to perform the tasks',hpaData,arrayData,tissue,celltype); +0346 end +0347 +0348 addedRxnsForTasks=refModelNoExc.rxns(any(addedRxnMat,2)); +0349 else +0350 outModel=initModel; +0351 addedRxnMat=[]; +0352 addedRxnsForTasks={}; +0353 end +0354 +0355 %The model can now perform all the tasks defined in the task list. The +0356 %algorithm cannot deal with gene-complexes at the moment. It is therefore +0357 %ok to remove bad genes from a reaction (as long as at least one gene is +0358 %kept) +0359 model=outModel; +0360 +0361 [~, I]=ismember(model.genes,cModel.genes); %All should be found +0362 %This is a little weird way to make sure that only one bad gene is included +0363 %if there are no good ones (since all -Inf==max(-Inf)) +0364 geneScores(isinf(geneScores))=-1000+rand(sum(isinf(geneScores)),1); +0365 +0366 model.grRules(:)={''}; +0367 for i=1:numel(model.rxns) +0368 ids=find(model.rxnGeneMat(i,:)); +0369 if numel(ids)>1 +0370 scores=geneScores(I(ids)); +0371 %Only keep the positive ones if possible +0372 model.rxnGeneMat(i,ids(~(scores>0 | scores==max(scores))))=0; +0373 end +0374 %Rewrite the grRules to be only OR +0375 if isfield(model,'grRules') +0376 J=find(model.rxnGeneMat(i,:)); +0377 for j=1:numel(J) +0378 model.grRules{i}=[model.grRules{i} '(' model.genes{J(j)} ')']; +0379 if j<numel(J) +0380 model.grRules{i}=[model.grRules{i} ' or ']; +0381 end +0382 end +0383 end +0384 end +0385 +0386 %Find all genes that are not used and delete them +0387 I=sum(model.rxnGeneMat)==0; +0388 model.genes(I)=[]; +0389 model.rxnGeneMat(:,I)=[]; +0390 if isfield(model,'geneShortNames') +0391 model.geneShortNames(I)=[]; +0392 end +0393 if isfield(model,'geneMiriams') +0394 model.geneMiriams(I)=[]; +0395 end +0396 if isfield(model,'geneFrom') +0397 model.geneFrom(I)=[]; +0398 end +0399 if isfield(model,'geneComps') +0400 model.geneComps(I)=[]; +0401 end +0402 +0403 %At this stage the model will contain some exchange reactions but probably +0404 %not all (and maybe zero). This can be inconvenient, so all exchange +0405 %reactions from the reference model are added, except for those which +0406 %involve metabolites that are not in the model. 0407 -0408 %Create a model with only the exchange reactions in refModel -0409 excModel=removeReactions(refModel,setdiff(refModel.rxns,getExchangeRxns(refModel)),true,true); -0410 -0411 %Find the metabolites there which are not exchange metabolites and which do -0412 %not exist in the output model -0413 I=~ismember(excModel.mets,model.mets) & excModel.unconstrained==0; +0408 %First delete and included exchange reactions in order to prevent the order +0409 %from changing +0410 model=removeReactions(model,getExchangeRxns(model)); +0411 +0412 %Create a model with only the exchange reactions in refModel +0413 excModel=removeReactions(refModel,setdiff(refModel.rxns,getExchangeRxns(refModel)),true,true); 0414 -0415 %Then find those reactions and delete them -0416 [~, J]=find(excModel.S(I,:)); -0417 excModel=removeReactions(excModel,J,true,true); +0415 %Find the metabolites there which are not exchange metabolites and which do +0416 %not exist in the output model +0417 I=~ismember(excModel.mets,model.mets) & excModel.unconstrained==0; 0418 -0419 %Merge with the output model -0420 model=mergeModels({model;excModel},'metNames'); -0421 model.id='INITModel'; -0422 model.name=['Automatically generated model for ' tissue]; -0423 if any(celltype) -0424 model.name=[model.name ' - ' celltype]; -0425 end -0426 -0427 if printReport==true -0428 printScores(model,'Final model statistics',hpaData,arrayData,tissue,celltype); +0419 %Then find those reactions and delete them +0420 [~, J]=find(excModel.S(I,:)); +0421 excModel=removeReactions(excModel,J,true,true); +0422 +0423 %Merge with the output model +0424 model=mergeModels({model;excModel},'metNames'); +0425 model.id='INITModel'; +0426 model.name=['Automatically generated model for ' tissue]; +0427 if any(celltype) +0428 model.name=[model.name ' - ' celltype]; 0429 end 0430 -0431 %Add information about essential reactions and reactions included for -0432 %gap-filling and return a taskReport -0433 if ~isempty(taskStructure) -0434 I=find(taskReport.ok); %Ignore failed tasks -0435 for i=1:numel(I) -0436 taskReport.essential{I(i),1}=cModel.rxns(essentialRxnMat(:,I(i))); -0437 taskReport.gapfill{I(i),1}=refModelNoExc.rxns(addedRxnMat(:,i)); -0438 end -0439 else -0440 taskReport=[]; -0441 end -0442 -0443 %Fix grRules and reconstruct rxnGeneMat -0444 [grRules,rxnGeneMat] = standardizeGrRules(model,true); -0445 model.grRules = grRules; -0446 model.rxnGeneMat = rxnGeneMat; -0447 end -0448 -0449 %This is for printing a summary of a model -0450 function [rxnS, geneS]=printScores(model,name,hpaData,arrayData,tissue,celltype) -0451 [a, b]=scoreModel(model,hpaData,arrayData,tissue,celltype); -0452 rxnS=mean(a); -0453 geneS=mean(b(~isinf(b))); -0454 fprintf([name ':\n']); -0455 fprintf(['\t' num2str(numel(model.rxns)) ' reactions, ' num2str(numel(model.genes)) ' genes\n']); -0456 fprintf(['\tMean reaction score: ' num2str(rxnS) '\n']); -0457 fprintf(['\tMean gene score: ' num2str(geneS) '\n']); -0458 fprintf(['\tReactions with positive scores: ' num2str(100*sum(a>0)/numel(a)) '%%\n\n']); -0459 end +0431 if printReport==true +0432 printScores(model,'Final model statistics',hpaData,arrayData,tissue,celltype); +0433 end +0434 +0435 %Add information about essential reactions and reactions included for +0436 %gap-filling and return a taskReport +0437 if ~isempty(taskStructure) +0438 I=find(taskReport.ok); %Ignore failed tasks +0439 for i=1:numel(I) +0440 taskReport.essential{I(i),1}=cModel.rxns(essentialRxnMat(:,I(i))); +0441 taskReport.gapfill{I(i),1}=refModelNoExc.rxns(addedRxnMat(:,i)); +0442 end +0443 else +0444 taskReport=[]; +0445 end +0446 +0447 %Fix grRules and reconstruct rxnGeneMat +0448 [grRules,rxnGeneMat] = standardizeGrRules(model,true); +0449 model.grRules = grRules; +0450 model.rxnGeneMat = rxnGeneMat; +0451 end +0452 +0453 %This is for printing a summary of a model +0454 function [rxnS, geneS]=printScores(model,name,hpaData,arrayData,tissue,celltype) +0455 [a, b]=scoreModel(model,hpaData,arrayData,tissue,celltype); +0456 rxnS=mean(a); +0457 geneS=mean(b(~isinf(b))); +0458 fprintf([name ':\n']); +0459 fprintf(['\t' num2str(numel(model.rxns)) ' reactions, ' num2str(numel(model.genes)) ' genes\n']); +0460 fprintf(['\tMean reaction score: ' num2str(rxnS) '\n']); +0461 fprintf(['\tMean gene score: ' num2str(geneS) '\n']); +0462 fprintf(['\tReactions with positive scores: ' num2str(100*sum(a>0)/numel(a)) '%%\n\n']); +0463 end
Generated by m2html © 2005
\ No newline at end of file diff --git a/doc/INIT/runINIT.html b/doc/INIT/runINIT.html index a37eb130..e4847050 100644 --- a/doc/INIT/runINIT.html +++ b/doc/INIT/runINIT.html @@ -171,282 +171,275 @@

SOURCE CODE ^if isempty(rxnScores) 0068 rxnScores=zeros(numel(model.rxns),1); 0069 end -0070 if nargin<3 +0070 if nargin<3 || isempty(presentMets) 0071 presentMets={}; -0072 end -0073 if isempty(presentMets) -0074 presentMets={}; -0075 end -0076 presentMets=presentMets(:); -0077 if nargin<4 -0078 essentialRxns={}; +0072 else +0073 presentMets=convertCharArray(presentMets); +0074 end +0075 if nargin<4 || isempty(essentialRxns) +0076 essentialRxns={}; +0077 else +0078 essentialRxns=convertCharArray(essentialRxns); 0079 end -0080 if isempty(essentialRxns) -0081 essentialRxns={}; +0080 if nargin<5 || isempty(prodWeight) +0081 prodWeight=0.5; 0082 end -0083 essentialRxns=essentialRxns(:); -0084 if nargin<5 -0085 prodWeight=0.5; -0086 end -0087 if isempty(prodWeight) -0088 prodWeight=0.5; -0089 end -0090 if nargin<6 -0091 allowExcretion=false; -0092 end -0093 if nargin<7 -0094 noRevLoops=false; -0095 end -0096 if nargin<8 -0097 params=[]; -0098 end -0099 -0100 if numel(presentMets)~=numel(unique(presentMets)) -0101 EM='Duplicate metabolite names in presentMets'; -0102 dispEM(EM); -0103 end -0104 -0105 %Default is that the metabolites cannot be produced -0106 if ~isempty(presentMets) -0107 metProduction=ones(numel(presentMets),1)*-2; -0108 presentMets=upper(presentMets); -0109 pmIndexes=find(ismember(presentMets,upper(model.metNames))); -0110 metProduction(pmIndexes)=-1; %Then set that they are at least found -0111 else -0112 metProduction=[]; -0113 pmIndexes=[]; +0083 if nargin<6 +0084 allowExcretion=false; +0085 end +0086 if nargin<7 +0087 noRevLoops=false; +0088 end +0089 if nargin<8 +0090 params=[]; +0091 end +0092 +0093 if numel(presentMets)~=numel(unique(presentMets)) +0094 EM='Duplicate metabolite names in presentMets'; +0095 dispEM(EM); +0096 end +0097 +0098 %Default is that the metabolites cannot be produced +0099 if ~isempty(presentMets) +0100 metProduction=ones(numel(presentMets),1)*-2; +0101 presentMets=upper(presentMets); +0102 pmIndexes=find(ismember(presentMets,upper(model.metNames))); +0103 metProduction(pmIndexes)=-1; %Then set that they are at least found +0104 else +0105 metProduction=[]; +0106 pmIndexes=[]; +0107 end +0108 +0109 %The model should be in the reversible format and all relevant exchange +0110 %reactions should be open +0111 if isfield(model,'unconstrained') +0112 EM='Exchange metabolites are still present in the model. Use simplifyModel if this is not intended'; +0113 dispEM(EM,false); 0114 end 0115 -0116 %The model should be in the reversible format and all relevant exchange -0117 %reactions should be open -0118 if isfield(model,'unconstrained') -0119 EM='Exchange metabolites are still present in the model. Use simplifyModel if this is not intended'; -0120 dispEM(EM,false); -0121 end -0122 -0123 %The irreversible reactions that are essential must have a flux and are -0124 %therefore not optimized for using MILP, which reduces the problem size. -0125 %However, reversible reactions must have a flux in one direction, so they -0126 %have to stay in the problem. The essentiality constraint on reversible -0127 %reactions is implemented in the same manner as for reversible reactions -0128 %when noRevLoops==true, but with the additional constraint that C ub=-1. -0129 %This forces one of the directions to be active. -0130 revRxns=find(model.rev~=0); -0131 essentialReversible=find(ismember(model.rxns(revRxns),essentialRxns)); -0132 essentialRxns=intersect(essentialRxns,model.rxns(model.rev==0)); -0133 -0134 %Convert the model to irreversible -0135 irrevModel=convertToIrrev(model); -0136 rxnScores=[rxnScores;rxnScores(model.rev==1)]; -0137 %These are used if noRevLoops is true -0138 if noRevLoops==true -0139 forwardIndexes=find(model.rev~=0); -0140 backwardIndexes=(numel(model.rxns)+1:numel(irrevModel.rxns))'; -0141 else -0142 %Then they should only be used for essential reversible reactions -0143 forwardIndexes=revRxns(essentialReversible); -0144 backwardIndexes=essentialReversible+numel(model.rxns); -0145 end -0146 -0147 %Get the indexes of the essential reactions and remove them from the -0148 %scoring vector -0149 essentialIndex=find(ismember(irrevModel.rxns,essentialRxns)); -0150 rxnScores(essentialIndex)=[]; -0151 -0152 %Go through each of the presentMets (if they exist) and modify the S matrix -0153 %so that each reaction which produces any of them also produces a -0154 %corresponding fake metabolite and the opposite in the reverse direction. -0155 -0156 %This is to deal with the fact that there is no compartment info regarding -0157 %the presentMets. This modifies the irrevModel structure, but that is fine -0158 %since it's the model structure that is returned. -0159 if any(pmIndexes) -0160 irrevModel.metNames=upper(irrevModel.metNames); -0161 metsToAdd.mets=strcat({'FAKEFORPM'},num2str(pmIndexes)); -0162 metsToAdd.metNames=metsToAdd.mets; -0163 metsToAdd.compartments=irrevModel.comps{1}; -0164 -0165 %There is no constraints on the metabolites yet, since maybe not all of -0166 %them could be produced -0167 irrevModel=addMets(irrevModel,metsToAdd); -0168 end -0169 -0170 %Modify the matrix -0171 for i=1:numel(pmIndexes) -0172 %Get the matching mets -0173 I=ismember(irrevModel.metNames,presentMets(pmIndexes(i))); -0174 -0175 %Find the reactions where any of them are used. -0176 [~, K, L]=find(irrevModel.S(I,:)); -0177 -0178 %This ugly loop is to avoid problems if a metabolite occurs several -0179 %times in one reaction -0180 KK=unique(K); -0181 LL=zeros(numel(KK),1); -0182 for j=1:numel(KK) -0183 LL(j)=sum(L(K==KK(j))); -0184 end -0185 irrevModel.S(numel(irrevModel.mets)-numel(pmIndexes)+i,KK)=LL; -0186 end -0187 -0188 %Some nice to have numbers -0189 nMets=numel(irrevModel.mets); -0190 nRxns=numel(irrevModel.rxns); -0191 nEssential=numel(essentialIndex); -0192 nNonEssential=nRxns-nEssential; -0193 nonEssentialIndex=setdiff(1:nRxns,essentialIndex); -0194 S=irrevModel.S; -0195 -0196 %Add so that each non-essential reaction produces one unit of a fake -0197 %metabolite -0198 temp=sparse(1:nRxns,1:nRxns,1); -0199 temp(essentialIndex,:)=[]; -0200 S=[S;temp]; -0201 -0202 %Add another set of reactions (will be binary) which also produce these -0203 %fake metabolites, but with a stoichiometry of 1000 -0204 temp=sparse(1:nNonEssential,1:nNonEssential,1000); -0205 temp=[sparse(nMets,nNonEssential);temp]; -0206 S=[S temp]; -0207 -0208 %Add reactions for net-production of (real) metabolites -0209 if prodWeight~=0 -0210 temp=[speye(nMets-numel(pmIndexes))*-1;sparse(nNonEssential+numel(pmIndexes),nMets-numel(pmIndexes))]; -0211 S=[S temp]; -0212 %To keep the number of reactions added like this -0213 nNetProd=nMets-numel(pmIndexes); -0214 else -0215 nNetProd=0; -0216 end -0217 -0218 %Add constraints so that reversible reactions can only be used in one -0219 %direction. This is done by adding the fake metabolites A, B, C for each -0220 %reversible reaction in the following manner -0221 % forward: A + .. => ... backwards: B + ... => ... int1: C => 1000 A int2: -0222 % C => 1000 B A ub=999.9 B ub=999.9 C lb=-1 int1 and int2 are binary -0223 if any(forwardIndexes) -0224 nRevBounds=numel(forwardIndexes); -0225 -0226 %Add the A metabolites for the forward reactions and the B metabolites -0227 %for the reverse reactions -0228 I=speye(numel(irrevModel.rxns))*-1; -0229 temp=[I(forwardIndexes,:);I(backwardIndexes,:)]; -0230 -0231 %Padding -0232 temp=[temp sparse(size(temp,1),size(S,2)-numel(irrevModel.rxns))]; -0233 -0234 %Add the int1 & int2 reactions that produce A and B -0235 temp=[temp speye(nRevBounds*2)*1000]; -0236 -0237 %And add that they also consume C -0238 temp=[temp;[sparse(nRevBounds,size(S,2)) speye(nRevBounds)*-1 speye(nRevBounds)*-1]]; -0239 -0240 %Add the new reactions and metabolites -0241 S=[S sparse(size(S,1),nRevBounds*2)]; -0242 S=[S;temp]; -0243 else -0244 nRevBounds=0; -0245 end -0246 -0247 %Add so that the essential reactions must have a small flux and that the -0248 %binary ones (and net-production reactions) may have zero flux. The integer -0249 %reactions for reversible reactions have [0 1] -0250 prob.blx=[irrevModel.lb;zeros(nNonEssential+nNetProd+nRevBounds*2,1)]; -0251 prob.blx(essentialIndex)=max(0.1,prob.blx(essentialIndex)); -0252 -0253 %Add so that the binary ones and net-production reactions can have at the -0254 %most flux 1.0 -0255 prob.bux=[irrevModel.ub;ones(nNonEssential+nNetProd+nRevBounds*2,1)]; -0256 -0257 %Add that the fake metabolites must be produced in a small amount and that -0258 %the A and B metabolites for reversible reactions can be [0 999.9] and C -0259 %metabolites [-1 0] -0260 prob.blc=[irrevModel.b(:,1);ones(nNonEssential,1);zeros(nRevBounds*2,1);ones(nRevBounds,1)*-1]; -0261 -0262 %Add that normal metabolites can be freely excreted if -0263 %allowExcretion==true, and that the fake ones can be excreted 1000 units at -0264 %most. C metabolites for essential reversible reactions should have an -0265 %upper bound of -1. If noRevLoops is false, then add this constraint for -0266 %all the reactions instead. -0267 if noRevLoops==true -0268 revUB=zeros(nRevBounds,1); -0269 revUB(essentialReversible)=-1; -0270 else -0271 revUB=ones(nRevBounds,1)*-1; -0272 end -0273 if allowExcretion==true -0274 metUB=inf(nMets,1); -0275 else -0276 metUB=irrevModel.b(:,min(size(irrevModel.b,2),2)); -0277 end -0278 prob.buc=[metUB;ones(nNonEssential,1)*1000;ones(nRevBounds*2,1)*999.9;revUB]; -0279 -0280 %Add objective coefficients for the binary reactions. The negative is used -0281 %since we're minimizing. The negative is taken for the prodWeight as well, -0282 %in order to be consistent with the syntax that positive scores are good -0283 prob.c=[zeros(nRxns,1);rxnScores;ones(nNetProd,1)*prodWeight*-1;zeros(nRevBounds*2,1)]; -0284 prob.a=S; -0285 -0286 % adapt problem structure for cobra-style solver -0287 prob.c=[prob.c;zeros(size(prob.a,1),1)]; -0288 prob.A=[prob.a -speye(size(prob.a,1))]; -0289 prob.b=zeros(size(prob.a,1), 1); -0290 prob.ub=[prob.bux; prob.buc]; -0291 prob.osense=1; -0292 prob.csense=char(zeros(size(prob.a,1),1)); -0293 prob.csense(:)='E'; -0294 -0295 %We still don't know which of the presentMets that can be produced. Go -0296 %through them, force production, and see if the problem can be solved -0297 for i=1:numel(pmIndexes) -0298 prob.blc(numel(irrevModel.mets)-numel(pmIndexes)+i)=1; -0299 prob.lb=[prob.blx; prob.blc]; -0300 res=optimizeProb(prob,params); -0301 isFeasible=checkSolution(res); -0302 if ~isFeasible -0303 %Reset the constraint again -0304 prob.blc(numel(irrevModel.mets)-numel(pmIndexes)+i)=0; -0305 else -0306 %Metabolite produced -0307 metProduction(pmIndexes(i))=1; -0308 end -0309 end -0310 prob.lb=[prob.blx; prob.blc]; -0311 -0312 %Add that the binary reactions may only take integer values. -0313 prob.vartype = repmat('C', 1, size(prob.A, 2)); -0314 allInt=[(nRxns+1):(nRxns+nNonEssential) size(S,2)-nRevBounds*2+1:size(S,2)]; -0315 prob.vartype(allInt) = 'B'; -0316 -0317 % solve problem -0318 res=optimizeProb(prob,params); -0319 -0320 %Problem should not be infeasible, but it is possible that the time limit -0321 %was reached before finding any solutions. -0322 if ~checkSolution(res) -0323 if strcmp(res.origStat, 'TIME_LIMIT') -0324 EM='Time limit reached without finding a solution. Try increasing the TimeLimit parameter.'; -0325 else -0326 EM='The problem is infeasible'; -0327 end -0328 dispEM(EM); -0329 end -0330 -0331 fValue=res.obj; -0332 -0333 %Get all reactions used in the irreversible model -0334 usedRxns=(nonEssentialIndex(res.full(nRxns+1:nRxns+nNonEssential)<0.1))'; -0335 -0336 %Map to reversible model IDs -0337 usedRxns=[usedRxns(usedRxns<=numel(model.rxns));revRxns(usedRxns(usedRxns>numel(model.rxns))-numel(model.rxns))]; -0338 -0339 %Then get the ones that are not used in either direction or is essential -0340 I=true(numel(model.rxns),1); -0341 I(usedRxns)=false; -0342 I(essentialIndex)=false; -0343 deletedRxns=model.rxns(I); -0344 outModel=removeReactions(model,I,true,true); -0345 end +0116 %The irreversible reactions that are essential must have a flux and are +0117 %therefore not optimized for using MILP, which reduces the problem size. +0118 %However, reversible reactions must have a flux in one direction, so they +0119 %have to stay in the problem. The essentiality constraint on reversible +0120 %reactions is implemented in the same manner as for reversible reactions +0121 %when noRevLoops==true, but with the additional constraint that C ub=-1. +0122 %This forces one of the directions to be active. +0123 revRxns=find(model.rev~=0); +0124 essentialReversible=find(ismember(model.rxns(revRxns),essentialRxns)); +0125 essentialRxns=intersect(essentialRxns,model.rxns(model.rev==0)); +0126 +0127 %Convert the model to irreversible +0128 irrevModel=convertToIrrev(model); +0129 rxnScores=[rxnScores;rxnScores(model.rev==1)]; +0130 %These are used if noRevLoops is true +0131 if noRevLoops==true +0132 forwardIndexes=find(model.rev~=0); +0133 backwardIndexes=(numel(model.rxns)+1:numel(irrevModel.rxns))'; +0134 else +0135 %Then they should only be used for essential reversible reactions +0136 forwardIndexes=revRxns(essentialReversible); +0137 backwardIndexes=essentialReversible+numel(model.rxns); +0138 end +0139 +0140 %Get the indexes of the essential reactions and remove them from the +0141 %scoring vector +0142 essentialIndex=find(ismember(irrevModel.rxns,essentialRxns)); +0143 rxnScores(essentialIndex)=[]; +0144 +0145 %Go through each of the presentMets (if they exist) and modify the S matrix +0146 %so that each reaction which produces any of them also produces a +0147 %corresponding fake metabolite and the opposite in the reverse direction. +0148 +0149 %This is to deal with the fact that there is no compartment info regarding +0150 %the presentMets. This modifies the irrevModel structure, but that is fine +0151 %since it's the model structure that is returned. +0152 if any(pmIndexes) +0153 irrevModel.metNames=upper(irrevModel.metNames); +0154 metsToAdd.mets=strcat({'FAKEFORPM'},num2str(pmIndexes)); +0155 metsToAdd.metNames=metsToAdd.mets; +0156 metsToAdd.compartments=irrevModel.comps{1}; +0157 +0158 %There is no constraints on the metabolites yet, since maybe not all of +0159 %them could be produced +0160 irrevModel=addMets(irrevModel,metsToAdd); +0161 end +0162 +0163 %Modify the matrix +0164 for i=1:numel(pmIndexes) +0165 %Get the matching mets +0166 I=ismember(irrevModel.metNames,presentMets(pmIndexes(i))); +0167 +0168 %Find the reactions where any of them are used. +0169 [~, K, L]=find(irrevModel.S(I,:)); +0170 +0171 %This ugly loop is to avoid problems if a metabolite occurs several +0172 %times in one reaction +0173 KK=unique(K); +0174 LL=zeros(numel(KK),1); +0175 for j=1:numel(KK) +0176 LL(j)=sum(L(K==KK(j))); +0177 end +0178 irrevModel.S(numel(irrevModel.mets)-numel(pmIndexes)+i,KK)=LL; +0179 end +0180 +0181 %Some nice to have numbers +0182 nMets=numel(irrevModel.mets); +0183 nRxns=numel(irrevModel.rxns); +0184 nEssential=numel(essentialIndex); +0185 nNonEssential=nRxns-nEssential; +0186 nonEssentialIndex=setdiff(1:nRxns,essentialIndex); +0187 S=irrevModel.S; +0188 +0189 %Add so that each non-essential reaction produces one unit of a fake +0190 %metabolite +0191 temp=sparse(1:nRxns,1:nRxns,1); +0192 temp(essentialIndex,:)=[]; +0193 S=[S;temp]; +0194 +0195 %Add another set of reactions (will be binary) which also produce these +0196 %fake metabolites, but with a stoichiometry of 1000 +0197 temp=sparse(1:nNonEssential,1:nNonEssential,1000); +0198 temp=[sparse(nMets,nNonEssential);temp]; +0199 S=[S temp]; +0200 +0201 %Add reactions for net-production of (real) metabolites +0202 if prodWeight~=0 +0203 temp=[speye(nMets-numel(pmIndexes))*-1;sparse(nNonEssential+numel(pmIndexes),nMets-numel(pmIndexes))]; +0204 S=[S temp]; +0205 %To keep the number of reactions added like this +0206 nNetProd=nMets-numel(pmIndexes); +0207 else +0208 nNetProd=0; +0209 end +0210 +0211 %Add constraints so that reversible reactions can only be used in one +0212 %direction. This is done by adding the fake metabolites A, B, C for each +0213 %reversible reaction in the following manner +0214 % forward: A + .. => ... backwards: B + ... => ... int1: C => 1000 A int2: +0215 % C => 1000 B A ub=999.9 B ub=999.9 C lb=-1 int1 and int2 are binary +0216 if any(forwardIndexes) +0217 nRevBounds=numel(forwardIndexes); +0218 +0219 %Add the A metabolites for the forward reactions and the B metabolites +0220 %for the reverse reactions +0221 I=speye(numel(irrevModel.rxns))*-1; +0222 temp=[I(forwardIndexes,:);I(backwardIndexes,:)]; +0223 +0224 %Padding +0225 temp=[temp sparse(size(temp,1),size(S,2)-numel(irrevModel.rxns))]; +0226 +0227 %Add the int1 & int2 reactions that produce A and B +0228 temp=[temp speye(nRevBounds*2)*1000]; +0229 +0230 %And add that they also consume C +0231 temp=[temp;[sparse(nRevBounds,size(S,2)) speye(nRevBounds)*-1 speye(nRevBounds)*-1]]; +0232 +0233 %Add the new reactions and metabolites +0234 S=[S sparse(size(S,1),nRevBounds*2)]; +0235 S=[S;temp]; +0236 else +0237 nRevBounds=0; +0238 end +0239 +0240 %Add so that the essential reactions must have a small flux and that the +0241 %binary ones (and net-production reactions) may have zero flux. The integer +0242 %reactions for reversible reactions have [0 1] +0243 prob.blx=[irrevModel.lb;zeros(nNonEssential+nNetProd+nRevBounds*2,1)]; +0244 prob.blx(essentialIndex)=max(0.1,prob.blx(essentialIndex)); +0245 +0246 %Add so that the binary ones and net-production reactions can have at the +0247 %most flux 1.0 +0248 prob.bux=[irrevModel.ub;ones(nNonEssential+nNetProd+nRevBounds*2,1)]; +0249 +0250 %Add that the fake metabolites must be produced in a small amount and that +0251 %the A and B metabolites for reversible reactions can be [0 999.9] and C +0252 %metabolites [-1 0] +0253 prob.blc=[irrevModel.b(:,1);ones(nNonEssential,1);zeros(nRevBounds*2,1);ones(nRevBounds,1)*-1]; +0254 +0255 %Add that normal metabolites can be freely excreted if +0256 %allowExcretion==true, and that the fake ones can be excreted 1000 units at +0257 %most. C metabolites for essential reversible reactions should have an +0258 %upper bound of -1. If noRevLoops is false, then add this constraint for +0259 %all the reactions instead. +0260 if noRevLoops==true +0261 revUB=zeros(nRevBounds,1); +0262 revUB(essentialReversible)=-1; +0263 else +0264 revUB=ones(nRevBounds,1)*-1; +0265 end +0266 if allowExcretion==true +0267 metUB=inf(nMets,1); +0268 else +0269 metUB=irrevModel.b(:,min(size(irrevModel.b,2),2)); +0270 end +0271 prob.buc=[metUB;ones(nNonEssential,1)*1000;ones(nRevBounds*2,1)*999.9;revUB]; +0272 +0273 %Add objective coefficients for the binary reactions. The negative is used +0274 %since we're minimizing. The negative is taken for the prodWeight as well, +0275 %in order to be consistent with the syntax that positive scores are good +0276 prob.c=[zeros(nRxns,1);rxnScores;ones(nNetProd,1)*prodWeight*-1;zeros(nRevBounds*2,1)]; +0277 prob.a=S; +0278 +0279 % adapt problem structure for cobra-style solver +0280 prob.c=[prob.c;zeros(size(prob.a,1),1)]; +0281 prob.A=[prob.a -speye(size(prob.a,1))]; +0282 prob.b=zeros(size(prob.a,1), 1); +0283 prob.ub=[prob.bux; prob.buc]; +0284 prob.osense=1; +0285 prob.csense=char(zeros(size(prob.a,1),1)); +0286 prob.csense(:)='E'; +0287 +0288 %We still don't know which of the presentMets that can be produced. Go +0289 %through them, force production, and see if the problem can be solved +0290 for i=1:numel(pmIndexes) +0291 prob.blc(numel(irrevModel.mets)-numel(pmIndexes)+i)=1; +0292 prob.lb=[prob.blx; prob.blc]; +0293 res=optimizeProb(prob,params); +0294 isFeasible=checkSolution(res); +0295 if ~isFeasible +0296 %Reset the constraint again +0297 prob.blc(numel(irrevModel.mets)-numel(pmIndexes)+i)=0; +0298 else +0299 %Metabolite produced +0300 metProduction(pmIndexes(i))=1; +0301 end +0302 end +0303 prob.lb=[prob.blx; prob.blc]; +0304 +0305 %Add that the binary reactions may only take integer values. +0306 prob.vartype = repmat('C', 1, size(prob.A, 2)); +0307 allInt=[(nRxns+1):(nRxns+nNonEssential) size(S,2)-nRevBounds*2+1:size(S,2)]; +0308 prob.vartype(allInt) = 'B'; +0309 +0310 % solve problem +0311 res=optimizeProb(prob,params); +0312 +0313 %Problem should not be infeasible, but it is possible that the time limit +0314 %was reached before finding any solutions. +0315 if ~checkSolution(res) +0316 if strcmp(res.origStat, 'TIME_LIMIT') +0317 EM='Time limit reached without finding a solution. Try increasing the TimeLimit parameter.'; +0318 else +0319 EM='The problem is infeasible'; +0320 end +0321 dispEM(EM); +0322 end +0323 +0324 fValue=res.obj; +0325 +0326 %Get all reactions used in the irreversible model +0327 usedRxns=(nonEssentialIndex(res.full(nRxns+1:nRxns+nNonEssential)<0.1))'; +0328 +0329 %Map to reversible model IDs +0330 usedRxns=[usedRxns(usedRxns<=numel(model.rxns));revRxns(usedRxns(usedRxns>numel(model.rxns))-numel(model.rxns))]; +0331 +0332 %Then get the ones that are not used in either direction or is essential +0333 I=true(numel(model.rxns),1); +0334 I(usedRxns)=false; +0335 I(essentialIndex)=false; +0336 deletedRxns=model.rxns(I); +0337 outModel=removeReactions(model,I,true,true); +0338 end
Generated by m2html © 2005
\ No newline at end of file diff --git a/doc/core/FSEOF.html b/doc/core/FSEOF.html index b5f329f4..2984f0fc 100644 --- a/doc/core/FSEOF.html +++ b/doc/core/FSEOF.html @@ -81,115 +81,119 @@

SOURCE CODE ^% 0024 % Usage: targets=FSEOF(model,biomassRxn,targetRxn,iterations,coefficient,outputFile) 0025 -0026 if nargin<4 -0027 iterations=10; -0028 coefficient=0.9; -0029 end -0030 -0031 if nargin <5 -0032 coefficient=0.9; -0033 end -0034 -0035 if nargin == 6 -0036 output=1; -0037 else -0038 output=0; -0039 end -0040 -0041 %Find out the maximum theoretical yield of target reaction -0042 model=setParam(model,'obj',targetRxn,1); -0043 sol=solveLP(model,1); -0044 targetMax=abs(sol.f*coefficient); % 90 percent of the theoretical yield -0045 -0046 model=setParam(model,'obj',biomassRxn,1); -0047 -0048 fseof.results=zeros(length(model.rxns),iterations); -0049 fseof.target=zeros(length(model.rxns),1); -0050 rxnDirection=zeros(length(model.rxns),1); -0051 -0052 %Enforce objective flux iteratively -0053 for i=1:iterations -0054 n=i*targetMax/iterations; -0055 model=setParam(model,'lb',targetRxn,n); -0056 -0057 sol=solveLP(model,1); -0058 -0059 fseof.results(:,i)=sol.x; -0060 -0061 %Loop through all fluxes and identify the ones that increased upon the -0062 %enforced objective flux -0063 for j=1:length(fseof.results) -0064 if fseof.results(j,1) > 0 %Check the positive fluxes -0065 -0066 if i == 1 %The initial round -0067 rxnDirection(j,1)=1; -0068 fseof.target(j,1)=1; -0069 else -0070 -0071 if (fseof.results(j,i) > fseof.results(j,i-1)) & fseof.target(j,1) -0072 fseof.target(j,1)=1; -0073 else -0074 fseof.target(j,1)=0; -0075 end -0076 end -0077 -0078 elseif fseof.results(j,1) < 0 %Check the negative fluxes -0079 -0080 if i == 1 %The initial round -0081 rxnDirection(j,1)=-1; -0082 fseof.target(j,1)=1; -0083 else -0084 if (fseof.results(j,i) < fseof.results(j,i-1)) & fseof.target(j,1) -0085 fseof.target(j,1)=1; -0086 else -0087 fseof.target(j,1)=0; -0088 end -0089 end -0090 -0091 end -0092 -0093 end -0094 end -0095 -0096 %Generating output -0097 formatSpec='%s\t%s\t%s\t%s\t%s\t%s\t%s\n'; -0098 if output == 1 %Output to a file -0099 fid=fopen(outputFile,'w'); -0100 fprintf(fid,formatSpec,'Slope','rowID','Enzyme ID','Enzyme Name','Subsystems','Direction','Gr Rule'); -0101 else %Output to screen -0102 fprintf(formatSpec,'Slope','rowID','Enzyme ID','Enzyme Name','Subsystems','Direction','Gr Rule'); -0103 end -0104 -0105 for num=1:length(fseof.target) -0106 if fseof.target(num,1) == 1 -0107 A0=num2str(abs(fseof.results(num,iterations)-fseof.results(num,1))/abs(targetMax-targetMax/iterations)); %Slope calculation -0108 A1=num2str(num); %row ID -0109 A2=char(model.rxns(num)); %enzyme ID -0110 A3=char(model.rxnNames(num)); %enzyme Name -0111 if isfield(model,'subSystems') && ~isempty(model.subSystems{num}); -0112 A4=char(strjoin(model.subSystems{num,1},';')); %Subsystems -0113 else -0114 A4=''; -0115 end -0116 A5=num2str(model.rev(num)*rxnDirection(num,1)); %reaction Dirction -0117 A6=char(model.grRules(num)); %Gr Rule -0118 if output == 1 %Output to a file -0119 fprintf(fid,formatSpec,A0,A1,A2,A3,A4,A5,A6); -0120 else %Output screen -0121 fprintf(formatSpec,A0,A1,A2,A3,A4,A5,A6); -0122 end -0123 end -0124 end -0125 -0126 if output == 1 %Output to a file -0127 fclose(fid); +0026 biomassRxn=char(biomassRxn); +0027 targetRxn=char(targetRxn); +0028 +0029 if nargin<4 +0030 iterations=10; +0031 coefficient=0.9; +0032 end +0033 +0034 if nargin <5 +0035 coefficient=0.9; +0036 end +0037 +0038 if nargin == 6 +0039 output=1; +0040 else +0041 output=0; +0042 end +0043 +0044 %Find out the maximum theoretical yield of target reaction +0045 model=setParam(model,'obj',targetRxn,1); +0046 sol=solveLP(model,1); +0047 targetMax=abs(sol.f*coefficient); % 90 percent of the theoretical yield +0048 +0049 model=setParam(model,'obj',biomassRxn,1); +0050 +0051 fseof.results=zeros(length(model.rxns),iterations); +0052 fseof.target=zeros(length(model.rxns),1); +0053 rxnDirection=zeros(length(model.rxns),1); +0054 +0055 %Enforce objective flux iteratively +0056 for i=1:iterations +0057 n=i*targetMax/iterations; +0058 model=setParam(model,'lb',targetRxn,n); +0059 +0060 sol=solveLP(model,1); +0061 +0062 fseof.results(:,i)=sol.x; +0063 +0064 %Loop through all fluxes and identify the ones that increased upon the +0065 %enforced objective flux +0066 for j=1:length(fseof.results) +0067 if fseof.results(j,1) > 0 %Check the positive fluxes +0068 +0069 if i == 1 %The initial round +0070 rxnDirection(j,1)=1; +0071 fseof.target(j,1)=1; +0072 else +0073 +0074 if (fseof.results(j,i) > fseof.results(j,i-1)) & fseof.target(j,1) +0075 fseof.target(j,1)=1; +0076 else +0077 fseof.target(j,1)=0; +0078 end +0079 end +0080 +0081 elseif fseof.results(j,1) < 0 %Check the negative fluxes +0082 +0083 if i == 1 %The initial round +0084 rxnDirection(j,1)=-1; +0085 fseof.target(j,1)=1; +0086 else +0087 if (fseof.results(j,i) < fseof.results(j,i-1)) & fseof.target(j,1) +0088 fseof.target(j,1)=1; +0089 else +0090 fseof.target(j,1)=0; +0091 end +0092 end +0093 +0094 end +0095 +0096 end +0097 end +0098 +0099 %Generating output +0100 formatSpec='%s\t%s\t%s\t%s\t%s\t%s\t%s\n'; +0101 if output == 1 %Output to a file +0102 outputFile=char(outputFile); +0103 fid=fopen(outputFile,'w'); +0104 fprintf(fid,formatSpec,'Slope','rowID','Enzyme ID','Enzyme Name','Subsystems','Direction','Gr Rule'); +0105 else %Output to screen +0106 fprintf(formatSpec,'Slope','rowID','Enzyme ID','Enzyme Name','Subsystems','Direction','Gr Rule'); +0107 end +0108 +0109 for num=1:length(fseof.target) +0110 if fseof.target(num,1) == 1 +0111 A0=num2str(abs(fseof.results(num,iterations)-fseof.results(num,1))/abs(targetMax-targetMax/iterations)); %Slope calculation +0112 A1=num2str(num); %row ID +0113 A2=char(model.rxns(num)); %enzyme ID +0114 A3=char(model.rxnNames(num)); %enzyme Name +0115 if isfield(model,'subSystems') && ~isempty(model.subSystems{num}); +0116 A4=char(strjoin(model.subSystems{num,1},';')); %Subsystems +0117 else +0118 A4=''; +0119 end +0120 A5=num2str(model.rev(num)*rxnDirection(num,1)); %reaction Dirction +0121 A6=char(model.grRules(num)); %Gr Rule +0122 if output == 1 %Output to a file +0123 fprintf(fid,formatSpec,A0,A1,A2,A3,A4,A5,A6); +0124 else %Output screen +0125 fprintf(formatSpec,A0,A1,A2,A3,A4,A5,A6); +0126 end +0127 end 0128 end 0129 -0130 if nargout == 1 -0131 targets.logical=logical(fseof.target); -0132 targets.slope=abs(fseof.results(:,iterations)-fseof.results(:,1))/abs(targetMax-targetMax/iterations); %Slope calculation -0133 end -0134 end +0130 if output == 1 %Output to a file +0131 fclose(fid); +0132 end +0133 +0134 if nargout == 1 +0135 targets.logical=logical(fseof.target); +0136 targets.slope=abs(fseof.results(:,iterations)-fseof.results(:,1))/abs(targetMax-targetMax/iterations); %Slope calculation +0137 end +0138 end
Generated by m2html © 2005
\ No newline at end of file diff --git a/doc/core/addExchangeRxns.html b/doc/core/addExchangeRxns.html index e1aad455..709cbea7 100644 --- a/doc/core/addExchangeRxns.html +++ b/doc/core/addExchangeRxns.html @@ -53,7 +53,7 @@

DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

This function calls: +
  • convertCharArray convertCharArray
  • getIndexes getIndexes
  • This function is called by: @@ -87,70 +87,73 @@

    SOURCE CODE ^if nargin<3 0025 mets=model.mets; -0026 end -0027 reactionType=upper(reactionType); -0028 J=getIndexes(model,mets,'mets',false); -0029 mets=model.mets(J); -0030 -0031 %Production is positive for OUT and BOTH -0032 if strcmp(reactionType,'IN') -0033 I=speye(numel(model.mets)); -0034 else -0035 I=speye(numel(model.mets))*-1; -0036 end -0037 I=I(:,J); -0038 -0039 %Add an I matrix which corresponds to production of all metabolites -0040 model.S=[model.S I]; -0041 if strcmp(reactionType,'BOTH') -0042 model.lb=[model.lb;ones(numel(J),1)*-1000]; -0043 model.rev=[model.rev;ones(numel(J),1)]; -0044 else -0045 model.lb=[model.lb;zeros(numel(J),1)]; -0046 model.rev=[model.rev;zeros(numel(J),1)]; -0047 end -0048 model.ub=[model.ub;ones(numel(J),1)*1000]; -0049 model.c=[model.c;zeros(numel(J),1)]; -0050 -0051 filler=cell(numel(J),1); -0052 filler(:)={''}; -0053 addedRxns=strcat('EXC_',reactionType,'_',mets); -0054 addedRxnNames=strcat(model.metNames(J),' exchange (',reactionType,')'); -0055 model.rxns=[model.rxns;addedRxns]; -0056 model.rxnNames=[model.rxnNames;addedRxnNames]; -0057 -0058 if isfield(model,'eccodes') -0059 model.eccodes=[model.eccodes;filler]; -0060 end -0061 if isfield(model,'subSystems') -0062 model.subSystems=[model.subSystems;filler]; +0026 elseif ~islogical(mets) && ~isnumeric(mets) +0027 mets=convertCharArray(mets); +0028 end +0029 J=getIndexes(model,mets,'mets',false); +0030 mets=model.mets(J); +0031 +0032 reactionType=char(upper(reactionType)); +0033 +0034 %Production is positive for OUT and BOTH +0035 if strcmp(reactionType,'IN') +0036 I=speye(numel(model.mets)); +0037 else +0038 I=speye(numel(model.mets))*-1; +0039 end +0040 I=I(:,J); +0041 +0042 %Add an I matrix which corresponds to production of all metabolites +0043 model.S=[model.S I]; +0044 if strcmp(reactionType,'BOTH') +0045 model.lb=[model.lb;ones(numel(J),1)*-1000]; +0046 model.rev=[model.rev;ones(numel(J),1)]; +0047 else +0048 model.lb=[model.lb;zeros(numel(J),1)]; +0049 model.rev=[model.rev;zeros(numel(J),1)]; +0050 end +0051 model.ub=[model.ub;ones(numel(J),1)*1000]; +0052 model.c=[model.c;zeros(numel(J),1)]; +0053 +0054 filler=cell(numel(J),1); +0055 filler(:)={''}; +0056 addedRxns=strcat('EXC_',reactionType,'_',mets); +0057 addedRxnNames=strcat(model.metNames(J),' exchange (',reactionType,')'); +0058 model.rxns=[model.rxns;addedRxns]; +0059 model.rxnNames=[model.rxnNames;addedRxnNames]; +0060 +0061 if isfield(model,'eccodes') +0062 model.eccodes=[model.eccodes;filler]; 0063 end -0064 if isfield(model,'grRules') -0065 model.grRules=[model.grRules;filler]; +0064 if isfield(model,'subSystems') +0065 model.subSystems=[model.subSystems;filler]; 0066 end -0067 if isfield(model,'rxnFrom') -0068 model.rxnFrom=[model.rxnFrom;filler]; +0067 if isfield(model,'grRules') +0068 model.grRules=[model.grRules;filler]; 0069 end -0070 if isfield(model,'rxnMiriams') -0071 model.rxnMiriams=[model.rxnMiriams;filler]; +0070 if isfield(model,'rxnFrom') +0071 model.rxnFrom=[model.rxnFrom;filler]; 0072 end -0073 if isfield(model,'rxnGeneMat') -0074 model.rxnGeneMat=[model.rxnGeneMat;sparse(numel(J),numel(model.genes))]; +0073 if isfield(model,'rxnMiriams') +0074 model.rxnMiriams=[model.rxnMiriams;filler]; 0075 end -0076 if isfield(model,'rxnComps') -0077 model.rxnComps=[model.rxnComps;ones(numel(J),1)]; -0078 fprintf('NOTE: The exchange reactions are assigned to the first compartment\n'); -0079 end -0080 if isfield(model,'rxnNotes') -0081 model.rxnNotes=[model.rxnNotes;filler]; +0076 if isfield(model,'rxnGeneMat') +0077 model.rxnGeneMat=[model.rxnGeneMat;sparse(numel(J),numel(model.genes))]; +0078 end +0079 if isfield(model,'rxnComps') +0080 model.rxnComps=[model.rxnComps;ones(numel(J),1)]; +0081 fprintf('NOTE: The exchange reactions are assigned to the first compartment\n'); 0082 end -0083 if isfield(model,'rxnReferences') -0084 model.rxnReferences=[model.rxnReferences;filler]; +0083 if isfield(model,'rxnNotes') +0084 model.rxnNotes=[model.rxnNotes;filler]; 0085 end -0086 if isfield(model,'rxnConfidenceScores') -0087 model.rxnConfidenceScores=[model.rxnConfidenceScores;NaN(numel(J),1)]; +0086 if isfield(model,'rxnReferences') +0087 model.rxnReferences=[model.rxnReferences;filler]; 0088 end -0089 end +0089 if isfield(model,'rxnConfidenceScores') +0090 model.rxnConfidenceScores=[model.rxnConfidenceScores;NaN(numel(J),1)]; +0091 end +0092 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/addGenesRaven.html b/doc/core/addGenesRaven.html index 651602db..095f22d6 100644 --- a/doc/core/addGenesRaven.html +++ b/doc/core/addGenesRaven.html @@ -54,10 +54,10 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • dispEM dispEM
  • This function is called by: +
  • addRxns addRxns
  • changeGrRules changeGrRules
  • @@ -97,106 +97,100 @@

    SOURCE CODE ^if ~isfield(genesToAdd,'genes') 0033 EM='genes is a required field in genesToAdd'; 0034 dispEM(EM); -0035 end -0036 -0037 if ~iscellstr(genesToAdd.genes) -0038 EM='genesToAdd.genes must be a cell array of strings'; -0039 dispEM(EM); -0040 end -0041 -0042 %Number of genes -0043 nGenes=numel(genesToAdd.genes); -0044 nOldGenes=numel(model.genes); -0045 filler=cell(nGenes,1); -0046 filler(:)={''}; -0047 largeFiller=cell(nOldGenes,1); -0048 largeFiller(:)={''}; -0049 -0050 %Check that no gene ids are already present in the model -0051 I=ismember(genesToAdd.genes,model.genes); -0052 if all(I) -0053 warning('All genes in genesToAdd.genes are already present in model.genes'); -0054 return -0055 elseif any(I) -0056 existingGenes=strjoin(genesToAdd.genes(I), ', '); -0057 warning(['The following genes are already present in model.genes and will therefore not be added: ', existingGenes]) -0058 genesToAdd.genes(I)=[]; -0059 if isfield(genesToAdd,'geneShortNames') -0060 genesToAdd.geneShortNames(I)=[]; +0035 else +0036 genesToAdd.genes=convertCharArray(genesToAdd.genes); +0037 end +0038 +0039 %Number of genes +0040 nGenes=numel(genesToAdd.genes); +0041 nOldGenes=numel(model.genes); +0042 filler=cell(nGenes,1); +0043 filler(:)={''}; +0044 largeFiller=cell(nOldGenes,1); +0045 largeFiller(:)={''}; +0046 +0047 %Check that no gene ids are already present in the model +0048 I=ismember(genesToAdd.genes,model.genes); +0049 if all(I) +0050 warning('All genes in genesToAdd.genes are already present in model.genes'); +0051 return +0052 elseif any(I) +0053 existingGenes=strjoin(genesToAdd.genes(I), ', '); +0054 warning(['The following genes are already present in model.genes and will therefore not be added: ', existingGenes]) +0055 genesToAdd.genes(I)=[]; +0056 if isfield(genesToAdd,'geneShortNames') +0057 genesToAdd.geneShortNames(I)=[]; +0058 end +0059 if isfield(genesToAdd,'geneMiriams') +0060 genesToAdd.geneMiriams(I)=[]; 0061 end -0062 if isfield(genesToAdd,'geneMiriams') -0063 genesToAdd.geneMiriams(I)=[]; -0064 end -0065 else -0066 newModel.genes=[newModel.genes;genesToAdd.genes(:)]; -0067 end -0068 -0069 %Some more checks and if they pass then add each field to the structure -0070 if isfield(genesToAdd,'geneShortNames') -0071 if numel(genesToAdd.geneShortNames)~=nGenes -0072 EM='genesToAdd.geneShortNames must have the same number of elements as genesToAdd.genes'; -0073 dispEM(EM); -0074 end -0075 if ~iscellstr(genesToAdd.geneShortNames) -0076 EM='genesToAdd.geneShortNames must be a cell array of strings'; -0077 dispEM(EM); -0078 end -0079 %Add empty field if it doesn't exist -0080 if ~isfield(newModel,'geneShortNames') -0081 newModel.geneShortNames=largeFiller; +0062 else +0063 newModel.genes=[newModel.genes;genesToAdd.genes(:)]; +0064 end +0065 +0066 %Some more checks and if they pass then add each field to the structure +0067 if isfield(genesToAdd,'geneShortNames') +0068 genesToAdd.geneShortNames=convertCharArray(genesToAdd.geneShortNames); +0069 if numel(genesToAdd.geneShortNames)~=nGenes +0070 EM='genesToAdd.geneShortNames must have the same number of elements as genesToAdd.genes'; +0071 dispEM(EM); +0072 end +0073 %Add empty field if it doesn't exist +0074 if ~isfield(newModel,'geneShortNames') +0075 newModel.geneShortNames=largeFiller; +0076 end +0077 newModel.geneShortNames=[newModel.geneShortNames;genesToAdd.geneShortNames(:)]; +0078 else +0079 %Add empty strings if structure is in model +0080 if isfield(newModel,'geneShortNames') +0081 newModel.geneShortNames=[newModel.geneShortNames;filler]; 0082 end -0083 newModel.geneShortNames=[newModel.geneShortNames;genesToAdd.geneShortNames(:)]; -0084 else -0085 %Add empty strings if structure is in model -0086 if isfield(newModel,'geneShortNames') -0087 newModel.geneShortNames=[newModel.geneShortNames;filler]; -0088 end -0089 end -0090 -0091 %Don't check the type of geneMiriams -0092 if isfield(genesToAdd,'geneMiriams') -0093 if numel(genesToAdd.geneMiriams)~=nGenes -0094 EM='genesToAdd.geneMiriams must have the same number of elements as genesToAdd.genes'; -0095 dispEM(EM); -0096 end -0097 %Add empty field if it doesn't exist -0098 if ~isfield(newModel,'geneMiriams') -0099 newModel.geneMiriams=cell(nOldGenes,1); -0100 end -0101 newModel.geneMiriams=[newModel.geneMiriams;genesToAdd.geneMiriams(:)]; -0102 else -0103 if isfield(newModel,'geneMiriams') -0104 newModel.geneMiriams=[newModel.geneMiriams;cell(nGenes,1)]; -0105 end -0106 end -0107 -0108 if isfield(genesToAdd,'geneComps') -0109 if numel(genesToAdd.geneComps)~=nGenes -0110 EM='genesToAdd.geneComps must have the same number of elements as genesToAdd.genes'; -0111 dispEM(EM); +0083 end +0084 +0085 %Don't check the type of geneMiriams +0086 if isfield(genesToAdd,'geneMiriams') +0087 if numel(genesToAdd.geneMiriams)~=nGenes +0088 EM='genesToAdd.geneMiriams must have the same number of elements as genesToAdd.genes'; +0089 dispEM(EM); +0090 end +0091 %Add empty field if it doesn't exist +0092 if ~isfield(newModel,'geneMiriams') +0093 newModel.geneMiriams=cell(nOldGenes,1); +0094 end +0095 newModel.geneMiriams=[newModel.geneMiriams;genesToAdd.geneMiriams(:)]; +0096 else +0097 if isfield(newModel,'geneMiriams') +0098 newModel.geneMiriams=[newModel.geneMiriams;cell(nGenes,1)]; +0099 end +0100 end +0101 +0102 if isfield(genesToAdd,'geneComps') +0103 if numel(genesToAdd.geneComps)~=nGenes +0104 EM='genesToAdd.geneComps must have the same number of elements as genesToAdd.genes'; +0105 dispEM(EM); +0106 end +0107 %Add empty field if it doesn't exist +0108 if ~isfield(newModel,'geneComps') +0109 newModel.geneComps=ones(nOldGenes,1); +0110 EM='Adding genes with compartment information to a model without such information. All existing genes will be assigned to the first compartment'; +0111 dispEM(EM,false); 0112 end -0113 %Add empty field if it doesn't exist -0114 if ~isfield(newModel,'geneComps') -0115 newModel.geneComps=ones(nOldGenes,1); -0116 EM='Adding genes with compartment information to a model without such information. All existing genes will be assigned to the first compartment'; -0117 dispEM(EM,false); +0113 newModel.geneComps=[newModel.geneComps;genesToAdd.geneComps(:)]; +0114 else +0115 if isfield(newModel,'geneComps') +0116 newModel.geneComps=[newModel.geneComps;ones(nGenes,1)]; +0117 fprintf('NOTE: The added genes will be assigned to the first compartment\n'); 0118 end -0119 newModel.geneComps=[newModel.geneComps;genesToAdd.geneComps(:)]; -0120 else -0121 if isfield(newModel,'geneComps') -0122 newModel.geneComps=[newModel.geneComps;ones(nGenes,1)]; -0123 fprintf('NOTE: The added genes will be assigned to the first compartment\n'); -0124 end -0125 end -0126 -0127 if isfield(newModel,'geneFrom') -0128 newModel.geneFrom=[newModel.geneFrom;filler]; -0129 end -0130 -0131 if isfield(newModel,'rxnGeneMat') -0132 newModel.rxnGeneMat=[newModel.rxnGeneMat,zeros(length(newModel.rxns),nGenes)]; -0133 end -0134 end +0119 end +0120 +0121 if isfield(newModel,'geneFrom') +0122 newModel.geneFrom=[newModel.geneFrom;filler]; +0123 end +0124 +0125 if isfield(newModel,'rxnGeneMat') +0126 newModel.rxnGeneMat=[newModel.rxnGeneMat,zeros(length(newModel.rxns),nGenes)]; +0127 end +0128 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/addMets.html b/doc/core/addMets.html index e09bfb72..25fea06e 100644 --- a/doc/core/addMets.html +++ b/doc/core/addMets.html @@ -85,15 +85,13 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • dispEM dispEM
  • generateNewIds generateNewIds
  • This function is called by: -

    SUBFUNCTIONS ^

    - +

    SOURCE CODE ^

    0001 function newModel=addMets(model,metsToAdd,copyInfo,prefix)
    @@ -156,287 +154,254 @@ 

    SOURCE CODE ^end 0059 if nargin<4 0060 prefix='m_'; -0061 end -0062 -0063 newModel=model; +0061 else +0062 prefix=char(prefix); +0063 end 0064 -0065 if isempty(metsToAdd) -0066 return; -0067 end -0068 -0069 %Check some stuff regarding the required fields -0070 if ~isfield(metsToAdd,'mets') -0071 metsToAdd.mets=generateNewIds(newModel,'mets',prefix,numel(metsToAdd.metNames)); -0072 end -0073 if ~isfield(metsToAdd,'metNames') -0074 metsToAdd.metNames=metsToAdd.mets; -0075 end -0076 if ~isfield(metsToAdd,'compartments') -0077 EM='compartments is a required field in metsToAdd'; -0078 dispEM(EM); -0079 end -0080 if ischar(metsToAdd.mets) -0081 metsToAdd.mets={metsToAdd.mets}; -0082 elseif ~iscellstr(metsToAdd.mets) -0083 EM='metsToAdd.mets must be a cell array of strings'; +0065 newModel=model; +0066 +0067 if isempty(metsToAdd) +0068 return; +0069 end +0070 +0071 %Check some stuff regarding the required fields +0072 if ~isfield(metsToAdd,'mets') +0073 metsToAdd.mets=generateNewIds(newModel,'mets',prefix,numel(metsToAdd.metNames)); +0074 else +0075 metsToAdd.mets=convertCharArray(metsToAdd.mets); +0076 end +0077 if ~isfield(metsToAdd,'metNames') +0078 metsToAdd.metNames=metsToAdd.mets; +0079 else +0080 metsToAdd.metNames=convertCharArray(metsToAdd.metNames); +0081 end +0082 if ~isfield(metsToAdd,'compartments') +0083 EM='compartments is a required field in metsToAdd'; 0084 dispEM(EM); -0085 end -0086 if ischar(metsToAdd.metNames) -0087 metsToAdd.metNames={metsToAdd.metNames}; -0088 elseif ~iscellstr(metsToAdd.metNames) -0089 EM='metsToAdd.metNames must be a cell array of strings'; -0090 dispEM(EM); -0091 end -0092 if ~iscellstr(metsToAdd.compartments) -0093 if ischar(metsToAdd.compartments) -0094 temp=cell(numel(metsToAdd.mets),1); -0095 temp(:)={metsToAdd.compartments}; -0096 metsToAdd.compartments=temp; -0097 else -0098 EM='metsToAdd.compartments must be a cell array of strings'; -0099 dispEM(EM); -0100 end -0101 end -0102 -0103 %Number of metabolites -0104 nMets=numel(metsToAdd.mets); -0105 nOldMets=numel(model.mets); -0106 filler=cell(nMets,1); -0107 filler(:)={''}; -0108 largeFiller=cell(nOldMets,1); -0109 largeFiller(:)={''}; -0110 -0111 %Check that no metabolite ids are already present in the model -0112 I=ismember(metsToAdd.mets,model.mets); -0113 if any(I) -0114 dispEM(['One or more elements in metsToAdd.mets are already present in model.mets: '... -0115 metsToAdd.mets{I}]); -0116 else -0117 newModel.mets=[newModel.mets;metsToAdd.mets(:)]; -0118 end -0119 -0120 %Check that all the compartments could be found -0121 [I, compMap]=ismember(metsToAdd.compartments,model.comps); -0122 if ~all(I) -0123 EM='metsToAdd.compartments must match model.comps'; -0124 dispEM(EM); -0125 end -0126 -0127 %Check that the metabolite names aren't present in the same compartment. -0128 %Not the neatest way maybe.. -0129 t1=strcat(metsToAdd.metNames(:),'***',metsToAdd.compartments(:)); -0130 t2=strcat(model.metNames,'***',model.comps(model.metComps)); -0131 if any(ismember(t1,t2)) -0132 EM='One or more elements in metsToAdd.metNames already exist in the same compartments as the one it is being added to'; -0133 dispEM(EM); -0134 end -0135 -0136 %Some more checks and if they pass then add each field to the structure -0137 if numel(metsToAdd.metNames)~=nMets -0138 EM='metsToAdd.metNames must have the same number of elements as metsToAdd.mets'; -0139 dispEM(EM); -0140 else -0141 newModel.metNames=[newModel.metNames;metsToAdd.metNames(:)]; -0142 end -0143 -0144 if numel(compMap)~=nMets -0145 EM='metsToAdd.compartments must have the same number of elements as metsToAdd.mets'; -0146 dispEM(EM); -0147 else -0148 newModel.metComps=[newModel.metComps;compMap(:)]; -0149 end -0150 -0151 if isfield(metsToAdd,'b') -0152 if size(metsToAdd.b,1)~=nMets -0153 EM='metsToAdd.b must have the same number of elements as metsToAdd.mets'; -0154 dispEM(EM); -0155 else -0156 %Add empty field if it doesn't exist -0157 if ~isfield(newModel,'b') -0158 newModel.b=zeros(nOldMets,1); -0159 end -0160 -0161 %If the original is only one vector -0162 if size(metsToAdd.b,2)>size(newModel.b,2) -0163 newModel.b=[newModel.b newModel.b]; -0164 end -0165 %Add the new ones -0166 newModel.b=[newModel.b;metsToAdd.b]; -0167 end -0168 else -0169 if isfield(newModel,'b') -0170 %Add the default -0171 newModel.b=[newModel.b;zeros(nMets,size(newModel.b,2))]; -0172 end -0173 end -0174 -0175 if isfield(metsToAdd,'unconstrained') -0176 if numel(metsToAdd.unconstrained)~=nMets -0177 EM='metsToAdd.unconstrained must have the same number of elements as metsToAdd.mets'; -0178 dispEM(EM); -0179 else -0180 %Add empty field if it doesn't exist -0181 if ~isfield(newModel,'unconstrained') -0182 newModel.unconstrained=zeros(nOldMets,1); -0183 end -0184 -0185 %Add the new ones -0186 newModel.unconstrained=[newModel.unconstrained;metsToAdd.unconstrained(:)]; -0187 end -0188 else -0189 if isfield(newModel,'unconstrained') -0190 %Add the default -0191 newModel.unconstrained=[newModel.unconstrained;zeros(nMets,1)]; -0192 end -0193 end -0194 -0195 if isfield(metsToAdd,'inchis') -0196 if numel(metsToAdd.inchis)~=nMets -0197 EM='metsToAdd.inchis must have the same number of elements as metsToAdd.mets'; -0198 dispEM(EM); -0199 end -0200 if ~iscellstr(metsToAdd.inchis) -0201 EM='metsToAdd.inchis must be a cell array of strings'; -0202 dispEM(EM); -0203 end -0204 %Add empty field if it doesn't exist -0205 if ~isfield(newModel,'inchis') -0206 newModel.inchis=largeFiller; -0207 end -0208 newModel.inchis=[newModel.inchis;metsToAdd.inchis(:)]; -0209 else -0210 %Add empty strings if structure is in model -0211 if isfield(newModel,'inchis') -0212 newModel.inchis=[newModel.inchis;filler]; -0213 end -0214 end -0215 -0216 if isfield(metsToAdd,'metFormulas') -0217 if numel(metsToAdd.metFormulas)~=nMets -0218 EM='metsToAdd.metFormulas must have the same number of elements as metsToAdd.mets'; -0219 dispEM(EM); -0220 end -0221 if ~iscellstr(metsToAdd.metFormulas) -0222 EM='metsToAdd.metFormulas must be a cell array of strings'; -0223 dispEM(EM); -0224 end -0225 %Add empty field if it doesn't exist -0226 if ~isfield(newModel,'metFormulas') -0227 newModel.metFormulas=largeFiller; +0085 else +0086 metsToAdd.compartments=convertCharArray(metsToAdd.compartments); +0087 end +0088 +0089 %Number of metabolites +0090 nMets=numel(metsToAdd.mets); +0091 nOldMets=numel(model.mets); +0092 filler=cell(nMets,1); +0093 filler(:)={''}; +0094 largeFiller=cell(nOldMets,1); +0095 largeFiller(:)={''}; +0096 +0097 %Check that no metabolite ids are already present in the model +0098 I=ismember(metsToAdd.mets,model.mets); +0099 if any(I) +0100 dispEM(['One or more elements in metsToAdd.mets are already present in model.mets: '... +0101 metsToAdd.mets{I}]); +0102 else +0103 newModel.mets=[newModel.mets;metsToAdd.mets(:)]; +0104 end +0105 +0106 %Check that all the compartments could be found +0107 [I, compMap]=ismember(metsToAdd.compartments,model.comps); +0108 if ~all(I) +0109 EM='metsToAdd.compartments must match model.comps'; +0110 dispEM(EM); +0111 end +0112 +0113 %Check that the metabolite names aren't present in the same compartment. +0114 %Not the neatest way maybe.. +0115 t1=strcat(metsToAdd.metNames(:),'***',metsToAdd.compartments(:)); +0116 t2=strcat(model.metNames,'***',model.comps(model.metComps)); +0117 if any(ismember(t1,t2)) +0118 EM='One or more elements in metsToAdd.metNames already exist in the same compartments as the one it is being added to'; +0119 dispEM(EM); +0120 end +0121 +0122 %Some more checks and if they pass then add each field to the structure +0123 if numel(metsToAdd.metNames)~=nMets +0124 EM='metsToAdd.metNames must have the same number of elements as metsToAdd.mets'; +0125 dispEM(EM); +0126 else +0127 newModel.metNames=[newModel.metNames;metsToAdd.metNames(:)]; +0128 end +0129 +0130 if numel(compMap)~=nMets +0131 EM='metsToAdd.compartments must have the same number of elements as metsToAdd.mets'; +0132 dispEM(EM); +0133 else +0134 newModel.metComps=[newModel.metComps;compMap(:)]; +0135 end +0136 +0137 if isfield(metsToAdd,'b') +0138 if size(metsToAdd.b,1)~=nMets +0139 EM='metsToAdd.b must have the same number of elements as metsToAdd.mets'; +0140 dispEM(EM); +0141 else +0142 %Add empty field if it doesn't exist +0143 if ~isfield(newModel,'b') +0144 newModel.b=zeros(nOldMets,1); +0145 end +0146 +0147 %If the original is only one vector +0148 if size(metsToAdd.b,2)>size(newModel.b,2) +0149 newModel.b=[newModel.b newModel.b]; +0150 end +0151 %Add the new ones +0152 newModel.b=[newModel.b;metsToAdd.b]; +0153 end +0154 else +0155 if isfield(newModel,'b') +0156 %Add the default +0157 newModel.b=[newModel.b;zeros(nMets,size(newModel.b,2))]; +0158 end +0159 end +0160 +0161 if isfield(metsToAdd,'unconstrained') +0162 if numel(metsToAdd.unconstrained)~=nMets +0163 EM='metsToAdd.unconstrained must have the same number of elements as metsToAdd.mets'; +0164 dispEM(EM); +0165 else +0166 %Add empty field if it doesn't exist +0167 if ~isfield(newModel,'unconstrained') +0168 newModel.unconstrained=zeros(nOldMets,1); +0169 end +0170 +0171 %Add the new ones +0172 newModel.unconstrained=[newModel.unconstrained;metsToAdd.unconstrained(:)]; +0173 end +0174 else +0175 if isfield(newModel,'unconstrained') +0176 %Add the default +0177 newModel.unconstrained=[newModel.unconstrained;zeros(nMets,1)]; +0178 end +0179 end +0180 +0181 if isfield(metsToAdd,'inchis') +0182 metsToAdd.inchis=convertCharArray(metsToAdd.inchis); +0183 if numel(metsToAdd.inchis)~=nMets +0184 EM='metsToAdd.inchis must have the same number of elements as metsToAdd.mets'; +0185 dispEM(EM); +0186 end +0187 %Add empty field if it doesn't exist +0188 if ~isfield(newModel,'inchis') +0189 newModel.inchis=largeFiller; +0190 end +0191 newModel.inchis=[newModel.inchis;metsToAdd.inchis(:)]; +0192 else +0193 %Add empty strings if structure is in model +0194 if isfield(newModel,'inchis') +0195 newModel.inchis=[newModel.inchis;filler]; +0196 end +0197 end +0198 +0199 if isfield(metsToAdd,'metFormulas') +0200 metsToAdd.metFormulas=convertCharArray(metsToAdd.metFormulas); +0201 if numel(metsToAdd.metFormulas)~=nMets +0202 EM='metsToAdd.metFormulas must have the same number of elements as metsToAdd.mets'; +0203 dispEM(EM); +0204 end +0205 %Add empty field if it doesn't exist +0206 if ~isfield(newModel,'metFormulas') +0207 newModel.metFormulas=largeFiller; +0208 end +0209 newModel.metFormulas=[newModel.metFormulas;metsToAdd.metFormulas(:)]; +0210 else +0211 %Add default +0212 if isfield(newModel,'metFormulas') +0213 newModel.metFormulas=[newModel.metFormulas;filler]; +0214 end +0215 end +0216 +0217 if isfield(metsToAdd,'metCharges') +0218 if numel(metsToAdd.metCharges)~=nMets +0219 EM='metsToAdd.metCharges must have the same number of elements as metsToAdd.mets'; +0220 dispEM(EM); +0221 end +0222 if ~isnumeric(metsToAdd.metCharges) +0223 EM='metsToAdd.metCharges must be of type "double"'; +0224 dispEM(EM); +0225 end +0226 if ~isfield(newModel,'metCharges') +0227 newModel.metCharges=NaN(numel(largeFiller),1); 0228 end -0229 newModel.metFormulas=[newModel.metFormulas;metsToAdd.metFormulas(:)]; +0229 newModel.metCharges=[newModel.metCharges;metsToAdd.metCharges(:)]; 0230 else 0231 %Add default -0232 if isfield(newModel,'metFormulas') -0233 newModel.metFormulas=[newModel.metFormulas;filler]; +0232 if isfield(newModel,'metCharges') +0233 newModel.metCharges=[newModel.metCharges;NaN(numel(filler),1)]; 0234 end 0235 end 0236 -0237 if isfield(metsToAdd,'metCharges') -0238 if numel(metsToAdd.metCharges)~=nMets -0239 EM='metsToAdd.metCharges must have the same number of elements as metsToAdd.mets'; -0240 dispEM(EM); -0241 end -0242 if ~isnumeric(metsToAdd.metCharges) -0243 EM='metsToAdd.metCharges must be of type "double"'; -0244 dispEM(EM); -0245 end -0246 newModel.metCharges=[newModel.metCharges;metsToAdd.metCharges(:)]; -0247 else -0248 %Add default -0249 if isfield(newModel,'metCharges') -0250 newModel.metCharges=[newModel.metCharges;NaN(numel(filler),1)]; -0251 end -0252 end -0253 -0254 if isfield(metsToAdd,'metNotes') -0255 if numel(metsToAdd.metNotes)~=nMets -0256 EM='metsToAdd.metNotes must have the same number of elements as metsToAdd.mets'; -0257 dispEM(EM); -0258 end -0259 if ~iscellstr(metsToAdd.metNotes) -0260 EM='metsToAdd.metNotes must be a cell array of strings'; -0261 dispEM(EM); -0262 end -0263 %Add empty field if it doesn't exist -0264 if ~isfield(newModel,'metNotes') -0265 newModel.metNotes=largeFiller; -0266 end -0267 newModel.metNotes=[newModel.inchis;metsToAdd.metNotes(:)]; -0268 else -0269 %Add empty strings if structure is in model -0270 if isfield(newModel,'metNotes') -0271 newModel.metNotes=[newModel.metNotes;filler]; -0272 end -0273 end -0274 -0275 %Don't check the type of metMiriams -0276 if isfield(metsToAdd,'metMiriams') -0277 if numel(metsToAdd.metMiriams)~=nMets -0278 EM='metsToAdd.metMiriams must have the same number of elements as metsToAdd.mets'; -0279 dispEM(EM); -0280 end -0281 %Add empty field if it doesn't exist -0282 if ~isfield(newModel,'metMiriams') -0283 newModel.metMiriams=cell(nOldMets,1); -0284 end -0285 newModel.metMiriams=[newModel.metMiriams;metsToAdd.metMiriams(:)]; -0286 else -0287 if isfield(newModel,'metMiriams') -0288 newModel.metMiriams=[newModel.metMiriams;cell(nMets,1)]; -0289 end -0290 end -0291 -0292 if isfield(newModel,'metFrom') -0293 newModel.metFrom=[newModel.metFrom;filler]; -0294 end -0295 -0296 %Expand the S matrix -0297 newModel.S=[newModel.S;sparse(nMets,size(newModel.S,2))]; -0298 -0299 if copyInfo==true -0300 [I, J]=ismember(metsToAdd.metNames,model.metNames); -0301 J=J(I); -0302 %I is the indexes of the new metabolites for which a metabolite with -0303 %the same name existed -0304 I=find(I)+nOldMets; -0305 %Go through each of the added mets and copy annotation if it doesn't -0306 %exist -0307 for i=1:numel(I) -0308 if isfield(newModel,'inchis') -0309 if isempty(newModel.inchis{I(i)}) -0310 newModel.inchis(I(i))=newModel.inchis(J(i)); -0311 end -0312 end -0313 if isfield(newModel,'metFormulas') -0314 if isempty(newModel.metFormulas{I(i)}) -0315 newModel.metFormulas(I(i))=newModel.metFormulas(J(i)); -0316 end -0317 end -0318 if isfield(newModel,'metMiriams') -0319 if isempty(newModel.metMiriams{I(i)}) -0320 newModel.metMiriams(I(i))=newModel.metMiriams(J(i)); -0321 end -0322 end -0323 if isfield(newModel,'metCharges') -0324 newModel.metCharges(I(i))=newModel.metCharges(J(i)); -0325 end -0326 end -0327 end -0328 end -0329 -0330 %For getting the numerical form of metabolite ids on the form "m1". -0331 function I=getInteger(s) -0332 %Checks if a string is on the form "m1" and if so returns the value of the -0333 %integer -0334 I=0; -0335 if strcmpi(s(1),'m') -0336 t=str2double(s(2:end)); -0337 if ~isnan(t) && ~isempty(t) -0338 I=t; -0339 end -0340 end -0341 end

    +0237 if isfield(metsToAdd,'metNotes') +0238 metsToAdd.metNotes=convertCharArray(metsToAdd.metNotes); +0239 if numel(metsToAdd.metNotes)~=nMets +0240 EM='metsToAdd.metNotes must have the same number of elements as metsToAdd.mets'; +0241 dispEM(EM); +0242 end +0243 %Add empty field if it doesn't exist +0244 if ~isfield(newModel,'metNotes') +0245 newModel.metNotes=largeFiller; +0246 end +0247 newModel.metNotes=[newModel.metNotes;metsToAdd.metNotes(:)]; +0248 else +0249 %Add empty strings if structure is in model +0250 if isfield(newModel,'metNotes') +0251 newModel.metNotes=[newModel.metNotes;filler]; +0252 end +0253 end +0254 +0255 %Don't check the type of metMiriams +0256 if isfield(metsToAdd,'metMiriams') +0257 if numel(metsToAdd.metMiriams)~=nMets +0258 EM='metsToAdd.metMiriams must have the same number of elements as metsToAdd.mets'; +0259 dispEM(EM); +0260 end +0261 %Add empty field if it doesn't exist +0262 if ~isfield(newModel,'metMiriams') +0263 newModel.metMiriams=cell(nOldMets,1); +0264 end +0265 newModel.metMiriams=[newModel.metMiriams;metsToAdd.metMiriams(:)]; +0266 else +0267 if isfield(newModel,'metMiriams') +0268 newModel.metMiriams=[newModel.metMiriams;cell(nMets,1)]; +0269 end +0270 end +0271 +0272 if isfield(newModel,'metFrom') +0273 newModel.metFrom=[newModel.metFrom;filler]; +0274 end +0275 +0276 %Expand the S matrix +0277 newModel.S=[newModel.S;sparse(nMets,size(newModel.S,2))]; +0278 +0279 if copyInfo==true +0280 [I, J]=ismember(metsToAdd.metNames,model.metNames); +0281 J=J(I); +0282 %I is the indexes of the new metabolites for which a metabolite with +0283 %the same name existed +0284 I=find(I)+nOldMets; +0285 %Go through each of the added mets and copy annotation if it doesn't +0286 %exist +0287 for i=1:numel(I) +0288 if isfield(newModel,'inchis') +0289 if isempty(newModel.inchis{I(i)}) +0290 newModel.inchis(I(i))=newModel.inchis(J(i)); +0291 end +0292 end +0293 if isfield(newModel,'metFormulas') +0294 if isempty(newModel.metFormulas{I(i)}) +0295 newModel.metFormulas(I(i))=newModel.metFormulas(J(i)); +0296 end +0297 end +0298 if isfield(newModel,'metMiriams') +0299 if isempty(newModel.metMiriams{I(i)}) +0300 newModel.metMiriams(I(i))=newModel.metMiriams(J(i)); +0301 end +0302 end +0303 if isfield(newModel,'metCharges') +0304 newModel.metCharges(I(i))=newModel.metCharges(J(i)); +0305 end +0306 end +0307 end +0308 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/addRxns.html b/doc/core/addRxns.html index aabb1812..cd07e0b9 100644 --- a/doc/core/addRxns.html +++ b/doc/core/addRxns.html @@ -133,7 +133,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • addGenesRaven addGenesRaven
  • addMets addMets
  • buildEquation buildEquation
  • constructS constructS
  • convertCharArray convertCharArray
  • dispEM dispEM
  • standardizeGrRules standardizeGrRules
  • This function is called by: @@ -247,564 +247,559 @@

    SOURCE CODE ^if nargin<4 0105 compartment=[]; -0106 end -0107 if nargin<5 -0108 allowNewMets=false; -0109 end -0110 if nargin<6 -0111 allowNewGenes=false; -0112 end -0113 -0114 if allowNewGenes & isfield(rxnsToAdd,'grRules') -0115 genesToAdd.genes = strjoin(rxnsToAdd.grRules); -0116 genesToAdd.genes = regexp(genesToAdd.genes,' |)|(|and|or','split'); % Remove all grRule punctuation -0117 genesToAdd.genes = genesToAdd.genes(~cellfun(@isempty,genesToAdd.genes)); % Remove spaces and empty genes -0118 genesToAdd.genes = setdiff(unique(genesToAdd.genes),model.genes); % Only keep new genes -0119 if isfield(model,'geneComps') -0120 genesToAdd.geneComps(1:numel(genesToAdd.genes)) = repmat(11,numel(genesToAdd.genes),1); -0121 end -0122 if ~isempty(genesToAdd.genes) -0123 fprintf('\nNew genes added to the model:\n') -0124 fprintf([strjoin(genesToAdd.genes,'\n') '\n']) -0125 newModel=addGenesRaven(model,genesToAdd); -0126 else -0127 newModel=model; -0128 end -0129 else -0130 newModel=model; -0131 end -0132 -0133 %If no reactions should be added -0134 if isempty(rxnsToAdd) -0135 return; -0136 end -0137 -0138 %Check the input -0139 if isfield(rxnsToAdd,'stoichCoeffs') -0140 eqnType=1; -0141 elseif ~isnumeric(eqnType) -0142 EM='eqnType must be numeric'; -0143 dispEM(EM); -0144 elseif ~ismember(eqnType,[1 2 3]) -0145 EM='eqnType must be 1, 2, or 3'; -0146 dispEM(EM); -0147 end -0148 -0149 if eqnType==2 || (eqnType==1 && allowNewMets==true) -0150 if ~ischar(compartment) -0151 EM='compartment must be a string'; -0152 dispEM(EM); -0153 end -0154 if ~ismember(compartment,model.comps) -0155 EM='compartment must match one of the compartments in model.comps'; -0156 dispEM(EM); -0157 end -0158 end -0159 -0160 if ~isfield(rxnsToAdd,'rxns') -0161 EM='rxns is a required field in rxnsToAdd'; -0162 dispEM(EM); -0163 elseif iscell(rxnsToAdd.rxns) -0164 %To fit with some later printing -0165 rxnsToAdd.rxns=rxnsToAdd.rxns(:); -0166 end -0167 if ~(isfield(rxnsToAdd,'equations') || (isfield(rxnsToAdd,'mets') && isfield(rxnsToAdd,'stoichCoeffs'))) -0168 EM='Either "equations" or "mets"+"stoichCoeffs" are required fields in rxnsToAdd'; -0169 dispEM(EM); -0170 end -0171 -0172 if any(ismember(rxnsToAdd.rxns,model.rxns)) -0173 EM='One or more reaction id was already present in the model. Use changeRxns or remove the existing reactions before adding new ones'; -0174 dispEM(EM); -0175 end -0176 -0177 if ~iscellstr(rxnsToAdd.rxns) && ~ischar(rxnsToAdd.rxns) -0178 %It could also be a string, but it's not encouraged -0179 EM='rxnsToAdd.rxns must be a cell array of strings'; -0180 dispEM(EM); -0181 else -0182 rxnsToAdd.rxns=cellstr(rxnsToAdd.rxns); -0183 end -0184 -0185 %Normal case: equations provided -0186 if isfield(rxnsToAdd,'equations') -0187 if ~iscellstr(rxnsToAdd.equations) && ~ischar(rxnsToAdd.equations) -0188 %It could also be a string, but it's not encouraged -0189 EM='rxnsToAdd.equations must be a cell array of strings'; -0190 dispEM(EM); -0191 else -0192 rxnsToAdd.equations=cellstr(rxnsToAdd.equations); -0193 end -0194 -0195 %Alternative case: mets+stoichiometry provided -0196 else -0197 %In the case of 1 rxn added (array of strings + vector), transform to -0198 %cells of length=1: -0199 if iscellstr(rxnsToAdd.mets) -0200 rxnsToAdd.mets = {rxnsToAdd.mets}; +0106 else +0107 compartment=char(compartment); +0108 end +0109 if nargin<5 +0110 allowNewMets=false; +0111 elseif ~islogical(allowNewMets) +0112 allowNewMets=char(allowNewMets); +0113 end +0114 if nargin<6 +0115 allowNewGenes=false; +0116 end +0117 +0118 if allowNewGenes & isfield(rxnsToAdd,'grRules') +0119 genesToAdd.genes = strjoin(convertCharArray(rxnsToAdd.grRules)); +0120 genesToAdd.genes = regexp(genesToAdd.genes,' |)|(|and|or','split'); % Remove all grRule punctuation +0121 genesToAdd.genes = genesToAdd.genes(~cellfun(@isempty,genesToAdd.genes)); % Remove spaces and empty genes +0122 genesToAdd.genes = setdiff(unique(genesToAdd.genes),model.genes); % Only keep new genes +0123 if isfield(model,'geneComps') +0124 genesToAdd.geneComps(1:numel(genesToAdd.genes)) = repmat(11,numel(genesToAdd.genes),1); +0125 end +0126 if ~isempty(genesToAdd.genes) +0127 fprintf('\nNew genes added to the model:\n') +0128 fprintf([strjoin(genesToAdd.genes,'\n') '\n']) +0129 newModel=addGenesRaven(model,genesToAdd); +0130 else +0131 newModel=model; +0132 end +0133 else +0134 newModel=model; +0135 end +0136 +0137 %If no reactions should be added +0138 if isempty(rxnsToAdd) +0139 return; +0140 end +0141 +0142 %Check the input +0143 if isfield(rxnsToAdd,'stoichCoeffs') +0144 eqnType=1; +0145 elseif ~isnumeric(eqnType) +0146 EM='eqnType must be numeric'; +0147 dispEM(EM); +0148 elseif ~ismember(eqnType,[1 2 3]) +0149 EM='eqnType must be 1, 2, or 3'; +0150 dispEM(EM); +0151 end +0152 +0153 if eqnType==2 || (eqnType==1 && allowNewMets==true) +0154 compartment=char(compartment); +0155 if ~ismember(compartment,model.comps) +0156 EM='compartment must match one of the compartments in model.comps'; +0157 dispEM(EM); +0158 end +0159 end +0160 +0161 if ~isfield(rxnsToAdd,'rxns') +0162 EM='rxns is a required field in rxnsToAdd'; +0163 dispEM(EM); +0164 else +0165 rxnsToAdd.rxns=convertCharArray(rxnsToAdd.rxns); +0166 %To fit with some later printing +0167 rxnsToAdd.rxns=rxnsToAdd.rxns(:); +0168 end +0169 if ~(isfield(rxnsToAdd,'equations') || (isfield(rxnsToAdd,'mets') && isfield(rxnsToAdd,'stoichCoeffs'))) +0170 EM='Either "equations" or "mets"+"stoichCoeffs" are required fields in rxnsToAdd'; +0171 dispEM(EM); +0172 end +0173 +0174 if any(ismember(rxnsToAdd.rxns,model.rxns)) +0175 EM='One or more reaction id was already present in the model. Use changeRxns or remove the existing reactions before adding new ones'; +0176 dispEM(EM); +0177 end +0178 +0179 %Normal case: equations provided +0180 if isfield(rxnsToAdd,'equations') +0181 rxnsToAdd.equations=convertCharArray(rxnsToAdd.equations); +0182 +0183 %Alternative case: mets+stoichiometry provided +0184 else +0185 %In the case of 1 rxn added (array of strings + vector), transform to +0186 %cells of length=1: +0187 if iscellstr(rxnsToAdd.mets) +0188 rxnsToAdd.mets={rxnsToAdd.mets}; +0189 end +0190 if isnumeric(rxnsToAdd.stoichCoeffs) +0191 rxnsToAdd.stoichCoeffs = {rxnsToAdd.stoichCoeffs}; +0192 end +0193 %Now both rxnsToAdd.mets and rxnsToAdd.stoichCoeffs should be cell +0194 %arrays & of the same size: +0195 if ~iscell(rxnsToAdd.mets) || ~iscell(rxnsToAdd.stoichCoeffs) +0196 EM='rxnsToAdd.mets & rxnsToAdd.stoichCoeffs must be cell arrays'; +0197 dispEM(EM); +0198 elseif length(rxnsToAdd.stoichCoeffs) ~= length(rxnsToAdd.mets) +0199 EM = 'rxnsToAdd.stoichCoeffs must have the same number of elements as rxnsToAdd.mets'; +0200 dispEM(EM); 0201 end -0202 if isnumeric(rxnsToAdd.stoichCoeffs) -0203 rxnsToAdd.stoichCoeffs = {rxnsToAdd.stoichCoeffs}; -0204 end -0205 %Now both rxnsToAdd.mets and rxnsToAdd.stoichCoeffs should be cell -0206 %arrays & of the same size: -0207 if ~iscell(rxnsToAdd.mets) || ~iscell(rxnsToAdd.stoichCoeffs) -0208 EM='rxnsToAdd.mets & rxnsToAdd.stoichCoeffs must be cell arrays'; -0209 dispEM(EM); -0210 elseif length(rxnsToAdd.stoichCoeffs) ~= length(rxnsToAdd.mets) -0211 EM = 'rxnsToAdd.stoichCoeffs must have the same number of elements as rxnsToAdd.mets'; -0212 dispEM(EM); -0213 end -0214 %In this case we need lb to decide if the reaction is reversible or not: -0215 if ~isfield(rxnsToAdd,'lb') -0216 %Fill with standard if it doesn't exist -0217 rxnsToAdd.lb=-inf(size(rxnsToAdd.mets)); -0218 elseif ~isnumeric(rxnsToAdd.lb) -0219 EM = 'rxnsToAdd.lb must be a vector'; -0220 dispEM(EM); -0221 elseif length(rxnsToAdd.lb) ~= length(rxnsToAdd.mets) -0222 EM = 'rxnsToAdd.lb must have the same number of elements as rxnsToAdd.mets'; -0223 dispEM(EM); -0224 end -0225 %Now we construct equations, to comply with the rest of the script: -0226 rxnsToAdd.equations = cell(size(rxnsToAdd.mets)); -0227 for i = 1:length(rxnsToAdd.mets) -0228 mets = rxnsToAdd.mets{i}; -0229 stoichCoeffs = rxnsToAdd.stoichCoeffs{i}; -0230 isrev = rxnsToAdd.lb(i) < 0; -0231 rxnsToAdd.equations{i} = buildEquation(mets,stoichCoeffs,isrev); -0232 end -0233 end -0234 -0235 nRxns=numel(rxnsToAdd.rxns); -0236 nOldRxns=numel(model.rxns); -0237 filler=cell(nRxns,1); -0238 filler(:)={''}; -0239 cellfiller=cellfun(@(x) cell(0,0),filler,'UniformOutput',false); -0240 largeFiller=cell(nOldRxns,1); -0241 largeFiller(:)={''}; -0242 celllargefiller=cellfun(@(x) cell(0,0),largeFiller,'UniformOutput',false); +0202 %In this case we need lb to decide if the reaction is reversible or not: +0203 if ~isfield(rxnsToAdd,'lb') +0204 %Fill with standard if it doesn't exist +0205 rxnsToAdd.lb=-inf(size(rxnsToAdd.mets)); +0206 elseif ~isnumeric(rxnsToAdd.lb) +0207 EM = 'rxnsToAdd.lb must be a vector'; +0208 dispEM(EM); +0209 elseif length(rxnsToAdd.lb) ~= length(rxnsToAdd.mets) +0210 EM = 'rxnsToAdd.lb must have the same number of elements as rxnsToAdd.mets'; +0211 dispEM(EM); +0212 end +0213 %Now we construct equations, to comply with the rest of the script: +0214 rxnsToAdd.equations = cell(size(rxnsToAdd.mets)); +0215 for i = 1:length(rxnsToAdd.mets) +0216 mets = rxnsToAdd.mets{i}; +0217 stoichCoeffs = rxnsToAdd.stoichCoeffs{i}; +0218 isrev = rxnsToAdd.lb(i) < 0; +0219 rxnsToAdd.equations{i} = buildEquation(mets,stoichCoeffs,isrev); +0220 end +0221 end +0222 +0223 nRxns=numel(rxnsToAdd.rxns); +0224 nOldRxns=numel(model.rxns); +0225 filler=cell(nRxns,1); +0226 filler(:)={''}; +0227 cellfiller=cellfun(@(x) cell(0,0),filler,'UniformOutput',false); +0228 largeFiller=cell(nOldRxns,1); +0229 largeFiller(:)={''}; +0230 celllargefiller=cellfun(@(x) cell(0,0),largeFiller,'UniformOutput',false); +0231 +0232 %***Add everything to the model except for the equations. +0233 if numel(rxnsToAdd.equations)~=nRxns +0234 EM='rxnsToAdd.equations must have the same number of elements as rxnsToAdd.rxns'; +0235 dispEM(EM); +0236 end +0237 +0238 %Parse the equations. This is done at this early stage since I need the +0239 %reversibility info +0240 [S, mets, badRxns, reversible]=constructS(rxnsToAdd.equations); +0241 EM='The following equations have one or more metabolites both as substrate and product. Only the net equations will be added:'; +0242 dispEM(EM,false,rxnsToAdd.rxns(badRxns)); 0243 -0244 %***Add everything to the model except for the equations. -0245 if numel(rxnsToAdd.equations)~=nRxns -0246 EM='rxnsToAdd.equations must have the same number of elements as rxnsToAdd.rxns'; -0247 dispEM(EM); -0248 end -0249 -0250 %Parse the equations. This is done at this early stage since I need the -0251 %reversibility info -0252 [S, mets, badRxns, reversible]=constructS(rxnsToAdd.equations); -0253 EM='The following equations have one or more metabolites both as substrate and product. Only the net equations will be added:'; -0254 dispEM(EM,false,rxnsToAdd.rxns(badRxns)); -0255 -0256 newModel.rev=[newModel.rev;reversible]; -0257 newModel.rxns=[newModel.rxns;rxnsToAdd.rxns(:)]; -0258 -0259 if isfield(rxnsToAdd,'rxnNames') -0260 if numel(rxnsToAdd.rxnNames)~=nRxns -0261 EM='rxnsToAdd.rxnNames must have the same number of elements as rxnsToAdd.rxns'; -0262 dispEM(EM); -0263 end -0264 %Fill with standard if it doesn't exist -0265 if ~isfield(newModel,'rxnNames') -0266 newModel.rxnNames=largeFiller; -0267 end -0268 newModel.rxnNames=[newModel.rxnNames;rxnsToAdd.rxnNames(:)]; -0269 else -0270 %Fill with standard if it doesn't exist -0271 if isfield(newModel,'rxnNames') -0272 newModel.rxnNames=[newModel.rxnNames;filler]; -0273 end -0274 end -0275 -0276 if isfield(newModel,'annotation') & isfield(newModel.annotation,'defaultLB') -0277 newLb=newModel.annotation.defaultLB; -0278 else -0279 newLb=-inf; -0280 end -0281 -0282 if isfield(rxnsToAdd,'lb') -0283 if numel(rxnsToAdd.lb)~=nRxns -0284 EM='rxnsToAdd.lb must have the same number of elements as rxnsToAdd.rxns'; -0285 dispEM(EM); -0286 end -0287 %Fill with standard if it doesn't exist -0288 if ~isfield(newModel,'lb') -0289 newModel.lb=zeros(nOldRxns,1); -0290 newModel.lb(newModel.rev~=0)=newLb; -0291 end -0292 newModel.lb=[newModel.lb;rxnsToAdd.lb(:)]; +0244 newModel.rev=[newModel.rev;reversible]; +0245 newModel.rxns=[newModel.rxns;rxnsToAdd.rxns(:)]; +0246 +0247 if isfield(rxnsToAdd,'rxnNames') +0248 rxnsToAdd.rxnNames=convertCharArray(rxnsToAdd.rxnNames); +0249 if numel(rxnsToAdd.rxnNames)~=nRxns +0250 EM='rxnsToAdd.rxnNames must have the same number of elements as rxnsToAdd.rxns'; +0251 dispEM(EM); +0252 end +0253 %Fill with standard if it doesn't exist +0254 if ~isfield(newModel,'rxnNames') +0255 newModel.rxnNames=largeFiller; +0256 end +0257 newModel.rxnNames=[newModel.rxnNames;rxnsToAdd.rxnNames(:)]; +0258 else +0259 %Fill with standard if it doesn't exist +0260 if isfield(newModel,'rxnNames') +0261 newModel.rxnNames=[newModel.rxnNames;filler]; +0262 end +0263 end +0264 +0265 if isfield(newModel,'annotation') & isfield(newModel.annotation,'defaultLB') +0266 newLb=newModel.annotation.defaultLB; +0267 else +0268 newLb=-inf; +0269 end +0270 +0271 if isfield(rxnsToAdd,'lb') +0272 if numel(rxnsToAdd.lb)~=nRxns +0273 EM='rxnsToAdd.lb must have the same number of elements as rxnsToAdd.rxns'; +0274 dispEM(EM); +0275 end +0276 %Fill with standard if it doesn't exist +0277 if ~isfield(newModel,'lb') +0278 newModel.lb=zeros(nOldRxns,1); +0279 newModel.lb(newModel.rev~=0)=newLb; +0280 end +0281 newModel.lb=[newModel.lb;rxnsToAdd.lb(:)]; +0282 else +0283 %Fill with standard if it doesn't exist +0284 if isfield(newModel,'lb') +0285 I=zeros(nRxns,1); +0286 I(reversible~=0)=newLb; +0287 newModel.lb=[newModel.lb;I]; +0288 end +0289 end +0290 +0291 if isfield(newModel,'annotation') & isfield(newModel.annotation,'defaultUB') +0292 newUb=newModel.annotation.defaultUB; 0293 else -0294 %Fill with standard if it doesn't exist -0295 if isfield(newModel,'lb') -0296 I=zeros(nRxns,1); -0297 I(reversible~=0)=newLb; -0298 newModel.lb=[newModel.lb;I]; -0299 end -0300 end -0301 -0302 if isfield(newModel,'annotation') & isfield(newModel.annotation,'defaultUB') -0303 newUb=newModel.annotation.defaultUB; -0304 else -0305 newUb=inf; -0306 end -0307 -0308 if isfield(rxnsToAdd,'ub') -0309 if numel(rxnsToAdd.ub)~=nRxns -0310 EM='rxnsToAdd.ub must have the same number of elements as rxnsToAdd.rxns'; -0311 dispEM(EM); -0312 end -0313 %Fill with standard if it doesn't exist -0314 if ~isfield(newModel,'ub') -0315 newModel.ub=repmat(newUb,nOldrxns,1); -0316 end -0317 newModel.ub=[newModel.ub;rxnsToAdd.ub(:)]; -0318 else +0294 newUb=inf; +0295 end +0296 +0297 if isfield(rxnsToAdd,'ub') +0298 if numel(rxnsToAdd.ub)~=nRxns +0299 EM='rxnsToAdd.ub must have the same number of elements as rxnsToAdd.rxns'; +0300 dispEM(EM); +0301 end +0302 %Fill with standard if it doesn't exist +0303 if ~isfield(newModel,'ub') +0304 newModel.ub=repmat(newUb,nOldRxns,1); +0305 end +0306 newModel.ub=[newModel.ub;rxnsToAdd.ub(:)]; +0307 else +0308 %Fill with standard if it doesn't exist +0309 if isfield(newModel,'ub') +0310 newModel.ub=[newModel.ub;repmat(newUb,nRxns,1)]; +0311 end +0312 end +0313 +0314 if isfield(rxnsToAdd,'c') +0315 if numel(rxnsToAdd.c)~=nRxns +0316 EM='rxnsToAdd.c must have the same number of elements as rxnsToAdd.rxns'; +0317 dispEM(EM); +0318 end 0319 %Fill with standard if it doesn't exist -0320 if isfield(newModel,'ub') -0321 newModel.ub=[newModel.ub;repmat(newUb,nRxns,1)]; +0320 if ~isfield(newModel,'c') +0321 newModel.c=zeros(nOldRxns,1); 0322 end -0323 end -0324 -0325 if isfield(rxnsToAdd,'c') -0326 if numel(rxnsToAdd.c)~=nRxns -0327 EM='rxnsToAdd.c must have the same number of elements as rxnsToAdd.rxns'; -0328 dispEM(EM); -0329 end -0330 %Fill with standard if it doesn't exist -0331 if ~isfield(newModel,'c') -0332 newModel.c=zeros(nOldRxns,1); -0333 end -0334 newModel.c=[newModel.c;rxnsToAdd.c(:)]; -0335 else -0336 %Fill with standard if it doesn't exist -0337 if isfield(newModel,'c') -0338 newModel.c=[newModel.c;zeros(nRxns,1)]; -0339 end -0340 end -0341 -0342 if isfield(rxnsToAdd,'eccodes') -0343 if numel(rxnsToAdd.eccodes)~=nRxns -0344 EM='rxnsToAdd.eccodes must have the same number of elements as rxnsToAdd.rxns'; -0345 dispEM(EM); +0323 newModel.c=[newModel.c;rxnsToAdd.c(:)]; +0324 else +0325 %Fill with standard if it doesn't exist +0326 if isfield(newModel,'c') +0327 newModel.c=[newModel.c;zeros(nRxns,1)]; +0328 end +0329 end +0330 +0331 if isfield(rxnsToAdd,'eccodes') +0332 rxnsToAdd.eccodes=convertCharArray(rxnsToAdd.eccodes); +0333 if numel(rxnsToAdd.eccodes)~=nRxns +0334 EM='rxnsToAdd.eccodes must have the same number of elements as rxnsToAdd.rxns'; +0335 dispEM(EM); +0336 end +0337 %Fill with standard if it doesn't exist +0338 if ~isfield(newModel,'eccodes') +0339 newModel.eccodes=largeFiller; +0340 end +0341 newModel.eccodes=[newModel.eccodes;rxnsToAdd.eccodes(:)]; +0342 else +0343 %Fill with standard if it doesn't exist +0344 if isfield(newModel,'eccodes') +0345 newModel.eccodes=[newModel.eccodes;filler]; 0346 end -0347 %Fill with standard if it doesn't exist -0348 if ~isfield(newModel,'eccodes') -0349 newModel.eccodes=largeFiller; -0350 end -0351 newModel.eccodes=[newModel.eccodes;rxnsToAdd.eccodes(:)]; -0352 else -0353 %Fill with standard if it doesn't exist -0354 if isfield(newModel,'eccodes') -0355 newModel.eccodes=[newModel.eccodes;filler]; -0356 end -0357 end -0358 -0359 if isfield(rxnsToAdd,'subSystems') -0360 if numel(rxnsToAdd.subSystems)~=nRxns -0361 EM='rxnsToAdd.subSystems must have the same number of elements as rxnsToAdd.rxns'; -0362 dispEM(EM); -0363 end -0364 for i=1:numel(rxnsToAdd.subSystems) -0365 if ischar(rxnsToAdd.subSystems{i}) -0366 rxnsToAdd.subSystems{i}=rxnsToAdd.subSystems(i); -0367 end +0347 end +0348 +0349 if isfield(rxnsToAdd,'subSystems') +0350 if numel(rxnsToAdd.subSystems)~=nRxns +0351 EM='rxnsToAdd.subSystems must have the same number of elements as rxnsToAdd.rxns'; +0352 dispEM(EM); +0353 end +0354 for i=1:numel(rxnsToAdd.subSystems) +0355 if ischar(rxnsToAdd.subSystems{i}) +0356 rxnsToAdd.subSystems{i}=rxnsToAdd.subSystems(i); +0357 end +0358 end +0359 %Fill with standard if it doesn't exist +0360 if ~isfield(newModel,'subSystems') +0361 newModel.subSystems=celllargefiller; +0362 end +0363 newModel.subSystems=[newModel.subSystems;rxnsToAdd.subSystems]; +0364 else +0365 %Fill with standard if it doesn't exist +0366 if isfield(newModel,'subSystems') +0367 newModel.subSystems=[newModel.subSystems;cellfiller]; 0368 end -0369 %Fill with standard if it doesn't exist -0370 if ~isfield(newModel,'subSystems') -0371 newModel.subSystems=celllargefiller; -0372 end -0373 newModel.subSystems=[newModel.subSystems;rxnsToAdd.subSystems]; -0374 else +0369 end +0370 if isfield(rxnsToAdd,'rxnMiriams') +0371 if numel(rxnsToAdd.rxnMiriams)~=nRxns +0372 EM='rxnsToAdd.rxnMiriams must have the same number of elements as rxnsToAdd.rxns'; +0373 dispEM(EM); +0374 end 0375 %Fill with standard if it doesn't exist -0376 if isfield(newModel,'subSystems') -0377 newModel.subSystems=[newModel.subSystems;cellfiller]; +0376 if ~isfield(newModel,'rxnMiriams') +0377 newModel.rxnMiriams=cell(nOldRxns,1); 0378 end -0379 end -0380 if isfield(rxnsToAdd,'rxnMiriams') -0381 if numel(rxnsToAdd.rxnMiriams)~=nRxns -0382 EM='rxnsToAdd.rxnMiriams must have the same number of elements as rxnsToAdd.rxns'; -0383 dispEM(EM); +0379 newModel.rxnMiriams=[newModel.rxnMiriams;rxnsToAdd.rxnMiriams(:)]; +0380 else +0381 %Fill with standard if it doesn't exist +0382 if isfield(newModel,'rxnMiriams') +0383 newModel.rxnMiriams=[newModel.rxnMiriams;cell(nRxns,1)]; 0384 end -0385 %Fill with standard if it doesn't exist -0386 if ~isfield(newModel,'rxnMiriams') -0387 newModel.rxnMiriams=cell(nOldRxns,1); -0388 end -0389 newModel.rxnMiriams=[newModel.rxnMiriams;rxnsToAdd.rxnMiriams(:)]; -0390 else +0385 end +0386 if isfield(rxnsToAdd,'rxnComps') +0387 if numel(rxnsToAdd.rxnComps)~=nRxns +0388 EM='rxnsToAdd.rxnComps must have the same number of elements as rxnsToAdd.rxns'; +0389 dispEM(EM); +0390 end 0391 %Fill with standard if it doesn't exist -0392 if isfield(newModel,'rxnMiriams') -0393 newModel.rxnMiriams=[newModel.rxnMiriams;cell(nRxns,1)]; -0394 end -0395 end -0396 if isfield(rxnsToAdd,'rxnComps') -0397 if numel(rxnsToAdd.rxnComps)~=nRxns -0398 EM='rxnsToAdd.rxnComps must have the same number of elements as rxnsToAdd.rxns'; -0399 dispEM(EM); -0400 end -0401 %Fill with standard if it doesn't exist -0402 if ~isfield(newModel,'rxnComps') -0403 newModel.rxnComps=ones(nOldRxns,1); -0404 EM='Adding reactions with compartment information to a model without such information. All existing reactions will be assigned to the first compartment'; -0405 dispEM(EM,false); -0406 end -0407 newModel.rxnComps=[newModel.rxnComps;rxnsToAdd.rxnComps(:)]; -0408 else -0409 %Fill with standard if it doesn't exist -0410 if isfield(newModel,'rxnComps') -0411 newModel.rxnComps=[newModel.rxnComps;ones(nRxns,1)]; -0412 %fprintf('NOTE: The added reactions will be assigned to the first -0413 %compartment\n'); -0414 end -0415 end -0416 if isfield(rxnsToAdd,'grRules') -0417 if numel(rxnsToAdd.grRules)~=nRxns -0418 EM='rxnsToAdd.grRules must have the same number of elements as rxnsToAdd.rxns'; -0419 dispEM(EM); -0420 end -0421 %Fill with standard if it doesn't exist -0422 if ~isfield(newModel,'grRules') -0423 newModel.grRules=largeFiller; -0424 end -0425 newModel.grRules=[newModel.grRules;rxnsToAdd.grRules(:)]; -0426 else -0427 %Fill with standard if it doesn't exist -0428 if isfield(newModel,'grRules') -0429 newModel.grRules=[newModel.grRules;filler]; -0430 end -0431 end -0432 -0433 if isfield(rxnsToAdd,'rxnFrom') -0434 if numel(rxnsToAdd.rxnFrom)~=nRxns -0435 EM='rxnsToAdd.rxnFrom must have the same number of elements as rxnsToAdd.rxns'; -0436 dispEM(EM); -0437 end -0438 %Fill with standard if it doesn't exist -0439 if ~isfield(newModel,'rxnFrom') -0440 newModel.rxnFrom=largeFiller; -0441 end -0442 newModel.rxnFrom=[newModel.rxnFrom;rxnsToAdd.rxnFrom(:)]; -0443 else -0444 %Fill with standard if it doesn't exist -0445 if isfield(newModel,'rxnFrom') -0446 newModel.rxnFrom=[newModel.rxnFrom;filler]; +0392 if ~isfield(newModel,'rxnComps') +0393 newModel.rxnComps=ones(nOldRxns,1); +0394 EM='Adding reactions with compartment information to a model without such information. All existing reactions will be assigned to the first compartment'; +0395 dispEM(EM,false); +0396 end +0397 newModel.rxnComps=[newModel.rxnComps;rxnsToAdd.rxnComps(:)]; +0398 else +0399 %Fill with standard if it doesn't exist +0400 if isfield(newModel,'rxnComps') +0401 newModel.rxnComps=[newModel.rxnComps;ones(nRxns,1)]; +0402 %fprintf('NOTE: The added reactions will be assigned to the first +0403 %compartment\n'); +0404 end +0405 end +0406 if isfield(rxnsToAdd,'grRules') +0407 rxnsToAdd.grRules=convertCharArray(rxnsToAdd.grRules); +0408 if numel(rxnsToAdd.grRules)~=nRxns +0409 EM='rxnsToAdd.grRules must have the same number of elements as rxnsToAdd.rxns'; +0410 dispEM(EM); +0411 end +0412 %Fill with standard if it doesn't exist +0413 if ~isfield(newModel,'grRules') +0414 newModel.grRules=largeFiller; +0415 end +0416 newModel.grRules=[newModel.grRules;rxnsToAdd.grRules(:)]; +0417 else +0418 %Fill with standard if it doesn't exist +0419 if isfield(newModel,'grRules') +0420 newModel.grRules=[newModel.grRules;filler]; +0421 end +0422 end +0423 +0424 if isfield(rxnsToAdd,'rxnFrom') +0425 rxnsToAdd.rxnFrom=convertCharArray(rxnsToAdd.rxnFrom); +0426 if numel(rxnsToAdd.rxnFrom)~=nRxns +0427 EM='rxnsToAdd.rxnFrom must have the same number of elements as rxnsToAdd.rxns'; +0428 dispEM(EM); +0429 end +0430 %Fill with standard if it doesn't exist +0431 if ~isfield(newModel,'rxnFrom') +0432 newModel.rxnFrom=largeFiller; +0433 end +0434 newModel.rxnFrom=[newModel.rxnFrom;rxnsToAdd.rxnFrom(:)]; +0435 else +0436 %Fill with standard if it doesn't exist +0437 if isfield(newModel,'rxnFrom') +0438 newModel.rxnFrom=[newModel.rxnFrom;filler]; +0439 end +0440 end +0441 +0442 if isfield(rxnsToAdd,'rxnNotes') +0443 rxnsToAdd.rxnNotes=convertCharArray(rxnsToAdd.rxnNotes); +0444 if numel(rxnsToAdd.rxnNotes)~=nRxns +0445 EM='rxnsToAdd.rxnNotes must have the same number of elements as rxnsToAdd.rxns'; +0446 dispEM(EM); 0447 end -0448 end -0449 -0450 if isfield(rxnsToAdd,'rxnNotes') -0451 if numel(rxnsToAdd.rxnNotes)~=nRxns -0452 EM='rxnsToAdd.rxnNotes must have the same number of elements as rxnsToAdd.rxns'; -0453 dispEM(EM); -0454 end -0455 %Fill with standard if it doesn't exist -0456 if ~isfield(newModel,'rxnNotes') -0457 newModel.rxnNotes=largeFiller; -0458 end -0459 newModel.rxnNotes=[newModel.rxnNotes;rxnsToAdd.rxnNotes(:)]; -0460 else -0461 %Fill with standard if it doesn't exist -0462 if isfield(newModel,'rxnNotes') -0463 newModel.rxnNotes=[newModel.rxnNotes;filler]; -0464 end -0465 end -0466 -0467 if isfield(rxnsToAdd,'rxnReferences') -0468 if numel(rxnsToAdd.rxnReferences)~=nRxns -0469 EM='rxnsToAdd.rxnReferences must have the same number of elements as rxnsToAdd.rxns'; -0470 dispEM(EM); -0471 end +0448 %Fill with standard if it doesn't exist +0449 if ~isfield(newModel,'rxnNotes') +0450 newModel.rxnNotes=largeFiller; +0451 end +0452 newModel.rxnNotes=[newModel.rxnNotes;rxnsToAdd.rxnNotes(:)]; +0453 else +0454 %Fill with standard if it doesn't exist +0455 if isfield(newModel,'rxnNotes') +0456 newModel.rxnNotes=[newModel.rxnNotes;filler]; +0457 end +0458 end +0459 +0460 if isfield(rxnsToAdd,'rxnReferences') +0461 rxnsToAdd.rxnReferences=convertCharArray(rxnsToAdd.rxnReferences); +0462 if numel(rxnsToAdd.rxnReferences)~=nRxns +0463 EM='rxnsToAdd.rxnReferences must have the same number of elements as rxnsToAdd.rxns'; +0464 dispEM(EM); +0465 end +0466 %Fill with standard if it doesn't exist +0467 if ~isfield(newModel,'rxnReferences') +0468 newModel.rxnReferences=largeFiller; +0469 end +0470 newModel.rxnReferences=[newModel.rxnReferences;rxnsToAdd.rxnReferences(:)]; +0471 else 0472 %Fill with standard if it doesn't exist -0473 if ~isfield(newModel,'rxnReferences') -0474 newModel.rxnReferences=largeFiller; +0473 if isfield(newModel,'rxnReferences') +0474 newModel.rxnReferences=[newModel.rxnReferences;filler]; 0475 end -0476 newModel.rxnReferences=[newModel.rxnReferences;rxnsToAdd.rxnReferences(:)]; -0477 else -0478 %Fill with standard if it doesn't exist -0479 if isfield(newModel,'rxnReferences') -0480 newModel.rxnReferences=[newModel.rxnReferences;filler]; -0481 end -0482 end -0483 -0484 if isfield(rxnsToAdd,'pwys') -0485 if numel(rxnsToAdd.pwys)~=nRxns -0486 EM='rxnsToAdd.pwys must have the same number of elements as rxnsToAdd.rxns'; -0487 dispEM(EM); -0488 end -0489 %Fill with standard if it doesn't exist -0490 if ~isfield(newModel,'pwys') -0491 newModel.pwys=largeFiller; -0492 end -0493 newModel.pwys=[newModel.pwys;rxnsToAdd.pwys(:)]; -0494 else -0495 %Fill with standard if it doesn't exist -0496 if isfield(newModel,'pwys') -0497 newModel.pwys=[newModel.pwys;filler]; -0498 end -0499 end -0500 -0501 if isfield(rxnsToAdd,'rxnConfidenceScores') -0502 if numel(rxnsToAdd.rxnConfidenceScores)~=nRxns -0503 EM='rxnsToAdd.rxnConfidenceScores must have the same number of elements as rxnsToAdd.rxns'; -0504 dispEM(EM); -0505 end -0506 %Fill with standard if it doesn't exist -0507 if ~isfield(newModel,'rxnConfidenceScores') -0508 newModel.rxnConfidenceScores=NaN(nOldRxns,1); -0509 EM='Adding reactions with confidence scores without such information. All existing reactions will have confidence scores as NaNs'; -0510 dispEM(EM,false); -0511 end -0512 newModel.rxnConfidenceScores=[newModel.rxnConfidenceScores;rxnsToAdd.rxnConfidenceScores(:)]; -0513 else -0514 %Fill with standard if it doesn't exist -0515 if isfield(newModel,'rxnConfidenceScores') -0516 newModel.rxnConfidenceScores=[newModel.rxnConfidenceScores;NaN(nRxns,1)]; -0517 end -0518 end -0519 -0520 -0521 %***Start parsing the equations and adding the info to the S matrix The -0522 %mets are matched to model.mets -0523 if eqnType==1 -0524 [I, J]=ismember(mets,model.mets); -0525 if ~all(I) -0526 if allowNewMets==true | isstr(allowNewMets) -0527 %Add the new mets -0528 metsToAdd.mets=mets(~I); -0529 metsToAdd.metNames=metsToAdd.mets; -0530 metsToAdd.compartments=compartment; -0531 if isstr(allowNewMets) -0532 newModel=addMets(newModel,metsToAdd,true,allowNewMets); -0533 else -0534 newModel=addMets(newModel,metsToAdd,true); -0535 end -0536 else -0537 EM='One or more equations contain metabolites that are not in model.mets. Set allowNewMets to true to allow this function to add metabolites or use addMets to add them before calling this function'; -0538 dispEM(EM); -0539 end -0540 end -0541 %Calculate the indexes of the metabolites and add the info -0542 metIndexes=J; -0543 metIndexes(~I)=numel(newModel.mets)-sum(~I)+1:numel(newModel.mets); -0544 end -0545 -0546 %Do some stuff that is the same for eqnType=2 and eqnType=3 -0547 if eqnType==2 || eqnType==3 -0548 %For later.. -0549 t2=strcat(model.metNames,'***',model.comps(model.metComps)); -0550 end -0551 -0552 %The mets are matched to model.metNames and assigned to "compartment" -0553 if eqnType==2 -0554 %%Check that the metabolite names aren't present in the same -0555 %%compartment. -0556 %Not the neatest way maybe.. -0557 t1=strcat(mets,'***',compartment); -0558 [I, J]=ismember(t1,t2); -0559 -0560 if ~all(I) -0561 if allowNewMets==true | isstr(allowNewMets) -0562 %Add the new mets -0563 metsToAdd.metNames=mets(~I); -0564 metsToAdd.compartments=compartment; -0565 if isstr(allowNewMets) -0566 newModel=addMets(newModel,metsToAdd,true,allowNewMets); -0567 else -0568 newModel=addMets(newModel,metsToAdd,true); -0569 end -0570 else -0571 EM='One or more equations contain metabolites that are not in model.mets. Set allowNewMets to true to allow this function to add metabolites or use addMets to add them before calling this function'; -0572 dispEM(EM); -0573 end -0574 end -0575 -0576 %Calculate the indexes of the metabolites -0577 metIndexes=J; -0578 metIndexes(~I)=numel(newModel.mets)-sum(~I)+1:numel(newModel.mets); -0579 end -0580 -0581 %The equations are on the form metNames[compName] -0582 if eqnType==3 -0583 %Parse the metabolite names -0584 metNames=cell(numel(mets),1); -0585 compartments=metNames; -0586 for i=1:numel(mets) -0587 starts=max(strfind(mets{i},'[')); -0588 ends=max(strfind(mets{i},']')); -0589 -0590 %Check that the formatting is correct -0591 if isempty(starts) || isempty(ends) || ends<numel(mets{i}) -0592 EM=['The metabolite ' mets{i} ' is not correctly formatted for eqnType=3']; -0593 dispEM(EM); -0594 end -0595 -0596 %Check that the compartment is correct -0597 compartments{i}=mets{i}(starts+1:ends-1); -0598 I=ismember(compartments(i),newModel.comps); -0599 if ~I -0600 EM=['The metabolite ' mets{i} ' has a compartment that is not in model.comps']; -0601 dispEM(EM); -0602 end -0603 metNames{i}=mets{i}(1:starts-1); -0604 end -0605 -0606 %Check if the metabolite exists already -0607 t1=strcat(metNames,'***',compartments); -0608 [I, J]=ismember(t1,t2); -0609 -0610 if ~all(I) -0611 if allowNewMets==true | isstr(allowNewMets) -0612 %Add the new mets -0613 metsToAdd.metNames=metNames(~I); -0614 metsToAdd.compartments=compartments(~I); -0615 if isstr(allowNewMets) -0616 newModel=addMets(newModel,metsToAdd,true,allowNewMets); -0617 else -0618 newModel=addMets(newModel,metsToAdd,true); -0619 end -0620 else -0621 EM='One or more equations contain metabolites that are not in model.metNames. Set allowNewMets to true to allow this function to add metabolites or use addMets to add them before calling this function'; -0622 dispEM(EM); -0623 end -0624 end -0625 -0626 %Calculate the indexes of the metabolites -0627 metIndexes=J; -0628 metIndexes(~I)=numel(newModel.mets)-sum(~I)+1:numel(newModel.mets); -0629 end -0630 -0631 %Add the info to the stoichiometric matrix -0632 newModel.S=[newModel.S sparse(size(newModel.S,1),nRxns)]; -0633 -0634 for i=1:nRxns -0635 newModel.S(metIndexes,nOldRxns+i)=S(:,i); -0636 %Parse the grRules and check whether all genes in grRules appear in -0637 %genes -0638 if isfield(newModel,'grRules') -0639 rule=newModel.grRules{nOldRxns+i}; -0640 rule=strrep(rule,'(',''); -0641 rule=strrep(rule,')',''); -0642 rule=strrep(rule,' or ',' '); -0643 rule=strrep(rule,' and ',' '); -0644 genes=regexp(rule,' ','split'); -0645 [I, J]=ismember(genes,newModel.genes); -0646 if ~all(I) && any(rule) -0647 EM=['Not all genes for reaction ' rxnsToAdd.rxns{i} ' were found in model.genes. If needed, add genes with addGenesRaven before calling this function, or set the ''allowNewGenes'' flag to true']; -0648 dispEM(EM); -0649 end -0650 end -0651 end -0652 -0653 %Make temporary minimal model structure with only new rxns, to parse to -0654 %standardizeGrRules -0655 newRxnsModel.genes=newModel.genes; -0656 newRxnsModel.grRules=newModel.grRules(length(model.rxns)+1:end); -0657 newRxnsModel.rxns=newModel.rxns(length(model.rxns)+1:end); -0658 -0659 %Fix grRules and reconstruct rxnGeneMat -0660 [grRules,rxnGeneMat] = standardizeGrRules(newRxnsModel,true); -0661 newModel.rxnGeneMat = [newModel.rxnGeneMat; rxnGeneMat]; -0662 newModel.grRules = [newModel.grRules(1:nOldRxns); grRules]; -0663 end +0476 end +0477 +0478 if isfield(rxnsToAdd,'pwys') +0479 rxnsToAdd.pwys=convertCharArray(rxnsToAdd.pwys); +0480 if numel(rxnsToAdd.pwys)~=nRxns +0481 EM='rxnsToAdd.pwys must have the same number of elements as rxnsToAdd.rxns'; +0482 dispEM(EM); +0483 end +0484 %Fill with standard if it doesn't exist +0485 if ~isfield(newModel,'pwys') +0486 newModel.pwys=largeFiller; +0487 end +0488 newModel.pwys=[newModel.pwys;rxnsToAdd.pwys(:)]; +0489 else +0490 %Fill with standard if it doesn't exist +0491 if isfield(newModel,'pwys') +0492 newModel.pwys=[newModel.pwys;filler]; +0493 end +0494 end +0495 +0496 if isfield(rxnsToAdd,'rxnConfidenceScores') +0497 if numel(rxnsToAdd.rxnConfidenceScores)~=nRxns +0498 EM='rxnsToAdd.rxnConfidenceScores must have the same number of elements as rxnsToAdd.rxns'; +0499 dispEM(EM); +0500 end +0501 %Fill with standard if it doesn't exist +0502 if ~isfield(newModel,'rxnConfidenceScores') +0503 newModel.rxnConfidenceScores=NaN(nOldRxns,1); +0504 EM='Adding reactions with confidence scores without such information. All existing reactions will have confidence scores as NaNs'; +0505 dispEM(EM,false); +0506 end +0507 newModel.rxnConfidenceScores=[newModel.rxnConfidenceScores;rxnsToAdd.rxnConfidenceScores(:)]; +0508 else +0509 %Fill with standard if it doesn't exist +0510 if isfield(newModel,'rxnConfidenceScores') +0511 newModel.rxnConfidenceScores=[newModel.rxnConfidenceScores;NaN(nRxns,1)]; +0512 end +0513 end +0514 +0515 +0516 %***Start parsing the equations and adding the info to the S matrix The +0517 %mets are matched to model.mets +0518 if eqnType==1 +0519 [I, J]=ismember(mets,model.mets); +0520 if ~all(I) +0521 if allowNewMets==true | isstr(allowNewMets) +0522 %Add the new mets +0523 metsToAdd.mets=mets(~I); +0524 metsToAdd.metNames=metsToAdd.mets; +0525 metsToAdd.compartments=compartment; +0526 if isstr(allowNewMets) +0527 newModel=addMets(newModel,metsToAdd,true,allowNewMets); +0528 else +0529 newModel=addMets(newModel,metsToAdd,true); +0530 end +0531 else +0532 EM='One or more equations contain metabolites that are not in model.mets. Set allowNewMets to true to allow this function to add metabolites or use addMets to add them before calling this function'; +0533 dispEM(EM); +0534 end +0535 end +0536 %Calculate the indexes of the metabolites and add the info +0537 metIndexes=J; +0538 metIndexes(~I)=numel(newModel.mets)-sum(~I)+1:numel(newModel.mets); +0539 end +0540 +0541 %Do some stuff that is the same for eqnType=2 and eqnType=3 +0542 if eqnType==2 || eqnType==3 +0543 %For later.. +0544 t2=strcat(model.metNames,'***',model.comps(model.metComps)); +0545 end +0546 +0547 %The mets are matched to model.metNames and assigned to "compartment" +0548 if eqnType==2 +0549 %%Check that the metabolite names aren't present in the same +0550 %%compartment. +0551 %Not the neatest way maybe.. +0552 t1=strcat(mets,'***',compartment); +0553 [I, J]=ismember(t1,t2); +0554 +0555 if ~all(I) +0556 if allowNewMets==true | isstr(allowNewMets) +0557 %Add the new mets +0558 metsToAdd.metNames=mets(~I); +0559 metsToAdd.compartments=compartment; +0560 if isstr(allowNewMets) +0561 newModel=addMets(newModel,metsToAdd,true,allowNewMets); +0562 else +0563 newModel=addMets(newModel,metsToAdd,true); +0564 end +0565 else +0566 EM='One or more equations contain metabolites that are not in model.mets. Set allowNewMets to true to allow this function to add metabolites or use addMets to add them before calling this function'; +0567 dispEM(EM); +0568 end +0569 end +0570 +0571 %Calculate the indexes of the metabolites +0572 metIndexes=J; +0573 metIndexes(~I)=numel(newModel.mets)-sum(~I)+1:numel(newModel.mets); +0574 end +0575 +0576 %The equations are on the form metNames[compName] +0577 if eqnType==3 +0578 %Parse the metabolite names +0579 metNames=cell(numel(mets),1); +0580 compartments=metNames; +0581 for i=1:numel(mets) +0582 starts=max(strfind(mets{i},'[')); +0583 ends=max(strfind(mets{i},']')); +0584 +0585 %Check that the formatting is correct +0586 if isempty(starts) || isempty(ends) || ends<numel(mets{i}) +0587 EM=['The metabolite ' mets{i} ' is not correctly formatted for eqnType=3']; +0588 dispEM(EM); +0589 end +0590 +0591 %Check that the compartment is correct +0592 compartments{i}=mets{i}(starts+1:ends-1); +0593 I=ismember(compartments(i),newModel.comps); +0594 if ~I +0595 EM=['The metabolite ' mets{i} ' has a compartment that is not in model.comps']; +0596 dispEM(EM); +0597 end +0598 metNames{i}=mets{i}(1:starts-1); +0599 end +0600 +0601 %Check if the metabolite exists already +0602 t1=strcat(metNames,'***',compartments); +0603 [I, J]=ismember(t1,t2); +0604 +0605 if ~all(I) +0606 if allowNewMets==true | isstr(allowNewMets) +0607 %Add the new mets +0608 metsToAdd.metNames=metNames(~I); +0609 metsToAdd.compartments=compartments(~I); +0610 if isstr(allowNewMets) +0611 newModel=addMets(newModel,metsToAdd,true,allowNewMets); +0612 else +0613 newModel=addMets(newModel,metsToAdd,true); +0614 end +0615 else +0616 EM='One or more equations contain metabolites that are not in model.metNames. Set allowNewMets to true to allow this function to add metabolites or use addMets to add them before calling this function'; +0617 dispEM(EM); +0618 end +0619 end +0620 +0621 %Calculate the indexes of the metabolites +0622 metIndexes=J; +0623 metIndexes(~I)=numel(newModel.mets)-sum(~I)+1:numel(newModel.mets); +0624 end +0625 +0626 %Add the info to the stoichiometric matrix +0627 newModel.S=[newModel.S sparse(size(newModel.S,1),nRxns)]; +0628 +0629 for i=1:nRxns +0630 newModel.S(metIndexes,nOldRxns+i)=S(:,i); +0631 %Parse the grRules and check whether all genes in grRules appear in +0632 %genes +0633 if isfield(newModel,'grRules') +0634 rule=newModel.grRules{nOldRxns+i}; +0635 rule=strrep(rule,'(',''); +0636 rule=strrep(rule,')',''); +0637 rule=strrep(rule,' or ',' '); +0638 rule=strrep(rule,' and ',' '); +0639 genes=regexp(rule,' ','split'); +0640 [I, J]=ismember(genes,newModel.genes); +0641 if ~all(I) && any(rule) +0642 EM=['Not all genes for reaction ' rxnsToAdd.rxns{i} ' were found in model.genes. If needed, add genes with addGenesRaven before calling this function, or set the ''allowNewGenes'' flag to true']; +0643 dispEM(EM); +0644 end +0645 end +0646 end +0647 +0648 %Make temporary minimal model structure with only new rxns, to parse to +0649 %standardizeGrRules +0650 newRxnsModel.genes=newModel.genes; +0651 newRxnsModel.grRules=newModel.grRules(length(model.rxns)+1:end); +0652 newRxnsModel.rxns=newModel.rxns(length(model.rxns)+1:end); +0653 +0654 %Fix grRules and reconstruct rxnGeneMat +0655 [grRules,rxnGeneMat] = standardizeGrRules(newRxnsModel,true); +0656 newModel.rxnGeneMat = [newModel.rxnGeneMat; rxnGeneMat]; +0657 newModel.grRules = [newModel.grRules(1:nOldRxns); grRules]; +0658 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/addRxnsGenesMets.html b/doc/core/addRxnsGenesMets.html index 1d9a0e01..a5ce32c0 100644 --- a/doc/core/addRxnsGenesMets.html +++ b/doc/core/addRxnsGenesMets.html @@ -33,8 +33,8 @@

    DESCRIPTION ^DESCRIPTION ^DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • addMets addMets
  • addRxns addRxns
  • constructEquations constructEquations
  • convertCharArray convertCharArray
  • dispEM dispEM
  • This function is called by: @@ -90,8 +92,8 @@

    SOURCE CODE ^% 0006 % model draft model where reactions should be copied to 0007 % sourceModel model where reactions and metabolites are sourced from -0008 % rxns cell array with reaction IDs (from source model) -0009 % string allowed if only one reaction is added +0008 % rxns cell array with reaction IDs (from source model). Can also +0009 % be string if only one reaction is added 0010 % addGene three options: 0011 % false no genes are annotated to the new reactions 0012 % true grRules ared copied from the sourceModel and @@ -101,159 +103,162 @@

    SOURCE CODE ^% array, and any new genes are added when 0017 % required 0018 % (opt, default false) -0019 % rxnNote string explaining why reactions were copied to model, -0020 % is included as newModel.rxnNotes (opt, default -0021 % 'Added via addRxnsAndMets()') -0022 % confidence double specifying confidence score for all reactions. -0023 % 4: biochemical data: direct evidence from enzymes -0024 % assays -0025 % 3: genetic data: knockout/-in or overexpression -0026 % analysis -0027 % 2: physiological data: indirect evidence, e.g. -0028 % secretion products or defined medium requirement -0029 % sequence data: genome annotation -0030 % 1: modeling data: required for functional model, -0031 % hypothetical reaction -0032 % 0: no evidence -0033 % following doi:10.1038/nprot.2009.203 (opt, default 0) -0034 % -0035 % newModel an updated model structure +0019 % rxnNote cell array with strings explaining why reactions were copied +0020 % to the model, to be included as newModel.rxnNotes. Can also +0021 % be string if same rxnNotes should be added for each new +0022 % reaction, or only one reaction is to be added (opt, default +0023 % 'Added via addRxnsAndMets()') +0024 % confidence integer specifying confidence score for all reactions. +0025 % 4: biochemical data: direct evidence from enzymes +0026 % assays +0027 % 3: genetic data: knockout/-in or overexpression +0028 % analysis +0029 % 2: physiological data: indirect evidence, e.g. +0030 % secretion products or defined medium requirement +0031 % sequence data: genome annotation +0032 % 1: modeling data: required for functional model, +0033 % hypothetical reaction +0034 % 0: no evidence +0035 % following doi:10.1038/nprot.2009.203 (opt, default 0) 0036 % -0037 % This function only works if the draft model and source model follow -0038 % the same metabolite and compartment naming convention. Metabolites are -0039 % only matched by metaboliteName[compartment]. Useful if one wants to copy -0040 % additional reactions from source to draft after getModelFromHomology was -0041 % used involving the same models. -0042 % -0043 % Usage: newModel=addRxnsGenesMets(model,sourceModel,rxns,addGene,rxnNote,confidence) -0044 -0045 if nargin<6 -0046 confidence=0; -0047 end -0048 if nargin<5 -0049 rxnNote='Added via addRxnsGenesMets()'; -0050 end -0051 if nargin<4 -0052 addGene=false; -0053 end -0054 -0055 %If the supplied object is a character array, then convert it to a cell -0056 %array -0057 if ischar(rxns) -0058 rxns={rxns}; -0059 end -0060 -0061 % Obtain indexes of reactions in source model -0062 [notNewRxn,oldRxn]=ismember(rxns,model.rxns); -0063 rxns=rxns(~notNewRxn); -0064 if isempty(rxns) -0065 error('All reactions are already in the model.'); -0066 elseif ~isempty(notNewRxn) -0067 fprintf('The following reactions were already present in the model and will not be added:\n') -0068 fprintf([strjoin(model.rxns(oldRxn(find(oldRxn))),'\n') '\n']) -0069 end -0070 -0071 [~, rxnIdx]=ismember(rxns,sourceModel.rxns); % Get rxnIDs -0072 if any(rxnIdx==0) -0073 error('Not all reaction IDs could be found in the source model') -0074 end -0075 -0076 % Add new metabolites -0077 metIdx=find(any(sourceModel.S(:,rxnIdx),2)); % Get metabolite IDs -0078 % Many of the metabolites in are already in the draft model, so only add -0079 % the new metabolites -0080 -0081 % Match by metNames[metComps]. First make these structures for each model. -0082 metCompsN =cellstr(num2str(model.metComps)); -0083 map=containers.Map(cellstr(num2str(transpose([1:length(model.comps)]))),model.comps); -0084 metCompsN = map.values(metCompsN); -0085 metCompsN = strcat(model.metNames,'[',metCompsN,']'); -0086 -0087 sourcemetCompsN=cellstr(num2str(sourceModel.metComps)); -0088 map=containers.Map(cellstr(num2str(transpose([1:length(sourceModel.comps)]))),sourceModel.comps); -0089 sourcemetCompsN = map.values(sourcemetCompsN); -0090 sourcemetCompsN=strcat(sourceModel.metNames,'[',sourcemetCompsN,']'); -0091 -0092 newMetCompsN=sourcemetCompsN(metIdx); -0093 notNewMet=newMetCompsN(ismember(newMetCompsN,metCompsN)); -0094 -0095 if ~isempty(notNewMet) -0096 fprintf('\nThe following metabolites were already present in the model and will not be added:\n') -0097 fprintf([strjoin(transpose(notNewMet),'\n') '\n']) -0098 end -0099 -0100 metIdx=metIdx(~ismember(sourcemetCompsN(metIdx),metCompsN)); -0101 -0102 if ~isempty(metIdx) -0103 fprintf('\nThe following metabolites will be added to the model:\n') -0104 fprintf([strjoin(transpose(sourcemetCompsN(metIdx)),'\n') '\n']) -0105 -0106 if isfield(sourceModel,'mets') -0107 metsToAdd.mets=sourceModel.mets(metIdx); -0108 end -0109 if isfield(sourceModel,'metNames') -0110 metsToAdd.metNames=sourceModel.metNames(metIdx); -0111 end -0112 if isfield(sourceModel,'metFormulas') -0113 metsToAdd.metFormulas=sourceModel.metFormulas(metIdx); -0114 end -0115 if isfield(sourceModel,'metCharge') -0116 metsToAdd.metCharge=sourceModel.metCharge(metIdx); -0117 end -0118 if isfield(sourceModel,'metMiriams') -0119 metsToAdd.metMiriams=sourceModel.metMiriams(metIdx); -0120 end -0121 if isfield(sourceModel,'metFormulas') -0122 metsToAdd.metFormulas=sourceModel.metFormulas(metIdx); -0123 end -0124 if isfield(sourceModel,'inchis') -0125 metsToAdd.inchis=sourceModel.inchis(metIdx); -0126 end -0127 -0128 metsToAdd.compartments=strtrim(cellstr(num2str(sourceModel.metComps(metIdx)))); % Convert from compartment string to compartment number -0129 [~,idx]=ismember(metsToAdd.compartments,strsplit(num2str(1:length(sourceModel.comps)))); % Match compartment number to compartment abbreviation -0130 metsToAdd.compartments=sourceModel.comps(idx); % Fill in compartment abbreviations +0037 % newModel an updated model structure +0038 % +0039 % This function only works if the draft model and source model follow +0040 % the same metabolite and compartment naming convention. Metabolites are +0041 % only matched by metaboliteName[compartment]. Useful if one wants to copy +0042 % additional reactions from source to draft after getModelFromHomology was +0043 % used involving the same models. +0044 % +0045 % Usage: newModel=addRxnsGenesMets(model,sourceModel,rxns,addGene,rxnNote,confidence) +0046 +0047 if nargin<6 +0048 confidence=0; +0049 end +0050 rxns=convertCharArray(rxns); +0051 if nargin<5 +0052 rxnNote={'Added via addRxnsGenesMets()'}; +0053 else +0054 rxnNote=convertCharArray(rxnNote); +0055 if numel(rxnNote)==1 && numel(rxns)>1 +0056 rxnNoteArray=cell(numel(rxns),1); +0057 rxnNoteArray{:}=rxnNote; +0058 rxnNote=rxnNoteArray; +0059 end +0060 end +0061 if nargin<4 +0062 addGene=false; +0063 end +0064 +0065 % Obtain indexes of reactions in source model +0066 [notNewRxn,oldRxn]=ismember(rxns,model.rxns); +0067 rxns=rxns(~notNewRxn); +0068 if isempty(rxns) +0069 error('All reactions are already in the model.'); +0070 elseif ~isempty(notNewRxn) +0071 fprintf('The following reactions were already present in the model and will not be added:\n') +0072 fprintf([strjoin(model.rxns(oldRxn(find(oldRxn))),'\n') '\n']) +0073 end +0074 +0075 [~, rxnIdx]=ismember(rxns,sourceModel.rxns); % Get rxnIDs +0076 if any(rxnIdx==0) +0077 error('Not all reaction IDs could be found in the source model') +0078 end +0079 +0080 % Add new metabolites +0081 metIdx=find(any(sourceModel.S(:,rxnIdx),2)); % Get metabolite IDs +0082 % Many of the metabolites in are already in the draft model, so only add +0083 % the new metabolites +0084 +0085 % Match by metNames[metComps]. First make these structures for each model. +0086 metCompsN =cellstr(num2str(model.metComps)); +0087 map=containers.Map(cellstr(num2str(transpose([1:length(model.comps)]))),model.comps); +0088 metCompsN = map.values(metCompsN); +0089 metCompsN = strcat(model.metNames,'[',metCompsN,']'); +0090 +0091 sourcemetCompsN=cellstr(num2str(sourceModel.metComps)); +0092 map=containers.Map(cellstr(num2str(transpose([1:length(sourceModel.comps)]))),sourceModel.comps); +0093 sourcemetCompsN = map.values(sourcemetCompsN); +0094 sourcemetCompsN=strcat(sourceModel.metNames,'[',sourcemetCompsN,']'); +0095 +0096 newMetCompsN=sourcemetCompsN(metIdx); +0097 notNewMet=newMetCompsN(ismember(newMetCompsN,metCompsN)); +0098 +0099 if ~isempty(notNewMet) +0100 fprintf('\nThe following metabolites were already present in the model and will not be added:\n') +0101 fprintf([strjoin(transpose(notNewMet),'\n') '\n']) +0102 end +0103 +0104 metIdx=metIdx(~ismember(sourcemetCompsN(metIdx),metCompsN)); +0105 +0106 if ~isempty(metIdx) +0107 fprintf('\nThe following metabolites will be added to the model:\n') +0108 fprintf([strjoin(transpose(sourcemetCompsN(metIdx)),'\n') '\n']) +0109 +0110 if isfield(sourceModel,'mets') +0111 metsToAdd.mets=sourceModel.mets(metIdx); +0112 end +0113 if isfield(sourceModel,'metNames') +0114 metsToAdd.metNames=sourceModel.metNames(metIdx); +0115 end +0116 if isfield(sourceModel,'metFormulas') +0117 metsToAdd.metFormulas=sourceModel.metFormulas(metIdx); +0118 end +0119 if isfield(sourceModel,'metCharge') +0120 metsToAdd.metCharge=sourceModel.metCharge(metIdx); +0121 end +0122 if isfield(sourceModel,'metMiriams') +0123 metsToAdd.metMiriams=sourceModel.metMiriams(metIdx); +0124 end +0125 if isfield(sourceModel,'metFormulas') +0126 metsToAdd.metFormulas=sourceModel.metFormulas(metIdx); +0127 end +0128 if isfield(sourceModel,'inchis') +0129 metsToAdd.inchis=sourceModel.inchis(metIdx); +0130 end 0131 -0132 model=addMets(model,metsToAdd); -0133 end -0134 fprintf('\nNumber of metabolites added to the model:\n') -0135 fprintf([num2str(numel(metIdx)),'\n']) -0136 -0137 % Add new genes -0138 if ~islogical(addGene) | addGene ~= false -0139 if ischar(addGene) -0140 rxnToAdd.grRules={addGene}; -0141 elseif iscell(addGene) -0142 rxnToAdd.grRules=addGene(~notNewRxn); -0143 else -0144 rxnToAdd.grRules=sourceModel.grRules(rxnIdx); % Get the relevant grRules -0145 end -0146 end -0147 % Add new reactions -0148 rxnToAdd.equations=constructEquations(sourceModel,rxnIdx); -0149 rxnToAdd.rxnNames=sourceModel.rxnNames(rxnIdx); -0150 rxnToAdd.rxns=sourceModel.rxns(rxnIdx); -0151 rxnToAdd.lb=sourceModel.lb(rxnIdx); -0152 rxnToAdd.ub=sourceModel.ub(rxnIdx); -0153 rxnToAdd.rxnNotes=cell(1,numel(rxnToAdd.rxns)); -0154 rxnToAdd.rxnNotes(:)={rxnNote}; -0155 rxnToAdd.rxnConfidenceScores=NaN(1,numel(rxnToAdd.rxns)); -0156 if ~isnumeric(confidence) -0157 EM='confidence score must be numeric'; -0158 dispEM(EM, true); -0159 end -0160 rxnToAdd.rxnConfidenceScores(:)=confidence; -0161 if isfield(sourceModel,'subSystems') -0162 rxnToAdd.subSystems=sourceModel.subSystems(rxnIdx); -0163 end -0164 if isfield(sourceModel,'eccodes') -0165 rxnToAdd.eccodes=sourceModel.eccodes(rxnIdx); +0132 metsToAdd.compartments=strtrim(cellstr(num2str(sourceModel.metComps(metIdx)))); % Convert from compartment string to compartment number +0133 [~,idx]=ismember(metsToAdd.compartments,strsplit(num2str(1:length(sourceModel.comps)))); % Match compartment number to compartment abbreviation +0134 metsToAdd.compartments=sourceModel.comps(idx); % Fill in compartment abbreviations +0135 +0136 model=addMets(model,metsToAdd); +0137 end +0138 fprintf('\nNumber of metabolites added to the model:\n') +0139 fprintf([num2str(numel(metIdx)),'\n']) +0140 +0141 % Add new genes +0142 if ~islogical(addGene) | addGene ~= false +0143 if ischar(addGene) +0144 rxnToAdd.grRules={addGene}; +0145 elseif iscell(addGene) +0146 rxnToAdd.grRules=addGene(~notNewRxn); +0147 else +0148 rxnToAdd.grRules=sourceModel.grRules(rxnIdx); % Get the relevant grRules +0149 end +0150 end +0151 % Add new reactions +0152 rxnToAdd.equations=constructEquations(sourceModel,rxnIdx); +0153 rxnToAdd.rxnNames=sourceModel.rxnNames(rxnIdx); +0154 rxnToAdd.rxns=sourceModel.rxns(rxnIdx); +0155 rxnToAdd.lb=sourceModel.lb(rxnIdx); +0156 rxnToAdd.ub=sourceModel.ub(rxnIdx); +0157 rxnToAdd.rxnNotes(:)=rxnNote(~notNewRxn); +0158 rxnToAdd.rxnConfidenceScores=NaN(1,numel(rxnToAdd.rxns)); +0159 if ~isnumeric(confidence) +0160 EM='confidence score must be numeric'; +0161 dispEM(EM, true); +0162 end +0163 rxnToAdd.rxnConfidenceScores(:)=confidence; +0164 if isfield(sourceModel,'subSystems') +0165 rxnToAdd.subSystems=sourceModel.subSystems(rxnIdx); 0166 end -0167 model=addRxns(model,rxnToAdd,3,'',false,true); -0168 -0169 fprintf('\nNumber of reactions added to the model:\n') -0170 fprintf([num2str(numel(rxnIdx)),'\n']) -0171 end +0167 if isfield(sourceModel,'eccodes') +0168 rxnToAdd.eccodes=sourceModel.eccodes(rxnIdx); +0169 end +0170 model=addRxns(model,rxnToAdd,3,'',false,true); +0171 +0172 fprintf('\nNumber of reactions added to the model:\n') +0173 fprintf([num2str(numel(rxnIdx)),'\n']) +0174 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/addTransport.html b/doc/core/addTransport.html index 4f1d4aba..4c81dae1 100644 --- a/doc/core/addTransport.html +++ b/doc/core/addTransport.html @@ -57,7 +57,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • addMets addMets
  • convertCharArray convertCharArray
  • dispEM dispEM
  • generateNewIds generateNewIds
  • This function is called by: @@ -93,157 +93,151 @@

    SOURCE CODE ^% Usage: [model, addedRxns]=addTransport(model,fromComp,toComps,metNames,... 0026 % isRev,onlyToExisting,prefix) 0027 -0028 if iscell(fromComp) -0029 fromComp=fromComp{1}; -0030 end -0031 [I, fromID]=ismember(model.comps,fromComp); -0032 fromID=find(fromID); -0033 if sum(I)~=1 -0034 EM='fromComps must have exactly one match in model.comps'; -0035 dispEM(EM); -0036 end -0037 if ischar(toComps) -0038 toComps={toComps}; -0039 end -0040 [I, toIDs]=ismember(toComps,model.comps); -0041 if ~all(I) -0042 EM='All compartments in toComps must have a match in model.comps'; -0043 dispEM(EM); -0044 end -0045 if nargin<4 -0046 %Find all metabolites in fromComp -0047 metNames=model.metNames(model.metComps==fromID); -0048 end -0049 -0050 %If an empty set was given -0051 if isempty(metNames) -0052 %Find all metabolites in fromComp -0053 metNames=model.metNames(ismember(model.metComps,model.comps(fromID))); -0054 end -0055 -0056 if nargin<5 -0057 isRev=true; -0058 end -0059 if nargin<6 -0060 onlyToExisting=true; +0028 fromComp=char(fromComp); +0029 [I, fromID]=ismember(model.comps,fromComp); +0030 fromID=find(fromID); +0031 if sum(I)~=1 +0032 EM='fromComps must have exactly one match in model.comps'; +0033 dispEM(EM); +0034 end +0035 toComps=convertCharArray(toComps); +0036 [I, toIDs]=ismember(toComps,model.comps); +0037 if ~all(I) +0038 EM='All compartments in toComps must have a match in model.comps'; +0039 dispEM(EM); +0040 end +0041 if nargin<4 +0042 %Find all metabolites in fromComp +0043 metNames=model.metNames(model.metComps==fromID); +0044 elseif isempty(metNames) +0045 %Find all metabolites in fromComp +0046 metNames=model.metNames(ismember(model.metComps,model.comps(fromID))); +0047 else +0048 metNames=convertCharArray(metNames); +0049 end +0050 +0051 if nargin<5 +0052 isRev=true; +0053 end +0054 if nargin<6 +0055 onlyToExisting=true; +0056 end +0057 if nargin<7 +0058 prefix='tr_'; +0059 else +0060 prefix=char(prefix); 0061 end -0062 if nargin<7 -0063 prefix='tr_'; -0064 end -0065 -0066 %Check that the names are unique -0067 if ischar(metNames) -0068 metNames={metNames}; -0069 end -0070 if numel(unique(metNames))~=numel(metNames) -0071 dispEM('Not all metabolite names are unique'); -0072 end -0073 -0074 %Get the indexes of the mets in fromComp -0075 I=find(model.metComps==fromID); -0076 [J, K]=ismember(metNames,model.metNames(I)); -0077 if ~all(J) -0078 EM='Not all metabolites in metNames exist in fromComp'; -0079 dispEM(EM); -0080 end -0081 fromMets=I(K); %These are the ids of the metabolites to transport. The order corresponds to metNames -0082 addedRxns={}; -0083 %Loop through and add for each compartment in toComps -0084 for i=1:numel(toComps) -0085 fromMetsInComp=fromMets; %If onlyToExisting==true then not all mets are transported to each compartment -0086 %Get the indexes of the mets in the compartment -0087 I=find(model.metComps==toIDs(i)); -0088 [J, K]=ismember(metNames,model.metNames(I)); -0089 if onlyToExisting==true || all(J) -0090 toMets=I(K(J)); %Only look at the existing ones -0091 fromMetsInComp=fromMetsInComp(J); -0092 else -0093 %This is if not all metabolites exist in the target compartment, -0094 %and they should be added -0095 metsToAdd.metNames=metNames(J==0); -0096 metsToAdd.compartments=toComps{i}; -0097 model=addMets(model,metsToAdd); -0098 -0099 %Redo the mapping when all mets are there. A bit lazy, but it's -0100 %fast anyways -0101 I=find(model.metComps==toIDs(i)); -0102 [~, K]=ismember(metNames,model.metNames(I)); -0103 toMets=I(K); %All are guaranteed to be found now -0104 end +0062 +0063 %Check that the names are unique +0064 if numel(unique(metNames))~=numel(metNames) +0065 dispEM('Not all metabolite names are unique'); +0066 end +0067 +0068 %Get the indexes of the mets in fromComp +0069 I=find(model.metComps==fromID); +0070 [J, K]=ismember(metNames,model.metNames(I)); +0071 if ~all(J) +0072 EM='Not all metabolites in metNames exist in fromComp'; +0073 dispEM(EM); +0074 end +0075 fromMets=I(K); %These are the ids of the metabolites to transport. The order corresponds to metNames +0076 addedRxns={}; +0077 %Loop through and add for each compartment in toComps +0078 for i=1:numel(toComps) +0079 fromMetsInComp=fromMets; %If onlyToExisting==true then not all mets are transported to each compartment +0080 %Get the indexes of the mets in the compartment +0081 I=find(model.metComps==toIDs(i)); +0082 [J, K]=ismember(metNames,model.metNames(I)); +0083 if onlyToExisting==true || all(J) +0084 toMets=I(K(J)); %Only look at the existing ones +0085 fromMetsInComp=fromMetsInComp(J); +0086 else +0087 %This is if not all metabolites exist in the target compartment, +0088 %and they should be added +0089 metsToAdd.metNames=metNames(J==0); +0090 metsToAdd.compartments=toComps{i}; +0091 model=addMets(model,metsToAdd); +0092 +0093 %Redo the mapping when all mets are there. A bit lazy, but it's +0094 %fast anyways +0095 I=find(model.metComps==toIDs(i)); +0096 [~, K]=ismember(metNames,model.metNames(I)); +0097 toMets=I(K); %All are guaranteed to be found now +0098 end +0099 +0100 %Construct the S matrix +0101 nRxns=numel(fromMetsInComp); +0102 newS=zeros(numel(model.mets),nRxns); +0103 newS(sub2ind(size(newS),fromMetsInComp(:),(1:nRxns)'))=-1; +0104 newS(sub2ind(size(newS),toMets(:),(1:nRxns)'))=1; 0105 -0106 %Construct the S matrix -0107 nRxns=numel(fromMetsInComp); -0108 newS=zeros(numel(model.mets),nRxns); -0109 newS(sub2ind(size(newS),fromMetsInComp(:),(1:nRxns)'))=-1; -0110 newS(sub2ind(size(newS),toMets(:),(1:nRxns)'))=1; -0111 -0112 %Add the reactions -0113 model.S=[model.S sparse(newS)]; -0114 if isfield(model.annotation,'defaultLB') -0115 lb = model.annotation.defaultLB; -0116 ub = model.annotation.defaultUB; -0117 else -0118 lb = -inf; -0119 ub = inf; -0120 end -0121 if isRev==true -0122 model.lb=[model.lb;ones(nRxns,1)*lb]; -0123 model.rev=[model.rev;ones(nRxns,1)]; -0124 else -0125 model.lb=[model.lb;zeros(nRxns,1)]; -0126 model.rev=[model.rev;zeros(nRxns,1)]; -0127 end -0128 model.ub=[model.ub;ones(nRxns,1)*ub]; -0129 model.c=[model.c;zeros(nRxns,1)]; -0130 -0131 %Add annotation -0132 filler=cell(nRxns,1); -0133 filler(:)={''}; -0134 addedRxnsID=generateNewIds(model,'rxns',prefix,nRxns); -0135 addedRxnsName=transpose(strcat(metNames, {' transport, '}, model.compNames(fromID), '-', model.compNames(toIDs(i)))); -0136 model.rxns=[model.rxns;addedRxnsID]; -0137 model.rxnNames=[model.rxnNames;addedRxnsName]; -0138 -0139 if isfield(model,'eccodes') -0140 model.eccodes=[model.eccodes;filler]; -0141 end -0142 if isfield(model,'subSystems') -0143 ssFiller=filler; -0144 if isRev==1 -0145 ssFiller(:)={{['Transport between ' fromComp ' and ' toComps{i}]}}; -0146 else -0147 ssFiller(:)={{['Transport from ' fromComp ' to ' toComps{i}]}}; -0148 end -0149 model.subSystems=[model.subSystems;ssFiller]; +0106 %Add the reactions +0107 model.S=[model.S sparse(newS)]; +0108 if isfield(model.annotation,'defaultLB') +0109 lb = model.annotation.defaultLB; +0110 ub = model.annotation.defaultUB; +0111 else +0112 lb = -inf; +0113 ub = inf; +0114 end +0115 if isRev==true +0116 model.lb=[model.lb;ones(nRxns,1)*lb]; +0117 model.rev=[model.rev;ones(nRxns,1)]; +0118 else +0119 model.lb=[model.lb;zeros(nRxns,1)]; +0120 model.rev=[model.rev;zeros(nRxns,1)]; +0121 end +0122 model.ub=[model.ub;ones(nRxns,1)*ub]; +0123 model.c=[model.c;zeros(nRxns,1)]; +0124 +0125 %Add annotation +0126 filler=cell(nRxns,1); +0127 filler(:)={''}; +0128 addedRxnsID=generateNewIds(model,'rxns',prefix,nRxns); +0129 addedRxnsName=transpose(strcat(metNames, {' transport, '}, model.compNames(fromID), '-', model.compNames(toIDs(i)))); +0130 model.rxns=[model.rxns;addedRxnsID]; +0131 model.rxnNames=[model.rxnNames;addedRxnsName]; +0132 +0133 if isfield(model,'eccodes') +0134 model.eccodes=[model.eccodes;filler]; +0135 end +0136 if isfield(model,'subSystems') +0137 ssFiller=filler; +0138 if isRev==1 +0139 ssFiller(:)={{['Transport between ' fromComp ' and ' toComps{i}]}}; +0140 else +0141 ssFiller(:)={{['Transport from ' fromComp ' to ' toComps{i}]}}; +0142 end +0143 model.subSystems=[model.subSystems;ssFiller]; +0144 end +0145 if isfield(model,'grRules') +0146 model.grRules=[model.grRules;filler]; +0147 end +0148 if isfield(model,'rxnFrom') +0149 model.rxnFrom=[model.rxnFrom;filler]; 0150 end -0151 if isfield(model,'grRules') -0152 model.grRules=[model.grRules;filler]; +0151 if isfield(model,'rxnMiriams') +0152 model.rxnMiriams=[model.rxnMiriams;cell(nRxns,1)]; 0153 end -0154 if isfield(model,'rxnFrom') -0155 model.rxnFrom=[model.rxnFrom;filler]; -0156 end -0157 if isfield(model,'rxnMiriams') -0158 model.rxnMiriams=[model.rxnMiriams;cell(nRxns,1)]; -0159 end -0160 if isfield(model,'rxnComps') -0161 model.rxnComps=[model.rxnComps;ones(nRxns,1)]; -0162 fprintf('NOTE: The added transport reactions will be added to the first compartment\n'); +0154 if isfield(model,'rxnComps') +0155 model.rxnComps=[model.rxnComps;ones(nRxns,1)]; +0156 fprintf('NOTE: The added transport reactions will be added to the first compartment\n'); +0157 end +0158 if isfield(model,'rxnGeneMat') +0159 model.rxnGeneMat=[model.rxnGeneMat;sparse(nRxns,numel(model.genes))]; +0160 end +0161 if isfield(model,'rxnNotes') +0162 model.rxnNotes=[model.rxnNotes;filler]; 0163 end -0164 if isfield(model,'rxnGeneMat') -0165 model.rxnGeneMat=[model.rxnGeneMat;sparse(nRxns,numel(model.genes))]; +0164 if isfield(model,'rxnReferences') +0165 model.rxnReferences=[model.rxnReferences;filler]; 0166 end -0167 if isfield(model,'rxnNotes') -0168 model.rxnNotes=[model.rxnNotes;filler]; +0167 if isfield(model,'rxnConfidenceScores') +0168 model.rxnConfidenceScores=[model.rxnConfidenceScores;ones(nRxns,1)]; 0169 end -0170 if isfield(model,'rxnReferences') -0171 model.rxnReferences=[model.rxnReferences;filler]; -0172 end -0173 if isfield(model,'rxnConfidenceScores') -0174 model.rxnConfidenceScores=[model.rxnConfidenceScores;ones(nRxns,1)]; -0175 end -0176 addedRxns = [addedRxns; addedRxnsID]; -0177 end -0178 end +0170 addedRxns = [addedRxns; addedRxnsID]; +0171 end +0172 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/buildEquation.html b/doc/core/buildEquation.html index 2cfe1941..af52df23 100644 --- a/doc/core/buildEquation.html +++ b/doc/core/buildEquation.html @@ -30,7 +30,7 @@

    DESCRIPTION ^
     buildEquation
        Construct single equation string for a given reaction
     
    -   mets            string array with metabolites involved in the reaction.
    +   mets            cell array with metabolites involved in the reaction.
        stoichCoeffs    vector with corresponding stoichiometric coeffs.
        isrev           logical indicating if the reaction is or not
                        reversible.
    @@ -43,7 +43,7 @@ 

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • dispEM dispEM
  • This function is called by: @@ -58,7 +58,7 @@

    SOURCE CODE ^% buildEquation 0003 % Construct single equation string for a given reaction 0004 % -0005 % mets string array with metabolites involved in the reaction. +0005 % mets cell array with metabolites involved in the reaction. 0006 % stoichCoeffs vector with corresponding stoichiometric coeffs. 0007 % isrev logical indicating if the reaction is or not 0008 % reversible. @@ -67,61 +67,56 @@

    SOURCE CODE ^% 0012 % Usage: equationString=buildEquation(mets,stoichCoeffs,isrev) 0013 -0014 if ~iscellstr(mets) && ~ischar(mets) -0015 EM = 'mets must be a cell array of strings'; -0016 dispEM(EM); -0017 else -0018 mets = cellstr(mets); -0019 end -0020 if ~isnumeric(stoichCoeffs) -0021 EM = 'stoichCoeffs must be a numeric vector'; -0022 dispEM(EM); -0023 elseif ~islogical(isrev) -0024 EM = 'isrev must be a logical'; -0025 dispEM(EM); -0026 elseif length(mets) ~= length(stoichCoeffs) -0027 EM = 'lengths of mets and stoichCoeffs should be the same'; -0028 dispEM(EM); -0029 end +0014 mets=convertCharArray(mets); +0015 if ~isnumeric(stoichCoeffs) +0016 EM = 'stoichCoeffs must be a numeric vector'; +0017 dispEM(EM); +0018 elseif ~islogical(isrev) +0019 EM = 'isrev must be a logical'; +0020 dispEM(EM); +0021 elseif length(mets) ~= length(stoichCoeffs) +0022 EM = 'lengths of mets and stoichCoeffs should be the same'; +0023 dispEM(EM); +0024 end +0025 +0026 %Reactant half: +0027 reactants = mets(stoichCoeffs<0); +0028 reactantsCoeffs = abs(stoichCoeffs(stoichCoeffs<0)); +0029 reactantsEqn = concatenateEquation(reactants,reactantsCoeffs); 0030 -0031 %Reactant half: -0032 reactants = mets(stoichCoeffs<0); -0033 reactantsCoeffs = abs(stoichCoeffs(stoichCoeffs<0)); -0034 reactantsEqn = concatenateEquation(reactants,reactantsCoeffs); +0031 %Product half: +0032 products = mets(stoichCoeffs>0); +0033 productsCoeffs = abs(stoichCoeffs(stoichCoeffs>0)); +0034 productsEqn = concatenateEquation(products,productsCoeffs); 0035 -0036 %Product half: -0037 products = mets(stoichCoeffs>0); -0038 productsCoeffs = abs(stoichCoeffs(stoichCoeffs>0)); -0039 productsEqn = concatenateEquation(products,productsCoeffs); -0040 -0041 %Full equation: -0042 if isrev -0043 equationString = [reactantsEqn ' <=> ' productsEqn]; -0044 else -0045 equationString = [reactantsEqn ' => ' productsEqn]; -0046 end -0047 -0048 end -0049 -0050 function eqn = concatenateEquation(mets,stoichCoeffs) -0051 %This function concatenates metabolites and stoich. coefficients to form -0052 %either the left or right side of the rxn equation -0053 eqn = ''; -0054 for i = 1:length(stoichCoeffs) -0055 if i == 1 -0056 plusString=''; -0057 else -0058 plusString=' + '; -0059 end -0060 stoich = stoichCoeffs(i); -0061 if stoich == 1 -0062 stoich = ''; -0063 else -0064 stoich = [num2str(stoich) ' ']; -0065 end -0066 eqn = [eqn plusString stoich mets{i}]; -0067 end -0068 end

    +0036 %Full equation: +0037 if isrev +0038 equationString = [reactantsEqn ' <=> ' productsEqn]; +0039 else +0040 equationString = [reactantsEqn ' => ' productsEqn]; +0041 end +0042 +0043 end +0044 +0045 function eqn = concatenateEquation(mets,stoichCoeffs) +0046 %This function concatenates metabolites and stoich. coefficients to form +0047 %either the left or right side of the rxn equation +0048 eqn = ''; +0049 for i = 1:length(stoichCoeffs) +0050 if i == 1 +0051 plusString=''; +0052 else +0053 plusString=' + '; +0054 end +0055 stoich = stoichCoeffs(i); +0056 if stoich == 1 +0057 stoich = ''; +0058 else +0059 stoich = [num2str(stoich) ' ']; +0060 end +0061 eqn = [eqn plusString stoich mets{i}]; +0062 end +0063 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/canConsume.html b/doc/core/canConsume.html index 47cf03b1..3e020b1a 100644 --- a/doc/core/canConsume.html +++ b/doc/core/canConsume.html @@ -45,7 +45,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • addExchangeRxns addExchangeRxns
  • convertCharArray convertCharArray
  • haveFlux haveFlux
  • This function is called by: @@ -71,11 +71,13 @@

    SOURCE CODE ^if nargin<2 0017 mets=model.mets; -0018 end -0019 -0020 [model, rxns]=addExchangeRxns(model,'in',mets); -0021 consumed=haveFlux(model,10^-5,rxns); -0022 end +0018 elseif ~islogical(mets) && ~isnumeric(mets) +0019 mets=convertCharArray(mets); +0020 end +0021 +0022 [model, rxns]=addExchangeRxns(model,'in',mets); +0023 consumed=haveFlux(model,10^-5,rxns); +0024 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/canProduce.html b/doc/core/canProduce.html index 823bfb08..9693b126 100644 --- a/doc/core/canProduce.html +++ b/doc/core/canProduce.html @@ -46,7 +46,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • addExchangeRxns addExchangeRxns
  • convertCharArray convertCharArray
  • haveFlux haveFlux
  • This function is called by: @@ -73,11 +73,13 @@

    SOURCE CODE ^if nargin<2 0018 mets=model.mets; -0019 end -0020 -0021 [model, rxns]=addExchangeRxns(model,'out',mets); -0022 produced=haveFlux(model,10^-5,rxns); -0023 end +0019 elseif ~islogical(mets) && ~isnumeric(mets) +0020 mets=convertCharArray(mets); +0021 end +0022 +0023 [model, rxns]=addExchangeRxns(model,'out',mets); +0024 produced=haveFlux(model,10^-5,rxns); +0025 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/changeGrRules.html b/doc/core/changeGrRules.html index b9938be9..7da325c9 100644 --- a/doc/core/changeGrRules.html +++ b/doc/core/changeGrRules.html @@ -48,7 +48,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • addGenesRaven addGenesRaven
  • convertCharArray convertCharArray
  • getIndexes getIndexes
  • standardizeGrRules standardizeGrRules
  • This function is called by: @@ -79,43 +79,38 @@

    SOURCE CODE ^end 0022 -0023 if isstr(rxns) -0024 rxns={rxns}; -0025 end -0026 -0027 if isstr(grRules) -0028 grRules={grRules}; -0029 end -0030 -0031 if ~(numel(grRules)==numel(rxns)) -0032 error('Number of rxns and grRules should be identical') -0033 end -0034 -0035 for i=1:length(rxns) -0036 % Add genes to model -0037 geneList=transpose(cell(unique(regexp(grRules{i},'[)(]*|( and )*|( or )*','split')))); % Extract individual, unique genes from the geneAssoc provided -0038 geneList=geneList(~cellfun(@isempty, geneList)); -0039 genesToAdd.genes=setdiff(geneList,model.genes); % Only keep the genes that are not yet part of the model.genes. -0040 if ~isempty(genesToAdd.genes) -0041 model=addGenesRaven(model,genesToAdd); % Add genes -0042 end -0043 -0044 % Find reaction and gene indices -0045 idx=getIndexes(model,rxns,'rxns'); -0046 end -0047 -0048 % Change gene associations -0049 if replace==true % Replace old gene associations -0050 model.grRules(idx)=grRules; -0051 else % Add gene associations, add new gene rules after 'OR'. -0052 model.grRules(idx)=strcat('(',model.grRules(idx),') or (',grRules,')'); -0053 end -0054 -0055 %Fix grRules and reconstruct rxnGeneMat -0056 [grRules,rxnGeneMat] = standardizeGrRules(model,true); -0057 model.grRules = grRules; -0058 model.rxnGeneMat = rxnGeneMat; -0059 end +0023 rxns=convertCharArray(rxns); +0024 grRules=convertCharArray(grRules); +0025 +0026 if ~(numel(grRules)==numel(rxns)) +0027 error('Number of rxns and grRules should be identical') +0028 end +0029 +0030 for i=1:length(rxns) +0031 % Add genes to model +0032 geneList=transpose(cell(unique(regexp(grRules{i},'[)(]*|( and )*|( or )*','split')))); % Extract individual, unique genes from the geneAssoc provided +0033 geneList=geneList(~cellfun(@isempty, geneList)); +0034 genesToAdd.genes=setdiff(geneList,model.genes); % Only keep the genes that are not yet part of the model.genes. +0035 if ~isempty(genesToAdd.genes) +0036 model=addGenesRaven(model,genesToAdd); % Add genes +0037 end +0038 +0039 % Find reaction and gene indices +0040 idx=getIndexes(model,rxns,'rxns'); +0041 end +0042 +0043 % Change gene associations +0044 if replace==true % Replace old gene associations +0045 model.grRules(idx)=grRules; +0046 else % Add gene associations, add new gene rules after 'OR'. +0047 model.grRules(idx)=strcat('(',model.grRules(idx),') or (',grRules,')'); +0048 end +0049 +0050 %Fix grRules and reconstruct rxnGeneMat +0051 [grRules,rxnGeneMat] = standardizeGrRules(model,true); +0052 model.grRules = grRules; +0053 model.rxnGeneMat = rxnGeneMat; +0054 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/changeRxns.html b/doc/core/changeRxns.html index 8b5972ee..9bbdc649 100644 --- a/doc/core/changeRxns.html +++ b/doc/core/changeRxns.html @@ -85,7 +85,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • addRxns addRxns
  • convertCharArray convertCharArray
  • dispEM dispEM
  • permuteModel permuteModel
  • removeReactions removeReactions
  • This function is called by: @@ -160,91 +160,88 @@

    SOURCE CODE ^end 0066 -0067 if ischar(rxns) -0068 rxns={rxns}; -0069 end -0070 if ischar(equations) -0071 equations={equations}; -0072 end -0073 -0074 %Find the indexes of the reactions and throw an error if they aren't all -0075 %found -0076 [I, J]=ismember(rxns,model.rxns); -0077 if ~all(I) -0078 EM='All reaction ids must exist in the model'; -0079 dispEM(EM); -0080 end -0081 -0082 %The reactions are changed in the following manner. First create a -0083 %rxns-structure by copying info from the model. Then remove the old -0084 %reactions. Then add the updated ones using addRxns. Lastly, the model is -0085 %reordered to match the original order. This is done like this to make use -0086 %of the advanced parsing of equations that addRxns use. -0087 rxnsToChange.rxns=rxns; -0088 if isfield(equations,'mets') && isfield(equations,'stoichCoeffs') -0089 rxnsToChange.mets=equations.mets; -0090 rxnsToChange.stoichCoeffs=equations.stoichCoeffs; -0091 else -0092 rxnsToChange.equations=equations; +0067 rxns=convertCharArray(rxns); +0068 equations=convertCharArray(equations); +0069 compartment=char(compartment); +0070 +0071 %Find the indexes of the reactions and throw an error if they aren't all +0072 %found +0073 [I, J]=ismember(rxns,model.rxns); +0074 if ~all(I) +0075 EM='All reaction ids must exist in the model'; +0076 dispEM(EM); +0077 end +0078 +0079 %The reactions are changed in the following manner. First create a +0080 %rxns-structure by copying info from the model. Then remove the old +0081 %reactions. Then add the updated ones using addRxns. Lastly, the model is +0082 %reordered to match the original order. This is done like this to make use +0083 %of the advanced parsing of equations that addRxns use. +0084 rxnsToChange.rxns=rxns; +0085 if isfield(equations,'mets') && isfield(equations,'stoichCoeffs') +0086 rxnsToChange.mets=equations.mets; +0087 rxnsToChange.stoichCoeffs=equations.stoichCoeffs; +0088 else +0089 rxnsToChange.equations=equations; +0090 end +0091 if isfield(model,'rxnNames') +0092 rxnsToChange.rxnNames=model.rxnNames(J); 0093 end -0094 if isfield(model,'rxnNames') -0095 rxnsToChange.rxnNames=model.rxnNames(J); +0094 if isfield(model,'lb') +0095 rxnsToChange.lb=model.lb(J); 0096 end -0097 if isfield(model,'lb') -0098 rxnsToChange.lb=model.lb(J); +0097 if isfield(model,'ub') +0098 rxnsToChange.ub=model.ub(J); 0099 end -0100 if isfield(model,'ub') -0101 rxnsToChange.ub=model.ub(J); +0100 if isfield(model,'c') +0101 rxnsToChange.c=model.c(J); 0102 end -0103 if isfield(model,'c') -0104 rxnsToChange.c=model.c(J); +0103 if isfield(model,'eccodes') +0104 rxnsToChange.eccodes=model.eccodes(J); 0105 end -0106 if isfield(model,'eccodes') -0107 rxnsToChange.eccodes=model.eccodes(J); +0106 if isfield(model,'subSystems') +0107 rxnsToChange.subSystems=model.subSystems(J); 0108 end -0109 if isfield(model,'subSystems') -0110 rxnsToChange.subSystems=model.subSystems(J); +0109 if isfield(model,'rxnComps') +0110 rxnsToChange.rxnComps=model.rxnComps(J); 0111 end -0112 if isfield(model,'rxnComps') -0113 rxnsToChange.rxnComps=model.rxnComps(J); +0112 if isfield(model,'grRules') +0113 rxnsToChange.grRules=model.grRules(J); 0114 end -0115 if isfield(model,'grRules') -0116 rxnsToChange.grRules=model.grRules(J); +0115 if isfield(model,'rxnFrom') +0116 rxnsToChange.rxnFrom=model.rxnFrom(J); 0117 end -0118 if isfield(model,'rxnFrom') -0119 rxnsToChange.rxnFrom=model.rxnFrom(J); +0118 if isfield(model,'rxnScores') +0119 rxnsToChange.rxnScores=model.rxnScores(J); 0120 end -0121 if isfield(model,'rxnScores') -0122 rxnsToChange.rxnScores=model.rxnScores(J); +0121 if isfield(model,'rxnMiriams') +0122 rxnsToChange.rxnMiriams=model.rxnMiriams(J); 0123 end -0124 if isfield(model,'rxnMiriams') -0125 rxnsToChange.rxnMiriams=model.rxnMiriams(J); +0124 if isfield(model,'rxnNotes') +0125 rxnsToChange.rxnNotes=model.rxnNotes(J); 0126 end -0127 if isfield(model,'rxnNotes') -0128 rxnsToChange.rxnNotes=model.rxnNotes(J); +0127 if isfield(model,'rxnReferences') +0128 rxnsToChange.rxnReferences=model.rxnReferences(J); 0129 end -0130 if isfield(model,'rxnReferences') -0131 rxnsToChange.rxnReferences=model.rxnReferences(J); +0130 if isfield(model,'rxnConfidenceScores') +0131 rxnsToChange.rxnConfidenceScores=model.rxnConfidenceScores(J); 0132 end -0133 if isfield(model,'rxnConfidenceScores') -0134 rxnsToChange.rxnConfidenceScores=model.rxnConfidenceScores(J); +0133 if isfield(model,'pwys') +0134 rxnsToChange.pwys=model.pwys(J); 0135 end -0136 if isfield(model,'pwys') -0137 rxnsToChange.pwys=model.pwys(J); -0138 end -0139 -0140 %Calculate the new order of reactions -0141 order=ones(numel(model.rxns),1); -0142 order(J)=0; -0143 order=cumsum(order); -0144 order(J)=order(end)+1:order(end)+numel(rxns); +0136 +0137 %Calculate the new order of reactions +0138 order=ones(numel(model.rxns),1); +0139 order(J)=0; +0140 order=cumsum(order); +0141 order(J)=order(end)+1:order(end)+numel(rxns); +0142 +0143 %Remove the original reactions +0144 model=removeReactions(model,rxns); 0145 -0146 %Remove the original reactions -0147 model=removeReactions(model,rxns); -0148 -0149 model=addRxns(model,rxnsToChange,eqnType,compartment,allowNewMets); -0150 model=permuteModel(model,order,'rxns'); -0151 end +0146 model=addRxns(model,rxnsToChange,eqnType,compartment,allowNewMets); +0147 model=permuteModel(model,order,'rxns'); +0148 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/checkProduction.html b/doc/core/checkProduction.html index 8c828f82..bddc084c 100644 --- a/doc/core/checkProduction.html +++ b/doc/core/checkProduction.html @@ -74,7 +74,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • addExchangeRxns addExchangeRxns
  • canProduce canProduce
  • convertCharArray convertCharArray
  • haveFlux haveFlux
  • This function is called by: @@ -133,108 +133,110 @@

    SOURCE CODE ^if nargin<3 0050 excretionFromCompartments=model.comps; -0051 end -0052 -0053 if nargin<4 -0054 printDetails=true; -0055 end -0056 -0057 %Add an exchange reaction for each metabolite in the allowed compartments -0058 %and see if it can carry a flux -0059 allowedMetIds=ismember(model.comps(model.metComps),excretionFromCompartments); -0060 allowedMetIndexes=find(allowedMetIds); -0061 [model, addedRxns]=addExchangeRxns(model,'out',allowedMetIndexes); -0062 -0063 canProduce=haveFlux(model,10^-5,addedRxns); +0051 else +0052 excretionFromCompartments=convertCharArray(excretionFromCompartments); +0053 end +0054 +0055 if nargin<4 +0056 printDetails=true; +0057 end +0058 +0059 %Add an exchange reaction for each metabolite in the allowed compartments +0060 %and see if it can carry a flux +0061 allowedMetIds=ismember(model.comps(model.metComps),excretionFromCompartments); +0062 allowedMetIndexes=find(allowedMetIds); +0063 [model, addedRxns]=addExchangeRxns(model,'out',allowedMetIndexes); 0064 -0065 notProduced=find(~canProduce); -0066 minToConnect={}; -0067 if checkNeededForProduction==true -0068 %For each of the metabolites that couldn't be produced allow uptake and -0069 %check which of the other metabolites that couldn't be produced that -0070 %can be produced -0071 neededForProductionMat=false(numel(notProduced)); -0072 for i=1:numel(notProduced) -0073 %Add uptake for this metabolite -0074 if i>1 -0075 %Reset last iteration -0076 model.S(:,numel(model.rxns)-numel(addedRxns)+notProduced(i-1))=model.S(:,numel(model.rxns)-numel(addedRxns)+notProduced(i-1))*-1; -0077 end -0078 %Change the production reaction to an uptake reaction -0079 model.S(:,numel(model.rxns)-numel(addedRxns)+notProduced(i))=model.S(:,numel(model.rxns)-numel(addedRxns)+notProduced(i))*-1; -0080 -0081 %Test which of the metabolites that couldn't be produced that can -0082 %be produced now -0083 neededForProductionMat(i,:)=haveFlux(model,10^-5,addedRxns(notProduced)); -0084 end -0085 %Calculate the smallest number of metabolites that must be connected to -0086 %make everything connected and return their names -0087 -0088 %The algorithm is relatively straight forward. It finds the metabolite -0089 %that connects the most unconnected metabolites (iteratively), adds it -0090 %and removes the now connected metabolites until all are connected. -0091 %This is not guaranteed to find the global minimum -0092 neededForProdTemp=neededForProductionMat; -0093 while 1==1 -0094 %Get all metabolites a metabolite makes connected -0095 totalConnected=false(size(neededForProdTemp)); -0096 for i=1:numel(notProduced) -0097 totalConnected(i,:)=neededForProdTemp(i,:); -0098 -0099 lastIter=0; -0100 while 1==1 -0101 [~, a]=find(neededForProdTemp(totalConnected(i,:),:)); -0102 totalConnected(i,a)=true; -0103 if numel(a)==lastIter -0104 break; %No more connections were possible -0105 else -0106 lastIter=numel(a); -0107 end -0108 end -0109 end -0110 [connections, mostConnected]=max(sum(totalConnected,2)); -0111 -0112 if connections>0 -0113 %Add the most connected metabolite to the list and remove all -0114 %metabolites that it's connected to -0115 metID=allowedMetIndexes(notProduced(mostConnected)); -0116 entry=[model.metNames{metID},'[',model.comps{model.metComps(metID)},'] (connects ' num2str(connections) ' metabolites)']; -0117 minToConnect=[minToConnect;entry]; -0118 neededForProdTemp(totalConnected(mostConnected,:),:)=false; -0119 neededForProdTemp(:,totalConnected(mostConnected,:))=false; -0120 else -0121 break; -0122 end -0123 end -0124 else -0125 neededForProductionMat=[]; -0126 end -0127 -0128 notProducedNames=strcat(model.metNames(allowedMetIndexes(notProduced)),'[',model.comps(model.metComps(allowedMetIndexes(notProduced))),']'); +0065 canProduce=haveFlux(model,10^-5,addedRxns); +0066 +0067 notProduced=find(~canProduce); +0068 minToConnect={}; +0069 if checkNeededForProduction==true +0070 %For each of the metabolites that couldn't be produced allow uptake and +0071 %check which of the other metabolites that couldn't be produced that +0072 %can be produced +0073 neededForProductionMat=false(numel(notProduced)); +0074 for i=1:numel(notProduced) +0075 %Add uptake for this metabolite +0076 if i>1 +0077 %Reset last iteration +0078 model.S(:,numel(model.rxns)-numel(addedRxns)+notProduced(i-1))=model.S(:,numel(model.rxns)-numel(addedRxns)+notProduced(i-1))*-1; +0079 end +0080 %Change the production reaction to an uptake reaction +0081 model.S(:,numel(model.rxns)-numel(addedRxns)+notProduced(i))=model.S(:,numel(model.rxns)-numel(addedRxns)+notProduced(i))*-1; +0082 +0083 %Test which of the metabolites that couldn't be produced that can +0084 %be produced now +0085 neededForProductionMat(i,:)=haveFlux(model,10^-5,addedRxns(notProduced)); +0086 end +0087 %Calculate the smallest number of metabolites that must be connected to +0088 %make everything connected and return their names +0089 +0090 %The algorithm is relatively straight forward. It finds the metabolite +0091 %that connects the most unconnected metabolites (iteratively), adds it +0092 %and removes the now connected metabolites until all are connected. +0093 %This is not guaranteed to find the global minimum +0094 neededForProdTemp=neededForProductionMat; +0095 while 1==1 +0096 %Get all metabolites a metabolite makes connected +0097 totalConnected=false(size(neededForProdTemp)); +0098 for i=1:numel(notProduced) +0099 totalConnected(i,:)=neededForProdTemp(i,:); +0100 +0101 lastIter=0; +0102 while 1==1 +0103 [~, a]=find(neededForProdTemp(totalConnected(i,:),:)); +0104 totalConnected(i,a)=true; +0105 if numel(a)==lastIter +0106 break; %No more connections were possible +0107 else +0108 lastIter=numel(a); +0109 end +0110 end +0111 end +0112 [connections, mostConnected]=max(sum(totalConnected,2)); +0113 +0114 if connections>0 +0115 %Add the most connected metabolite to the list and remove all +0116 %metabolites that it's connected to +0117 metID=allowedMetIndexes(notProduced(mostConnected)); +0118 entry=[model.metNames{metID},'[',model.comps{model.metComps(metID)},'] (connects ' num2str(connections) ' metabolites)']; +0119 minToConnect=[minToConnect;entry]; +0120 neededForProdTemp(totalConnected(mostConnected,:),:)=false; +0121 neededForProdTemp(:,totalConnected(mostConnected,:))=false; +0122 else +0123 break; +0124 end +0125 end +0126 else +0127 neededForProductionMat=[]; +0128 end 0129 -0130 if printDetails==true -0131 fprintf('The following metabolites could not be produced:\n'); -0132 [notProducedNamesTemp,perm]=sort(notProducedNames); -0133 -0134 if checkNeededForProduction==true -0135 neededForProdTemp=neededForProductionMat(:,perm); -0136 neededForProdTemp=neededForProdTemp(perm,:); -0137 fprintf('\tIf the production of a metabolite is dependent on some other metabolites then those are printed under the name\n\n'); -0138 end -0139 for i=1:numel(notProducedNamesTemp) -0140 fprintf([notProducedNamesTemp{i} '\n']); -0141 neededForProdTemp(i,i)=false; %Not neat to do this here. Prevent printing itself -0142 if checkNeededForProduction==true -0143 enablesProduction=find(neededForProdTemp(:,i)); -0144 if any(enablesProduction) -0145 for j=1:numel(enablesProduction) -0146 fprintf(['\t' notProducedNamesTemp{enablesProduction(j)} '\n']); -0147 end -0148 end -0149 end -0150 end -0151 end -0152 end +0130 notProducedNames=strcat(model.metNames(allowedMetIndexes(notProduced)),'[',model.comps(model.metComps(allowedMetIndexes(notProduced))),']'); +0131 +0132 if printDetails==true +0133 fprintf('The following metabolites could not be produced:\n'); +0134 [notProducedNamesTemp,perm]=sort(notProducedNames); +0135 +0136 if checkNeededForProduction==true +0137 neededForProdTemp=neededForProductionMat(:,perm); +0138 neededForProdTemp=neededForProdTemp(perm,:); +0139 fprintf('\tIf the production of a metabolite is dependent on some other metabolites then those are printed under the name\n\n'); +0140 end +0141 for i=1:numel(notProducedNamesTemp) +0142 fprintf([notProducedNamesTemp{i} '\n']); +0143 neededForProdTemp(i,i)=false; %Not neat to do this here. Prevent printing itself +0144 if checkNeededForProduction==true +0145 enablesProduction=find(neededForProdTemp(:,i)); +0146 if any(enablesProduction) +0147 for j=1:numel(enablesProduction) +0148 fprintf(['\t' notProducedNamesTemp{enablesProduction(j)} '\n']); +0149 end +0150 end +0151 end +0152 end +0153 end +0154 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/checkRxn.html b/doc/core/checkRxn.html index 43c4f589..b83e46df 100644 --- a/doc/core/checkRxn.html +++ b/doc/core/checkRxn.html @@ -33,7 +33,7 @@

    DESCRIPTION ^SOURCE CODE ^% reactions which cannot have flux 0006 % 0007 % model a model structure -0008 % rxn the id of the reaction to check +0008 % rxn the id of one reaction to check 0009 % cutoff minimal flux for successful production/consumption (opt, 0010 % default 10^-7) 0011 % revDir true if the reaction should be reversed (opt, default @@ -87,73 +87,70 @@

    SOURCE CODE ^% 0023 % Usage: report=checkRxn(model,rxn,cutoff,revDir,printReport) 0024 -0025 %Convert to cell string -0026 if ischar(rxn) -0027 rxn={rxn}; +0025 rxn=char(rxn); +0026 if nargin<3 +0027 cutoff=10^-7; 0028 end -0029 if nargin<3 -0030 cutoff=10^-7; +0029 if nargin<4 +0030 revDir=false; 0031 end -0032 if nargin<4 -0033 revDir=false; +0032 if isempty(cutoff) +0033 cutoff=10^-7; 0034 end -0035 if isempty(cutoff) -0036 cutoff=10^-7; +0035 if nargin<5 +0036 printReport=true; 0037 end -0038 if nargin<5 -0039 printReport=true; -0040 end -0041 -0042 [I, rxnID]=ismember(rxn,model.rxns); -0043 -0044 if ~I -0045 EM='Reaction ID not found'; -0046 dispEM(EM); -0047 end -0048 -0049 if revDir==false -0050 report.reactants=find(model.S(:,rxnID)<0); -0051 report.products=find(model.S(:,rxnID)>0); -0052 else -0053 report.reactants=find(model.S(:,rxnID)>0); -0054 report.products=find(model.S(:,rxnID)<0); -0055 end -0056 report.canMake=false(numel(report.reactants),1); -0057 report.canConsume=false(numel(report.products),1); -0058 -0059 %Remove this field as it would give an annoying note otherwise -0060 if isfield(model,'rxnComps') -0061 model=rmfield(model,'rxnComps'); -0062 end -0063 -0064 %There are several ways to do this. Here I choose to add the reactions one -0065 %by one and checking their bounds. This might not be optimal -0066 for i=1:numel(report.reactants) -0067 [tempModel, testRxn]=addExchangeRxns(model,'out',report.reactants(i)); -0068 tempModel=setParam(tempModel,'obj',testRxn,1); -0069 sol=solveLP(tempModel); -0070 if sol.f*-1>cutoff -0071 report.canMake(i)=true; -0072 else -0073 if printReport==true -0074 fprintf(['Failed to make ' model.metNames{report.reactants(i)} '[' model.comps{model.metComps(report.reactants(i))} ']\n']); -0075 end -0076 end -0077 end -0078 -0079 for i=1:numel(report.products) -0080 [tempModel, testRxn]=addExchangeRxns(model,'in',report.products(i)); -0081 tempModel=setParam(tempModel,'obj',testRxn,1); -0082 sol=solveLP(tempModel); -0083 if sol.f*-1>cutoff -0084 report.canConsume(i)=true; -0085 else -0086 if printReport==true -0087 fprintf(['Failed to consume ' model.metNames{report.products(i)} '[' model.comps{model.metComps(report.products(i))} ']\n']); -0088 end -0089 end -0090 end -0091 end +0038 +0039 [I, rxnID]=ismember(rxn,model.rxns); +0040 +0041 if ~I +0042 EM='Reaction ID not found'; +0043 dispEM(EM); +0044 end +0045 +0046 if revDir==false +0047 report.reactants=find(model.S(:,rxnID)<0); +0048 report.products=find(model.S(:,rxnID)>0); +0049 else +0050 report.reactants=find(model.S(:,rxnID)>0); +0051 report.products=find(model.S(:,rxnID)<0); +0052 end +0053 report.canMake=false(numel(report.reactants),1); +0054 report.canConsume=false(numel(report.products),1); +0055 +0056 %Remove this field as it would give an annoying note otherwise +0057 if isfield(model,'rxnComps') +0058 model=rmfield(model,'rxnComps'); +0059 end +0060 +0061 %There are several ways to do this. Here I choose to add the reactions one +0062 %by one and checking their bounds. This might not be optimal +0063 for i=1:numel(report.reactants) +0064 [tempModel, testRxn]=addExchangeRxns(model,'out',report.reactants(i)); +0065 tempModel=setParam(tempModel,'obj',testRxn,1); +0066 sol=solveLP(tempModel); +0067 if sol.f*-1>cutoff +0068 report.canMake(i)=true; +0069 else +0070 if printReport==true +0071 fprintf(['Failed to make ' model.metNames{report.reactants(i)} '[' model.comps{model.metComps(report.reactants(i))} ']\n']); +0072 end +0073 end +0074 end +0075 +0076 for i=1:numel(report.products) +0077 [tempModel, testRxn]=addExchangeRxns(model,'in',report.products(i)); +0078 tempModel=setParam(tempModel,'obj',testRxn,1); +0079 sol=solveLP(tempModel); +0080 if sol.f*-1>cutoff +0081 report.canConsume(i)=true; +0082 else +0083 if printReport==true +0084 fprintf(['Failed to consume ' model.metNames{report.products(i)} '[' model.comps{model.metComps(report.products(i))} ']\n']); +0085 end +0086 end +0087 end +0088 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/compareMultipleModels.html b/doc/core/compareMultipleModels.html index 1c2d6a78..0b4f6038 100644 --- a/doc/core/compareMultipleModels.html +++ b/doc/core/compareMultipleModels.html @@ -127,390 +127,395 @@

    SOURCE CODE ^% Usage: compStruct=compareMultipleModels(models,printResults,... 0042 % plotResults,groupVector,funcCompare,taskFile); 0043 -0044 %% Set up input defaults -0045 if nargin < 2 || isempty(printResults) -0046 printResults=false; +0044 %% Stats toolbox required +0045 if ~(exist('mdscale.m','file') && exist('pdist.m','file') && exist('squareform.m','file') && exist('tsne.m','file')) +0046 error('The MATLAB Statistics and Machine Learning Toolbox is required for this function') 0047 end -0048 if nargin < 3 || isempty(plotResults) -0049 plotResults=false; -0050 end -0051 if nargin < 4 -0052 groupVector = []; -0053 elseif ~isnumeric(groupVector) -0054 % convert strings to numeric groups -0055 [groupNames,~,groupVector] = unique(groupVector); -0056 else -0057 % generate group names for vector of numbers -0058 groupNames = arrayfun(@num2str,unique(groupVector),'UniformOutput',false); -0059 end -0060 if nargin < 5 || isempty(funcCompare) -0061 funcCompare = false; -0062 end -0063 if nargin < 6 -0064 taskFile = []; -0065 end -0066 if numel(models) <= 1 -0067 EM = 'Cannot compare only one model. Use printModelStats if you want a summary of a model'; -0068 dispEM(EM); -0069 end -0070 if isempty(taskFile) && funcCompare -0071 EM = 'Cannot perform the functional comparison without a task file. Specify taskFile or set funcCompare to FALSE.'; -0072 dispEM(EM); -0073 end -0074 -0075 %% Set up model ID structure -0076 compStruct.modelIDs = {}; -0077 fprintf('\n Getting model IDs \n') -0078 for i = 1:numel(models) -0079 if ~ischar(models{i}.id) % to deal with non-character IDs (cells, strings, etc) -0080 compStruct.modelIDs{i,1} = models{i}.id{1}; -0081 else -0082 compStruct.modelIDs{i,1} = models{i}.id; -0083 end -0084 end -0085 fprintf('*** Done \n\n') -0086 -0087 -0088 %% Flatten models' subSystems field -0089 % Convert from cell array of cells to cell array of strings -0090 % NOTE: this function currently only recognizes one subSystem per reaction; -0091 % additional subSystems will be ignored! -0092 for i = 1:numel(models) -0093 cells = cellfun(@iscell,models{i}.subSystems); -0094 models{i}.subSystems(cells) = cellfun(@(s) s{1}, models{i}.subSystems(cells), 'UniformOutput', false); -0095 end -0096 -0097 -0098 %% Compare models structure & function based on high-dimensional methods -0099 % Compare number of reactions in each subsystem in each model using a heatmap -0100 field = 'subSystems'; -0101 fprintf('\n Comparing subsystem utilization \n') -0102 if any(~cellfun(@(m) isfield(m,field),models)) -0103 fprintf('\nWARNING: At least one model does not contain the field "subSystems". \n') -0104 fprintf(' Skipping subsystem comparison. \n\n') -0105 else -0106 [id,compMat] = compareModelField(models,field); -0107 compStruct.subsystems.ID = id; -0108 compStruct.subsystems.matrix = compMat; -0109 fprintf('*** Done \n\n') -0110 -0111 if printResults -0112 % This could use some cleaning up -0113 fprintf('*** Comparison of reaction subsystem populations:\n\n'); -0114 -0115 nrow = min([15,numel(compStruct.subsystems.ID)]); -0116 ncol = min([10,numel(compStruct.modelIDs)]); -0117 summaryArray = [{field}, compStruct.modelIDs(1:ncol)']; -0118 summaryArray = [summaryArray; [compStruct.subsystems.ID(1:nrow), ... -0119 arrayfun(@num2str,compStruct.subsystems.matrix(1:nrow,1:ncol),'UniformOutput',false)]]; -0120 -0121 charArray = []; -0122 for i = 1:size(summaryArray,2) -0123 charArray = [charArray, char(strcat(summaryArray(:,i),{' '}))]; -0124 end -0125 disp(charArray); -0126 if numel(compStruct.subsystems.ID) > 15 -0127 fprintf('...\n'); -0128 end -0129 fprintf('\n\n'); -0130 end -0131 -0132 if plotResults==true -0133 % Plot all subsystems -0134 figure; -0135 plottingData = (compStruct.subsystems.matrix - mean(compStruct.subsystems.matrix,2))./mean(compStruct.subsystems.matrix,2); -0136 color_map = redblue(length(0:.01:2)); -0137 h = genHeatMap(plottingData',compStruct.subsystems.ID,compStruct.modelIDs,'both','euclidean',color_map,[-1,1]); -0138 title('Subsystem Coverage - all subsystems','FontSize',18,'FontWeight','bold') -0139 -0140 % Plot only subsystems with deviation from mean -0141 keepSubs = (sum(plottingData~=0,2) ~= 0); -0142 if sum(keepSubs) > 1 -0143 figure; -0144 h_small = genHeatMap(plottingData(keepSubs,:)',compStruct.subsystems.ID(keepSubs),... -0145 compStruct.modelIDs,'both','euclidean',color_map,[-1,1]); -0146 title('Subsystem Coverage','FontSize',18,'FontWeight','bold') -0147 -0148 % Plot enrichment in subsystems with deviation from mean -0149 figure; -0150 color_map_bw = [1 1 1;0 0 0]; -0151 h_enriched = genHeatMap(plottingData(keepSubs,:)',compStruct.subsystems.ID(keepSubs),... -0152 compStruct.modelIDs,'both','euclidean',color_map_bw,[-10^-4,10^-4]); -0153 title('Subsystem Enrichment','FontSize',18,'FontWeight','bold') -0154 end -0155 end -0156 -0157 end -0158 -0159 % Compare overall reaction structure across all models using a heatmap -0160 field = 'rxns'; -0161 fprintf('\n Comparing model reaction correlations \n') -0162 -0163 % Create binary matrix of reactions -0164 [id,binary_matrix] = compareModelField(models,field); -0165 compStruct.reactions.IDs = id; -0166 compStruct.reactions.matrix = binary_matrix; -0167 -0168 % calculate hamming similarity -0169 compStruct.structComp = 1-squareform(pdist(binary_matrix','hamming')); -0170 fprintf('*** Done \n\n') -0171 if plotResults == true -0172 color_map = [ones(100,1) linspace(1,0,100)' linspace(1,0,100)']; -0173 figure; -0174 h = genHeatMap(compStruct.structComp,compStruct.modelIDs,compStruct.modelIDs,'both','euclidean',color_map); -0175 title('Structural Similarity','FontSize',18,'FontWeight','bold') -0176 end -0177 -0178 % Compare overall reaction structure across all models using tSNE projection -0179 rng(42) % For consistency -0180 fprintf('\n Comparing model reaction structures \n') -0181 if exist('tsne') > 0 -0182 proj_coords = tsne(double(binary_matrix'),'Distance','hamming','NumDimensions',3); % 3D -0183 compStruct.structCompMap = proj_coords; -0184 axis_labels = {'tSNE 1';'tSNE 2';'tSNE 3'}; -0185 fprintf('*** Done \n\n') -0186 else -0187 fprintf('\nWARNING: Could not complete full structural comparison because the function \n') -0188 fprintf(' "tsne" does not exist in your Matlab version. \n') -0189 fprintf(' Using MDS to project data instead of tSNE. \n') -0190 fprintf(' Please upgrade to Matlab 2017b or higher for full functionality. \n\n') -0191 [proj_coords,stress,disparities] = mdscale(pdist(double(binary_matrix'),'hamming'),3); -0192 compStruct.structCompMap = proj_coords; -0193 axis_labels = {'MDS 1';'MDS 2';'MDS 3'}; -0194 end -0195 -0196 % plot structure comparison results -0197 if plotResults == true -0198 figure; hold on; -0199 if ~isempty(groupVector) -0200 color_data = groupVector; -0201 if length(groupNames) <= 7 -0202 % "lines" colormap only has 7 unique colors -0203 color_palette = lines(length(groupNames)); -0204 else -0205 color_palette = parula(length(groupNames)); -0206 end -0207 colormap(color_palette); -0208 else -0209 color_data = 'k'; -0210 end -0211 scatter3(proj_coords(:,1),proj_coords(:,2),proj_coords(:,3),35,color_data,'filled'); -0212 view(135,25); % to make it obvious that it is a 3D plot -0213 xlabel(axis_labels{1}); ylabel(axis_labels{2}); zlabel(axis_labels{3}); -0214 set(gca,'FontSize',14,'LineWidth',1.25); -0215 title('Structural Comparison','FontSize',18,'FontWeight','bold') -0216 -0217 % add legend -0218 if ~isempty(groupVector) -0219 for i = 1:length(groupNames) -0220 h(i) = scatter3([],[],[],35,color_palette(i,:),'filled'); -0221 end -0222 legend(h,groupNames); -0223 end -0224 end -0225 -0226 % Compare model functions by assessing their capacity to perform tasks -0227 if funcCompare == true && ~isempty(taskFile) -0228 fprintf('\n Checking model performance on specified tasks. \n') -0229 taskStructure=parseTaskList(taskFile); -0230 for i = 1:numel(models) -0231 fprintf('\n Checking model # %.0f \n',i) -0232 taskReport{i} = checkTasks(models{i},[],false,false,false,taskStructure); -0233 end -0234 -0235 % Save results -0236 taskMatrix = zeros(length(taskReport{1}.ok),numel(taskReport)); -0237 for i = 1:numel(taskReport) -0238 taskMatrix(:,i) = taskReport{i}.ok; -0239 end -0240 compStruct.funcComp.matrix = taskMatrix; -0241 compStruct.funcComp.tasks = taskReport{1}.description; -0242 fprintf('*** Done \n\n') -0243 -0244 % Plot results -0245 if plotResults == true -0246 figure; -0247 color_map_bw = [1 1 1;0 0 0]; -0248 h_enriched = genHeatMap(taskMatrix,compStruct.modelIDs,... -0249 taskReport{1}.description,'both','euclidean',color_map_bw,[0,1]); -0250 title('Functional Comparison - All Tasks','FontSize',18,'FontWeight','bold') -0251 -0252 figure; -0253 color_map_bw = [1 1 1;0 0 0]; -0254 h_enriched = genHeatMap(taskMatrix(intersect(find(sum(taskMatrix,2)~=numel(models)),find(sum(taskMatrix,2)~=0)),:),... -0255 compStruct.modelIDs,taskReport{1}.description(intersect(find(sum(taskMatrix,2)~=numel(models)),find(sum(taskMatrix,2)~=0))),... -0256 'both','euclidean',color_map_bw,[0,1]); -0257 title('Functional Similarity','FontSize',18,'FontWeight','bold') -0258 end -0259 end -0260 -0261 end -0262 -0263 %% Additional Functions -0264 -0265 function [id,compMat] = compareModelField(models,field) -0266 % Generates a list of unique field entries and a matrix quantifying the -0267 % number of appearances of each field entry in each model -0268 -0269 % get unique list of field entries -0270 hasfield = cellfun(@(m) isfield(m,field),models); -0271 id = cellfun(@(m) m.(field),models(hasfield),'UniformOutput',false); -0272 id = unique(vertcat(id{:})); +0048 +0049 %% Set up input defaults +0050 if nargin < 2 || isempty(printResults) +0051 printResults=false; +0052 end +0053 if nargin < 3 || isempty(plotResults) +0054 plotResults=false; +0055 end +0056 if nargin < 4 +0057 groupVector = []; +0058 elseif ~isnumeric(groupVector) +0059 % convert strings to numeric groups +0060 [groupNames,~,groupVector] = unique(groupVector); +0061 else +0062 % generate group names for vector of numbers +0063 groupNames = arrayfun(@num2str,unique(groupVector),'UniformOutput',false); +0064 end +0065 if nargin < 5 || isempty(funcCompare) +0066 funcCompare = false; +0067 end +0068 if nargin < 6 +0069 taskFile = []; +0070 else +0071 taskFile=char(taskFile); +0072 end +0073 if numel(models) <= 1 +0074 EM = 'Cannot compare only one model. Use printModelStats if you want a summary of a model'; +0075 dispEM(EM); +0076 end +0077 if isempty(taskFile) && funcCompare +0078 EM = 'Cannot perform the functional comparison without a task file. Specify taskFile or set funcCompare to FALSE.'; +0079 dispEM(EM); +0080 end +0081 +0082 %% Set up model ID structure +0083 compStruct.modelIDs = {}; +0084 fprintf('\n Getting model IDs \n') +0085 for i = 1:numel(models) +0086 if ~ischar(models{i}.id) % to deal with non-character IDs (cells, strings, etc) +0087 compStruct.modelIDs{i,1} = models{i}.id{1}; +0088 else +0089 compStruct.modelIDs{i,1} = models{i}.id; +0090 end +0091 end +0092 fprintf('*** Done \n\n') +0093 +0094 +0095 %% Flatten models' subSystems field +0096 % Convert from cell array of cells to cell array of strings +0097 % NOTE: this function currently only recognizes one subSystem per reaction; +0098 % additional subSystems will be ignored! +0099 for i = 1:numel(models) +0100 cells = cellfun(@iscell,models{i}.subSystems); +0101 models{i}.subSystems(cells) = cellfun(@(s) s{1}, models{i}.subSystems(cells), 'UniformOutput', false); +0102 end +0103 +0104 +0105 %% Compare models structure & function based on high-dimensional methods +0106 % Compare number of reactions in each subsystem in each model using a heatmap +0107 field = 'subSystems'; +0108 fprintf('\n Comparing subsystem utilization \n') +0109 if any(~cellfun(@(m) isfield(m,field),models)) +0110 fprintf('\nWARNING: At least one model does not contain the field "subSystems". \n') +0111 fprintf(' Skipping subsystem comparison. \n\n') +0112 else +0113 [id,compMat] = compareModelField(models,field); +0114 compStruct.subsystems.ID = id; +0115 compStruct.subsystems.matrix = compMat; +0116 fprintf('*** Done \n\n') +0117 +0118 if printResults +0119 % This could use some cleaning up +0120 fprintf('*** Comparison of reaction subsystem populations:\n\n'); +0121 +0122 nrow = min([15,numel(compStruct.subsystems.ID)]); +0123 ncol = min([10,numel(compStruct.modelIDs)]); +0124 summaryArray = [{field}, compStruct.modelIDs(1:ncol)']; +0125 summaryArray = [summaryArray; [compStruct.subsystems.ID(1:nrow), ... +0126 arrayfun(@num2str,compStruct.subsystems.matrix(1:nrow,1:ncol),'UniformOutput',false)]]; +0127 +0128 charArray = []; +0129 for i = 1:size(summaryArray,2) +0130 charArray = [charArray, char(strcat(summaryArray(:,i),{' '}))]; +0131 end +0132 disp(charArray); +0133 if numel(compStruct.subsystems.ID) > 15 +0134 fprintf('...\n'); +0135 end +0136 fprintf('\n\n'); +0137 end +0138 +0139 if plotResults==true +0140 % Plot all subsystems +0141 figure; +0142 plottingData = (compStruct.subsystems.matrix - mean(compStruct.subsystems.matrix,2))./mean(compStruct.subsystems.matrix,2); +0143 color_map = redblue(length(0:.01:2)); +0144 h = genHeatMap(plottingData',compStruct.subsystems.ID,compStruct.modelIDs,'both','euclidean',color_map,[-1,1]); +0145 title('Subsystem Coverage - all subsystems','FontSize',18,'FontWeight','bold') +0146 +0147 % Plot only subsystems with deviation from mean +0148 keepSubs = (sum(plottingData~=0,2) ~= 0); +0149 if sum(keepSubs) > 1 +0150 figure; +0151 h_small = genHeatMap(plottingData(keepSubs,:)',compStruct.subsystems.ID(keepSubs),... +0152 compStruct.modelIDs,'both','euclidean',color_map,[-1,1]); +0153 title('Subsystem Coverage','FontSize',18,'FontWeight','bold') +0154 +0155 % Plot enrichment in subsystems with deviation from mean +0156 figure; +0157 color_map_bw = [1 1 1;0 0 0]; +0158 h_enriched = genHeatMap(plottingData(keepSubs,:)',compStruct.subsystems.ID(keepSubs),... +0159 compStruct.modelIDs,'both','euclidean',color_map_bw,[-10^-4,10^-4]); +0160 title('Subsystem Enrichment','FontSize',18,'FontWeight','bold') +0161 end +0162 end +0163 +0164 end +0165 +0166 % Compare overall reaction structure across all models using a heatmap +0167 field = 'rxns'; +0168 fprintf('\n Comparing model reaction correlations \n') +0169 +0170 % Create binary matrix of reactions +0171 [id,binary_matrix] = compareModelField(models,field); +0172 compStruct.reactions.IDs = id; +0173 compStruct.reactions.matrix = binary_matrix; +0174 +0175 % calculate hamming similarity +0176 compStruct.structComp = 1-squareform(pdist(binary_matrix','hamming')); +0177 fprintf('*** Done \n\n') +0178 if plotResults == true +0179 color_map = [ones(100,1) linspace(1,0,100)' linspace(1,0,100)']; +0180 figure; +0181 h = genHeatMap(compStruct.structComp,compStruct.modelIDs,compStruct.modelIDs,'both','euclidean',color_map); +0182 title('Structural Similarity','FontSize',18,'FontWeight','bold') +0183 end +0184 +0185 % Compare overall reaction structure across all models using tSNE projection +0186 rng(42) % For consistency +0187 fprintf('\n Comparing model reaction structures \n') +0188 if exist('tsne') > 0 +0189 proj_coords = tsne(double(binary_matrix'),'Distance','hamming','NumDimensions',3); % 3D +0190 compStruct.structCompMap = proj_coords; +0191 axis_labels = {'tSNE 1';'tSNE 2';'tSNE 3'}; +0192 else % Seems odd to use mdscale if tsne is not found, as both are +0193 % distributed with stats toolbox. If tsne is not present, then also +0194 % mdscale is missing. Anyway, will leave this for now. +0195 [proj_coords,stress,disparities] = mdscale(pdist(double(binary_matrix'),'hamming'),3); +0196 compStruct.structCompMap = proj_coords; +0197 axis_labels = {'MDS 1';'MDS 2';'MDS 3'}; +0198 end +0199 fprintf('*** Done \n\n') +0200 +0201 % plot structure comparison results +0202 if plotResults == true +0203 figure; hold on; +0204 if ~isempty(groupVector) +0205 color_data = groupVector; +0206 if length(groupNames) <= 7 +0207 % "lines" colormap only has 7 unique colors +0208 color_palette = lines(length(groupNames)); +0209 else +0210 color_palette = parula(length(groupNames)); +0211 end +0212 colormap(color_palette); +0213 else +0214 color_data = 'k'; +0215 end +0216 scatter3(proj_coords(:,1),proj_coords(:,2),proj_coords(:,3),35,color_data,'filled'); +0217 view(135,25); % to make it obvious that it is a 3D plot +0218 xlabel(axis_labels{1}); ylabel(axis_labels{2}); zlabel(axis_labels{3}); +0219 set(gca,'FontSize',14,'LineWidth',1.25); +0220 title('Structural Comparison','FontSize',18,'FontWeight','bold') +0221 +0222 % add legend +0223 if ~isempty(groupVector) +0224 for i = 1:length(groupNames) +0225 h(i) = scatter3([],[],[],35,color_palette(i,:),'filled'); +0226 end +0227 legend(h,groupNames); +0228 end +0229 end +0230 +0231 % Compare model functions by assessing their capacity to perform tasks +0232 if funcCompare == true && ~isempty(taskFile) +0233 fprintf('\n Checking model performance on specified tasks. \n') +0234 taskStructure=parseTaskList(taskFile); +0235 for i = 1:numel(models) +0236 fprintf('\n Checking model # %.0f \n',i) +0237 taskReport{i} = checkTasks(models{i},[],false,false,false,taskStructure); +0238 end +0239 +0240 % Save results +0241 taskMatrix = zeros(length(taskReport{1}.ok),numel(taskReport)); +0242 for i = 1:numel(taskReport) +0243 taskMatrix(:,i) = taskReport{i}.ok; +0244 end +0245 compStruct.funcComp.matrix = taskMatrix; +0246 compStruct.funcComp.tasks = taskReport{1}.description; +0247 fprintf('*** Done \n\n') +0248 +0249 % Plot results +0250 if plotResults == true +0251 figure; +0252 color_map_bw = [1 1 1;0 0 0]; +0253 h_enriched = genHeatMap(taskMatrix,compStruct.modelIDs,... +0254 taskReport{1}.description,'both','euclidean',color_map_bw,[0,1]); +0255 title('Functional Comparison - All Tasks','FontSize',18,'FontWeight','bold') +0256 +0257 figure; +0258 color_map_bw = [1 1 1;0 0 0]; +0259 h_enriched = genHeatMap(taskMatrix(intersect(find(sum(taskMatrix,2)~=numel(models)),find(sum(taskMatrix,2)~=0)),:),... +0260 compStruct.modelIDs,taskReport{1}.description(intersect(find(sum(taskMatrix,2)~=numel(models)),find(sum(taskMatrix,2)~=0))),... +0261 'both','euclidean',color_map_bw,[0,1]); +0262 title('Functional Similarity','FontSize',18,'FontWeight','bold') +0263 end +0264 end +0265 +0266 end +0267 +0268 %% Additional Functions +0269 +0270 function [id,compMat] = compareModelField(models,field) +0271 % Generates a list of unique field entries and a matrix quantifying the +0272 % number of appearances of each field entry in each model 0273 -0274 % assemble matrix comparing frequency of each entry in each model -0275 compMat = zeros(numel(id),numel(models)); -0276 for i = 1:numel(models) -0277 [~,entryIndex] = ismember(models{i}.(field),id); % get index of each field entry in the unique id list -0278 compMat(:,i) = histcounts(entryIndex, 0.5:1:(numel(id)+0.5)); % determine the frequency at which each index appears -0279 end -0280 end -0281 -0282 -0283 function h = genHeatMap(data,colnames,rownames,clust_dim,clust_dist,col_map,col_bounds,grid_color) -0284 %genHeatMap Generate a heatmap for a given matrix of data. -0285 % -0286 % Usage: -0287 % -0288 % genHeatMap(data,colnames,rownames,clust_dim,clust_dist,col_map,col_bounds,grid_color); -0289 % -0290 % Inputs: -0291 % -0292 % data Numerical matrix. -0293 % -0294 % colnames Cell array of data column names. -0295 % -0296 % rownames Cell array of data row names. -0297 % -0298 % clust_dim 'none' - the data will be plotted as provided (DEFAULT) -0299 % 'rows' - cluster/rearrange the rows based on distance -0300 % 'cols' - cluster/rearrange the columns based on distance -0301 % 'both' - cluster/rearrange rows and columns based on distance +0274 % get unique list of field entries +0275 hasfield = cellfun(@(m) isfield(m,field),models); +0276 id = cellfun(@(m) m.(field),models(hasfield),'UniformOutput',false); +0277 id = unique(vertcat(id{:})); +0278 +0279 % assemble matrix comparing frequency of each entry in each model +0280 compMat = zeros(numel(id),numel(models)); +0281 for i = 1:numel(models) +0282 [~,entryIndex] = ismember(models{i}.(field),id); % get index of each field entry in the unique id list +0283 compMat(:,i) = histcounts(entryIndex, 0.5:1:(numel(id)+0.5)); % determine the frequency at which each index appears +0284 end +0285 end +0286 +0287 +0288 function h = genHeatMap(data,colnames,rownames,clust_dim,clust_dist,col_map,col_bounds,grid_color) +0289 %genHeatMap Generate a heatmap for a given matrix of data. +0290 % +0291 % Usage: +0292 % +0293 % genHeatMap(data,colnames,rownames,clust_dim,clust_dist,col_map,col_bounds,grid_color); +0294 % +0295 % Inputs: +0296 % +0297 % data Numerical matrix. +0298 % +0299 % colnames Cell array of data column names. +0300 % +0301 % rownames Cell array of data row names. 0302 % -0303 % clust_dist Distance metric to be used for clustering, ignored if -0304 % clust_dim is 'none'. Options are the same as those for -0305 % distance in, e.g., PDIST ('euclidean', 'hamming', etc.). -0306 % (DEFAULT = 'euclidean') +0303 % clust_dim 'none' - the data will be plotted as provided (DEFAULT) +0304 % 'rows' - cluster/rearrange the rows based on distance +0305 % 'cols' - cluster/rearrange the columns based on distance +0306 % 'both' - cluster/rearrange rows and columns based on distance 0307 % -0308 % col_map Colormap, provided as string (e.g., 'parula', 'hot', 'etc.') -0309 % or an Nx3 RGB matrix of N colors. -0310 % (DEFAULT = 'hot') -0311 % -0312 % col_bounds A 2-element vector with min and max values, to manually set -0313 % the bounds of the colormap. -0314 % (DEFAULT = min/max of data). -0315 % -0316 % grid_color Color of the grid surrounding the heatmap cells. -0317 % (DEFAULT = 'none') -0318 % -0319 % -0320 -0321 % handle input arguments -0322 if nargin < 4 || isempty(clust_dim) -0323 clust_dim = 'none'; -0324 elseif ~ismember(clust_dim,{'none','rows','cols','both'}) -0325 error('%s is not a valid CLUST_DIM option. Choose "none", "rows", "cols", or "both".',clust_dim); -0326 end -0327 if nargin < 5 || isempty(clust_dist) -0328 clust_dist = 'euclidean'; -0329 end -0330 if nargin < 6 || isempty(col_map) -0331 col_map = 'hot'; -0332 end -0333 if nargin < 7 || isempty(col_bounds) -0334 col_bounds = [min(data(:)),max(data(:))]; -0335 end -0336 if nargin < 8 -0337 grid_color = 'none'; -0338 end -0339 -0340 % perform hierarchical clustering to sort rows (if specified) -0341 linkage_method = 'average'; -0342 if ismember(clust_dim,{'rows','both'}) -0343 L = linkage(data,linkage_method,clust_dist); -0344 row_ind = optimalleaforder(L,pdist(data,clust_dist)); -0345 else -0346 row_ind = 1:size(data,1); -0347 end -0348 % perform hierarchical clustering to sort columns (if specified) -0349 if ismember(clust_dim,{'cols','both'}) -0350 L = linkage(data',linkage_method,clust_dist); -0351 col_ind = optimalleaforder(L,pdist(data',clust_dist)); -0352 else -0353 col_ind = 1:size(data,2); -0354 end -0355 -0356 % reorder data matrix according to clustering results -0357 sortdata = data(row_ind,col_ind); -0358 sortrows = rownames(row_ind); -0359 sortcols = colnames(col_ind); +0308 % clust_dist Distance metric to be used for clustering, ignored if +0309 % clust_dim is 'none'. Options are the same as those for +0310 % distance in, e.g., PDIST ('euclidean', 'hamming', etc.). +0311 % (DEFAULT = 'euclidean') +0312 % +0313 % col_map Colormap, provided as string (e.g., 'parula', 'hot', 'etc.') +0314 % or an Nx3 RGB matrix of N colors. +0315 % (DEFAULT = 'hot') +0316 % +0317 % col_bounds A 2-element vector with min and max values, to manually set +0318 % the bounds of the colormap. +0319 % (DEFAULT = min/max of data). +0320 % +0321 % grid_color Color of the grid surrounding the heatmap cells. +0322 % (DEFAULT = 'none') +0323 % +0324 % +0325 +0326 % handle input arguments +0327 if nargin < 4 || isempty(clust_dim) +0328 clust_dim = 'none'; +0329 elseif ~ismember(clust_dim,{'none','rows','cols','both'}) +0330 error('%s is not a valid CLUST_DIM option. Choose "none", "rows", "cols", or "both".',clust_dim); +0331 end +0332 if nargin < 5 || isempty(clust_dist) +0333 clust_dist = 'euclidean'; +0334 end +0335 if nargin < 6 || isempty(col_map) +0336 col_map = 'hot'; +0337 end +0338 if nargin < 7 || isempty(col_bounds) +0339 col_bounds = [min(data(:)),max(data(:))]; +0340 end +0341 if nargin < 8 +0342 grid_color = 'none'; +0343 end +0344 +0345 % perform hierarchical clustering to sort rows (if specified) +0346 linkage_method = 'average'; +0347 if ismember(clust_dim,{'rows','both'}) +0348 L = linkage(data,linkage_method,clust_dist); +0349 row_ind = optimalleaforder(L,pdist(data,clust_dist)); +0350 else +0351 row_ind = 1:size(data,1); +0352 end +0353 % perform hierarchical clustering to sort columns (if specified) +0354 if ismember(clust_dim,{'cols','both'}) +0355 L = linkage(data',linkage_method,clust_dist); +0356 col_ind = optimalleaforder(L,pdist(data',clust_dist)); +0357 else +0358 col_ind = 1:size(data,2); +0359 end 0360 -0361 % check if data is square matrix with identical row and column names -0362 if (length(colnames) == length(rownames)) && all(strcmp(colnames,rownames)) -0363 % flip data so the diagonal is from upper left to lower right -0364 sortdata = fliplr(sortdata); -0365 sortcols = flipud(sortcols); -0366 end -0367 -0368 % pad data matrix with zeros (pcolor cuts off last row and column) -0369 sortdata(end+1,end+1) = 0; -0370 -0371 % generate pcolor plot -0372 a = axes; -0373 set(a,'YAxisLocation','Right','XTick',[],'YTick', (1:size(sortdata,1))+0.5,'YTickLabels',sortrows); -0374 set(a,'TickLength',[0 0],'XLim',[1 size(sortdata,2)],'YLim',[1 size(sortdata,1)]); -0375 hold on -0376 -0377 h = pcolor(sortdata); -0378 set(h,'EdgeColor',grid_color); -0379 set(gca,'XTick', (1:size(sortdata,2))+0.5); -0380 set(gca,'YTick', (1:size(sortdata,1))+0.5); -0381 set(gca,'XTickLabels',sortcols,'YTickLabels',sortrows); -0382 set(gca,'XTickLabelRotation',90); -0383 colormap(col_map); -0384 -0385 if ~isempty(col_bounds) -0386 caxis(col_bounds); -0387 end -0388 -0389 end -0390 -0391 -0392 function c = redblue(m) -0393 %REDBLUE Shades of red and blue color map -0394 % REDBLUE(M), is an M-by-3 matrix that defines a colormap. -0395 % The colors begin with bright blue, range through shades of -0396 % blue to white, and then through shades of red to bright red. -0397 % REDBLUE, by itself, is the same length as the current figure's -0398 % colormap. If no figure exists, MATLAB creates one. -0399 % -0400 % For example, to reset the colormap of the current figure: -0401 % -0402 % colormap(redblue) -0403 % -0404 % See also HSV, GRAY, HOT, BONE, COPPER, PINK, FLAG, -0405 % COLORMAP, RGBPLOT. -0406 if nargin < 1, m = size(get(gcf,'colormap'),1); end -0407 -0408 if (mod(m,2) == 0) -0409 % From [0 0 1] to [1 1 1], then [1 1 1] to [1 0 0]; -0410 m1 = m*0.5; -0411 r = (0:m1-1)'/max(m1-1,1); -0412 g = r; -0413 r = [r; ones(m1,1)]; -0414 g = [g; flipud(g)]; -0415 b = flipud(r); -0416 else -0417 % From [0 0 1] to [1 1 1] to [1 0 0]; -0418 m1 = floor(m*0.5); -0419 r = (0:m1-1)'/max(m1,1); -0420 g = r; -0421 r = [r; ones(m1+1,1)]; -0422 g = [g; 1; flipud(g)]; -0423 b = flipud(r); -0424 end -0425 -0426 c = [r g b]; -0427 end +0361 % reorder data matrix according to clustering results +0362 sortdata = data(row_ind,col_ind); +0363 sortrows = rownames(row_ind); +0364 sortcols = colnames(col_ind); +0365 +0366 % check if data is square matrix with identical row and column names +0367 if (length(colnames) == length(rownames)) && all(strcmp(colnames,rownames)) +0368 % flip data so the diagonal is from upper left to lower right +0369 sortdata = fliplr(sortdata); +0370 sortcols = flipud(sortcols); +0371 end +0372 +0373 % pad data matrix with zeros (pcolor cuts off last row and column) +0374 sortdata(end+1,end+1) = 0; +0375 +0376 % generate pcolor plot +0377 a = axes; +0378 set(a,'YAxisLocation','Right','XTick',[],'YTick', (1:size(sortdata,1))+0.5,'YTickLabels',sortrows); +0379 set(a,'TickLength',[0 0],'XLim',[1 size(sortdata,2)],'YLim',[1 size(sortdata,1)]); +0380 hold on +0381 +0382 h = pcolor(sortdata); +0383 set(h,'EdgeColor',grid_color); +0384 set(gca,'XTick', (1:size(sortdata,2))+0.5); +0385 set(gca,'YTick', (1:size(sortdata,1))+0.5); +0386 set(gca,'XTickLabels',sortcols,'YTickLabels',sortrows); +0387 set(gca,'XTickLabelRotation',90); +0388 colormap(col_map); +0389 +0390 if ~isempty(col_bounds) +0391 caxis(col_bounds); +0392 end +0393 +0394 end +0395 +0396 +0397 function c = redblue(m) +0398 %REDBLUE Shades of red and blue color map +0399 % REDBLUE(M), is an M-by-3 matrix that defines a colormap. +0400 % The colors begin with bright blue, range through shades of +0401 % blue to white, and then through shades of red to bright red. +0402 % REDBLUE, by itself, is the same length as the current figure's +0403 % colormap. If no figure exists, MATLAB creates one. +0404 % +0405 % For example, to reset the colormap of the current figure: +0406 % +0407 % colormap(redblue) +0408 % +0409 % See also HSV, GRAY, HOT, BONE, COPPER, PINK, FLAG, +0410 % COLORMAP, RGBPLOT. +0411 if nargin < 1, m = size(get(gcf,'colormap'),1); end +0412 +0413 if (mod(m,2) == 0) +0414 % From [0 0 1] to [1 1 1], then [1 1 1] to [1 0 0]; +0415 m1 = m*0.5; +0416 r = (0:m1-1)'/max(m1-1,1); +0417 g = r; +0418 r = [r; ones(m1,1)]; +0419 g = [g; flipud(g)]; +0420 b = flipud(r); +0421 else +0422 % From [0 0 1] to [1 1 1] to [1 0 0]; +0423 m1 = floor(m*0.5); +0424 r = (0:m1-1)'/max(m1,1); +0425 g = r; +0426 r = [r; ones(m1+1,1)]; +0427 g = [g; 1; flipud(g)]; +0428 b = flipud(r); +0429 end +0430 +0431 c = [r g b]; +0432 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/constructEquations.html b/doc/core/constructEquations.html index eeb4da81..8bd6da45 100644 --- a/doc/core/constructEquations.html +++ b/doc/core/constructEquations.html @@ -66,7 +66,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • buildEquation buildEquation
  • convertCharArray convertCharArray
  • getIndexes getIndexes
  • sortModel sortModel
  • This function is called by: @@ -111,74 +111,73 @@

    SOURCE CODE ^% Usage: equationStrings=constructEquations(model,rxns,useComps,... 0035 % sortRevRxns,sortMetNames,useMetID,useFormula,useRevField) 0036 -0037 if nargin<2 +0037 if nargin<2 || isempty(rxns) 0038 rxns=model.rxns; -0039 end -0040 if nargin<3 -0041 useComps=true; -0042 end -0043 if nargin<4 -0044 sortRevRxns=false; -0045 end -0046 if nargin<5 -0047 sortMetNames=false; -0048 end -0049 if nargin<6 -0050 useMetID=false; -0051 end -0052 if nargin<7 -0053 useFormula=false; -0054 end -0055 if nargin<8 -0056 useRevField=true; -0057 end -0058 if isempty(rxns) && nargin>2 -0059 rxns=model.rxns; -0060 end -0061 -0062 %Sort reversible equations -0063 if sortRevRxns==true -0064 model=sortModel(model); -0065 end -0066 -0067 %Sort metabolite names, including compartment -0068 if sortMetNames==true -0069 model=sortModel(model,false,true); -0070 end -0071 -0072 Rindexes=getIndexes(model,rxns,'rxns'); -0073 -0074 equationStrings=cell(numel(Rindexes),1); -0075 -0076 for i=1:numel(Rindexes) -0077 Mindexes=find(model.S(:,Rindexes(i))); -0078 %Define metabolites by id, formula or name, and with or without compartment: -0079 if useMetID==true && useFormula==false -0080 mets = model.mets(Mindexes); -0081 elseif useMetID==false && useFormula==true -0082 mets = strcat('[',model.metFormulas(Mindexes),']'); -0083 elseif useMetID==true && useFormula==true -0084 error('Arguments useMetID and useFormula cannot be both TRUE!'); -0085 else -0086 mets = model.metNames(Mindexes); -0087 end -0088 if useComps==true -0089 comps = model.comps(model.metComps(Mindexes)); -0090 mets = strcat(mets,'[',comps,']'); -0091 end -0092 %Define stoich coeffs and reversibility: -0093 stoichCoeffs = model.S(Mindexes,Rindexes(i)); -0094 if useRevField == true -0095 isrev = model.rev(Rindexes(i))==1; -0096 else -0097 isrev = model.lb(Rindexes(i))<0 & model.ub(Rindexes(i))>0; -0098 end -0099 -0100 %Construct equation: -0101 equationStrings{i} = buildEquation(mets,stoichCoeffs,isrev); -0102 end -0103 -0104 end +0039 elseif ~islogical(rxns) && ~isnumeric(rxns) +0040 rxns=convertCharArray(rxns); +0041 end +0042 if nargin<3 +0043 useComps=true; +0044 end +0045 if nargin<4 +0046 sortRevRxns=false; +0047 end +0048 if nargin<5 +0049 sortMetNames=false; +0050 end +0051 if nargin<6 +0052 useMetID=false; +0053 end +0054 if nargin<7 +0055 useFormula=false; +0056 end +0057 if nargin<8 +0058 useRevField=true; +0059 end +0060 +0061 %Sort reversible equations +0062 if sortRevRxns==true +0063 model=sortModel(model); +0064 end +0065 +0066 %Sort metabolite names, including compartment +0067 if sortMetNames==true +0068 model=sortModel(model,false,true); +0069 end +0070 +0071 Rindexes=getIndexes(model,rxns,'rxns'); +0072 +0073 equationStrings=cell(numel(Rindexes),1); +0074 +0075 for i=1:numel(Rindexes) +0076 Mindexes=find(model.S(:,Rindexes(i))); +0077 %Define metabolites by id, formula or name, and with or without compartment: +0078 if useMetID==true && useFormula==false +0079 mets = model.mets(Mindexes); +0080 elseif useMetID==false && useFormula==true +0081 mets = strcat('[',model.metFormulas(Mindexes),']'); +0082 elseif useMetID==true && useFormula==true +0083 error('Arguments useMetID and useFormula cannot be both TRUE!'); +0084 else +0085 mets = model.metNames(Mindexes); +0086 end +0087 if useComps==true +0088 comps = model.comps(model.metComps(Mindexes)); +0089 mets = strcat(mets,'[',comps,']'); +0090 end +0091 %Define stoich coeffs and reversibility: +0092 stoichCoeffs = model.S(Mindexes,Rindexes(i)); +0093 if useRevField == true +0094 isrev = model.rev(Rindexes(i))==1; +0095 else +0096 isrev = model.lb(Rindexes(i))<0 & model.ub(Rindexes(i))>0; +0097 end +0098 +0099 %Construct equation: +0100 equationStrings{i} = buildEquation(mets,stoichCoeffs,isrev); +0101 end +0102 +0103 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/constructS.html b/doc/core/constructS.html index 447fb77d..aa2aa8ee 100644 --- a/doc/core/constructS.html +++ b/doc/core/constructS.html @@ -54,7 +54,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • dispEM dispEM
  • parseRxnEqu parseRxnEqu
  • This function is called by: @@ -89,133 +89,141 @@

    SOURCE CODE ^% 0023 % Usage: [S, mets, badRxns, reversible]=constructS(equations,mets) 0024 -0025 badRxns=false(numel(equations),1); -0026 -0027 %Check that no equations are too short to have reversibility data -0028 I=cellfun(@numel,equations); -0029 I=find(I<4,1); -0030 if any(I) -0031 if isempty(rxns) -0032 EM=['The following equation does not have reversibility data: ' equations{I} ]; -0033 dispEM(EM); -0034 else -0035 EM=['The reaction ' rxns{I} ' does not have reversibility data']; -0036 dispEM(EM); -0037 end -0038 end -0039 -0040 %Makes life a little easier -0041 equations=strtrim(equations); -0042 equations=fixEquations(equations); -0043 -0044 if nargin<2 -0045 mets=parseRxnEqu(equations); +0025 equations=convertCharArray(equations); +0026 switch nargin +0027 case 2 +0028 mets=convertCharArray(mets); +0029 case 3 +0030 rxns=convertCharArray(rxns); +0031 end +0032 +0033 badRxns=false(numel(equations),1); +0034 +0035 %Check that no equations are too short to have reversibility data +0036 I=cellfun(@numel,equations); +0037 I=find(I<4,1); +0038 if any(I) +0039 if isempty(rxns) +0040 EM=['The following equation does not have reversibility data: ' equations{I} ]; +0041 dispEM(EM); +0042 else +0043 EM=['The reaction ' rxns{I} ' does not have reversibility data']; +0044 dispEM(EM); +0045 end 0046 end -0047 if nargin<3 -0048 rxns=[]; -0049 end -0050 -0051 %Get which reactions are reversible -0052 reversible=cellfun(@any,strfind(equations,' <=> ')); -0053 -0054 %Make them all reversible. This is not all that neat, but nevermind -0055 equations=strrep(equations,' => ',' <=> '); -0056 -0057 %Replace the the plus signs with some weird character that will be used for -0058 %parsing -0059 equations=strrep(equations,' + ', '€'); -0060 -0061 %Generate the stoichiometric matrix -0062 S=zeros(numel(mets),numel(equations)); -0063 -0064 %Loop through the equations and add the info to the S matrix -0065 for i=1:numel(equations) -0066 %Start by finding the position of the (=> or <=>) -0067 arrowIndex=strfind(equations{i},' <=> '); -0068 -0069 if numel(arrowIndex)~=1 -0070 if isempty(rxns) -0071 EM=['The following equation does not have reversibility data: ' equations{i} ]; -0072 dispEM(EM); -0073 else -0074 EM=['The reaction ' rxns{i} ' does not have reversibility data']; -0075 dispEM(EM); -0076 end -0077 end -0078 -0079 reactants=regexp(equations{i}(1:arrowIndex-1),'€','split'); -0080 products=regexp(equations{i}(arrowIndex+5:end),'€','split'); -0081 -0082 %If the splitting character is at the end (if exchange rxns), then an -0083 %empty string will exist together with the real ones. Remove it -0084 reactants(cellfun(@isempty,reactants))=[]; -0085 products(cellfun(@isempty,products))=[]; +0047 +0048 %Makes life a little easier +0049 equations=strtrim(equations); +0050 equations=fixEquations(equations); +0051 +0052 if nargin<2 +0053 mets=parseRxnEqu(equations); +0054 end +0055 if nargin<3 +0056 rxns=[]; +0057 end +0058 +0059 %Get which reactions are reversible +0060 reversible=cellfun(@any,strfind(equations,' <=> ')); +0061 +0062 %Make them all reversible. This is not all that neat, but nevermind +0063 equations=strrep(equations,' => ',' <=> '); +0064 +0065 %Replace the the plus signs with some weird character that will be used for +0066 %parsing +0067 equations=strrep(equations,' + ', '€'); +0068 +0069 %Generate the stoichiometric matrix +0070 S=zeros(numel(mets),numel(equations)); +0071 +0072 %Loop through the equations and add the info to the S matrix +0073 for i=1:numel(equations) +0074 %Start by finding the position of the (=> or <=>) +0075 arrowIndex=strfind(equations{i},' <=> '); +0076 +0077 if numel(arrowIndex)~=1 +0078 if isempty(rxns) +0079 EM=['The following equation does not have reversibility data: ' equations{i} ]; +0080 dispEM(EM); +0081 else +0082 EM=['The reaction ' rxns{i} ' does not have reversibility data']; +0083 dispEM(EM); +0084 end +0085 end 0086 -0087 %A vector where an element is -1 is the corresponding metabolite is a -0088 %reactant and 1 if it's a product -0089 multiplyWith=[ones(numel(reactants),1)*-1; ones(numel(products),1)]; -0090 -0091 metabolites=[reactants products]; -0092 -0093 %Now loop through the reactants and see if the metabolite has a -0094 %coefficient (it will look as 'number name') -0095 for j=1:numel(metabolites) -0096 space=strfind(metabolites{j},' '); -0097 -0098 if isempty(space) -0099 %No coefficient -0100 coeff=1; -0101 name=metabolites{j}; -0102 else -0103 coeff=str2double(metabolites{j}(1:space(1))); -0104 -0105 %If it was not a coefficiant -0106 if isnan(coeff) -0107 coeff=1; -0108 name=metabolites{j}; -0109 else -0110 name=metabolites{j}(space+1:end); -0111 end -0112 end -0113 -0114 %Find the name in the mets list [a b]=ismember(name,mets); -0115 b=find(strcmp(name,mets),1); -0116 -0117 if any(b) -0118 %Check if the metabolite already participates in this reaction -0119 if S(b,i)~=0 -0120 badRxns(i)=true; -0121 end -0122 S(b,i)=S(b,i)+coeff*multiplyWith(j); -0123 else -0124 if isempty(rxns) -0125 EM=['Could not find metabolite ' name ' in metabolite list']; -0126 dispEM(EM); -0127 else -0128 EM=['The metabolite "' name '" in reaction ' rxns{i} ' was not found in the metabolite list']; -0129 dispEM(EM); -0130 end -0131 end -0132 end -0133 end -0134 S=sparse(S); -0135 end -0136 -0137 function equ=fixEquations(equ) -0138 %If the equation starts with "=>" or "<=>" then add a space again. This is -0139 %an alternative way to represent uptake reactions. The opposite way for -0140 %producing reactions -0141 equ=equ(:); -0142 for i=1:numel(equ) -0143 if strcmp(equ{i}(1:2),'=>') || strcmp(equ{i}(1:3),'<=>') -0144 equ{i}=[' ' equ{i}]; -0145 else -0146 if strcmp(equ{i}(end-1:end),'=>') || strcmp(equ{i}(end-2:end),'<=>') -0147 equ{i}=[equ{i} ' ']; -0148 end -0149 end -0150 end -0151 end +0087 reactants=regexp(equations{i}(1:arrowIndex-1),'€','split'); +0088 products=regexp(equations{i}(arrowIndex+5:end),'€','split'); +0089 +0090 %If the splitting character is at the end (if exchange rxns), then an +0091 %empty string will exist together with the real ones. Remove it +0092 reactants(cellfun(@isempty,reactants))=[]; +0093 products(cellfun(@isempty,products))=[]; +0094 +0095 %A vector where an element is -1 is the corresponding metabolite is a +0096 %reactant and 1 if it's a product +0097 multiplyWith=[ones(numel(reactants),1)*-1; ones(numel(products),1)]; +0098 +0099 metabolites=[reactants products]; +0100 +0101 %Now loop through the reactants and see if the metabolite has a +0102 %coefficient (it will look as 'number name') +0103 for j=1:numel(metabolites) +0104 space=strfind(metabolites{j},' '); +0105 +0106 if isempty(space) +0107 %No coefficient +0108 coeff=1; +0109 name=metabolites{j}; +0110 else +0111 coeff=str2double(metabolites{j}(1:space(1))); +0112 +0113 %If it was not a coefficiant +0114 if isnan(coeff) +0115 coeff=1; +0116 name=metabolites{j}; +0117 else +0118 name=metabolites{j}(space+1:end); +0119 end +0120 end +0121 +0122 %Find the name in the mets list [a b]=ismember(name,mets); +0123 b=find(strcmp(name,mets),1); +0124 +0125 if any(b) +0126 %Check if the metabolite already participates in this reaction +0127 if S(b,i)~=0 +0128 badRxns(i)=true; +0129 end +0130 S(b,i)=S(b,i)+coeff*multiplyWith(j); +0131 else +0132 if isempty(rxns) +0133 EM=['Could not find metabolite ' name ' in metabolite list']; +0134 dispEM(EM); +0135 else +0136 EM=['The metabolite "' name '" in reaction ' rxns{i} ' was not found in the metabolite list']; +0137 dispEM(EM); +0138 end +0139 end +0140 end +0141 end +0142 S=sparse(S); +0143 end +0144 +0145 function equ=fixEquations(equ) +0146 %If the equation starts with "=>" or "<=>" then add a space again. This is +0147 %an alternative way to represent uptake reactions. The opposite way for +0148 %producing reactions +0149 equ=equ(:); +0150 for i=1:numel(equ) +0151 if strcmp(equ{i}(1:2),'=>') || strcmp(equ{i}(1:3),'<=>') +0152 equ{i}=[' ' equ{i}]; +0153 else +0154 if strcmp(equ{i}(end-1:end),'=>') || strcmp(equ{i}(end-2:end),'<=>') +0155 equ{i}=[equ{i} ' ']; +0156 end +0157 end +0158 end +0159 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/consumeSomething.html b/doc/core/consumeSomething.html index f716afe5..07cc1df6 100644 --- a/doc/core/consumeSomething.html +++ b/doc/core/consumeSomething.html @@ -72,7 +72,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • dispEM dispEM
  • getExchangeRxns getExchangeRxns
  • getIndexes getIndexes
  • setParam setParam
  • This function is called by: @@ -125,137 +125,139 @@

    SOURCE CODE ^if nargin<2 0044 ignoreMets=[]; -0045 end -0046 if nargin<3 -0047 isNames=false; -0048 end -0049 if nargin<4 -0050 minNrFluxes=false; -0051 end -0052 if nargin<5 -0053 params.relGap=0.8; -0054 end -0055 if nargin<6 -0056 ignoreIntBounds=false; -0057 end -0058 -0059 if isNames==true && ~isempty(ignoreMets) -0060 %Check that metsToRemove is a cell array -0061 if iscellstr(ignoreMets)==false -0062 EM='Must supply a cell array of strings if isNames=true'; -0063 dispEM(EM); -0064 end -0065 end -0066 -0067 if isNames==false -0068 indexesToIgnore=getIndexes(model,ignoreMets,'mets'); -0069 else -0070 indexesToIgnore=[]; -0071 for i=1:numel(ignoreMets) -0072 indexesToIgnore=[indexesToIgnore;find(strcmp(ignoreMets(i),model.metNames))]; -0073 end -0074 end -0075 -0076 %Change all internal reactions to be unbounded in both directions -0077 if ignoreIntBounds==true -0078 [~, I]=getExchangeRxns(model); -0079 nonExc=true(numel(model.rxns),1); -0080 nonExc(I)=false; -0081 model=setParam(model,'lb',nonExc,-1000); -0082 model=setParam(model,'ub',nonExc,1000); -0083 model=setParam(model,'rev',nonExc,1); -0084 end -0085 -0086 solution=[]; -0087 metabolite=[]; -0088 -0089 nRxns=numel(model.rxns); -0090 nMets=numel(model.mets); -0091 -0092 %Add uptake reactions for all metabolites -0093 model.S=[model.S speye(nMets)]; -0094 -0095 %Add so that they all consume a fake metabolite -0096 model.S=[model.S;[sparse(1,nRxns) ones(1,nMets)*-1]]; -0097 -0098 %Change so that the ignoreMets have a coefficient 0 in their reactions. -0099 %Does not remove the actual reaction to make mapping easier later -0100 model.S(:,indexesToIgnore+nRxns)=0; -0101 -0102 %Add an uptake reaction for this last fake metabolite -0103 model.S(size(model.S,1),size(model.S,2)+1)=1; -0104 model.b=[model.b;zeros(1,size(model.b,2))]; -0105 model.lb=[model.lb;zeros(nMets,1);1]; -0106 model.ub=[model.ub;inf(nMets+1,1)]; -0107 model.rev=[model.rev;zeros(nMets+1,1)]; -0108 model.c=zeros(size(model.S,2),1); -0109 -0110 %Add padding to the reaction annotation to prevent an error in solveLP -0111 padding=1:numel(model.rev); -0112 padding=num2cell(padding)'; -0113 padding=cellfun(@num2str,padding,'uniformoutput',false); -0114 model.rxns=padding; -0115 model.rxnNames=padding; -0116 model.eccodes=padding; -0117 model.rxnMiriams=padding; -0118 model.grRules=padding; -0119 if isfield(model,'genes') -0120 model.rxnGeneMat=sparse(numel(model.rev),numel(model.genes)); -0121 end -0122 model.subSystems=padding; -0123 model.rxnFrom=padding; -0124 model.rxnComps=ones(numel(model.rev),1); -0125 model.rxnNotes=padding; -0126 model.rxnReferences=padding; -0127 model.rxnConfidenceScores=NaN(numel(model.rev),1); -0128 -0129 sol=solveLP(model,1); -0130 if any(sol.x) -0131 %It could be that several metabolites were consumed in order to get the -0132 %best solution. The setdiff is to avoid including the last fake -0133 %metabolite -0134 I=setdiff(find(sol.x(nRxns+1:end)>0.1),size(model.S,1)); -0135 -0136 if any(I) %This should always be true -0137 %Change the coefficients so that only the first is consumed. This -0138 %is not always possible, but it is tested for since it it results -0139 %in more easily interpretable results -0140 -0141 oldS=model.S; -0142 foundSingle=false; -0143 %Test if any of the metabolites could be consumed on their own -0144 for i=1:numel(I) -0145 model.S=oldS; -0146 J=nRxns+1:numel(model.lb)-1; -0147 J(I(i))=[]; -0148 model.S(:,J)=0; -0149 sol=solveLP(model); -0150 if any(sol.x) -0151 foundSingle=true; -0152 break; -0153 end -0154 end -0155 %This means that there was no metabolite which could be consumed on -0156 %its own. Then let all the consumeable metabolites be consumed. -0157 if foundSingle==false -0158 model.S=oldS; -0159 end -0160 if minNrFluxes==true -0161 %Has to add names for the rxns to prevent an error in -0162 %minNrFluxes -0163 model.rxns=cell(numel(model.lb),1); -0164 model.rxns(:)={'TEMP'}; -0165 model.mets=cell(size(model.b,1),1); -0166 model.mets(:)={'TEMP'}; -0167 sol=solveLP(model,3,params); -0168 else -0169 sol=solveLP(model,1); -0170 end -0171 solution=sol.x(1:nRxns); -0172 metabolite=find(sol.x(nRxns+1:end-1)>0.1); -0173 end -0174 end -0175 end +0045 elseif ~islogical(ignoreMets) && ~isnumeric(ignoreMets) +0046 ignoreMets=convertCharArray(ignoreMets); +0047 end +0048 if nargin<3 +0049 isNames=false; +0050 end +0051 if nargin<4 +0052 minNrFluxes=false; +0053 end +0054 if nargin<5 +0055 params.relGap=0.8; +0056 end +0057 if nargin<6 +0058 ignoreIntBounds=false; +0059 end +0060 +0061 if isNames==true && ~isempty(ignoreMets) +0062 %Check that metsToRemove is a cell array +0063 if iscellstr(ignoreMets)==false +0064 EM='Must supply a cell array of strings if isNames=true'; +0065 dispEM(EM); +0066 end +0067 end +0068 +0069 if isNames==false +0070 indexesToIgnore=getIndexes(model,ignoreMets,'mets'); +0071 else +0072 indexesToIgnore=[]; +0073 for i=1:numel(ignoreMets) +0074 indexesToIgnore=[indexesToIgnore;find(strcmp(ignoreMets(i),model.metNames))]; +0075 end +0076 end +0077 +0078 %Change all internal reactions to be unbounded in both directions +0079 if ignoreIntBounds==true +0080 [~, I]=getExchangeRxns(model); +0081 nonExc=true(numel(model.rxns),1); +0082 nonExc(I)=false; +0083 model=setParam(model,'lb',nonExc,-1000); +0084 model=setParam(model,'ub',nonExc,1000); +0085 model=setParam(model,'rev',nonExc,1); +0086 end +0087 +0088 solution=[]; +0089 metabolite=[]; +0090 +0091 nRxns=numel(model.rxns); +0092 nMets=numel(model.mets); +0093 +0094 %Add uptake reactions for all metabolites +0095 model.S=[model.S speye(nMets)]; +0096 +0097 %Add so that they all consume a fake metabolite +0098 model.S=[model.S;[sparse(1,nRxns) ones(1,nMets)*-1]]; +0099 +0100 %Change so that the ignoreMets have a coefficient 0 in their reactions. +0101 %Does not remove the actual reaction to make mapping easier later +0102 model.S(:,indexesToIgnore+nRxns)=0; +0103 +0104 %Add an uptake reaction for this last fake metabolite +0105 model.S(size(model.S,1),size(model.S,2)+1)=1; +0106 model.b=[model.b;zeros(1,size(model.b,2))]; +0107 model.lb=[model.lb;zeros(nMets,1);1]; +0108 model.ub=[model.ub;inf(nMets+1,1)]; +0109 model.rev=[model.rev;zeros(nMets+1,1)]; +0110 model.c=zeros(size(model.S,2),1); +0111 +0112 %Add padding to the reaction annotation to prevent an error in solveLP +0113 padding=1:numel(model.rev); +0114 padding=num2cell(padding)'; +0115 padding=cellfun(@num2str,padding,'uniformoutput',false); +0116 model.rxns=padding; +0117 model.rxnNames=padding; +0118 model.eccodes=padding; +0119 model.rxnMiriams=padding; +0120 model.grRules=padding; +0121 if isfield(model,'genes') +0122 model.rxnGeneMat=sparse(numel(model.rev),numel(model.genes)); +0123 end +0124 model.subSystems=padding; +0125 model.rxnFrom=padding; +0126 model.rxnComps=ones(numel(model.rev),1); +0127 model.rxnNotes=padding; +0128 model.rxnReferences=padding; +0129 model.rxnConfidenceScores=NaN(numel(model.rev),1); +0130 +0131 sol=solveLP(model,1); +0132 if any(sol.x) +0133 %It could be that several metabolites were consumed in order to get the +0134 %best solution. The setdiff is to avoid including the last fake +0135 %metabolite +0136 I=setdiff(find(sol.x(nRxns+1:end)>0.1),size(model.S,1)); +0137 +0138 if any(I) %This should always be true +0139 %Change the coefficients so that only the first is consumed. This +0140 %is not always possible, but it is tested for since it it results +0141 %in more easily interpretable results +0142 +0143 oldS=model.S; +0144 foundSingle=false; +0145 %Test if any of the metabolites could be consumed on their own +0146 for i=1:numel(I) +0147 model.S=oldS; +0148 J=nRxns+1:numel(model.lb)-1; +0149 J(I(i))=[]; +0150 model.S(:,J)=0; +0151 sol=solveLP(model); +0152 if any(sol.x) +0153 foundSingle=true; +0154 break; +0155 end +0156 end +0157 %This means that there was no metabolite which could be consumed on +0158 %its own. Then let all the consumeable metabolites be consumed. +0159 if foundSingle==false +0160 model.S=oldS; +0161 end +0162 if minNrFluxes==true +0163 %Has to add names for the rxns to prevent an error in +0164 %minNrFluxes +0165 model.rxns=cell(numel(model.lb),1); +0166 model.rxns(:)={'TEMP'}; +0167 model.mets=cell(size(model.b,1),1); +0168 model.mets(:)={'TEMP'}; +0169 sol=solveLP(model,3,params); +0170 else +0171 sol=solveLP(model,1); +0172 end +0173 solution=sol.x(1:nRxns); +0174 metabolite=find(sol.x(nRxns+1:end-1)>0.1); +0175 end +0176 end +0177 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/convertCharArray.html b/doc/core/convertCharArray.html new file mode 100644 index 00000000..cf0b6cd7 --- /dev/null +++ b/doc/core/convertCharArray.html @@ -0,0 +1,84 @@ + + + + Description of convertCharArray + + + + + + + + + +
    Home > core > convertCharArray.m
    + + + +

    convertCharArray +

    + +

    PURPOSE ^

    +
    convertCharArray
    + +

    SYNOPSIS ^

    +
    function inputConverted = convertCharArray(funcInput)
    + +

    DESCRIPTION ^

    +
    convertCharArray
    +   Converts input to make sure it is a cell array of character vectors.
    +   String arrays are transformed into character vectors, and if only one
    +   character vector is given. Output is always a cell array, also if only
    +   one character vector is given as input.
    +
    +   Input:
    +   funcInput          function input that should be checked
    +
    +   Output:
    +   inputConverted      cell array of character vectors
    + + +

    CROSS-REFERENCE INFORMATION ^

    +This function calls: + +This function is called by: + + + + + +

    SOURCE CODE ^

    +
    0001 function inputConverted = convertCharArray(funcInput)
    +0002 %convertCharArray
    +0003 %   Converts input to make sure it is a cell array of character vectors.
    +0004 %   String arrays are transformed into character vectors, and if only one
    +0005 %   character vector is given. Output is always a cell array, also if only
    +0006 %   one character vector is given as input.
    +0007 %
    +0008 %   Input:
    +0009 %   funcInput          function input that should be checked
    +0010 %
    +0011 %   Output:
    +0012 %   inputConverted      cell array of character vectors
    +0013 %
    +0014 
    +0015 if ~isempty(funcInput)
    +0016     if ischar(funcInput) || isstring(funcInput)
    +0017         inputConverted = {char(funcInput)};
    +0018     elseif ~iscell(funcInput) && ~(all(cellfun(@ischar, funcInput)) || all(cellfun(@isstring, funcInput)))
    +0019         error([inputname(1) ' should be a (cell array of) character vector(s)'])
    +0020     else
    +0021         inputConverted = cellstr(funcInput);
    +0022     end
    +0023 else
    +0024     inputConverted=[];
    +0025 end
    +0026 end
    +0027
    +
    Generated by m2html © 2005
    + + \ No newline at end of file diff --git a/doc/core/convertToIrrev.html b/doc/core/convertToIrrev.html index dcb995f3..0751733d 100644 --- a/doc/core/convertToIrrev.html +++ b/doc/core/convertToIrrev.html @@ -45,7 +45,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • getIndexes getIndexes
  • This function is called by: @@ -72,81 +72,82 @@

    SOURCE CODE ^if nargin<2 0017 I=true(numel(model.rxns),1); 0018 else -0019 I=getIndexes(model,rxns,'rxns',true); -0020 end -0021 -0022 irrevModel=model; -0023 -0024 revIndexesBool=model.rev~=0 & I; -0025 revIndexes=find(revIndexesBool); -0026 if any(revIndexesBool) -0027 irrevModel.S=[model.S,model.S(:,revIndexes)*-1]; -0028 irrevModel.rev(revIndexes)=0; -0029 irrevModel.rev=[irrevModel.rev;zeros(numel(revIndexes),1)]; -0030 -0031 %Get the limits for all normal and reversible rxns -0032 ubNormal=irrevModel.ub; -0033 ubNormal(revIndexes(ubNormal(revIndexes)<0))=0; -0034 lbNormal=irrevModel.lb; -0035 lbNormal(revIndexes(lbNormal(revIndexes)<0))=0; -0036 ubRev=irrevModel.lb(revIndexes)*-1; -0037 ubRev(ubRev<0)=0; -0038 lbRev=irrevModel.ub(revIndexes)*-1; -0039 lbRev(lbRev<0)=0; -0040 irrevModel.ub=[ubNormal;ubRev]; -0041 irrevModel.lb=[lbNormal;lbRev]; -0042 -0043 %The objective coefficents should be zero for the backwards reversible -0044 %reactions unless they were negative in the original. In that case they -0045 %should be positive for the backwards reversible and deleted from the -0046 %original -0047 irrevC=zeros(numel(revIndexes),1); -0048 -0049 if any(irrevModel.c(revIndexes)<0) -0050 originalC=irrevModel.c(revIndexes); -0051 irrevC(irrevModel.c(revIndexes)<0)=originalC(originalC<0)*-1; -0052 irrevModel.c(irrevModel.c<0 & revIndexesBool)=0; -0053 end -0054 irrevModel.c=[irrevModel.c;irrevC]; -0055 -0056 irrevModel.rxns=[irrevModel.rxns;strcat(irrevModel.rxns(revIndexes),'_REV')]; -0057 irrevModel.rxnNames=[irrevModel.rxnNames;strcat(irrevModel.rxnNames(revIndexes),' (reversible)')]; -0058 -0059 if isfield(irrevModel,'grRules') -0060 irrevModel.grRules=[irrevModel.grRules;irrevModel.grRules(revIndexes,:)]; -0061 end -0062 if isfield(irrevModel,'rxnMiriams') -0063 irrevModel.rxnMiriams=[irrevModel.rxnMiriams;irrevModel.rxnMiriams(revIndexes,:)]; -0064 end -0065 if isfield(irrevModel,'rxnGeneMat') -0066 irrevModel.rxnGeneMat=[irrevModel.rxnGeneMat;irrevModel.rxnGeneMat(revIndexes,:)]; -0067 end -0068 if isfield(irrevModel,'subSystems') -0069 irrevModel.subSystems=[irrevModel.subSystems;irrevModel.subSystems(revIndexes)]; -0070 end -0071 if isfield(irrevModel,'eccodes') -0072 irrevModel.eccodes=[irrevModel.eccodes;irrevModel.eccodes(revIndexes)]; -0073 end -0074 if isfield(irrevModel,'rxnComps') -0075 irrevModel.rxnComps=[irrevModel.rxnComps;irrevModel.rxnComps(revIndexes)]; -0076 end -0077 if isfield(irrevModel,'rxnFrom') -0078 irrevModel.rxnFrom=[irrevModel.rxnFrom;irrevModel.rxnFrom(revIndexes)]; -0079 end -0080 if isfield(irrevModel,'rxnScores') -0081 irrevModel.rxnScores=[irrevModel.rxnScores;irrevModel.rxnScores(revIndexes)]; -0082 end -0083 if isfield(irrevModel,'rxnNotes') -0084 irrevModel.rxnNotes=[irrevModel.rxnNotes;irrevModel.rxnNotes(revIndexes)]; -0085 end -0086 if isfield(irrevModel,'rxnConfidenceScores') -0087 irrevModel.rxnConfidenceScores=[irrevModel.rxnConfidenceScores;irrevModel.rxnConfidenceScores(revIndexes)]; -0088 end -0089 if isfield(irrevModel,'rxnReferences') -0090 irrevModel.rxnReferences=[irrevModel.rxnReferences;irrevModel.rxnReferences(revIndexes)]; -0091 end -0092 end -0093 end +0019 rxns=convertCharArray(rxns); +0020 I=getIndexes(model,rxns,'rxns',true); +0021 end +0022 +0023 irrevModel=model; +0024 +0025 revIndexesBool=model.rev~=0 & I; +0026 revIndexes=find(revIndexesBool); +0027 if any(revIndexesBool) +0028 irrevModel.S=[model.S,model.S(:,revIndexes)*-1]; +0029 irrevModel.rev(revIndexes)=0; +0030 irrevModel.rev=[irrevModel.rev;zeros(numel(revIndexes),1)]; +0031 +0032 %Get the limits for all normal and reversible rxns +0033 ubNormal=irrevModel.ub; +0034 ubNormal(revIndexes(ubNormal(revIndexes)<0))=0; +0035 lbNormal=irrevModel.lb; +0036 lbNormal(revIndexes(lbNormal(revIndexes)<0))=0; +0037 ubRev=irrevModel.lb(revIndexes)*-1; +0038 ubRev(ubRev<0)=0; +0039 lbRev=irrevModel.ub(revIndexes)*-1; +0040 lbRev(lbRev<0)=0; +0041 irrevModel.ub=[ubNormal;ubRev]; +0042 irrevModel.lb=[lbNormal;lbRev]; +0043 +0044 %The objective coefficents should be zero for the backwards reversible +0045 %reactions unless they were negative in the original. In that case they +0046 %should be positive for the backwards reversible and deleted from the +0047 %original +0048 irrevC=zeros(numel(revIndexes),1); +0049 +0050 if any(irrevModel.c(revIndexes)<0) +0051 originalC=irrevModel.c(revIndexes); +0052 irrevC(irrevModel.c(revIndexes)<0)=originalC(originalC<0)*-1; +0053 irrevModel.c(irrevModel.c<0 & revIndexesBool)=0; +0054 end +0055 irrevModel.c=[irrevModel.c;irrevC]; +0056 +0057 irrevModel.rxns=[irrevModel.rxns;strcat(irrevModel.rxns(revIndexes),'_REV')]; +0058 irrevModel.rxnNames=[irrevModel.rxnNames;strcat(irrevModel.rxnNames(revIndexes),' (reversible)')]; +0059 +0060 if isfield(irrevModel,'grRules') +0061 irrevModel.grRules=[irrevModel.grRules;irrevModel.grRules(revIndexes,:)]; +0062 end +0063 if isfield(irrevModel,'rxnMiriams') +0064 irrevModel.rxnMiriams=[irrevModel.rxnMiriams;irrevModel.rxnMiriams(revIndexes,:)]; +0065 end +0066 if isfield(irrevModel,'rxnGeneMat') +0067 irrevModel.rxnGeneMat=[irrevModel.rxnGeneMat;irrevModel.rxnGeneMat(revIndexes,:)]; +0068 end +0069 if isfield(irrevModel,'subSystems') +0070 irrevModel.subSystems=[irrevModel.subSystems;irrevModel.subSystems(revIndexes)]; +0071 end +0072 if isfield(irrevModel,'eccodes') +0073 irrevModel.eccodes=[irrevModel.eccodes;irrevModel.eccodes(revIndexes)]; +0074 end +0075 if isfield(irrevModel,'rxnComps') +0076 irrevModel.rxnComps=[irrevModel.rxnComps;irrevModel.rxnComps(revIndexes)]; +0077 end +0078 if isfield(irrevModel,'rxnFrom') +0079 irrevModel.rxnFrom=[irrevModel.rxnFrom;irrevModel.rxnFrom(revIndexes)]; +0080 end +0081 if isfield(irrevModel,'rxnScores') +0082 irrevModel.rxnScores=[irrevModel.rxnScores;irrevModel.rxnScores(revIndexes)]; +0083 end +0084 if isfield(irrevModel,'rxnNotes') +0085 irrevModel.rxnNotes=[irrevModel.rxnNotes;irrevModel.rxnNotes(revIndexes)]; +0086 end +0087 if isfield(irrevModel,'rxnConfidenceScores') +0088 irrevModel.rxnConfidenceScores=[irrevModel.rxnConfidenceScores;irrevModel.rxnConfidenceScores(revIndexes)]; +0089 end +0090 if isfield(irrevModel,'rxnReferences') +0091 irrevModel.rxnReferences=[irrevModel.rxnReferences;irrevModel.rxnReferences(revIndexes)]; +0092 end +0093 end +0094 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/copyToComps.html b/doc/core/copyToComps.html index 7f0edf81..c018d12c 100644 --- a/doc/core/copyToComps.html +++ b/doc/core/copyToComps.html @@ -57,7 +57,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • getIndexes getIndexes
  • mergeModels mergeModels
  • removeReactions removeReactions
  • This function is called by: @@ -95,64 +95,74 @@

    SOURCE CODE ^if nargin<3 0029 rxns=model.rxns; -0030 end -0031 if nargin<4 -0032 deleteOriginal=false; -0033 end -0034 if nargin<5 -0035 compNames=toComps; -0036 end -0037 if nargin<6 -0038 compOutside=cell(numel(toComps),1); -0039 compOutside(:)={''}; +0030 elseif ~islogical(rxns) && ~isnumeric(rxns) +0031 rxns=convertCharArray(rxns); +0032 end +0033 if nargin<4 +0034 deleteOriginal=false; +0035 end +0036 if nargin<5 +0037 compNames=toComps; +0038 else +0039 compNames=convertCharArray(compNames); 0040 end -0041 -0042 originalID=model.id; -0043 originalName=model.name; -0044 -0045 rxns=getIndexes(model,rxns,'rxns'); -0046 -0047 for i=1:numel(toComps) -0048 %Check if the compartment exists, otherwise add it -0049 [I J]=ismember(toComps(i),model.comps); -0050 if I==false -0051 model.comps=[model.comps;toComps(i)]; -0052 model.compNames=[model.compNames;compNames(i)]; -0053 if isfield(model,'compOutside') -0054 model.compOutside=[model.compOutside;compOutside(i)]; -0055 end -0056 if isfield(model,'compMiriams') -0057 model.compMiriams=[model.compMiriams;cell(1,1)]; -0058 end -0059 J=numel(model.comps); -0060 end -0061 %Copy the reactions by making a model structure with only them, then -0062 %change the localization, and finally merge with the original model -0063 modelToAdd=model; -0064 modelToAdd=removeReactions(modelToAdd,setdiff(1:numel(model.rxns),rxns),true,true); -0065 modelToAdd.rxns=strcat(modelToAdd.rxns,'_',toComps(i)); -0066 modelToAdd.mets=strcat(modelToAdd.mets,'_',toComps(i)); -0067 modelToAdd.comps=modelToAdd.comps(J); -0068 modelToAdd.compNames=modelToAdd.compNames(J); -0069 if isfield(modelToAdd,'compOutside') -0070 modelToAdd.compOutside=modelToAdd.compOutside(J); -0071 end -0072 if isfield(modelToAdd,'compMiriams') -0073 modelToAdd.compMiriams=modelToAdd.compMiriams(J); -0074 end -0075 modelToAdd.metComps=ones(numel(modelToAdd.mets),1); -0076 -0077 %Merge the models -0078 model=mergeModels({model;modelToAdd},'metNames'); -0079 end -0080 -0081 if deleteOriginal==true -0082 model=removeReactions(model,rxns,true,true,true); %Also delete unused compartments -0083 end -0084 -0085 model.id=originalID; -0086 model.name=originalName; -0087 end +0041 if nargin<6 +0042 compOutside=cell(numel(toComps),1); +0043 compOutside(:)={''}; +0044 else +0045 compOutside=convertCharArray(compOutside); +0046 end +0047 +0048 originalID=model.id; +0049 originalName=model.name; +0050 +0051 rxns=getIndexes(model,rxns,'rxns'); +0052 +0053 for i=1:numel(toComps) +0054 %Check if the compartment exists, otherwise add it +0055 [I,J]=ismember(toComps(i),model.comps); +0056 if I==false +0057 model.comps=[model.comps;toComps(i)]; +0058 model.compNames=[model.compNames;compNames(i)]; +0059 if isfield(model,'compOutside') +0060 model.compOutside=[model.compOutside;compOutside(i)]; +0061 end +0062 if isfield(model,'compMiriams') +0063 model.compMiriams=[model.compMiriams;cell(1,1)]; +0064 end +0065 J=numel(model.comps); +0066 end +0067 %Copy the reactions by making a model structure with only them, then +0068 %change the localization, and finally merge with the original model +0069 modelToAdd=model; +0070 modelToAdd=removeReactions(modelToAdd,setdiff(1:numel(model.rxns),rxns),true,true); +0071 modelToAdd.rxns=strcat(modelToAdd.rxns,'_',toComps(i)); +0072 modelToAdd.mets=strcat(modelToAdd.mets,'_',toComps(i)); +0073 modelToAdd.comps=modelToAdd.comps(J); +0074 modelToAdd.compNames=modelToAdd.compNames(J); +0075 if isfield(modelToAdd,'compOutside') +0076 modelToAdd.compOutside=modelToAdd.compOutside(J); +0077 end +0078 if isfield(modelToAdd,'compMiriams') +0079 modelToAdd.compMiriams=modelToAdd.compMiriams(J); +0080 end +0081 modelToAdd.metComps=ones(numel(modelToAdd.mets),1); +0082 +0083 %Merge the models +0084 model=mergeModels({model;modelToAdd},'metNames'); +0085 end +0086 +0087 model=rmfield(model,'rxnFrom'); +0088 model=rmfield(model,'metFrom'); +0089 model=rmfield(model,'geneFrom'); +0090 +0091 if deleteOriginal==true +0092 model=removeReactions(model,rxns,true,true,true); %Also delete unused compartments +0093 end +0094 +0095 model.id=originalID; +0096 model.name=originalName; +0097 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/dispEM.html b/doc/core/dispEM.html index 76a64050..71d0c2c3 100644 --- a/doc/core/dispEM.html +++ b/doc/core/dispEM.html @@ -46,10 +46,10 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • This function is called by: +
  • addGenesRaven addGenesRaven
  • addMets addMets
  • addRxns addRxns
  • addRxnsGenesMets addRxnsGenesMets
  • addTransport addTransport
  • analyzeSampling analyzeSampling
  • buildEquation buildEquation
  • changeRxns changeRxns
  • checkModelStruct checkModelStruct
  • checkRxn checkRxn
  • checkTasks checkTasks
  • compareMultipleModels compareMultipleModels
  • compareRxnsGenesMetsComps compareRxnsGenesMetsComps
  • constructS constructS
  • consumeSomething consumeSomething
  • contractModel contractModel
  • expandModel expandModel
  • fillGaps fillGaps
  • findGeneDeletions findGeneDeletions
  • fitParameters fitParameters
  • fitTasks fitTasks
  • getElementalBalance getElementalBalance
  • getEssentialRxns getEssentialRxns
  • getExpressionStructure getExpressionStructure
  • getFluxZ getFluxZ
  • getMetsInComp getMetsInComp
  • getMinNrFluxes getMinNrFluxes
  • getModelFromHomology getModelFromHomology
  • getRxnsInComp getRxnsInComp
  • guessComposition guessComposition
  • makeSomething makeSomething
  • mapCompartments mapCompartments
  • mergeCompartments mergeCompartments
  • mergeModels mergeModels
  • parseTaskList parseTaskList
  • predictLocalization predictLocalization
  • printFluxes printFluxes
  • randomSampling randomSampling
  • removeBadRxns removeBadRxns
  • reporterMetabolites reporterMetabolites
  • setParam setParam
  • simplifyModel simplifyModel
  • sortModel sortModel
  • standardizeGrRules standardizeGrRules
  • @@ -78,8 +78,8 @@

    SOURCE CODE ^elseif isempty(toList) 0023 return; -0024 elseif ~iscell(toList) -0025 toList={toList}; +0024 else +0025 toList=convertCharArray(toList); 0026 end 0027 if nargin<4 0028 trimWarnings=true; diff --git a/doc/core/findGeneDeletions.html b/doc/core/findGeneDeletions.html index 40937171..eb2a1aea 100644 --- a/doc/core/findGeneDeletions.html +++ b/doc/core/findGeneDeletions.html @@ -138,132 +138,134 @@

    SOURCE CODE ^if nargin<5 0051 oeFactor=10; 0052 end -0053 -0054 %Check that the test type is correct -0055 if ~strcmpi(testType,'sgd') && ~strcmpi(testType,'dgd') && ~strcmpi(testType,'sgo') && ~strcmpi(testType,'dgo') -0056 EM='Incorrect test type'; -0057 dispEM(EM); -0058 end -0059 -0060 %Check that the analysis type is correct -0061 if ~strcmpi(analysisType,'fba') && ~strcmpi(analysisType,'moma') -0062 EM='Incorrect analysis type'; -0063 dispEM(EM); -0064 end -0065 -0066 if (strcmpi(testType,'sgo') || strcmpi(testType,'dgo')) && strcmpi(analysisType,'fba') -0067 EM='Over expression is only available when using MOMA'; -0068 dispEM(EM); -0069 end -0070 -0071 if strcmpi(analysisType,'moma') && nargin<4 -0072 EM='A reference model must be supplied when using MOMA'; -0073 dispEM(EM); -0074 end -0075 -0076 originalGenes=model.genes; -0077 details=zeros(numel(model.genes),1); -0078 -0079 %First simplify the model to reduce the size -0080 model=simplifyModel(model,true,false,true,true); -0081 model=removeReactions(model,{},true,true); %Removes unused genes -0082 details(~ismember(originalGenes,model.genes))=4; -0083 -0084 [~, geneMapping]=ismember(model.genes,originalGenes); +0053 testType=char(testType); +0054 analysisType=char(analysisType); +0055 +0056 %Check that the test type is correct +0057 if ~strcmpi(testType,'sgd') && ~strcmpi(testType,'dgd') && ~strcmpi(testType,'sgo') && ~strcmpi(testType,'dgo') +0058 EM='Incorrect test type'; +0059 dispEM(EM); +0060 end +0061 +0062 %Check that the analysis type is correct +0063 if ~strcmpi(analysisType,'fba') && ~strcmpi(analysisType,'moma') +0064 EM='Incorrect analysis type'; +0065 dispEM(EM); +0066 end +0067 +0068 if (strcmpi(testType,'sgo') || strcmpi(testType,'dgo')) && strcmpi(analysisType,'fba') +0069 EM='Over expression is only available when using MOMA'; +0070 dispEM(EM); +0071 end +0072 +0073 if strcmpi(analysisType,'moma') && nargin<4 +0074 EM='A reference model must be supplied when using MOMA'; +0075 dispEM(EM); +0076 end +0077 +0078 originalGenes=model.genes; +0079 details=zeros(numel(model.genes),1); +0080 +0081 %First simplify the model to reduce the size +0082 model=simplifyModel(model,true,false,true,true); +0083 model=removeReactions(model,{},true,true); %Removes unused genes +0084 details(~ismember(originalGenes,model.genes))=4; 0085 -0086 %Do single deletion/over expression. This is done here since the double -0087 %deletion depends on which single deletions prove lethal (to reduce the -0088 %size of the system) -0089 if strcmpi(testType,'sgd') || strcmpi(testType,'sgo') || strcmpi(testType,'dgd') -0090 fluxes=zeros(numel(model.rxns),numel(model.genes)); -0091 solvable=true(numel(model.genes),1); -0092 for i=1:numel(model.genes) -0093 if strcmpi(testType,'sgd') || strcmpi(testType,'dgd') -0094 %Constrain all reactions involving the gene to 0 -0095 tempModel=removeGenes(model,i,false,false,false); -0096 else -0097 %To over express a gene, the stoichiometry of the corresponding -0098 %reactions are changed so that the same flux leads to a higher -0099 %production -0100 tempModel=model; -0101 I=find(model.rxnGeneMat(:,i)); -0102 tempModel.S(:,I)=tempModel.S(:,I).*oeFactor; -0103 end -0104 if strcmpi(analysisType,'fba') || strcmpi(testType,'dgd') -0105 sol=solveLP(tempModel); -0106 else -0107 [fluxA, ~, flag]=qMOMA(tempModel,refModel); -0108 sol.x=fluxA; -0109 sol.stat=flag; -0110 end -0111 -0112 %If the optimization terminated successfully -0113 if sol.stat==1 -0114 fluxes(:,i)=sol.x; -0115 details(geneMapping(i))=1; -0116 else -0117 solvable(i)=false; -0118 details(geneMapping(i))=2; -0119 end -0120 end -0121 -0122 fluxes=fluxes(:,solvable); -0123 genes=geneMapping(solvable); -0124 end -0125 -0126 %Now do for DGO. This is rather straight forward since it is always -0127 %solvable and it doesn't matter if there are iso-enzymes -0128 if strcmpi(testType,'dgo') -0129 genesToModify=nchoosek(1:numel(model.genes),2); -0130 genes=geneMapping(genesToModify); -0131 %Since I assume that this is never lethal I set the details already -0132 details(geneMapping)=1; -0133 -0134 fluxes=sparse(numel(model.rxns),size(genesToModify,1)); -0135 for i=1:size(genesToModify,1) -0136 I=find(model.rxnGeneMat(:,genesToModify(i,:))); -0137 %To over express a gene, the stoichiometry of the corresponding -0138 %reactions are changed so that the same flux leads to a higher -0139 %production -0140 tempModel=model; -0141 tempModel.S(:,I)=tempModel.S(:,I).*oeFactor; -0142 fluxA=qMOMA(tempModel,refModel); -0143 fluxes(:,i)=fluxA; -0144 end -0145 end -0146 -0147 %For double deletions FBA or MOMA -0148 if strcmpi(testType,'dgd') -0149 %This is a little lazy but it's fine. Check which genes have already -0150 %been deleted in 'sgd' analysis. -0151 [~, I]=ismember(originalGenes(details==1),model.genes); -0152 genesToModify=nchoosek(I,2); -0153 genes=geneMapping(genesToModify); -0154 -0155 fluxes=sparse(numel(model.rxns),size(genesToModify,1)); -0156 for i=1:size(genesToModify,1) -0157 tempModel=removeGenes(model,genesToModify(i,:),false,false,false); -0158 -0159 if strcmpi(analysisType,'fba') -0160 sol=solveLP(tempModel); -0161 else -0162 [fluxA, ~, flag]=qMOMA(tempModel,refModel); -0163 sol.x=fluxA; -0164 sol.stat=flag; -0165 end -0166 -0167 if sol.stat==1 -0168 fluxes(:,i)=sol.x; -0169 end -0170 end -0171 end -0172 -0173 %Map back to the old model -0174 [~, I]=ismember(model.rxns,originalModel.rxns); -0175 temp=fluxes; -0176 fluxes=sparse(numel(originalModel.rxns),size(temp,2)); -0177 fluxes(I,:)=temp; -0178 end +0086 [~, geneMapping]=ismember(model.genes,originalGenes); +0087 +0088 %Do single deletion/over expression. This is done here since the double +0089 %deletion depends on which single deletions prove lethal (to reduce the +0090 %size of the system) +0091 if strcmpi(testType,'sgd') || strcmpi(testType,'sgo') || strcmpi(testType,'dgd') +0092 fluxes=zeros(numel(model.rxns),numel(model.genes)); +0093 solvable=true(numel(model.genes),1); +0094 for i=1:numel(model.genes) +0095 if strcmpi(testType,'sgd') || strcmpi(testType,'dgd') +0096 %Constrain all reactions involving the gene to 0 +0097 tempModel=removeGenes(model,i,false,false,false); +0098 else +0099 %To over express a gene, the stoichiometry of the corresponding +0100 %reactions are changed so that the same flux leads to a higher +0101 %production +0102 tempModel=model; +0103 I=find(model.rxnGeneMat(:,i)); +0104 tempModel.S(:,I)=tempModel.S(:,I).*oeFactor; +0105 end +0106 if strcmpi(analysisType,'fba') || strcmpi(testType,'dgd') +0107 sol=solveLP(tempModel); +0108 else +0109 [fluxA, ~, flag]=qMOMA(tempModel,refModel); +0110 sol.x=fluxA; +0111 sol.stat=flag; +0112 end +0113 +0114 %If the optimization terminated successfully +0115 if sol.stat==1 +0116 fluxes(:,i)=sol.x; +0117 details(geneMapping(i))=1; +0118 else +0119 solvable(i)=false; +0120 details(geneMapping(i))=2; +0121 end +0122 end +0123 +0124 fluxes=fluxes(:,solvable); +0125 genes=geneMapping(solvable); +0126 end +0127 +0128 %Now do for DGO. This is rather straight forward since it is always +0129 %solvable and it doesn't matter if there are iso-enzymes +0130 if strcmpi(testType,'dgo') +0131 genesToModify=nchoosek(1:numel(model.genes),2); +0132 genes=geneMapping(genesToModify); +0133 %Since I assume that this is never lethal I set the details already +0134 details(geneMapping)=1; +0135 +0136 fluxes=sparse(numel(model.rxns),size(genesToModify,1)); +0137 for i=1:size(genesToModify,1) +0138 I=find(model.rxnGeneMat(:,genesToModify(i,:))); +0139 %To over express a gene, the stoichiometry of the corresponding +0140 %reactions are changed so that the same flux leads to a higher +0141 %production +0142 tempModel=model; +0143 tempModel.S(:,I)=tempModel.S(:,I).*oeFactor; +0144 fluxA=qMOMA(tempModel,refModel); +0145 fluxes(:,i)=fluxA; +0146 end +0147 end +0148 +0149 %For double deletions FBA or MOMA +0150 if strcmpi(testType,'dgd') +0151 %This is a little lazy but it's fine. Check which genes have already +0152 %been deleted in 'sgd' analysis. +0153 [~, I]=ismember(originalGenes(details==1),model.genes); +0154 genesToModify=nchoosek(I,2); +0155 genes=geneMapping(genesToModify); +0156 +0157 fluxes=sparse(numel(model.rxns),size(genesToModify,1)); +0158 for i=1:size(genesToModify,1) +0159 tempModel=removeGenes(model,genesToModify(i,:),false,false,false); +0160 +0161 if strcmpi(analysisType,'fba') +0162 sol=solveLP(tempModel); +0163 else +0164 [fluxA, ~, flag]=qMOMA(tempModel,refModel); +0165 sol.x=fluxA; +0166 sol.stat=flag; +0167 end +0168 +0169 if sol.stat==1 +0170 fluxes(:,i)=sol.x; +0171 end +0172 end +0173 end +0174 +0175 %Map back to the old model +0176 [~, I]=ismember(model.rxns,originalModel.rxns); +0177 temp=fluxes; +0178 fluxes=sparse(numel(originalModel.rxns),size(temp,2)); +0179 fluxes(I,:)=temp; +0180 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/findRAVENroot.html b/doc/core/findRAVENroot.html new file mode 100644 index 00000000..eebd5f87 --- /dev/null +++ b/doc/core/findRAVENroot.html @@ -0,0 +1,78 @@ + + + + Description of findRAVENroot + + + + + + + + + +
    Home > core > findRAVENroot.m
    + + + +

    findRAVENroot +

    + +

    PURPOSE ^

    +
    findRAVENroot
    + +

    SYNOPSIS ^

    +
    function [ravenPath, prevDir] = findRAVENroot()
    + +

    DESCRIPTION ^

    +
     findRAVENroot
    +   Finds the root of the RAVEN directory, by searching for the path to
    +   RAVEN2.png. Can also record the current directory, in case a function will
    +   use the ravenPath to navigate to a precise folder, and it should return to
    +   the previous directory afterwards. See e.g. optimizeProb calling glpk.
    + + +

    CROSS-REFERENCE INFORMATION ^

    +This function calls: + +This function is called by: + + + + + +

    SOURCE CODE ^

    +
    0001 function [ravenPath, prevDir] = findRAVENroot()
    +0002 % findRAVENroot
    +0003 %   Finds the root of the RAVEN directory, by searching for the path to
    +0004 %   RAVEN2.png. Can also record the current directory, in case a function will
    +0005 %   use the ravenPath to navigate to a precise folder, and it should return to
    +0006 %   the previous directory afterwards. See e.g. optimizeProb calling glpk.
    +0007 
    +0008 ST=dbstack('-completenames');
    +0009 prevDir = pwd();
    +0010 if length(ST)>1
    +0011     ravenPath=ST(2).file; % In case findRAVENroot is run via another function
    +0012 else
    +0013     ravenPath=ST(1).file;
    +0014 end
    +0015 rootFound = 0;
    +0016 while rootFound == 0
    +0017     isRoot = exist(fullfile(ravenPath,'RAVEN2.png'),'file');
    +0018     if isRoot == 2
    +0019         rootFound = 1;
    +0020     else
    +0021         ravenPathOld = ravenPath;
    +0022         ravenPath = fileparts(ravenPath);
    +0023         if strcmp(ravenPathOld,ravenPath)
    +0024             error('Cannot find the RAVEN root directory. Make sure you have not removed the RAVEN2.png file from your RAVEN installation.')
    +0025         end
    +0026     end
    +0027 end
    +
    Generated by m2html © 2005
    + + \ No newline at end of file diff --git a/doc/core/fitParameters.html b/doc/core/fitParameters.html index f40cba8b..1d60849a 100644 --- a/doc/core/fitParameters.html +++ b/doc/core/fitParameters.html @@ -31,7 +31,8 @@

    DESCRIPTION ^DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • dispEM dispEM
  • This function is called by: @@ -82,113 +83,117 @@

    SOURCE CODE ^% Fits parameters such as maintenance ATP by quadratic programming 0004 % 0005 % model a model structure -0006 % xRxns cell array with the IDs of the reactions that will be fixed for each data point -0007 % xValues matrix with the corresponding values for each -0008 % xRxns (columns are reactions) -0009 % rxnsToFit cell array with the IDs of reactions that will be fitted to -0010 % valuesToFit matrix with the corresponding values for each -0011 % rxnsToFit (columns are reactions) -0012 % parameterPositions stucture that determines where the parameters are in the -0013 % stoichiometric matrix. Contains the fields: -0014 % position cell array of vectors where each element contains -0015 % the positions in the S-matrix for that parameter -0016 % isNegative cell array of vectors where the elements are true -0017 % if that position should be the negative of the -0018 % fitted value (to differentiate between -0019 % production/consumption) -0020 % fitToRatio if the ratio of simulated to measured values should -0021 % be fitted instead of the absolute value. Used to prevent -0022 % large fluxes from having too large impact (opt, -0023 % default true) -0024 % initialGuess initial guess of the parameters (opt) -0025 % plotFitting true if the resulting fitting should be plotted -0026 % (opt, default false) -0027 % -0028 % parameters fitted parameters in the same order as in -0029 % parameterPositions -0030 % fitnessScore the correponding residual sum of squares -0031 % newModel updated model structure with the fitted parameters -0032 % -0033 % Usage: [parameters, fitnessScore, exitFlag, newModel]=fitParameters(model,... -0034 % xRxns,xValues,rxnsToFit,valuesToFit,parameterPositions,fitToRatio,... -0035 % initialGuess,plotFitting) -0036 -0037 if nargin<7 -0038 fitToRatio=true; -0039 end -0040 if nargin<8 -0041 initialGuess=ones(numel(parameterPositions.position),1); -0042 end -0043 if isempty(initialGuess) -0044 initialGuess=ones(numel(parameterPositions.position),1); -0045 end -0046 if nargin<9 -0047 plotFitting=false; -0048 end -0049 -0050 %Find the indexes of reactions that will be fitted -0051 [I, rxnsToFitIndexes]=ismember(rxnsToFit,model.rxns); -0052 -0053 if ~all(I) -0054 EM='Could not find all reactions in rxnsToFit'; -0055 dispEM(EM); -0056 end -0057 -0058 %Find the indexes of reactions that will be used for constraints. -0059 [I, xRxnsIndexes]=ismember(xRxns,model.rxns); -0060 -0061 if ~all(I) -0062 EM='Could not find all reactions in xRxns'; -0063 dispEM(EM); -0064 end -0065 -0066 [parameters, fitnessScore, exitFlag]=fminsearch(@(parameters) getRSS(parameters,model,xRxnsIndexes,xValues,rxnsToFitIndexes,valuesToFit,parameterPositions,fitToRatio),initialGuess); -0067 -0068 parameters=abs(parameters); +0006 % xRxns cell array with the IDs of the reactions that will be +0007 % fixed for each data point +0008 % xValues matrix with the corresponding values for each +0009 % xRxns (columns are reactions) +0010 % rxnsToFit cell array with the IDs of reactions that will be fitted to +0011 % valuesToFit matrix with the corresponding values for each +0012 % rxnsToFit (columns are reactions) +0013 % parameterPositions stucture that determines where the parameters are in the +0014 % stoichiometric matrix. Contains the fields: +0015 % position cell array of vectors where each element contains +0016 % the positions in the S-matrix for that parameter +0017 % isNegative cell array of vectors where the elements are true +0018 % if that position should be the negative of the +0019 % fitted value (to differentiate between +0020 % production/consumption) +0021 % fitToRatio if the ratio of simulated to measured values should +0022 % be fitted instead of the absolute value. Used to prevent +0023 % large fluxes from having too large impact (opt, +0024 % default true) +0025 % initialGuess initial guess of the parameters (opt) +0026 % plotFitting true if the resulting fitting should be plotted +0027 % (opt, default false) +0028 % +0029 % parameters fitted parameters in the same order as in +0030 % parameterPositions +0031 % fitnessScore the correponding residual sum of squares +0032 % newModel updated model structure with the fitted parameters +0033 % +0034 % Usage: [parameters, fitnessScore, exitFlag, newModel]=fitParameters(model,... +0035 % xRxns,xValues,rxnsToFit,valuesToFit,parameterPositions,fitToRatio,... +0036 % initialGuess,plotFitting) +0037 +0038 if nargin<7 +0039 fitToRatio=true; +0040 end +0041 if nargin<8 +0042 initialGuess=ones(numel(parameterPositions.position),1); +0043 end +0044 if isempty(initialGuess) +0045 initialGuess=ones(numel(parameterPositions.position),1); +0046 end +0047 if nargin<9 +0048 plotFitting=false; +0049 end +0050 +0051 xRxns=convertCharArray(xRxns); +0052 rxnsToFit=convertCharArray(rxnsToFit); +0053 +0054 %Find the indexes of reactions that will be fitted +0055 [I, rxnsToFitIndexes]=ismember(rxnsToFit,model.rxns); +0056 +0057 if ~all(I) +0058 EM='Could not find all reactions in rxnsToFit'; +0059 dispEM(EM); +0060 end +0061 +0062 %Find the indexes of reactions that will be used for constraints. +0063 [I, xRxnsIndexes]=ismember(xRxns,model.rxns); +0064 +0065 if ~all(I) +0066 EM='Could not find all reactions in xRxns'; +0067 dispEM(EM); +0068 end 0069 -0070 if plotFitting==true -0071 %Set the resulting parameters -0072 [~, resultingFluxes, newModel]=getRSS(parameters,model,xRxnsIndexes,xValues,rxnsToFitIndexes,valuesToFit,parameterPositions,true); -0073 plot(xValues,valuesToFit,'o',xValues,resultingFluxes,'-*'); -0074 end -0075 end -0076 -0077 function [rss, resultingFluxes, newModel]=getRSS(parameters,model,xRxnsIndexes,xValues,rxnsToFitIndexes,valuesToFit,parameterPositions,fitToRatio) -0078 parameters=abs(parameters); -0079 -0080 %Set the parameters at the positions specified in parameterPositions -0081 for i=1:numel(parameterPositions.position) -0082 %Set positive -0083 model.S(parameterPositions.position{i}(parameterPositions.isNegative{i}==false))=parameters(i); -0084 -0085 %Set negative -0086 model.S(parameterPositions.position{i}(parameterPositions.isNegative{i}==true))=parameters(i)*-1; -0087 end -0088 -0089 %Also return an updated model -0090 newModel=model; -0091 -0092 %Loop through each data point, set xRxns to xValues and calculate the sum -0093 %of squares for the rxnsToFit -0094 rss=0; -0095 resultingFluxes=[]; -0096 for i=1:size(xValues,1) -0097 %Fix for more xRxns! -0098 model.lb(xRxnsIndexes)=xValues(i,:); -0099 model.ub(xRxnsIndexes)=xValues(i); -0100 -0101 sol=solveLP(model); -0102 -0103 %Calculate the rss -0104 if fitToRatio==false -0105 rs=sol.x(rxnsToFitIndexes)'-valuesToFit(i,:); -0106 else -0107 rs=sol.x(rxnsToFitIndexes)'./valuesToFit(i,:)-ones(1,size(valuesToFit,2)); -0108 end -0109 rss=rss+rs*rs'; -0110 resultingFluxes=[resultingFluxes sol.x(rxnsToFitIndexes)]; -0111 end -0112 end +0070 [parameters, fitnessScore, exitFlag]=fminsearch(@(parameters) getRSS(parameters,model,xRxnsIndexes,xValues,rxnsToFitIndexes,valuesToFit,parameterPositions,fitToRatio),initialGuess); +0071 +0072 parameters=abs(parameters); +0073 +0074 if plotFitting==true +0075 %Set the resulting parameters +0076 [~, resultingFluxes, newModel]=getRSS(parameters,model,xRxnsIndexes,xValues,rxnsToFitIndexes,valuesToFit,parameterPositions,true); +0077 plot(xValues,valuesToFit,'o',xValues,resultingFluxes,'-*'); +0078 end +0079 end +0080 +0081 function [rss, resultingFluxes, newModel]=getRSS(parameters,model,xRxnsIndexes,xValues,rxnsToFitIndexes,valuesToFit,parameterPositions,fitToRatio) +0082 parameters=abs(parameters); +0083 +0084 %Set the parameters at the positions specified in parameterPositions +0085 for i=1:numel(parameterPositions.position) +0086 %Set positive +0087 model.S(parameterPositions.position{i}(parameterPositions.isNegative{i}==false))=parameters(i); +0088 +0089 %Set negative +0090 model.S(parameterPositions.position{i}(parameterPositions.isNegative{i}==true))=parameters(i)*-1; +0091 end +0092 +0093 %Also return an updated model +0094 newModel=model; +0095 +0096 %Loop through each data point, set xRxns to xValues and calculate the sum +0097 %of squares for the rxnsToFit +0098 rss=0; +0099 resultingFluxes=[]; +0100 for i=1:size(xValues,1) +0101 %Fix for more xRxns! +0102 model.lb(xRxnsIndexes)=xValues(i,:); +0103 model.ub(xRxnsIndexes)=xValues(i); +0104 +0105 sol=solveLP(model); +0106 +0107 %Calculate the rss +0108 if fitToRatio==false +0109 rs=sol.x(rxnsToFitIndexes)'-valuesToFit(i,:); +0110 else +0111 rs=sol.x(rxnsToFitIndexes)'./valuesToFit(i,:)-ones(1,size(valuesToFit,2)); +0112 end +0113 rss=rss+rs*rs'; +0114 resultingFluxes=[resultingFluxes sol.x(rxnsToFitIndexes)]; +0115 end +0116 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/followChanged.html b/doc/core/followChanged.html index 73193020..54a3d0b8 100644 --- a/doc/core/followChanged.html +++ b/doc/core/followChanged.html @@ -52,7 +52,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • constructEquations constructEquations
  • convertCharArray convertCharArray
  • This function is called by: @@ -95,74 +95,76 @@

    SOURCE CODE ^end 0033 if nargin<7 0034 metaboliteList=[]; -0035 end -0036 -0037 %If a metabolite list is to be used, then find all the reactions involving -0038 %any of those metabolites Finds the metabolites -0039 if nargin>6 -0040 reactionIndexes=[]; -0041 for i=1:length(metaboliteList) -0042 metaboliteIndex=find(strcmpi(metaboliteList(i),model.metNames)); %Should use id maybe, setting -0043 if ~isempty(metaboliteIndex) -0044 [~, b]=find(model.S(metaboliteIndex,:)); -0045 reactionIndexes=[reactionIndexes; b(:)]; -0046 else -0047 fprintf('Could not find any reactions with the metabolite %s\n\n',char(metaboliteList(i))) -0048 end -0049 end -0050 reactionIndexes=unique(reactionIndexes); -0051 else -0052 reactionIndexes=(1:length(fluxesA))'; -0053 end -0054 -0055 %Finds the reactions where either flux is at or above the cutOffFlux value -0056 in1=find(abs(fluxesA(reactionIndexes))>=cutOffFlux)'; -0057 in2=find(abs(fluxesB(reactionIndexes))>=cutOffFlux)'; -0058 ineither=reactionIndexes(unique([in1 in2])); -0059 -0060 %Keep only those solutions where the difference is larger than or equal to -0061 %cutOffDiff -0062 ineither=ineither(find(abs(fluxesA(ineither)-fluxesB(ineither))>=cutOffDiff)); -0063 -0064 %Finds the reactions where the fluxes differ more than cutOffChange percent -0065 %First check those fluxes that are non-zero in solution1.x -0066 nonZeroFluxes=ineither(find(fluxesA(ineither))); -0067 quota=1+cutOffChange/100; -0068 larger=nonZeroFluxes(find((fluxesB(nonZeroFluxes)./fluxesA(nonZeroFluxes))>=(quota)))'; -0069 smaller=nonZeroFluxes(find((fluxesB(nonZeroFluxes)./fluxesA(nonZeroFluxes))<(1/quota)))'; -0070 fluxIndexes=[larger smaller]; -0071 -0072 %Then add those where solution1 has a zero flux -0073 zeroFluxes=ineither(find(fluxesA(ineither)==0)); -0074 fluxIndexes=unique([fluxIndexes zeroFluxes(find(abs(fluxesB(zeroFluxes))>=cutOffFlux))']); -0075 -0076 formulas=constructEquations(model,model.rxns(fluxIndexes)); +0035 else +0036 metaboliteList=convertCharArray(metaboliteList); +0037 end +0038 +0039 %If a metabolite list is to be used, then find all the reactions involving +0040 %any of those metabolites Finds the metabolites +0041 if nargin>6 +0042 reactionIndexes=[]; +0043 for i=1:length(metaboliteList) +0044 metaboliteIndex=find(strcmpi(metaboliteList(i),model.metNames)); %Should use id maybe, setting +0045 if ~isempty(metaboliteIndex) +0046 [~, b]=find(model.S(metaboliteIndex,:)); +0047 reactionIndexes=[reactionIndexes; b(:)]; +0048 else +0049 fprintf('Could not find any reactions with the metabolite %s\n\n',char(metaboliteList(i))) +0050 end +0051 end +0052 reactionIndexes=unique(reactionIndexes); +0053 else +0054 reactionIndexes=(1:length(fluxesA))'; +0055 end +0056 +0057 %Finds the reactions where either flux is at or above the cutOffFlux value +0058 in1=find(abs(fluxesA(reactionIndexes))>=cutOffFlux)'; +0059 in2=find(abs(fluxesB(reactionIndexes))>=cutOffFlux)'; +0060 ineither=reactionIndexes(unique([in1 in2])); +0061 +0062 %Keep only those solutions where the difference is larger than or equal to +0063 %cutOffDiff +0064 ineither=ineither(find(abs(fluxesA(ineither)-fluxesB(ineither))>=cutOffDiff)); +0065 +0066 %Finds the reactions where the fluxes differ more than cutOffChange percent +0067 %First check those fluxes that are non-zero in solution1.x +0068 nonZeroFluxes=ineither(find(fluxesA(ineither))); +0069 quota=1+cutOffChange/100; +0070 larger=nonZeroFluxes(find((fluxesB(nonZeroFluxes)./fluxesA(nonZeroFluxes))>=(quota)))'; +0071 smaller=nonZeroFluxes(find((fluxesB(nonZeroFluxes)./fluxesA(nonZeroFluxes))<(1/quota)))'; +0072 fluxIndexes=[larger smaller]; +0073 +0074 %Then add those where solution1 has a zero flux +0075 zeroFluxes=ineither(find(fluxesA(ineither)==0)); +0076 fluxIndexes=unique([fluxIndexes zeroFluxes(find(abs(fluxesB(zeroFluxes))>=cutOffFlux))']); 0077 -0078 if nargin>4 -0079 if nargin>5 -0080 fprintf('These reactions have flux values that differ by more than %s percent, absolute values above %s, and a total difference above %s (%s reactions)\n\n',num2str(cutOffChange),num2str(cutOffFlux),num2str(cutOffDiff),num2str(length(formulas))); -0081 else -0082 fprintf('These reactions have flux values that differ by more than %s percent and absolute values above %s (%s reactions)\n\n',num2str(cutOffChange),num2str(cutOffFlux),num2str(length(formulas))); -0083 end -0084 else -0085 fprintf('These reactions have flux values that differ by more than %s percent (%s reactions)\n\n',num2str(cutOffChange),num2str(length(formulas))); -0086 end -0087 -0088 metaboliteNames=[]; -0089 for i=1:length(metaboliteList) -0090 metaboliteNames=[metaboliteNames char(metaboliteList(i)) ' ']; -0091 end -0092 -0093 if ~isempty(metaboliteNames) -0094 fprintf('Only prints reactions involving one or more of the following metabolites:\n%s\n\n',metaboliteNames) -0095 end -0096 -0097 for i=1:length(formulas) -0098 fluxText=['Flux: ' num2str(fluxesA(fluxIndexes(i))) ' Reference flux: ' num2str(fluxesB(fluxIndexes(i))) ' Difference: ' num2str(fluxesA(fluxIndexes(i))-fluxesB(fluxIndexes(i)))]; -0099 fprintf('%s: %s\n\t%s\n\t%s\n\n', char(model.rxns(fluxIndexes(i))), char(formulas(i)),... -0100 char(model.rxnNames(fluxIndexes(i))),fluxText); -0101 end -0102 end +0078 formulas=constructEquations(model,model.rxns(fluxIndexes)); +0079 +0080 if nargin>4 +0081 if nargin>5 +0082 fprintf('These reactions have flux values that differ by more than %s percent, absolute values above %s, and a total difference above %s (%s reactions)\n\n',num2str(cutOffChange),num2str(cutOffFlux),num2str(cutOffDiff),num2str(length(formulas))); +0083 else +0084 fprintf('These reactions have flux values that differ by more than %s percent and absolute values above %s (%s reactions)\n\n',num2str(cutOffChange),num2str(cutOffFlux),num2str(length(formulas))); +0085 end +0086 else +0087 fprintf('These reactions have flux values that differ by more than %s percent (%s reactions)\n\n',num2str(cutOffChange),num2str(length(formulas))); +0088 end +0089 +0090 metaboliteNames=[]; +0091 for i=1:length(metaboliteList) +0092 metaboliteNames=[metaboliteNames char(metaboliteList(i)) ' ']; +0093 end +0094 +0095 if ~isempty(metaboliteNames) +0096 fprintf('Only prints reactions involving one or more of the following metabolites:\n%s\n\n',metaboliteNames) +0097 end +0098 +0099 for i=1:length(formulas) +0100 fluxText=['Flux: ' num2str(fluxesA(fluxIndexes(i))) ' Reference flux: ' num2str(fluxesB(fluxIndexes(i))) ' Difference: ' num2str(fluxesA(fluxIndexes(i))-fluxesB(fluxIndexes(i)))]; +0101 fprintf('%s: %s\n\t%s\n\t%s\n\n', char(model.rxns(fluxIndexes(i))), char(formulas(i)),... +0102 char(model.rxnNames(fluxIndexes(i))),fluxText); +0103 end +0104 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/generateNewIds.html b/doc/core/generateNewIds.html index fb074a5e..dff156b8 100644 --- a/doc/core/generateNewIds.html +++ b/doc/core/generateNewIds.html @@ -75,41 +75,43 @@

    SOURCE CODE ^% 0017 % Usage: newIds=generateNewIds(model,type,prefix,quantity,numLength) 0018 % -0019 -0020 if type=='rxns' -0021 existingIds=model.rxns; -0022 elseif type=='mets' -0023 existingIds=model.mets; -0024 else -0025 error('type should be either ''rxns'' or ''mets''.') -0026 end -0027 if nargin<5 -0028 numLength=4; -0029 end -0030 -0031 % Subset only existingIds that have the prefix -0032 existingIds=existingIds(~cellfun(@isempty,regexp(existingIds,['^' prefix]))); -0033 -0034 if ~isempty(existingIds) -0035 existingIds=regexprep(existingIds,['^' prefix],''); -0036 existingIds=sort(existingIds); -0037 lastId=existingIds{end}; -0038 numLength=length(lastId); -0039 lastId=str2double(lastId); -0040 else -0041 lastId=0; -0042 fprintf(['No ' type ' ids with prefix "' prefix ... -0043 '" currently exist in the model. The first new id will be "' ... -0044 [prefix,num2str(1,['%0' num2str(numLength) 'd'])] '"\n'],'%s') -0045 lastId=0; -0046 end -0047 -0048 newIds=cell(quantity,1); +0019 type=char(type); +0020 prefix=char(prefix); +0021 +0022 if type=='rxns' +0023 existingIds=model.rxns; +0024 elseif type=='mets' +0025 existingIds=model.mets; +0026 else +0027 error('type should be either ''rxns'' or ''mets''.') +0028 end +0029 if nargin<5 +0030 numLength=4; +0031 end +0032 +0033 % Subset only existingIds that have the prefix +0034 existingIds=existingIds(~cellfun(@isempty,regexp(existingIds,['^' prefix]))); +0035 +0036 if ~isempty(existingIds) +0037 existingIds=regexprep(existingIds,['^' prefix],''); +0038 existingIds=sort(existingIds); +0039 lastId=existingIds{end}; +0040 numLength=length(lastId); +0041 lastId=str2double(lastId); +0042 else +0043 lastId=0; +0044 fprintf(['No ' type ' ids with prefix "' prefix ... +0045 '" currently exist in the model. The first new id will be "' ... +0046 [prefix,num2str(1,['%0' num2str(numLength) 'd'])] '"\n'],'%s') +0047 lastId=0; +0048 end 0049 -0050 for k=1:quantity -0051 newIds{k}=[prefix,num2str(k+lastId,['%0' num2str(numLength) 'd'])]; -0052 end -0053 end +0050 newIds=cell(quantity,1); +0051 +0052 for k=1:quantity +0053 newIds{k}=[prefix,num2str(k+lastId,['%0' num2str(numLength) 'd'])]; +0054 end +0055 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/getAllRxnsFromGenes.html b/doc/core/getAllRxnsFromGenes.html index d1b9e4c0..d1eedca2 100644 --- a/doc/core/getAllRxnsFromGenes.html +++ b/doc/core/getAllRxnsFromGenes.html @@ -47,7 +47,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • getIndexes getIndexes
  • This function is called by: @@ -73,26 +73,24 @@

    SOURCE CODE ^% 0016 % Usage: allRxns=getAllRxnsFromGenes(model,rxns) 0017 -0018 %If the supplied object is a character array, then convert it to a cell -0019 %array -0020 if ischar(rxns) -0021 rxns={rxns}; -0022 end -0023 -0024 rxnIdx=getIndexes(model,rxns,'rxns'); -0025 [~, geneIdx]=find(model.rxnGeneMat(rxnIdx,:)); -0026 [allRxns, ~]=find(model.rxnGeneMat(:,geneIdx)); -0027 if iscell(rxns) -0028 allRxns=unique([model.rxns(allRxns);model.rxns(rxnIdx)]); -0029 elseif isnumeric(rxns) || islogical(rxns) -0030 allRxns=unique([allRxns;rxnIdx]); -0031 if islogical(rxns) -0032 temp=false(numel(model.rxns),1); -0033 temp(allRxns)=true; -0034 allRxns=temp; -0035 end -0036 end -0037 end +0018 if ~islogical(rxns) && ~isnumeric(rxns) +0019 rxns=convertCharArray(rxns); +0020 end +0021 +0022 rxnIdx=getIndexes(model,rxns,'rxns'); +0023 [~, geneIdx]=find(model.rxnGeneMat(rxnIdx,:)); +0024 [allRxns, ~]=find(model.rxnGeneMat(:,geneIdx)); +0025 if iscell(rxns) +0026 allRxns=unique([model.rxns(allRxns);model.rxns(rxnIdx)]); +0027 elseif isnumeric(rxns) || islogical(rxns) +0028 allRxns=unique([allRxns;rxnIdx]); +0029 if islogical(rxns) +0030 temp=false(numel(model.rxns),1); +0031 temp(allRxns)=true; +0032 allRxns=temp; +0033 end +0034 end +0035 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/getAllowedBounds.html b/doc/core/getAllowedBounds.html index fc681b32..4f15dc97 100644 --- a/doc/core/getAllowedBounds.html +++ b/doc/core/getAllowedBounds.html @@ -48,7 +48,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • getIndexes getIndexes
  • This function is called by: @@ -77,41 +77,42 @@

    SOURCE CODE ^if nargin<2 0020 rxns=1:numel(model.rxns); -0021 else -0022 rxns=getIndexes(model,rxns, 'rxns'); -0023 end -0024 -0025 minFluxes=zeros(numel(rxns),1); -0026 maxFluxes=zeros(numel(rxns),1); -0027 exitFlags=zeros(numel(rxns),2); -0028 -0029 c=zeros(numel(model.rxns),1); -0030 hsSolMin=[]; -0031 hsSolMax=[]; -0032 for i=1:numel(rxns) -0033 model.c=c; -0034 -0035 %Get minimal flux -0036 model.c(rxns(i))=-1; -0037 [solution, hsSolMin]=solveLP(model,0,[],hsSolMin); -0038 exitFlags(i,1)=solution.stat; -0039 if ~isempty(solution.f) -0040 minFluxes(i)=solution.x(rxns(i)); -0041 else -0042 minFluxes(i)=NaN; -0043 end -0044 -0045 %Get maximal flux -0046 model.c(rxns(i))=1; -0047 [solution, hsSolMax]=solveLP(model,0,[],hsSolMax); -0048 exitFlags(i,2)=solution.stat; -0049 if ~isempty(solution.f) -0050 maxFluxes(i)=solution.x(rxns(i)); -0051 else -0052 maxFluxes(i)=NaN; -0053 end -0054 end -0055 end +0021 elseif ~islogical(rxns) && ~isnumeric(rxns) +0022 rxns=convertCharArray(rxns); +0023 rxns=getIndexes(model,rxns, 'rxns'); +0024 end +0025 +0026 minFluxes=zeros(numel(rxns),1); +0027 maxFluxes=zeros(numel(rxns),1); +0028 exitFlags=zeros(numel(rxns),2); +0029 +0030 c=zeros(numel(model.rxns),1); +0031 hsSolMin=[]; +0032 hsSolMax=[]; +0033 for i=1:numel(rxns) +0034 model.c=c; +0035 +0036 %Get minimal flux +0037 model.c(rxns(i))=-1; +0038 [solution, hsSolMin]=solveLP(model,0,[],hsSolMin); +0039 exitFlags(i,1)=solution.stat; +0040 if ~isempty(solution.f) +0041 minFluxes(i)=solution.x(rxns(i)); +0042 else +0043 minFluxes(i)=NaN; +0044 end +0045 +0046 %Get maximal flux +0047 model.c(rxns(i))=1; +0048 [solution, hsSolMax]=solveLP(model,0,[],hsSolMax); +0049 exitFlags(i,2)=solution.stat; +0050 if ~isempty(solution.f) +0051 maxFluxes(i)=solution.x(rxns(i)); +0052 else +0053 maxFluxes(i)=NaN; +0054 end +0055 end +0056 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/getElementalBalance.html b/doc/core/getElementalBalance.html index aada6e53..ce78a54f 100644 --- a/doc/core/getElementalBalance.html +++ b/doc/core/getElementalBalance.html @@ -58,7 +58,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • dispEM dispEM
  • getIndexes getIndexes
  • parseFormulas parseFormulas
  • removeReactions removeReactions
  • This function is called by: @@ -97,117 +97,119 @@

    SOURCE CODE ^if nargin<2 0030 rxns=[]; -0031 end -0032 -0033 if nargin<3 -0034 printUnbalanced=false; -0035 end -0036 -0037 if nargin<4 -0038 printUnparsable=false; -0039 end -0040 -0041 if ~isempty(rxns) -0042 indexes=~getIndexes(model,rxns,'rxns',true); -0043 model=removeReactions(model,indexes,true); -0044 end -0045 -0046 balanceStructure.balanceStatus=nan(numel(model.rxns),1); +0031 elseif ~islogical(rxns) && ~isnumeric(rxns) +0032 rxns=convertCharArray(rxns); +0033 end +0034 +0035 if nargin<3 +0036 printUnbalanced=false; +0037 end +0038 +0039 if nargin<4 +0040 printUnparsable=false; +0041 end +0042 +0043 if ~isempty(rxns) +0044 indexes=~getIndexes(model,rxns,'rxns',true); +0045 model=removeReactions(model,indexes,true); +0046 end 0047 -0048 %Get the formulas -0049 if isfield(model,'metFormulas') -0050 [balanceStructure.elements, useMat, exitFlag]=parseFormulas(model.metFormulas, true); -0051 else -0052 if isfield(model,'inchis') -0053 [balanceStructure.elements, useMat, exitFlag]=parseFormulas(model.inchis, true,true); -0054 else -0055 EM='The model must contain either the "metFormulas" or the "inchis" field in order to test for elemental balancing'; -0056 dispEM(EM); -0057 end -0058 end -0059 -0060 balanceStructure.leftComp=zeros(numel(model.rxns),numel(balanceStructure.elements.names)); -0061 balanceStructure.rightComp=balanceStructure.leftComp; -0062 -0063 %Look at the right and left side of the reactions separately -0064 S{1}=model.S; -0065 S{2}=model.S; -0066 S{1}(S{1}>0)=0; %Left side -0067 S{2}(S{2}<0)=0; %Right side -0068 S{1}=abs(S{1}); %Both should have positive values -0069 -0070 %First do it for left side and then for right -0071 for i=1:2 -0072 for j=1:numel(model.rxns) -0073 %Get the balance status of the involved mets -0074 I=exitFlag(S{i}(:,j)~=0); -0075 if any(I==-1) -0076 balanceStructure.balanceStatus(j)=-2; -0077 end -0078 if any(I==0) -0079 %Don't change a more serious error to a less serious one -0080 balanceStructure.balanceStatus(j)=min(-1,balanceStructure.balanceStatus(j)); -0081 end -0082 %Loop through each element -0083 for k=1:numel(balanceStructure.elements.names) -0084 if i==1 -0085 balanceStructure.leftComp(j,k)=sum(S{i}(:,j).*useMat(:,k)); -0086 else -0087 balanceStructure.rightComp(j,k)=sum(S{i}(:,j).*useMat(:,k)); -0088 end -0089 end -0090 end -0091 end -0092 -0093 %Now compare the left and right sides to find which are unbalanced. This is -0094 %done even if the reaction as a whole couldn't be balanced -0095 total=abs(balanceStructure.rightComp-balanceStructure.leftComp)>10^-8; %To deal with roundoff error -0096 -0097 %Get which reactions are unbalanced. Don't change an error to just -0098 %unbalanced -0099 balanceStructure.balanceStatus(any(total,2))=min(balanceStructure.balanceStatus(any(total,2)),0); -0100 -0101 %The remaining ones are all balanced -0102 balanceStructure.balanceStatus(isnan(balanceStructure.balanceStatus))=1; -0103 -0104 %Print warnings -0105 toPrint=[]; -0106 if printUnbalanced==true -0107 toPrint=[toPrint;find(balanceStructure.balanceStatus==0)]; -0108 end -0109 if printUnparsable==true -0110 toPrint=[toPrint;find(balanceStructure.balanceStatus<0)]; -0111 end -0112 -0113 toPrint=sort(toPrint); -0114 for i=1:numel(toPrint) -0115 if balanceStructure.balanceStatus(toPrint(i))<0 -0116 if balanceStructure.balanceStatus(toPrint(i))==-1 -0117 EM=['The reaction ' model.rxns{toPrint(i)} ' could not be balanced due to missing information']; -0118 dispEM(EM,false); -0119 else -0120 EM=['The reaction ' model.rxns{toPrint(i)} ' could not be balanced due to a parsing error']; -0121 dispEM(EM,false); -0122 end -0123 else -0124 %Find the compounds that it's not balanced for -0125 notBalanced=find(total(toPrint(i),:)); -0126 for j=1:numel(notBalanced) -0127 EM=['The reaction ' model.rxns{toPrint(i)} ' is not balanced with respect to ' balanceStructure.elements.names{notBalanced(j)}]; -0128 dispEM(EM,false); -0129 end -0130 end -0131 end -0132 -0133 % Re-order the structure entries so they're consistent with the ordering of -0134 % the input reaction indexes -0135 if ~isempty(rxns) -0136 rxns = getIndexes(model,rxns,'rxns'); -0137 [~,i] = sort(rxns); -0138 balanceStructure.balanceStatus(i) = balanceStructure.balanceStatus; -0139 balanceStructure.leftComp(i,:) = balanceStructure.leftComp; -0140 balanceStructure.rightComp(i,:) = balanceStructure.rightComp; -0141 end +0048 balanceStructure.balanceStatus=nan(numel(model.rxns),1); +0049 +0050 %Get the formulas +0051 if isfield(model,'metFormulas') +0052 [balanceStructure.elements, useMat, exitFlag]=parseFormulas(model.metFormulas, true); +0053 else +0054 if isfield(model,'inchis') +0055 [balanceStructure.elements, useMat, exitFlag]=parseFormulas(model.inchis, true,true); +0056 else +0057 EM='The model must contain either the "metFormulas" or the "inchis" field in order to test for elemental balancing'; +0058 dispEM(EM); +0059 end +0060 end +0061 +0062 balanceStructure.leftComp=zeros(numel(model.rxns),numel(balanceStructure.elements.names)); +0063 balanceStructure.rightComp=balanceStructure.leftComp; +0064 +0065 %Look at the right and left side of the reactions separately +0066 S{1}=model.S; +0067 S{2}=model.S; +0068 S{1}(S{1}>0)=0; %Left side +0069 S{2}(S{2}<0)=0; %Right side +0070 S{1}=abs(S{1}); %Both should have positive values +0071 +0072 %First do it for left side and then for right +0073 for i=1:2 +0074 for j=1:numel(model.rxns) +0075 %Get the balance status of the involved mets +0076 I=exitFlag(S{i}(:,j)~=0); +0077 if any(I==-1) +0078 balanceStructure.balanceStatus(j)=-2; +0079 end +0080 if any(I==0) +0081 %Don't change a more serious error to a less serious one +0082 balanceStructure.balanceStatus(j)=min(-1,balanceStructure.balanceStatus(j)); +0083 end +0084 %Loop through each element +0085 for k=1:numel(balanceStructure.elements.names) +0086 if i==1 +0087 balanceStructure.leftComp(j,k)=sum(S{i}(:,j).*useMat(:,k)); +0088 else +0089 balanceStructure.rightComp(j,k)=sum(S{i}(:,j).*useMat(:,k)); +0090 end +0091 end +0092 end +0093 end +0094 +0095 %Now compare the left and right sides to find which are unbalanced. This is +0096 %done even if the reaction as a whole couldn't be balanced +0097 total=abs(balanceStructure.rightComp-balanceStructure.leftComp)>10^-8; %To deal with roundoff error +0098 +0099 %Get which reactions are unbalanced. Don't change an error to just +0100 %unbalanced +0101 balanceStructure.balanceStatus(any(total,2))=min(balanceStructure.balanceStatus(any(total,2)),0); +0102 +0103 %The remaining ones are all balanced +0104 balanceStructure.balanceStatus(isnan(balanceStructure.balanceStatus))=1; +0105 +0106 %Print warnings +0107 toPrint=[]; +0108 if printUnbalanced==true +0109 toPrint=[toPrint;find(balanceStructure.balanceStatus==0)]; +0110 end +0111 if printUnparsable==true +0112 toPrint=[toPrint;find(balanceStructure.balanceStatus<0)]; +0113 end +0114 +0115 toPrint=sort(toPrint); +0116 for i=1:numel(toPrint) +0117 if balanceStructure.balanceStatus(toPrint(i))<0 +0118 if balanceStructure.balanceStatus(toPrint(i))==-1 +0119 EM=['The reaction ' model.rxns{toPrint(i)} ' could not be balanced due to missing information']; +0120 dispEM(EM,false); +0121 else +0122 EM=['The reaction ' model.rxns{toPrint(i)} ' could not be balanced due to a parsing error']; +0123 dispEM(EM,false); +0124 end +0125 else +0126 %Find the compounds that it's not balanced for +0127 notBalanced=find(total(toPrint(i),:)); +0128 for j=1:numel(notBalanced) +0129 EM=['The reaction ' model.rxns{toPrint(i)} ' is not balanced with respect to ' balanceStructure.elements.names{notBalanced(j)}]; +0130 dispEM(EM,false); +0131 end +0132 end +0133 end +0134 +0135 % Re-order the structure entries so they're consistent with the ordering of +0136 % the input reaction indexes +0137 if ~isempty(rxns) +0138 rxns = getIndexes(model,rxns,'rxns'); +0139 [~,i] = sort(rxns); +0140 balanceStructure.balanceStatus(i) = balanceStructure.balanceStatus; +0141 balanceStructure.leftComp(i,:) = balanceStructure.leftComp; +0142 balanceStructure.rightComp(i,:) = balanceStructure.rightComp; +0143 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/getEssentialRxns.html b/doc/core/getEssentialRxns.html index b4b261b7..77a3a1c1 100644 --- a/doc/core/getEssentialRxns.html +++ b/doc/core/getEssentialRxns.html @@ -46,7 +46,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • dispEM dispEM
  • setParam setParam
  • This function is called by: @@ -73,52 +73,54 @@

    SOURCE CODE ^if nargin<2 0018 ignoreRxns={}; -0019 end -0020 -0021 %Too make sure that it doesn't try to optimize for something -0022 model.c=zeros(numel(model.rxns),1); -0023 -0024 %First check that the problem is solvable -0025 [sol, hsSolOut]=solveLP(model,1); -0026 -0027 if sol.stat==-1 || isempty(sol.x) -0028 EM='No feasible solution to the full model'; -0029 dispEM(EM); -0030 end -0031 -0032 %Check which reactions have flux. Only those can be essential. This is not -0033 %the smallest list of reactions, but it's a fast way -0034 rxnsToCheck=setdiff(model.rxns(abs(sol.x)>10^-8),ignoreRxns); -0035 nToCheck=numel(rxnsToCheck); -0036 minimize=true; -0037 while 1 -0038 if minimize==true -0039 sol=solveLP(setParam(model,'obj',rxnsToCheck,-1)); -0040 else -0041 sol=solveLP(setParam(model,'obj',rxnsToCheck,1)); -0042 end -0043 rxnsToCheck=intersect(rxnsToCheck,model.rxns(abs(sol.x)>10^-8)); -0044 if numel(rxnsToCheck)>=nToCheck -0045 if minimize==true -0046 minimize=false; -0047 else -0048 break; -0049 end -0050 else -0051 nToCheck=numel(rxnsToCheck); -0052 end -0053 end -0054 -0055 essentialRxns={}; -0056 for i=1:numel(rxnsToCheck) -0057 sol=solveLP(setParam(model,'eq',rxnsToCheck(i),0),0,[],hsSolOut); -0058 if sol.stat==-1 || isempty(sol.x) -0059 essentialRxns=[essentialRxns;rxnsToCheck(i)]; -0060 end -0061 end -0062 -0063 [~, essentialRxnsIndexes]=ismember(essentialRxns,model.rxns); -0064 end +0019 else +0020 ignoreRxns=convertCharArray(ignoreRxns); +0021 end +0022 +0023 %Too make sure that it doesn't try to optimize for something +0024 model.c=zeros(numel(model.rxns),1); +0025 +0026 %First check that the problem is solvable +0027 [sol, hsSolOut]=solveLP(model,1); +0028 +0029 if sol.stat==-1 || isempty(sol.x) +0030 EM='No feasible solution to the full model'; +0031 dispEM(EM); +0032 end +0033 +0034 %Check which reactions have flux. Only those can be essential. This is not +0035 %the smallest list of reactions, but it's a fast way +0036 rxnsToCheck=setdiff(model.rxns(abs(sol.x)>10^-12),ignoreRxns); +0037 nToCheck=numel(rxnsToCheck); +0038 minimize=true; +0039 while 1 +0040 if minimize==true +0041 sol=solveLP(setParam(model,'obj',rxnsToCheck,-1)); +0042 else +0043 sol=solveLP(setParam(model,'obj',rxnsToCheck,1)); +0044 end +0045 rxnsToCheck=intersect(rxnsToCheck,model.rxns(abs(sol.x)>10^-8)); +0046 if numel(rxnsToCheck)>=nToCheck +0047 if minimize==true +0048 minimize=false; +0049 else +0050 break; +0051 end +0052 else +0053 nToCheck=numel(rxnsToCheck); +0054 end +0055 end +0056 +0057 essentialRxns={}; +0058 for i=1:numel(rxnsToCheck) +0059 sol=solveLP(setParam(model,'eq',rxnsToCheck(i),0),0,[],hsSolOut); +0060 if sol.stat==-1 || isempty(sol.x) +0061 essentialRxns=[essentialRxns;rxnsToCheck(i)]; +0062 end +0063 end +0064 +0065 [~, essentialRxnsIndexes]=ismember(essentialRxns,model.rxns); +0066 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/getExchangeRxns.html b/doc/core/getExchangeRxns.html index 9a4d0c5d..9f901a4e 100644 --- a/doc/core/getExchangeRxns.html +++ b/doc/core/getExchangeRxns.html @@ -77,31 +77,33 @@

    SOURCE CODE ^if nargin<2 0020 reactionType='both'; -0021 end -0022 -0023 hasNoProducts=sparse(numel(model.rxns),1); -0024 hasNoReactants=sparse(numel(model.rxns),1); -0025 -0026 if isfield(model,'unconstrained') -0027 if strcmpi(reactionType,'both') || strcmpi(reactionType,'out') -0028 [~, I]=find(model.S(model.unconstrained~=0,:)>0); -0029 hasNoProducts(I)=true; -0030 end -0031 if strcmpi(reactionType,'both') || strcmpi(reactionType,'in') -0032 [~, I]=find(model.S(model.unconstrained~=0,:)<0); -0033 hasNoReactants(I)=true; -0034 end -0035 else -0036 if strcmpi(reactionType,'both') || strcmpi(reactionType,'out') -0037 hasNoProducts=sum((model.S>0))==0; -0038 end -0039 if strcmpi(reactionType,'both') || strcmpi(reactionType,'in') -0040 hasNoReactants=sum((model.S<0))==0; -0041 end -0042 end -0043 exchangeRxnsIndexes=find(hasNoProducts(:) | hasNoReactants(:)); -0044 exchangeRxns=model.rxns(exchangeRxnsIndexes); -0045 end +0021 else +0022 reactionType=char(reactionType); +0023 end +0024 +0025 hasNoProducts=sparse(numel(model.rxns),1); +0026 hasNoReactants=sparse(numel(model.rxns),1); +0027 +0028 if isfield(model,'unconstrained') +0029 if strcmpi(reactionType,'both') || strcmpi(reactionType,'out') +0030 [~, I]=find(model.S(model.unconstrained~=0,:)>0); +0031 hasNoProducts(I)=true; +0032 end +0033 if strcmpi(reactionType,'both') || strcmpi(reactionType,'in') +0034 [~, I]=find(model.S(model.unconstrained~=0,:)<0); +0035 hasNoReactants(I)=true; +0036 end +0037 else +0038 if strcmpi(reactionType,'both') || strcmpi(reactionType,'out') +0039 hasNoProducts=sum((model.S>0))==0; +0040 end +0041 if strcmpi(reactionType,'both') || strcmpi(reactionType,'in') +0042 hasNoReactants=sum((model.S<0))==0; +0043 end +0044 end +0045 exchangeRxnsIndexes=find(hasNoProducts(:) | hasNoReactants(:)); +0046 exchangeRxns=model.rxns(exchangeRxnsIndexes); +0047 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/getIndexes.html b/doc/core/getIndexes.html index 40b491c3..40a53064 100644 --- a/doc/core/getIndexes.html +++ b/doc/core/getIndexes.html @@ -52,10 +52,10 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • This function is called by: +
  • addExchangeRxns addExchangeRxns
  • changeGrRules changeGrRules
  • constructEquations constructEquations
  • consumeSomething consumeSomething
  • convertToIrrev convertToIrrev
  • copyToComps copyToComps
  • getAllRxnsFromGenes getAllRxnsFromGenes
  • getAllowedBounds getAllowedBounds
  • getElementalBalance getElementalBalance
  • haveFlux haveFlux
  • makeSomething makeSomething
  • printModel printModel
  • removeGenes removeGenes
  • removeMets removeMets
  • removeReactions removeReactions
  • simplifyModel simplifyModel
  • @@ -87,86 +87,85 @@

    SOURCE CODE ^end 0026 -0027 %If the supplied object is a character array, then convert it to a cell -0028 %array -0029 if ischar(objects) -0030 objects={objects}; -0031 end -0032 -0033 indexes=[]; -0034 -0035 switch type -0036 case 'rxns' -0037 searchIn=model.rxns; -0038 case 'mets' -0039 searchIn=model.mets; -0040 case 'genes' -0041 searchIn=model.genes; -0042 case 'metnames' -0043 searchIn=model.metNames; -0044 case 'metcomps' -0045 % If provided as metaboliteName[comp], then index search is quite -0046 % different from general approach, and therefore coded separately. -0047 mets=regexprep(objects,'(^.+)\[(.+)\]$','$1'); -0048 comps=regexprep(objects,'(^.+)\[(.+)\]$','$2'); -0049 indexes=zeros(1,numel(objects)); -0050 for i=1:numel(objects) -0051 index=find(strcmp(mets(i),model.metNames)); -0052 index=index(strcmp(comps(i),model.comps(model.metComps(index)))); -0053 if ~isempty(index) -0054 indexes(i)=index; -0055 else -0056 error(['Could not find object ' objects{i} ' in the model']); -0057 end -0058 end -0059 indexes=indexes(:); -0060 if returnLogical==true -0061 tempIndexes=false(numel(model.mets),1); -0062 tempIndexes(indexes)=true; -0063 indexes=tempIndexes; -0064 end -0065 return %None of the remaining function needs to run if metcomps -0066 otherwise -0067 if contains(objects,{'rxns','mets','metnames','metcomps','genes'}) -0068 error('The second and third parameter provided to run getIndexes are likely switched. Note that the second parameter is the object to find the index for, while the third parameter is the object type (''rxns'', ''mets'', ''metnames'', ''metcomps'' or ''genes'').') -0069 else -0070 error('Incorrect value of the ''type'' parameter. Allowed values are ''rxns'', ''mets'', ''metnames'', ''metcomps'' or ''genes''.'); -0071 end -0072 end -0073 -0074 if iscell(objects) -0075 for i=1:numel(objects) -0076 index=find(strcmp(objects(i),searchIn)); -0077 if strcmpi(type,'metnames') -0078 indexes{i}=index; -0079 elseif ~isempty(index) -0080 indexes(i)=index; -0081 else -0082 error(['Could not find object ' objects{i} ' in the model']); -0083 end -0084 end -0085 else -0086 %Now it's either a logical (or 0/1) array or an array with indexes. We -0087 %want it to be an array with indexes. -0088 if all(objects) -0089 %This gets weird if it's all 1 -0090 indexes=objects; -0091 else -0092 indexes=find(objects); -0093 end -0094 end -0095 -0096 if returnLogical==true -0097 tempIndexes=false(numel(searchIn),1); -0098 tempIndexes(indexes)=true; -0099 indexes=tempIndexes; -0100 end -0101 -0102 indexes=indexes(:); -0103 if iscell(indexes) && length(indexes)==1 -0104 indexes=indexes{1}; -0105 end -0106 end +0027 if ~islogical(objects) && ~isnumeric(objects) +0028 objects=convertCharArray(objects); +0029 end +0030 type=char(type); +0031 +0032 indexes=[]; +0033 +0034 switch type +0035 case 'rxns' +0036 searchIn=model.rxns; +0037 case 'mets' +0038 searchIn=model.mets; +0039 case 'genes' +0040 searchIn=model.genes; +0041 case 'metnames' +0042 searchIn=model.metNames; +0043 case 'metcomps' +0044 % If provided as metaboliteName[comp], then index search is quite +0045 % different from general approach, and therefore coded separately. +0046 mets=regexprep(objects,'(^.+)\[(.+)\]$','$1'); +0047 comps=regexprep(objects,'(^.+)\[(.+)\]$','$2'); +0048 indexes=zeros(1,numel(objects)); +0049 for i=1:numel(objects) +0050 index=find(strcmp(mets(i),model.metNames)); +0051 index=index(strcmp(comps(i),model.comps(model.metComps(index)))); +0052 if ~isempty(index) +0053 indexes(i)=index; +0054 else +0055 error(['Could not find object ' objects{i} ' in the model']); +0056 end +0057 end +0058 indexes=indexes(:); +0059 if returnLogical==true +0060 tempIndexes=false(numel(model.mets),1); +0061 tempIndexes(indexes)=true; +0062 indexes=tempIndexes; +0063 end +0064 return %None of the remaining function needs to run if metcomps +0065 otherwise +0066 if contains(objects,{'rxns','mets','metnames','metcomps','genes'}) +0067 error('The second and third parameter provided to run getIndexes are likely switched. Note that the second parameter is the object to find the index for, while the third parameter is the object type (''rxns'', ''mets'', ''metnames'', ''metcomps'' or ''genes'').') +0068 else +0069 error('Incorrect value of the ''type'' parameter. Allowed values are ''rxns'', ''mets'', ''metnames'', ''metcomps'' or ''genes''.'); +0070 end +0071 end +0072 +0073 if iscell(objects) +0074 for i=1:numel(objects) +0075 index=find(strcmp(objects(i),searchIn)); +0076 if strcmpi(type,'metnames') +0077 indexes{i}=index; +0078 elseif ~isempty(index) +0079 indexes(i)=index; +0080 else +0081 error(['Could not find object ''' objects{i} ''' in the model']); +0082 end +0083 end +0084 else +0085 %Now it's either a logical (or 0/1) array or an array with indexes. We +0086 %want it to be an array with indexes. +0087 if all(objects) +0088 %This gets weird if it's all 1 +0089 indexes=objects; +0090 else +0091 indexes=find(objects); +0092 end +0093 end +0094 +0095 if returnLogical==true +0096 tempIndexes=false(numel(searchIn),1); +0097 tempIndexes(indexes)=true; +0098 indexes=tempIndexes; +0099 end +0100 +0101 indexes=indexes(:); +0102 if iscell(indexes) && length(indexes)==1 +0103 indexes=indexes{1}; +0104 end +0105 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/getMetsInComp.html b/doc/core/getMetsInComp.html index 9feb3bc3..144ca76a 100644 --- a/doc/core/getMetsInComp.html +++ b/doc/core/getMetsInComp.html @@ -63,20 +63,18 @@

    SOURCE CODE ^% 0011 % Usage: [I, metNames]=getMetsInComp(model,comp) 0012 -0013 if ischar(comp) -0014 comp={comp}; -0015 end +0013 comp=char(comp); +0014 +0015 J=find(ismember(upper(model.comps),upper(comp))); 0016 -0017 J=find(ismember(upper(model.comps),upper(comp))); -0018 -0019 if numel(J)~=1 -0020 EM=['No unique match to compartment "' comp{1} '"']; -0021 dispEM(EM); -0022 end -0023 -0024 I=model.metComps==J; -0025 metNames=model.metNames(I); -0026 end +0017 if numel(J)~=1 +0018 EM=['No unique match to compartment "' comp{1} '"']; +0019 dispEM(EM); +0020 end +0021 +0022 I=model.metComps==J; +0023 metNames=model.metNames(I); +0024 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/getMinNrFluxes.html b/doc/core/getMinNrFluxes.html index 20ab4ad9..891e3efe 100644 --- a/doc/core/getMinNrFluxes.html +++ b/doc/core/getMinNrFluxes.html @@ -59,7 +59,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • convertToIrrev convertToIrrev
  • dispEM dispEM
  • This function is called by: @@ -97,147 +97,141 @@

    SOURCE CODE ^% 0028 % Usage: [x,I,exitFlag]=getMinNrFluxes(model, toMinimize, params, scores) 0029 -0030 % glpk solver as implemented by COBRA does not work well for MILP. -0031 global CBT_MILP_SOLVER -0032 if strcmp(getpref('RAVEN','solver'),'cobra') && strcmp(CBT_MILP_SOLVER,'glpk') -0033 dispEM('The current solver is set to ''cobra'', while in COBRA the MILP solver has been set to ''glpk''. The COBRA implementation of glpk is not well suitable for solving MILPs. Please install the Gurobi or an alternative MILP solver.',true); -0034 end -0035 -0036 exitFlag=1; -0037 -0038 if nargin<2 -0039 toMinimize=model.rxns; -0040 else -0041 if ~iscell(toMinimize) -0042 toMinimize=model.rxns(toMinimize); -0043 end -0044 end -0045 -0046 %For passing parameters to the solver -0047 if nargin<3 -0048 params=struct(); -0049 end -0050 -0051 if nargin<4 -0052 %It says that the default is -1, but that is to fit with other code -0053 scores=ones(numel(toMinimize),1)*1; -0054 else -0055 if numel(scores)~=numel(toMinimize) -0056 EM='The number of scores must be the same as the number of reactions to minimize'; -0057 dispEM(EM); -0058 end -0059 -0060 %Change positive scores to have a small negative weight. This is a -0061 %temporary solution. -0062 scores(scores>=0)=max(scores(scores<0)); -0063 -0064 %It says that the default is -1, but that is to fit with other code -0065 scores=scores*-1; -0066 end -0067 -0068 %Check if the model is in irreversible format -0069 if any(model.rev) -0070 %Convert the model to irreversible format -0071 irrevModel=convertToIrrev(model); -0072 -0073 %Find the indexes for the reactions in toMinimize -0074 [indexes, I]=ismember(strrep(irrevModel.rxns,'_REV',''),toMinimize); -0075 else -0076 irrevModel=model; -0077 -0078 %Find the indexes for the reactions in toMinimize -0079 [indexes, I]=ismember(irrevModel.rxns,toMinimize); -0080 end -0081 -0082 indexes=find(indexes); -0083 %Adjust scores to fit with reversible -0084 scores=scores(I(indexes)); -0085 -0086 %Add binary constraints in the following manner: - Add one unique -0087 %"metabolite" for each integer reaction as a substrate. -0088 % These metabolites can have net production -0089 %- Add reactions for the production of each of those metabolites. The -0090 % amount produced in one reaction unit must be larger than the largest -0091 % possible flux in the model (but not too large to avoid bad scaling) -0092 -0093 %Calculate a solution to the problem without any constraints. This is to -0094 %get an estimate about the magnitude of fluxes in the model and to get a -0095 %feasible start solution. -0096 sol=solveLP(irrevModel,1); -0097 -0098 %Return an empty solution if the non-constrained problem couldn't be solved -0099 if isempty(sol.x) -0100 x=[]; -0101 I=[]; -0102 exitFlag=-1; -0103 return; -0104 end -0105 -0106 %Take the maximal times 5 to have a safe margin. If it's smaller than 1000, -0107 %then use 1000 instead. -0108 maxFlux=max(max(sol.x)*5,1000); -0109 -0110 intArray=speye(numel(irrevModel.rxns))*-1; -0111 intArray=intArray(indexes,:); -0112 prob.a=[irrevModel.S;intArray]; -0113 a=[sparse(numel(irrevModel.mets),numel(indexes));speye(numel(indexes))*maxFlux]; -0114 prob.a=[prob.a a]; -0115 prob.ints.sub=numel(irrevModel.rxns)+1:numel(irrevModel.rxns)+numel(indexes); -0116 -0117 prob.c=[zeros(numel(irrevModel.rxns),1);scores(:);zeros(size(prob.a,1),1)]; %Minimize the number of fluxes -0118 prob.A=[prob.a -speye(size(prob.a,1))]; -0119 prob.blc=[irrevModel.b(:,1);zeros(numel(indexes),1)]; -0120 if size(irrevModel.b,2)==2 -0121 prob.buc=[irrevModel.b(:,2);inf(numel(indexes),1)]; -0122 else -0123 prob.buc=[irrevModel.b(:,1);inf(numel(indexes),1)]; -0124 end -0125 prob.blx=[irrevModel.lb;zeros(numel(indexes),1)]; -0126 prob.bux=[irrevModel.ub;ones(numel(indexes),1)]; -0127 prob.lb = [prob.blx; prob.blc]; -0128 prob.ub = [prob.bux; prob.buc]; -0129 prob.osense=1; -0130 prob.csense=char(zeros(size(prob.a,1),1)); -0131 prob.csense(:)='E'; -0132 prob.b=zeros(size(prob.a,1), 1); -0133 -0134 %Use the output from the linear solution as starting point. Only the values -0135 %for the integer variables will be used, but all are supplied. -0136 prob.sol.int.xx=zeros(numel(prob.c),1); -0137 prob.sol.int.xx(prob.ints.sub(sol.x(indexes)>10^-12))=1; -0138 prob.x0=[]; -0139 prob.vartype=repmat('C', 1, size(prob.A,2)); -0140 prob.vartype(prob.ints.sub) = 'B'; -0141 prob=rmfield(prob,{'blx','bux','blc','buc'}); -0142 -0143 % Optimize the problem -0144 res = optimizeProb(prob,params); -0145 isFeasible=checkSolution(res); -0146 -0147 if ~isFeasible -0148 x=[]; -0149 I=[]; -0150 exitFlag=-1; -0151 return; -0152 end -0153 -0154 xx=res.full(1:numel(irrevModel.rxns)); -0155 I=res.full(numel(xx)+1:end); +0030 exitFlag=1; +0031 +0032 if nargin<2 +0033 toMinimize=model.rxns; +0034 elseif ~islogical(toMinimize) && ~isnumeric(toMinimize) +0035 toMinimize=convertCharArray(toMinimize); +0036 else +0037 toMinimize=model.rxns(toMinimize); +0038 end +0039 +0040 %For passing parameters to the solver +0041 if nargin<3 +0042 params=struct(); +0043 end +0044 +0045 if nargin<4 +0046 %It says that the default is -1, but that is to fit with other code +0047 scores=ones(numel(toMinimize),1)*1; +0048 else +0049 if numel(scores)~=numel(toMinimize) +0050 EM='The number of scores must be the same as the number of reactions to minimize'; +0051 dispEM(EM); +0052 end +0053 +0054 %Change positive scores to have a small negative weight. This is a +0055 %temporary solution. +0056 scores(scores>=0)=max(scores(scores<0)); +0057 +0058 %It says that the default is -1, but that is to fit with other code +0059 scores=scores*-1; +0060 end +0061 +0062 %Check if the model is in irreversible format +0063 if any(model.rev) +0064 %Convert the model to irreversible format +0065 irrevModel=convertToIrrev(model); +0066 +0067 %Find the indexes for the reactions in toMinimize +0068 [indexes, I]=ismember(strrep(irrevModel.rxns,'_REV',''),toMinimize); +0069 else +0070 irrevModel=model; +0071 +0072 %Find the indexes for the reactions in toMinimize +0073 [indexes, I]=ismember(irrevModel.rxns,toMinimize); +0074 end +0075 +0076 indexes=find(indexes); +0077 %Adjust scores to fit with reversible +0078 scores=scores(I(indexes)); +0079 +0080 %Add binary constraints in the following manner: - Add one unique +0081 %"metabolite" for each integer reaction as a substrate. +0082 % These metabolites can have net production +0083 %- Add reactions for the production of each of those metabolites. The +0084 % amount produced in one reaction unit must be larger than the largest +0085 % possible flux in the model (but not too large to avoid bad scaling) +0086 +0087 %Calculate a solution to the problem without any constraints. This is to +0088 %get an estimate about the magnitude of fluxes in the model and to get a +0089 %feasible start solution. +0090 sol=solveLP(irrevModel,1); +0091 +0092 %Return an empty solution if the non-constrained problem couldn't be solved +0093 if isempty(sol.x) +0094 x=[]; +0095 I=[]; +0096 exitFlag=-1; +0097 return; +0098 end +0099 +0100 %Take the maximal times 5 to have a safe margin. If it's smaller than 1000, +0101 %then use 1000 instead. +0102 maxFlux=max(max(sol.x)*5,1000); +0103 +0104 intArray=speye(numel(irrevModel.rxns))*-1; +0105 intArray=intArray(indexes,:); +0106 prob.a=[irrevModel.S;intArray]; +0107 a=[sparse(numel(irrevModel.mets),numel(indexes));speye(numel(indexes))*maxFlux]; +0108 prob.a=[prob.a a]; +0109 prob.ints.sub=numel(irrevModel.rxns)+1:numel(irrevModel.rxns)+numel(indexes); +0110 +0111 prob.c=[zeros(numel(irrevModel.rxns),1);scores(:);zeros(size(prob.a,1),1)]; %Minimize the number of fluxes +0112 prob.A=[prob.a -speye(size(prob.a,1))]; +0113 prob.blc=[irrevModel.b(:,1);zeros(numel(indexes),1)]; +0114 if size(irrevModel.b,2)==2 +0115 prob.buc=[irrevModel.b(:,2);inf(numel(indexes),1)]; +0116 else +0117 prob.buc=[irrevModel.b(:,1);inf(numel(indexes),1)]; +0118 end +0119 prob.blx=[irrevModel.lb;zeros(numel(indexes),1)]; +0120 prob.bux=[irrevModel.ub;ones(numel(indexes),1)]; +0121 prob.lb = [prob.blx; prob.blc]; +0122 prob.ub = [prob.bux; prob.buc]; +0123 prob.osense=1; +0124 prob.csense=repmat('E', 1, size(prob.a,1),1); +0125 prob.b=zeros(size(prob.a,1), 1); +0126 +0127 %Use the output from the linear solution as starting point. Only the values +0128 %for the integer variables will be used, but all are supplied. +0129 prob.sol.int.xx=zeros(numel(prob.c),1); +0130 prob.sol.int.xx(prob.ints.sub(sol.x(indexes)>10^-12))=1; +0131 prob.x0=[]; +0132 prob.vartype=repmat('C', size(prob.A,2), 1); +0133 prob.vartype(prob.ints.sub) = 'I'; % with .lb = 0 and .ub = 1, they are binary +0134 % integers (glpk in octave only allows 'continuous' or '', not 'binary') +0135 prob=rmfield(prob,{'blx','bux','blc','buc'}); +0136 +0137 % Optimize the problem +0138 res = optimizeProb(prob,params); +0139 isFeasible=checkSolution(res); +0140 +0141 if ~isFeasible +0142 x=[]; +0143 I=[]; +0144 exitFlag=-1; +0145 return; +0146 end +0147 +0148 xx=res.full(1:numel(irrevModel.rxns)); +0149 I=res.full(numel(xx)+1:end); +0150 +0151 %Check if Mosek aborted because it reached the time limit +0152 %TODO: modify for cobra/gurobi +0153 % if strcmp('MSK_RES_TRM_MAX_TIME',res.rcode) +0154 % exitFlag=-2; +0155 % end 0156 -0157 %Check if Mosek aborted because it reached the time limit -0158 %TODO: modify for cobra/gurobi -0159 % if strcmp('MSK_RES_TRM_MAX_TIME',res.rcode) -0160 % exitFlag=-2; -0161 % end +0157 %Map back to original model from irrevModel +0158 x=xx(1:numel(model.rxns)); +0159 if numel(irrevModel.rxns)>numel(model.rxns) +0160 x(model.rev~=0)=x(model.rev~=0)-xx(numel(model.rxns)+1:end); +0161 end 0162 -0163 %Map back to original model from irrevModel -0164 x=xx(1:numel(model.rxns)); -0165 if numel(irrevModel.rxns)>numel(model.rxns) -0166 x(model.rev~=0)=x(model.rev~=0)-xx(numel(model.rxns)+1:end); -0167 end -0168 -0169 I=ismember(toMinimize,strrep(irrevModel.rxns(indexes(I>10^-12)),'_REV','')); -0170 end +0163 I=ismember(toMinimize,strrep(irrevModel.rxns(indexes(I>10^-12)),'_REV','')); +0164 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/getModelFromHomology.html b/doc/core/getModelFromHomology.html index 231f31fe..3b66226b 100644 --- a/doc/core/getModelFromHomology.html +++ b/doc/core/getModelFromHomology.html @@ -96,7 +96,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • deleteUnusedGenes deleteUnusedGenes
  • dispEM dispEM
  • mergeModels mergeModels
  • removeGenes removeGenes
  • removeReactions removeReactions
  • standardizeGrRules standardizeGrRules
  • This function is called by: @@ -176,459 +176,461 @@

    SOURCE CODE ^% collect the old genes from the template model (organism) 0070 hitGenes.newGenes = []; % collect the new genes of the draft model (target organism) 0071 -0072 if nargin<4 -0073 preferredOrder=[]; -0074 end -0075 if nargin<5 -0076 strictness=1; -0077 end -0078 if nargin<6 -0079 onlyGenesInModels=false; -0080 end -0081 if nargin<7 -0082 maxE=10^-30; -0083 end -0084 if nargin<8 -0085 minLen=200; -0086 end -0087 if nargin<9 -0088 minIde=40; -0089 end -0090 if nargin<10 -0091 mapNewGenesToOld=true; -0092 end -0093 -0094 preferredOrder=preferredOrder(:); -0095 -0096 if isfield(models,'S') -0097 models={models}; -0098 end -0099 -0100 %Check that all the information is in the blast structure -0101 modelNames=cell(numel(models),1); -0102 for i=1:numel(models) -0103 modelNames{i}=models{i}.id; -0104 %Gene short names and geneMiriams are often different between species, -0105 %safer not to include them -0106 if isfield(models{i},'geneShortNames') -0107 models{i}=rmfield(models{i},'geneShortNames'); -0108 end -0109 if isfield(models{i},'geneMiriams') -0110 models{i}=rmfield(models{i},'geneMiriams'); -0111 end -0112 end -0113 -0114 %Assume for now that all information is there and that it's correct. This -0115 %is important to fix since no further checks are being made! -0116 -0117 %Check whether provided fasta files use the same gene identifiers as -0118 %provided template models -0119 for i=1:numel(blastStructure) -0120 if ~strcmp(blastStructure(i).fromId,getModelFor) -0121 j=strcmpi(blastStructure(i).fromId,modelNames); -0122 if j==0 -0123 error(['While the blastStructure contains sequences from '... -0124 'organismID "%s" (as\nprovided in getBlast), none of '... -0125 'template models have this id (as model.id)'],... -0126 string(blastStructure(i).fromId)); -0127 end -0128 k=sum(ismember(blastStructure(i).fromGenes,models{j}.genes)); -0129 if k<(numel(models{j}.genes)*0.05) -0130 error(['Less than 5%% of the genes in the template model '... -0131 'with model.id "%s"\ncan be found in the blastStructure. '... -0132 'Ensure that the protein FASTA\nused in getBlast and '... -0133 'the template model used in getModelFromHomology\nuse '... -0134 'the same style of gene identifiers'],models{j}.id) -0135 end -0136 end -0137 end -0138 -0139 %Standardize grRules of template models -0140 for i=1:length(models) -0141 fprintf('\nStandardizing grRules of template model with ID "%s" ...',models{i}.id); -0142 [models{i}.grRules,models{i}.rxnGeneMat]=standardizeGrRules(models{i},false); -0143 end -0144 fprintf(' done\n'); -0145 -0146 %Remove all gene matches that are below the cutoffs -0147 for i=1:numel(blastStructure) -0148 indexes=blastStructure(i).evalue<maxE & blastStructure(i).aligLen>=minLen & blastStructure(i).identity>=minIde; %Do it in this direction to lose NaNs -0149 blastStructure(i).fromGenes(~indexes)=[]; -0150 blastStructure(i).toGenes(~indexes)=[]; -0151 blastStructure(i).evalue(~indexes)=[]; -0152 blastStructure(i).identity(~indexes)=[]; -0153 blastStructure(i).aligLen(~indexes)=[]; -0154 blastStructure(i).bitscore(~indexes)=[]; -0155 blastStructure(i).ppos(~indexes)=[]; -0156 end -0157 -0158 %Remove all reactions from the models that have no genes encoding for them. -0159 %Also remove all genes that encode for no reactions. There shouldn't be any -0160 %but there might be mistakes -0161 for i=1:numel(models) -0162 [hasGenes, ~]=find(models{i}.rxnGeneMat); -0163 hasNoGenes=1:numel(models{i}.rxns); -0164 hasNoGenes(hasGenes)=[]; -0165 models{i}=removeReactions(models{i},hasNoGenes,true,true); -0166 end -0167 -0168 %Create a structure that contains all genes used in the blasts in any -0169 %direction for each of the models in 'models' and for the new organism. The -0170 %first cell is for the new organism and then according to the preferred -0171 %order. If no such order is supplied, then according to the order in -0172 %'models' -0173 allGenes=cell(numel(models)+1,1); -0174 if isempty(preferredOrder) -0175 useOrder=modelNames; -0176 else -0177 useOrder=preferredOrder; -0178 end -0179 -0180 %Get the corresponding indexes for those models in the 'models' structure -0181 useOrderIndexes=zeros(numel(models),1); -0182 for i=1:numel(models) -0183 [~, index]=ismember(models{i}.id,useOrder); -0184 useOrderIndexes(index)=i; -0185 end -0186 -0187 %Remove all genes from the blast structure that have no genes in the models -0188 if onlyGenesInModels==true -0189 modelGenes={}; -0190 for i=1:numel(models) -0191 modelGenes=[modelGenes;models{i}.genes]; -0192 end -0193 for i=1:numel(blastStructure) -0194 %Check to see if it should match the toId or fromId -0195 if strcmpi(blastStructure(i).fromId,getModelFor) -0196 I=ismember(blastStructure(i).toGenes,modelGenes); -0197 else -0198 I=ismember(blastStructure(i).fromGenes,modelGenes); -0199 end -0200 blastStructure(i).fromGenes(~I)=[]; -0201 blastStructure(i).toGenes(~I)=[]; -0202 blastStructure(i).evalue(~I)=[]; -0203 blastStructure(i).identity(~I)=[]; -0204 blastStructure(i).aligLen(~I)=[]; -0205 blastStructure(i).bitscore(~I)=[]; -0206 blastStructure(i).ppos(~I)=[]; -0207 -0208 %Check that no matching in blastStructure is empty. This happens if -0209 %no genes in the models are present in the corresponding sheet -0210 if isempty(blastStructure(i).fromGenes) -0211 EM=['No genes in matching from ' blastStructure(i).fromId ' to ' blastStructure(i).toId ' are present in the corresponding model']; -0212 dispEM(EM); -0213 end -0214 end -0215 end -0216 -0217 %If only best orthologs are to be used then all other measurements are -0218 %deleted from the blastStructure. All code after this stays the same. This -0219 %means that preferred order can still matter. The best ortholog scoring is -0220 %based only on the E-value -0221 if strictness==3 -0222 for i=1:numel(blastStructure) -0223 keep=false(numel(blastStructure(i).toGenes),1); -0224 [allFromGenes, ~, I]=unique(blastStructure(i).fromGenes); -0225 -0226 %It would be nice to get rid of this loop -0227 for j=1:numel(allFromGenes) -0228 allMatches=find(I==j); -0229 bestMatches=allMatches(blastStructure(i).evalue(allMatches)==min(blastStructure(i).evalue(allMatches))); -0230 -0231 %Keep the best matches -0232 keep(bestMatches)=true; -0233 end -0234 -0235 %Delete all matches that were not best matches -0236 blastStructure(i).fromGenes(~keep)=[]; -0237 blastStructure(i).toGenes(~keep)=[]; -0238 blastStructure(i).evalue(~keep)=[]; -0239 blastStructure(i).identity(~keep)=[]; -0240 blastStructure(i).aligLen(~keep)=[]; -0241 blastStructure(i).bitscore(~keep)=[]; -0242 blastStructure(i).ppos(~keep)=[]; -0243 end -0244 end -0245 -0246 useOrder=[{getModelFor};useOrder]; +0072 getModelFor=char(getModelFor); +0073 +0074 if nargin<4 +0075 preferredOrder=[]; +0076 else +0077 preferredOrder=convertCharArray(preferredOrder); +0078 end +0079 if nargin<5 +0080 strictness=1; +0081 end +0082 if nargin<6 +0083 onlyGenesInModels=false; +0084 end +0085 if nargin<7 +0086 maxE=10^-30; +0087 end +0088 if nargin<8 +0089 minLen=200; +0090 end +0091 if nargin<9 +0092 minIde=40; +0093 end +0094 if nargin<10 +0095 mapNewGenesToOld=true; +0096 end +0097 +0098 if isfield(models,'S') +0099 models={models}; +0100 end +0101 +0102 %Check that all the information is in the blast structure +0103 modelNames=cell(numel(models),1); +0104 for i=1:numel(models) +0105 modelNames{i}=models{i}.id; +0106 %Gene short names and geneMiriams are often different between species, +0107 %safer not to include them +0108 if isfield(models{i},'geneShortNames') +0109 models{i}=rmfield(models{i},'geneShortNames'); +0110 end +0111 if isfield(models{i},'geneMiriams') +0112 models{i}=rmfield(models{i},'geneMiriams'); +0113 end +0114 end +0115 +0116 %Assume for now that all information is there and that it's correct. This +0117 %is important to fix since no further checks are being made! +0118 +0119 %Check whether provided fasta files use the same gene identifiers as +0120 %provided template models +0121 for i=1:numel(blastStructure) +0122 if ~strcmp(blastStructure(i).fromId,getModelFor) +0123 j=strcmpi(blastStructure(i).fromId,modelNames); +0124 if j==0 +0125 error(['While the blastStructure contains sequences from '... +0126 'organismID "%s" (as\nprovided in getBlast), none of '... +0127 'template models have this id (as model.id)'],... +0128 string(blastStructure(i).fromId)); +0129 end +0130 k=sum(ismember(blastStructure(i).fromGenes,models{j}.genes)); +0131 if k<(numel(models{j}.genes)*0.05) +0132 error(['Less than 5%% of the genes in the template model '... +0133 'with model.id "%s"\ncan be found in the blastStructure. '... +0134 'Ensure that the protein FASTA\nused in getBlast and '... +0135 'the template model used in getModelFromHomology\nuse '... +0136 'the same style of gene identifiers'],models{j}.id) +0137 end +0138 end +0139 end +0140 +0141 %Standardize grRules of template models +0142 for i=1:length(models) +0143 fprintf('\nStandardizing grRules of template model with ID "%s" ...',models{i}.id); +0144 [models{i}.grRules,models{i}.rxnGeneMat]=standardizeGrRules(models{i},false); +0145 end +0146 fprintf(' done\n'); +0147 +0148 %Remove all gene matches that are below the cutoffs +0149 for i=1:numel(blastStructure) +0150 indexes=blastStructure(i).evalue<maxE & blastStructure(i).aligLen>=minLen & blastStructure(i).identity>=minIde; %Do it in this direction to lose NaNs +0151 blastStructure(i).fromGenes(~indexes)=[]; +0152 blastStructure(i).toGenes(~indexes)=[]; +0153 blastStructure(i).evalue(~indexes)=[]; +0154 blastStructure(i).identity(~indexes)=[]; +0155 blastStructure(i).aligLen(~indexes)=[]; +0156 blastStructure(i).bitscore(~indexes)=[]; +0157 blastStructure(i).ppos(~indexes)=[]; +0158 end +0159 +0160 %Remove all reactions from the models that have no genes encoding for them. +0161 %Also remove all genes that encode for no reactions. There shouldn't be any +0162 %but there might be mistakes +0163 for i=1:numel(models) +0164 [hasGenes, ~]=find(models{i}.rxnGeneMat); +0165 hasNoGenes=1:numel(models{i}.rxns); +0166 hasNoGenes(hasGenes)=[]; +0167 models{i}=removeReactions(models{i},hasNoGenes,true,true); +0168 end +0169 +0170 %Create a structure that contains all genes used in the blasts in any +0171 %direction for each of the models in 'models' and for the new organism. The +0172 %first cell is for the new organism and then according to the preferred +0173 %order. If no such order is supplied, then according to the order in +0174 %'models' +0175 allGenes=cell(numel(models)+1,1); +0176 if isempty(preferredOrder) +0177 useOrder=modelNames; +0178 else +0179 useOrder=preferredOrder; +0180 end +0181 +0182 %Get the corresponding indexes for those models in the 'models' structure +0183 useOrderIndexes=zeros(numel(models),1); +0184 for i=1:numel(models) +0185 [~, index]=ismember(models{i}.id,useOrder); +0186 useOrderIndexes(index)=i; +0187 end +0188 +0189 %Remove all genes from the blast structure that have no genes in the models +0190 if onlyGenesInModels==true +0191 modelGenes={}; +0192 for i=1:numel(models) +0193 modelGenes=[modelGenes;models{i}.genes]; +0194 end +0195 for i=1:numel(blastStructure) +0196 %Check to see if it should match the toId or fromId +0197 if strcmpi(blastStructure(i).fromId,getModelFor) +0198 I=ismember(blastStructure(i).toGenes,modelGenes); +0199 else +0200 I=ismember(blastStructure(i).fromGenes,modelGenes); +0201 end +0202 blastStructure(i).fromGenes(~I)=[]; +0203 blastStructure(i).toGenes(~I)=[]; +0204 blastStructure(i).evalue(~I)=[]; +0205 blastStructure(i).identity(~I)=[]; +0206 blastStructure(i).aligLen(~I)=[]; +0207 blastStructure(i).bitscore(~I)=[]; +0208 blastStructure(i).ppos(~I)=[]; +0209 +0210 %Check that no matching in blastStructure is empty. This happens if +0211 %no genes in the models are present in the corresponding sheet +0212 if isempty(blastStructure(i).fromGenes) +0213 EM=['No genes in matching from ' blastStructure(i).fromId ' to ' blastStructure(i).toId ' are present in the corresponding model']; +0214 dispEM(EM); +0215 end +0216 end +0217 end +0218 +0219 %If only best orthologs are to be used then all other measurements are +0220 %deleted from the blastStructure. All code after this stays the same. This +0221 %means that preferred order can still matter. The best ortholog scoring is +0222 %based only on the E-value +0223 if strictness==3 +0224 for i=1:numel(blastStructure) +0225 keep=false(numel(blastStructure(i).toGenes),1); +0226 [allFromGenes, ~, I]=unique(blastStructure(i).fromGenes); +0227 +0228 %It would be nice to get rid of this loop +0229 for j=1:numel(allFromGenes) +0230 allMatches=find(I==j); +0231 bestMatches=allMatches(blastStructure(i).evalue(allMatches)==min(blastStructure(i).evalue(allMatches))); +0232 +0233 %Keep the best matches +0234 keep(bestMatches)=true; +0235 end +0236 +0237 %Delete all matches that were not best matches +0238 blastStructure(i).fromGenes(~keep)=[]; +0239 blastStructure(i).toGenes(~keep)=[]; +0240 blastStructure(i).evalue(~keep)=[]; +0241 blastStructure(i).identity(~keep)=[]; +0242 blastStructure(i).aligLen(~keep)=[]; +0243 blastStructure(i).bitscore(~keep)=[]; +0244 blastStructure(i).ppos(~keep)=[]; +0245 end +0246 end 0247 -0248 for i=1:numel(blastStructure) -0249 [~, toIndex]=ismember(blastStructure(i).toId,useOrder); -0250 [~, fromIndex]=ismember(blastStructure(i).fromId,useOrder); -0251 -0252 %Add all genes to the corresponding list in allGenes -0253 allGenes{toIndex}=[allGenes{toIndex};blastStructure(i).toGenes]; -0254 allGenes{fromIndex}=[allGenes{fromIndex};blastStructure(i).fromGenes]; -0255 end -0256 -0257 %Keep only the unique gene names -0258 maxOtherGeneNr=0; %Determines the dimension of the connectivity matrixes -0259 for i=1:numel(allGenes) -0260 allGenes{i}=unique(allGenes{i}); -0261 if i>1 -0262 if numel(allGenes{i})>maxOtherGeneNr -0263 maxOtherGeneNr=numel(allGenes{i}); -0264 end -0265 end -0266 end -0267 -0268 %Generate a cell array of matrixes that describes how the genes in the new -0269 %organism map to the models. Each cell matches to the corresponding model -0270 %in useOrder (starting at 2 of course). First dimension is gene in new -0271 %organism, second which gene it is in the other organism. The second matrix -0272 %describes how they map back. -0273 -0274 %As it is now, a significant match is indicated by a 1. This could be -0275 %expanded to contain some kind of significance level. The first dimension -0276 %is still the genes in the new model. -0277 -0278 allTo=cell(numel(useOrder)-1,1); -0279 allFrom=cell(numel(useOrder)-1,1); -0280 -0281 for i=1:numel(useOrder)-1 -0282 allTo{i}=sparse(numel(allGenes{1}),numel(allGenes{i+1})); -0283 allFrom{i}=sparse(numel(allGenes{1}),numel(allGenes{i+1})); -0284 end -0285 -0286 %Fill the matches to other species -0287 for i=1:numel(blastStructure) -0288 if strcmp(blastStructure(i).toId,getModelFor) -0289 %This was 'to' the new organism. They should all match so no checks -0290 %are being made -0291 [~, a]=ismember(blastStructure(i).toGenes,allGenes{1}); -0292 [~, fromModel]=ismember(blastStructure(i).fromId,useOrder); -0293 [~, b]=ismember(blastStructure(i).fromGenes,allGenes{fromModel}); -0294 idx = sub2ind(size(allTo{fromModel-1}), a, b); -0295 allTo{fromModel-1}(idx)=1; -0296 else -0297 %This was 'from' the new organism -0298 [~, a]=ismember(blastStructure(i).fromGenes,allGenes{1}); -0299 [~, toModel]=ismember(blastStructure(i).toId,useOrder); -0300 [~, b]=ismember(blastStructure(i).toGenes,allGenes{toModel}); -0301 idx = sub2ind(size(allFrom{toModel-1}), a, b); -0302 allFrom{toModel-1}(idx)=1; -0303 end -0304 end -0305 -0306 %Now we have all the gene matches in a convenient way. For all the genes in -0307 %the new organism get the genes that should be included from other -0308 %organisms. If all genes should be included this simply means keep the -0309 %allFrom matrix as it is. If only orthologs which could be mapped in both -0310 %BLAST directions are to be included then only those elements are kept. -0311 -0312 finalMappings=cell(numel(useOrder)-1,1); -0313 if strictness==1 || strictness==3 -0314 for j=1:numel(allFrom) -0315 finalMappings{j}=allTo{j}~=0 & allFrom{j}~=0; -0316 end -0317 else -0318 if mapNewGenesToOld==true -0319 finalMappings=allFrom; -0320 else -0321 finalMappings=allTo; -0322 end -0323 end -0324 -0325 %Remove all genes from the mapping that are not in the models. This doesn't -0326 %do much if only genes in the models were used for the original mapping. -0327 %Also simplify the finalMapping and allGenes structures so that they only -0328 %contain mappings that exist -0329 usedNewGenes=false(numel(allGenes{1}),1); -0330 -0331 for i=1:numel(allGenes)-1 -0332 %First remove mappings for those genes that are not in the model -0333 if onlyGenesInModels==false -0334 a=ismember(allGenes{i+1},models{useOrderIndexes(i)}.genes); -0335 finalMappings{i}(:,~a)=false; -0336 end -0337 -0338 %Then remove unused ones and simplify -0339 [a, b]=find(finalMappings{i}); -0340 usedGenes=false(numel(allGenes{i+1}),1); -0341 usedNewGenes(a)=true; -0342 usedGenes(b)=true; -0343 finalMappings{i}=finalMappings{i}(:,usedGenes); -0344 allGenes{i+1}=allGenes{i+1}(usedGenes); -0345 end -0346 -0347 %Remove all new genes that have not been mapped to anything -0348 allGenes{1}=allGenes{1}(usedNewGenes); -0349 for i=1:numel(finalMappings) -0350 finalMappings{i}=finalMappings{i}(usedNewGenes,:); -0351 end -0352 -0353 %Now is it time to choose which reactions should be included from which -0354 %models. If there is a preferred order specified then each gene can only -0355 %result in reactions from one model, otherwise they should all be included -0356 -0357 %Start by simplifying the models by removing genes/reactions that are not -0358 %used. This is where it gets weird with complexes, especially "or" -0359 %complexes. In this step only reactions which are encoded by one single -0360 %gene, or where all genes should be deleted, are deleted. The info on the -0361 %full complex is still present in the grRules -0362 -0363 for i=1:numel(models) -0364 a=ismember(models{useOrderIndexes(i)}.genes,allGenes{i+1}); -0365 -0366 %Remove reactions that are not associated to any of the genes in -0367 %allGenes, thereby also keeping complexes where only for one of the -0368 %genes was matched -0369 [rxnsToKeep,~] = find(models{useOrderIndexes(i)}.rxnGeneMat(:,a)); -0370 rxnsToRemove = repmat(1,numel(models{useOrderIndexes(i)}.rxns),1); -0371 rxnsToRemove(rxnsToKeep) = 0; -0372 rxnsToRemove = find(rxnsToRemove); -0373 models{useOrderIndexes(i)}=removeReactions(models{useOrderIndexes(i)},rxnsToRemove,true,true,true); -0374 end -0375 -0376 %Since mergeModels function will be used in the end, the models are -0377 %simplified further by deleting genes/reactions in the order specified by -0378 %preferredOrder. This means that the last model will only contain reactions -0379 %for genes that mapped only to that model -0380 -0381 allUsedGenes=false(numel(allGenes{1}),1); +0248 useOrder=[{getModelFor};useOrder]; +0249 +0250 for i=1:numel(blastStructure) +0251 [~, toIndex]=ismember(blastStructure(i).toId,useOrder); +0252 [~, fromIndex]=ismember(blastStructure(i).fromId,useOrder); +0253 +0254 %Add all genes to the corresponding list in allGenes +0255 allGenes{toIndex}=[allGenes{toIndex};blastStructure(i).toGenes]; +0256 allGenes{fromIndex}=[allGenes{fromIndex};blastStructure(i).fromGenes]; +0257 end +0258 +0259 %Keep only the unique gene names +0260 maxOtherGeneNr=0; %Determines the dimension of the connectivity matrixes +0261 for i=1:numel(allGenes) +0262 allGenes{i}=unique(allGenes{i}); +0263 if i>1 +0264 if numel(allGenes{i})>maxOtherGeneNr +0265 maxOtherGeneNr=numel(allGenes{i}); +0266 end +0267 end +0268 end +0269 +0270 %Generate a cell array of matrixes that describes how the genes in the new +0271 %organism map to the models. Each cell matches to the corresponding model +0272 %in useOrder (starting at 2 of course). First dimension is gene in new +0273 %organism, second which gene it is in the other organism. The second matrix +0274 %describes how they map back. +0275 +0276 %As it is now, a significant match is indicated by a 1. This could be +0277 %expanded to contain some kind of significance level. The first dimension +0278 %is still the genes in the new model. +0279 +0280 allTo=cell(numel(useOrder)-1,1); +0281 allFrom=cell(numel(useOrder)-1,1); +0282 +0283 for i=1:numel(useOrder)-1 +0284 allTo{i}=sparse(numel(allGenes{1}),numel(allGenes{i+1})); +0285 allFrom{i}=sparse(numel(allGenes{1}),numel(allGenes{i+1})); +0286 end +0287 +0288 %Fill the matches to other species +0289 for i=1:numel(blastStructure) +0290 if strcmp(blastStructure(i).toId,getModelFor) +0291 %This was 'to' the new organism. They should all match so no checks +0292 %are being made +0293 [~, a]=ismember(blastStructure(i).toGenes,allGenes{1}); +0294 [~, fromModel]=ismember(blastStructure(i).fromId,useOrder); +0295 [~, b]=ismember(blastStructure(i).fromGenes,allGenes{fromModel}); +0296 idx = sub2ind(size(allTo{fromModel-1}), a, b); +0297 allTo{fromModel-1}(idx)=1; +0298 else +0299 %This was 'from' the new organism +0300 [~, a]=ismember(blastStructure(i).fromGenes,allGenes{1}); +0301 [~, toModel]=ismember(blastStructure(i).toId,useOrder); +0302 [~, b]=ismember(blastStructure(i).toGenes,allGenes{toModel}); +0303 idx = sub2ind(size(allFrom{toModel-1}), a, b); +0304 allFrom{toModel-1}(idx)=1; +0305 end +0306 end +0307 +0308 %Now we have all the gene matches in a convenient way. For all the genes in +0309 %the new organism get the genes that should be included from other +0310 %organisms. If all genes should be included this simply means keep the +0311 %allFrom matrix as it is. If only orthologs which could be mapped in both +0312 %BLAST directions are to be included then only those elements are kept. +0313 +0314 finalMappings=cell(numel(useOrder)-1,1); +0315 if strictness==1 || strictness==3 +0316 for j=1:numel(allFrom) +0317 finalMappings{j}=allTo{j}~=0 & allFrom{j}~=0; +0318 end +0319 else +0320 if mapNewGenesToOld==true +0321 finalMappings=allFrom; +0322 else +0323 finalMappings=allTo; +0324 end +0325 end +0326 +0327 %Remove all genes from the mapping that are not in the models. This doesn't +0328 %do much if only genes in the models were used for the original mapping. +0329 %Also simplify the finalMapping and allGenes structures so that they only +0330 %contain mappings that exist +0331 usedNewGenes=false(numel(allGenes{1}),1); +0332 +0333 for i=1:numel(allGenes)-1 +0334 %First remove mappings for those genes that are not in the model +0335 if onlyGenesInModels==false +0336 a=ismember(allGenes{i+1},models{useOrderIndexes(i)}.genes); +0337 finalMappings{i}(:,~a)=false; +0338 end +0339 +0340 %Then remove unused ones and simplify +0341 [a, b]=find(finalMappings{i}); +0342 usedGenes=false(numel(allGenes{i+1}),1); +0343 usedNewGenes(a)=true; +0344 usedGenes(b)=true; +0345 finalMappings{i}=finalMappings{i}(:,usedGenes); +0346 allGenes{i+1}=allGenes{i+1}(usedGenes); +0347 end +0348 +0349 %Remove all new genes that have not been mapped to anything +0350 allGenes{1}=allGenes{1}(usedNewGenes); +0351 for i=1:numel(finalMappings) +0352 finalMappings{i}=finalMappings{i}(usedNewGenes,:); +0353 end +0354 +0355 %Now is it time to choose which reactions should be included from which +0356 %models. If there is a preferred order specified then each gene can only +0357 %result in reactions from one model, otherwise they should all be included +0358 +0359 %Start by simplifying the models by removing genes/reactions that are not +0360 %used. This is where it gets weird with complexes, especially "or" +0361 %complexes. In this step only reactions which are encoded by one single +0362 %gene, or where all genes should be deleted, are deleted. The info on the +0363 %full complex is still present in the grRules +0364 +0365 for i=1:numel(models) +0366 a=ismember(models{useOrderIndexes(i)}.genes,allGenes{i+1}); +0367 +0368 %Remove reactions that are not associated to any of the genes in +0369 %allGenes, thereby also keeping complexes where only for one of the +0370 %genes was matched +0371 [rxnsToKeep,~] = find(models{useOrderIndexes(i)}.rxnGeneMat(:,a)); +0372 rxnsToRemove = repmat(1,numel(models{useOrderIndexes(i)}.rxns),1); +0373 rxnsToRemove(rxnsToKeep) = 0; +0374 rxnsToRemove = find(rxnsToRemove); +0375 models{useOrderIndexes(i)}=removeReactions(models{useOrderIndexes(i)},rxnsToRemove,true,true,true); +0376 end +0377 +0378 %Since mergeModels function will be used in the end, the models are +0379 %simplified further by deleting genes/reactions in the order specified by +0380 %preferredOrder. This means that the last model will only contain reactions +0381 %for genes that mapped only to that model 0382 -0383 if ~isempty(preferredOrder) && numel(models)>1 -0384 [usedGenes, ~]=find(finalMappings{1}); %All that are used in the first model in preferredOrder -0385 allUsedGenes(usedGenes)=true; -0386 for i=2:numel(finalMappings) -0387 [usedGenes, ~]=find(finalMappings{i}); -0388 usedGenes=unique(usedGenes); -0389 a=ismember(usedGenes,find(allUsedGenes)); -0390 -0391 [~, genesToDelete]=find(finalMappings{i}(usedGenes(a),:)); %IMPORTANT! IS it really correct to remove all genes that map? -0392 genesToDelete=unique(genesToDelete); %Maybe not needed, but for clarity if nothing else -0393 -0394 %Remove all the genes that were already found and add the other -0395 %ones to allUsedGenes -0396 models{useOrderIndexes(i)}=removeGenes(models{useOrderIndexes(i)},allGenes{i+1}(genesToDelete),true,true,false); -0397 allUsedGenes(usedGenes)=true; -0398 -0399 %Remove the deleted genes from finalMappings and allGenes. -0400 finalMappings{i}(:,genesToDelete)=[]; -0401 allGenes{i+1}(genesToDelete)=[]; -0402 end -0403 end -0404 -0405 %Now loop through the models and update the gene associations. Genes not -0406 %belonging to the new organism will be renamed as 'OLD_MODELID_gene' -0407 for i=1:numel(models) -0408 %Find all the new genes that should be used for this model -0409 [newGenes, oldGenes]=find(finalMappings{i}); -0410 -0411 %Create a new gene list with the genes from the new organism and those -0412 %genes that could not be removed -0413 replaceableGenes=allGenes{i+1}(unique(oldGenes)); -0414 nonReplaceableGenes=setdiff(models{useOrderIndexes(i)}.genes,replaceableGenes); -0415 fullGeneList=[allGenes{1}(unique(newGenes));nonReplaceableGenes]; -0416 -0417 %Just to save some indexing later. This is the LAST index of -0418 %replaceable ones -0419 nonRepStartIndex=numel(unique(newGenes)); -0420 -0421 %Construct a new rxnGeneMat -0422 newRxnGeneMat=sparse(numel(models{useOrderIndexes(i)}.rxns),numel(fullGeneList)); -0423 -0424 %Now update the rxnGeneMat. This is a little tricky and could -0425 %probably be done in a more efficient way, but I just loop through the -0426 %reactions and add them one by one -0427 for j=1:numel(models{useOrderIndexes(i)}.rxns) -0428 %Get the old genes encoding for this reaction -0429 [~, oldGeneIds]=find(models{useOrderIndexes(i)}.rxnGeneMat(j,:)); -0430 -0431 %Update the matrix for each gene. This includes replacing one gene -0432 %with several new ones if there were several matches -0433 for k=1:numel(oldGeneIds) -0434 %Match the gene to one in the gene list. This is done as a text -0435 %match. Could probably be done better, but I'm a little lost in -0436 %the indexing -0437 -0438 geneName=models{useOrderIndexes(i)}.genes(oldGeneIds(k)); +0383 allUsedGenes=false(numel(allGenes{1}),1); +0384 +0385 if ~isempty(preferredOrder) && numel(models)>1 +0386 [usedGenes, ~]=find(finalMappings{1}); %All that are used in the first model in preferredOrder +0387 allUsedGenes(usedGenes)=true; +0388 for i=2:numel(finalMappings) +0389 [usedGenes, ~]=find(finalMappings{i}); +0390 usedGenes=unique(usedGenes); +0391 a=ismember(usedGenes,find(allUsedGenes)); +0392 +0393 [~, genesToDelete]=find(finalMappings{i}(usedGenes(a),:)); %IMPORTANT! IS it really correct to remove all genes that map? +0394 genesToDelete=unique(genesToDelete); %Maybe not needed, but for clarity if nothing else +0395 +0396 %Remove all the genes that were already found and add the other +0397 %ones to allUsedGenes +0398 models{useOrderIndexes(i)}=removeGenes(models{useOrderIndexes(i)},allGenes{i+1}(genesToDelete),true,true,false); +0399 allUsedGenes(usedGenes)=true; +0400 +0401 %Remove the deleted genes from finalMappings and allGenes. +0402 finalMappings{i}(:,genesToDelete)=[]; +0403 allGenes{i+1}(genesToDelete)=[]; +0404 end +0405 end +0406 +0407 %Now loop through the models and update the gene associations. Genes not +0408 %belonging to the new organism will be renamed as 'OLD_MODELID_gene' +0409 for i=1:numel(models) +0410 %Find all the new genes that should be used for this model +0411 [newGenes, oldGenes]=find(finalMappings{i}); +0412 +0413 %Create a new gene list with the genes from the new organism and those +0414 %genes that could not be removed +0415 replaceableGenes=allGenes{i+1}(unique(oldGenes)); +0416 nonReplaceableGenes=setdiff(models{useOrderIndexes(i)}.genes,replaceableGenes); +0417 fullGeneList=[allGenes{1}(unique(newGenes));nonReplaceableGenes]; +0418 +0419 %Just to save some indexing later. This is the LAST index of +0420 %replaceable ones +0421 nonRepStartIndex=numel(unique(newGenes)); +0422 +0423 %Construct a new rxnGeneMat +0424 newRxnGeneMat=sparse(numel(models{useOrderIndexes(i)}.rxns),numel(fullGeneList)); +0425 +0426 %Now update the rxnGeneMat. This is a little tricky and could +0427 %probably be done in a more efficient way, but I just loop through the +0428 %reactions and add them one by one +0429 for j=1:numel(models{useOrderIndexes(i)}.rxns) +0430 %Get the old genes encoding for this reaction +0431 [~, oldGeneIds]=find(models{useOrderIndexes(i)}.rxnGeneMat(j,:)); +0432 +0433 %Update the matrix for each gene. This includes replacing one gene +0434 %with several new ones if there were several matches +0435 for k=1:numel(oldGeneIds) +0436 %Match the gene to one in the gene list. This is done as a text +0437 %match. Could probably be done better, but I'm a little lost in +0438 %the indexing 0439 -0440 %First search in the mappable genes -0441 mapIndex=find(ismember(allGenes{i+1},geneName)); -0442 -0443 if ~isempty(mapIndex) -0444 % add the old genes -0445 hitGenes.oldGenes = [hitGenes.oldGenes, {geneName}]; -0446 -0447 %Get the new genes for that gene -0448 a=find(finalMappings{i}(:,mapIndex)); -0449 -0450 %Find the positions of these genes in the final gene list -0451 [~, b]=ismember(allGenes{1}(a),fullGeneList); -0452 -0453 %Update the matrix -0454 newRxnGeneMat(j,b)=1; -0455 -0456 %Update the grRules string. This is tricky, but I hope that -0457 %it's ok to replace the old gene name with the new one and -0458 %add ') or (' if there were several matches. Be sure of -0459 %this! -0460 repString=fullGeneList{b(1)}; -0461 if numel(b)>1 -0462 for l=2:numel(b) -0463 repString=[repString ' or ' fullGeneList{b(l)}]; -0464 end -0465 repString=['(' repString ')']; -0466 end -0467 -0468 % add the new matched genes -0469 hitGenes.newGenes = [hitGenes.newGenes, {repString}]; -0470 -0471 %Use regexprep instead of strrep to prevent partial matches -0472 models{useOrderIndexes(i)}.grRules{j}=regexprep(models{useOrderIndexes(i)}.grRules{j},['(^|\s|\()' geneName{1} '($|\s|\))'],['$1' repString '$2']); -0473 else -0474 %Then search in the non-replaceable genes. There could only -0475 %be one match here -0476 index=find(ismember(nonReplaceableGenes,geneName)); -0477 -0478 %Update the matrix -0479 newRxnGeneMat(j,nonRepStartIndex+index)=1; -0480 -0481 models{useOrderIndexes(i)}.grRules{j}=strrep(models{useOrderIndexes(i)}.grRules{j},geneName{1},strcat('OLD_',models{useOrderIndexes(i)}.id,'_',geneName{1})); -0482 end -0483 end -0484 end -0485 -0486 %Add the new list of genes -0487 models{useOrderIndexes(i)}.rxnGeneMat=newRxnGeneMat; -0488 if ~isempty(nonReplaceableGenes) -0489 models{useOrderIndexes(i)}.genes=[allGenes{1}(unique(newGenes));strcat('OLD_',models{useOrderIndexes(i)}.id,'_',nonReplaceableGenes)]; -0490 else -0491 models{useOrderIndexes(i)}.genes=allGenes{1}(unique(newGenes)); -0492 end -0493 if isfield(models{useOrderIndexes(i)},'geneComps') -0494 geneComps=models{useOrderIndexes(i)}.geneComps(1); -0495 models{useOrderIndexes(i)}.geneComps=zeros(numel(models{useOrderIndexes(i)}.genes),1); -0496 %Assume that all genes are in the same compartment, and this -0497 %compartment is specified for the first gene -0498 models{useOrderIndexes(i)}.geneComps(:)=geneComps; -0499 end -0500 end -0501 -0502 %Now merge the models. All information should be correct except for 'or' -0503 %complexes -0504 draftModel=mergeModels(models,'metNames'); -0505 -0506 %Change name of the resulting model -0507 draftModel.id=getModelFor; -0508 name='Generated by getModelFromHomology using '; -0509 for i=1:numel(models) -0510 if i<numel(models) -0511 name=[name models{i}.id ', ']; -0512 else -0513 name=[name models{i}.id]; -0514 end -0515 end -0516 draftModel.name=name; -0517 draftModel.rxnNotes=cell(length(draftModel.rxns),1); -0518 draftModel.rxnNotes(:)={'Included by getModelFromHomology'}; -0519 draftModel.rxnConfidenceScores=NaN(length(draftModel.rxns),1); -0520 draftModel.rxnConfidenceScores(:)=2; -0521 draftModel=deleteUnusedGenes(draftModel,0); -0522 %Standardize grRules and notify if problematic grRules are found -0523 [draftModel.grRules,draftModel.rxnGeneMat]=standardizeGrRules(draftModel,false); -0524 end +0440 geneName=models{useOrderIndexes(i)}.genes(oldGeneIds(k)); +0441 +0442 %First search in the mappable genes +0443 mapIndex=find(ismember(allGenes{i+1},geneName)); +0444 +0445 if ~isempty(mapIndex) +0446 % add the old genes +0447 hitGenes.oldGenes = [hitGenes.oldGenes, {geneName}]; +0448 +0449 %Get the new genes for that gene +0450 a=find(finalMappings{i}(:,mapIndex)); +0451 +0452 %Find the positions of these genes in the final gene list +0453 [~, b]=ismember(allGenes{1}(a),fullGeneList); +0454 +0455 %Update the matrix +0456 newRxnGeneMat(j,b)=1; +0457 +0458 %Update the grRules string. This is tricky, but I hope that +0459 %it's ok to replace the old gene name with the new one and +0460 %add ') or (' if there were several matches. Be sure of +0461 %this! +0462 repString=fullGeneList{b(1)}; +0463 if numel(b)>1 +0464 for l=2:numel(b) +0465 repString=[repString ' or ' fullGeneList{b(l)}]; +0466 end +0467 repString=['(' repString ')']; +0468 end +0469 +0470 % add the new matched genes +0471 hitGenes.newGenes = [hitGenes.newGenes, {repString}]; +0472 +0473 %Use regexprep instead of strrep to prevent partial matches +0474 models{useOrderIndexes(i)}.grRules{j}=regexprep(models{useOrderIndexes(i)}.grRules{j},['(^|\s|\()' geneName{1} '($|\s|\))'],['$1' repString '$2']); +0475 else +0476 %Then search in the non-replaceable genes. There could only +0477 %be one match here +0478 index=find(ismember(nonReplaceableGenes,geneName)); +0479 +0480 %Update the matrix +0481 newRxnGeneMat(j,nonRepStartIndex+index)=1; +0482 +0483 models{useOrderIndexes(i)}.grRules{j}=strrep(models{useOrderIndexes(i)}.grRules{j},geneName{1},strcat('OLD_',models{useOrderIndexes(i)}.id,'_',geneName{1})); +0484 end +0485 end +0486 end +0487 +0488 %Add the new list of genes +0489 models{useOrderIndexes(i)}.rxnGeneMat=newRxnGeneMat; +0490 if ~isempty(nonReplaceableGenes) +0491 models{useOrderIndexes(i)}.genes=[allGenes{1}(unique(newGenes));strcat('OLD_',models{useOrderIndexes(i)}.id,'_',nonReplaceableGenes)]; +0492 else +0493 models{useOrderIndexes(i)}.genes=allGenes{1}(unique(newGenes)); +0494 end +0495 if isfield(models{useOrderIndexes(i)},'geneComps') +0496 geneComps=models{useOrderIndexes(i)}.geneComps(1); +0497 models{useOrderIndexes(i)}.geneComps=zeros(numel(models{useOrderIndexes(i)}.genes),1); +0498 %Assume that all genes are in the same compartment, and this +0499 %compartment is specified for the first gene +0500 models{useOrderIndexes(i)}.geneComps(:)=geneComps; +0501 end +0502 end +0503 +0504 %Now merge the models. All information should be correct except for 'or' +0505 %complexes +0506 draftModel=mergeModels(models,'metNames'); +0507 +0508 %Change name of the resulting model +0509 draftModel.id=getModelFor; +0510 name='Generated by getModelFromHomology using '; +0511 for i=1:numel(models) +0512 if i<numel(models) +0513 name=[name models{i}.id ', ']; +0514 else +0515 name=[name models{i}.id]; +0516 end +0517 end +0518 draftModel.name=name; +0519 draftModel.rxnNotes=cell(length(draftModel.rxns),1); +0520 draftModel.rxnNotes(:)={'Included by getModelFromHomology'}; +0521 draftModel.rxnConfidenceScores=NaN(length(draftModel.rxns),1); +0522 draftModel.rxnConfidenceScores(:)=2; +0523 draftModel=deleteUnusedGenes(draftModel,0); +0524 %Standardize grRules and notify if problematic grRules are found +0525 [draftModel.grRules,draftModel.rxnGeneMat]=standardizeGrRules(draftModel,false); +0526 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/getRxnsInComp.html b/doc/core/getRxnsInComp.html index ed0df70f..d518ce36 100644 --- a/doc/core/getRxnsInComp.html +++ b/doc/core/getRxnsInComp.html @@ -69,34 +69,32 @@

    SOURCE CODE ^% 0014 % Usage: [I, rxnNames]=getRxnsInComp(model,comp,includePartial) 0015 -0016 if ischar(comp) -0017 comp={comp}; -0018 end -0019 if nargin<3 -0020 includePartial=false; -0021 end +0016 comp=char(comp); +0017 if nargin<3 +0018 includePartial=false; +0019 end +0020 +0021 J=find(ismember(upper(model.comps),upper(comp))); 0022 -0023 J=find(ismember(upper(model.comps),upper(comp))); -0024 -0025 if numel(J)~=1 -0026 EM=['No unique match to compartment "' comp{1} '"']; -0027 dispEM(EM); -0028 end +0023 if numel(J)~=1 +0024 EM=['No unique match to compartment "' comp{1} '"']; +0025 dispEM(EM); +0026 end +0027 +0028 K=model.metComps==J; %Get all metabolites in the compartment 0029 -0030 K=model.metComps==J; %Get all metabolites in the compartment +0030 S=model.S~=0; 0031 -0032 S=model.S~=0; -0033 -0034 %Find the reactions which involve any of the mets -0035 [~, I]=find(S(K,:)); -0036 I=unique(I); -0037 -0038 %Then remove the ones which also include metabolites in other comps -0039 if includePartial==false -0040 I=I(sum(S(:,I))==sum(S(K,I))); -0041 end -0042 rxnNames=model.rxnNames(I); -0043 end +0032 %Find the reactions which involve any of the mets +0033 [~, I]=find(S(K,:)); +0034 I=unique(I); +0035 +0036 %Then remove the ones which also include metabolites in other comps +0037 if includePartial==false +0038 I=I(sum(S(:,I))==sum(S(K,I))); +0039 end +0040 rxnNames=model.rxnNames(I); +0041 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/haveFlux.html b/doc/core/haveFlux.html index 1f7befac..cd51311b 100644 --- a/doc/core/haveFlux.html +++ b/doc/core/haveFlux.html @@ -51,7 +51,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • getIndexes getIndexes
  • simplifyModel simplifyModel
  • This function is called by: @@ -89,52 +89,56 @@

    SOURCE CODE ^end 0028 if nargin<3 0029 rxns=model.rxns; -0030 end -0031 -0032 %This is since we're maximizing for the sum of fluxes, which isn't possible -0033 %when there are infinite bounds -0034 model.lb(model.lb==-inf)=-10000; -0035 model.ub(model.ub==inf)=10000; -0036 -0037 %Get the reaction IDs. A bit of an awkward way, but fine. -0038 indexes=getIndexes(model,rxns,'rxns'); -0039 rxns=model.rxns(indexes); -0040 -0041 %First remove all dead-end reactions -0042 smallModel=simplifyModel(model,false,false,true,true); -0043 -0044 %Get the indexes of the reactions in the connected model -0045 indexes=getIndexes(smallModel,intersect(smallModel.rxns,rxns),'rxns'); -0046 J=false(numel(indexes),1); -0047 mixIndexes=indexes(randperm(numel(indexes))); -0048 -0049 %Maximize for all fluxes first in order to get fewer rxns to test -0050 smallModel.c=ones(numel(smallModel.c),1); -0051 sol=solveLP(smallModel); -0052 J(abs(sol.x(mixIndexes))>cutOff)=true; -0053 -0054 %Loop through and maximize then minimize each rxn if it doesn't already -0055 %have a flux -0056 Z=zeros(numel(smallModel.c),1); -0057 hsSolOut=[]; -0058 for i=[1 -1] -0059 for j=1:numel(J) -0060 if J(j)==false -0061 %Only minimize for reversible reactions -0062 if i==1 || smallModel.rev(mixIndexes(j))~=0 -0063 smallModel.c=Z; -0064 smallModel.c(mixIndexes(j))=i; -0065 [sol, hsSolOut]=solveLP(smallModel,0,[],hsSolOut); -0066 if any(sol.x) -0067 J(abs(sol.x(mixIndexes))>cutOff)=true; -0068 end -0069 end -0070 end -0071 end -0072 end -0073 -0074 I=ismember(rxns,smallModel.rxns(mixIndexes(J))); -0075 end +0030 elseif ~islogical(rxns) && ~isnumeric(rxns) +0031 rxns=convertCharArray(rxns); +0032 end +0033 +0034 %This is since we're maximizing for the sum of fluxes, which isn't possible +0035 %when there are infinite bounds +0036 model.lb(model.lb==-inf)=-10000; +0037 model.ub(model.ub==inf)=10000; +0038 +0039 %Get the reaction IDs. A bit of an awkward way, but fine. +0040 indexes=getIndexes(model,rxns,'rxns'); +0041 rxns=model.rxns(indexes); +0042 +0043 %First remove all dead-end reactions +0044 smallModel=simplifyModel(model,false,false,true,true); +0045 +0046 %Get the indexes of the reactions in the connected model +0047 indexes=getIndexes(smallModel,intersect(smallModel.rxns,rxns),'rxns'); +0048 J=false(numel(indexes),1); +0049 mixIndexes=indexes(randperm(numel(indexes))); +0050 +0051 %Maximize for all fluxes first in order to get fewer rxns to test +0052 smallModel.c=ones(numel(smallModel.c),1); +0053 sol=solveLP(smallModel); +0054 if ~isempty(sol.x) +0055 J(abs(sol.x(mixIndexes))>cutOff)=true; +0056 end +0057 +0058 %Loop through and maximize then minimize each rxn if it doesn't already +0059 %have a flux +0060 Z=zeros(numel(smallModel.c),1); +0061 hsSolOut=[]; +0062 for i=[1 -1] +0063 for j=1:numel(J) +0064 if J(j)==false +0065 %Only minimize for reversible reactions +0066 if i==1 || smallModel.rev(mixIndexes(j))~=0 +0067 smallModel.c=Z; +0068 smallModel.c(mixIndexes(j))=i; +0069 [sol, hsSolOut]=solveLP(smallModel,0,[],hsSolOut); +0070 if any(sol.x) +0071 J(abs(sol.x(mixIndexes))>cutOff)=true; +0072 end +0073 end +0074 end +0075 end +0076 end +0077 +0078 I=ismember(rxns,smallModel.rxns(mixIndexes(J))); +0079 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/index.html b/doc/core/index.html index 5da70d52..9efd9d84 100644 --- a/doc/core/index.html +++ b/doc/core/index.html @@ -19,7 +19,7 @@

    Index for core

    Matlab files in this directory:

    -
     FSEOFFSEOF: implements the algorithm of Flux Scanning based on Enforced Objective Flux.
     addExchangeRxnsaddExchangeRxns
     addGenesRavenaddGenesRaven
     addMetsaddMets
     addRxnsaddRxns
     addRxnsGenesMetsaddRxnsGenesMets
     addTransportaddTransport
     analyzeSamplinganalyzeSampling
     buildEquationbuildEquation
     canConsumecanConsume
     canProducecanProduce
     changeGeneAssocchangeGeneAssoc
     changeGrRuleschangeGrRules
     changeRxnschangeRxns
     checkModelStructcheckModelStruct
     checkProductioncheckProduction
     checkRxncheckRxn
     checkTaskscheckTasks
     compareMultipleModelscompareMultipleModels
     compareRxnsGenesMetsCompscompareRxnsGenesMetsComps
     constructEquationsconstructEquations
     constructSconstructS
     consumeSomethingconsumeSomething
     contractModelcontractModel
     convertToIrrevconvertToIrrev
     copyToCompscopyToComps
     deleteUnusedGenesdeleteUnusedGenes
     dispEMdispEM
     expandModelexpandModel
     fillGapsfillGaps
     findGeneDeletionsfindGeneDeletions
     fitParametersfitParameters
     fitTasksfitTasks
     followChangedfollowChanged
     followFluxesfollowFluxes
     gapReportgapReport
     generateNewIdsgenerateNewIds
     getAllRxnsFromGenesgetAllRxnsFromGenes
     getAllSubGraphsgetAllSubGraphs
     getAllowedBoundsgetAllowedBounds
     getElementalBalancegetElementalBalance
     getEssentialRxnsgetEssentialRxns
     getExchangeRxnsgetExchangeRxns
     getExpressionStructuregetExpressionStructure
     getFluxZgetFluxZ
     getIndexesgetIndexes
     getMetsInCompgetMetsInComp
     getMinNrFluxesgetMinNrFluxes
     getModelFromHomologygetModelFromHomology
     getObjectiveStringgetObjectiveString
     getRxnsInCompgetRxnsInComp
     getTransportRxnsgetTransportRxns
     guessCompositionguessComposition
     haveFluxhaveFlux
     makeSomethingmakeSomething
     mapCompartmentsmapCompartments
     mergeCompartmentsmergeCompartments
     mergeModelsmergeModels
     parseFormulasparseFormulas
     parseRxnEquparseRxnEqu
     parseTaskListparseTaskList
     permuteModelpermuteModel
     predictLocalizationpredictLocalization
     printFluxesprintFluxes
     printModelprintModel
     printModelStatsprintModelStats
     randomSamplingrandomSampling
     removeBadRxnsremoveBadRxns
     removeGenesremoveGenes
     removeMetsremoveMets
     removeReactionsremoveReactions
     replaceMetsreplaceMets
     reporterMetabolitesreporterMetabolites
     setExchangeBoundssetExchangeBounds
     setParamsetParam
     simplifyModelsimplifyModel
     sortModelsortModel
     standardizeGrRulesstandardizeGrRules
    + FSEOFFSEOF: implements the algorithm of Flux Scanning based on Enforced Objective Flux.  addExchangeRxnsaddExchangeRxns  addGenesRavenaddGenesRaven  addMetsaddMets  addRxnsaddRxns  addRxnsGenesMetsaddRxnsGenesMets  addTransportaddTransport  analyzeSamplinganalyzeSampling  buildEquationbuildEquation  canConsumecanConsume  canProducecanProduce  changeGrRuleschangeGrRules  changeRxnschangeRxns  checkModelStructcheckModelStruct  checkProductioncheckProduction  checkRxncheckRxn  checkTaskscheckTasks  compareMultipleModelscompareMultipleModels  compareRxnsGenesMetsCompscompareRxnsGenesMetsComps  constructEquationsconstructEquations  constructSconstructS  consumeSomethingconsumeSomething  contractModelcontractModel  convertCharArrayconvertCharArray  convertToIrrevconvertToIrrev  copyToCompscopyToComps  deleteUnusedGenesdeleteUnusedGenes  dispEMdispEM  expandModelexpandModel  fillGapsfillGaps  findGeneDeletionsfindGeneDeletions  findRAVENrootfindRAVENroot  fitParametersfitParameters  fitTasksfitTasks  followChangedfollowChanged  followFluxesfollowFluxes  gapReportgapReport  generateNewIdsgenerateNewIds  getAllRxnsFromGenesgetAllRxnsFromGenes  getAllSubGraphsgetAllSubGraphs  getAllowedBoundsgetAllowedBounds  getElementalBalancegetElementalBalance  getEssentialRxnsgetEssentialRxns  getExchangeRxnsgetExchangeRxns  getExpressionStructuregetExpressionStructure  getFluxZgetFluxZ  getIndexesgetIndexes  getMetsInCompgetMetsInComp  getMinNrFluxesgetMinNrFluxes  getModelFromHomologygetModelFromHomology  getRxnsInCompgetRxnsInComp  getTransportRxnsgetTransportRxns  guessCompositionguessComposition  haveFluxhaveFlux  makeSomethingmakeSomething  mapCompartmentsmapCompartments  mergeCompartmentsmergeCompartments  mergeModelsmergeModels  parseFormulasparseFormulas  parseRxnEquparseRxnEqu  parseTaskListparseTaskList  permuteModelpermuteModel  predictLocalizationpredictLocalization  printFluxesprintFluxes  printModelprintModel  printModelStatsprintModelStats  randomSamplingrandomSampling  removeBadRxnsremoveBadRxns  removeGenesremoveGenes  removeMetsremoveMets  removeReactionsremoveReactions  replaceMetsreplaceMets  reporterMetabolitesreporterMetabolites  setExchangeBoundssetExchangeBounds  setParamsetParam  simplifyModelsimplifyModel  sortModelsortModel  standardizeGrRulesstandardizeGrRules diff --git a/doc/core/makeSomething.html b/doc/core/makeSomething.html index ca637d74..24880be6 100644 --- a/doc/core/makeSomething.html +++ b/doc/core/makeSomething.html @@ -74,7 +74,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • dispEM dispEM
  • getExchangeRxns getExchangeRxns
  • getIndexes getIndexes
  • setParam setParam
  • This function is called by: @@ -129,145 +129,147 @@

    SOURCE CODE ^if nargin<2 0046 ignoreMets=[]; -0047 end -0048 if nargin<3 -0049 isNames=false; -0050 end -0051 if nargin<4 -0052 minNrFluxes=false; -0053 end -0054 if nargin<5 -0055 allowExcretion=true; -0056 end -0057 if nargin<6 -0058 params.relGap=0.8; -0059 end -0060 if nargin<7 -0061 ignoreIntBounds=false; -0062 end -0063 -0064 if isNames==true && ~isempty(ignoreMets) -0065 %Check that metsToRemove is a cell array -0066 if iscellstr(ignoreMets)==false -0067 EM='Must supply a cell array of strings if isNames=true'; -0068 dispEM(EM); -0069 end -0070 end -0071 -0072 if isNames==false -0073 indexesToIgnore=getIndexes(model,ignoreMets,'mets'); -0074 else -0075 indexesToIgnore=[]; -0076 for i=1:numel(ignoreMets) -0077 indexesToIgnore=[indexesToIgnore;find(strcmp(ignoreMets(i),model.metNames))]; -0078 end -0079 end -0080 -0081 %Allow for excretion of all metabolites -0082 if allowExcretion==true -0083 model.b=[model.b(:,1) inf(numel(model.mets),1)]; -0084 end -0085 -0086 %Change all internal reactions to be unbounded in both directions -0087 if ignoreIntBounds==true -0088 [~, I]=getExchangeRxns(model); -0089 nonExc=true(numel(model.rxns),1); -0090 nonExc(I)=false; -0091 model=setParam(model,'lb',nonExc,-1000); -0092 model=setParam(model,'ub',nonExc,1000); -0093 model=setParam(model,'rev',nonExc,1); -0094 end -0095 -0096 solution=[]; -0097 metabolite=[]; -0098 -0099 nRxns=numel(model.rxns); -0100 nMets=numel(model.mets); -0101 -0102 %Add excretion reactions for all metabolites -0103 model.S=[model.S speye(nMets)*-1]; -0104 -0105 %Add so that they all produce a fake metabolite -0106 model.S=[model.S;[sparse(1,nRxns) ones(1,nMets)]]; -0107 -0108 %Change so that the ignoreMets have a coefficient 0 in their reactions. -0109 %Does not remove the actual reaction to make mapping easier later -0110 model.S(:,indexesToIgnore+nRxns)=0; -0111 -0112 %Add an excretion reaction for this last fake metabolite -0113 model.S(size(model.S,1),size(model.S,2)+1)=-1; -0114 model.b=[model.b;zeros(1,size(model.b,2))]; -0115 model.lb=[model.lb;zeros(nMets,1);1]; -0116 model.ub=[model.ub;inf(nMets+1,1)]; -0117 model.rev=[model.rev;zeros(nMets+1,1)]; -0118 model.c=zeros(size(model.S,2),1); -0119 -0120 %Add padding to the reaction annotation to prevent an error in solveLP -0121 padding=1:numel(model.rev); -0122 padding=num2cell(padding)'; -0123 padding=cellfun(@num2str,padding,'uniformoutput',false); -0124 model.rxns=padding; -0125 model.rxnNames=padding; -0126 model.eccodes=padding; -0127 model.rxnMiriams=padding; -0128 model.grRules=padding; -0129 if isfield(model,'genes') -0130 model.rxnGeneMat=sparse(numel(model.rev),numel(model.genes)); -0131 end -0132 model.subSystems=padding; -0133 model.rxnFrom=padding; -0134 model.rxnComps=ones(numel(model.rev),1); -0135 model.rxnNotes=padding; -0136 model.rxnReferences=padding; -0137 model.rxnConfidenceScores=NaN(numel(model.rev),1); -0138 -0139 sol=solveLP(model,1); -0140 if any(sol.x) -0141 %It could be that several metabolites were produced in order to get the -0142 %best solution. The setdiff is to avoid including the last fake -0143 %metabolite -0144 I=setdiff(find(sol.x(nRxns+1:end)>0.1),size(model.S,1)); -0145 -0146 if any(I) %This should always be true -0147 %Change the coefficients so that only the first is produced. This -0148 %is not always possible, but it is tested for since it it results -0149 %in more easily interpretable results -0150 -0151 oldS=model.S; -0152 foundSingle=false; -0153 %Test if any of the metabolites could be produced on their own -0154 for i=1:numel(I) -0155 model.S=oldS; -0156 J=nRxns+1:numel(model.lb)-1; -0157 J(I(i))=[]; -0158 model.S(:,J)=0; -0159 sol=solveLP(model); -0160 if any(sol.x) -0161 foundSingle=true; -0162 break; -0163 end -0164 end -0165 %This means that there was no metabolite which could be produced on -0166 %its own. Then let all the produceable metabolites be produced. -0167 if foundSingle==false -0168 model.S=oldS; -0169 end -0170 if minNrFluxes==true -0171 %Has to add names for the rxns to prevent an error in -0172 %minNrFluxes -0173 model.rxns=cell(numel(model.lb),1); -0174 model.rxns(:)=sprintfc('tmp_%d',1:numel(model.lb)); -0175 model.mets=cell(size(model.b,1),1); -0176 model.mets(:)={'TEMP'}; -0177 sol=solveLP(model,3,params); -0178 else -0179 sol=solveLP(model,1); -0180 end -0181 solution=sol.x(1:nRxns); -0182 metabolite=find(sol.x(nRxns+1:end-1)>0.1); -0183 end -0184 end -0185 end +0047 elseif ~islogical(ignoreMets) && ~isnumeric(ignoreMets) +0048 ignoreMets=convertCharArray(ignoreMets); +0049 end +0050 if nargin<3 +0051 isNames=false; +0052 end +0053 if nargin<4 +0054 minNrFluxes=false; +0055 end +0056 if nargin<5 +0057 allowExcretion=true; +0058 end +0059 if nargin<6 +0060 params.relGap=0.8; +0061 end +0062 if nargin<7 +0063 ignoreIntBounds=false; +0064 end +0065 +0066 if isNames==true && ~isempty(ignoreMets) +0067 %Check that metsToRemove is a cell array +0068 if iscellstr(ignoreMets)==false +0069 EM='Must supply a cell array of strings if isNames=true'; +0070 dispEM(EM); +0071 end +0072 end +0073 +0074 if isNames==false +0075 indexesToIgnore=getIndexes(model,ignoreMets,'mets'); +0076 else +0077 indexesToIgnore=[]; +0078 for i=1:numel(ignoreMets) +0079 indexesToIgnore=[indexesToIgnore;find(strcmp(ignoreMets(i),model.metNames))]; +0080 end +0081 end +0082 +0083 %Allow for excretion of all metabolites +0084 if allowExcretion==true +0085 model.b=[model.b(:,1) inf(numel(model.mets),1)]; +0086 end +0087 +0088 %Change all internal reactions to be unbounded in both directions +0089 if ignoreIntBounds==true +0090 [~, I]=getExchangeRxns(model); +0091 nonExc=true(numel(model.rxns),1); +0092 nonExc(I)=false; +0093 model=setParam(model,'lb',nonExc,-1000); +0094 model=setParam(model,'ub',nonExc,1000); +0095 model=setParam(model,'rev',nonExc,1); +0096 end +0097 +0098 solution=[]; +0099 metabolite=[]; +0100 +0101 nRxns=numel(model.rxns); +0102 nMets=numel(model.mets); +0103 +0104 %Add excretion reactions for all metabolites +0105 model.S=[model.S speye(nMets)*-1]; +0106 +0107 %Add so that they all produce a fake metabolite +0108 model.S=[model.S;[sparse(1,nRxns) ones(1,nMets)]]; +0109 +0110 %Change so that the ignoreMets have a coefficient 0 in their reactions. +0111 %Does not remove the actual reaction to make mapping easier later +0112 model.S(:,indexesToIgnore+nRxns)=0; +0113 +0114 %Add an excretion reaction for this last fake metabolite +0115 model.S(size(model.S,1),size(model.S,2)+1)=-1; +0116 model.b=[model.b;zeros(1,size(model.b,2))]; +0117 model.lb=[model.lb;zeros(nMets,1);1]; +0118 model.ub=[model.ub;inf(nMets+1,1)]; +0119 model.rev=[model.rev;zeros(nMets+1,1)]; +0120 model.c=zeros(size(model.S,2),1); +0121 +0122 %Add padding to the reaction annotation to prevent an error in solveLP +0123 padding=1:numel(model.rev); +0124 padding=num2cell(padding)'; +0125 padding=cellfun(@num2str,padding,'uniformoutput',false); +0126 model.rxns=padding; +0127 model.rxnNames=padding; +0128 model.eccodes=padding; +0129 model.rxnMiriams=padding; +0130 model.grRules=padding; +0131 if isfield(model,'genes') +0132 model.rxnGeneMat=sparse(numel(model.rev),numel(model.genes)); +0133 end +0134 model.subSystems=padding; +0135 model.rxnFrom=padding; +0136 model.rxnComps=ones(numel(model.rev),1); +0137 model.rxnNotes=padding; +0138 model.rxnReferences=padding; +0139 model.rxnConfidenceScores=NaN(numel(model.rev),1); +0140 +0141 sol=solveLP(model,1); +0142 if any(sol.x) +0143 %It could be that several metabolites were produced in order to get the +0144 %best solution. The setdiff is to avoid including the last fake +0145 %metabolite +0146 I=setdiff(find(sol.x(nRxns+1:end)>0.1),size(model.S,1)); +0147 +0148 if any(I) %This should always be true +0149 %Change the coefficients so that only the first is produced. This +0150 %is not always possible, but it is tested for since it it results +0151 %in more easily interpretable results +0152 +0153 oldS=model.S; +0154 foundSingle=false; +0155 %Test if any of the metabolites could be produced on their own +0156 for i=1:numel(I) +0157 model.S=oldS; +0158 J=nRxns+1:numel(model.lb)-1; +0159 J(I(i))=[]; +0160 model.S(:,J)=0; +0161 sol=solveLP(model); +0162 if any(sol.x) +0163 foundSingle=true; +0164 break; +0165 end +0166 end +0167 %This means that there was no metabolite which could be produced on +0168 %its own. Then let all the produceable metabolites be produced. +0169 if foundSingle==false +0170 model.S=oldS; +0171 end +0172 if minNrFluxes==true +0173 %Has to add names for the rxns to prevent an error in +0174 %minNrFluxes +0175 model.rxns=cell(numel(model.lb),1); +0176 model.rxns(:)=sprintfc('tmp_%d',1:numel(model.lb)); +0177 model.mets=cell(size(model.b,1),1); +0178 model.mets(:)={'TEMP'}; +0179 sol=solveLP(model,3,params); +0180 else +0181 sol=solveLP(model,1); +0182 end +0183 solution=sol.x(1:nRxns); +0184 metabolite=find(sol.x(nRxns+1:end-1)>0.1); +0185 end +0186 end +0187 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/mergeModels.html b/doc/core/mergeModels.html index 9796f951..589d6050 100644 --- a/doc/core/mergeModels.html +++ b/doc/core/mergeModels.html @@ -28,7 +28,10 @@

    SYNOPSIS ^DESCRIPTION ^

     mergeModels
    -   Merges models into one model structure.
    +   Merges models into one model structure. Reactions are added without any
    +   checks, so duplicate reactions might appear. Metabolites are matched by
    +   their name and compartment (metaboliteName[comp]), while genes are
    +   matched by their name.
     
        models          a cell array with model structures
        metParam        string specifying whether to refer to metabolite name
    @@ -58,109 +61,109 @@ 

    CROSS-REFERENCE INFORMATION ^
 <h2><a name=SOURCE CODE ^

    0001 function model=mergeModels(models,metParam,supressWarnings)
     0002 % mergeModels
    -0003 %   Merges models into one model structure.
    -0004 %
    -0005 %   models          a cell array with model structures
    -0006 %   metParam        string specifying whether to refer to metabolite name
    -0007 %                   (metNames) or ID (mets) for matching (default, metNames)
    -0008 %   supressWarnings true if warnings should be supressed (opt, default
    -0009 %                   false)
    -0010 %
    -0011 %   model     a model structure with the merged model. Follows the structure
    -0012 %             of normal models but also has 'rxnFrom/metFrom/geneFrom' fields
    -0013 %             to indicate from which model each reaction/metabolite/gene was
    -0014 %             taken
    -0015 %
    -0016 %   Usage: model=mergeModels(models)
    -0017 
    -0018 %Just return the model
    -0019 if numel(models)<=1
    -0020     model=models{1};
    -0021     return;
    -0022 end
    -0023 
    -0024 if nargin<2
    -0025     metParam='metNames';
    -0026 end
    -0027 
    -0028 if nargin<3
    -0029     supressWarnings=false;
    -0030 end
    -0031 
    -0032 %Add new functionality in the order specified in models
    -0033 model=models{1};
    -0034 model.id='MERGED';
    -0035 model.name='';
    +0003 %   Merges models into one model structure. Reactions are added without any
    +0004 %   checks, so duplicate reactions might appear. Metabolites are matched by
    +0005 %   their name and compartment (metaboliteName[comp]), while genes are
    +0006 %   matched by their name.
    +0007 %
    +0008 %   models          a cell array with model structures
    +0009 %   metParam        string specifying whether to refer to metabolite name
    +0010 %                   (metNames) or ID (mets) for matching (default, metNames)
    +0011 %   supressWarnings true if warnings should be supressed (opt, default
    +0012 %                   false)
    +0013 %
    +0014 %   model     a model structure with the merged model. Follows the structure
    +0015 %             of normal models but also has 'rxnFrom/metFrom/geneFrom' fields
    +0016 %             to indicate from which model each reaction/metabolite/gene was
    +0017 %             taken
    +0018 %
    +0019 %   Usage: model=mergeModels(models)
    +0020 
    +0021 %Just return the model
    +0022 if numel(models)<=1
    +0023     model=models{1};
    +0024     return;
    +0025 end
    +0026 
    +0027 if nargin<2
    +0028     metParam='metNames';
    +0029 else
    +0030     metParam=char(metParam);
    +0031 end
    +0032 
    +0033 if nargin<3
    +0034     supressWarnings=false;
    +0035 end
     0036 
    -0037 model.rxnFrom=cell(numel(models{1}.rxns),1);
    -0038 model.rxnFrom(:)={models{1}.id};
    -0039 model.metFrom=cell(numel(models{1}.mets),1);
    -0040 model.metFrom(:)={models{1}.id};
    -0041 if isfield(models{1},'genes')
    -0042     model.geneFrom=cell(numel(models{1}.genes),1);
    -0043     model.geneFrom(:)={models{1}.id};
    -0044 end
    -0045 
    -0046 if isfield(model,'subSystems')
    -0047     hasDeletedSubSystem=false;
    -0048 else
    -0049     if supressWarnings==false
    -0050         EM='Cannot add subsystems since the existing model has no subsystems info. All reactions must have a subsystem for this to be included';
    -0051         dispEM(EM,false);
    -0052     end
    -0053     hasDeletedSubSystem=true;
    -0054 end
    -0055 
    -0056 if isfield(model,'equations')
    -0057     model=rmfield(model,'equations');
    -0058 end
    -0059 
    -0060 for i=2:numel(models)
    -0061     %Add the model id to the rxn id id it already exists in the model (id
    -0062     %have to be unique) This is because it makes a '[]' string if no new
    -0063     %reactions
    -0064     if ~isempty(models{i}.rxns)
    -0065         I=ismember(models{i}.rxns,model.rxns);
    -0066         models{i}.rxns(I)=strcat(models{i}.rxns(I),['_' models{i}.id]);
    -0067     end
    -0068     
    -0069     %Make sure that there are no conflicting reaction ids
    -0070     [~, ~, conflicting]=intersect(model.rxns,models{i}.rxns);
    -0071     
    -0072     if ~isempty(conflicting)
    -0073         printString=cell(numel(conflicting),1);
    -0074         for j=1:numel(conflicting)
    -0075             printString{j}=['Old: ' models{i}.rxns{conflicting(j)} ' New: ' models{i}.rxns{conflicting(j)} '_' models{i}.id];
    -0076             models{i}.rxns{conflicting(j)}=[models{i}.rxns{conflicting(j)} '_' models{i}.id];
    +0037 %Add new functionality in the order specified in models
    +0038 model=models{1};
    +0039 model.id='MERGED';
    +0040 model.name='';
    +0041 
    +0042 model.rxnFrom=cell(numel(models{1}.rxns),1);
    +0043 model.rxnFrom(:)={models{1}.id};
    +0044 model.metFrom=cell(numel(models{1}.mets),1);
    +0045 model.metFrom(:)={models{1}.id};
    +0046 if isfield(models{1},'genes')
    +0047     model.geneFrom=cell(numel(models{1}.genes),1);
    +0048     model.geneFrom(:)={models{1}.id};
    +0049 end
    +0050 
    +0051 if isfield(model,'equations')
    +0052     model=rmfield(model,'equations');
    +0053 end
    +0054 
    +0055 for i=2:numel(models)
    +0056     %Add the model id to the rxn id id it already exists in the model (id
    +0057     %have to be unique) This is because it makes a '[]' string if no new
    +0058     %reactions
    +0059     if ~isempty(models{i}.rxns)
    +0060         I=ismember(models{i}.rxns,model.rxns);
    +0061         models{i}.rxns(I)=strcat(models{i}.rxns(I),['_' models{i}.id]);
    +0062     end
    +0063     
    +0064     %Make sure that there are no conflicting reaction ids
    +0065     [~, ~, conflicting]=intersect(model.rxns,models{i}.rxns);
    +0066     
    +0067     if ~isempty(conflicting)
    +0068         printString=cell(numel(conflicting),1);
    +0069         for j=1:numel(conflicting)
    +0070             printString{j}=['Old: ' models{i}.rxns{conflicting(j)} ' New: ' models{i}.rxns{conflicting(j)} '_' models{i}.id];
    +0071             models{i}.rxns{conflicting(j)}=[models{i}.rxns{conflicting(j)} '_' models{i}.id];
    +0072         end
    +0073         if supressWarnings==false
    +0074             EM=['The following reaction IDs in ' models{i}.id ' are already present in the model and were renamed:'];
    +0075             dispEM(EM,false,printString);
    +0076             fprintf('\n');
     0077         end
    -0078         if supressWarnings==false
    -0079             EM=['The following reaction IDs in ' models{i}.id ' are already present in the model and were renamed:'];
    -0080             dispEM(EM,false,printString);
    -0081             fprintf('\n');
    -0082         end
    -0083     end
    -0084     
    -0085     %Add all static stuff
    -0086     rxnFrom=cell(numel(models{i}.rxns),1);
    -0087     rxnFrom(:)={models{i}.id};
    -0088     model.rxnFrom=[model.rxnFrom;rxnFrom];
    -0089     model.rxns=[model.rxns;models{i}.rxns];
    -0090     model.rxnNames=[model.rxnNames;models{i}.rxnNames];
    -0091     model.lb=[model.lb;models{i}.lb];
    -0092     model.ub=[model.ub;models{i}.ub];
    -0093     model.c=[model.c;models{i}.c];
    -0094     model.rev=[model.rev;models{i}.rev];
    -0095     
    -0096     if hasDeletedSubSystem==false
    -0097         if isfield(models{i},'subSystems')
    -0098             model.subSystems=[model.subSystems;models{i}.subSystems];
    -0099         else
    -0100             if supressWarnings==false
    -0101                 EM='Cannot add subsystems since the existing model has no subsystems info. All reactions must have a subsystem for this to be included. Deleting subSystems field';
    -0102                 dispEM(EM,false);
    -0103             end
    -0104             hasDeletedSubSystem=true;
    -0105             model=rmfield(model,'subSystems');
    +0078     end
    +0079     
    +0080     %Add all static stuff
    +0081     rxnFrom=cell(numel(models{i}.rxns),1);
    +0082     rxnFrom(:)={models{i}.id};
    +0083     model.rxnFrom=[model.rxnFrom;rxnFrom];
    +0084     model.rxns=[model.rxns;models{i}.rxns];
    +0085     model.rxnNames=[model.rxnNames;models{i}.rxnNames];
    +0086     model.lb=[model.lb;models{i}.lb];
    +0087     model.ub=[model.ub;models{i}.ub];
    +0088     model.c=[model.c;models{i}.c];
    +0089     model.rev=[model.rev;models{i}.rev];
    +0090     
    +0091     if isfield(models{i},'subSystems')
    +0092         if isfield(model,'subSystems')
    +0093             model.subSystems=[model.subSystems;models{i}.subSystems];
    +0094         else
    +0095             emptySubSystem=cell(numel(model.rxns)-numel(models{i}.rxns),1);
    +0096             emptySubSystem(:)={''};
    +0097             emptySubSystem=cellfun(@(x) cell(0,0),emptySubSystem,'UniformOutput',false);
    +0098             model.subSystems=[emptySubSystem;models{i}.subSystems];
    +0099         end
    +0100     else
    +0101         if isfield(model,'subSystems')
    +0102             emptySubSystem=cell(numel(models{i}.rxns),1);
    +0103             emptySubSystem(:)={''};
    +0104             emptySubSystem=cellfun(@(x) cell(0,0),emptySubSystem,'UniformOutput',false);
    +0105             model.subSystems=[model.subSystems;emptySubSystem];
     0106         end
     0107     end
     0108     
    diff --git a/doc/core/permuteModel.html b/doc/core/permuteModel.html
    index 32b608e1..fbe054ff 100644
    --- a/doc/core/permuteModel.html
    +++ b/doc/core/permuteModel.html
    @@ -72,7 +72,7 @@ 

    SOURCE CODE ^% Usage: newModel=permuteModel(model, indexes, type) 0016 0017 newModel=model; -0018 indexes=indexes(:); +0018 type=char(type); 0019 0020 switch type 0021 case 'rxns' diff --git a/doc/core/predictLocalization.html b/doc/core/predictLocalization.html index dc09b8cb..08903f28 100644 --- a/doc/core/predictLocalization.html +++ b/doc/core/predictLocalization.html @@ -197,900 +197,901 @@

    SOURCE CODE ^dispEM(EM,false); 0093 end 0094 -0095 I=ismember(defaultCompartment,GSS.compartments); -0096 if I==false -0097 EM='defaultCompartment not found in GSS'; -0098 dispEM(EM); -0099 end -0100 -0101 if numel(model.comps)>1 -0102 EM='The model has several compartments. All compartments will be merged'; -0103 dispEM(EM,false); -0104 model=mergeCompartments(model,true,true); -0105 end -0106 -0107 %***Begin formating the data structures -0108 -0109 %Expand the model so that iso-enzymes have different reactions -0110 model=expandModel(model); -0111 -0112 %Identify reactions that have to be deleted because the involved mets are -0113 %never produced. This is done in an iterative manner -0114 removedRxns={}; -0115 %This is to keep track of which metabolites are removed in this step. It is -0116 %needed to adjust the transport costs -0117 originalModelMets=model.mets; -0118 while 1 -0119 irrevModel=convertToIrrev(model); -0120 -0121 I=sum(irrevModel.S>0,2); -0122 -0123 %Pretend that the unconstrained metabolites are made enough -0124 if isfield(irrevModel,'unconstrained') -0125 I(irrevModel.unconstrained~=0)=2; -0126 end -0127 metsToDelete=false(numel(model.mets),1); -0128 -0129 %This is not very neat but iterate through each metabolite and check -0130 %whether it can be produced (without using only one isolated reversible -0131 %reaction) -0132 for i=1:numel(irrevModel.mets) -0133 %If something can be made in two reactions then everything is fine. -0134 %If it can be made in one reaction it is fine unless it is through -0135 %an isolated reversible reaction (which can act as a mini loop) -0136 if I(i)<2 -0137 if I(i)==1 -0138 %Find the reaction where this metabolite is produced -0139 [~, J]=find(irrevModel.S(i,:)>0); -0140 -0141 %Check the metabolites that are consumed in this reaction. -0142 %The problem is if any of them is only produced in the -0143 %opposite reversible reaction -0144 K=irrevModel.S(:,J)<0; -0145 check=find(K & I<=1); -0146 -0147 for j=1:numel(check) -0148 %Find the reactions where it participates -0149 [~, L]=find(irrevModel.S(check(j),:)>0); -0150 -0151 if ~isempty(L) -0152 rxn=irrevModel.rxns(J); -0153 rxnRev=irrevModel.rxns(L); -0154 if strcmp(strrep(rxn,'_REV',''),strrep(rxnRev,'_REV','')) -0155 metsToDelete(i)=true; -0156 end -0157 else -0158 %If the metabolite was never produced then do -0159 %nothing and deal with it when the loop gets there -0160 continue; -0161 end -0162 end -0163 else -0164 %Not made anywhere -0165 metsToDelete(i)=true; -0166 end -0167 end -0168 end -0169 -0170 if any(metsToDelete) -0171 %Delete any reactions involving any of the metsToDelete -0172 [~, I]=find(model.S(metsToDelete,:)); -0173 removedRxns=[removedRxns;model.rxns(I)]; -0174 model=removeReactions(model,I,true,true); -0175 else -0176 %All bad reactions deleted -0177 break; -0178 end -0179 end -0180 -0181 %Adjust the transport costs -0182 transportCost=transportCost(ismember(originalModelMets,model.mets)); -0183 -0184 %Assign fake genes to reactions without genes. This is just to make things -0185 %easier later on -0186 I=find(sum(model.rxnGeneMat,2)==0); -0187 for i=1:numel(I) -0188 model.genes=[model.genes;['&&FAKE&&' num2str(i)]]; -0189 if isfield(model,'geneShortNames') -0190 model.geneShortNames=[model.geneShortNames;{''}]; -0191 end -0192 if isfield(model,'geneMiriams') -0193 model.geneMiriams=[model.geneMiriams;{[]}]; -0194 end -0195 if isfield(model,'geneFrom') -0196 model.geneFrom=[model.geneFrom;{{'FAKE'}}]; -0197 end -0198 model.rxnGeneMat(I(i),numel(model.genes))=1; -0199 model.grRules{I(i)}=''; -0200 end -0201 -0202 %Update the GSS. All genes, fake or real, for which there is no evidence -0203 %gets a score 0.5 in all compartments. Also just to make it easier further -0204 %on -0205 I=setdiff(model.genes,GSS.genes); -0206 GSS.genes=[GSS.genes;I]; -0207 GSS.scores=[GSS.scores;ones(numel(I),numel(GSS.compartments))*0.5]; -0208 -0209 %Gene complexes should be moved together in order to be biologically -0210 %relevant. The average score for the genes is used for each compartment. -0211 %This is done by changing the model so that gene complexes are used as a -0212 %single gene name and then a score is calculated for that "gene". -0213 -0214 %Only "and"-relationships exist after expandModel -0215 genes=unique(model.grRules); -0216 nGenes=strrep(genes,'(',''); -0217 nGenes=strrep(nGenes,')',''); -0218 %nGenes=strrep(nGenes,' and ','_and_'); -0219 complexes=setdiff(nGenes,model.genes); -0220 if ~isempty(complexes) -0221 if isempty(complexes{1}) %Empty grRules also come up here -0222 complexes(1)=[]; -0223 end -0224 end -0225 cScores=zeros(numel(complexes),numel(GSS.compartments)); -0226 for i=1:numel(complexes) -0227 genesInComplex=regexp(complexes{i},' and ','split'); -0228 -0229 %Find these genes in GSS -0230 [I, J]=ismember(genesInComplex,GSS.genes); -0231 -0232 if any(I) -0233 %Get the average of the genes that were found -0234 mScores=mean(GSS.scores(J(I),:)); -0235 -0236 %And add 0.5 for the genes that were not found in order to be -0237 %consistent with non-complexes -0238 mScores=(mScores.*sum(I)+(numel(genesInComplex)-sum(I))*0.5)/numel(genesInComplex); -0239 else -0240 EM=['Could not parse grRule "' complexes{i} '". Assigning score 0.0 in all compartments']; -0241 dispEM(EM,false); -0242 mScores=ones(1,numel(genesInComplex))*0.5; -0243 end -0244 cScores(i,:)=mScores; -0245 -0246 %Add this complex as a new gene -0247 model.genes=[model.genes;complexes{i}]; -0248 if isfield(model,'geneMiriams') -0249 model.geneMiriams=[model.geneMiriams;{[]}]; -0250 end -0251 if isfield(model,'geneShortNames') -0252 model.geneShortNames=[model.geneShortNames;{''}]; -0253 end -0254 if isfield(model,'geneFrom') -0255 model.geneFrom=[model.geneFrom;{'COMPLEX'}]; -0256 end -0257 %Find the reactions which had the original complex and change them to -0258 %use the new "gene" -0259 I=ismember(model.grRules,['(' complexes{i} ')']); -0260 -0261 %Should check more carefully if there can be an error here -0262 if ~isempty(I) -0263 model.rxnGeneMat(I,:)=0; %Ok since the split on "or" was applied -0264 model.rxnGeneMat(I,numel(model.genes))=1; -0265 end -0266 end -0267 -0268 %Add the new "genes" -0269 GSS.genes=[GSS.genes;complexes]; -0270 GSS.scores=[GSS.scores;cScores]; -0271 -0272 %After merging the complexes it could happen that there are genes that are -0273 %no longer in use. Delete such genes -0274 model=removeReactions(model,{},false,true); -0275 -0276 %Exchange reactions, defined as involving an unconstrained metabolite, are -0277 %special in that they have to stay in the defaultCompartment. This means -0278 %that uptake/excretion of metabolites is always via the default -0279 %compartment. This is a small simplification, but should be valid in most -0280 %cases -0281 [~, I]=getExchangeRxns(model); -0282 -0283 %It will be easier later on if the same place. Put them in the beginning -0284 J=1:numel(model.rxns); -0285 J(I)=[]; -0286 model=permuteModel(model,[I;J'],'rxns'); -0287 -0288 %Number of exchange reactions -0289 nER=numel(I); -0290 -0291 %Also put the exchange metabolites in the beginning -0292 if isfield(model,'unconstrained') -0293 I=find(model.unconstrained); -0294 J=1:numel(model.mets); -0295 J(I)=[]; -0296 model=permuteModel(model,[I;J'],'mets'); -0297 %Also reorder the transport costs -0298 transportCost=transportCost([I;J']); -0299 %Number of exchange metabolites -0300 nEM=numel(I); -0301 else -0302 nEM=0; -0303 end -0304 -0305 %There is no point of having genes for exchange reactions, so delete them. -0306 %Also to make computations easier -0307 model.rxnGeneMat(1:nER,:)=0; -0308 model.grRules(1:nER)={''}; -0309 -0310 %Remove unused genes -0311 model=removeReactions(model,{},false,true); -0312 -0313 %Remove genes with no match to the model and reorder so that the genes are -0314 %in the same order as model.genes. Since the fake genes are already added -0315 %so that all genes in model exist in GSS it is fine to do like this -0316 [~, J]=ismember(model.genes,GSS.genes); -0317 GSS.genes=model.genes; -0318 GSS.scores=GSS.scores(J,:); -0319 -0320 %Reorder the GSS so that the first index corresponds to the default -0321 %compartment -0322 [~, J]=ismember(defaultCompartment,GSS.compartments); -0323 reorder=1:numel(GSS.compartments); -0324 reorder(J)=[]; -0325 reorder=[J reorder]; -0326 GSS.scores=GSS.scores(:,reorder); -0327 GSS.compartments=GSS.compartments(reorder); -0328 -0329 %Since it is only checked whether the metabolites can be synthesized, there -0330 %is no need to care about the stoichiometry. Change to -1/1 to simplify -0331 %later. Keep the S matrix for later though -0332 oldS=model.S; -0333 model.S(model.S>0)=1; -0334 model.S(model.S<0)=-1; -0335 -0336 %Here is a bit of a trick. To avoid the recurring calculation which -0337 %reactions are reversible, the reversible reactions have the coefficients -0338 %-10/10 instead of -1/1 -0339 model.S(:,model.rev==1)=model.S(:,model.rev==1).*10; -0340 -0341 %***Begin problem formulation -0342 -0343 %Some numbers that are good to have -0344 nRxns=numel(model.rxns)-nER; %Excluding exchange rxns -0345 nMets=numel(model.mets)-nEM; %Excluding exchange mets -0346 nGenes=numel(model.genes); -0347 nComps=numel(GSS.compartments); -0348 -0349 %Create a big stoichiometric matrix that will be the current model. In -0350 %order to have faster simulations the maximal model size is declared and -0351 %reactions are then moved within it. -0352 -0353 %First the original model (with the first nE being exchange rxns), then -0354 %reserve space for number of rxns minus exchange rxns for each non-default -0355 %compartment, then transport reactions for all non-exchange mets between -0356 %the default compartment and all others. -0357 %NOTE: Kept eye()*0 since eye() can be used to include all transport from -0358 %the beginning -0359 s=repmat(eye(nMets)*0,1,nComps-1); -0360 s=[zeros(numel(model.mets)-nMets,size(s,2));s]; -0361 S=[model.S sparse(numel(model.mets),nRxns*(nComps-1)) s]; -0362 s=[sparse(nMets*(nComps-1),numel(model.rxns)+nRxns*(nComps-1)) eye(nMets*(nComps-1))*0]; -0363 S=[S;s]; -0364 -0365 %Also replicate the transport costs -0366 transportCost=[transportCost(1:nEM);repmat(transportCost(nEM+1:end),nComps,1)]; -0367 -0368 %Create a binary matrix that says where the genes are in the current -0369 %solution -0370 g2c=false(nGenes,nComps); -0371 %All genes start in the default compartment -0372 g2c(:,1)=true; -0373 -0374 %Start of main optimization loop -0375 tic; -0376 bestScore=-inf; -0377 bestS=[]; -0378 bestg2c=[]; -0379 -0380 %Temp for testing -0381 plotScore=[]; -0382 nTrans=[]; -0383 totScore=[]; -0384 minScore=sum(min(GSS.scores,[],2)); -0385 maxScore=sum(max(GSS.scores,[],2)); -0386 -0387 while toc<maxTime*60 -0388 %Pick a random gene, weighted by it is current score minus the best -0389 %score for that gene (often 1.0, but can be 0.5 for no genes or average -0390 %for complexes). Genes with bad fits are more likely to be moved. This -0391 %formulation never moves a gene from its best compartment. Therefore a -0392 %small uniform weight is added -0393 [I, J]=find(g2c); -0394 geneToMove=randsample(nGenes,1,true,max(GSS.scores(I,:),[],2)-GSS.scores(sub2ind(size(g2c),I,J))+0.1); -0395 -0396 %Sample among possible compartments to move to. Add a larger weight to -0397 %even out the odds a little. Also a way of getting rid of loops where -0398 %the same set of genes are moved back and forth several times -0399 toComp=randsample(nComps,1,true,GSS.scores(geneToMove,:)+0.2); -0400 -0401 %Check that it moves to a new compartment -0402 if toComp==find(g2c(geneToMove,:)) -0403 continue; -0404 end -0405 -0406 %Moves the gene -0407 [newS, newg2c]=moveGene(S,model,g2c,geneToMove,toComp,nRxns,nMets); -0408 -0409 %Tries to connect the network. If this was not possible in 10 -0410 %iterations, then abort. If more than 20 modifications were needed then -0411 %it is unlikely that it will be a lower score -0412 wasConnected=false; -0413 for j=1:10 -0414 %Find the metabolites that are now unconnected -0415 unconnected=findUnconnected(newS,nEM); -0416 -0417 %Continue if there are still unconnected -0418 if any(unconnected) -0419 %For each gene find out how many of these could be connected if -0420 %the gene was moved and how many would be disconnected by -0421 %moving that gene -0422 [geneIndex, moveTo, deltaConnected, deltaScore]=selectGenes(newS,nEM,nMets,nER,nRxns,model,unconnected,g2c,GSS); -0423 -0424 %Score which gene would be the best to move. The highest -0425 %deltaScore is 1.0. It should be possible to move a gene from -0426 %worst to best compartment even if it disconnects, say, 1.5 -0427 %more metabolites -0428 [score, I]=max(1.5*deltaScore+deltaConnected); -0429 -0430 %Check if it has to add a transport or if there is a gene that -0431 %could be moved order to have a more connected network -0432 hasToAddTransport=true; -0433 if ~isempty(deltaConnected) -0434 if score>0 -0435 hasToAddTransport=false; -0436 end -0437 end -0438 -0439 %If it is possible to move any gene in order to have a more -0440 %connected network, then move the best one -0441 if hasToAddTransport==false -0442 [newS, newg2c]=moveGene(newS,model,g2c,geneIndex(I),moveTo(I),nRxns,nMets); -0443 else -0444 %Choose a random unconnected metabolite that should be -0445 %connected -0446 transMet=unconnected(randsample(numel(unconnected),1)); -0447 -0448 %First get where the metabolite is now -0449 comps=ceil((transMet-nEM)/((size(S,1)-nEM)/nComps)); -0450 -0451 %Find the corresponding metabolite index if it were in the -0452 %default compartment -0453 dcIndex=transMet-(comps-1)*nMets; -0454 -0455 %Then get the indexes of that metabolite in all -0456 %compartments -0457 allIndexes=dcIndex; -0458 for k=1:nComps-1 -0459 allIndexes=[allIndexes;dcIndex+nMets*k]; -0460 end -0461 -0462 %It could be that some of these are not used in any -0463 %reaction. Get only the ones which are -0464 I=sum(newS(allIndexes,:)~=0,2)>0; -0465 -0466 %Then get the ones that are used but not in unconnected. -0467 %These are metabolites that could potentially be -0468 %transported to connect transMet -0469 connectedUsed=setdiff(allIndexes(I),unconnected); -0470 -0471 %This may be an error but leave it for now. It seems to -0472 %happen if nothing can be connected in one step -0473 if isempty(connectedUsed) -0474 break; -0475 end -0476 -0477 %If transMet is in the default compartment then everything -0478 %is fine, just connect it to a random one -0479 if transMet==dcIndex -0480 newS=addTransport(newS,nRxns,nER,nMets,nEM,nComps,transMet,connectedUsed(randsample(numel(connectedUsed),1))); -0481 else -0482 %If one of the connectedUsed is in the default -0483 %compartment then connect to that one -0484 I=connectedUsed(connectedUsed<(nMets+nEM)); -0485 if any(I) -0486 newS=addTransport(newS,nRxns,nER,nMets,nEM,nComps,transMet,I(randsample(numel(I),1))); -0487 else -0488 %This is if the only way to connect it is by adding -0489 %two transport reactions, going via the default -0490 %compartment -0491 break; -0492 end -0493 end -0494 end -0495 else -0496 wasConnected=true; -0497 break; -0498 end -0499 end -0500 -0501 %If the network was connected in a new way, it is possible that some -0502 %transport reactions are no longer needed. They should be removed -0503 if wasConnected==true -0504 %These are the metabolites that are being transported -0505 activeTransport=find(sum(newS(:,nER+nRxns*nComps+1:end),2)); -0506 -0507 %Get the metabolites that are unconnected if transport was not used -0508 unconnected=findUnconnected(newS(:,1:nER+nRxns*nComps),nEM); -0509 -0510 %Find the transport reactions that are not needed and delete them -0511 I=setdiff(activeTransport,unconnected); -0512 -0513 %Since both metabolites in a transport rxns must be connected for -0514 %the reaction to be deleted, the sum over the colums should be 4 -0515 newS(:,find(sum(newS(I,nER+nRxns*nComps+1:end))==4)+nER+nRxns*nComps)=0; -0516 -0517 %Score the solution and determine whether to keep it as a new -0518 %solution -0519 [score, geneScore, trCost]=scoreModel(newS,newg2c,GSS,transportCost); -0520 -0521 %If it was the best solution so far, keep it -0522 if score>bestScore -0523 bestScore=score; -0524 bestS=newS; -0525 bestg2c=newg2c; -0526 end -0527 -0528 %This should not be steepest descent later -0529 if score>=bestScore% || exp((score-bestScore)*7)>rand() -0530 plotScore=[plotScore;geneScore]; -0531 nTrans=[nTrans;trCost]; -0532 totScore=[totScore;score]; -0533 S=newS; -0534 g2c=newg2c; -0535 -0536 if plotResults==true -0537 subplot(3,2,1); -0538 spy(S); -0539 subplot(3,2,2); -0540 plot(plotScore,'r'); -0541 xlabel('Gene score'); -0542 subplot(3,2,3); -0543 plot((plotScore-minScore)/(maxScore-minScore),'r'); -0544 xlabel('Gene score relative to predictions'); -0545 subplot(3,2,4); -0546 plot(nTrans,'g'); -0547 xlabel('Transport cost'); -0548 subplot(3,2,5); -0549 plot(totScore,'b'); -0550 xlabel('Total score'); -0551 subplot(3,2,6); -0552 pause(0.2); -0553 end -0554 end -0555 end -0556 end -0557 scores.totScore=score; -0558 scores.geneScore=geneScore; -0559 scores.transCost=trCost; -0560 -0561 %Find which metabolites are transported and to where -0562 [I, J]=find(bestS(nEM+1:nEM+nMets,end-nMets*(nComps-1)+1:end)); -0563 J=ceil(J/nMets+1); -0564 transportStruct.mets=model.metNames(I+nEM); -0565 transportStruct.toComp=GSS.compartments(J); -0566 -0567 [I, J]=find(bestg2c); -0568 geneLocalization.genes=GSS.genes(I); -0569 geneLocalization.comps=GSS.compartments(J); -0570 -0571 %Resort the gene names -0572 [~, I]=sort(geneLocalization.genes); -0573 geneLocalization.genes=geneLocalization.genes(I); -0574 geneLocalization.comps=geneLocalization.comps(I); -0575 -0576 %Remove the fake genes -0577 I=strncmp('&&FAKE&&',geneLocalization.genes,8); -0578 geneLocalization.genes(I)=[]; -0579 geneLocalization.comps(I)=[]; -0580 -0581 %Put together the model. This is done by first duplicating the S matrix -0582 %into the different compartments. Then the transport reactions are added -0583 %based on transportStruct. By now model.S should have the same size as the -0584 %S matrix used in the optimization, but with conserved stoichiometry. In -0585 %the final step all reactions and metabolites that are not used in the S -0586 %matrix from the optimization are deleted from the model -0587 outModel=model; -0588 outModel.S=oldS; -0589 -0590 %This is the S matrix without exchange rxns or metabolites -0591 copyPart=outModel.S(nEM+1:end,nER+1:end); -0592 -0593 %Replicate to give the rxnGeneMat for the full system -0594 copyRxnGeneMat=outModel.rxnGeneMat(nER+1:end,:); -0595 outModel.rxnGeneMat=[outModel.rxnGeneMat;repmat(copyRxnGeneMat,nComps-1,1)]; -0596 -0597 %First fix the compartments. The model is already ordered with the exchange -0598 %metabolites first. The original model may contain one or two compartments, -0599 %depending on whether any exchange metabolites are defined -0600 nStartComps=numel(outModel.comps); -0601 if nStartComps==1 -0602 outModel.comps={'1'}; -0603 outModel.compNames=GSS.compartments(1); -0604 else -0605 if model.metComps(1)==1 -0606 outModel.compNames(1)=GSS.compartments(1); -0607 else -0608 outModel.compNames(2)=GSS.compartments(1); -0609 end -0610 end -0611 outModel.compNames=[outModel.compNames;GSS.compartments(2:end)]; -0612 -0613 %Ugly little loop -0614 for i=1:numel(GSS.compartments)-1 -0615 outModel.comps=[outModel.comps;num2str(numel(outModel.comps)+1)]; -0616 end -0617 %This information is not known from the data, so empty fields are added -0618 outModel.compOutside=cell(numel(outModel.comps),1); -0619 outModel.compOutside(:)={''}; -0620 -0621 for i=1:nComps-1 -0622 outModel.S=[outModel.S sparse(size(outModel.S,1),nRxns)]; -0623 outModel.S=[outModel.S;[sparse(nMets,nRxns*i+nER) copyPart]]; -0624 outModel.rxns=[outModel.rxns;strcat(outModel.rxns(nER+1:nER+nRxns),'_',GSS.compartments{i+1})]; -0625 outModel.rxnNames=[outModel.rxnNames;strcat(outModel.rxnNames(nER+1:nER+nRxns),' (',GSS.compartments{i+1},')')]; -0626 outModel.lb=[outModel.lb;outModel.lb(nER+1:nER+nRxns)]; -0627 outModel.ub=[outModel.ub;outModel.ub(nER+1:nER+nRxns)]; -0628 outModel.rev=[outModel.rev;outModel.rev(nER+1:nER+nRxns)]; -0629 outModel.c=[outModel.c;outModel.c(nER+1:nER+nRxns)]; -0630 if isfield(outModel,'grRules') -0631 outModel.grRules=[outModel.grRules;outModel.grRules(nER+1:nER+nRxns)]; -0632 end -0633 if isfield(outModel,'subSystems') -0634 outModel.subSystems=[outModel.subSystems;outModel.subSystems(nER+1:nER+nRxns)]; -0635 end -0636 if isfield(outModel,'eccodes') -0637 outModel.eccodes=[outModel.eccodes;outModel.eccodes(nER+1:nER+nRxns)]; -0638 end -0639 if isfield(outModel,'rxnFrom') -0640 outModel.rxnFrom=[outModel.rxnFrom;outModel.rxnFrom(nER+1:nER+nRxns)]; -0641 end -0642 if isfield(outModel,'rxnMiriams') -0643 outModel.rxnMiriams=[outModel.rxnMiriams;outModel.rxnMiriams(nER+1:nER+nRxns)]; -0644 end -0645 if isfield(outModel,'rxnNotes') -0646 outModel.rxnNotes=[outModel.rxnNotes;outModel.rxnNotes(nER+1:nER+nRxns)]; -0647 end -0648 if isfield(outModel,'rxnReferences') -0649 outModel.rxnReferences=[outModel.rxnReferences;outModel.rxnReferences(nER+1:nER+nRxns)]; -0650 end -0651 if isfield(outModel,'rxnConfidenceScores') -0652 outModel.rxnConfidenceScores=[outModel.rxnConfidenceScores;outModel.rxnConfidenceScores(nER+1:nER+nRxns)]; -0653 end -0654 outModel.mets=[outModel.mets;strcat(outModel.mets(nEM+1:nEM+nMets),'_',GSS.compartments{i+1})]; -0655 outModel.metNames=[outModel.metNames;outModel.metNames(nEM+1:nEM+nMets)]; -0656 outModel.b=[outModel.b;outModel.b(nEM+1:nEM+nMets,:)]; -0657 I=ones(nMets,1)*nStartComps+i; -0658 outModel.metComps=[outModel.metComps;I]; -0659 if isfield(outModel,'inchis') -0660 outModel.inchis=[outModel.inchis;outModel.inchis(nEM+1:nEM+nMets)]; -0661 end -0662 if isfield(outModel,'unconstrained') -0663 outModel.unconstrained=[outModel.unconstrained;outModel.unconstrained(nEM+1:nEM+nMets)]; -0664 end -0665 if isfield(outModel,'metMiriams') -0666 outModel.metMiriams=[outModel.metMiriams;outModel.metMiriams(nEM+1:nEM+nMets)]; -0667 end -0668 if isfield(outModel,'metFormulas') -0669 outModel.metFormulas=[outModel.metFormulas;outModel.metFormulas(nEM+1:nEM+nMets)]; -0670 end -0671 if isfield(outModel,'metFrom') -0672 outModel.metFrom=[outModel.metFrom;outModel.metFrom(nEM+1:nEM+nMets)]; -0673 end -0674 if isfield(outModel,'metCharges') -0675 outModel.metCharges=[outModel.metCharges;outModel.metCharges(nEM+1:nEM+nMets)]; -0676 end -0677 end -0678 -0679 %Add the transport reactions -0680 transS=bestS(:,numel(outModel.rxns)+1:end); -0681 J=sum(transS)>0; %Active rxns -0682 -0683 %Transport reactions are written in a different way compared to a "real" -0684 %stoichimetric matrix. This is to fix that -0685 transS(transS~=0)=1; -0686 transS(1:nEM+nMets,:)=transS(1:nEM+nMets,:)*-1; -0687 I=find(sum(transS>0,2)); -0688 nTransRxns=numel(I); -0689 outModel.S=[outModel.S transS(:,J)]; -0690 filler=ones(nTransRxns,1); -0691 outModel.lb=[outModel.lb;filler*-1000]; -0692 outModel.ub=[outModel.ub;filler*1000]; -0693 outModel.rev=[outModel.rev;filler]; -0694 outModel.c=[outModel.c;filler*0]; -0695 outModel.rxnGeneMat=[outModel.rxnGeneMat;sparse(nTransRxns,numel(outModel.genes))]; -0696 -0697 for i=1:numel(I) -0698 outModel.rxns=[outModel.rxns;strcat('transport',num2str(i))]; -0699 outModel.rxnNames=[outModel.rxnNames;['Transport of ',outModel.metNames{I(i)}]]; -0700 if isfield(outModel,'grRules') -0701 outModel.grRules=[outModel.grRules;{''}]; -0702 end -0703 if isfield(outModel,'rxnMiriams') -0704 outModel.rxnMiriams=[outModel.rxnMiriams;{[]}]; -0705 end -0706 if isfield(outModel,'subSystems') -0707 outModel.subSystems=[outModel.subSystems;{{'Inferred transport reactions'}}]; -0708 end -0709 if isfield(outModel,'eccodes') -0710 outModel.eccodes=[outModel.eccodes;{''}]; -0711 end -0712 if isfield(outModel,'rxnFrom') -0713 outModel.rxnFrom=[outModel.rxnFrom;{''}]; -0714 end -0715 if isfield(outModel,'rxnNotes') -0716 outModel.rxnNotes=[outModel.rxnNotes;{''}]; -0717 end -0718 if isfield(outModel,'rxnReferences') -0719 outModel.rxnReferences=[outModel.rxnReferences;{''}]; -0720 end -0721 if isfield(outModel,'rxnConfidenceScores') -0722 outModel.rxnConfidenceScores=[outModel.rxnConfidenceScores;NaN]; -0723 end -0724 end -0725 -0726 %Then remove all reactions and metabolites that aren't used in the final -0727 %solution from the optimization -0728 [~, J]=find(bestS(:,1:nER+nComps*nRxns)); -0729 K=true(numel(outModel.rxns),1); -0730 K(J)=false; -0731 K(end-nTransRxns+1:end)=false; -0732 outModel=removeReactions(outModel,K,true); -0733 -0734 %Remove all fake genes -0735 I=strncmp('&&FAKE&&',outModel.genes,8); -0736 outModel.genes(I)=[]; -0737 if isfield(outModel,'geneMiriams') -0738 outModel.geneMiriams(I)=[]; -0739 end -0740 if isfield(outModel,'geneShortNames') -0741 outModel.geneShortNames(I)=[]; -0742 end -0743 outModel.rxnGeneMat(:,I)=[]; -0744 -0745 %Fix grRules and reconstruct rxnGeneMat -0746 [grRules,rxnGeneMat] = standardizeGrRules(outModel,true); -0747 outModel.grRules = grRules; -0748 outModel.rxnGeneMat = rxnGeneMat; -0749 end -0750 -0751 %Moves a gene and all associated reactions from one compartment to another -0752 function [S, g2c]=moveGene(S,model,g2c,geneToMove,toComp,nRxns,nMets) -0753 %Find the current compartment and update to the new one -0754 currentComp=find(g2c(geneToMove,:)); -0755 g2c(geneToMove,:)=false; -0756 g2c(geneToMove,toComp)=true; -0757 -0758 %Find the reactions in the original model that the gene controls -0759 [I, ~]=find(model.rxnGeneMat(:,geneToMove)); -0760 -0761 %Calculate their current positions in the S matrix -0762 oldRxns=I+(currentComp-1)*nRxns; -0763 -0764 %And their new positions -0765 newRxns=I+(toComp-1)*nRxns; -0766 -0767 %The metabolite ids also have to be changed in order to match the new -0768 %compartment -0769 metChange=nMets*(toComp-currentComp); -0770 -0771 %Update the reactions -0772 [I, J, K]=find(S(:,oldRxns)); -0773 I=I+metChange; -0774 -0775 %Move the reactions -0776 S(:,oldRxns)=0; -0777 S(sub2ind(size(S),I,newRxns(J)))=K; -0778 end -0779 -0780 %Finds which metabolites are unconnected, in the sense that they are never -0781 %a product or only a product in a reversible reaction where one reactant is -0782 %only a product in the opposite direction of that reaction. This function -0783 %ignores exchange metabolites. Returns a vector of metabolite indexes. -0784 %metsToCheck is an array of metabolite indexes to check for connectivity. -0785 %If not supplied then all metabolites are checked -0786 function unconnected=findUnconnected(S,nEM,metsToCheck) -0787 if nargin>2 -0788 %Do this by deleting everything from the network that is not in -0789 %metsToCheck and that is not exchange metabolites -0790 I=false(size(S,1),1); -0791 I(1:nEM)=true; -0792 I(metsToCheck)=true; -0793 S=S(I,:); -0794 end -0795 -0796 em=false(size(S,1),1); -0797 em(1:nEM)=true; -0798 -0799 %Construct a matrix in which the reversible reactions are inverted -0800 I=sum(S>2,1) | sum(S>2,1); -0801 revS=S; -0802 revS(:,I)=revS(:,I)*-1; -0803 -0804 %First calculate the ones that are ok -0805 %Produced in 2 rxns, is exchange, is not used at all, is produced in -0806 %non-reversible, involved in more than 1 reversible reactions -0807 connected=sum(S>0,2)>1 | em | sum(S~=0,2)==0 | sum(S(:,~I)>0,2)>0 | sum(S(:,I)~=0,2)>1; -0808 -0809 %Then get the ones that are unconnected because they are never produced -0810 unconnected=sum(S>0 | revS>0,2)==0 & connected==false; -0811 -0812 %Then get the ones that are potentially unconnected -0813 maybeUnconnected=~connected & ~unconnected; -0814 %maybeUnconnected=find(maybeUnconnectedS); -0815 -0816 %The metabolites in maybeUnconnected are involved in one reversible -0817 %reaction and not produced in any other reaction. This means that the -0818 %reactions which have at least one met in maybeUnconnected as reactant and -0819 %one as product are unconnected. The metabolites in maybeUnconnected that -0820 %are present in those reactions are then dead ends -0821 deadRxns=any(S(maybeUnconnected,:)>0) & any(S(maybeUnconnected,:)<0); -0822 -0823 %Get the mets involved in any of those reactions -0824 problematic=any(S(:,deadRxns)~=0,2); -0825 -0826 %If any of these are in the maybeUnconnected list then the metabolite is -0827 %unconnected -0828 unconnected(problematic & maybeUnconnected)=true; -0829 -0830 %Map back to metsToCheck -0831 if nargin>2 -0832 unconnected=metsToCheck(unconnected(nEM+1:end)); -0833 else -0834 unconnected=find(unconnected); -0835 end +0095 defaultCompartment=char(defaultCompartment); +0096 I=ismember(defaultCompartment,GSS.compartments); +0097 if I==false +0098 EM='defaultCompartment not found in GSS'; +0099 dispEM(EM); +0100 end +0101 +0102 if numel(model.comps)>1 +0103 EM='The model has several compartments. All compartments will be merged'; +0104 dispEM(EM,false); +0105 model=mergeCompartments(model,true,true); +0106 end +0107 +0108 %***Begin formating the data structures +0109 +0110 %Expand the model so that iso-enzymes have different reactions +0111 model=expandModel(model); +0112 +0113 %Identify reactions that have to be deleted because the involved mets are +0114 %never produced. This is done in an iterative manner +0115 removedRxns={}; +0116 %This is to keep track of which metabolites are removed in this step. It is +0117 %needed to adjust the transport costs +0118 originalModelMets=model.mets; +0119 while 1 +0120 irrevModel=convertToIrrev(model); +0121 +0122 I=sum(irrevModel.S>0,2); +0123 +0124 %Pretend that the unconstrained metabolites are made enough +0125 if isfield(irrevModel,'unconstrained') +0126 I(irrevModel.unconstrained~=0)=2; +0127 end +0128 metsToDelete=false(numel(model.mets),1); +0129 +0130 %This is not very neat but iterate through each metabolite and check +0131 %whether it can be produced (without using only one isolated reversible +0132 %reaction) +0133 for i=1:numel(irrevModel.mets) +0134 %If something can be made in two reactions then everything is fine. +0135 %If it can be made in one reaction it is fine unless it is through +0136 %an isolated reversible reaction (which can act as a mini loop) +0137 if I(i)<2 +0138 if I(i)==1 +0139 %Find the reaction where this metabolite is produced +0140 [~, J]=find(irrevModel.S(i,:)>0); +0141 +0142 %Check the metabolites that are consumed in this reaction. +0143 %The problem is if any of them is only produced in the +0144 %opposite reversible reaction +0145 K=irrevModel.S(:,J)<0; +0146 check=find(K & I<=1); +0147 +0148 for j=1:numel(check) +0149 %Find the reactions where it participates +0150 [~, L]=find(irrevModel.S(check(j),:)>0); +0151 +0152 if ~isempty(L) +0153 rxn=irrevModel.rxns(J); +0154 rxnRev=irrevModel.rxns(L); +0155 if strcmp(strrep(rxn,'_REV',''),strrep(rxnRev,'_REV','')) +0156 metsToDelete(i)=true; +0157 end +0158 else +0159 %If the metabolite was never produced then do +0160 %nothing and deal with it when the loop gets there +0161 continue; +0162 end +0163 end +0164 else +0165 %Not made anywhere +0166 metsToDelete(i)=true; +0167 end +0168 end +0169 end +0170 +0171 if any(metsToDelete) +0172 %Delete any reactions involving any of the metsToDelete +0173 [~, I]=find(model.S(metsToDelete,:)); +0174 removedRxns=[removedRxns;model.rxns(I)]; +0175 model=removeReactions(model,I,true,true); +0176 else +0177 %All bad reactions deleted +0178 break; +0179 end +0180 end +0181 +0182 %Adjust the transport costs +0183 transportCost=transportCost(ismember(originalModelMets,model.mets)); +0184 +0185 %Assign fake genes to reactions without genes. This is just to make things +0186 %easier later on +0187 I=find(sum(model.rxnGeneMat,2)==0); +0188 for i=1:numel(I) +0189 model.genes=[model.genes;['&&FAKE&&' num2str(i)]]; +0190 if isfield(model,'geneShortNames') +0191 model.geneShortNames=[model.geneShortNames;{''}]; +0192 end +0193 if isfield(model,'geneMiriams') +0194 model.geneMiriams=[model.geneMiriams;{[]}]; +0195 end +0196 if isfield(model,'geneFrom') +0197 model.geneFrom=[model.geneFrom;{{'FAKE'}}]; +0198 end +0199 model.rxnGeneMat(I(i),numel(model.genes))=1; +0200 model.grRules{I(i)}=''; +0201 end +0202 +0203 %Update the GSS. All genes, fake or real, for which there is no evidence +0204 %gets a score 0.5 in all compartments. Also just to make it easier further +0205 %on +0206 I=setdiff(model.genes,GSS.genes); +0207 GSS.genes=[GSS.genes;I]; +0208 GSS.scores=[GSS.scores;ones(numel(I),numel(GSS.compartments))*0.5]; +0209 +0210 %Gene complexes should be moved together in order to be biologically +0211 %relevant. The average score for the genes is used for each compartment. +0212 %This is done by changing the model so that gene complexes are used as a +0213 %single gene name and then a score is calculated for that "gene". +0214 +0215 %Only "and"-relationships exist after expandModel +0216 genes=unique(model.grRules); +0217 nGenes=strrep(genes,'(',''); +0218 nGenes=strrep(nGenes,')',''); +0219 %nGenes=strrep(nGenes,' and ','_and_'); +0220 complexes=setdiff(nGenes,model.genes); +0221 if ~isempty(complexes) +0222 if isempty(complexes{1}) %Empty grRules also come up here +0223 complexes(1)=[]; +0224 end +0225 end +0226 cScores=zeros(numel(complexes),numel(GSS.compartments)); +0227 for i=1:numel(complexes) +0228 genesInComplex=regexp(complexes{i},' and ','split'); +0229 +0230 %Find these genes in GSS +0231 [I, J]=ismember(genesInComplex,GSS.genes); +0232 +0233 if any(I) +0234 %Get the average of the genes that were found +0235 mScores=mean(GSS.scores(J(I),:)); +0236 +0237 %And add 0.5 for the genes that were not found in order to be +0238 %consistent with non-complexes +0239 mScores=(mScores.*sum(I)+(numel(genesInComplex)-sum(I))*0.5)/numel(genesInComplex); +0240 else +0241 EM=['Could not parse grRule "' complexes{i} '". Assigning score 0.0 in all compartments']; +0242 dispEM(EM,false); +0243 mScores=ones(1,numel(genesInComplex))*0.5; +0244 end +0245 cScores(i,:)=mScores; +0246 +0247 %Add this complex as a new gene +0248 model.genes=[model.genes;complexes{i}]; +0249 if isfield(model,'geneMiriams') +0250 model.geneMiriams=[model.geneMiriams;{[]}]; +0251 end +0252 if isfield(model,'geneShortNames') +0253 model.geneShortNames=[model.geneShortNames;{''}]; +0254 end +0255 if isfield(model,'geneFrom') +0256 model.geneFrom=[model.geneFrom;{'COMPLEX'}]; +0257 end +0258 %Find the reactions which had the original complex and change them to +0259 %use the new "gene" +0260 I=ismember(model.grRules,['(' complexes{i} ')']); +0261 +0262 %Should check more carefully if there can be an error here +0263 if ~isempty(I) +0264 model.rxnGeneMat(I,:)=0; %Ok since the split on "or" was applied +0265 model.rxnGeneMat(I,numel(model.genes))=1; +0266 end +0267 end +0268 +0269 %Add the new "genes" +0270 GSS.genes=[GSS.genes;complexes]; +0271 GSS.scores=[GSS.scores;cScores]; +0272 +0273 %After merging the complexes it could happen that there are genes that are +0274 %no longer in use. Delete such genes +0275 model=removeReactions(model,{},false,true); +0276 +0277 %Exchange reactions, defined as involving an unconstrained metabolite, are +0278 %special in that they have to stay in the defaultCompartment. This means +0279 %that uptake/excretion of metabolites is always via the default +0280 %compartment. This is a small simplification, but should be valid in most +0281 %cases +0282 [~, I]=getExchangeRxns(model); +0283 +0284 %It will be easier later on if the same place. Put them in the beginning +0285 J=1:numel(model.rxns); +0286 J(I)=[]; +0287 model=permuteModel(model,[I;J'],'rxns'); +0288 +0289 %Number of exchange reactions +0290 nER=numel(I); +0291 +0292 %Also put the exchange metabolites in the beginning +0293 if isfield(model,'unconstrained') +0294 I=find(model.unconstrained); +0295 J=1:numel(model.mets); +0296 J(I)=[]; +0297 model=permuteModel(model,[I;J'],'mets'); +0298 %Also reorder the transport costs +0299 transportCost=transportCost([I;J']); +0300 %Number of exchange metabolites +0301 nEM=numel(I); +0302 else +0303 nEM=0; +0304 end +0305 +0306 %There is no point of having genes for exchange reactions, so delete them. +0307 %Also to make computations easier +0308 model.rxnGeneMat(1:nER,:)=0; +0309 model.grRules(1:nER)={''}; +0310 +0311 %Remove unused genes +0312 model=removeReactions(model,{},false,true); +0313 +0314 %Remove genes with no match to the model and reorder so that the genes are +0315 %in the same order as model.genes. Since the fake genes are already added +0316 %so that all genes in model exist in GSS it is fine to do like this +0317 [~, J]=ismember(model.genes,GSS.genes); +0318 GSS.genes=model.genes; +0319 GSS.scores=GSS.scores(J,:); +0320 +0321 %Reorder the GSS so that the first index corresponds to the default +0322 %compartment +0323 [~, J]=ismember(defaultCompartment,GSS.compartments); +0324 reorder=1:numel(GSS.compartments); +0325 reorder(J)=[]; +0326 reorder=[J reorder]; +0327 GSS.scores=GSS.scores(:,reorder); +0328 GSS.compartments=GSS.compartments(reorder); +0329 +0330 %Since it is only checked whether the metabolites can be synthesized, there +0331 %is no need to care about the stoichiometry. Change to -1/1 to simplify +0332 %later. Keep the S matrix for later though +0333 oldS=model.S; +0334 model.S(model.S>0)=1; +0335 model.S(model.S<0)=-1; +0336 +0337 %Here is a bit of a trick. To avoid the recurring calculation which +0338 %reactions are reversible, the reversible reactions have the coefficients +0339 %-10/10 instead of -1/1 +0340 model.S(:,model.rev==1)=model.S(:,model.rev==1).*10; +0341 +0342 %***Begin problem formulation +0343 +0344 %Some numbers that are good to have +0345 nRxns=numel(model.rxns)-nER; %Excluding exchange rxns +0346 nMets=numel(model.mets)-nEM; %Excluding exchange mets +0347 nGenes=numel(model.genes); +0348 nComps=numel(GSS.compartments); +0349 +0350 %Create a big stoichiometric matrix that will be the current model. In +0351 %order to have faster simulations the maximal model size is declared and +0352 %reactions are then moved within it. +0353 +0354 %First the original model (with the first nE being exchange rxns), then +0355 %reserve space for number of rxns minus exchange rxns for each non-default +0356 %compartment, then transport reactions for all non-exchange mets between +0357 %the default compartment and all others. +0358 %NOTE: Kept eye()*0 since eye() can be used to include all transport from +0359 %the beginning +0360 s=repmat(eye(nMets)*0,1,nComps-1); +0361 s=[zeros(numel(model.mets)-nMets,size(s,2));s]; +0362 S=[model.S sparse(numel(model.mets),nRxns*(nComps-1)) s]; +0363 s=[sparse(nMets*(nComps-1),numel(model.rxns)+nRxns*(nComps-1)) eye(nMets*(nComps-1))*0]; +0364 S=[S;s]; +0365 +0366 %Also replicate the transport costs +0367 transportCost=[transportCost(1:nEM);repmat(transportCost(nEM+1:end),nComps,1)]; +0368 +0369 %Create a binary matrix that says where the genes are in the current +0370 %solution +0371 g2c=false(nGenes,nComps); +0372 %All genes start in the default compartment +0373 g2c(:,1)=true; +0374 +0375 %Start of main optimization loop +0376 tic; +0377 bestScore=-inf; +0378 bestS=[]; +0379 bestg2c=[]; +0380 +0381 %Temp for testing +0382 plotScore=[]; +0383 nTrans=[]; +0384 totScore=[]; +0385 minScore=sum(min(GSS.scores,[],2)); +0386 maxScore=sum(max(GSS.scores,[],2)); +0387 +0388 while toc<maxTime*60 +0389 %Pick a random gene, weighted by it is current score minus the best +0390 %score for that gene (often 1.0, but can be 0.5 for no genes or average +0391 %for complexes). Genes with bad fits are more likely to be moved. This +0392 %formulation never moves a gene from its best compartment. Therefore a +0393 %small uniform weight is added +0394 [I, J]=find(g2c); +0395 geneToMove=randsample(nGenes,1,true,max(GSS.scores(I,:),[],2)-GSS.scores(sub2ind(size(g2c),I,J))+0.1); +0396 +0397 %Sample among possible compartments to move to. Add a larger weight to +0398 %even out the odds a little. Also a way of getting rid of loops where +0399 %the same set of genes are moved back and forth several times +0400 toComp=randsample(nComps,1,true,GSS.scores(geneToMove,:)+0.2); +0401 +0402 %Check that it moves to a new compartment +0403 if toComp==find(g2c(geneToMove,:)) +0404 continue; +0405 end +0406 +0407 %Moves the gene +0408 [newS, newg2c]=moveGene(S,model,g2c,geneToMove,toComp,nRxns,nMets); +0409 +0410 %Tries to connect the network. If this was not possible in 10 +0411 %iterations, then abort. If more than 20 modifications were needed then +0412 %it is unlikely that it will be a lower score +0413 wasConnected=false; +0414 for j=1:10 +0415 %Find the metabolites that are now unconnected +0416 unconnected=findUnconnected(newS,nEM); +0417 +0418 %Continue if there are still unconnected +0419 if any(unconnected) +0420 %For each gene find out how many of these could be connected if +0421 %the gene was moved and how many would be disconnected by +0422 %moving that gene +0423 [geneIndex, moveTo, deltaConnected, deltaScore]=selectGenes(newS,nEM,nMets,nER,nRxns,model,unconnected,g2c,GSS); +0424 +0425 %Score which gene would be the best to move. The highest +0426 %deltaScore is 1.0. It should be possible to move a gene from +0427 %worst to best compartment even if it disconnects, say, 1.5 +0428 %more metabolites +0429 [score, I]=max(1.5*deltaScore+deltaConnected); +0430 +0431 %Check if it has to add a transport or if there is a gene that +0432 %could be moved order to have a more connected network +0433 hasToAddTransport=true; +0434 if ~isempty(deltaConnected) +0435 if score>0 +0436 hasToAddTransport=false; +0437 end +0438 end +0439 +0440 %If it is possible to move any gene in order to have a more +0441 %connected network, then move the best one +0442 if hasToAddTransport==false +0443 [newS, newg2c]=moveGene(newS,model,g2c,geneIndex(I),moveTo(I),nRxns,nMets); +0444 else +0445 %Choose a random unconnected metabolite that should be +0446 %connected +0447 transMet=unconnected(randsample(numel(unconnected),1)); +0448 +0449 %First get where the metabolite is now +0450 comps=ceil((transMet-nEM)/((size(S,1)-nEM)/nComps)); +0451 +0452 %Find the corresponding metabolite index if it were in the +0453 %default compartment +0454 dcIndex=transMet-(comps-1)*nMets; +0455 +0456 %Then get the indexes of that metabolite in all +0457 %compartments +0458 allIndexes=dcIndex; +0459 for k=1:nComps-1 +0460 allIndexes=[allIndexes;dcIndex+nMets*k]; +0461 end +0462 +0463 %It could be that some of these are not used in any +0464 %reaction. Get only the ones which are +0465 I=sum(newS(allIndexes,:)~=0,2)>0; +0466 +0467 %Then get the ones that are used but not in unconnected. +0468 %These are metabolites that could potentially be +0469 %transported to connect transMet +0470 connectedUsed=setdiff(allIndexes(I),unconnected); +0471 +0472 %This may be an error but leave it for now. It seems to +0473 %happen if nothing can be connected in one step +0474 if isempty(connectedUsed) +0475 break; +0476 end +0477 +0478 %If transMet is in the default compartment then everything +0479 %is fine, just connect it to a random one +0480 if transMet==dcIndex +0481 newS=addTransport(newS,nRxns,nER,nMets,nEM,nComps,transMet,connectedUsed(randsample(numel(connectedUsed),1))); +0482 else +0483 %If one of the connectedUsed is in the default +0484 %compartment then connect to that one +0485 I=connectedUsed(connectedUsed<(nMets+nEM)); +0486 if any(I) +0487 newS=addTransport(newS,nRxns,nER,nMets,nEM,nComps,transMet,I(randsample(numel(I),1))); +0488 else +0489 %This is if the only way to connect it is by adding +0490 %two transport reactions, going via the default +0491 %compartment +0492 break; +0493 end +0494 end +0495 end +0496 else +0497 wasConnected=true; +0498 break; +0499 end +0500 end +0501 +0502 %If the network was connected in a new way, it is possible that some +0503 %transport reactions are no longer needed. They should be removed +0504 if wasConnected==true +0505 %These are the metabolites that are being transported +0506 activeTransport=find(sum(newS(:,nER+nRxns*nComps+1:end),2)); +0507 +0508 %Get the metabolites that are unconnected if transport was not used +0509 unconnected=findUnconnected(newS(:,1:nER+nRxns*nComps),nEM); +0510 +0511 %Find the transport reactions that are not needed and delete them +0512 I=setdiff(activeTransport,unconnected); +0513 +0514 %Since both metabolites in a transport rxns must be connected for +0515 %the reaction to be deleted, the sum over the colums should be 4 +0516 newS(:,find(sum(newS(I,nER+nRxns*nComps+1:end))==4)+nER+nRxns*nComps)=0; +0517 +0518 %Score the solution and determine whether to keep it as a new +0519 %solution +0520 [score, geneScore, trCost]=scoreModel(newS,newg2c,GSS,transportCost); +0521 +0522 %If it was the best solution so far, keep it +0523 if score>bestScore +0524 bestScore=score; +0525 bestS=newS; +0526 bestg2c=newg2c; +0527 end +0528 +0529 %This should not be steepest descent later +0530 if score>=bestScore% || exp((score-bestScore)*7)>rand() +0531 plotScore=[plotScore;geneScore]; +0532 nTrans=[nTrans;trCost]; +0533 totScore=[totScore;score]; +0534 S=newS; +0535 g2c=newg2c; +0536 +0537 if plotResults==true +0538 subplot(3,2,1); +0539 spy(S); +0540 subplot(3,2,2); +0541 plot(plotScore,'r'); +0542 xlabel('Gene score'); +0543 subplot(3,2,3); +0544 plot((plotScore-minScore)/(maxScore-minScore),'r'); +0545 xlabel('Gene score relative to predictions'); +0546 subplot(3,2,4); +0547 plot(nTrans,'g'); +0548 xlabel('Transport cost'); +0549 subplot(3,2,5); +0550 plot(totScore,'b'); +0551 xlabel('Total score'); +0552 subplot(3,2,6); +0553 pause(0.2); +0554 end +0555 end +0556 end +0557 end +0558 scores.totScore=score; +0559 scores.geneScore=geneScore; +0560 scores.transCost=trCost; +0561 +0562 %Find which metabolites are transported and to where +0563 [I, J]=find(bestS(nEM+1:nEM+nMets,end-nMets*(nComps-1)+1:end)); +0564 J=ceil(J/nMets+1); +0565 transportStruct.mets=model.metNames(I+nEM); +0566 transportStruct.toComp=GSS.compartments(J); +0567 +0568 [I, J]=find(bestg2c); +0569 geneLocalization.genes=GSS.genes(I); +0570 geneLocalization.comps=GSS.compartments(J); +0571 +0572 %Resort the gene names +0573 [~, I]=sort(geneLocalization.genes); +0574 geneLocalization.genes=geneLocalization.genes(I); +0575 geneLocalization.comps=geneLocalization.comps(I); +0576 +0577 %Remove the fake genes +0578 I=strncmp('&&FAKE&&',geneLocalization.genes,8); +0579 geneLocalization.genes(I)=[]; +0580 geneLocalization.comps(I)=[]; +0581 +0582 %Put together the model. This is done by first duplicating the S matrix +0583 %into the different compartments. Then the transport reactions are added +0584 %based on transportStruct. By now model.S should have the same size as the +0585 %S matrix used in the optimization, but with conserved stoichiometry. In +0586 %the final step all reactions and metabolites that are not used in the S +0587 %matrix from the optimization are deleted from the model +0588 outModel=model; +0589 outModel.S=oldS; +0590 +0591 %This is the S matrix without exchange rxns or metabolites +0592 copyPart=outModel.S(nEM+1:end,nER+1:end); +0593 +0594 %Replicate to give the rxnGeneMat for the full system +0595 copyRxnGeneMat=outModel.rxnGeneMat(nER+1:end,:); +0596 outModel.rxnGeneMat=[outModel.rxnGeneMat;repmat(copyRxnGeneMat,nComps-1,1)]; +0597 +0598 %First fix the compartments. The model is already ordered with the exchange +0599 %metabolites first. The original model may contain one or two compartments, +0600 %depending on whether any exchange metabolites are defined +0601 nStartComps=numel(outModel.comps); +0602 if nStartComps==1 +0603 outModel.comps={'1'}; +0604 outModel.compNames=GSS.compartments(1); +0605 else +0606 if model.metComps(1)==1 +0607 outModel.compNames(1)=GSS.compartments(1); +0608 else +0609 outModel.compNames(2)=GSS.compartments(1); +0610 end +0611 end +0612 outModel.compNames=[outModel.compNames;GSS.compartments(2:end)]; +0613 +0614 %Ugly little loop +0615 for i=1:numel(GSS.compartments)-1 +0616 outModel.comps=[outModel.comps;num2str(numel(outModel.comps)+1)]; +0617 end +0618 %This information is not known from the data, so empty fields are added +0619 outModel.compOutside=cell(numel(outModel.comps),1); +0620 outModel.compOutside(:)={''}; +0621 +0622 for i=1:nComps-1 +0623 outModel.S=[outModel.S sparse(size(outModel.S,1),nRxns)]; +0624 outModel.S=[outModel.S;[sparse(nMets,nRxns*i+nER) copyPart]]; +0625 outModel.rxns=[outModel.rxns;strcat(outModel.rxns(nER+1:nER+nRxns),'_',GSS.compartments{i+1})]; +0626 outModel.rxnNames=[outModel.rxnNames;strcat(outModel.rxnNames(nER+1:nER+nRxns),' (',GSS.compartments{i+1},')')]; +0627 outModel.lb=[outModel.lb;outModel.lb(nER+1:nER+nRxns)]; +0628 outModel.ub=[outModel.ub;outModel.ub(nER+1:nER+nRxns)]; +0629 outModel.rev=[outModel.rev;outModel.rev(nER+1:nER+nRxns)]; +0630 outModel.c=[outModel.c;outModel.c(nER+1:nER+nRxns)]; +0631 if isfield(outModel,'grRules') +0632 outModel.grRules=[outModel.grRules;outModel.grRules(nER+1:nER+nRxns)]; +0633 end +0634 if isfield(outModel,'subSystems') +0635 outModel.subSystems=[outModel.subSystems;outModel.subSystems(nER+1:nER+nRxns)]; +0636 end +0637 if isfield(outModel,'eccodes') +0638 outModel.eccodes=[outModel.eccodes;outModel.eccodes(nER+1:nER+nRxns)]; +0639 end +0640 if isfield(outModel,'rxnFrom') +0641 outModel.rxnFrom=[outModel.rxnFrom;outModel.rxnFrom(nER+1:nER+nRxns)]; +0642 end +0643 if isfield(outModel,'rxnMiriams') +0644 outModel.rxnMiriams=[outModel.rxnMiriams;outModel.rxnMiriams(nER+1:nER+nRxns)]; +0645 end +0646 if isfield(outModel,'rxnNotes') +0647 outModel.rxnNotes=[outModel.rxnNotes;outModel.rxnNotes(nER+1:nER+nRxns)]; +0648 end +0649 if isfield(outModel,'rxnReferences') +0650 outModel.rxnReferences=[outModel.rxnReferences;outModel.rxnReferences(nER+1:nER+nRxns)]; +0651 end +0652 if isfield(outModel,'rxnConfidenceScores') +0653 outModel.rxnConfidenceScores=[outModel.rxnConfidenceScores;outModel.rxnConfidenceScores(nER+1:nER+nRxns)]; +0654 end +0655 outModel.mets=[outModel.mets;strcat(outModel.mets(nEM+1:nEM+nMets),'_',GSS.compartments{i+1})]; +0656 outModel.metNames=[outModel.metNames;outModel.metNames(nEM+1:nEM+nMets)]; +0657 outModel.b=[outModel.b;outModel.b(nEM+1:nEM+nMets,:)]; +0658 I=ones(nMets,1)*nStartComps+i; +0659 outModel.metComps=[outModel.metComps;I]; +0660 if isfield(outModel,'inchis') +0661 outModel.inchis=[outModel.inchis;outModel.inchis(nEM+1:nEM+nMets)]; +0662 end +0663 if isfield(outModel,'unconstrained') +0664 outModel.unconstrained=[outModel.unconstrained;outModel.unconstrained(nEM+1:nEM+nMets)]; +0665 end +0666 if isfield(outModel,'metMiriams') +0667 outModel.metMiriams=[outModel.metMiriams;outModel.metMiriams(nEM+1:nEM+nMets)]; +0668 end +0669 if isfield(outModel,'metFormulas') +0670 outModel.metFormulas=[outModel.metFormulas;outModel.metFormulas(nEM+1:nEM+nMets)]; +0671 end +0672 if isfield(outModel,'metFrom') +0673 outModel.metFrom=[outModel.metFrom;outModel.metFrom(nEM+1:nEM+nMets)]; +0674 end +0675 if isfield(outModel,'metCharges') +0676 outModel.metCharges=[outModel.metCharges;outModel.metCharges(nEM+1:nEM+nMets)]; +0677 end +0678 end +0679 +0680 %Add the transport reactions +0681 transS=bestS(:,numel(outModel.rxns)+1:end); +0682 J=sum(transS)>0; %Active rxns +0683 +0684 %Transport reactions are written in a different way compared to a "real" +0685 %stoichimetric matrix. This is to fix that +0686 transS(transS~=0)=1; +0687 transS(1:nEM+nMets,:)=transS(1:nEM+nMets,:)*-1; +0688 I=find(sum(transS>0,2)); +0689 nTransRxns=numel(I); +0690 outModel.S=[outModel.S transS(:,J)]; +0691 filler=ones(nTransRxns,1); +0692 outModel.lb=[outModel.lb;filler*-1000]; +0693 outModel.ub=[outModel.ub;filler*1000]; +0694 outModel.rev=[outModel.rev;filler]; +0695 outModel.c=[outModel.c;filler*0]; +0696 outModel.rxnGeneMat=[outModel.rxnGeneMat;sparse(nTransRxns,numel(outModel.genes))]; +0697 +0698 for i=1:numel(I) +0699 outModel.rxns=[outModel.rxns;strcat('transport',num2str(i))]; +0700 outModel.rxnNames=[outModel.rxnNames;['Transport of ',outModel.metNames{I(i)}]]; +0701 if isfield(outModel,'grRules') +0702 outModel.grRules=[outModel.grRules;{''}]; +0703 end +0704 if isfield(outModel,'rxnMiriams') +0705 outModel.rxnMiriams=[outModel.rxnMiriams;{[]}]; +0706 end +0707 if isfield(outModel,'subSystems') +0708 outModel.subSystems=[outModel.subSystems;{{'Inferred transport reactions'}}]; +0709 end +0710 if isfield(outModel,'eccodes') +0711 outModel.eccodes=[outModel.eccodes;{''}]; +0712 end +0713 if isfield(outModel,'rxnFrom') +0714 outModel.rxnFrom=[outModel.rxnFrom;{''}]; +0715 end +0716 if isfield(outModel,'rxnNotes') +0717 outModel.rxnNotes=[outModel.rxnNotes;{''}]; +0718 end +0719 if isfield(outModel,'rxnReferences') +0720 outModel.rxnReferences=[outModel.rxnReferences;{''}]; +0721 end +0722 if isfield(outModel,'rxnConfidenceScores') +0723 outModel.rxnConfidenceScores=[outModel.rxnConfidenceScores;NaN]; +0724 end +0725 end +0726 +0727 %Then remove all reactions and metabolites that aren't used in the final +0728 %solution from the optimization +0729 [~, J]=find(bestS(:,1:nER+nComps*nRxns)); +0730 K=true(numel(outModel.rxns),1); +0731 K(J)=false; +0732 K(end-nTransRxns+1:end)=false; +0733 outModel=removeReactions(outModel,K,true); +0734 +0735 %Remove all fake genes +0736 I=strncmp('&&FAKE&&',outModel.genes,8); +0737 outModel.genes(I)=[]; +0738 if isfield(outModel,'geneMiriams') +0739 outModel.geneMiriams(I)=[]; +0740 end +0741 if isfield(outModel,'geneShortNames') +0742 outModel.geneShortNames(I)=[]; +0743 end +0744 outModel.rxnGeneMat(:,I)=[]; +0745 +0746 %Fix grRules and reconstruct rxnGeneMat +0747 [grRules,rxnGeneMat] = standardizeGrRules(outModel,true); +0748 outModel.grRules = grRules; +0749 outModel.rxnGeneMat = rxnGeneMat; +0750 end +0751 +0752 %Moves a gene and all associated reactions from one compartment to another +0753 function [S, g2c]=moveGene(S,model,g2c,geneToMove,toComp,nRxns,nMets) +0754 %Find the current compartment and update to the new one +0755 currentComp=find(g2c(geneToMove,:)); +0756 g2c(geneToMove,:)=false; +0757 g2c(geneToMove,toComp)=true; +0758 +0759 %Find the reactions in the original model that the gene controls +0760 [I, ~]=find(model.rxnGeneMat(:,geneToMove)); +0761 +0762 %Calculate their current positions in the S matrix +0763 oldRxns=I+(currentComp-1)*nRxns; +0764 +0765 %And their new positions +0766 newRxns=I+(toComp-1)*nRxns; +0767 +0768 %The metabolite ids also have to be changed in order to match the new +0769 %compartment +0770 metChange=nMets*(toComp-currentComp); +0771 +0772 %Update the reactions +0773 [I, J, K]=find(S(:,oldRxns)); +0774 I=I+metChange; +0775 +0776 %Move the reactions +0777 S(:,oldRxns)=0; +0778 S(sub2ind(size(S),I,newRxns(J)))=K; +0779 end +0780 +0781 %Finds which metabolites are unconnected, in the sense that they are never +0782 %a product or only a product in a reversible reaction where one reactant is +0783 %only a product in the opposite direction of that reaction. This function +0784 %ignores exchange metabolites. Returns a vector of metabolite indexes. +0785 %metsToCheck is an array of metabolite indexes to check for connectivity. +0786 %If not supplied then all metabolites are checked +0787 function unconnected=findUnconnected(S,nEM,metsToCheck) +0788 if nargin>2 +0789 %Do this by deleting everything from the network that is not in +0790 %metsToCheck and that is not exchange metabolites +0791 I=false(size(S,1),1); +0792 I(1:nEM)=true; +0793 I(metsToCheck)=true; +0794 S=S(I,:); +0795 end +0796 +0797 em=false(size(S,1),1); +0798 em(1:nEM)=true; +0799 +0800 %Construct a matrix in which the reversible reactions are inverted +0801 I=sum(S>2,1) | sum(S>2,1); +0802 revS=S; +0803 revS(:,I)=revS(:,I)*-1; +0804 +0805 %First calculate the ones that are ok +0806 %Produced in 2 rxns, is exchange, is not used at all, is produced in +0807 %non-reversible, involved in more than 1 reversible reactions +0808 connected=sum(S>0,2)>1 | em | sum(S~=0,2)==0 | sum(S(:,~I)>0,2)>0 | sum(S(:,I)~=0,2)>1; +0809 +0810 %Then get the ones that are unconnected because they are never produced +0811 unconnected=sum(S>0 | revS>0,2)==0 & connected==false; +0812 +0813 %Then get the ones that are potentially unconnected +0814 maybeUnconnected=~connected & ~unconnected; +0815 %maybeUnconnected=find(maybeUnconnectedS); +0816 +0817 %The metabolites in maybeUnconnected are involved in one reversible +0818 %reaction and not produced in any other reaction. This means that the +0819 %reactions which have at least one met in maybeUnconnected as reactant and +0820 %one as product are unconnected. The metabolites in maybeUnconnected that +0821 %are present in those reactions are then dead ends +0822 deadRxns=any(S(maybeUnconnected,:)>0) & any(S(maybeUnconnected,:)<0); +0823 +0824 %Get the mets involved in any of those reactions +0825 problematic=any(S(:,deadRxns)~=0,2); +0826 +0827 %If any of these are in the maybeUnconnected list then the metabolite is +0828 %unconnected +0829 unconnected(problematic & maybeUnconnected)=true; +0830 +0831 %Map back to metsToCheck +0832 if nargin>2 +0833 unconnected=metsToCheck(unconnected(nEM+1:end)); +0834 else +0835 unconnected=find(unconnected); 0836 end -0837 -0838 %Given a set of unconnected metabolites, this function tries to move each -0839 %gene that could connect any of them, calculates the number of newly -0840 %connected metabolites minus the number of newly disconnected metabolites. -0841 %As some metabolites are very connected, only 25 genes are checked. Genes -0842 %that have a low score in their current compartment are more likely to be -0843 %moved -0844 function [geneIndex, moveTo, deltaConnected, deltaScore]=selectGenes(S,nEM,nMets,nER,nRxns,model,unconnected,g2c,GSS) -0845 %If moveTo is 0 then the gene cannot connect any of the metabolites -0846 moveTo=zeros(numel(model.genes),1); -0847 deltaConnected=zeros(numel(model.genes),1); -0848 -0849 %First get where the metabolites are now -0850 nComps=size(g2c,2); -0851 comps=ceil((unconnected-nEM)/((size(S,1)-nEM)/nComps)); -0852 -0853 %Find the corresponding metabolite indexes if they all were in the default -0854 %compartment -0855 dcIndexes=unique(unconnected-(comps-1)*nMets); -0856 -0857 %Then find them if they were in any other compartment -0858 allIndexes=dcIndexes; -0859 for i=1:nComps-1 -0860 allIndexes=[allIndexes;dcIndexes+nMets*i]; -0861 end -0862 -0863 %Also check which reversible reactions that could be used -0864 I=sum(S>2,1) | sum(S>2,1); -0865 revS=S; -0866 revS(:,I)=revS(:,I)*-1; -0867 -0868 %Find all reactions that could make any of the unconnected metabolites in -0869 %some other compartment -0870 newMets=setdiff(allIndexes,unconnected); -0871 [~, potential]=find(S(newMets,:)>0 | revS(newMets,:)>0); -0872 potential(potential<=nER | potential>nER+nRxns*nComps)=[]; %No exchange rxns or transport rxns -0873 -0874 %Map J to the real metabolic reactions in model -0875 rxnComps=ceil((potential-nER)/(nRxns)); -0876 -0877 %Find the corresponding reaction indexes if they all were in the default -0878 %compartment -0879 dcRxnIndexes=potential-(rxnComps-1)*nRxns; -0880 -0881 %Get the genes for those reactions -0882 genes=find(sum(model.rxnGeneMat(dcRxnIndexes,:)>0,1)); -0883 -0884 %For some cases there can be very many reactions to connect something. This -0885 %is in particular true in the beginning of the optimization if, say, ATP is -0886 %unconnected. Therefore limit the number of genes to be checked to 25. -0887 %Weigh so that genes with bad scores in their current compartment are more -0888 %likely to be moved. -0889 -0890 %Get scores for these genes -0891 [~, J]=find(g2c(genes,:)); -0892 -0893 %Add a small weight so that genes in their best compartment could be moved -0894 %as well -0895 geneScores=GSS.scores(sub2ind(size(g2c),genes(:),J)); -0896 modGeneScores=1.1-geneScores; -0897 if numel(genes)>25 -0898 rGenes=genes(randsample(numel(genes),min(numel(genes),25),true,modGeneScores)); -0899 -0900 %The sampling with weights could give duplicates -0901 rGenes=unique(rGenes); -0902 -0903 %Reorder the geneScores to match -0904 [~, I]=ismember(rGenes,genes); -0905 geneScores=geneScores(I); -0906 genes=rGenes; -0907 end -0908 for i=1:numel(genes) -0909 %Since one gene is moved at a time, only metabolites involved in any of -0910 %the reactions for that gene can become unconnected. This helps to -0911 %speed up the algorithm. First get all involved reactions in the -0912 %default compartment -0913 rxns=find(model.rxnGeneMat(:,genes(i))); -0914 -0915 %Then get their mets -0916 mets=find(sum(model.S(:,rxns)~=0,2)>0); -0917 -0918 %Then get their indexes in all compartments -0919 allIndexes=mets; -0920 for j=1:nComps-1 -0921 allIndexes=[allIndexes;mets+nMets*j]; -0922 end -0923 -0924 %Check which of the unconnected metabolites that these reactions -0925 %correspond to. This could have been done earlier, but it is fast. The -0926 %reversibility check is skipped because it is unlikely to be an issue -0927 %here. Worst case is that the gene is tested once to much -0928 [I, ~]=find(model.S(:,rxns)); -0929 moveToComps=unique(comps(ismember(dcIndexes,I))); -0930 -0931 %Try to move the gene to each of the compartments -0932 bestMove=-inf; -0933 bestComp=[]; -0934 for j=1:numel(moveToComps) -0935 newS=moveGene(S,model,g2c,genes(i),moveToComps(j),nRxns,nMets); -0936 -0937 %Check how many metabolites that are unconnected after moving the -0938 %gene -0939 dConnected=numel(unconnected)-numel(findUnconnected(newS,nEM,[allIndexes;unconnected])); -0940 if dConnected>bestMove -0941 bestMove=dConnected; -0942 bestComp=moveToComps(j); -0943 end -0944 end -0945 -0946 %Add the difference in connectivity and where the genes should be moved -0947 moveTo(genes(i))=bestComp; -0948 deltaConnected(genes(i))=bestMove; -0949 end -0950 -0951 %Finish up -0952 geneIndex=genes(:); -0953 moveTo=moveTo(geneIndex); -0954 deltaConnected=deltaConnected(geneIndex); -0955 deltaScore=GSS.scores(sub2ind(size(g2c),geneIndex(:),moveTo))-geneScores; -0956 end -0957 -0958 %Small function to add a transport reactions between two metabolites. -0959 %Transport reactions are written as having a coefficient 2.0 for both -0960 %reactant and product. This is not a "real" reaction, but since all normal -0961 %reactions have coefficient -1/1 or -10/10 it is a compact way of writing -0962 %it -0963 function S=addTransport(S,nRxns,nER,nMets,nEM,nComps,metA,metB) -0964 mets=[metA;metB]; -0965 %Find the current compartments for the metabolites -0966 comps=ceil((mets-nEM)/((size(S,1)-nEM)/nComps)); -0967 -0968 if sum(comps==1)~=1 -0969 EM='Tried to create a transport reaction from a non-default compartment'; -0970 dispEM(EM); -0971 end -0972 -0973 %Calculate the reaction index -0974 rIndex=(nER+nRxns*nComps)+mets(comps~=1)-nEM-nMets; -0975 -0976 S(mets,rIndex)=2; -0977 end -0978 -0979 %Scores a network based on the localization of the genes and the number of -0980 %transporter reactions used -0981 function [score, geneScore, transportCost]=scoreModel(S,g2c,GSS,transportCost) -0982 [I, J]=find(g2c); -0983 geneScore=sum(GSS.scores(sub2ind(size(g2c),I,J))); -0984 [I, ~]=find(S==2); -0985 I=unique(I); -0986 transportCost=sum(transportCost(I)); -0987 score=geneScore-transportCost; -0988 end

    +0837 end +0838 +0839 %Given a set of unconnected metabolites, this function tries to move each +0840 %gene that could connect any of them, calculates the number of newly +0841 %connected metabolites minus the number of newly disconnected metabolites. +0842 %As some metabolites are very connected, only 25 genes are checked. Genes +0843 %that have a low score in their current compartment are more likely to be +0844 %moved +0845 function [geneIndex, moveTo, deltaConnected, deltaScore]=selectGenes(S,nEM,nMets,nER,nRxns,model,unconnected,g2c,GSS) +0846 %If moveTo is 0 then the gene cannot connect any of the metabolites +0847 moveTo=zeros(numel(model.genes),1); +0848 deltaConnected=zeros(numel(model.genes),1); +0849 +0850 %First get where the metabolites are now +0851 nComps=size(g2c,2); +0852 comps=ceil((unconnected-nEM)/((size(S,1)-nEM)/nComps)); +0853 +0854 %Find the corresponding metabolite indexes if they all were in the default +0855 %compartment +0856 dcIndexes=unique(unconnected-(comps-1)*nMets); +0857 +0858 %Then find them if they were in any other compartment +0859 allIndexes=dcIndexes; +0860 for i=1:nComps-1 +0861 allIndexes=[allIndexes;dcIndexes+nMets*i]; +0862 end +0863 +0864 %Also check which reversible reactions that could be used +0865 I=sum(S>2,1) | sum(S>2,1); +0866 revS=S; +0867 revS(:,I)=revS(:,I)*-1; +0868 +0869 %Find all reactions that could make any of the unconnected metabolites in +0870 %some other compartment +0871 newMets=setdiff(allIndexes,unconnected); +0872 [~, potential]=find(S(newMets,:)>0 | revS(newMets,:)>0); +0873 potential(potential<=nER | potential>nER+nRxns*nComps)=[]; %No exchange rxns or transport rxns +0874 +0875 %Map J to the real metabolic reactions in model +0876 rxnComps=ceil((potential-nER)/(nRxns)); +0877 +0878 %Find the corresponding reaction indexes if they all were in the default +0879 %compartment +0880 dcRxnIndexes=potential-(rxnComps-1)*nRxns; +0881 +0882 %Get the genes for those reactions +0883 genes=find(sum(model.rxnGeneMat(dcRxnIndexes,:)>0,1)); +0884 +0885 %For some cases there can be very many reactions to connect something. This +0886 %is in particular true in the beginning of the optimization if, say, ATP is +0887 %unconnected. Therefore limit the number of genes to be checked to 25. +0888 %Weigh so that genes with bad scores in their current compartment are more +0889 %likely to be moved. +0890 +0891 %Get scores for these genes +0892 [~, J]=find(g2c(genes,:)); +0893 +0894 %Add a small weight so that genes in their best compartment could be moved +0895 %as well +0896 geneScores=GSS.scores(sub2ind(size(g2c),genes(:),J)); +0897 modGeneScores=1.1-geneScores; +0898 if numel(genes)>25 +0899 rGenes=genes(randsample(numel(genes),min(numel(genes),25),true,modGeneScores)); +0900 +0901 %The sampling with weights could give duplicates +0902 rGenes=unique(rGenes); +0903 +0904 %Reorder the geneScores to match +0905 [~, I]=ismember(rGenes,genes); +0906 geneScores=geneScores(I); +0907 genes=rGenes; +0908 end +0909 for i=1:numel(genes) +0910 %Since one gene is moved at a time, only metabolites involved in any of +0911 %the reactions for that gene can become unconnected. This helps to +0912 %speed up the algorithm. First get all involved reactions in the +0913 %default compartment +0914 rxns=find(model.rxnGeneMat(:,genes(i))); +0915 +0916 %Then get their mets +0917 mets=find(sum(model.S(:,rxns)~=0,2)>0); +0918 +0919 %Then get their indexes in all compartments +0920 allIndexes=mets; +0921 for j=1:nComps-1 +0922 allIndexes=[allIndexes;mets+nMets*j]; +0923 end +0924 +0925 %Check which of the unconnected metabolites that these reactions +0926 %correspond to. This could have been done earlier, but it is fast. The +0927 %reversibility check is skipped because it is unlikely to be an issue +0928 %here. Worst case is that the gene is tested once to much +0929 [I, ~]=find(model.S(:,rxns)); +0930 moveToComps=unique(comps(ismember(dcIndexes,I))); +0931 +0932 %Try to move the gene to each of the compartments +0933 bestMove=-inf; +0934 bestComp=[]; +0935 for j=1:numel(moveToComps) +0936 newS=moveGene(S,model,g2c,genes(i),moveToComps(j),nRxns,nMets); +0937 +0938 %Check how many metabolites that are unconnected after moving the +0939 %gene +0940 dConnected=numel(unconnected)-numel(findUnconnected(newS,nEM,[allIndexes;unconnected])); +0941 if dConnected>bestMove +0942 bestMove=dConnected; +0943 bestComp=moveToComps(j); +0944 end +0945 end +0946 +0947 %Add the difference in connectivity and where the genes should be moved +0948 moveTo(genes(i))=bestComp; +0949 deltaConnected(genes(i))=bestMove; +0950 end +0951 +0952 %Finish up +0953 geneIndex=genes(:); +0954 moveTo=moveTo(geneIndex); +0955 deltaConnected=deltaConnected(geneIndex); +0956 deltaScore=GSS.scores(sub2ind(size(g2c),geneIndex(:),moveTo))-geneScores; +0957 end +0958 +0959 %Small function to add a transport reactions between two metabolites. +0960 %Transport reactions are written as having a coefficient 2.0 for both +0961 %reactant and product. This is not a "real" reaction, but since all normal +0962 %reactions have coefficient -1/1 or -10/10 it is a compact way of writing +0963 %it +0964 function S=addTransport(S,nRxns,nER,nMets,nEM,nComps,metA,metB) +0965 mets=[metA;metB]; +0966 %Find the current compartments for the metabolites +0967 comps=ceil((mets-nEM)/((size(S,1)-nEM)/nComps)); +0968 +0969 if sum(comps==1)~=1 +0970 EM='Tried to create a transport reaction from a non-default compartment'; +0971 dispEM(EM); +0972 end +0973 +0974 %Calculate the reaction index +0975 rIndex=(nER+nRxns*nComps)+mets(comps~=1)-nEM-nMets; +0976 +0977 S(mets,rIndex)=2; +0978 end +0979 +0980 %Scores a network based on the localization of the genes and the number of +0981 %transporter reactions used +0982 function [score, geneScore, transportCost]=scoreModel(S,g2c,GSS,transportCost) +0983 [I, J]=find(g2c); +0984 geneScore=sum(GSS.scores(sub2ind(size(g2c),I,J))); +0985 [I, ~]=find(S==2); +0986 I=unique(I); +0987 transportCost=sum(transportCost(I)); +0988 score=geneScore-transportCost; +0989 end

    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/printFluxes.html b/doc/core/printFluxes.html index 9b40b729..9184b92c 100644 --- a/doc/core/printFluxes.html +++ b/doc/core/printFluxes.html @@ -60,13 +60,13 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • constructEquations constructEquations
  • convertCharArray convertCharArray
  • dispEM dispEM
  • getElementalBalance getElementalBalance
  • removeReactions removeReactions
  • This function is called by: @@ -109,7 +109,7 @@

    SOURCE CODE ^% hand sides are lumped 0033 % 0034 % Usage: printFluxes(model, fluxes, onlyExchange, cutOffFlux, -0035 % outputFile,outputString) +0035 % outputFile,outputString,metaboliteList) 0036 0037 if nargin<3 0038 onlyExchange=true; @@ -124,139 +124,141 @@

    SOURCE CODE ^else 0049 if ~isempty(outputFile) -0050 fid=fopen(outputFile,'w'); -0051 else -0052 fid=1; -0053 end -0054 end -0055 if nargin<6 -0056 outputString='%rxnID\t(%rxnName):\t%flux\n'; -0057 end -0058 if isempty(outputString) -0059 outputString='%rxnID\t(%rxnName):\t%flux\n'; +0050 outputFile=char(outputFile); +0051 fid=fopen(outputFile,'w'); +0052 else +0053 fid=1; +0054 end +0055 end +0056 if nargin<6 || isempty(outputString) +0057 outputString='%rxnID\t(%rxnName):\t%flux\n'; +0058 else +0059 outputString=char(outputString); 0060 end 0061 if nargin<7 0062 metaboliteList={}; -0063 end -0064 if numel(fluxes)~=numel(model.rxns) -0065 EM='The number of fluxes and the number of reactions must be the same'; -0066 dispEM(EM); -0067 end -0068 -0069 %Only keep reactions involving the defined metabolites -0070 if ~isempty(metaboliteList) -0071 I=ismember(upper(model.metNames),upper(metaboliteList)); -0072 [~, K]=find(model.S(I,:)); -0073 -0074 %Delete all other reactions -0075 toDelete=true(numel(model.rxns),1); -0076 toDelete(K)=false; -0077 model=removeReactions(model,toDelete); -0078 fluxes(toDelete)=[]; -0079 end -0080 -0081 if onlyExchange==true -0082 fprintf(fid,'EXCHANGE FLUXES:\n'); -0083 else -0084 fprintf(fid,'FLUXES:\n'); -0085 end -0086 -0087 %Remove reactions which are below the cut off -0088 toDelete=abs(fluxes)<cutOffFlux; -0089 model=removeReactions(model,toDelete,true,true); -0090 fluxes(toDelete)=[]; -0091 -0092 if any(strfind(outputString,'%eqn')) -0093 %Construct the equations -0094 eqn=constructEquations(model); -0095 else -0096 eqn=cell(numel(model.rxns),1); -0097 eqn(:)={''}; -0098 end -0099 if any(strfind(outputString,'%element')) -0100 %For printing equations using the composition -0101 cModel=model; -0102 cModel.metNames=cModel.metFormulas; -0103 cModel.metNames(cellfun(@isempty,cModel.metNames))={'?'}; -0104 element=constructEquations(cModel); -0105 else -0106 element=cell(numel(model.rxns),1); -0107 element(:)={''}; -0108 end -0109 -0110 if any(strfind(outputString,'%unbalanced')) || any(strfind(outputString,'%lumped')) -0111 balanceStructure=getElementalBalance(model); -0112 end -0113 -0114 unbalanced=cell(numel(model.rxns),1); -0115 unbalanced(:)={''}; -0116 if any(strfind(outputString,'%unbalanced')) -0117 unbalanced(balanceStructure.balanceStatus==0)={'(*)'}; -0118 unbalanced(balanceStructure.balanceStatus<0)={'(-)'}; -0119 end -0120 -0121 lumped=cell(numel(model.rxns),1); -0122 lumped(:)={''}; -0123 if any(strfind(outputString,'%lumped')) -0124 for i=1:numel(model.rxns) -0125 leftGroup=''; -0126 rightGroup=''; -0127 for j=1:numel(balanceStructure.elements.names) -0128 I=balanceStructure.leftComp(i,j); -0129 if I~=0 -0130 if I==1 -0131 leftGroup=[leftGroup balanceStructure.elements.abbrevs{j}]; -0132 else -0133 leftGroup=[leftGroup balanceStructure.elements.abbrevs{j} num2str(I)]; -0134 end -0135 end -0136 I=balanceStructure.rightComp(i,j); -0137 if I~=0 -0138 if I==1 -0139 rightGroup=[rightGroup balanceStructure.elements.abbrevs{j}]; -0140 else -0141 rightGroup=[rightGroup balanceStructure.elements.abbrevs{j} num2str(I)]; -0142 end -0143 end -0144 end -0145 if model.rev(i) -0146 lumped{i}=[leftGroup ' <=> ' rightGroup]; -0147 else -0148 lumped{i}=[leftGroup ' => ' rightGroup]; -0149 end -0150 end -0151 end -0152 -0153 for i=1:numel(model.rxns) -0154 %Only print if it's an exchange reaction or if all reactions should be -0155 %printed. Exchange reactions only have reactants or only products. -0156 reactants=model.S(:,i)<0; -0157 products=model.S(:,i)>0; -0158 -0159 %Only print if the absolute value is >= cutOffFlux -0160 if (onlyExchange==false || (~any(reactants) || ~any(products))) -0161 printString=outputString; -0162 -0163 %Produce the final string -0164 printString=strrep(printString,'%rxnID',model.rxns{i}); -0165 printString=strrep(printString,'%eqn',eqn{i}); -0166 printString=strrep(printString,'%rxnName',model.rxnNames{i}); -0167 printString=strrep(printString,'%lower',num2str(model.lb(i))); -0168 printString=strrep(printString,'%upper',num2str(model.ub(i))); -0169 printString=strrep(printString,'%obj',num2str(model.c(i))); -0170 printString=strrep(printString,'%flux',num2str(fluxes(i))); -0171 printString=strrep(printString,'%element',element{i}); -0172 printString=strrep(printString,'%unbalanced',unbalanced{i}); -0173 printString=strrep(printString,'%lumped',lumped{i}); -0174 fprintf(fid,printString); -0175 end -0176 end -0177 -0178 if fid~=1 -0179 fprintf('File successfully saved.\n'); -0180 fclose(fid); -0181 end -0182 end +0063 else +0064 metaboliteList=convertCharArray(metaboliteList); +0065 end +0066 if numel(fluxes)~=numel(model.rxns) +0067 EM='The number of fluxes and the number of reactions must be the same'; +0068 dispEM(EM); +0069 end +0070 +0071 %Only keep reactions involving the defined metabolites +0072 if ~isempty(metaboliteList) +0073 I=ismember(upper(model.metNames),upper(metaboliteList)); +0074 [~, K]=find(model.S(I,:)); +0075 +0076 %Delete all other reactions +0077 toDelete=true(numel(model.rxns),1); +0078 toDelete(K)=false; +0079 model=removeReactions(model,toDelete); +0080 fluxes(toDelete)=[]; +0081 end +0082 +0083 if onlyExchange==true +0084 fprintf(fid,'EXCHANGE FLUXES:\n'); +0085 else +0086 fprintf(fid,'FLUXES:\n'); +0087 end +0088 +0089 %Remove reactions which are below the cut off +0090 toDelete=abs(fluxes)<cutOffFlux; +0091 model=removeReactions(model,toDelete,true,true); +0092 fluxes(toDelete)=[]; +0093 +0094 if any(strfind(outputString,'%eqn')) +0095 %Construct the equations +0096 eqn=constructEquations(model); +0097 else +0098 eqn=cell(numel(model.rxns),1); +0099 eqn(:)={''}; +0100 end +0101 if any(strfind(outputString,'%element')) +0102 %For printing equations using the composition +0103 cModel=model; +0104 cModel.metNames=cModel.metFormulas; +0105 cModel.metNames(cellfun(@isempty,cModel.metNames))={'?'}; +0106 element=constructEquations(cModel); +0107 else +0108 element=cell(numel(model.rxns),1); +0109 element(:)={''}; +0110 end +0111 +0112 if any(strfind(outputString,'%unbalanced')) || any(strfind(outputString,'%lumped')) +0113 balanceStructure=getElementalBalance(model); +0114 end +0115 +0116 unbalanced=cell(numel(model.rxns),1); +0117 unbalanced(:)={''}; +0118 if any(strfind(outputString,'%unbalanced')) +0119 unbalanced(balanceStructure.balanceStatus==0)={'(*)'}; +0120 unbalanced(balanceStructure.balanceStatus<0)={'(-)'}; +0121 end +0122 +0123 lumped=cell(numel(model.rxns),1); +0124 lumped(:)={''}; +0125 if any(strfind(outputString,'%lumped')) +0126 for i=1:numel(model.rxns) +0127 leftGroup=''; +0128 rightGroup=''; +0129 for j=1:numel(balanceStructure.elements.names) +0130 I=balanceStructure.leftComp(i,j); +0131 if I~=0 +0132 if I==1 +0133 leftGroup=[leftGroup balanceStructure.elements.abbrevs{j}]; +0134 else +0135 leftGroup=[leftGroup balanceStructure.elements.abbrevs{j} num2str(I)]; +0136 end +0137 end +0138 I=balanceStructure.rightComp(i,j); +0139 if I~=0 +0140 if I==1 +0141 rightGroup=[rightGroup balanceStructure.elements.abbrevs{j}]; +0142 else +0143 rightGroup=[rightGroup balanceStructure.elements.abbrevs{j} num2str(I)]; +0144 end +0145 end +0146 end +0147 if model.rev(i) +0148 lumped{i}=[leftGroup ' <=> ' rightGroup]; +0149 else +0150 lumped{i}=[leftGroup ' => ' rightGroup]; +0151 end +0152 end +0153 end +0154 +0155 for i=1:numel(model.rxns) +0156 %Only print if it's an exchange reaction or if all reactions should be +0157 %printed. Exchange reactions only have reactants or only products. +0158 reactants=model.S(:,i)<0; +0159 products=model.S(:,i)>0; +0160 +0161 %Only print if the absolute value is >= cutOffFlux +0162 if (onlyExchange==false || (~any(reactants) || ~any(products))) +0163 printString=outputString; +0164 +0165 %Produce the final string +0166 printString=strrep(printString,'%rxnID',model.rxns{i}); +0167 printString=strrep(printString,'%eqn',eqn{i}); +0168 printString=strrep(printString,'%rxnName',model.rxnNames{i}); +0169 printString=strrep(printString,'%lower',num2str(model.lb(i))); +0170 printString=strrep(printString,'%upper',num2str(model.ub(i))); +0171 printString=strrep(printString,'%obj',num2str(model.c(i))); +0172 printString=strrep(printString,'%flux',num2str(fluxes(i))); +0173 printString=strrep(printString,'%element',element{i}); +0174 printString=strrep(printString,'%unbalanced',unbalanced{i}); +0175 printString=strrep(printString,'%lumped',lumped{i}); +0176 fprintf(fid,printString); +0177 end +0178 end +0179 +0180 if fid~=1 +0181 fprintf('File successfully saved.\n'); +0182 fclose(fid); +0183 end +0184 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/printModel.html b/doc/core/printModel.html index 2e8bd0d7..cfd396c6 100644 --- a/doc/core/printModel.html +++ b/doc/core/printModel.html @@ -67,7 +67,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • getIndexes getIndexes
  • printFluxes printFluxes
  • This function is called by: @@ -113,33 +113,35 @@

    SOURCE CODE ^% 0036 % Usage: printModel(model,rxnList,outputString,outputFile,metaboliteList) 0037 -0038 if nargin<2 +0038 if nargin<2 || isempty(rxnList) 0039 rxnList=model.rxns; -0040 end -0041 if isempty(rxnList) -0042 rxnList=model.rxns; -0043 end -0044 if nargin<3 -0045 outputString='%rxnID (%rxnName)\n\t%eqn [%lower %upper]\n'; -0046 end -0047 if isempty(outputString) -0048 outputString='%rxnID (%rxnName)\n\t%eqn [%lower %upper]\n'; -0049 end -0050 if nargin<4 -0051 outputFile=[]; +0040 elseif ~islogical(rxnList) && ~isnumeric(rxnList) +0041 rxnList=convertCharArray(rxnList); +0042 end +0043 if nargin<3 || isempty(outputString) +0044 outputString='%rxnID (%rxnName)\n\t%eqn [%lower %upper]\n'; +0045 else +0046 outputString=char(outputString); +0047 end +0048 if nargin<4 +0049 outputFile=[]; +0050 else +0051 outputFile=char(outputFile); 0052 end 0053 if nargin<5 0054 metaboliteList=[]; -0055 end -0056 -0057 I=getIndexes(model,rxnList,'rxns',true)*1.00; %To convert it to "fluxes" +0055 else +0056 metaboliteList=convertCharArray(metaboliteList); +0057 end 0058 -0059 if ~isempty(metaboliteList) -0060 printFluxes(model, I, false, 0.1, outputFile,outputString,metaboliteList); -0061 else -0062 printFluxes(model, I, false, 0.1, outputFile,outputString); -0063 end -0064 end +0059 I=getIndexes(model,rxnList,'rxns',true)*1.00; %To convert it to "fluxes" +0060 +0061 if ~isempty(metaboliteList) +0062 printFluxes(model, I, false, 0.1, outputFile,outputString,metaboliteList); +0063 else +0064 printFluxes(model, I, false, 0.1, outputFile,outputString); +0065 end +0066 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/removeBadRxns.html b/doc/core/removeBadRxns.html index 12245428..2f8c01cb 100644 --- a/doc/core/removeBadRxns.html +++ b/doc/core/removeBadRxns.html @@ -101,7 +101,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • consumeSomething consumeSomething
  • convertCharArray convertCharArray
  • dispEM dispEM
  • getElementalBalance getElementalBalance
  • getExchangeRxns getExchangeRxns
  • makeSomething makeSomething
  • removeReactions removeReactions
  • This function is called by: @@ -186,168 +186,172 @@

    SOURCE CODE ^end 0075 if nargin<3 0076 ignoreMets=[]; -0077 end -0078 if nargin<4 -0079 isNames=false; -0080 end -0081 if nargin<5 -0082 balanceElements={'C';'P';'S';'N';'O'}; -0083 end -0084 if nargin<6 -0085 refModel=[]; -0086 else -0087 if ~isempty(refModel) -0088 EM='The feature to supply a reference model is currently not supported'; -0089 dispEM(EM,false); -0090 end -0091 end -0092 if nargin<7 -0093 ignoreIntBounds=false; -0094 end -0095 if nargin<8 -0096 printReport=false; -0097 end -0098 -0099 %Check if the model has open exchange reactions and print a warning in that -0100 %case -0101 if ~isfield(model,'unconstrained') -0102 [~, I]=getExchangeRxns(model); -0103 if any(I) -0104 if any(model.lb(I)~=0) || any(model.ub(I)~=0) -0105 EM='The model contains open exchange reactions. This is not the intended use of this function. Consider importing your model using importModel(filename,false)'; -0106 dispEM(EM,false); -0107 end -0108 end -0109 end -0110 -0111 %Check that the model is feasible -0112 sol=solveLP(model); -0113 if isempty(sol.f) -0114 EM='The model is not feasible. Consider removing lower bounds (such as ATP maintenance)'; -0115 dispEM(EM); -0116 end -0117 -0118 %Check that the reference model is feasible -0119 if any(refModel) -0120 sol=solveLP(refModel); -0121 if isempty(sol.f) -0122 EM='The reference model is not feasible'; -0123 dispEM(EM); -0124 end -0125 end -0126 -0127 %Initialize some stuff -0128 removedRxns={}; -0129 balanceStructure=getElementalBalance(model); +0077 elseif ~islogical(ignoreMets) && ~isnumeric(ignoreMets) +0078 ignoreMets=convertCharArray(ignoreMets); +0079 end +0080 if nargin<4 +0081 isNames=false; +0082 end +0083 if nargin<5 +0084 balanceElements={'C';'P';'S';'N';'O'}; +0085 else +0086 balanceElements=convertCharArray(balanceElements); +0087 end +0088 if nargin<6 +0089 refModel=[]; +0090 else +0091 if ~isempty(refModel) +0092 EM='The feature to supply a reference model is currently not supported'; +0093 dispEM(EM,false); +0094 end +0095 end +0096 if nargin<7 +0097 ignoreIntBounds=false; +0098 end +0099 if nargin<8 +0100 printReport=false; +0101 end +0102 +0103 %Check if the model has open exchange reactions and print a warning in that +0104 %case +0105 if ~isfield(model,'unconstrained') +0106 [~, I]=getExchangeRxns(model); +0107 if any(I) +0108 if any(model.lb(I)~=0) || any(model.ub(I)~=0) +0109 EM='The model contains open exchange reactions. This is not the intended use of this function. Consider importing your model using importModel(filename,false)'; +0110 dispEM(EM,false); +0111 end +0112 end +0113 end +0114 +0115 %Check that the model is feasible +0116 sol=solveLP(model); +0117 if isempty(sol.f) +0118 EM='The model is not feasible. Consider removing lower bounds (such as ATP maintenance)'; +0119 dispEM(EM); +0120 end +0121 +0122 %Check that the reference model is feasible +0123 if any(refModel) +0124 sol=solveLP(refModel); +0125 if isempty(sol.f) +0126 EM='The reference model is not feasible'; +0127 dispEM(EM); +0128 end +0129 end 0130 -0131 %Check which elements to balance for -0132 if ~isempty(setdiff(balanceElements,balanceStructure.elements.abbrevs)) -0133 EM='Could not recognize all elements to balance for'; -0134 dispEM(EM); -0135 end -0136 bal=ismember(balanceStructure.elements.abbrevs,balanceElements); -0137 -0138 %Main loop. First run for makeSomething, second for consumeSomething -0139 warned=false(2,1); %This is to prevent the same warning being printed multiple times if rxnRules==3 -0140 for i=1:2 -0141 while 1 -0142 %Make some metabolite using as few reactions as possible -0143 if i==1 -0144 [solution, metabolite]=makeSomething(model,ignoreMets,isNames,false,true,[],ignoreIntBounds); -0145 if ~isempty(solution) -0146 if printReport -0147 fprintf(['Can make: ' model.metNames{metabolite(1)} '\n']); -0148 end -0149 else -0150 %If no solution could be found, then finish -0151 break; -0152 end -0153 else -0154 [solution, metabolite]=consumeSomething(model,ignoreMets,isNames,false,[],ignoreIntBounds); -0155 if ~isempty(solution) -0156 if printReport -0157 fprintf(['Can consume: ' model.metNames{metabolite(1)} '\n']); -0158 end -0159 else -0160 %If no solution could be found, then finish -0161 break; -0162 end -0163 end -0164 -0165 %Find all reactions that are unbalanced and still carry flux -0166 I=find(abs(solution)>10^-8 & balanceStructure.balanceStatus>=0 & ~all(balanceStructure.leftComp(:,bal)==balanceStructure.rightComp(:,bal),2)); -0167 -0168 %If there are unbalanced rxns then delete one of them and iterate -0169 if any(I) -0170 rxnToRemove=I(randsample(numel(I),1)); -0171 else -0172 %If there are no unbalanced rxns in the solution -0173 if rxnRules==1 -0174 if i==1 -0175 EM=['No unbalanced reactions were found in the solution, but the model can still make "' model.metNames{metabolite} '". Aborting search. Consider setting rxnRules to 2 or 3 for a more exhaustive search']; -0176 dispEM(EM,false); -0177 else -0178 EM=['No unbalanced reactions were found in the solution, but the model can still consume "' model.metNames{metabolite} '". Aborting search. Consider setting rxnRules to 2 or 3 for a more exhaustive search']; -0179 dispEM(EM,false); -0180 end -0181 break; -0182 else -0183 %Find reactions which are not checked for mass balancing, -0184 %but that still carry flux -0185 I=find(abs(solution)>10^-8 & balanceStructure.balanceStatus<0); -0186 -0187 %If there are any such reactions, remove one of them and -0188 %iterate -0189 if any(I) -0190 rxnToRemove=I(randsample(numel(I),1)); -0191 else -0192 if rxnRules==2 -0193 %This happens when all reactions used are balanced -0194 %according to the metabolite formulas. This cannot -0195 %be, and indicates that one or more of the formulas -0196 %are wrong. Print a warning and delete any reaction -0197 %with flux -0198 if i==1 -0199 EM=['No unbalanced or unparsable reactions were found in the solution, but the model can still make "' model.metNames{metabolite} '". Aborting search. Consider setting rxnRules to 3 for a more exhaustive search']; -0200 dispEM(EM,false); -0201 else -0202 EM=['No unbalanced or unparsable reactions were found in the solution, but the model can still consume "' model.metNames{metabolite} '". Aborting search. Consider setting rxnRules to 3 for a more exhaustive search']; -0203 dispEM(EM,false); -0204 end -0205 break; -0206 else -0207 if i==1 -0208 if warned(1)==false -0209 EM=['No unbalanced or unparsable reactions were found in the solution, but the model can still make "' model.metNames{metabolite} '". This indicates some error in the metabolite formulas. Removing random reactions in the solution']; -0210 dispEM(EM,false); -0211 warned(1)=true; -0212 end -0213 else -0214 if warned(2)==false -0215 EM=['No unbalanced or unparsable reactions were found in the solution, but the model can still consume "' model.metNames{metabolite} '". This indicates some error in the metabolite formulas. Removing random reactions in the solution']; -0216 dispEM(EM,false); -0217 warned(2)=true; -0218 end -0219 end -0220 I=find(abs(solution)>10^-8); -0221 rxnToRemove=I(randsample(numel(I),1)); -0222 end -0223 end -0224 end -0225 end -0226 removedRxns=[removedRxns;model.rxns(rxnToRemove)]; -0227 if printReport -0228 fprintf(['\tRemoved: ' model.rxns{rxnToRemove} '\n']); +0131 %Initialize some stuff +0132 removedRxns={}; +0133 balanceStructure=getElementalBalance(model); +0134 +0135 %Check which elements to balance for +0136 if ~isempty(setdiff(balanceElements,balanceStructure.elements.abbrevs)) +0137 EM='Could not recognize all elements to balance for'; +0138 dispEM(EM); +0139 end +0140 bal=ismember(balanceStructure.elements.abbrevs,balanceElements); +0141 +0142 %Main loop. First run for makeSomething, second for consumeSomething +0143 warned=false(2,1); %This is to prevent the same warning being printed multiple times if rxnRules==3 +0144 for i=1:2 +0145 while 1 +0146 %Make some metabolite using as few reactions as possible +0147 if i==1 +0148 [solution, metabolite]=makeSomething(model,ignoreMets,isNames,false,true,[],ignoreIntBounds); +0149 if ~isempty(solution) +0150 if printReport +0151 fprintf(['Can make: ' model.metNames{metabolite(1)} '\n']); +0152 end +0153 else +0154 %If no solution could be found, then finish +0155 break; +0156 end +0157 else +0158 [solution, metabolite]=consumeSomething(model,ignoreMets,isNames,false,[],ignoreIntBounds); +0159 if ~isempty(solution) +0160 if printReport +0161 fprintf(['Can consume: ' model.metNames{metabolite(1)} '\n']); +0162 end +0163 else +0164 %If no solution could be found, then finish +0165 break; +0166 end +0167 end +0168 +0169 %Find all reactions that are unbalanced and still carry flux +0170 I=find(abs(solution)>10^-8 & balanceStructure.balanceStatus>=0 & ~all(balanceStructure.leftComp(:,bal)==balanceStructure.rightComp(:,bal),2)); +0171 +0172 %If there are unbalanced rxns then delete one of them and iterate +0173 if any(I) +0174 rxnToRemove=I(randperm(numel(I),1)); +0175 else +0176 %If there are no unbalanced rxns in the solution +0177 if rxnRules==1 +0178 if i==1 +0179 EM=['No unbalanced reactions were found in the solution, but the model can still make "' model.metNames{metabolite} '". Aborting search. Consider setting rxnRules to 2 or 3 for a more exhaustive search']; +0180 dispEM(EM,false); +0181 else +0182 EM=['No unbalanced reactions were found in the solution, but the model can still consume "' model.metNames{metabolite} '". Aborting search. Consider setting rxnRules to 2 or 3 for a more exhaustive search']; +0183 dispEM(EM,false); +0184 end +0185 break; +0186 else +0187 %Find reactions which are not checked for mass balancing, +0188 %but that still carry flux +0189 I=find(abs(solution)>10^-8 & balanceStructure.balanceStatus<0); +0190 +0191 %If there are any such reactions, remove one of them and +0192 %iterate +0193 if any(I) +0194 rxnToRemove=I(randperm(numel(I),1)); +0195 else +0196 if rxnRules==2 +0197 %This happens when all reactions used are balanced +0198 %according to the metabolite formulas. This cannot +0199 %be, and indicates that one or more of the formulas +0200 %are wrong. Print a warning and delete any reaction +0201 %with flux +0202 if i==1 +0203 EM=['No unbalanced or unparsable reactions were found in the solution, but the model can still make "' model.metNames{metabolite} '". Aborting search. Consider setting rxnRules to 3 for a more exhaustive search']; +0204 dispEM(EM,false); +0205 else +0206 EM=['No unbalanced or unparsable reactions were found in the solution, but the model can still consume "' model.metNames{metabolite} '". Aborting search. Consider setting rxnRules to 3 for a more exhaustive search']; +0207 dispEM(EM,false); +0208 end +0209 break; +0210 else +0211 if i==1 +0212 if warned(1)==false +0213 EM=['No unbalanced or unparsable reactions were found in the solution, but the model can still make "' model.metNames{metabolite} '". This indicates some error in the metabolite formulas. Removing random reactions in the solution']; +0214 dispEM(EM,false); +0215 warned(1)=true; +0216 end +0217 else +0218 if warned(2)==false +0219 EM=['No unbalanced or unparsable reactions were found in the solution, but the model can still consume "' model.metNames{metabolite} '". This indicates some error in the metabolite formulas. Removing random reactions in the solution']; +0220 dispEM(EM,false); +0221 warned(2)=true; +0222 end +0223 end +0224 I=find(abs(solution)>10^-8); +0225 rxnToRemove=I(randperm(numel(I),1)); +0226 end +0227 end +0228 end 0229 end -0230 model=removeReactions(model,rxnToRemove); -0231 balanceStructure.balanceStatus(rxnToRemove)=[]; -0232 balanceStructure.leftComp(rxnToRemove,:)=[]; -0233 balanceStructure.rightComp(rxnToRemove,:)=[]; -0234 end -0235 end -0236 -0237 newModel=model; -0238 end +0230 removedRxns=[removedRxns;model.rxns(rxnToRemove)]; +0231 if printReport +0232 fprintf(['\tRemoved: ' model.rxns{rxnToRemove} '\n']); +0233 end +0234 model=removeReactions(model,rxnToRemove); +0235 balanceStructure.balanceStatus(rxnToRemove)=[]; +0236 balanceStructure.leftComp(rxnToRemove,:)=[]; +0237 balanceStructure.rightComp(rxnToRemove,:)=[]; +0238 end +0239 end +0240 +0241 newModel=model; +0242 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/removeGenes.html b/doc/core/removeGenes.html index 43833d99..88094677 100644 --- a/doc/core/removeGenes.html +++ b/doc/core/removeGenes.html @@ -49,7 +49,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • getIndexes getIndexes
  • removeReactions removeReactions
  • standardizeGrRules standardizeGrRules
  • This function is called by: @@ -99,8 +99,8 @@

    SOURCE CODE ^end 0038 reducedModel = model; 0039 %Only remove genes that are actually in the model -0040 try -0041 ischar(genesToRemove{1}); +0040 if ~islogical(genesToRemove) || ~isnumeric(genesToRemove) +0041 genesToRemove=convertCharArray(genesToRemove); 0042 genesToRemove=genesToRemove(ismember(genesToRemove,model.genes)); 0043 end 0044 if ~isempty(genesToRemove) diff --git a/doc/core/removeMets.html b/doc/core/removeMets.html index 3ac02121..fdf5d5f3 100644 --- a/doc/core/removeMets.html +++ b/doc/core/removeMets.html @@ -55,7 +55,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • getIndexes getIndexes
  • removeReactions removeReactions
  • This function is called by: @@ -88,110 +88,102 @@

    SOURCE CODE ^% 0023 % Usage: reducedModel=removeMets(model,metsToRemove,isNames,... 0024 % removeUnusedRxns,removeUnusedGenes,removeUnusedComps) -0025 -0026 if ischar(metsToRemove) -0027 metsToRemove={metsToRemove}; -0028 end -0029 -0030 if nargin<3 -0031 isNames=false; -0032 end -0033 -0034 if nargin<4 -0035 removeUnusedRxns=false; -0036 end -0037 -0038 if nargin<5 -0039 removeUnusedGenes=false; -0040 end -0041 -0042 if nargin<6 -0043 removeUnusedComps=false; -0044 end -0045 -0046 if isNames==true -0047 %Check that metsToRemove is a cell array -0048 if iscellstr(metsToRemove)==false -0049 if ischar(metsToRemove) -0050 metsToRemove={metsToRemove}; -0051 else -0052 EM='Must supply a cell array of strings if isNames=true'; -0053 dispEM(EM); -0054 end -0055 end -0056 end -0057 -0058 reducedModel=model; -0059 -0060 if isNames==false -0061 indexesToDelete=getIndexes(model,metsToRemove,'mets'); -0062 else -0063 indexesToDelete=[]; -0064 for i=1:numel(metsToRemove) -0065 indexesToDelete=[indexesToDelete;find(strcmp(metsToRemove(i),model.metNames))]; -0066 end -0067 end -0068 -0069 %Remove metabolites -0070 if ~isempty(indexesToDelete) -0071 reducedModel.mets(indexesToDelete)=[]; -0072 reducedModel.S(indexesToDelete,:)=[]; -0073 if isfield(reducedModel,'b') -0074 reducedModel.b(indexesToDelete,:)=[]; -0075 end -0076 if isfield(reducedModel,'metNames') -0077 reducedModel.metNames(indexesToDelete)=[]; -0078 end -0079 if isfield(reducedModel,'metComps') -0080 reducedModel.metComps(indexesToDelete)=[]; -0081 end -0082 if isfield(reducedModel,'inchis') -0083 reducedModel.inchis(indexesToDelete)=[]; -0084 end -0085 if isfield(reducedModel,'metFormulas') -0086 reducedModel.metFormulas(indexesToDelete)=[]; -0087 end -0088 if isfield(reducedModel,'metMiriams') -0089 reducedModel.metMiriams(indexesToDelete)=[]; -0090 end -0091 if isfield(reducedModel,'unconstrained') -0092 reducedModel.unconstrained(indexesToDelete)=[]; -0093 end -0094 if isfield(reducedModel,'metFrom') -0095 reducedModel.metFrom(indexesToDelete)=[]; -0096 end -0097 if isfield(reducedModel,'metCharges') -0098 reducedModel.metCharges(indexesToDelete)=[]; -0099 end -0100 end -0101 -0102 %Remove unused reactions -0103 if removeUnusedRxns==true -0104 %Get unused reactions -0105 [~, a]=find(reducedModel.S); -0106 rxnsToRemove=1:numel(reducedModel.rxns); -0107 rxnsToRemove(a)=[]; -0108 reducedModel=removeReactions(reducedModel,rxnsToRemove,false,removeUnusedGenes); -0109 end -0110 -0111 %Remove unused compartments -0112 if removeUnusedComps==true -0113 oldComps=reducedModel.comps; -0114 I=ismember(1:numel(oldComps),reducedModel.metComps); -0115 if ~all(I) -0116 reducedModel.comps(~I)=[]; -0117 reducedModel.compNames(~I)=[]; -0118 if isfield(reducedModel,'compOutside') -0119 reducedModel.compOutside(~I)=[]; -0120 end -0121 if isfield(reducedModel,'compMiriams') -0122 reducedModel.compMiriams(~I)=[]; -0123 end -0124 [~, J]=ismember(oldComps(reducedModel.metComps),reducedModel.comps); -0125 reducedModel.metComps=J; -0126 end -0127 end -0128 end +0025 if ~islogical(metsToRemove) && ~isnumeric(metsToRemove) +0026 metsToRemove=convertCharArray(metsToRemove); +0027 end +0028 +0029 if nargin<3 +0030 isNames=false; +0031 end +0032 +0033 if nargin<4 +0034 removeUnusedRxns=false; +0035 end +0036 +0037 if nargin<5 +0038 removeUnusedGenes=false; +0039 end +0040 +0041 if nargin<6 +0042 removeUnusedComps=false; +0043 end +0044 +0045 %Check that metsToRemove is a cell array +0046 if isNames==true && ~iscell(metsToRemove) +0047 error('Must supply a cell array of strings if isNames=true'); +0048 end +0049 +0050 reducedModel=model; +0051 +0052 if isNames==false +0053 indexesToDelete=getIndexes(model,metsToRemove,'mets'); +0054 else +0055 indexesToDelete=[]; +0056 for i=1:numel(metsToRemove) +0057 indexesToDelete=[indexesToDelete;find(strcmp(metsToRemove(i),model.metNames))]; +0058 end +0059 end +0060 +0061 %Remove metabolites +0062 if ~isempty(indexesToDelete) +0063 reducedModel.mets(indexesToDelete)=[]; +0064 reducedModel.S(indexesToDelete,:)=[]; +0065 if isfield(reducedModel,'b') +0066 reducedModel.b(indexesToDelete,:)=[]; +0067 end +0068 if isfield(reducedModel,'metNames') +0069 reducedModel.metNames(indexesToDelete)=[]; +0070 end +0071 if isfield(reducedModel,'metComps') +0072 reducedModel.metComps(indexesToDelete)=[]; +0073 end +0074 if isfield(reducedModel,'inchis') +0075 reducedModel.inchis(indexesToDelete)=[]; +0076 end +0077 if isfield(reducedModel,'metFormulas') +0078 reducedModel.metFormulas(indexesToDelete)=[]; +0079 end +0080 if isfield(reducedModel,'metMiriams') +0081 reducedModel.metMiriams(indexesToDelete)=[]; +0082 end +0083 if isfield(reducedModel,'unconstrained') +0084 reducedModel.unconstrained(indexesToDelete)=[]; +0085 end +0086 if isfield(reducedModel,'metFrom') +0087 reducedModel.metFrom(indexesToDelete)=[]; +0088 end +0089 if isfield(reducedModel,'metCharges') +0090 reducedModel.metCharges(indexesToDelete)=[]; +0091 end +0092 end +0093 +0094 %Remove unused reactions +0095 if removeUnusedRxns==true +0096 %Get unused reactions +0097 [~, a]=find(reducedModel.S); +0098 rxnsToRemove=1:numel(reducedModel.rxns); +0099 rxnsToRemove(a)=[]; +0100 reducedModel=removeReactions(reducedModel,rxnsToRemove,false,removeUnusedGenes); +0101 end +0102 +0103 %Remove unused compartments +0104 if removeUnusedComps==true +0105 oldComps=reducedModel.comps; +0106 I=ismember(1:numel(oldComps),reducedModel.metComps); +0107 if ~all(I) +0108 reducedModel.comps(~I)=[]; +0109 reducedModel.compNames(~I)=[]; +0110 if isfield(reducedModel,'compOutside') +0111 reducedModel.compOutside(~I)=[]; +0112 end +0113 if isfield(reducedModel,'compMiriams') +0114 reducedModel.compMiriams(~I)=[]; +0115 end +0116 [~, J]=ismember(oldComps(reducedModel.metComps),reducedModel.comps); +0117 reducedModel.metComps=J; +0118 end +0119 end +0120 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/removeReactions.html b/doc/core/removeReactions.html index 70323e42..8ec35c52 100644 --- a/doc/core/removeReactions.html +++ b/doc/core/removeReactions.html @@ -50,7 +50,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • getIndexes getIndexes
  • removeMets removeMets
  • This function is called by: @@ -88,121 +88,120 @@

    SOURCE CODE ^if nargin<5 0028 removeUnusedComps=false; 0029 end -0030 -0031 if ischar(rxnsToRemove) -0032 rxnsToRemove={rxnsToRemove}; -0033 end -0034 -0035 reducedModel=model; -0036 -0037 if ~isempty(rxnsToRemove) || removeUnusedMets || removeUnusedGenes -0038 indexesToDelete=getIndexes(model,rxnsToRemove,'rxns'); -0039 -0040 %Remove reactions -0041 if ~isempty(indexesToDelete) -0042 reducedModel.rxns(indexesToDelete)=[]; -0043 if isfield(reducedModel,'lb') -0044 reducedModel.lb(indexesToDelete)=[]; -0045 end -0046 if isfield(reducedModel,'ub') -0047 reducedModel.ub(indexesToDelete)=[]; -0048 end -0049 if isfield(reducedModel,'rev') -0050 reducedModel.rev(indexesToDelete)=[]; -0051 end -0052 if isfield(reducedModel,'c') -0053 reducedModel.c(indexesToDelete)=[]; -0054 end -0055 if isfield(reducedModel,'S') -0056 reducedModel.S(:,indexesToDelete)=[]; -0057 end -0058 if isfield(reducedModel,'rxnNames') -0059 reducedModel.rxnNames(indexesToDelete)=[]; -0060 end -0061 if isfield(reducedModel,'rxnGeneMat') -0062 reducedModel.rxnGeneMat(indexesToDelete,:)=[]; -0063 end -0064 if isfield(reducedModel,'grRules') -0065 reducedModel.grRules(indexesToDelete,:)=[]; -0066 end -0067 if isfield(reducedModel,'subSystems') -0068 reducedModel.subSystems(indexesToDelete,:)=[]; -0069 end -0070 if isfield(reducedModel,'eccodes') -0071 reducedModel.eccodes(indexesToDelete,:)=[]; -0072 end -0073 if isfield(reducedModel,'equations') -0074 reducedModel.equations(indexesToDelete,:)=[]; -0075 end -0076 if isfield(reducedModel,'rxnMiriams') -0077 reducedModel.rxnMiriams(indexesToDelete,:)=[]; -0078 end -0079 if isfield(reducedModel,'rxnComps') -0080 reducedModel.rxnComps(indexesToDelete,:)=[]; -0081 end -0082 if isfield(reducedModel,'rxnFrom') -0083 reducedModel.rxnFrom(indexesToDelete,:)=[]; -0084 end -0085 if isfield(reducedModel,'rxnScores') -0086 reducedModel.rxnScores(indexesToDelete,:)=[]; -0087 end -0088 if isfield(reducedModel,'rxnNotes') -0089 reducedModel.rxnNotes(indexesToDelete,:)=[]; -0090 end -0091 if isfield(reducedModel,'rxnReferences') -0092 reducedModel.rxnReferences(indexesToDelete,:)=[]; -0093 end -0094 if isfield(reducedModel,'rxnConfidenceScores') -0095 reducedModel.rxnConfidenceScores(indexesToDelete,:)=[]; -0096 end -0097 if isfield(reducedModel,'pwys') -0098 reducedModel.pwys(indexesToDelete,:)=[]; -0099 end -0100 if isfield(reducedModel,'spontaneous') -0101 reducedModel.spontaneous(indexesToDelete)=[]; -0102 end -0103 end -0104 -0105 %Remove unused metabolites -0106 if removeUnusedMets==true -0107 if isfield(reducedModel,'S') -0108 [usedMets, ~]=find(reducedModel.S); -0109 unUsedMets=true(numel(reducedModel.mets),1); -0110 unUsedMets(usedMets)=false; -0111 reducedModel=removeMets(reducedModel,unUsedMets,false,false,false,removeUnusedComps); -0112 end -0113 end -0114 -0115 %Remove unused genes -0116 if removeUnusedGenes==true && isfield(reducedModel,'rxnGeneMat') -0117 %Find all genes that are not used -0118 [~, b]=find(reducedModel.rxnGeneMat); -0119 toKeep=false(numel(reducedModel.genes),1); -0120 toKeep(b)=true; -0121 -0122 reducedModel.genes=reducedModel.genes(toKeep); -0123 reducedModel.rxnGeneMat=reducedModel.rxnGeneMat(:,toKeep); -0124 -0125 if isfield(reducedModel,'geneShortNames') -0126 reducedModel.geneShortNames=reducedModel.geneShortNames(toKeep); -0127 end -0128 -0129 if isfield(reducedModel,'geneMiriams') -0130 reducedModel.geneMiriams=reducedModel.geneMiriams(toKeep); -0131 end -0132 -0133 if isfield(reducedModel,'geneFrom') -0134 reducedModel.geneFrom=reducedModel.geneFrom(toKeep); -0135 end -0136 -0137 if isfield(reducedModel,'geneComps') -0138 reducedModel.geneComps=reducedModel.geneComps(toKeep); -0139 end -0140 end -0141 else -0142 reducedModel=model; -0143 end -0144 end +0030 if ~islogical(rxnsToRemove) && ~isnumeric(rxnsToRemove) +0031 rxnsToRemove=convertCharArray(rxnsToRemove); +0032 end +0033 +0034 reducedModel=model; +0035 +0036 if ~isempty(rxnsToRemove) || removeUnusedMets || removeUnusedGenes +0037 indexesToDelete=getIndexes(model,rxnsToRemove,'rxns'); +0038 +0039 %Remove reactions +0040 if ~isempty(indexesToDelete) +0041 reducedModel.rxns(indexesToDelete)=[]; +0042 if isfield(reducedModel,'lb') +0043 reducedModel.lb(indexesToDelete)=[]; +0044 end +0045 if isfield(reducedModel,'ub') +0046 reducedModel.ub(indexesToDelete)=[]; +0047 end +0048 if isfield(reducedModel,'rev') +0049 reducedModel.rev(indexesToDelete)=[]; +0050 end +0051 if isfield(reducedModel,'c') +0052 reducedModel.c(indexesToDelete)=[]; +0053 end +0054 if isfield(reducedModel,'S') +0055 reducedModel.S(:,indexesToDelete)=[]; +0056 end +0057 if isfield(reducedModel,'rxnNames') +0058 reducedModel.rxnNames(indexesToDelete)=[]; +0059 end +0060 if isfield(reducedModel,'rxnGeneMat') +0061 reducedModel.rxnGeneMat(indexesToDelete,:)=[]; +0062 end +0063 if isfield(reducedModel,'grRules') +0064 reducedModel.grRules(indexesToDelete,:)=[]; +0065 end +0066 if isfield(reducedModel,'subSystems') +0067 reducedModel.subSystems(indexesToDelete,:)=[]; +0068 end +0069 if isfield(reducedModel,'eccodes') +0070 reducedModel.eccodes(indexesToDelete,:)=[]; +0071 end +0072 if isfield(reducedModel,'equations') +0073 reducedModel.equations(indexesToDelete,:)=[]; +0074 end +0075 if isfield(reducedModel,'rxnMiriams') +0076 reducedModel.rxnMiriams(indexesToDelete,:)=[]; +0077 end +0078 if isfield(reducedModel,'rxnComps') +0079 reducedModel.rxnComps(indexesToDelete,:)=[]; +0080 end +0081 if isfield(reducedModel,'rxnFrom') +0082 reducedModel.rxnFrom(indexesToDelete,:)=[]; +0083 end +0084 if isfield(reducedModel,'rxnScores') +0085 reducedModel.rxnScores(indexesToDelete,:)=[]; +0086 end +0087 if isfield(reducedModel,'rxnNotes') +0088 reducedModel.rxnNotes(indexesToDelete,:)=[]; +0089 end +0090 if isfield(reducedModel,'rxnReferences') +0091 reducedModel.rxnReferences(indexesToDelete,:)=[]; +0092 end +0093 if isfield(reducedModel,'rxnConfidenceScores') +0094 reducedModel.rxnConfidenceScores(indexesToDelete,:)=[]; +0095 end +0096 if isfield(reducedModel,'pwys') +0097 reducedModel.pwys(indexesToDelete,:)=[]; +0098 end +0099 if isfield(reducedModel,'spontaneous') +0100 reducedModel.spontaneous(indexesToDelete)=[]; +0101 end +0102 end +0103 +0104 %Remove unused metabolites +0105 if removeUnusedMets==true +0106 if isfield(reducedModel,'S') +0107 [usedMets, ~]=find(reducedModel.S); +0108 unUsedMets=true(numel(reducedModel.mets),1); +0109 unUsedMets(usedMets)=false; +0110 reducedModel=removeMets(reducedModel,unUsedMets,false,false,false,removeUnusedComps); +0111 end +0112 end +0113 +0114 %Remove unused genes +0115 if removeUnusedGenes==true && isfield(reducedModel,'rxnGeneMat') +0116 %Find all genes that are not used +0117 [~, b]=find(reducedModel.rxnGeneMat); +0118 toKeep=false(numel(reducedModel.genes),1); +0119 toKeep(b)=true; +0120 +0121 reducedModel.genes=reducedModel.genes(toKeep); +0122 reducedModel.rxnGeneMat=reducedModel.rxnGeneMat(:,toKeep); +0123 +0124 if isfield(reducedModel,'geneShortNames') +0125 reducedModel.geneShortNames=reducedModel.geneShortNames(toKeep); +0126 end +0127 +0128 if isfield(reducedModel,'geneMiriams') +0129 reducedModel.geneMiriams=reducedModel.geneMiriams(toKeep); +0130 end +0131 +0132 if isfield(reducedModel,'geneFrom') +0133 reducedModel.geneFrom=reducedModel.geneFrom(toKeep); +0134 end +0135 +0136 if isfield(reducedModel,'geneComps') +0137 reducedModel.geneComps=reducedModel.geneComps(toKeep); +0138 end +0139 end +0140 else +0141 reducedModel=model; +0142 end +0143 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/replaceMets.html b/doc/core/replaceMets.html index ef9fb7b6..add0644d 100644 --- a/doc/core/replaceMets.html +++ b/doc/core/replaceMets.html @@ -49,7 +49,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • contractModel contractModel
  • This function is called by: @@ -77,92 +77,95 @@

    SOURCE CODE ^% 0018 % Usage: model=replaceMets(model,metabolite,replacement,verbose) 0019 -0020 if nargin<4 -0021 verbose=false; -0022 end -0023 -0024 % Find occurence of replacement metabolites. Annotation will be taken from -0025 % first metabolite found. Metabolite ID from replacement will be used where -0026 % possible. -0027 repIdx = find(strcmp(replacement,model.metNames)); -0028 if isempty(repIdx) -0029 EM='The replacement metabolite name cannot be found in the model.' -0030 dispEM(EM,true); -0031 end -0032 -0033 % Change name and information from metabolite to replacement metabolite -0034 metIdx = find(strcmp(metabolite,model.metNames)); -0035 if isempty(metIdx) -0036 EM='The to-be-replaced metabolite name cannot be found in the model.' -0037 dispEM(EM,true); -0038 end -0039 if verbose==true -0040 fprintf('\n\nThe following reactions contain the replaced metabolite as reactant:\n') -0041 fprintf(strjoin(model.rxns(find(model.S(metIdx,:))),'\n')) -0042 fprintf('\n') -0043 end -0044 model.metNames(metIdx) = model.metNames(repIdx(1)); -0045 if isfield(model,'metFormulas') -0046 model.metFormulas(metIdx) = model.metFormulas(repIdx(1)); -0047 end -0048 if isfield(model,'metMiriams') -0049 model.metMiriams(metIdx) = model.metMiriams(repIdx(1)); -0050 end -0051 if isfield(model,'metCharges') -0052 model.metCharges(metIdx) = model.metCharges(repIdx(1)); -0053 end -0054 if isfield(model,'inchis') -0055 model.inchis(metIdx) = model.inchis(repIdx(1)); -0056 end -0057 % Run through replacement metabolites and their compartments. If any of the -0058 % to-be-replaced metabolites is already present (checked by -0059 % metaboliteName[compartment], then the replacement metabolite is kept and -0060 % the to-be-replace metabolite ID deleted. -0061 -0062 % Build list of metaboliteName[compartment] -0063 metCompsN =cellstr(num2str(model.metComps)); -0064 map = containers.Map(cellstr(num2str(transpose(1:length(model.comps)))),model.comps); -0065 metCompsN = map.values(metCompsN); -0066 metCompsN = strcat(lower(model.metNames),'[',metCompsN,']'); -0067 -0068 idxDelete=[]; -0069 for i = 1:length(repIdx) -0070 metCompsNidx=find(strcmp(metCompsN(repIdx(i)), metCompsN)); -0071 if gt(length(metCompsNidx),1) % If more than 1 metabolite matches -0072 model.S(metCompsNidx(1),:) = model.S(metCompsNidx(1),:) + model.S(metCompsNidx(2:end),:); -0073 idxDelete=[idxDelete; metCompsNidx(2:end)]; % Make list of metabolite IDs to delete -0074 end -0075 end -0076 -0077 if ~isempty(idxDelete) -0078 model.S(idxDelete,:) =[]; -0079 model.mets(idxDelete) = []; -0080 model.metNames(idxDelete) = []; -0081 model.metComps(idxDelete) = []; -0082 model.b(idxDelete) = []; -0083 if isfield(model,'metFormulas') -0084 model.metFormulas(idxDelete) = []; -0085 end -0086 if isfield(model,'unconstrained') -0087 model.unconstrained(idxDelete) = []; +0020 metabolite=char(metabolite); +0021 replacement=char(replacement); +0022 +0023 if nargin<4 +0024 verbose=false; +0025 end +0026 +0027 % Find occurence of replacement metabolites. Annotation will be taken from +0028 % first metabolite found. Metabolite ID from replacement will be used where +0029 % possible. +0030 repIdx = find(strcmp(replacement,model.metNames)); +0031 if isempty(repIdx) +0032 error('The replacement metabolite name cannot be found in the model.'); +0033 end +0034 +0035 % Change name and information from metabolite to replacement metabolite +0036 metIdx = find(strcmp(metabolite,model.metNames)); +0037 if isempty(metIdx) +0038 error('The to-be-replaced metabolite name cannot be found in the model.'); +0039 end +0040 if verbose==true +0041 fprintf('\n\nThe following reactions contain the replaced metabolite as reactant:\n') +0042 fprintf(strjoin(model.rxns(find(model.S(metIdx,:))),'\n')) +0043 fprintf('\n') +0044 end +0045 model.metNames(metIdx) = model.metNames(repIdx(1)); +0046 if isfield(model,'metFormulas') +0047 model.metFormulas(metIdx) = model.metFormulas(repIdx(1)); +0048 end +0049 if isfield(model,'metMiriams') +0050 model.metMiriams(metIdx) = model.metMiriams(repIdx(1)); +0051 end +0052 if isfield(model,'metCharges') +0053 model.metCharges(metIdx) = model.metCharges(repIdx(1)); +0054 end +0055 if isfield(model,'inchis') +0056 model.inchis(metIdx) = model.inchis(repIdx(1)); +0057 end +0058 % Run through replacement metabolites and their compartments. If any of the +0059 % to-be-replaced metabolites is already present (checked by +0060 % metaboliteName[compartment], then the replacement metabolite is kept and +0061 % the to-be-replace metabolite ID deleted. +0062 +0063 % Build list of metaboliteName[compartment] +0064 metCompsN =cellstr(num2str(model.metComps)); +0065 map = containers.Map(cellstr(num2str(transpose(1:length(model.comps)))),model.comps); +0066 metCompsN = map.values(metCompsN); +0067 metCompsN = strcat(lower(model.metNames),'[',metCompsN,']'); +0068 +0069 idxDelete=[]; +0070 for i = 1:length(repIdx) +0071 metCompsNidx=find(strcmp(metCompsN(repIdx(i)), metCompsN)); +0072 if length(metCompsNidx)>1 +0073 for j = 2:length(metCompsNidx) +0074 model.S(metCompsNidx(1),:) = model.S(metCompsNidx(1),:) + model.S(metCompsNidx(j),:); +0075 idxDelete=[idxDelete; metCompsNidx(j)]; % Make list of metabolite IDs to delete +0076 end +0077 end +0078 end +0079 +0080 if ~isempty(idxDelete) +0081 model.S(idxDelete,:) =[]; +0082 model.mets(idxDelete) = []; +0083 model.metNames(idxDelete) = []; +0084 model.metComps(idxDelete) = []; +0085 model.b(idxDelete) = []; +0086 if isfield(model,'metFormulas') +0087 model.metFormulas(idxDelete) = []; 0088 end -0089 if isfield(model,'metMiriams') -0090 model.metMiriams(idxDelete) = []; +0089 if isfield(model,'unconstrained') +0090 model.unconstrained(idxDelete) = []; 0091 end -0092 if isfield(model,'metCharges') -0093 model.metCharges(idxDelete) = []; +0092 if isfield(model,'metMiriams') +0093 model.metMiriams(idxDelete) = []; 0094 end -0095 if isfield(model,'inchis') -0096 model.inchis(idxDelete) = []; +0095 if isfield(model,'metCharges') +0096 model.metCharges(idxDelete) = []; 0097 end -0098 if isfield(model,'metFrom') -0099 model.metFrom(idxDelete) = []; +0098 if isfield(model,'inchis') +0099 model.inchis(idxDelete) = []; 0100 end -0101 end -0102 -0103 % This could now have created duplicate reactions. Contract model. -0104 model=contractModel(model); -0105 end +0101 if isfield(model,'metFrom') +0102 model.metFrom(idxDelete) = []; +0103 end +0104 end +0105 +0106 % This could now have created duplicate reactions. Contract model. +0107 model=contractModel(model); +0108 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/reporterMetabolites.html b/doc/core/reporterMetabolites.html index 4e6ef3b7..3bb937cb 100644 --- a/doc/core/reporterMetabolites.html +++ b/doc/core/reporterMetabolites.html @@ -71,7 +71,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • dispEM dispEM
  • reporterMetabolites reporterMetabolites
  • This function is called by: @@ -121,153 +121,154 @@

    SOURCE CODE ^% Usage: repMets=reporterMetabolites(model,genes,genePValues,printResults,... 0040 % outputFile,geneFoldChanges) 0041 -0042 if nargin<4 -0043 printResults=false; -0044 end -0045 if nargin<5 -0046 outputFile=[]; -0047 end -0048 if nargin<6 -0049 geneFoldChanges=[]; -0050 end -0051 -0052 %Check some stuff -0053 if numel(genes)~=numel(genePValues) -0054 EM='The number of genes and the number of Z-scores must be the same'; -0055 dispEM(EM); -0056 end -0057 if ~isfield(model,'rxnGeneMat') -0058 EM='The model structure must have a rxnGeneMat field'; -0059 dispEM(EM); -0060 end -0061 -0062 %Remove the genes which are not in the model -0063 genePValues(~ismember(genes,model.genes))=[]; -0064 if any(geneFoldChanges) -0065 geneFoldChanges(~ismember(genes,model.genes))=[]; -0066 end -0067 genes(~ismember(genes,model.genes))=[]; -0068 -0069 %Remove the genes that has NA P-value -0070 genes(isnan(genePValues))=[]; -0071 if any(geneFoldChanges) -0072 geneFoldChanges(isnan(genePValues))=[]; -0073 end -0074 genePValues(isnan(genePValues))=[]; -0075 -0076 %Convert p-values to Z-scores -0077 geneZScores=norminv(genePValues)*-1; -0078 -0079 %This is to prevent errors if the p-values are exactly 0 or 1 -0080 geneZScores(geneZScores==-inf)=-15; -0081 geneZScores(geneZScores==inf)=15; -0082 -0083 %For each metabolite, calculate the aggregate Z-score and keep track of the -0084 %number of neighbouring genes -0085 metZScores=nan(numel(model.mets),1); -0086 metNGenes=nan(numel(model.mets),1); -0087 meanZ=nan(numel(model.mets),1); -0088 stdZ=nan(numel(model.mets),1); -0089 for i=1:numel(model.mets) -0090 %Get the involved rxns -0091 I=model.S(i,:); -0092 -0093 %Get the involved genes -0094 [~, J]=find(model.rxnGeneMat(I~=0,:)); -0095 -0096 %Find the genes in the gene list -0097 K=find(ismember(genes,model.genes(J))); -0098 -0099 %Calculate the aggregated Z-score for the metabolite -0100 if any(K) -0101 metZScores(i)=sum(geneZScores(K))/sqrt(numel(K)); -0102 meanZ(i)=mean(geneZScores(K)); -0103 stdZ(i)=std(geneZScores(K)); -0104 metNGenes(i)=numel(K); -0105 end -0106 end -0107 -0108 %Remove the metabolites which have no Z-scores -0109 mets=model.mets(~isnan(metZScores)); -0110 metNames=model.metNames(~isnan(metZScores)); -0111 metZScores(isnan(metZScores))=[]; -0112 metNGenes(isnan(metNGenes))=[]; -0113 meanZ(isnan(meanZ))=[]; -0114 stdZ(isnan(stdZ))=[]; -0115 -0116 %Then correct for background by calculating the mean Z-score for random -0117 %sets of the same size as the ones that were found for the metabolites -0118 sizes=unique(metNGenes); -0119 nGenes=numel(genes); -0120 -0121 for i=1:numel(sizes) -0122 %Sample 100000 sets for each size. Sample with replacement, which may -0123 %or may not be the best choice. -0124 I=ceil(rand(100000,sizes(i))*nGenes); -0125 J=geneZScores(I); -0126 K=sum(J,2)/sqrt(sizes(i)); -0127 -0128 %Correct all elements of this size -0129 mK=mean(K); -0130 stdK=std(K); -0131 metZScores(metNGenes==sizes(i))=(metZScores(metNGenes==sizes(i))-mK)/stdK; -0132 end -0133 -0134 %Calculate the P-values -0135 metPValues=1-normcdf(metZScores); -0136 -0137 %Sort the results -0138 [metZScores, I]=sort(metZScores,'descend'); -0139 mets=mets(I); -0140 metNames=metNames(I); -0141 metPValues=metPValues(I); -0142 metNGenes=metNGenes(I); -0143 meanZ=meanZ(I); -0144 stdZ=stdZ(I); -0145 -0146 %Prepare the output -0147 repMets.mets=mets; -0148 repMets.metNames=metNames; -0149 repMets.metZScores=metZScores; -0150 repMets.metPValues=metPValues; -0151 repMets.metNGenes=metNGenes; -0152 repMets.meanZ=meanZ; -0153 repMets.stdZ=stdZ; -0154 -0155 %Call this function recursively if geneFoldChanges has been specified -0156 repMets(1).test='all'; -0157 if any(geneFoldChanges) -0158 repMets=[repMets;reporterMetabolites(model,genes(geneFoldChanges>=0),genePValues(geneFoldChanges>=0))]; -0159 repMets=[repMets;reporterMetabolites(model,genes(geneFoldChanges<0),genePValues(geneFoldChanges<0))]; -0160 repMets(2).test='only up'; -0161 repMets(3).test='only down'; -0162 end -0163 -0164 %This is for printing results to the screen. For printing a full list of -0165 %all scores, specify a output file -0166 if printResults==true -0167 for i=1:numel(repMets) -0168 fprintf(['TOP 20 REPORTER METABOLITES\nTEST TYPE: ' repMets(i).test '\nID\tNAME\tP-VALUE\n']); -0169 for j=1:min(20,numel(repMets(i).mets)) -0170 fprintf([repMets(i).mets{j} '\t' repMets(i).metNames{j} '\t' num2str(repMets(i).metPValues(j)) '\n']); -0171 end -0172 fprintf('\n'); -0173 end -0174 end -0175 -0176 %Print results to file -0177 if any(outputFile) -0178 fid=fopen(outputFile,'w'); -0179 for i=1:numel(repMets) -0180 fprintf(fid,['REPORTER METABOLITES USING TEST TYPE: ' repMets(i).test '\n']); -0181 fprintf(fid,'ID\tNAME\tZ-SCORE\tP-VALUE\tNUMBER OF NEIGHBOURS\tAVERAGE Z-SCORE\tSTD Z-SCORE\n'); -0182 for j=1:numel(repMets(i).mets) -0183 fprintf(fid,[repMets(i).mets{j} '\t' repMets(i).metNames{j} '\t' num2str(repMets(i).metZScores(j)) '\t' num2str(repMets(i).metPValues(j)) '\t' num2str(repMets(i).metNGenes(j)) '\t' num2str(repMets(i).meanZ(j)) '\t' num2str(repMets(i).stdZ(j)) '\n']); -0184 end -0185 end -0186 fclose(fid); -0187 end -0188 end +0042 genes=convertCharArray(genes); +0043 if nargin<4 +0044 printResults=false; +0045 end +0046 if nargin<5 +0047 outputFile=[]; +0048 end +0049 if nargin<6 +0050 geneFoldChanges=[]; +0051 end +0052 +0053 %Check some stuff +0054 if numel(genes)~=numel(genePValues) +0055 EM='The number of genes and the number of Z-scores must be the same'; +0056 dispEM(EM); +0057 end +0058 if ~isfield(model,'rxnGeneMat') +0059 EM='The model structure must have a rxnGeneMat field'; +0060 dispEM(EM); +0061 end +0062 +0063 %Remove the genes which are not in the model +0064 genePValues(~ismember(genes,model.genes))=[]; +0065 if any(geneFoldChanges) +0066 geneFoldChanges(~ismember(genes,model.genes))=[]; +0067 end +0068 genes(~ismember(genes,model.genes))=[]; +0069 +0070 %Remove the genes that has NA P-value +0071 genes(isnan(genePValues))=[]; +0072 if any(geneFoldChanges) +0073 geneFoldChanges(isnan(genePValues))=[]; +0074 end +0075 genePValues(isnan(genePValues))=[]; +0076 +0077 %Convert p-values to Z-scores +0078 geneZScores=norminv(genePValues)*-1; +0079 +0080 %This is to prevent errors if the p-values are exactly 0 or 1 +0081 geneZScores(geneZScores==-inf)=-15; +0082 geneZScores(geneZScores==inf)=15; +0083 +0084 %For each metabolite, calculate the aggregate Z-score and keep track of the +0085 %number of neighbouring genes +0086 metZScores=nan(numel(model.mets),1); +0087 metNGenes=nan(numel(model.mets),1); +0088 meanZ=nan(numel(model.mets),1); +0089 stdZ=nan(numel(model.mets),1); +0090 for i=1:numel(model.mets) +0091 %Get the involved rxns +0092 I=model.S(i,:); +0093 +0094 %Get the involved genes +0095 [~, J]=find(model.rxnGeneMat(I~=0,:)); +0096 +0097 %Find the genes in the gene list +0098 K=find(ismember(genes,model.genes(J))); +0099 +0100 %Calculate the aggregated Z-score for the metabolite +0101 if any(K) +0102 metZScores(i)=sum(geneZScores(K))/sqrt(numel(K)); +0103 meanZ(i)=mean(geneZScores(K)); +0104 stdZ(i)=std(geneZScores(K)); +0105 metNGenes(i)=numel(K); +0106 end +0107 end +0108 +0109 %Remove the metabolites which have no Z-scores +0110 mets=model.mets(~isnan(metZScores)); +0111 metNames=model.metNames(~isnan(metZScores)); +0112 metZScores(isnan(metZScores))=[]; +0113 metNGenes(isnan(metNGenes))=[]; +0114 meanZ(isnan(meanZ))=[]; +0115 stdZ(isnan(stdZ))=[]; +0116 +0117 %Then correct for background by calculating the mean Z-score for random +0118 %sets of the same size as the ones that were found for the metabolites +0119 sizes=unique(metNGenes); +0120 nGenes=numel(genes); +0121 +0122 for i=1:numel(sizes) +0123 %Sample 100000 sets for each size. Sample with replacement, which may +0124 %or may not be the best choice. +0125 I=ceil(rand(100000,sizes(i))*nGenes); +0126 J=geneZScores(I); +0127 K=sum(J,2)/sqrt(sizes(i)); +0128 +0129 %Correct all elements of this size +0130 mK=mean(K); +0131 stdK=std(K); +0132 metZScores(metNGenes==sizes(i))=(metZScores(metNGenes==sizes(i))-mK)/stdK; +0133 end +0134 +0135 %Calculate the P-values +0136 metPValues=1-normcdf(metZScores); +0137 +0138 %Sort the results +0139 [metZScores, I]=sort(metZScores,'descend'); +0140 mets=mets(I); +0141 metNames=metNames(I); +0142 metPValues=metPValues(I); +0143 metNGenes=metNGenes(I); +0144 meanZ=meanZ(I); +0145 stdZ=stdZ(I); +0146 +0147 %Prepare the output +0148 repMets.mets=mets; +0149 repMets.metNames=metNames; +0150 repMets.metZScores=metZScores; +0151 repMets.metPValues=metPValues; +0152 repMets.metNGenes=metNGenes; +0153 repMets.meanZ=meanZ; +0154 repMets.stdZ=stdZ; +0155 +0156 %Call this function recursively if geneFoldChanges has been specified +0157 repMets(1).test='all'; +0158 if any(geneFoldChanges) +0159 repMets=[repMets;reporterMetabolites(model,genes(geneFoldChanges>=0),genePValues(geneFoldChanges>=0))]; +0160 repMets=[repMets;reporterMetabolites(model,genes(geneFoldChanges<0),genePValues(geneFoldChanges<0))]; +0161 repMets(2).test='only up'; +0162 repMets(3).test='only down'; +0163 end +0164 +0165 %This is for printing results to the screen. For printing a full list of +0166 %all scores, specify a output file +0167 if printResults==true +0168 for i=1:numel(repMets) +0169 fprintf(['TOP 20 REPORTER METABOLITES\nTEST TYPE: ' repMets(i).test '\nID\tNAME\tP-VALUE\n']); +0170 for j=1:min(20,numel(repMets(i).mets)) +0171 fprintf([repMets(i).mets{j} '\t' repMets(i).metNames{j} '\t' num2str(repMets(i).metPValues(j)) '\n']); +0172 end +0173 fprintf('\n'); +0174 end +0175 end +0176 +0177 %Print results to file +0178 if any(outputFile) +0179 fid=fopen(outputFile,'w'); +0180 for i=1:numel(repMets) +0181 fprintf(fid,['REPORTER METABOLITES USING TEST TYPE: ' repMets(i).test '\n']); +0182 fprintf(fid,'ID\tNAME\tZ-SCORE\tP-VALUE\tNUMBER OF NEIGHBOURS\tAVERAGE Z-SCORE\tSTD Z-SCORE\n'); +0183 for j=1:numel(repMets(i).mets) +0184 fprintf(fid,[repMets(i).mets{j} '\t' repMets(i).metNames{j} '\t' num2str(repMets(i).metZScores(j)) '\t' num2str(repMets(i).metPValues(j)) '\t' num2str(repMets(i).metNGenes(j)) '\t' num2str(repMets(i).meanZ(j)) '\t' num2str(repMets(i).stdZ(j)) '\n']); +0185 end +0186 end +0187 fclose(fid); +0188 end +0189 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/setExchangeBounds.html b/doc/core/setExchangeBounds.html index 73bf7bf5..b78f283b 100644 --- a/doc/core/setExchangeBounds.html +++ b/doc/core/setExchangeBounds.html @@ -78,7 +78,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • getExchangeRxns getExchangeRxns
  • setParam setParam
  • This function is called by: @@ -139,8 +139,8 @@

    SOURCE CODE ^% handle input arguments 0051 if nargin < 2 0052 mets = []; -0053 elseif ischar(mets) -0054 mets = {mets}; % in case only one metabolite is provided as a string +0053 elseif ~islogical(mets) || ~isnumeric(mets) +0054 mets=convertCharArray(mets); 0055 end 0056 0057 if nargin < 3 || isempty(lb) @@ -275,8 +275,8 @@

    SOURCE CODE ^% check for any metabolites that are exchanged in more than one reaction -0189 tbl = tabulate(metInd); -0190 repeatedInds = tbl(:,2) > 1; +0189 [tbl,i,~] = unique(metInd,'first'); +0190 repeatedInds = find(not(ismember(1:numel(tbl),i))); 0191 multiMetInd = exchMetInd(metInd(repeatedInds)); 0192 if ~isempty(multiMetInd) 0193 fprintf('WARNING: The following metabolites are involved in more than one exchange reaction:\n'); diff --git a/doc/core/setParam.html b/doc/core/setParam.html index ce068dfd..095b80a2 100644 --- a/doc/core/setParam.html +++ b/doc/core/setParam.html @@ -55,7 +55,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • dispEM dispEM
  • This function is called by: @@ -89,95 +89,88 @@

    SOURCE CODE ^% 0024 % Usage: model=setParam(model, paramType, rxnList, params) 0025 -0026 if ~isempty(setdiff(paramType,{'lb';'ub';'eq';'obj';'rev';'var'})) -0027 EM=['Incorrect parameter type: "' paramType '"']; -0028 dispEM(EM); -0029 end -0030 -0031 %Allow to set several parameters to the same value -0032 if numel(rxnList)~=numel(params) && numel(params)~=1 -0033 EM='The number of parameter values and the number of reactions must be the same'; -0034 dispEM(EM); -0035 end -0036 -0037 if isnumeric(rxnList) || islogical(rxnList) -0038 rxnList=model.rxns(rxnList); -0039 elseif ischar(rxnList) -0040 rxnList={rxnList}; -0041 end -0042 -0043 if ischar(paramType) -0044 paramType={paramType}; -0045 end -0046 -0047 if isnumeric(params) -0048 params=[params]; -0049 end -0050 -0051 if length(rxnList)>1 -0052 if length(paramType)==1 -0053 paramType(1:length(rxnList))=paramType; -0054 end -0055 if length(params)==1 -0056 params(1:length(rxnList))=params; -0057 end -0058 end -0059 -0060 %Find the indexes for the reactions in rxnList. Do not use getIndexes -0061 %as we do not want to throw errors if matches fail -0062 indexes=zeros(numel(rxnList),1); -0063 -0064 for i=1:numel(rxnList) -0065 index=find(strcmp(rxnList{i},model.rxns),1); -0066 if ~isempty(index) -0067 indexes(i)=index; -0068 else -0069 indexes(i)=-1; -0070 EM=['Reaction ' rxnList{i} ' is not present in the reaction list']; -0071 dispEM(EM,false); -0072 end -0073 end -0074 -0075 %Remove the reactions that were not found -0076 params(indexes==-1)=[]; -0077 indexes(indexes==-1)=[]; -0078 paramType(indexes==-1)=[]; -0079 %Change the parameters -0080 -0081 if ~isempty(indexes) -0082 if contains(paramType,'obj') -0083 model.c=zeros(numel(model.c),1); % parameter is changed, not added -0084 end -0085 for j=1:length(paramType) -0086 if strcmpi(paramType{j},'eq') -0087 model.lb(indexes(j))=params(j); -0088 model.ub(indexes(j))=params(j); -0089 end -0090 if strcmpi(paramType{j},'lb') -0091 model.lb(indexes(j))=params(j); -0092 end -0093 if strcmpi(paramType{j},'ub') -0094 model.ub(indexes(j))=params(j); +0026 paramType=convertCharArray(paramType); +0027 if ~isempty(setdiff(paramType,{'lb';'ub';'eq';'obj';'rev';'var'})) +0028 EM=['Incorrect parameter type: "' paramType '"']; +0029 dispEM(EM); +0030 end +0031 +0032 if isnumeric(rxnList) || islogical(rxnList) +0033 rxnList=model.rxns(rxnList); +0034 else +0035 rxnList=convertCharArray(rxnList); +0036 end +0037 +0038 %Allow to set several parameters to the same value +0039 if numel(rxnList)~=numel(params) && numel(params)~=1 +0040 EM='The number of parameter values and the number of reactions must be the same'; +0041 dispEM(EM); +0042 end +0043 +0044 if length(rxnList)>1 +0045 if length(paramType)==1 +0046 paramType(1:length(rxnList))=paramType; +0047 end +0048 if length(params)==1 +0049 params(1:length(rxnList))=params; +0050 end +0051 end +0052 +0053 %Find the indexes for the reactions in rxnList. Do not use getIndexes +0054 %as we do not want to throw errors if matches fail +0055 indexes=zeros(numel(rxnList),1); +0056 +0057 for i=1:numel(rxnList) +0058 index=find(strcmp(rxnList{i},model.rxns),1); +0059 if ~isempty(index) +0060 indexes(i)=index; +0061 else +0062 indexes(i)=-1; +0063 EM=['Reaction ' rxnList{i} ' is not present in the reaction list']; +0064 dispEM(EM,false); +0065 end +0066 end +0067 +0068 %Remove the reactions that were not found +0069 params(indexes==-1)=[]; +0070 indexes(indexes==-1)=[]; +0071 paramType(indexes==-1)=[]; +0072 %Change the parameters +0073 +0074 if ~isempty(indexes) +0075 if contains(paramType,'obj') +0076 model.c=zeros(numel(model.c),1); % parameter is changed, not added +0077 end +0078 for j=1:length(paramType) +0079 if strcmpi(paramType{j},'eq') +0080 model.lb(indexes(j))=params(j); +0081 model.ub(indexes(j))=params(j); +0082 end +0083 if strcmpi(paramType{j},'lb') +0084 model.lb(indexes(j))=params(j); +0085 end +0086 if strcmpi(paramType{j},'ub') +0087 model.ub(indexes(j))=params(j); +0088 end +0089 if strcmpi(paramType{j},'obj') +0090 model.c(indexes(j))=params(j); +0091 end +0092 if strcmpi(paramType{j},'rev') +0093 %Non-zero values are interpreted as reversible +0094 model.rev(indexes(j))=params(j)~=0; 0095 end -0096 if strcmpi(paramType{j},'obj') -0097 model.c(indexes(j))=params(j); -0098 end -0099 if strcmpi(paramType{j},'rev') -0100 %Non-zero values are interpreted as reversible -0101 model.rev(indexes(j))=params(j)~=0; -0102 end -0103 if strcmpi(paramType{j},'var') -0104 if params(j) < 0 -0105 model.lb(indexes(j)) = params(j) * (1+var/200); -0106 model.ub(indexes(j)) = params(j) * (1-var/200); -0107 else -0108 model.lb(indexes(j)) = params(j) * (1-var/200); -0109 model.ub(indexes(j)) = params(j) * (1+var/200); -0110 end -0111 end -0112 end -0113 end -0114 end +0096 if strcmpi(paramType{j},'var') +0097 if params(j) < 0 +0098 model.lb(indexes(j)) = params(j) * (1+var/200); +0099 model.ub(indexes(j)) = params(j) * (1-var/200); +0100 else +0101 model.lb(indexes(j)) = params(j) * (1-var/200); +0102 model.ub(indexes(j)) = params(j) * (1+var/200); +0103 end +0104 end +0105 end +0106 end +0107 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/simplifyModel.html b/doc/core/simplifyModel.html index f27f7c5e..f41cd684 100644 --- a/doc/core/simplifyModel.html +++ b/doc/core/simplifyModel.html @@ -67,7 +67,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • contractModel contractModel
  • convertCharArray convertCharArray
  • convertToIrrev convertToIrrev
  • dispEM dispEM
  • getAllowedBounds getAllowedBounds
  • getIndexes getIndexes
  • haveFlux haveFlux
  • removeMets removeMets
  • removeReactions removeReactions
  • This function is called by: @@ -137,262 +137,264 @@

    SOURCE CODE ^end 0060 if nargin<9 0061 reservedRxns=[]; -0062 end -0063 if nargin<10 -0064 suppressWarnings=false; -0065 end -0066 -0067 reducedModel=model; -0068 deletedReactions={}; -0069 deletedMetabolites={}; -0070 -0071 if deleteUnconstrained==true -0072 if isfield(reducedModel,'unconstrained') -0073 %Remove unbalanced metabolites -0074 deletedMetabolites=reducedModel.mets(reducedModel.unconstrained~=0); -0075 reducedModel=removeMets(reducedModel,reducedModel.unconstrained~=0,false,false,false,true); -0076 reducedModel=rmfield(reducedModel,'unconstrained'); -0077 end -0078 end -0079 -0080 if deleteDuplicates==true -0081 %Delete all but the last occurrence of duplicate reactions. The -0082 %reactions must have the same bounds, reversibility, and objective -0083 %coefficient to be regarded as duplicate -0084 [reducedModel, rxnsToDelete, ~]=contractModel(reducedModel); -0085 deletedReactions=[deletedReactions; rxnsToDelete]; -0086 end -0087 -0088 if deleteZeroInterval==true -0089 %Find all reactions where both LB and UB are 0 -0090 zeroIntervalReactions=and(reducedModel.lb==0,reducedModel.ub==0); -0091 -0092 rxnsToDelete=setdiff(reducedModel.rxns(zeroIntervalReactions),reservedRxns); -0093 deletedReactions=[deletedReactions; rxnsToDelete]; -0094 -0095 %Remove reactions -0096 reducedModel=removeReactions(reducedModel,rxnsToDelete); -0097 -0098 %Find metabolites that no longer are used and delete them -0099 notInUse=sum(reducedModel.S~=0,2)==0; -0100 deletedMetabolites=[deletedMetabolites;reducedModel.mets(notInUse)]; -0101 -0102 %Remove metabolites -0103 reducedModel=removeMets(reducedModel,notInUse); -0104 end -0105 -0106 if deleteInaccessible==true -0107 %Print a warning if exchange metabolites haven't been deleted yet. This -0108 %often means that the only allowed products are the metabolites that -0109 %are taken up be the system -0110 if isfield(reducedModel,'unconstrained') && suppressWarnings==false -0111 EM='Removing dead-end reactions before removing exchange metabolites'; -0112 dispEM(EM,false); -0113 end -0114 -0115 while true -0116 %Find all metabolites that are only reactants or only products. -0117 %Delete those metabolites and reactions. This is done until no more -0118 %such reactions are found -0119 -0120 %Construct a stoichiometric matrix where all reactions are written -0121 %as reversible -0122 -0123 %Add fake exchange reactions if model.b~=0 -0124 in=any(reducedModel.b<0,2); -0125 out=any(reducedModel.b>0,2); -0126 I=speye(numel(reducedModel.mets)); -0127 revS=[reducedModel.S,reducedModel.S(:,reducedModel.rev~=0)*-1 I(:,in) I(:,out)*-1]; -0128 -0129 metUsage=sum(abs(revS')>0); -0130 onlyProducts=sum(revS'>0) == metUsage; -0131 onlyReactants=sum(revS'<0) == metUsage; -0132 -0133 %Also remove metabolites that only participate in one reversible -0134 %reaction Don't remove the ones in one reversible reaction if is -0135 %also has a non-zero coefficient in model.b -0136 notInUse=onlyProducts | onlyReactants | (sum(abs(reducedModel.S')>0)<=1 & (~in & ~out)'); -0137 deletedRxn=false; -0138 if any(notInUse) -0139 %Find their corresponding reactions -0140 rxnsNotInUse=sum(abs(reducedModel.S(notInUse,:))>0,1)>0; -0141 rxnsToDelete=setdiff(reducedModel.rxns(rxnsNotInUse),reservedRxns); -0142 deletedReactions=[deletedReactions; rxnsToDelete]; -0143 -0144 %Remove reactions -0145 reducedModel=removeReactions(reducedModel,rxnsToDelete); -0146 -0147 %Remove metabolites. Recalculate since it could be that some -0148 %cannot be deleted due to reserved rxns -0149 notInUse=sum(reducedModel.S~=0,2)==0; -0150 deletedMetabolites=[deletedMetabolites; reducedModel.mets(notInUse)]; -0151 reducedModel=removeMets(reducedModel,notInUse); -0152 -0153 %It could happen that it just finds reserved reactions and gets -0154 %stuck -0155 if ~isempty(rxnsToDelete) -0156 deletedRxn=true; -0157 end -0158 else -0159 break; -0160 end -0161 if deletedRxn==false -0162 break; -0163 end -0164 end -0165 end -0166 -0167 if deleteMinMax==true -0168 %Get reactions that can't carry fluxes. This should be done -0169 %algebraically if possible -0170 I=~haveFlux(reducedModel); -0171 -0172 %Remove reactions -0173 rxnsToDelete=setdiff(reducedModel.rxns(I),reservedRxns); -0174 deletedReactions=[deletedReactions; rxnsToDelete]; -0175 reducedModel=removeReactions(reducedModel,rxnsToDelete); -0176 -0177 %Remove metabolites -0178 notInUse=sum(reducedModel.S~=0,2)==0; -0179 deletedMetabolites=[deletedMetabolites; reducedModel.mets(notInUse)]; -0180 reducedModel=removeMets(reducedModel,notInUse); -0181 end -0182 -0183 if constrainReversible==true -0184 revs=find(reducedModel.rev); -0185 [I,J]=getAllowedBounds(reducedModel,revs); -0186 -0187 I=abs(I); -0188 J=abs(J); -0189 -0190 %Get the "small" values -0191 K=I<10^-10; -0192 L=J<10^-10; -0193 -0194 %Keep the values where only one direction is zero (small) -0195 I(K==L)=[]; -0196 J(K==L)=[]; -0197 revs(K==L)=[]; -0198 -0199 %Change the reversibility of the remaining reactions -0200 reducedModel.rev(revs(J>10^-10))=0; %Ignore reverse direction -0201 reducedModel.lb(revs(J>10^-10))=0; -0202 -0203 toSwitch=revs(I>10^-10); -0204 reducedModel.rev(toSwitch)=0; %Change directionality -0205 reducedModel.ub(toSwitch)=reducedModel.lb(toSwitch)*-1; -0206 reducedModel.lb(toSwitch)=0; -0207 reducedModel.S(:,toSwitch)=reducedModel.S(:,toSwitch).*-1; -0208 reducedModel.c(toSwitch)=reducedModel.c(toSwitch)*-1; -0209 end -0210 if groupLinear==true -0211 if suppressWarnings==false -0212 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'); -0213 end -0214 -0215 reducedModel.genes={}; -0216 reducedModel.rxnGeneMat=sparse(numel(reducedModel.rxns),0); -0217 reducedModel.grRules(:)={''}; -0218 -0219 if isfield(reducedModel,'geneShortNames') -0220 reducedModel.geneShortNames={}; -0221 end -0222 if isfield(reducedModel,'geneMiriams') -0223 reducedModel.geneMiriams={}; -0224 end -0225 if isfield(reducedModel,'geneComps') -0226 reducedModel.geneComps=[]; -0227 end -0228 -0229 %Convert the model to irreversible -0230 irrevModel=convertToIrrev(reducedModel); -0231 -0232 %Loop through and iteratively group linear reactions -0233 while 1 -0234 %Get the banned reaction indexes. Note that the indexes will change -0235 %in each iteration, but the names will not as they won't be merged -0236 %with any other reaction -0237 bannedIndexes=getIndexes(irrevModel,reservedRxns,'rxns'); -0238 -0239 %Select all metabolites that are only present as reactants/products -0240 %in one reaction -0241 singleNegative=find(sum(irrevModel.S'<0)==1); -0242 singlePositive=find(sum(irrevModel.S'>0)==1); -0243 -0244 %Retrieve the common metabolites -0245 common=intersect(singleNegative,singlePositive); -0246 -0247 mergedSome=false; +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 %Remove unbalanced metabolites +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 %Delete all but the last occurrence of duplicate reactions. The +0084 %reactions must have the same bounds, reversibility, and objective +0085 %coefficient to be regarded as duplicate +0086 [reducedModel, rxnsToDelete, ~]=contractModel(reducedModel); +0087 deletedReactions=[deletedReactions; rxnsToDelete]; +0088 end +0089 +0090 if deleteZeroInterval==true +0091 %Find all reactions where both LB and UB are 0 +0092 zeroIntervalReactions=and(reducedModel.lb==0,reducedModel.ub==0); +0093 +0094 rxnsToDelete=setdiff(reducedModel.rxns(zeroIntervalReactions),reservedRxns); +0095 deletedReactions=[deletedReactions; rxnsToDelete]; +0096 +0097 %Remove reactions +0098 reducedModel=removeReactions(reducedModel,rxnsToDelete); +0099 +0100 %Find metabolites that no longer are used and delete them +0101 notInUse=sum(reducedModel.S~=0,2)==0; +0102 deletedMetabolites=[deletedMetabolites;reducedModel.mets(notInUse)]; +0103 +0104 %Remove metabolites +0105 reducedModel=removeMets(reducedModel,notInUse); +0106 end +0107 +0108 if deleteInaccessible==true +0109 %Print a warning if exchange metabolites haven't been deleted yet. This +0110 %often means that the only allowed products are the metabolites that +0111 %are taken up be the system +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 %Find all metabolites that are only reactants or only products. +0119 %Delete those metabolites and reactions. This is done until no more +0120 %such reactions are found +0121 +0122 %Construct a stoichiometric matrix where all reactions are written +0123 %as reversible +0124 +0125 %Add fake exchange reactions if model.b~=0 +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.rev~=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 %Also remove metabolites that only participate in one reversible +0136 %reaction Don't remove the ones in one reversible reaction if is +0137 %also has a non-zero coefficient in model.b +0138 notInUse=onlyProducts | onlyReactants | (sum(abs(reducedModel.S')>0)<=1 & (~in & ~out)'); +0139 deletedRxn=false; +0140 if any(notInUse) +0141 %Find their corresponding reactions +0142 rxnsNotInUse=sum(abs(reducedModel.S(notInUse,:))>0,1)>0; +0143 rxnsToDelete=setdiff(reducedModel.rxns(rxnsNotInUse),reservedRxns); +0144 deletedReactions=[deletedReactions; rxnsToDelete]; +0145 +0146 %Remove reactions +0147 reducedModel=removeReactions(reducedModel,rxnsToDelete); +0148 +0149 %Remove metabolites. Recalculate since it could be that some +0150 %cannot be deleted due to reserved rxns +0151 notInUse=sum(reducedModel.S~=0,2)==0; +0152 deletedMetabolites=[deletedMetabolites; reducedModel.mets(notInUse)]; +0153 reducedModel=removeMets(reducedModel,notInUse); +0154 +0155 %It could happen that it just finds reserved reactions and gets +0156 %stuck +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 %Get reactions that can't carry fluxes. This should be done +0171 %algebraically if possible +0172 I=~haveFlux(reducedModel); +0173 +0174 %Remove reactions +0175 rxnsToDelete=setdiff(reducedModel.rxns(I),reservedRxns); +0176 deletedReactions=[deletedReactions; rxnsToDelete]; +0177 reducedModel=removeReactions(reducedModel,rxnsToDelete); +0178 +0179 %Remove metabolites +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 %Get the "small" values +0193 K=I<10^-10; +0194 L=J<10^-10; +0195 +0196 %Keep the values where only one direction is zero (small) +0197 I(K==L)=[]; +0198 J(K==L)=[]; +0199 revs(K==L)=[]; +0200 +0201 %Change the reversibility of the remaining reactions +0202 reducedModel.rev(revs(J>10^-10))=0; %Ignore reverse direction +0203 reducedModel.lb(revs(J>10^-10))=0; +0204 +0205 toSwitch=revs(I>10^-10); +0206 reducedModel.rev(toSwitch)=0; %Change directionality +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,'geneMiriams') +0225 reducedModel.geneMiriams={}; +0226 end +0227 if isfield(reducedModel,'geneComps') +0228 reducedModel.geneComps=[]; +0229 end +0230 +0231 %Convert the model to irreversible +0232 irrevModel=convertToIrrev(reducedModel); +0233 +0234 %Loop through and iteratively group linear reactions +0235 while 1 +0236 %Get the banned reaction indexes. Note that the indexes will change +0237 %in each iteration, but the names will not as they won't be merged +0238 %with any other reaction +0239 bannedIndexes=getIndexes(irrevModel,reservedRxns,'rxns'); +0240 +0241 %Select all metabolites that are only present as reactants/products +0242 %in one reaction +0243 singleNegative=find(sum(irrevModel.S'<0)==1); +0244 singlePositive=find(sum(irrevModel.S'>0)==1); +0245 +0246 %Retrieve the common metabolites +0247 common=intersect(singleNegative,singlePositive); 0248 -0249 %Loop through each of them and see if the reactions should be -0250 %merged -0251 for i=1:numel(common) -0252 involvedRxns=find(irrevModel.S(common(i),:)); -0253 -0254 %Check so that one or both of the reactions haven't been merged -0255 %already -0256 if numel(involvedRxns)==2 && isempty(intersect(bannedIndexes,involvedRxns)) -0257 %Calculate how many times the second reaction has to be -0258 %multiplied before being merged with the first -0259 stoichRatio=abs(irrevModel.S(common(i),involvedRxns(1))/irrevModel.S(common(i),involvedRxns(2))); -0260 -0261 %Add the second to the first -0262 irrevModel.S(:,involvedRxns(1))=irrevModel.S(:,involvedRxns(1))+irrevModel.S(:,involvedRxns(2))*stoichRatio; -0263 -0264 %Clear the second reaction -0265 irrevModel.S(:,involvedRxns(2))=0; -0266 -0267 %This is to prevent numerical issues. It should be 0 -0268 %already -0269 irrevModel.S(common(i),involvedRxns(1))=0; -0270 -0271 %At this point the second reaction is certain to be deleted -0272 %in a later step and can therefore be ignored -0273 -0274 %Recalculate the bounds for the new reaction. This can be -0275 %problematic since the scale of the bounds may change -0276 %dramatically. Let the most constraining reaction determine -0277 %the new bound -0278 lb1=irrevModel.lb(involvedRxns(1)); -0279 lb2=irrevModel.lb(involvedRxns(2)); -0280 ub1=irrevModel.ub(involvedRxns(1)); -0281 ub2=irrevModel.ub(involvedRxns(2)); -0282 -0283 if lb2~=-inf -0284 irrevModel.lb(involvedRxns(1))=max(lb1,lb2/stoichRatio); -0285 end -0286 if ub2~=inf -0287 irrevModel.ub(involvedRxns(1))=min(ub1,ub2/stoichRatio); -0288 end -0289 -0290 %Then recalculate the objective coefficient. The resulting -0291 %coefficient is the weighted sum of the previous -0292 irrevModel.c(involvedRxns(1))=irrevModel.c(involvedRxns(1))+irrevModel.c(involvedRxns(2))*stoichRatio; -0293 -0294 %Iterate again -0295 mergedSome=true; -0296 end -0297 end -0298 -0299 %All possible reactions merged -0300 if mergedSome==false -0301 break; -0302 end -0303 -0304 %Now delete all reactions that involve no metabolites -0305 I=find(sum(irrevModel.S~=0)==0); -0306 -0307 %Remove reactions -0308 irrevModel=removeReactions(irrevModel,I); -0309 -0310 %Remove metabolites -0311 notInUse=sum(irrevModel.S~=0,2)==0; -0312 irrevModel=removeMets(irrevModel,notInUse); -0313 end -0314 -0315 reducedModel=irrevModel; -0316 end -0317 end +0249 mergedSome=false; +0250 +0251 %Loop through each of them and see if the reactions should be +0252 %merged +0253 for i=1:numel(common) +0254 involvedRxns=find(irrevModel.S(common(i),:)); +0255 +0256 %Check so that one or both of the reactions haven't been merged +0257 %already +0258 if numel(involvedRxns)==2 && isempty(intersect(bannedIndexes,involvedRxns)) +0259 %Calculate how many times the second reaction has to be +0260 %multiplied before being merged with the first +0261 stoichRatio=abs(irrevModel.S(common(i),involvedRxns(1))/irrevModel.S(common(i),involvedRxns(2))); +0262 +0263 %Add the second to the first +0264 irrevModel.S(:,involvedRxns(1))=irrevModel.S(:,involvedRxns(1))+irrevModel.S(:,involvedRxns(2))*stoichRatio; +0265 +0266 %Clear the second reaction +0267 irrevModel.S(:,involvedRxns(2))=0; +0268 +0269 %This is to prevent numerical issues. It should be 0 +0270 %already +0271 irrevModel.S(common(i),involvedRxns(1))=0; +0272 +0273 %At this point the second reaction is certain to be deleted +0274 %in a later step and can therefore be ignored +0275 +0276 %Recalculate the bounds for the new reaction. This can be +0277 %problematic since the scale of the bounds may change +0278 %dramatically. Let the most constraining reaction determine +0279 %the new bound +0280 lb1=irrevModel.lb(involvedRxns(1)); +0281 lb2=irrevModel.lb(involvedRxns(2)); +0282 ub1=irrevModel.ub(involvedRxns(1)); +0283 ub2=irrevModel.ub(involvedRxns(2)); +0284 +0285 if lb2~=-inf +0286 irrevModel.lb(involvedRxns(1))=max(lb1,lb2/stoichRatio); +0287 end +0288 if ub2~=inf +0289 irrevModel.ub(involvedRxns(1))=min(ub1,ub2/stoichRatio); +0290 end +0291 +0292 %Then recalculate the objective coefficient. The resulting +0293 %coefficient is the weighted sum of the previous +0294 irrevModel.c(involvedRxns(1))=irrevModel.c(involvedRxns(1))+irrevModel.c(involvedRxns(2))*stoichRatio; +0295 +0296 %Iterate again +0297 mergedSome=true; +0298 end +0299 end +0300 +0301 %All possible reactions merged +0302 if mergedSome==false +0303 break; +0304 end +0305 +0306 %Now delete all reactions that involve no metabolites +0307 I=find(sum(irrevModel.S~=0)==0); +0308 +0309 %Remove reactions +0310 irrevModel=removeReactions(irrevModel,I); +0311 +0312 %Remove metabolites +0313 notInUse=sum(irrevModel.S~=0,2)==0; +0314 irrevModel=removeMets(irrevModel,notInUse); +0315 end +0316 +0317 reducedModel=irrevModel; +0318 end +0319 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/sortModel.html b/doc/core/sortModel.html index 467f5505..29e489bf 100644 --- a/doc/core/sortModel.html +++ b/doc/core/sortModel.html @@ -135,7 +135,7 @@

    SOURCE CODE ^end 0074 end 0075 subsystemsUnique=unique(subsystemsUnique); -0076 for i=1:numel(subsystems) +0076 for i=1:numel(subsystemsUnique) 0077 %Get all reactions for that subsystem 0078 rxns=find(~cellfun(@isempty,regexp(subsystemsConcatenated,subsystemsUnique(i)))); 0079 diff --git a/doc/core/standardizeGrRules.html b/doc/core/standardizeGrRules.html index f8091f7f..d4f6fc7d 100644 --- a/doc/core/standardizeGrRules.html +++ b/doc/core/standardizeGrRules.html @@ -56,7 +56,7 @@

    CROSS-REFERENCE INFORMATION ^
 <li><a href=dispEM dispEM This function is called by: +
  • addRxns addRxns
  • changeGrRules changeGrRules
  • contractModel contractModel
  • expandModel expandModel
  • getModelFromHomology getModelFromHomology
  • mergeModels mergeModels
  • predictLocalization predictLocalization
  • removeGenes removeGenes
  • SUBFUNCTIONS ^

    diff --git a/doc/external/getBlast.html b/doc/external/getBlast.html index aecef88b..36b4feaf 100644 --- a/doc/external/getBlast.html +++ b/doc/external/getBlast.html @@ -122,10 +122,10 @@

    SOURCE CODE ^end 0045 0046 %Everything should be cell arrays -0047 organismID=cellstr(organismID); -0048 fastaFile=cellstr(fastaFile); -0049 modelIDs=cellstr(modelIDs); -0050 refFastaFiles=cellstr(refFastaFiles); +0047 organismID=convertCharArray(organismID); +0048 fastaFile=convertCharArray(fastaFile); +0049 modelIDs=convertCharArray(modelIDs); +0050 refFastaFiles=convertCharArray(refFastaFiles); 0051 0052 %Create blank structures for results 0053 blastStructure=[]; @@ -135,130 +135,128 @@

    SOURCE CODE ^%Get the directory for RAVEN Toolbox. This may not be the easiest or best -0061 %way to do this -0062 [ST, I]=dbstack('-completenames'); -0063 ravenPath=fileparts(fileparts(ST(I).file)); -0064 -0065 %Generate temporary names for BLAST databases and output files -0066 tmpDB=tempname; -0067 outFile=tempname; -0068 -0069 %Check for existence of files. If no full path is specified for a file, -0070 %assume that it is in the current folder -0071 if isrow(refFastaFiles) -0072 files=horzcat(fastaFile,refFastaFiles); -0073 else -0074 files=vertcat(fastaFile,refFastaFiles); -0075 end -0076 -0077 files=checkFileExistence(files,2); %Copy files to temp dir -0078 fastaFile = files(1); -0079 refFastaFiles = files(2:end); -0080 -0081 %Identify the operating system -0082 if isunix -0083 if ismac -0084 binEnd='.mac'; -0085 else -0086 binEnd=''; -0087 end -0088 elseif ispc -0089 binEnd='.exe'; -0090 setenv('BLASTDB_LMDB_MAP_SIZE','1000000'); -0091 else -0092 dispEM('Unknown OS, exiting.') -0093 return -0094 end -0095 -0096 %Run BLAST multi-threaded to use all logical cores assigned to MATLAB -0097 cores = evalc('feature(''numcores'')'); -0098 cores = strsplit(cores, 'MATLAB was assigned: '); -0099 cores = regexp(cores{2},'^\d*','match'); -0100 cores = cores{1}; -0101 -0102 %Create a database for the new organism and blast each of the refFastaFiles -0103 %against it -0104 [status, ~]=system(['"' fullfile(ravenPath,'software','blast+',['makeblastdb' binEnd]) '" -in ' fastaFile{1} ' -out "' fullfile(tmpDB, 'tmpDB') '" -dbtype prot']); -0105 if develMode -0106 blastReport.dbHashes.phr{numel(blastReport.dbHashes.phr)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.phr')); -0107 blastReport.dbHashes.pot{numel(blastReport.dbHashes.pot)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.pot')); -0108 blastReport.dbHashes.psq{numel(blastReport.dbHashes.psq)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.psq')); -0109 blastReport.dbHashes.pto{numel(blastReport.dbHashes.pto)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.pto')); -0110 end -0111 if status~=0 -0112 EM=['makeblastdb did not run successfully, error: ', num2str(status)]; -0113 dispEM(EM,true); -0114 end -0115 -0116 for i=1:numel(refFastaFiles) -0117 if ~hideVerbose -0118 fprintf(['BLASTing "' modelIDs{i} '" against "' organismID{1} '"..\n']); -0119 end -0120 [status, ~]=system(['"' fullfile(ravenPath,'software','blast+',['blastp' binEnd]) '" -query ' refFastaFiles{i} ' -out "' outFile '_' num2str(i) '" -db "' fullfile(tmpDB, 'tmpDB') '" -evalue 10e-5 -outfmt "10 qseqid sseqid evalue pident length bitscore ppos" -num_threads "' cores '"']); -0121 if develMode -0122 blastReport.blastTxtOutput{numel(blastReport.blastTxtOutput)+1}=importdata([outFile '_' num2str(i)]); -0123 end -0124 if status~=0 -0125 EM=['blastp did not run successfully, error: ', num2str(status)]; -0126 dispEM(EM,true); -0127 end -0128 end -0129 delete([tmpDB filesep 'tmpDB*']); -0130 -0131 %Then create a database for each of the reference organisms and blast the -0132 %new organism against them -0133 for i=1:numel(refFastaFiles) -0134 if ~hideVerbose -0135 fprintf(['BLASTing "' organismID{1} '" against "' modelIDs{i} '"..\n']); -0136 end -0137 [status, ~]=system(['"' fullfile(ravenPath,'software','blast+',['makeblastdb' binEnd]) '" -in ' refFastaFiles{i} ' -out "' fullfile(tmpDB, 'tmpDB') '" -dbtype prot']); -0138 if status~=0 -0139 EM=['makeblastdb did not run successfully, error: ', num2str(status)]; -0140 dispEM(EM,true); -0141 end -0142 [status, ~]=system(['"' fullfile(ravenPath,'software','blast+',['blastp' binEnd]) '" -query ' fastaFile{1} ' -out "' outFile '_r' num2str(i) '" -db "' fullfile(tmpDB, 'tmpDB') '" -evalue 10e-5 -outfmt "10 qseqid sseqid evalue pident length bitscore ppos" -num_threads "' cores '"']); -0143 if develMode -0144 blastReport.dbHashes.phr{numel(blastReport.dbHashes.phr)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.phr')); -0145 blastReport.dbHashes.pot{numel(blastReport.dbHashes.pot)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.pot')); -0146 blastReport.dbHashes.psq{numel(blastReport.dbHashes.psq)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.psq')); -0147 blastReport.dbHashes.pto{numel(blastReport.dbHashes.pto)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.pto')); -0148 blastReport.blastTxtOutput{numel(blastReport.blastTxtOutput)+1}=importdata([outFile '_r' num2str(i)]); -0149 end -0150 if status~=0 -0151 EM=['blastp did not run successfully, error: ', num2str(status)]; -0152 dispEM(EM,true); -0153 end -0154 delete([tmpDB filesep 'tmpDB*']); -0155 end -0156 -0157 %Done with the BLAST, do the parsing of the text files -0158 for i=1:numel(refFastaFiles)*2 -0159 tempStruct=[]; -0160 if i<=numel(refFastaFiles) -0161 tempStruct.fromId=modelIDs{i}; -0162 tempStruct.toId=organismID{1}; -0163 A=readtable([outFile '_' num2str(i)],'Delimiter',',','Format','%s%s%f%f%f%f%f'); -0164 else -0165 tempStruct.fromId=organismID{1}; -0166 tempStruct.toId=modelIDs{i-numel(refFastaFiles)}; -0167 A=readtable([outFile '_r' num2str(i-numel(refFastaFiles))],'Delimiter',',','Format','%s%s%f%f%f%f%f'); -0168 end -0169 tempStruct.fromGenes=A{:,1}; -0170 tempStruct.toGenes=A{:,2}; -0171 tempStruct.evalue=table2array(A(:,3)); -0172 tempStruct.identity=table2array(A(:,4)); -0173 tempStruct.aligLen=table2array(A(:,5)); -0174 tempStruct.bitscore=table2array(A(:,6)); -0175 tempStruct.ppos=table2array(A(:,7)); -0176 blastStructure=[blastStructure tempStruct]; -0177 end -0178 -0179 %Remove the old tempfiles -0180 delete([outFile '*']); -0181 %Remove the temp fasta files -0182 delete(files{:}) -0183 end +0060 %Get the directory for RAVEN Toolbox +0061 ravenPath=findRAVENroot(); +0062 +0063 %Generate temporary names for BLAST databases and output files +0064 tmpDB=tempname; +0065 outFile=tempname; +0066 +0067 %Check for existence of files. If no full path is specified for a file, +0068 %assume that it is in the current folder +0069 if isrow(refFastaFiles) +0070 files=horzcat(fastaFile,refFastaFiles); +0071 else +0072 files=vertcat(fastaFile,refFastaFiles); +0073 end +0074 +0075 files=checkFileExistence(files,2); %Copy files to temp dir +0076 fastaFile = files(1); +0077 refFastaFiles = files(2:end); +0078 +0079 %Identify the operating system +0080 if isunix +0081 if ismac +0082 binEnd='.mac'; +0083 else +0084 binEnd=''; +0085 end +0086 elseif ispc +0087 binEnd='.exe'; +0088 setenv('BLASTDB_LMDB_MAP_SIZE','1000000'); +0089 else +0090 dispEM('Unknown OS, exiting.') +0091 return +0092 end +0093 +0094 %Run BLAST multi-threaded to use all logical cores assigned to MATLAB +0095 cores = evalc('feature(''numcores'')'); +0096 cores = strsplit(cores, 'MATLAB was assigned: '); +0097 cores = regexp(cores{2},'^\d*','match'); +0098 cores = cores{1}; +0099 +0100 %Create a database for the new organism and blast each of the refFastaFiles +0101 %against it +0102 [status, ~]=system(['"' fullfile(ravenPath,'software','blast+',['makeblastdb' binEnd]) '" -in ' fastaFile{1} ' -out "' fullfile(tmpDB, 'tmpDB') '" -dbtype prot']); +0103 if develMode +0104 blastReport.dbHashes.phr{numel(blastReport.dbHashes.phr)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.phr')); +0105 blastReport.dbHashes.pot{numel(blastReport.dbHashes.pot)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.pot')); +0106 blastReport.dbHashes.psq{numel(blastReport.dbHashes.psq)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.psq')); +0107 blastReport.dbHashes.pto{numel(blastReport.dbHashes.pto)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.pto')); +0108 end +0109 if status~=0 +0110 EM=['makeblastdb did not run successfully, error: ', num2str(status)]; +0111 dispEM(EM,true); +0112 end +0113 +0114 for i=1:numel(refFastaFiles) +0115 if ~hideVerbose +0116 fprintf(['BLASTing "' modelIDs{i} '" against "' organismID{1} '"..\n']); +0117 end +0118 [status, ~]=system(['"' fullfile(ravenPath,'software','blast+',['blastp' binEnd]) '" -query ' refFastaFiles{i} ' -out "' outFile '_' num2str(i) '" -db "' fullfile(tmpDB, 'tmpDB') '" -evalue 10e-5 -outfmt "10 qseqid sseqid evalue pident length bitscore ppos" -num_threads "' cores '"']); +0119 if develMode +0120 blastReport.blastTxtOutput{numel(blastReport.blastTxtOutput)+1}=importdata([outFile '_' num2str(i)]); +0121 end +0122 if status~=0 +0123 EM=['blastp did not run successfully, error: ', num2str(status)]; +0124 dispEM(EM,true); +0125 end +0126 end +0127 delete([tmpDB filesep 'tmpDB*']); +0128 +0129 %Then create a database for each of the reference organisms and blast the +0130 %new organism against them +0131 for i=1:numel(refFastaFiles) +0132 if ~hideVerbose +0133 fprintf(['BLASTing "' organismID{1} '" against "' modelIDs{i} '"..\n']); +0134 end +0135 [status, ~]=system(['"' fullfile(ravenPath,'software','blast+',['makeblastdb' binEnd]) '" -in ' refFastaFiles{i} ' -out "' fullfile(tmpDB, 'tmpDB') '" -dbtype prot']); +0136 if status~=0 +0137 EM=['makeblastdb did not run successfully, error: ', num2str(status)]; +0138 dispEM(EM,true); +0139 end +0140 [status, ~]=system(['"' fullfile(ravenPath,'software','blast+',['blastp' binEnd]) '" -query ' fastaFile{1} ' -out "' outFile '_r' num2str(i) '" -db "' fullfile(tmpDB, 'tmpDB') '" -evalue 10e-5 -outfmt "10 qseqid sseqid evalue pident length bitscore ppos" -num_threads "' cores '"']); +0141 if develMode +0142 blastReport.dbHashes.phr{numel(blastReport.dbHashes.phr)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.phr')); +0143 blastReport.dbHashes.pot{numel(blastReport.dbHashes.pot)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.pot')); +0144 blastReport.dbHashes.psq{numel(blastReport.dbHashes.psq)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.psq')); +0145 blastReport.dbHashes.pto{numel(blastReport.dbHashes.pto)+1}=getMD5Hash(fullfile(tmpDB, 'tmpDB.pto')); +0146 blastReport.blastTxtOutput{numel(blastReport.blastTxtOutput)+1}=importdata([outFile '_r' num2str(i)]); +0147 end +0148 if status~=0 +0149 EM=['blastp did not run successfully, error: ', num2str(status)]; +0150 dispEM(EM,true); +0151 end +0152 delete([tmpDB filesep 'tmpDB*']); +0153 end +0154 +0155 %Done with the BLAST, do the parsing of the text files +0156 for i=1:numel(refFastaFiles)*2 +0157 tempStruct=[]; +0158 if i<=numel(refFastaFiles) +0159 tempStruct.fromId=modelIDs{i}; +0160 tempStruct.toId=organismID{1}; +0161 A=readtable([outFile '_' num2str(i)],'Delimiter',',','Format','%s%s%f%f%f%f%f'); +0162 else +0163 tempStruct.fromId=organismID{1}; +0164 tempStruct.toId=modelIDs{i-numel(refFastaFiles)}; +0165 A=readtable([outFile '_r' num2str(i-numel(refFastaFiles))],'Delimiter',',','Format','%s%s%f%f%f%f%f'); +0166 end +0167 tempStruct.fromGenes=A{:,1}; +0168 tempStruct.toGenes=A{:,2}; +0169 tempStruct.evalue=table2array(A(:,3)); +0170 tempStruct.identity=table2array(A(:,4)); +0171 tempStruct.aligLen=table2array(A(:,5)); +0172 tempStruct.bitscore=table2array(A(:,6)); +0173 tempStruct.ppos=table2array(A(:,7)); +0174 blastStructure=[blastStructure tempStruct]; +0175 end +0176 +0177 %Remove the old tempfiles +0178 delete([outFile '*']); +0179 %Remove the temp fasta files +0180 delete(files{:}) +0181 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/getBlastFromExcel.html b/doc/external/getBlastFromExcel.html index 3f3a4900..b456eb5d 100644 --- a/doc/external/getBlastFromExcel.html +++ b/doc/external/getBlastFromExcel.html @@ -96,89 +96,90 @@

    SOURCE CODE ^if ~(exist(blastFile,'file')==2) 0029 error('BLAST result file %s cannot be found',string(blastFile)); 0030 end -0031 -0032 blastStructure=[]; -0033 -0034 %Get a list of model IDs -0035 organisms=cell(numel(models)+1,1); -0036 organisms{1}=organismId; -0037 for i=1:numel(models) -0038 organisms{i+1}=models{i}.id; -0039 end -0040 -0041 %Get all the spreadsheets in the file -0042 [type, sheets]=xlsfinfo(blastFile); -0043 -0044 %Check if the file is a Microsoft Excel Spreadsheet -0045 if ~any(regexp(type,'Excel Spreadsheet')) -0046 EM='The file is not a Microsoft Excel Spreadsheet'; -0047 dispEM(EM); -0048 end -0049 -0050 for i=1:numel(sheets) -0051 %Check if the sheet has the right header and deal with organisms that -0052 %are in "models" -0053 [values,dataSheet]=xlsread(blastFile,i); -0054 labels=dataSheet(1,:); -0055 if strcmpi(labels{3},'E-value') && strcmpi(labels{4},'Alignment length') ... -0056 && strcmpi(labels{5},'Identity') && strcmpi(labels{6},'Bitscore') ... -0057 && strcmpi(labels{7},'PPOS') -0058 %At least one of the organisms must have a model -0059 fromID=find(strcmpi(labels{1},organisms)); -0060 toID=find(strcmpi(labels{2},organisms)); -0061 %Check that the organism ids exist and that one of them is the -0062 %organism of interest -0063 if any(fromID) && any(toID) && (toID==1 || fromID==1) -0064 %Check that no gene ids are empty. This could for example be -0065 %the case if the gene names are wrongly formatted as numbers -0066 %instead of strings -0067 emptyNames=cellfun(@isempty,dataSheet(2:end,1)) | cellfun(@isempty,dataSheet(2:end,2)); -0068 if any(emptyNames) -0069 if all(emptyNames) -0070 EM=['Only empty gene names in sheet from ' organisms{fromID} ' to ' organisms{toID}]; -0071 dispEM(EM); -0072 else -0073 EM=['Empty gene names in sheet from ' organisms{fromID} ' to ' organisms{toID} '. Ignoring genes with empty names']; -0074 dispEM(EM,false); -0075 end -0076 end -0077 blastStructure(numel(blastStructure)+1).toId=organisms{toID}; -0078 blastStructure(numel(blastStructure)).fromId=organisms{fromID}; -0079 blastStructure(numel(blastStructure)).fromGenes=dataSheet(2:end,1); -0080 blastStructure(numel(blastStructure)).toGenes=dataSheet(2:end,2); -0081 blastStructure(numel(blastStructure)).evalue=values(:,1); -0082 blastStructure(numel(blastStructure)).aligLen=values(:,2); -0083 blastStructure(numel(blastStructure)).identity=values(:,3); -0084 blastStructure(numel(blastStructure)).bitscore=values(:,4); -0085 blastStructure(numel(blastStructure)).ppos=values(:,5); -0086 -0087 %Remove matches where any of the values is NaN. This would have -0088 %been done anyways in getModelFromHomology, but it's neater to -0089 %do it here -0090 I=isnan(blastStructure(end).evalue) | isnan(blastStructure(end).aligLen) | isnan(blastStructure(end).identity); -0091 blastStructure(end).fromGenes(I)=[]; -0092 blastStructure(end).toGenes(I)=[]; -0093 blastStructure(end).evalue(I)=[]; -0094 blastStructure(end).aligLen(I)=[]; -0095 blastStructure(end).identity(I)=[]; -0096 blastStructure(end).bitscore(I)=[]; -0097 blastStructure(end).ppos(I)=[]; -0098 else -0099 if isempty(toID) || isempty(fromID) -0100 EM=['The data in sheet ' sheets{i} ' has no corresponding model. Ignoring sheet']; -0101 dispEM(EM,false); -0102 else -0103 EM=['The data in sheet ' sheets{i} ' does not involve the organism of interest. Ignoring sheet']; -0104 dispEM(EM,false); -0105 end -0106 end -0107 else -0108 EM=['The data in sheet ' sheets{i} ' is not correctly formatted. Ignoring sheet']; -0109 dispEM(EM,false); -0110 end -0111 end -0112 -0113 end +0031 organismId=char(organismId); +0032 +0033 blastStructure=[]; +0034 +0035 %Get a list of model IDs +0036 organisms=cell(numel(models)+1,1); +0037 organisms{1}=organismId; +0038 for i=1:numel(models) +0039 organisms{i+1}=models{i}.id; +0040 end +0041 +0042 %Get all the spreadsheets in the file +0043 [type, sheets]=xlsfinfo(blastFile); +0044 +0045 %Check if the file is a Microsoft Excel Spreadsheet +0046 if ~any(regexp(type,'Excel Spreadsheet')) +0047 EM='The file is not a Microsoft Excel Spreadsheet'; +0048 dispEM(EM); +0049 end +0050 +0051 for i=1:numel(sheets) +0052 %Check if the sheet has the right header and deal with organisms that +0053 %are in "models" +0054 [values,dataSheet]=xlsread(blastFile,i); +0055 labels=dataSheet(1,:); +0056 if strcmpi(labels{3},'E-value') && strcmpi(labels{4},'Alignment length') ... +0057 && strcmpi(labels{5},'Identity') && strcmpi(labels{6},'Bitscore') ... +0058 && strcmpi(labels{7},'PPOS') +0059 %At least one of the organisms must have a model +0060 fromID=find(strcmpi(labels{1},organisms)); +0061 toID=find(strcmpi(labels{2},organisms)); +0062 %Check that the organism ids exist and that one of them is the +0063 %organism of interest +0064 if any(fromID) && any(toID) && (toID==1 || fromID==1) +0065 %Check that no gene ids are empty. This could for example be +0066 %the case if the gene names are wrongly formatted as numbers +0067 %instead of strings +0068 emptyNames=cellfun(@isempty,dataSheet(2:end,1)) | cellfun(@isempty,dataSheet(2:end,2)); +0069 if any(emptyNames) +0070 if all(emptyNames) +0071 EM=['Only empty gene names in sheet from ' organisms{fromID} ' to ' organisms{toID}]; +0072 dispEM(EM); +0073 else +0074 EM=['Empty gene names in sheet from ' organisms{fromID} ' to ' organisms{toID} '. Ignoring genes with empty names']; +0075 dispEM(EM,false); +0076 end +0077 end +0078 blastStructure(numel(blastStructure)+1).toId=organisms{toID}; +0079 blastStructure(numel(blastStructure)).fromId=organisms{fromID}; +0080 blastStructure(numel(blastStructure)).fromGenes=dataSheet(2:end,1); +0081 blastStructure(numel(blastStructure)).toGenes=dataSheet(2:end,2); +0082 blastStructure(numel(blastStructure)).evalue=values(:,1); +0083 blastStructure(numel(blastStructure)).aligLen=values(:,2); +0084 blastStructure(numel(blastStructure)).identity=values(:,3); +0085 blastStructure(numel(blastStructure)).bitscore=values(:,4); +0086 blastStructure(numel(blastStructure)).ppos=values(:,5); +0087 +0088 %Remove matches where any of the values is NaN. This would have +0089 %been done anyways in getModelFromHomology, but it's neater to +0090 %do it here +0091 I=isnan(blastStructure(end).evalue) | isnan(blastStructure(end).aligLen) | isnan(blastStructure(end).identity); +0092 blastStructure(end).fromGenes(I)=[]; +0093 blastStructure(end).toGenes(I)=[]; +0094 blastStructure(end).evalue(I)=[]; +0095 blastStructure(end).aligLen(I)=[]; +0096 blastStructure(end).identity(I)=[]; +0097 blastStructure(end).bitscore(I)=[]; +0098 blastStructure(end).ppos(I)=[]; +0099 else +0100 if isempty(toID) || isempty(fromID) +0101 EM=['The data in sheet ' sheets{i} ' has no corresponding model. Ignoring sheet']; +0102 dispEM(EM,false); +0103 else +0104 EM=['The data in sheet ' sheets{i} ' does not involve the organism of interest. Ignoring sheet']; +0105 dispEM(EM,false); +0106 end +0107 end +0108 else +0109 EM=['The data in sheet ' sheets{i} ' is not correctly formatted. Ignoring sheet']; +0110 dispEM(EM,false); +0111 end +0112 end +0113 +0114 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/getDiamond.html b/doc/external/getDiamond.html index 3fff175b..e7c670fa 100644 --- a/doc/external/getDiamond.html +++ b/doc/external/getDiamond.html @@ -124,133 +124,131 @@

    SOURCE CODE ^end 0046 0047 %Everything should be cell arrays -0048 organismID=cellstr(organismID); -0049 fastaFile=cellstr(fastaFile); -0050 modelIDs=cellstr(modelIDs); -0051 refFastaFiles=cellstr(refFastaFiles); +0048 organismID=convertCharArray(organismID); +0049 fastaFile=convertCharArray(fastaFile); +0050 modelIDs=convertCharArray(modelIDs); +0051 refFastaFiles=convertCharArray(refFastaFiles); 0052 0053 %Create blank structures for results 0054 blastStructure=[]; 0055 diamondReport.dbHashes={}; 0056 diamondReport.diamondTxtOutput={}; 0057 -0058 %Get the directory for RAVEN Toolbox. This may not be the easiest or best -0059 %way to do this -0060 [ST, I]=dbstack('-completenames'); -0061 ravenPath=fileparts(fileparts(ST(I).file)); -0062 -0063 %Generate temporary names for DIAMOND databases and output files -0064 tmpDB=tempname; -0065 outFile=tempname; -0066 -0067 %Check for existence of files. If no full path is specified for a file, -0068 %assume that it is in the current folder -0069 if isrow(refFastaFiles) -0070 files=horzcat(fastaFile,refFastaFiles); -0071 else -0072 files=vertcat(fastaFile,refFastaFiles); -0073 end -0074 -0075 files=checkFileExistence(files,2); %Copy files to temp dir -0076 fastaFile = files(1); -0077 refFastaFiles = files(2:end); -0078 -0079 %Identify the operating system -0080 if isunix -0081 if ismac -0082 binEnd='.mac'; -0083 else -0084 binEnd=''; -0085 end -0086 elseif ispc -0087 binEnd='.exe'; -0088 else -0089 dispEM('Unknown OS, exiting.') -0090 return -0091 end -0092 -0093 %Run DIAMOND multi-threaded to use all logical cores assigned to MATLAB. -0094 cores = evalc('feature(''numcores'')'); -0095 cores = strsplit(cores, 'MATLAB was assigned: '); -0096 cores = regexp(cores{2},'^\d*','match'); -0097 cores = cores{1}; -0098 -0099 %Create a database for the new organism and blast each of the refFastaFiles -0100 %against it -0101 [status, message]=system(['"' fullfile(ravenPath,'software','diamond',['diamond' binEnd]) '" makedb --in "' fastaFile{1} '" --db "' fullfile(tmpDB) '"']); -0102 if develMode -0103 diamondReport.dbHashes{numel(diamondReport.dbHashes)+1} = char(regexp(message,'[a-f0-9]{32}','match')); -0104 end -0105 if status~=0 -0106 EM=['DIAMOND makedb did not run successfully, error: ', num2str(status)]; -0107 dispEM(EM,true); -0108 end -0109 -0110 for i=1:numel(refFastaFiles) -0111 if ~hideVerbose -0112 fprintf(['Running DIAMOND blastp with "' modelIDs{i} '" against "' organismID{1} '"..\n']); -0113 end -0114 [status, ~]=system(['"' fullfile(ravenPath,'software','diamond',['diamond' binEnd]) '" blastp --query "' refFastaFiles{i} '" --out "' outFile '_' num2str(i) '" --db "' fullfile(tmpDB) '" --more-sensitive --outfmt 6 qseqid sseqid evalue pident length bitscore ppos --threads ' cores ]); -0115 if develMode -0116 diamondReport.diamondTxtOutput{numel(diamondReport.diamondTxtOutput)+1}=importdata([outFile '_' num2str(i)]); -0117 end -0118 if status~=0 -0119 EM=['DIAMOND blastp did not run successfully, error: ', num2str(status)]; -0120 dispEM(EM,true); -0121 end -0122 end -0123 delete([tmpDB filesep 'tmpDB*']); -0124 -0125 %Then create a database for each of the reference organisms and blast the -0126 %new organism against them -0127 for i=1:numel(refFastaFiles) -0128 if ~hideVerbose -0129 fprintf(['Running DIAMOND blastp with "' organismID{1} '" against "' modelIDs{i} '"..\n']); -0130 end -0131 [status, message]=system(['"' fullfile(ravenPath,'software','diamond',['diamond' binEnd]) '" makedb --in "' refFastaFiles{i} '" --db "' fullfile(tmpDB) '"']); -0132 if status~=0 -0133 EM=['DIAMOND makedb did not run successfully, error: ', num2str(status)]; -0134 dispEM(EM,true); -0135 end -0136 [status, ~]=system(['"' fullfile(ravenPath,'software','diamond',['diamond' binEnd]) '" blastp --query "' fastaFile{1} '" --out "' outFile '_r' num2str(i) '" --db "' fullfile(tmpDB) '" --more-sensitive --outfmt 6 qseqid sseqid evalue pident length bitscore ppos --threads ' cores]); -0137 if develMode -0138 diamondReport.dbHashes{numel(diamondReport.dbHashes)+1} = char(regexp(message,'[a-f0-9]{32}','match')); -0139 diamondReport.diamondTxtOutput{numel(diamondReport.diamondTxtOutput)+1}=importdata([outFile '_r' num2str(i)]); -0140 end -0141 if status~=0 -0142 EM=['DIAMOND blastp did not run successfully, error: ', num2str(status)]; -0143 dispEM(EM,true); -0144 end -0145 delete([tmpDB filesep 'tmpDB*']); -0146 end -0147 -0148 %Done with the DIAMOND blastp, do the parsing of the text files -0149 for i=1:numel(refFastaFiles)*2 -0150 tempStruct=[]; -0151 if i<=numel(refFastaFiles) -0152 tempStruct.fromId=modelIDs{i}; -0153 tempStruct.toId=organismID{1}; -0154 A=readtable([outFile '_' num2str(i)],'Delimiter','\t','Format','%s%s%f%f%f%f%f'); -0155 else -0156 tempStruct.fromId=organismID{1}; -0157 tempStruct.toId=modelIDs{i-numel(refFastaFiles)}; -0158 A=readtable([outFile '_r' num2str(i-numel(refFastaFiles))],'Delimiter','\t','Format','%s%s%f%f%f%f%f'); -0159 end -0160 tempStruct.fromGenes=A{:,1}; -0161 tempStruct.toGenes=A{:,2}; -0162 tempStruct.evalue=table2array(A(:,3)); -0163 tempStruct.identity=table2array(A(:,4)); -0164 tempStruct.aligLen=table2array(A(:,5)); -0165 tempStruct.bitscore=table2array(A(:,6)); -0166 tempStruct.ppos=table2array(A(:,7)); -0167 blastStructure=[blastStructure tempStruct]; -0168 end -0169 -0170 %Remove the old tempfiles -0171 delete([outFile '*']); -0172 %Remove the temp fasta files -0173 delete(files{:}) -0174 end +0058 %Get the directory for RAVEN Toolbox. +0059 ravenPath=findRAVENroot(); +0060 +0061 %Generate temporary names for DIAMOND databases and output files +0062 tmpDB=tempname; +0063 outFile=tempname; +0064 +0065 %Check for existence of files. If no full path is specified for a file, +0066 %assume that it is in the current folder +0067 if isrow(refFastaFiles) +0068 files=horzcat(fastaFile,refFastaFiles); +0069 else +0070 files=vertcat(fastaFile,refFastaFiles); +0071 end +0072 +0073 files=checkFileExistence(files,2); %Copy files to temp dir +0074 fastaFile = files(1); +0075 refFastaFiles = files(2:end); +0076 +0077 %Identify the operating system +0078 if isunix +0079 if ismac +0080 binEnd='.mac'; +0081 else +0082 binEnd=''; +0083 end +0084 elseif ispc +0085 binEnd='.exe'; +0086 else +0087 dispEM('Unknown OS, exiting.') +0088 return +0089 end +0090 +0091 %Run DIAMOND multi-threaded to use all logical cores assigned to MATLAB. +0092 cores = evalc('feature(''numcores'')'); +0093 cores = strsplit(cores, 'MATLAB was assigned: '); +0094 cores = regexp(cores{2},'^\d*','match'); +0095 cores = cores{1}; +0096 +0097 %Create a database for the new organism and blast each of the refFastaFiles +0098 %against it +0099 [status, message]=system(['"' fullfile(ravenPath,'software','diamond',['diamond' binEnd]) '" makedb --in "' fastaFile{1} '" --db "' fullfile(tmpDB) '"']); +0100 if develMode +0101 diamondReport.dbHashes{numel(diamondReport.dbHashes)+1} = char(regexp(message,'[a-f0-9]{32}','match')); +0102 end +0103 if status~=0 +0104 EM=['DIAMOND makedb did not run successfully, error: ', num2str(status)]; +0105 dispEM(EM,true); +0106 end +0107 +0108 for i=1:numel(refFastaFiles) +0109 if ~hideVerbose +0110 fprintf(['Running DIAMOND blastp with "' modelIDs{i} '" against "' organismID{1} '"..\n']); +0111 end +0112 [status, ~]=system(['"' fullfile(ravenPath,'software','diamond',['diamond' binEnd]) '" blastp --query "' refFastaFiles{i} '" --out "' outFile '_' num2str(i) '" --db "' fullfile(tmpDB) '" --more-sensitive --outfmt 6 qseqid sseqid evalue pident length bitscore ppos --threads ' cores ]); +0113 if develMode +0114 diamondReport.diamondTxtOutput{numel(diamondReport.diamondTxtOutput)+1}=importdata([outFile '_' num2str(i)]); +0115 end +0116 if status~=0 +0117 EM=['DIAMOND blastp did not run successfully, error: ', num2str(status)]; +0118 dispEM(EM,true); +0119 end +0120 end +0121 delete([tmpDB filesep 'tmpDB*']); +0122 +0123 %Then create a database for each of the reference organisms and blast the +0124 %new organism against them +0125 for i=1:numel(refFastaFiles) +0126 if ~hideVerbose +0127 fprintf(['Running DIAMOND blastp with "' organismID{1} '" against "' modelIDs{i} '"..\n']); +0128 end +0129 [status, message]=system(['"' fullfile(ravenPath,'software','diamond',['diamond' binEnd]) '" makedb --in "' refFastaFiles{i} '" --db "' fullfile(tmpDB) '"']); +0130 if status~=0 +0131 EM=['DIAMOND makedb did not run successfully, error: ', num2str(status)]; +0132 dispEM(EM,true); +0133 end +0134 [status, ~]=system(['"' fullfile(ravenPath,'software','diamond',['diamond' binEnd]) '" blastp --query "' fastaFile{1} '" --out "' outFile '_r' num2str(i) '" --db "' fullfile(tmpDB) '" --more-sensitive --outfmt 6 qseqid sseqid evalue pident length bitscore ppos --threads ' cores]); +0135 if develMode +0136 diamondReport.dbHashes{numel(diamondReport.dbHashes)+1} = char(regexp(message,'[a-f0-9]{32}','match')); +0137 diamondReport.diamondTxtOutput{numel(diamondReport.diamondTxtOutput)+1}=importdata([outFile '_r' num2str(i)]); +0138 end +0139 if status~=0 +0140 EM=['DIAMOND blastp did not run successfully, error: ', num2str(status)]; +0141 dispEM(EM,true); +0142 end +0143 delete([tmpDB filesep 'tmpDB*']); +0144 end +0145 +0146 %Done with the DIAMOND blastp, do the parsing of the text files +0147 for i=1:numel(refFastaFiles)*2 +0148 tempStruct=[]; +0149 if i<=numel(refFastaFiles) +0150 tempStruct.fromId=modelIDs{i}; +0151 tempStruct.toId=organismID{1}; +0152 A=readtable([outFile '_' num2str(i)],'Delimiter','\t','Format','%s%s%f%f%f%f%f'); +0153 else +0154 tempStruct.fromId=organismID{1}; +0155 tempStruct.toId=modelIDs{i-numel(refFastaFiles)}; +0156 A=readtable([outFile '_r' num2str(i-numel(refFastaFiles))],'Delimiter','\t','Format','%s%s%f%f%f%f%f'); +0157 end +0158 tempStruct.fromGenes=A{:,1}; +0159 tempStruct.toGenes=A{:,2}; +0160 tempStruct.evalue=table2array(A(:,3)); +0161 tempStruct.identity=table2array(A(:,4)); +0162 tempStruct.aligLen=table2array(A(:,5)); +0163 tempStruct.bitscore=table2array(A(:,6)); +0164 tempStruct.ppos=table2array(A(:,7)); +0165 blastStructure=[blastStructure tempStruct]; +0166 end +0167 +0168 %Remove the old tempfiles +0169 delete([outFile '*']); +0170 %Remove the temp fasta files +0171 delete(files{:}) +0172 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/getWoLFScores.html b/doc/external/getWoLFScores.html index 339bffba..dad1f882 100644 --- a/doc/external/getWoLFScores.html +++ b/doc/external/getWoLFScores.html @@ -79,36 +79,35 @@

    SOURCE CODE ^'FASTA file %s cannot be found',string(inputFile)); 0021 end 0022 -0023 if ~strcmp(kingdom,'animal') && ~strcmp(kingdom,'fungi') && ~strcmp(kingdom,'plant') -0024 EM='Allowed kingdoms are "animal", "fungi", and "plant"'; -0025 dispEM(EM); -0026 end -0027 -0028 if ispc || ismac -0029 EM='This function currently runs only on Linux. Use parseScores if you want to use another predictor'; -0030 dispEM(EM); -0031 end -0032 -0033 %Get the directory for RAVEN Toolbox. This may not be the easiest or best -0034 %way to do this -0035 [ST, I]=dbstack('-completenames'); -0036 ravenPath=fileparts(fileparts(ST(I).file)); -0037 -0038 %Temporary output name -0039 outFile=tempname; -0040 fid=fopen(outFile,'w'); -0041 -0042 %Do the prediction -0043 [~, output]=unix(['perl "' ravenPath '/software/WoLFPSORT/bin/runWolfPsortSummary" ' kingdom ' < ' inputFile]); -0044 -0045 %Save output and call the general parser -0046 fprintf(fid,output); -0047 fclose(fid); -0048 GSS=parseScores(outFile,'wolf'); -0049 -0050 %Clean up -0051 delete(outFile); -0052 end +0023 kingdom=char(kingdom); +0024 if ~any(strcmp(kingdom,{'animal','fungi','plant'})) +0025 EM='Allowed kingdoms are "animal", "fungi", and "plant"'; +0026 dispEM(EM); +0027 end +0028 +0029 if ispc || ismac +0030 EM='This function currently runs only on Linux. Use parseScores if you want to use another predictor'; +0031 dispEM(EM); +0032 end +0033 +0034 %Get the directory for RAVEN Toolbox +0035 ravenPath=findRAVENroot(); +0036 +0037 %Temporary output name +0038 outFile=tempname; +0039 fid=fopen(outFile,'w'); +0040 +0041 %Do the prediction +0042 [~, output]=unix(['perl "' ravenPath '/software/WoLFPSORT/bin/runWolfPsortSummary" ' kingdom ' < ' inputFile]); +0043 +0044 %Save output and call the general parser +0045 fprintf(fid,output); +0046 fclose(fid); +0047 GSS=parseScores(outFile,'wolf'); +0048 +0049 %Clean up +0050 delete(outFile); +0051 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/kegg/constructMultiFasta.html b/doc/external/kegg/constructMultiFasta.html index 0c9e4435..68996f41 100644 --- a/doc/external/kegg/constructMultiFasta.html +++ b/doc/external/kegg/constructMultiFasta.html @@ -73,158 +73,160 @@

    SOURCE CODE ^% 0015 % Usage: constructMultiFasta(model,sourceFile,outputDir) 0016 -0017 if ~(exist(sourceFile,'file')==2) -0018 error('FASTA file %s cannot be found',string(sourceFile)); -0019 end -0020 -0021 fprintf('Scanning the source multi-FASTA file... '); -0022 %Open the source file -0023 fid = fopen(sourceFile, 'r'); -0024 -0025 %Since the list of genes will be accessed many times I use a Java hashtable -0026 hTable = java.util.Hashtable; -0027 -0028 for i=1:numel(model.genes) -0029 hTable.put(model.genes{i}, i); -0030 end -0031 -0032 %First go through the source file and save the position (in bytes) of the -0033 %start of each gene -0034 elementPositions=zeros(5000000,1,'int64'); %Make room for 5000000 elements -0035 totalElements=0; -0036 whereAmI=0; %Keeps track of where in the file we are -0037 while 1 -0038 %Read 10 mb at a time -0039 str=fread(fid,10000000,'int8'); -0040 -0041 %Find any '>' which indicates a new label in FASTA format -0042 newPosts=find(str==62); %62 is '>' -0043 -0044 elementPositions(totalElements+1:totalElements+numel(newPosts))=whereAmI+newPosts; +0017 sourceFile=char(sourceFile); +0018 outputDir=char(outputDir); +0019 if ~(exist(sourceFile,'file')==2) +0020 error('FASTA file %s cannot be found',string(sourceFile)); +0021 end +0022 +0023 fprintf('Scanning the source multi-FASTA file... '); +0024 %Open the source file +0025 fid = fopen(sourceFile, 'r'); +0026 +0027 %Since the list of genes will be accessed many times I use a Java hashtable +0028 hTable = java.util.Hashtable; +0029 +0030 for i=1:numel(model.genes) +0031 hTable.put(model.genes{i}, i); +0032 end +0033 +0034 %First go through the source file and save the position (in bytes) of the +0035 %start of each gene +0036 elementPositions=zeros(5000000,1,'int64'); %Make room for 5000000 elements +0037 totalElements=0; +0038 whereAmI=0; %Keeps track of where in the file we are +0039 while 1 +0040 %Read 10 mb at a time +0041 str=fread(fid,10000000,'int8'); +0042 +0043 %Find any '>' which indicates a new label in FASTA format +0044 newPosts=find(str==62); %62 is '>' 0045 -0046 totalElements=totalElements+numel(newPosts); +0046 elementPositions(totalElements+1:totalElements+numel(newPosts))=whereAmI+newPosts; 0047 -0048 whereAmI=whereAmI+10000000; +0048 totalElements=totalElements+numel(newPosts); 0049 -0050 if feof(fid) -0051 break; -0052 end -0053 end -0054 elementPositions=elementPositions(1:totalElements); -0055 fprintf('COMPLETE\n'); -0056 -0057 fprintf(['NOTICE: If Matlab is freezing and does not provide any output in 30 minutes, consider increasing Java Heap Memory\n', ... -0058 'in MATLAB settings and start over with the new session\n']); -0059 fprintf('Mapping genes to the multi-FASTA source file... '); -0060 %Now loop through the file to see which genes are present in the gene list -0061 %and save their position IN elementPositions! This is to enable a easy way -0062 %to get the distance to the following element -0063 genePositions=zeros(numel(model.genes),1); -0064 for i=1:numel(elementPositions) -0065 fseek(fid,elementPositions(i),-1); -0066 str=fread(fid,[1 30],'*char'); %Assumes that no ID is longer than 20 characters -0067 delim=find(str==32 | str==10,1,'first'); %Space or line feed -0068 -0069 geneIdentifier=str(1:delim-1); +0050 whereAmI=whereAmI+10000000; +0051 +0052 if feof(fid) +0053 break; +0054 end +0055 end +0056 elementPositions=elementPositions(1:totalElements); +0057 fprintf('COMPLETE\n'); +0058 +0059 fprintf(['NOTICE: If Matlab is freezing and does not provide any output in 30 minutes, consider increasing Java Heap Memory\n', ... +0060 'in MATLAB settings and start over with the new session\n']); +0061 fprintf('Mapping genes to the multi-FASTA source file... '); +0062 %Now loop through the file to see which genes are present in the gene list +0063 %and save their position IN elementPositions! This is to enable a easy way +0064 %to get the distance to the following element +0065 genePositions=zeros(numel(model.genes),1); +0066 for i=1:numel(elementPositions) +0067 fseek(fid,elementPositions(i),-1); +0068 str=fread(fid,[1 30],'*char'); %Assumes that no ID is longer than 20 characters +0069 delim=find(str==32 | str==10,1,'first'); %Space or line feed 0070 -0071 %This should never happen, but just to prevent errors. Could be that -0072 %'>' is a part of some gene information. An alternative would be to -0073 %check that the indexes follows a line feed -0074 if isempty(geneIdentifier) -0075 continue; -0076 end -0077 -0078 %If not found it means that the id was too long -0079 if isempty(delim) -0080 EM='Too long gene identifier, increase read length'; -0081 dispEM(EM); -0082 end -0083 -0084 %See if the gene was found -0085 id=hTable.get(geneIdentifier); -0086 -0087 if any(id) -0088 if genePositions(id)==0 -0089 genePositions(id)=i; -0090 end -0091 end -0092 end -0093 fprintf('COMPLETE\n'); -0094 -0095 fprintf('Generating the KEGG Orthology specific multi-FASTA files... 0%% complete'); -0096 %Loop through the reactions and print the corresponding sequences -0097 for i=1:numel(model.rxns) -0098 -0099 %Do not overwrite existing files -0100 if ~exist(fullfile(outputDir,[model.rxns{i} '.fa']), 'file') -0101 -0102 %Get the positions in elementPositions for the involved genes -0103 genesUsed=model.rxnGeneMat(i,:); -0104 -0105 %Open a file for this reaction. This saves empty files for KOs -0106 %without genes -0107 rxnfid=fopen(fullfile(outputDir,[model.rxns{i} '.fa']),'w'); -0108 -0109 if any(genesUsed) -0110 positions=genePositions(genesUsed~=0); -0111 -0112 %It could be that some genes were not found. Delete those -0113 %elements -0114 positions(positions==0)=[]; -0115 -0116 %Print each sequence -0117 for j=1:numel(positions) -0118 fseek(fid,elementPositions(positions(j)),-1); -0119 %Should check that it ends with a gene!!!! Check for eof -0120 if positions(j)<numel(elementPositions) -0121 str=fread(fid,[1 double(elementPositions(positions(j)+1))-double(elementPositions(positions(j)))-1],'*char'); -0122 -0123 %If the string does not end with a line feed character -0124 if str(end)~=10 -0125 str=[str fread(fid,[1 double(elementPositions(positions(j)+2))-double(elementPositions(positions(j)+1))],'*char')]; -0126 -0127 %This is if we still have not found a new gene. -0128 %Maximal unluck. This whole check should be done -0129 %when elementPositions are calculated! -0130 if str(end)~=10 -0131 %Skip this gene -0132 continue; -0133 end -0134 end -0135 else -0136 str=fread(fid,[1 inf],'*char'); -0137 end -0138 fwrite(rxnfid,['>' str]); -0139 end -0140 end -0141 fclose(rxnfid); -0142 end -0143 %Print the progress -0144 if rem(i-1,50) == 0 -0145 progress=num2str(i/numel(model.rxns)); -0146 progress=pad(progress,3,'left'); -0147 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); -0148 end -0149 end -0150 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); -0151 -0152 %Close the source file -0153 fclose(fid); -0154 end -0155 -0156 function files=listFiles(directory) -0157 %Supporter function to list the files in a directory and return them as a -0158 %cell array -0159 temp=dir(directory); -0160 files=cell(numel(temp),1); -0161 for i=1:numel(temp) -0162 files{i}=temp(i,1).name; -0163 end -0164 files=strrep(files,'.fa',''); -0165 files=strrep(files,'.hmm',''); -0166 files=strrep(files,'.out',''); -0167 files=strrep(files,'.faw',''); -0168 end +0071 geneIdentifier=str(1:delim-1); +0072 +0073 %This should never happen, but just to prevent errors. Could be that +0074 %'>' is a part of some gene information. An alternative would be to +0075 %check that the indexes follows a line feed +0076 if isempty(geneIdentifier) +0077 continue; +0078 end +0079 +0080 %If not found it means that the id was too long +0081 if isempty(delim) +0082 EM='Too long gene identifier, increase read length'; +0083 dispEM(EM); +0084 end +0085 +0086 %See if the gene was found +0087 id=hTable.get(geneIdentifier); +0088 +0089 if any(id) +0090 if genePositions(id)==0 +0091 genePositions(id)=i; +0092 end +0093 end +0094 end +0095 fprintf('COMPLETE\n'); +0096 +0097 fprintf('Generating the KEGG Orthology specific multi-FASTA files... 0%% complete'); +0098 %Loop through the reactions and print the corresponding sequences +0099 for i=1:numel(model.rxns) +0100 +0101 %Do not overwrite existing files +0102 if ~exist(fullfile(outputDir,[model.rxns{i} '.fa']), 'file') +0103 +0104 %Get the positions in elementPositions for the involved genes +0105 genesUsed=model.rxnGeneMat(i,:); +0106 +0107 %Open a file for this reaction. This saves empty files for KOs +0108 %without genes +0109 rxnfid=fopen(fullfile(outputDir,[model.rxns{i} '.fa']),'w'); +0110 +0111 if any(genesUsed) +0112 positions=genePositions(genesUsed~=0); +0113 +0114 %It could be that some genes were not found. Delete those +0115 %elements +0116 positions(positions==0)=[]; +0117 +0118 %Print each sequence +0119 for j=1:numel(positions) +0120 fseek(fid,elementPositions(positions(j)),-1); +0121 %Should check that it ends with a gene!!!! Check for eof +0122 if positions(j)<numel(elementPositions) +0123 str=fread(fid,[1 double(elementPositions(positions(j)+1))-double(elementPositions(positions(j)))-1],'*char'); +0124 +0125 %If the string does not end with a line feed character +0126 if str(end)~=10 +0127 str=[str fread(fid,[1 double(elementPositions(positions(j)+2))-double(elementPositions(positions(j)+1))],'*char')]; +0128 +0129 %This is if we still have not found a new gene. +0130 %Maximal unluck. This whole check should be done +0131 %when elementPositions are calculated! +0132 if str(end)~=10 +0133 %Skip this gene +0134 continue; +0135 end +0136 end +0137 else +0138 str=fread(fid,[1 inf],'*char'); +0139 end +0140 fwrite(rxnfid,['>' str]); +0141 end +0142 end +0143 fclose(rxnfid); +0144 end +0145 %Print the progress +0146 if rem(i-1,50) == 0 +0147 progress=num2str(i/numel(model.rxns)); +0148 progress=pad(progress,3,'left'); +0149 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); +0150 end +0151 end +0152 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); +0153 +0154 %Close the source file +0155 fclose(fid); +0156 end +0157 +0158 function files=listFiles(directory) +0159 %Supporter function to list the files in a directory and return them as a +0160 %cell array +0161 temp=dir(directory); +0162 files=cell(numel(temp),1); +0163 for i=1:numel(temp) +0164 files{i}=temp(i,1).name; +0165 end +0166 files=strrep(files,'.fa',''); +0167 files=strrep(files,'.hmm',''); +0168 files=strrep(files,'.out',''); +0169 files=strrep(files,'.faw',''); +0170 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/kegg/getGenesFromKEGG.html b/doc/external/kegg/getGenesFromKEGG.html index a9826794..fd844f21 100644 --- a/doc/external/kegg/getGenesFromKEGG.html +++ b/doc/external/kegg/getGenesFromKEGG.html @@ -172,216 +172,216 @@

    SOURCE CODE ^if nargin<1 0067 keggPath='RAVEN/external/kegg'; -0068 end -0069 -0070 [ST, I]=dbstack('-completenames'); -0071 ravenPath=fileparts(fileparts(fileparts(ST(I).file))); -0072 genesFile=fullfile(ravenPath,'external','kegg','keggGenes.mat'); -0073 if exist(genesFile, 'file') -0074 fprintf(['Importing KEGG genes from ' strrep(genesFile,'\','/') '... ']); -0075 load(genesFile); -0076 else -0077 fprintf(['NOTE: Cannot locate ' strrep(genesFile,'\','/') ', it will therefore be generated from the local KEGG database\n']); -0078 if ~exist(fullfile(keggPath,'ko'),'file') || ~exist(fullfile(keggPath,'reaction'),'file') -0079 EM=fprintf(['The files ''ko'' and ''reaction'' cannot be located at ' strrep(keggPath,'\','/') '/ and should be downloaded from the KEGG FTP\n']); -0080 dispEM(EM); -0081 else -0082 fprintf('Generating keggGenes.mat file... '); -0083 %Get all KOs that are associated to reactions -0084 allKOs=getAllKOs(keggPath); -0085 -0086 %Since the list of genes will be accessed many times the hash table -0087 %is established -0088 geneMap=containers.Map('KeyType','char','ValueType','int32'); -0089 -0090 %Add new functionality in the order specified in models -0091 model.id='KEGG'; -0092 model.name='Automatically generated from KEGG database'; -0093 -0094 %Preallocate memory -0095 model.rxns=cell(numel(allKOs),1); -0096 model.rxnNames=cell(numel(allKOs),1); -0097 -0098 %Reserve space for 500000 genes -0099 model.genes=cell(500000,1); -0100 -0101 %Load information on KO ID, name, and associated genes -0102 fid = fopen(fullfile(keggPath,'ko'), 'r'); -0103 -0104 %Keeps track of how many KOs that have been added -0105 koCounter=0; -0106 nGenes=0; -0107 addingGenes=false; -0108 -0109 %These contain the mapping between KOs and genes and are used to -0110 %generate the model.rxnGeneMat in the end -0111 koIndex=zeros(5000000,1); -0112 geneIndex=koIndex; -0113 nMappings=0; -0114 -0115 skipRead=false; -0116 -0117 %Loop through the file -0118 while 1 -0119 %Get the next line -0120 if skipRead==false -0121 tline = fgetl(fid); -0122 else -0123 skipRead=false; -0124 end -0125 -0126 %Abort at end of file -0127 if ~ischar(tline) -0128 break; -0129 end -0130 -0131 %Skip '///' -0132 if numel(tline)<12 -0133 addingGenes=false; -0134 continue; -0135 end -0136 -0137 %Check if it's a new reaction -0138 if strcmp(tline(1:12),'ENTRY ') -0139 %Check if it should be added -0140 koID=tline(13:18); -0141 -0142 if ismember(koID,allKOs) -0143 addMe=true; -0144 koCounter=koCounter+1; -0145 else -0146 addMe=false; -0147 continue; -0148 end -0149 -0150 %Add reaction ID (always 6 characters) -0151 model.rxns{koCounter}=koID; -0152 -0153 model.rxnNames{koCounter}=''; -0154 %Will be overwritten if it exists -0155 end -0156 -0157 %To get here we must be in a KO that should be added -0158 if addMe==true -0159 %Add name -0160 if strcmp(tline(1:12),'DEFINITION ') -0161 model.rxnNames{koCounter}=tline(13:end); -0162 end -0163 -0164 %Check if it's time to start adding genes -0165 if strcmp(tline(1:12),'GENES ') -0166 addingGenes=true; -0167 end -0168 -0169 %Add genes -0170 if addingGenes==true -0171 %We are now adding genes for the current KO. All gene -0172 %rows start with 12 spaces. If this is not true it -0173 %means that there is additional annotation such as -0174 %AUTHORS. This is not common but it exists -0175 if strcmp(tline(1:12),' ') || strcmp(tline(1:12),'GENES ') -0176 geneLine=tline(13:end); -0177 -0178 %Check if the line is from a new organism of from -0179 %the same as before -0180 if strcmp(geneLine(4),':') -0181 %If organism id contains 3 letters; -0182 currentOrganism=geneLine(1:3); -0183 %Parse the string -0184 genes=regexp(geneLine(6:end),' ','split'); -0185 genes=strcat(currentOrganism,':',genes(:)); -0186 elseif strcmp(geneLine(5),':') -0187 %If organism id contains 4 letters; -0188 currentOrganism=geneLine(1:4); -0189 %Parse the string -0190 genes=regexp(geneLine(7:end),' ','split'); -0191 genes=strcat(currentOrganism,':',genes(:)); -0192 end -0193 -0194 %Add the genes to the gene list -0195 for i=1:numel(genes) -0196 geneString=genes{i}; -0197 if geneMap.isKey(geneString) -0198 index=geneMap(geneString); -0199 else -0200 nGenes=nGenes+1; -0201 model.genes{nGenes}=geneString; -0202 index=nGenes; -0203 geneMap(geneString)=index; -0204 end -0205 -0206 %Add the connection to the KO -0207 nMappings=nMappings+1; -0208 koIndex(nMappings)=koCounter; -0209 geneIndex(nMappings)=index; -0210 end -0211 else -0212 %Now we want to throw away everything until the -0213 %next entry -0214 while 1 -0215 tline = fgetl(fid); -0216 if strcmp(tline,'///') -0217 %When the new entry is found, skip reading -0218 %one line to fit with the rest of the code -0219 skipRead=true; -0220 break; -0221 end -0222 end -0223 end -0224 end -0225 end -0226 end -0227 %Close the file -0228 fclose(fid); -0229 -0230 %If too much space was allocated, shrink the model -0231 model.rxns=model.rxns(1:koCounter); -0232 model.rxnNames=model.rxnNames(1:koCounter); -0233 model.genes=model.genes(1:nGenes); -0234 -0235 %Retrieve and add the gene associations -0236 model.rxnGeneMat=sparse(koIndex(1:nMappings),geneIndex(1:nMappings),ones(nMappings,1)); -0237 -0238 %To make sure the size is correct if the last KOs don't have genes -0239 if size(model.rxnGeneMat,1)~=koCounter -0240 model.rxnGeneMat(koCounter,1)=0; -0241 end -0242 -0243 %Trim the genes so that they only contain information that can be -0244 %matched to the KEGG file of protein sequences (remove all -0245 %information after first parenthesis) -0246 %NOTE: For some reason the organism abbreviation should be in lower -0247 %case in this database. Fix this here -0248 for i=1:numel(model.genes) -0249 parIndex=strfind(model.genes{i},'('); -0250 if any(parIndex) -0251 model.genes{i}=model.genes{i}(1:parIndex-1); -0252 end -0253 colIndex=strfind(model.genes{i},':'); -0254 model.genes{i}=[lower(model.genes{i}(1:colIndex-1)) model.genes{i}(colIndex:end)]; -0255 end -0256 -0257 %Save the model structure -0258 save(genesFile,'model'); -0259 end -0260 end -0261 -0262 %Only get the KOs in koList -0263 I=~ismember(model.rxns,koList); -0264 model=removeReactions(model,I,true,true); -0265 fprintf('COMPLETE\n'); -0266 end -0267 -0268 function allKOs=getAllKOs(keggPath) -0269 %Retrieves all KOs that are associated to reactions. This is because the -0270 %number of genes in KEGG is very large so without this parsing it would -0271 %take many hours -0272 -0273 allKOs={}; -0274 -0275 %First check if the reactions have already been parsed -0276 [ST, I]=dbstack('-completenames'); -0277 ravenPath=fileparts(fileparts(fileparts(ST(I).file))); +0068 else +0069 keggPath=char(keggPath); +0070 end +0071 +0072 ravenPath=findRAVENroot(); +0073 genesFile=fullfile(ravenPath,'external','kegg','keggGenes.mat'); +0074 if exist(genesFile, 'file') +0075 fprintf(['Importing KEGG genes from ' strrep(genesFile,'\','/') '... ']); +0076 load(genesFile); +0077 else +0078 fprintf(['NOTE: Cannot locate ' strrep(genesFile,'\','/') ', it will therefore be generated from the local KEGG database\n']); +0079 if ~exist(fullfile(keggPath,'ko'),'file') || ~exist(fullfile(keggPath,'reaction'),'file') +0080 EM=fprintf(['The files ''ko'' and ''reaction'' cannot be located at ' strrep(keggPath,'\','/') '/ and should be downloaded from the KEGG FTP\n']); +0081 dispEM(EM); +0082 else +0083 fprintf('Generating keggGenes.mat file... '); +0084 %Get all KOs that are associated to reactions +0085 allKOs=getAllKOs(keggPath); +0086 +0087 %Since the list of genes will be accessed many times the hash table +0088 %is established +0089 geneMap=containers.Map('KeyType','char','ValueType','int32'); +0090 +0091 %Add new functionality in the order specified in models +0092 model.id='KEGG'; +0093 model.name='Automatically generated from KEGG database'; +0094 +0095 %Preallocate memory +0096 model.rxns=cell(numel(allKOs),1); +0097 model.rxnNames=cell(numel(allKOs),1); +0098 +0099 %Reserve space for 500000 genes +0100 model.genes=cell(500000,1); +0101 +0102 %Load information on KO ID, name, and associated genes +0103 fid = fopen(fullfile(keggPath,'ko'), 'r'); +0104 +0105 %Keeps track of how many KOs that have been added +0106 koCounter=0; +0107 nGenes=0; +0108 addingGenes=false; +0109 +0110 %These contain the mapping between KOs and genes and are used to +0111 %generate the model.rxnGeneMat in the end +0112 koIndex=zeros(5000000,1); +0113 geneIndex=koIndex; +0114 nMappings=0; +0115 +0116 skipRead=false; +0117 +0118 %Loop through the file +0119 while 1 +0120 %Get the next line +0121 if skipRead==false +0122 tline = fgetl(fid); +0123 else +0124 skipRead=false; +0125 end +0126 +0127 %Abort at end of file +0128 if ~ischar(tline) +0129 break; +0130 end +0131 +0132 %Skip '///' +0133 if numel(tline)<12 +0134 addingGenes=false; +0135 continue; +0136 end +0137 +0138 %Check if it's a new reaction +0139 if strcmp(tline(1:12),'ENTRY ') +0140 %Check if it should be added +0141 koID=tline(13:18); +0142 +0143 if ismember(koID,allKOs) +0144 addMe=true; +0145 koCounter=koCounter+1; +0146 else +0147 addMe=false; +0148 continue; +0149 end +0150 +0151 %Add reaction ID (always 6 characters) +0152 model.rxns{koCounter}=koID; +0153 +0154 model.rxnNames{koCounter}=''; +0155 %Will be overwritten if it exists +0156 end +0157 +0158 %To get here we must be in a KO that should be added +0159 if addMe==true +0160 %Add name +0161 if strcmp(tline(1:12),'DEFINITION ') +0162 model.rxnNames{koCounter}=tline(13:end); +0163 end +0164 +0165 %Check if it's time to start adding genes +0166 if strcmp(tline(1:12),'GENES ') +0167 addingGenes=true; +0168 end +0169 +0170 %Add genes +0171 if addingGenes==true +0172 %We are now adding genes for the current KO. All gene +0173 %rows start with 12 spaces. If this is not true it +0174 %means that there is additional annotation such as +0175 %AUTHORS. This is not common but it exists +0176 if strcmp(tline(1:12),' ') || strcmp(tline(1:12),'GENES ') +0177 geneLine=tline(13:end); +0178 +0179 %Check if the line is from a new organism of from +0180 %the same as before +0181 if strcmp(geneLine(4),':') +0182 %If organism id contains 3 letters; +0183 currentOrganism=geneLine(1:3); +0184 %Parse the string +0185 genes=regexp(geneLine(6:end),' ','split'); +0186 genes=strcat(currentOrganism,':',genes(:)); +0187 elseif strcmp(geneLine(5),':') +0188 %If organism id contains 4 letters; +0189 currentOrganism=geneLine(1:4); +0190 %Parse the string +0191 genes=regexp(geneLine(7:end),' ','split'); +0192 genes=strcat(currentOrganism,':',genes(:)); +0193 end +0194 +0195 %Add the genes to the gene list +0196 for i=1:numel(genes) +0197 geneString=genes{i}; +0198 if geneMap.isKey(geneString) +0199 index=geneMap(geneString); +0200 else +0201 nGenes=nGenes+1; +0202 model.genes{nGenes}=geneString; +0203 index=nGenes; +0204 geneMap(geneString)=index; +0205 end +0206 +0207 %Add the connection to the KO +0208 nMappings=nMappings+1; +0209 koIndex(nMappings)=koCounter; +0210 geneIndex(nMappings)=index; +0211 end +0212 else +0213 %Now we want to throw away everything until the +0214 %next entry +0215 while 1 +0216 tline = fgetl(fid); +0217 if strcmp(tline,'///') +0218 %When the new entry is found, skip reading +0219 %one line to fit with the rest of the code +0220 skipRead=true; +0221 break; +0222 end +0223 end +0224 end +0225 end +0226 end +0227 end +0228 %Close the file +0229 fclose(fid); +0230 +0231 %If too much space was allocated, shrink the model +0232 model.rxns=model.rxns(1:koCounter); +0233 model.rxnNames=model.rxnNames(1:koCounter); +0234 model.genes=model.genes(1:nGenes); +0235 +0236 %Retrieve and add the gene associations +0237 model.rxnGeneMat=sparse(koIndex(1:nMappings),geneIndex(1:nMappings),ones(nMappings,1)); +0238 +0239 %To make sure the size is correct if the last KOs don't have genes +0240 if size(model.rxnGeneMat,1)~=koCounter +0241 model.rxnGeneMat(koCounter,1)=0; +0242 end +0243 +0244 %Trim the genes so that they only contain information that can be +0245 %matched to the KEGG file of protein sequences (remove all +0246 %information after first parenthesis) +0247 %NOTE: For some reason the organism abbreviation should be in lower +0248 %case in this database. Fix this here +0249 for i=1:numel(model.genes) +0250 parIndex=strfind(model.genes{i},'('); +0251 if any(parIndex) +0252 model.genes{i}=model.genes{i}(1:parIndex-1); +0253 end +0254 colIndex=strfind(model.genes{i},':'); +0255 model.genes{i}=[lower(model.genes{i}(1:colIndex-1)) model.genes{i}(colIndex:end)]; +0256 end +0257 +0258 %Save the model structure +0259 save(genesFile,'model'); +0260 end +0261 end +0262 +0263 %Only get the KOs in koList +0264 I=~ismember(model.rxns,koList); +0265 model=removeReactions(model,I,true,true); +0266 fprintf('COMPLETE\n'); +0267 end +0268 +0269 function allKOs=getAllKOs(keggPath) +0270 %Retrieves all KOs that are associated to reactions. This is because the +0271 %number of genes in KEGG is very large so without this parsing it would +0272 %take many hours +0273 +0274 allKOs={}; +0275 +0276 %First check if the reactions have already been parsed +0277 ravenPath=findRAVENroot; 0278 rxnsFile=fullfile(ravenPath,'external','kegg','keggRxns.mat'); 0279 if exist(rxnsFile, 'file') 0280 fprintf(['NOTE: Importing KEGG ORTHOLOGY list from ' strrep(rxnsFile,'\','/') '.\n']); diff --git a/doc/external/kegg/getKEGGModelForOrganism.html b/doc/external/kegg/getKEGGModelForOrganism.html index f98436a4..d6c84b28 100644 --- a/doc/external/kegg/getKEGGModelForOrganism.html +++ b/doc/external/kegg/getKEGGModelForOrganism.html @@ -540,803 +540,802 @@

    SOURCE CODE ^% keepGeneral,cutOff,minScoreRatioKO,minScoreRatioG,maxPhylDist,... 0250 % nSequences,seqIdentity) 0251 -0252 if nargin<2 +0252 if nargin<2 || isempty(fastaFile) 0253 fastaFile=[]; -0254 end -0255 if nargin<3 -0256 dataDir=[]; -0257 end -0258 if nargin<4 -0259 outDir=[]; -0260 end -0261 if isempty(outDir) -0262 outDir=tempdir; -0263 %Delete all *.out files if any exist -0264 delete(fullfile(outDir,'*.out')); -0265 elseif ~isstr(outDir) -0266 error('outDir should be provided as string'); -0267 end -0268 if nargin<5 -0269 keepSpontaneous=true; -0270 end -0271 if nargin<6 -0272 keepUndefinedStoich=true; -0273 end -0274 if nargin<7 -0275 keepIncomplete=true; -0276 end -0277 if nargin<8 -0278 keepGeneral=false; -0279 end -0280 if nargin<9 -0281 cutOff=10^-50; -0282 end -0283 if nargin<10 -0284 minScoreRatioKO=0.3; -0285 end -0286 if nargin<11 -0287 minScoreRatioG=0.8; -0288 end -0289 if nargin<12 -0290 maxPhylDist=inf; -0291 %Include all sequences for each reaction -0292 end -0293 if nargin<13 -0294 nSequences=inf; -0295 %Include all sequences for each reaction -0296 end -0297 if nargin<14 -0298 seqIdentity=0.9; -0299 end -0300 -0301 if isempty(fastaFile) -0302 fprintf(['\n\n*** The model reconstruction from KEGG based on the annotation available for KEGG Species <strong>' organismID '</strong> ***\n\n']); -0303 else -0304 fprintf('\n\n*** The model reconstruction from KEGG based on the protein homology search against KEGG Orthology specific HMMs ***\n\n'); -0305 %Check if query fasta exists -0306 fastaFile=checkFileExistence(fastaFile,2); %Copy file to temp dir -0307 end -0308 -0309 %Run the external binaries multi-threaded to use all logical cores assigned -0310 %to MATLAB -0311 cores = evalc('feature(''numcores'')'); -0312 cores = strsplit(cores, 'MATLAB was assigned: '); -0313 cores = regexp(cores{2},'^\d*','match'); -0314 cores = cores{1}; -0315 -0316 %Get the directory for RAVEN Toolbox. This is to get the path to the third -0317 %party software used -0318 [ST, I]=dbstack('-completenames'); -0319 ravenPath=fileparts(fileparts(fileparts(ST(I).file))); -0320 -0321 %Checking if dataDir is consistent. It must point to pre-trained HMMs set, -0322 %compatible with the the current RAVEN version. The user may have the -0323 %required zip file already in working directory or have it extracted. If -0324 %the zip file and directory is not here, it is downloaded from the cloud -0325 if ~isempty(dataDir) -0326 hmmOptions={'euk90_kegg100','prok90_kegg100'}; -0327 if ~endsWith(dataDir,hmmOptions) %Check if dataDir ends with any of the hmmOptions. -0328 %If not, then check whether the required folders exist anyway. -0329 if ~exist(fullfile(dataDir,'keggdb','genes.pep'),'file') && ... -0330 ~exist(fullfile(dataDir,'fasta'),'dir') && ... -0331 ~exist(fullfile(dataDir,'aligned'),'dir') && ... -0332 ~exist(fullfile(dataDir,'hmms'),'dir') -0333 error(['Pre-trained HMMs set is not recognised. If you want download RAVEN provided sets, it should match any of the following: ' strjoin(hmmOptions,' or ')]) -0334 end -0335 else -0336 if exist(dataDir,'dir') && exist(fullfile(dataDir,'hmms','K00844.hmm'),'file') -0337 fprintf(['NOTE: Found <strong>' dataDir '</strong> directory with pre-trained HMMs, it will therefore be used during reconstruction\n']); -0338 elseif ~exist(dataDir,'dir') && exist([dataDir,'.zip'],'file') -0339 fprintf('Extracting the HMMs archive file... '); -0340 unzip([dataDir,'.zip']); -0341 fprintf('COMPLETE\n'); -0342 else -0343 hmmIndex=strcmp(dataDir,hmmOptions); -0344 if ~any(hmmIndex) -0345 error(['Pre-trained HMMs are only provided with proteins clustered at 90% sequence identity (i.e. prok90_kegg100 and euk90_kegg100). ' ... -0346 'Use either of these datasets, or otherwise download the relevant sequence data from KEGG to train HMMs with your desired sequence identity']) -0347 else -0348 fprintf('Downloading the HMMs archive file... '); -0349 try -0350 websave([dataDir,'.zip'],['https://github.com/SysBioChalmers/RAVEN/releases/download/v2.6.0/',hmmOptions{hmmIndex},'.zip']); -0351 catch ME -0352 if strcmp(ME.identifier,'MATLAB:webservices:HTTP404StatusCodeError') -0353 error('Failed to download the HMMs archive file, the server returned a 404 error, try again later. If the problem persists please report it on the RAVEN GitHub Issues page: https://github.com/SysBioChalmers/RAVEN/issues') -0354 end -0355 end -0356 end -0357 -0358 fprintf('COMPLETE\n'); -0359 fprintf('Extracting the HMMs archive file... '); -0360 unzip([dataDir,'.zip']); -0361 fprintf('COMPLETE\n'); -0362 end -0363 %Check if HMMs are extracted -0364 if ~exist(fullfile(dataDir,'hmms','K00844.hmm'),'file') -0365 error(['The HMM files seem improperly extracted and not found in ',dataDir,'/hmms. Please remove ',dataDir,' folder and rerun getKEGGModelForOrganism']); -0366 end -0367 end -0368 end -0369 -0370 %Check if the fasta-file contains '/' or'\'. If not then it's probably just -0371 %a file name. Expand to full path. -0372 if any(fastaFile) -0373 if ~any(strfind(fastaFile,'\')) && ~any(strfind(fastaFile,'/')) -0374 fastaFile=which(fastaFile); -0375 end -0376 %Create the required sub-folders in dataDir if they dont exist -0377 if ~exist(fullfile(dataDir,'keggdb'),'dir') -0378 mkdir(dataDir,'keggdb'); -0379 end -0380 if ~exist(fullfile(dataDir,'fasta'),'dir') -0381 mkdir(dataDir,'fasta'); -0382 end -0383 if ~exist(fullfile(dataDir,'aligned'),'dir') -0384 mkdir(dataDir,'aligned'); -0385 end -0386 if ~exist(fullfile(dataDir,'hmms'),'dir') -0387 mkdir(dataDir,'hmms'); -0388 end -0389 if ~exist(outDir,'dir') -0390 mkdir(outDir); -0391 end -0392 end -0393 -0394 %First generate the full global KEGG model. Can be provided as input. -0395 %Otherwise, getModelFromKEGG is run. The dataDir must not be supplied as -0396 %there is also an internal RAVEN version available -0397 if nargin==15 -0398 model=globalModel.model; -0399 KOModel=globalModel.KOModel; -0400 elseif any(dataDir) -0401 [model, KOModel]=getModelFromKEGG(fullfile(dataDir,'keggdb'),keepSpontaneous,keepUndefinedStoich,keepIncomplete,keepGeneral); -0402 else -0403 [model, KOModel]=getModelFromKEGG([],keepSpontaneous,keepUndefinedStoich,keepIncomplete,keepGeneral); -0404 end -0405 model.id=organismID; -0406 model.c=zeros(numel(model.rxns),1); -0407 -0408 %If no FASTA file is supplied, then just remove all genes which are not for -0409 %the given organism ID -0410 if isempty(fastaFile) -0411 %Check if organismID can be found in KEGG species list or is -0412 %set to "eukaryotes" or "prokaryotes" -0413 phylDistsFull=getPhylDist(fullfile(dataDir,'keggdb'),true); -0414 if ~ismember(organismID,[phylDistsFull.ids 'eukaryotes' 'prokaryotes']) -0415 error('Provided organismID is incorrect. Only species abbreviations from KEGG Species List or "eukaryotes"/"prokaryotes" are allowed.'); -0416 end -0417 -0418 fprintf(['Pruning the model from <strong>non-' organismID '</strong> genes... ']); -0419 if ismember(organismID,{'eukaryotes','prokaryotes'}) -0420 phylDists=getPhylDist(fullfile(dataDir,'keggdb'),maxPhylDist==-1); -0421 if strcmp(organismID,'eukaryotes') -0422 proxyid='hsa'; -0423 %Use H. sapiens here -0424 else -0425 proxyid='eco'; -0426 %Use E. coli here -0427 end -0428 [~, phylDistId]=ismember(proxyid,phylDists.ids); -0429 idsToKeep=phylDists.ids(~isinf(phylDists.distMat(phylDistId,:))); -0430 taxIDs=cellfun(@(x) x{1},cellfun(@(x) strsplit(x,':'),model.genes,'UniformOutput',false),'UniformOutput',false); -0431 I=ismember(upper(taxIDs),upper(idsToKeep)); -0432 else -0433 %KEGG organism IDs may have three or four letters -0434 organismID=strcat(organismID,':'); -0435 %Add colon for accurate matching -0436 if length(organismID)==4 -0437 I=cellfun(@(x) strcmpi(x(1:4),organismID),model.genes); -0438 elseif length(organismID)==5 -0439 I=cellfun(@(x) strcmpi(x(1:5),organismID),model.genes); -0440 end -0441 end -0442 %Remove those genes -0443 model.genes=model.genes(I); -0444 model.rxnGeneMat=model.rxnGeneMat(:,I); -0445 fprintf('COMPLETE\n'); -0446 end -0447 -0448 %First remove all reactions without genes -0449 if keepSpontaneous==true -0450 fprintf('Removing non-spontaneous reactions without GPR rules... '); -0451 load(fullfile(ravenPath,'external','kegg','keggRxns.mat'),'isSpontaneous'); -0452 I=~any(model.rxnGeneMat,2)&~ismember(model.rxns,isSpontaneous); -0453 spontRxnsWithGenes=model.rxns(any(model.rxnGeneMat,2)&~ismember(model.rxns,isSpontaneous)); -0454 else -0455 fprintf('Removing reactions without GPR rules... '); -0456 I=~any(model.rxnGeneMat,2); -0457 end -0458 model=removeReactions(model,I,true); -0459 fprintf('COMPLETE\n'); -0460 -0461 %Clean gene names -0462 fprintf('Fixing gene names in the model... '); -0463 %Get rid of the prefix organism id -0464 model.genes=regexprep(model.genes,'^\w+?:',''); -0465 fprintf('COMPLETE\n'); -0466 -0467 %If no FASTA file is supplied, then we are done here -0468 if isempty(fastaFile) -0469 %Create grRules -0470 fprintf('Constructing GPR associations and annotations for the model... '); -0471 model.grRules=cell(numel(model.rxns),1); -0472 model.grRules(:)={''}; -0473 %Add the gene associations as 'or' -0474 for i=1:numel(model.rxns) -0475 %Find the involved genes -0476 I=find(model.rxnGeneMat(i,:)); -0477 if any(I) -0478 model.grRules{i}=['(' model.genes{I(1)}]; -0479 for j=2:numel(I) -0480 model.grRules{i}=[model.grRules{i} ' or ' model.genes{I(j)}]; -0481 end -0482 model.grRules{i}=[model.grRules{i} ')']; -0483 end -0484 end -0485 %Fix grRules and reconstruct rxnGeneMat -0486 [grRules,rxnGeneMat] = standardizeGrRules(model); %Give detailed output -0487 model.grRules = grRules; -0488 model.rxnGeneMat = rxnGeneMat; -0489 %Add geneMiriams, assuming that it follows the syntax -0490 %kegg.genes/organismID:geneName -0491 model.geneMiriams=''; -0492 for i=1:numel(model.genes) -0493 model.geneMiriams{i,1}.name{1,1}='kegg.genes'; -0494 model.geneMiriams{i,1}.value{1,1}=strcat(lower(organismID),model.genes{i,1}); -0495 end -0496 %Add the description to the reactions -0497 for i=1:numel(model.rxns) -0498 if ~isempty(model.rxnNotes{i}) -0499 model.rxnNotes(i)=strcat('Included by getKEGGModelForOrganism (without HMMs).',model.rxnNotes(i)); -0500 model.rxnNotes(i)=strrep(model.rxnNotes(i),'.','. '); -0501 else -0502 model.rxnNotes(i)={'Included by getKEGGModelForOrganism (without HMMs)'}; -0503 end -0504 end -0505 fprintf('COMPLETE\n\n'); -0506 fprintf('*** Model reconstruction complete ***\n'); -0507 return; -0508 end -0509 -0510 %Create a phylogenetic distance structure -0511 phylDistStruct=getPhylDist(fullfile(dataDir,'keggdb'),maxPhylDist==-1); -0512 [~, phylDistId]=ismember(model.id,phylDistStruct.ids); -0513 -0514 %Calculate the real maximal distance now. An abitary large number of 1000 -0515 %is used for the "all in kingdom" or "all sequences" options. This is a bit -0516 %inconvenient way to do it, but it is to make it fit with some older code -0517 if isinf(maxPhylDist) || maxPhylDist==-1 -0518 maxPhylDist=1000; -0519 end -0520 -0521 %Get the KO ids for which files have been generated. Maybe not the neatest -0522 %way.. -0523 fastaFiles=listFiles(fullfile(dataDir,'fasta','*.fa')); -0524 alignedFiles=listFiles(fullfile(dataDir,'aligned','*.fa')); -0525 alignedWorking=listFiles(fullfile(dataDir,'aligned','*.faw')); -0526 hmmFiles=listFiles(fullfile(dataDir,'hmms','*.hmm')); -0527 outFiles=listFiles(fullfile(outDir,'*.out')); -0528 -0529 %Check if multi-FASTA files should be generated. This should only be -0530 %performed if there are IDs in the KOModel structure that haven't been -0531 %parsed yet -0532 missingFASTA=setdiff(KOModel.rxns,[fastaFiles;alignedFiles;hmmFiles;outFiles]); -0533 -0534 if ~isempty(missingFASTA) -0535 if ~exist(fullfile(dataDir,'keggdb','genes.pep'),'file') -0536 EM=['The file ''genes.pep'' cannot be located at ' strrep(dataDir,'\','/') '/ and should be downloaded from the KEGG FTP.\n']; -0537 dispEM(EM); -0538 end -0539 %Only construct models for KOs which don't have files already -0540 fastaModel=removeReactions(KOModel,setdiff(KOModel.rxns,missingFASTA),true,true); -0541 %Permute the order of the KOs in the model so that constructMultiFasta -0542 %can be run on several processors at once -0543 fastaModel=permuteModel(fastaModel,randperm(RandStream.create('mrg32k3a','Seed',cputime()),numel(fastaModel.rxns)),'rxns'); -0544 constructMultiFasta(fastaModel,fullfile(dataDir,'keggdb','genes.pep'),fullfile(dataDir,'fasta')); -0545 else -0546 fprintf('Generating the KEGG Orthology specific multi-FASTA files... COMPLETE\n'); -0547 end -0548 -0549 if isunix -0550 if ismac -0551 binEnd='.mac'; -0552 else -0553 binEnd=''; -0554 end -0555 elseif ispc -0556 binEnd=''; -0557 else -0558 EM='Unknown OS, exiting.'; -0559 disp(EM); -0560 return -0561 end -0562 -0563 %Check if alignment of FASTA files should be performed -0564 missingAligned=setdiff(KOModel.rxns,[alignedFiles;hmmFiles;alignedWorking;outFiles]); -0565 if ~isempty(missingAligned) -0566 if seqIdentity==-1 -0567 fprintf('Performing the multiple alignment for KEGG Orthology specific protein sets... 0%% complete'); -0568 else -0569 fprintf('Performing clustering and multiple alignment for KEGG Orthology specific protein sets... 0%% complete'); -0570 end -0571 missingAligned=missingAligned(randperm(RandStream.create('mrg32k3a','Seed',cputime()),numel(missingAligned))); -0572 tmpFile=tempname; -0573 %On Windows, paths need to be translated to Unix before parsing it to WSL -0574 if ispc -0575 wslPath.tmpFile=getWSLpath(tmpFile); -0576 %mafft has problems writing to terminal (/dev/stderr) when running -0577 %on WSL via MATLAB, instead write and read progress file -0578 mafftOutput = tempname; -0579 wslPath.mafftOutput=getWSLpath(mafftOutput); -0580 wslPath.mafft=getWSLpath(fullfile(ravenPath,'software','mafft','mafft-linux64','mafft.bat')); -0581 wslPath.cdhit=getWSLpath(fullfile(ravenPath,'software','cd-hit','cd-hit')); -0582 end -0583 -0584 for i=1:numel(missingAligned) -0585 %This is checked here because it could be that it is created by a -0586 %parallel process. The faw-files are saved as temporary files to -0587 %kept track of which files are being worked on -0588 if ~exist(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),'file') &&... -0589 ~exist(fullfile(dataDir,'aligned',[missingAligned{i} '.fa']),'file') -0590 %Check that the multi-FASTA file exists. It should do so since -0591 %we are saving empty files as well. Print a warning and -0592 %continue if not -0593 if ~exist(fullfile(dataDir,'fasta',[missingAligned{i} '.fa']),'file') -0594 EM=['WARNING: The multi-FASTA file for ' missingAligned{i} ' does not exist']; -0595 dispEM(EM,false); -0596 continue; -0597 end -0598 -0599 %If the multi-FASTA file is empty then save an empty aligned -0600 %file and continue -0601 s=dir(fullfile(dataDir,'fasta',[missingAligned{i} '.fa'])); -0602 if s.bytes<=0 -0603 fid=fopen(fullfile(dataDir,'aligned',[missingAligned{i} '.fa']),'w'); -0604 fclose(fid); -0605 continue; -0606 end -0607 -0608 %Create an empty file to prevent other threads to start to work -0609 %on the same alignment -0610 fid=fopen(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),'w'); -0611 fclose(fid); -0612 -0613 %First load the FASTA file, then select up to nSequences -0614 %sequences of the most closely related species, apply any -0615 %constraints from maxPhylDist, and save it as a temporary file, -0616 %and create the model from that -0617 -0618 fastaStruct=fastaread(fullfile(dataDir,'fasta',[missingAligned{i} '.fa'])); -0619 phylDist=inf(numel(fastaStruct),1); -0620 for j=1:numel(fastaStruct) -0621 %Get the organism abbreviation -0622 index=strfind(fastaStruct(j).Header,':'); -0623 if any(index) -0624 abbrev=fastaStruct(j).Header(1:index(1)-1); -0625 [~, index]=ismember(abbrev,phylDistStruct.ids); -0626 if any(index) -0627 phylDist(j)=phylDistStruct.distMat(index(1),phylDistId); -0628 end -0629 end -0630 end -0631 -0632 %Inf means that it should not be included -0633 phylDist(phylDist>maxPhylDist)=[]; -0634 -0635 %Sort based on phylDist -0636 [~, order]=sort(phylDist); -0637 -0638 %Save the first nSequences hits to a temporary FASTA file -0639 if nSequences<=numel(fastaStruct) -0640 fastaStruct=fastaStruct(order(1:nSequences)); -0641 else -0642 fastaStruct=fastaStruct(order); -0643 end -0644 -0645 %Do the clustering and alignment if there are more than one -0646 %sequences, otherwise just save the sequence (or an empty file) -0647 if numel(fastaStruct)>1 -0648 if seqIdentity~=-1 -0649 cdhitInpCustom=tempname; -0650 fastawrite(cdhitInpCustom,fastaStruct); -0651 if seqIdentity<=1 && seqIdentity>0.7 -0652 nparam='5'; -0653 elseif seqIdentity>0.6 -0654 nparam='4'; -0655 elseif seqIdentity>0.5 -0656 nparam='3'; -0657 elseif seqIdentity>0.4 -0658 nparam='2'; -0659 else -0660 EM='The provided seqIdentity must be between 0 and 1\n'; -0661 dispEM(EM); -0662 end -0663 if ispc -0664 wslPath.cdhitInpCustom=getWSLpath(cdhitInpCustom); -0665 [status, output]=system(['wsl "' wslPath.cdhit '" -T "' num2str(cores) '" -i "' wslPath.cdhitInpCustom '" -o "' wslPath.tmpFile '" -c "' num2str(seqIdentity) '" -n ' nparam ' -M 2000']); -0666 elseif ismac || isunix -0667 [status, output]=system(['"' fullfile(ravenPath,'software','cd-hit',['cd-hit' binEnd]) '" -T "' num2str(cores) '" -i "' cdhitInpCustom '" -o "' tmpFile '" -c "' num2str(seqIdentity) '" -n ' nparam ' -M 2000']); -0668 end -0669 if status~=0 -0670 EM=['Error when performing clustering of ' missingAligned{i} ':\n' output]; -0671 dispEM(EM); -0672 end -0673 %Remove the old tempfile -0674 if exist(cdhitInpCustom, 'file') -0675 delete([cdhitInpCustom '*']); -0676 end -0677 else -0678 %This means that CD-HIT should be skipped since -0679 %seqIdentity is equal to -1 -0680 fastawrite(tmpFile,fastaStruct); -0681 end -0682 %Do the alignment for this file -0683 if ismac -0684 [status, output]=system(['"' fullfile(ravenPath,'software','mafft','mafft-mac','mafft.bat') '" --auto --anysymbol --thread "' num2str(cores) '" "' tmpFile '" > "' fullfile(dataDir,'aligned',[missingAligned{i} '.faw']) '"']); -0685 elseif isunix -0686 [status, output]=system(['"' fullfile(ravenPath,'software','mafft','mafft-linux64','mafft.bat') '" --auto --anysymbol --thread "' num2str(cores) '" "' tmpFile '" > "' fullfile(dataDir,'aligned',[missingAligned{i} '.faw']) '"']); -0687 elseif ispc -0688 wslPath.fawFile=getWSLpath(fullfile(dataDir,'aligned',[missingAligned{i} '.faw'])); -0689 [status, ~]=system(['wsl "' wslPath.mafft '" --auto --anysymbol --progress "' wslPath.mafftOutput '" --thread "' num2str(cores) '" --out "' wslPath.fawFile '" "' wslPath.tmpFile '"']); -0690 output=fileread(mafftOutput); -0691 delete(mafftOutput); -0692 end -0693 if status~=0 -0694 %It could be that alignment failed because only one -0695 %sequence was left after clustering. If that is the -0696 %case, then the clustered file is just copied as 'faw' -0697 %file -0698 if any(regexp(output,'Only 1 sequence found')) -0699 movefile(tmpFile,fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),'f'); -0700 else -0701 EM=['Error when performing alignment of ' missingAligned{i} ':\n' output]; -0702 dispEM(EM); -0703 end -0704 end -0705 %Remove the old tempfile -0706 if exist(tmpFile, 'file') -0707 delete([tmpFile '*']); -0708 end -0709 else -0710 %If there is only one sequence then it's not possible to do -0711 %a multiple alignment. Just print the sequence instead. An -0712 %empty file was written previously so that doesn't have to -0713 %be dealt with -0714 if numel(fastaStruct)==1 -0715 warnState = warning; %Save the current warning state -0716 warning('off','Bioinfo:fastawrite:AppendToFile'); -0717 fastawrite(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),fastaStruct); -0718 warning(warnState) %Reset warning state to previous settings -0719 end -0720 end -0721 %Move the temporary file to the real one -0722 movefile(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),fullfile(dataDir,'aligned',[missingAligned{i} '.fa']),'f'); -0723 -0724 %Print the progress every 25 files -0725 if rem(i-1,25) == 0 -0726 progress=num2str(floor(100*numel(listFiles(fullfile(dataDir,'aligned','*.fa')))/numel(KOModel.rxns))); -0727 progress=pad(progress,3,'left'); -0728 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); -0729 end -0730 end -0731 end -0732 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); -0733 else -0734 if seqIdentity==-1 -0735 fprintf('Performing the multiple alignment for KEGG Orthology specific protein sets... COMPLETE\n'); -0736 else -0737 fprintf('Performing clustering and multiple alignment for KEGG Orthology specific protein sets... COMPLETE\n'); -0738 end -0739 end -0740 -0741 %Check if training of Hidden Markov models should be performed -0742 missingHMMs=setdiff(KOModel.rxns,[hmmFiles;outFiles]); -0743 if ~isempty(missingHMMs) -0744 fprintf('Training the KEGG Orthology specific HMMs... 0%% complete'); -0745 missingHMMs=missingHMMs(randperm(RandStream.create('mrg32k3a','Seed',cputime()),numel(missingHMMs))); -0746 %Train models for all missing KOs -0747 for i=1:numel(missingHMMs) -0748 %This is checked here because it could be that it is created by a -0749 %parallel process -0750 if ~exist(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm']),'file') && ~exist(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmw']),'file') -0751 %Check that the aligned FASTA file exists. It could be that it -0752 %is still being worked on by some other instance of the program -0753 %(the .faw file should then exist). This should not happen on a -0754 %single computer. It doesn't throw an error, because it should -0755 %finalize the ones it can -0756 if ~exist(fullfile(dataDir,'aligned',[missingHMMs{i} '.fa']),'file') -0757 EM=['The aligned FASTA file for ' missingHMMs{i} ' does not exist']; -0758 dispEM(EM,false); -0759 continue; -0760 end -0761 -0762 %If the multi-FASTA file is empty then save an empty aligned -0763 %file and continue -0764 s=dir(fullfile(dataDir,'aligned',[missingHMMs{i} '.fa'])); -0765 if s.bytes<=0 -0766 fid=fopen(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm']),'w'); -0767 fclose(fid); -0768 continue; -0769 end -0770 %Create a temporary file to indicate that it is working on the -0771 %KO. This is because hmmbuild cannot overwrite existing files -0772 fid=fopen(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmw']),'w'); -0773 fclose(fid); -0774 -0775 %Create HMM -0776 [status, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmbuild' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm']) '" "' fullfile(dataDir,'aligned',[missingHMMs{i} '.fa']) '"']); -0777 if status~=0 -0778 EM=['Error when training HMM for ' missingHMMs{i} ':\n' output]; -0779 dispEM(EM); -0780 end -0781 -0782 %Delete the temporary file -0783 delete(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmw'])); -0784 -0785 %Print the progress every 25 files -0786 if rem(i-1,25) == 0 -0787 progress=num2str(floor(100*numel(listFiles(fullfile(dataDir,'hmms','*.hmm')))/numel(KOModel.rxns))); -0788 progress=pad(progress,3,'left'); -0789 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); -0790 end -0791 end -0792 end -0793 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); -0794 else -0795 fprintf('Training the KEGG Orthology specific HMMs... COMPLETE\n'); -0796 end -0797 -0798 %Check which new .out files that should be generated. Check if training of -0799 %Hidden Markov models should be performed -0800 missingOUT=setdiff(KOModel.rxns,outFiles); -0801 if ~isempty(missingOUT) -0802 fprintf('Querying the user-specified FASTA file against the KEGG Orthology specific HMMs... 0%% complete'); -0803 missingOUT=missingOUT(randperm(RandStream.create('mrg32k3a','Seed',cputime()),numel(missingOUT))); -0804 for i=1:numel(missingOUT) -0805 %This is checked here because it could be that it is created by a -0806 %parallel process -0807 if ~exist(fullfile(outDir,[missingOUT{i} '.out']),'file') -0808 %Check that the HMM file exists. It should do so since %we are -0809 %saving empty files as well. Print a warning and continue if -0810 %not -0811 if ~exist(fullfile(dataDir,'hmms',[missingOUT{i} '.hmm']),'file') -0812 EM=['The HMM file for ' missingOUT{i} ' does not exist']; -0813 dispEM(EM,false); -0814 continue; -0815 end -0816 -0817 %Save an empty file to prevent several threads working on the -0818 %same file -0819 fid=fopen(fullfile(outDir,[missingOUT{i} '.out']),'w'); -0820 fclose(fid); -0821 -0822 %If the HMM file is empty then save an out file and continue -0823 s=dir(fullfile(dataDir,'hmms',[missingOUT{i} '.hmm'])); -0824 if s.bytes<=0 -0825 continue; -0826 end -0827 -0828 %Check each gene in the input file against this model -0829 [status, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmsearch' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(dataDir,'hmms',[missingOUT{i} '.hmm']) '" "' fastaFile '"']); -0830 if status~=0 -0831 EM=['Error when querying HMM for ' missingOUT{i} ':\n' output]; -0832 dispEM(EM); -0833 end -0834 -0835 %Save the output to a file -0836 fid=fopen(fullfile(outDir,[missingOUT{i} '.out']),'w'); -0837 fwrite(fid,output); -0838 fclose(fid); -0839 -0840 %Print the progress every 25 files -0841 if rem(i-1,25) == 0 -0842 progress=num2str(floor(100*numel(listFiles(fullfile(outDir,'*.out')))/numel(KOModel.rxns))); -0843 progress=pad(progress,3,'left'); -0844 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); -0845 end -0846 end -0847 end -0848 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); -0849 else -0850 fprintf('Querying the user-specified FASTA file against the KEGG Orthology specific HMMs... COMPLETE\n'); -0851 end +0254 else +0255 fastaFile=char(fastaFile); +0256 end +0257 if nargin<3 +0258 dataDir=[]; +0259 else +0260 dataDir=char(dataDir); +0261 end +0262 if nargin<4 || isempty(outDir) +0263 outDir=tempdir; +0264 %Delete all *.out files if any exist +0265 delete(fullfile(outDir,'*.out')); +0266 else +0267 outDir=char(outDir); +0268 end +0269 if nargin<5 +0270 keepSpontaneous=true; +0271 end +0272 if nargin<6 +0273 keepUndefinedStoich=true; +0274 end +0275 if nargin<7 +0276 keepIncomplete=true; +0277 end +0278 if nargin<8 +0279 keepGeneral=false; +0280 end +0281 if nargin<9 +0282 cutOff=10^-50; +0283 end +0284 if nargin<10 +0285 minScoreRatioKO=0.3; +0286 end +0287 if nargin<11 +0288 minScoreRatioG=0.8; +0289 end +0290 if nargin<12 +0291 maxPhylDist=inf; +0292 %Include all sequences for each reaction +0293 end +0294 if nargin<13 +0295 nSequences=inf; +0296 %Include all sequences for each reaction +0297 end +0298 if nargin<14 +0299 seqIdentity=0.9; +0300 end +0301 +0302 if isempty(fastaFile) +0303 fprintf(['\n\n*** The model reconstruction from KEGG based on the annotation available for KEGG Species <strong>' organismID '</strong> ***\n\n']); +0304 else +0305 fprintf('\n\n*** The model reconstruction from KEGG based on the protein homology search against KEGG Orthology specific HMMs ***\n\n'); +0306 %Check if query fasta exists +0307 fastaFile=checkFileExistence(fastaFile,2); %Copy file to temp dir +0308 end +0309 +0310 %Run the external binaries multi-threaded to use all logical cores assigned +0311 %to MATLAB +0312 cores = evalc('feature(''numcores'')'); +0313 cores = strsplit(cores, 'MATLAB was assigned: '); +0314 cores = regexp(cores{2},'^\d*','match'); +0315 cores = cores{1}; +0316 +0317 %Get the directory for RAVEN Toolbox. +0318 ravenPath=findRAVENroot(); +0319 +0320 %Checking if dataDir is consistent. It must point to pre-trained HMMs set, +0321 %compatible with the the current RAVEN version. The user may have the +0322 %required zip file already in working directory or have it extracted. If +0323 %the zip file and directory is not here, it is downloaded from the cloud +0324 if ~isempty(dataDir) +0325 hmmOptions={'euk90_kegg100','prok90_kegg100'}; +0326 if ~endsWith(dataDir,hmmOptions) %Check if dataDir ends with any of the hmmOptions. +0327 %If not, then check whether the required folders exist anyway. +0328 if ~exist(fullfile(dataDir,'keggdb','genes.pep'),'file') && ... +0329 ~exist(fullfile(dataDir,'fasta'),'dir') && ... +0330 ~exist(fullfile(dataDir,'aligned'),'dir') && ... +0331 ~exist(fullfile(dataDir,'hmms'),'dir') +0332 error(['Pre-trained HMMs set is not recognised. If you want download RAVEN provided sets, it should match any of the following: ' strjoin(hmmOptions,' or ')]) +0333 end +0334 else +0335 if exist(dataDir,'dir') && exist(fullfile(dataDir,'hmms','K00844.hmm'),'file') +0336 fprintf(['NOTE: Found <strong>' dataDir '</strong> directory with pre-trained HMMs, it will therefore be used during reconstruction\n']); +0337 elseif ~exist(dataDir,'dir') && exist([dataDir,'.zip'],'file') +0338 fprintf('Extracting the HMMs archive file... '); +0339 unzip([dataDir,'.zip']); +0340 fprintf('COMPLETE\n'); +0341 else +0342 hmmIndex=strcmp(dataDir,hmmOptions); +0343 if ~any(hmmIndex) +0344 error(['Pre-trained HMMs are only provided with proteins clustered at 90% sequence identity (i.e. prok90_kegg100 and euk90_kegg100). ' ... +0345 'Use either of these datasets, or otherwise download the relevant sequence data from KEGG to train HMMs with your desired sequence identity']) +0346 else +0347 fprintf('Downloading the HMMs archive file... '); +0348 try +0349 websave([dataDir,'.zip'],['https://github.com/SysBioChalmers/RAVEN/releases/download/v2.6.0/',hmmOptions{hmmIndex},'.zip']); +0350 catch ME +0351 if strcmp(ME.identifier,'MATLAB:webservices:HTTP404StatusCodeError') +0352 error('Failed to download the HMMs archive file, the server returned a 404 error, try again later. If the problem persists please report it on the RAVEN GitHub Issues page: https://github.com/SysBioChalmers/RAVEN/issues') +0353 end +0354 end +0355 end +0356 +0357 fprintf('COMPLETE\n'); +0358 fprintf('Extracting the HMMs archive file... '); +0359 unzip([dataDir,'.zip']); +0360 fprintf('COMPLETE\n'); +0361 end +0362 %Check if HMMs are extracted +0363 if ~exist(fullfile(dataDir,'hmms','K00844.hmm'),'file') +0364 error(['The HMM files seem improperly extracted and not found in ',dataDir,'/hmms. Please remove ',dataDir,' folder and rerun getKEGGModelForOrganism']); +0365 end +0366 end +0367 end +0368 +0369 %Check if the fasta-file contains '/' or'\'. If not then it's probably just +0370 %a file name. Expand to full path. +0371 if any(fastaFile) +0372 if ~any(strfind(fastaFile,'\')) && ~any(strfind(fastaFile,'/')) +0373 fastaFile=which(fastaFile); +0374 end +0375 %Create the required sub-folders in dataDir if they dont exist +0376 if ~exist(fullfile(dataDir,'keggdb'),'dir') +0377 mkdir(dataDir,'keggdb'); +0378 end +0379 if ~exist(fullfile(dataDir,'fasta'),'dir') +0380 mkdir(dataDir,'fasta'); +0381 end +0382 if ~exist(fullfile(dataDir,'aligned'),'dir') +0383 mkdir(dataDir,'aligned'); +0384 end +0385 if ~exist(fullfile(dataDir,'hmms'),'dir') +0386 mkdir(dataDir,'hmms'); +0387 end +0388 if ~exist(outDir,'dir') +0389 mkdir(outDir); +0390 end +0391 end +0392 +0393 %First generate the full global KEGG model. Can be provided as input. +0394 %Otherwise, getModelFromKEGG is run. The dataDir must not be supplied as +0395 %there is also an internal RAVEN version available +0396 if nargin==15 +0397 model=globalModel.model; +0398 KOModel=globalModel.KOModel; +0399 elseif any(dataDir) +0400 [model, KOModel]=getModelFromKEGG(fullfile(dataDir,'keggdb'),keepSpontaneous,keepUndefinedStoich,keepIncomplete,keepGeneral); +0401 else +0402 [model, KOModel]=getModelFromKEGG([],keepSpontaneous,keepUndefinedStoich,keepIncomplete,keepGeneral); +0403 end +0404 model.id=organismID; +0405 model.c=zeros(numel(model.rxns),1); +0406 +0407 %If no FASTA file is supplied, then just remove all genes which are not for +0408 %the given organism ID +0409 if isempty(fastaFile) +0410 %Check if organismID can be found in KEGG species list or is +0411 %set to "eukaryotes" or "prokaryotes" +0412 phylDistsFull=getPhylDist(fullfile(dataDir,'keggdb'),true); +0413 if ~ismember(organismID,[phylDistsFull.ids 'eukaryotes' 'prokaryotes']) +0414 error('Provided organismID is incorrect. Only species abbreviations from KEGG Species List or "eukaryotes"/"prokaryotes" are allowed.'); +0415 end +0416 +0417 fprintf(['Pruning the model from <strong>non-' organismID '</strong> genes... ']); +0418 if ismember(organismID,{'eukaryotes','prokaryotes'}) +0419 phylDists=getPhylDist(fullfile(dataDir,'keggdb'),maxPhylDist==-1); +0420 if strcmp(organismID,'eukaryotes') +0421 proxyid='hsa'; +0422 %Use H. sapiens here +0423 else +0424 proxyid='eco'; +0425 %Use E. coli here +0426 end +0427 [~, phylDistId]=ismember(proxyid,phylDists.ids); +0428 idsToKeep=phylDists.ids(~isinf(phylDists.distMat(phylDistId,:))); +0429 taxIDs=cellfun(@(x) x{1},cellfun(@(x) strsplit(x,':'),model.genes,'UniformOutput',false),'UniformOutput',false); +0430 I=ismember(upper(taxIDs),upper(idsToKeep)); +0431 else +0432 %KEGG organism IDs may have three or four letters +0433 organismID=strcat(organismID,':'); +0434 %Add colon for accurate matching +0435 if length(organismID)==4 +0436 I=cellfun(@(x) strcmpi(x(1:4),organismID),model.genes); +0437 elseif length(organismID)==5 +0438 I=cellfun(@(x) strcmpi(x(1:5),organismID),model.genes); +0439 end +0440 end +0441 %Remove those genes +0442 model.genes=model.genes(I); +0443 model.rxnGeneMat=model.rxnGeneMat(:,I); +0444 fprintf('COMPLETE\n'); +0445 end +0446 +0447 %First remove all reactions without genes +0448 if keepSpontaneous==true +0449 fprintf('Removing non-spontaneous reactions without GPR rules... '); +0450 load(fullfile(ravenPath,'external','kegg','keggRxns.mat'),'isSpontaneous'); +0451 I=~any(model.rxnGeneMat,2)&~ismember(model.rxns,isSpontaneous); +0452 spontRxnsWithGenes=model.rxns(any(model.rxnGeneMat,2)&~ismember(model.rxns,isSpontaneous)); +0453 else +0454 fprintf('Removing reactions without GPR rules... '); +0455 I=~any(model.rxnGeneMat,2); +0456 end +0457 model=removeReactions(model,I,true); +0458 fprintf('COMPLETE\n'); +0459 +0460 %Clean gene names +0461 fprintf('Fixing gene names in the model... '); +0462 %Get rid of the prefix organism id +0463 model.genes=regexprep(model.genes,'^\w+?:',''); +0464 fprintf('COMPLETE\n'); +0465 +0466 %If no FASTA file is supplied, then we are done here +0467 if isempty(fastaFile) +0468 %Create grRules +0469 fprintf('Constructing GPR associations and annotations for the model... '); +0470 model.grRules=cell(numel(model.rxns),1); +0471 model.grRules(:)={''}; +0472 %Add the gene associations as 'or' +0473 for i=1:numel(model.rxns) +0474 %Find the involved genes +0475 I=find(model.rxnGeneMat(i,:)); +0476 if any(I) +0477 model.grRules{i}=['(' model.genes{I(1)}]; +0478 for j=2:numel(I) +0479 model.grRules{i}=[model.grRules{i} ' or ' model.genes{I(j)}]; +0480 end +0481 model.grRules{i}=[model.grRules{i} ')']; +0482 end +0483 end +0484 %Fix grRules and reconstruct rxnGeneMat +0485 [grRules,rxnGeneMat] = standardizeGrRules(model); %Give detailed output +0486 model.grRules = grRules; +0487 model.rxnGeneMat = rxnGeneMat; +0488 %Add geneMiriams, assuming that it follows the syntax +0489 %kegg.genes/organismID:geneName +0490 model.geneMiriams=''; +0491 for i=1:numel(model.genes) +0492 model.geneMiriams{i,1}.name{1,1}='kegg.genes'; +0493 model.geneMiriams{i,1}.value{1,1}=strcat(lower(organismID),model.genes{i,1}); +0494 end +0495 %Add the description to the reactions +0496 for i=1:numel(model.rxns) +0497 if ~isempty(model.rxnNotes{i}) +0498 model.rxnNotes(i)=strcat('Included by getKEGGModelForOrganism (without HMMs).',model.rxnNotes(i)); +0499 model.rxnNotes(i)=strrep(model.rxnNotes(i),'.','. '); +0500 else +0501 model.rxnNotes(i)={'Included by getKEGGModelForOrganism (without HMMs)'}; +0502 end +0503 end +0504 fprintf('COMPLETE\n\n'); +0505 fprintf('*** Model reconstruction complete ***\n'); +0506 return; +0507 end +0508 +0509 %Create a phylogenetic distance structure +0510 phylDistStruct=getPhylDist(fullfile(dataDir,'keggdb'),maxPhylDist==-1); +0511 [~, phylDistId]=ismember(model.id,phylDistStruct.ids); +0512 +0513 %Calculate the real maximal distance now. An abitary large number of 1000 +0514 %is used for the "all in kingdom" or "all sequences" options. This is a bit +0515 %inconvenient way to do it, but it is to make it fit with some older code +0516 if isinf(maxPhylDist) || maxPhylDist==-1 +0517 maxPhylDist=1000; +0518 end +0519 +0520 %Get the KO ids for which files have been generated. Maybe not the neatest +0521 %way.. +0522 fastaFiles=listFiles(fullfile(dataDir,'fasta','*.fa')); +0523 alignedFiles=listFiles(fullfile(dataDir,'aligned','*.fa')); +0524 alignedWorking=listFiles(fullfile(dataDir,'aligned','*.faw')); +0525 hmmFiles=listFiles(fullfile(dataDir,'hmms','*.hmm')); +0526 outFiles=listFiles(fullfile(outDir,'*.out')); +0527 +0528 %Check if multi-FASTA files should be generated. This should only be +0529 %performed if there are IDs in the KOModel structure that haven't been +0530 %parsed yet +0531 missingFASTA=setdiff(KOModel.rxns,[fastaFiles;alignedFiles;hmmFiles;outFiles]); +0532 +0533 if ~isempty(missingFASTA) +0534 if ~exist(fullfile(dataDir,'keggdb','genes.pep'),'file') +0535 EM=['The file ''genes.pep'' cannot be located at ' strrep(dataDir,'\','/') '/ and should be downloaded from the KEGG FTP.\n']; +0536 dispEM(EM); +0537 end +0538 %Only construct models for KOs which don't have files already +0539 fastaModel=removeReactions(KOModel,setdiff(KOModel.rxns,missingFASTA),true,true); +0540 %Permute the order of the KOs in the model so that constructMultiFasta +0541 %can be run on several processors at once +0542 fastaModel=permuteModel(fastaModel,randperm(RandStream.create('mrg32k3a','Seed',cputime()),numel(fastaModel.rxns)),'rxns'); +0543 constructMultiFasta(fastaModel,fullfile(dataDir,'keggdb','genes.pep'),fullfile(dataDir,'fasta')); +0544 else +0545 fprintf('Generating the KEGG Orthology specific multi-FASTA files... COMPLETE\n'); +0546 end +0547 +0548 if isunix +0549 if ismac +0550 binEnd='.mac'; +0551 else +0552 binEnd=''; +0553 end +0554 elseif ispc +0555 binEnd=''; +0556 else +0557 EM='Unknown OS, exiting.'; +0558 disp(EM); +0559 return +0560 end +0561 +0562 %Check if alignment of FASTA files should be performed +0563 missingAligned=setdiff(KOModel.rxns,[alignedFiles;hmmFiles;alignedWorking;outFiles]); +0564 if ~isempty(missingAligned) +0565 if seqIdentity==-1 +0566 fprintf('Performing the multiple alignment for KEGG Orthology specific protein sets... 0%% complete'); +0567 else +0568 fprintf('Performing clustering and multiple alignment for KEGG Orthology specific protein sets... 0%% complete'); +0569 end +0570 missingAligned=missingAligned(randperm(RandStream.create('mrg32k3a','Seed',cputime()),numel(missingAligned))); +0571 tmpFile=tempname; +0572 %On Windows, paths need to be translated to Unix before parsing it to WSL +0573 if ispc +0574 wslPath.tmpFile=getWSLpath(tmpFile); +0575 %mafft has problems writing to terminal (/dev/stderr) when running +0576 %on WSL via MATLAB, instead write and read progress file +0577 mafftOutput = tempname; +0578 wslPath.mafftOutput=getWSLpath(mafftOutput); +0579 wslPath.mafft=getWSLpath(fullfile(ravenPath,'software','mafft','mafft-linux64','mafft.bat')); +0580 wslPath.cdhit=getWSLpath(fullfile(ravenPath,'software','cd-hit','cd-hit')); +0581 end +0582 +0583 for i=1:numel(missingAligned) +0584 %This is checked here because it could be that it is created by a +0585 %parallel process. The faw-files are saved as temporary files to +0586 %kept track of which files are being worked on +0587 if ~exist(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),'file') &&... +0588 ~exist(fullfile(dataDir,'aligned',[missingAligned{i} '.fa']),'file') +0589 %Check that the multi-FASTA file exists. It should do so since +0590 %we are saving empty files as well. Print a warning and +0591 %continue if not +0592 if ~exist(fullfile(dataDir,'fasta',[missingAligned{i} '.fa']),'file') +0593 EM=['WARNING: The multi-FASTA file for ' missingAligned{i} ' does not exist']; +0594 dispEM(EM,false); +0595 continue; +0596 end +0597 +0598 %If the multi-FASTA file is empty then save an empty aligned +0599 %file and continue +0600 s=dir(fullfile(dataDir,'fasta',[missingAligned{i} '.fa'])); +0601 if s.bytes<=0 +0602 fid=fopen(fullfile(dataDir,'aligned',[missingAligned{i} '.fa']),'w'); +0603 fclose(fid); +0604 continue; +0605 end +0606 +0607 %Create an empty file to prevent other threads to start to work +0608 %on the same alignment +0609 fid=fopen(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),'w'); +0610 fclose(fid); +0611 +0612 %First load the FASTA file, then select up to nSequences +0613 %sequences of the most closely related species, apply any +0614 %constraints from maxPhylDist, and save it as a temporary file, +0615 %and create the model from that +0616 +0617 fastaStruct=fastaread(fullfile(dataDir,'fasta',[missingAligned{i} '.fa'])); +0618 phylDist=inf(numel(fastaStruct),1); +0619 for j=1:numel(fastaStruct) +0620 %Get the organism abbreviation +0621 index=strfind(fastaStruct(j).Header,':'); +0622 if any(index) +0623 abbrev=fastaStruct(j).Header(1:index(1)-1); +0624 [~, index]=ismember(abbrev,phylDistStruct.ids); +0625 if any(index) +0626 phylDist(j)=phylDistStruct.distMat(index(1),phylDistId); +0627 end +0628 end +0629 end +0630 +0631 %Inf means that it should not be included +0632 phylDist(phylDist>maxPhylDist)=[]; +0633 +0634 %Sort based on phylDist +0635 [~, order]=sort(phylDist); +0636 +0637 %Save the first nSequences hits to a temporary FASTA file +0638 if nSequences<=numel(fastaStruct) +0639 fastaStruct=fastaStruct(order(1:nSequences)); +0640 else +0641 fastaStruct=fastaStruct(order); +0642 end +0643 +0644 %Do the clustering and alignment if there are more than one +0645 %sequences, otherwise just save the sequence (or an empty file) +0646 if numel(fastaStruct)>1 +0647 if seqIdentity~=-1 +0648 cdhitInpCustom=tempname; +0649 fastawrite(cdhitInpCustom,fastaStruct); +0650 if seqIdentity<=1 && seqIdentity>0.7 +0651 nparam='5'; +0652 elseif seqIdentity>0.6 +0653 nparam='4'; +0654 elseif seqIdentity>0.5 +0655 nparam='3'; +0656 elseif seqIdentity>0.4 +0657 nparam='2'; +0658 else +0659 EM='The provided seqIdentity must be between 0 and 1\n'; +0660 dispEM(EM); +0661 end +0662 if ispc +0663 wslPath.cdhitInpCustom=getWSLpath(cdhitInpCustom); +0664 [status, output]=system(['wsl "' wslPath.cdhit '" -T "' num2str(cores) '" -i "' wslPath.cdhitInpCustom '" -o "' wslPath.tmpFile '" -c "' num2str(seqIdentity) '" -n ' nparam ' -M 2000']); +0665 elseif ismac || isunix +0666 [status, output]=system(['"' fullfile(ravenPath,'software','cd-hit',['cd-hit' binEnd]) '" -T "' num2str(cores) '" -i "' cdhitInpCustom '" -o "' tmpFile '" -c "' num2str(seqIdentity) '" -n ' nparam ' -M 2000']); +0667 end +0668 if status~=0 +0669 EM=['Error when performing clustering of ' missingAligned{i} ':\n' output]; +0670 dispEM(EM); +0671 end +0672 %Remove the old tempfile +0673 if exist(cdhitInpCustom, 'file') +0674 delete([cdhitInpCustom '*']); +0675 end +0676 else +0677 %This means that CD-HIT should be skipped since +0678 %seqIdentity is equal to -1 +0679 fastawrite(tmpFile,fastaStruct); +0680 end +0681 %Do the alignment for this file +0682 if ismac +0683 [status, output]=system(['"' fullfile(ravenPath,'software','mafft','mafft-mac','mafft.bat') '" --auto --anysymbol --thread "' num2str(cores) '" "' tmpFile '" > "' fullfile(dataDir,'aligned',[missingAligned{i} '.faw']) '"']); +0684 elseif isunix +0685 [status, output]=system(['"' fullfile(ravenPath,'software','mafft','mafft-linux64','mafft.bat') '" --auto --anysymbol --thread "' num2str(cores) '" "' tmpFile '" > "' fullfile(dataDir,'aligned',[missingAligned{i} '.faw']) '"']); +0686 elseif ispc +0687 wslPath.fawFile=getWSLpath(fullfile(dataDir,'aligned',[missingAligned{i} '.faw'])); +0688 [status, ~]=system(['wsl "' wslPath.mafft '" --auto --anysymbol --progress "' wslPath.mafftOutput '" --thread "' num2str(cores) '" --out "' wslPath.fawFile '" "' wslPath.tmpFile '"']); +0689 output=fileread(mafftOutput); +0690 delete(mafftOutput); +0691 end +0692 if status~=0 +0693 %It could be that alignment failed because only one +0694 %sequence was left after clustering. If that is the +0695 %case, then the clustered file is just copied as 'faw' +0696 %file +0697 if any(regexp(output,'Only 1 sequence found')) +0698 movefile(tmpFile,fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),'f'); +0699 else +0700 EM=['Error when performing alignment of ' missingAligned{i} ':\n' output]; +0701 dispEM(EM); +0702 end +0703 end +0704 %Remove the old tempfile +0705 if exist(tmpFile, 'file') +0706 delete([tmpFile '*']); +0707 end +0708 else +0709 %If there is only one sequence then it's not possible to do +0710 %a multiple alignment. Just print the sequence instead. An +0711 %empty file was written previously so that doesn't have to +0712 %be dealt with +0713 if numel(fastaStruct)==1 +0714 warnState = warning; %Save the current warning state +0715 warning('off','Bioinfo:fastawrite:AppendToFile'); +0716 fastawrite(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),fastaStruct); +0717 warning(warnState) %Reset warning state to previous settings +0718 end +0719 end +0720 %Move the temporary file to the real one +0721 movefile(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),fullfile(dataDir,'aligned',[missingAligned{i} '.fa']),'f'); +0722 +0723 %Print the progress every 25 files +0724 if rem(i-1,25) == 0 +0725 progress=num2str(floor(100*numel(listFiles(fullfile(dataDir,'aligned','*.fa')))/numel(KOModel.rxns))); +0726 progress=pad(progress,3,'left'); +0727 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); +0728 end +0729 end +0730 end +0731 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); +0732 else +0733 if seqIdentity==-1 +0734 fprintf('Performing the multiple alignment for KEGG Orthology specific protein sets... COMPLETE\n'); +0735 else +0736 fprintf('Performing clustering and multiple alignment for KEGG Orthology specific protein sets... COMPLETE\n'); +0737 end +0738 end +0739 +0740 %Check if training of Hidden Markov models should be performed +0741 missingHMMs=setdiff(KOModel.rxns,[hmmFiles;outFiles]); +0742 if ~isempty(missingHMMs) +0743 fprintf('Training the KEGG Orthology specific HMMs... 0%% complete'); +0744 missingHMMs=missingHMMs(randperm(RandStream.create('mrg32k3a','Seed',cputime()),numel(missingHMMs))); +0745 %Train models for all missing KOs +0746 for i=1:numel(missingHMMs) +0747 %This is checked here because it could be that it is created by a +0748 %parallel process +0749 if ~exist(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm']),'file') && ~exist(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmw']),'file') +0750 %Check that the aligned FASTA file exists. It could be that it +0751 %is still being worked on by some other instance of the program +0752 %(the .faw file should then exist). This should not happen on a +0753 %single computer. It doesn't throw an error, because it should +0754 %finalize the ones it can +0755 if ~exist(fullfile(dataDir,'aligned',[missingHMMs{i} '.fa']),'file') +0756 EM=['The aligned FASTA file for ' missingHMMs{i} ' does not exist']; +0757 dispEM(EM,false); +0758 continue; +0759 end +0760 +0761 %If the multi-FASTA file is empty then save an empty aligned +0762 %file and continue +0763 s=dir(fullfile(dataDir,'aligned',[missingHMMs{i} '.fa'])); +0764 if s.bytes<=0 +0765 fid=fopen(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm']),'w'); +0766 fclose(fid); +0767 continue; +0768 end +0769 %Create a temporary file to indicate that it is working on the +0770 %KO. This is because hmmbuild cannot overwrite existing files +0771 fid=fopen(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmw']),'w'); +0772 fclose(fid); +0773 +0774 %Create HMM +0775 [status, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmbuild' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm']) '" "' fullfile(dataDir,'aligned',[missingHMMs{i} '.fa']) '"']); +0776 if status~=0 +0777 EM=['Error when training HMM for ' missingHMMs{i} ':\n' output]; +0778 dispEM(EM); +0779 end +0780 +0781 %Delete the temporary file +0782 delete(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmw'])); +0783 +0784 %Print the progress every 25 files +0785 if rem(i-1,25) == 0 +0786 progress=num2str(floor(100*numel(listFiles(fullfile(dataDir,'hmms','*.hmm')))/numel(KOModel.rxns))); +0787 progress=pad(progress,3,'left'); +0788 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); +0789 end +0790 end +0791 end +0792 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); +0793 else +0794 fprintf('Training the KEGG Orthology specific HMMs... COMPLETE\n'); +0795 end +0796 +0797 %Check which new .out files that should be generated. Check if training of +0798 %Hidden Markov models should be performed +0799 missingOUT=setdiff(KOModel.rxns,outFiles); +0800 if ~isempty(missingOUT) +0801 fprintf('Querying the user-specified FASTA file against the KEGG Orthology specific HMMs... 0%% complete'); +0802 missingOUT=missingOUT(randperm(RandStream.create('mrg32k3a','Seed',cputime()),numel(missingOUT))); +0803 for i=1:numel(missingOUT) +0804 %This is checked here because it could be that it is created by a +0805 %parallel process +0806 if ~exist(fullfile(outDir,[missingOUT{i} '.out']),'file') +0807 %Check that the HMM file exists. It should do so since %we are +0808 %saving empty files as well. Print a warning and continue if +0809 %not +0810 if ~exist(fullfile(dataDir,'hmms',[missingOUT{i} '.hmm']),'file') +0811 EM=['The HMM file for ' missingOUT{i} ' does not exist']; +0812 dispEM(EM,false); +0813 continue; +0814 end +0815 +0816 %Save an empty file to prevent several threads working on the +0817 %same file +0818 fid=fopen(fullfile(outDir,[missingOUT{i} '.out']),'w'); +0819 fclose(fid); +0820 +0821 %If the HMM file is empty then save an out file and continue +0822 s=dir(fullfile(dataDir,'hmms',[missingOUT{i} '.hmm'])); +0823 if s.bytes<=0 +0824 continue; +0825 end +0826 +0827 %Check each gene in the input file against this model +0828 [status, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmsearch' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(dataDir,'hmms',[missingOUT{i} '.hmm']) '" "' fastaFile '"']); +0829 if status~=0 +0830 EM=['Error when querying HMM for ' missingOUT{i} ':\n' output]; +0831 dispEM(EM); +0832 end +0833 +0834 %Save the output to a file +0835 fid=fopen(fullfile(outDir,[missingOUT{i} '.out']),'w'); +0836 fwrite(fid,output); +0837 fclose(fid); +0838 +0839 %Print the progress every 25 files +0840 if rem(i-1,25) == 0 +0841 progress=num2str(floor(100*numel(listFiles(fullfile(outDir,'*.out')))/numel(KOModel.rxns))); +0842 progress=pad(progress,3,'left'); +0843 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); +0844 end +0845 end +0846 end +0847 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); +0848 else +0849 fprintf('Querying the user-specified FASTA file against the KEGG Orthology specific HMMs... COMPLETE\n'); +0850 end +0851 0852 -0853 -0854 %***Begin retrieving the output and putting together the resulting model -0855 -0856 fprintf('Parsing the HMM search results... '); -0857 %Retrieve matched genes from the HMMs -0858 koGeneMat=zeros(numel(KOModel.rxns),3000); %Make room for 3000 genes -0859 genes=cell(3000,1); -0860 %Store the best score for a gene in a hash list (since it will be searching -0861 %many times) -0862 hTable = java.util.Hashtable; -0863 -0864 geneCounter=0; -0865 for i=1:numel(KOModel.rxns) -0866 if exist(fullfile(outDir,[KOModel.rxns{i} '.out']), 'file') -0867 fid=fopen(fullfile(outDir,[KOModel.rxns{i} '.out']),'r'); -0868 beginMatches=false; -0869 while 1 -0870 %Get the next line -0871 tline = fgetl(fid); -0872 -0873 %Abort at end of file -0874 if ~ischar(tline) -0875 break; -0876 end -0877 -0878 if and(beginMatches,strcmp(tline,' ------ inclusion threshold ------')) -0879 break; -0880 end -0881 -0882 if beginMatches==false -0883 %This is how the listing of matches begins -0884 if any(strfind(tline,'E-value ')) -0885 %Read one more line that is only padding -0886 tline = fgetl(fid); -0887 beginMatches=true; -0888 end -0889 else -0890 %If matches should be read -0891 if ~strcmp(tline,' [No hits detected that satisfy reporting thresholds]') && ~isempty(tline) -0892 elements=regexp(tline,' ','split'); -0893 elements=elements(cellfun(@any,elements)); -0894 -0895 %Check if the match is below the treshhold -0896 score=str2double(elements{1}); -0897 gene=elements{9}; -0898 if score<=cutOff -0899 %If the score is exactly 0, change it to a very -0900 %small value to avoid NaN -0901 if score==0 -0902 score=10^-250; -0903 end -0904 %Check if the gene is added already and, is so, get -0905 %the best score for it -0906 I=hTable.get(gene); -0907 if any(I) -0908 koGeneMat(i,I)=score; -0909 else -0910 geneCounter=geneCounter+1; -0911 %The gene was not present yet so add it -0912 hTable.put(gene,geneCounter); -0913 genes{geneCounter}=gene; -0914 koGeneMat(i,geneCounter)=score; -0915 end -0916 end -0917 else -0918 break; -0919 end -0920 end -0921 end -0922 fclose(fid); -0923 end -0924 end -0925 fprintf('COMPLETE\n'); -0926 -0927 fprintf('Removing gene, KEGG Orthology associations below minScoreRatioKO, minScoreRatioG... '); -0928 koGeneMat=koGeneMat(:,1:geneCounter); -0929 -0930 %Remove the genes for each KO that are below minScoreRatioKO. -0931 for i=1:size(koGeneMat,1) -0932 J=find(koGeneMat(i,:)); -0933 if any(J) -0934 koGeneMat(i,J(log(koGeneMat(i,J))/log(min(koGeneMat(i,J)))<minScoreRatioKO))=0; -0935 end -0936 end -0937 -0938 %Remove the KOs for each gene that are below minScoreRatioG -0939 for i=1:size(koGeneMat,2) -0940 J=find(koGeneMat(:,i)); -0941 if any(J) -0942 koGeneMat(J(log(koGeneMat(J,i))/log(min(koGeneMat(J,i)))<minScoreRatioG),i)=0; -0943 end -0944 end -0945 fprintf('COMPLETE\n'); -0946 -0947 fprintf('Adding gene annotations to the model... '); -0948 %Create the new model -0949 model.genes=genes(1:geneCounter); -0950 model.grRules=cell(numel(model.rxns),1); -0951 model.grRules(:)={''}; -0952 model.rxnGeneMat=sparse(numel(model.rxns),numel(model.genes)); -0953 -0954 %Loop through the reactions and add the corresponding genes -0955 for i=1:numel(model.rxns) -0956 if isstruct(model.rxnMiriams{i}) -0957 %Get all KOs -0958 I=find(strcmpi(model.rxnMiriams{i}.name,'kegg.orthology')); -0959 KOs=model.rxnMiriams{i}.value(I); -0960 %Find the KOs and the corresponding genes -0961 J=ismember(KOModel.rxns,KOs); -0962 [~, K]=find(koGeneMat(J,:)); -0963 -0964 if any(K) -0965 model.rxnGeneMat(i,K)=1; -0966 %Also delete KOs for which no genes were found. If no genes at -0967 %all were matched to the reaction it will be deleted later -0968 L=sum(koGeneMat(J,:),2)==0; -0969 model.rxnMiriams{i}.value(I(L))=[]; -0970 model.rxnMiriams{i}.name(I(L))=[]; -0971 end -0972 end -0973 end -0974 fprintf('COMPLETE\n'); -0975 -0976 %Find and delete all reactions without genes. This also removes genes that -0977 %are not used (which could happen because minScoreRatioG and -0978 %minScoreRatioKO). If keepSpontaneous==true, the spontaneous reactions -0979 %without genes are kept in the model. Spontaneous reactions with original -0980 %gene associations are treated in the same way, like the rest of the -0981 %reactions - if gene associations were removed during HMM search, such -0982 %reactions are deleted from the model -0983 if keepSpontaneous==true -0984 %Not the most comprise way to delete reactions without genes, but this -0985 %makes the code easier to understand. Firstly the non-spontaneous -0986 %reactions without genes are removed. After that, the second deletion -0987 %step removes spontaneous reactions, which had gene associations before -0988 %HMM search, but no longer have after it -0989 fprintf('Removing non-spontaneous reactions which after HMM search no longer have GPR rules... '); -0990 I=~any(model.rxnGeneMat,2)&~ismember(model.rxns,isSpontaneous); -0991 model=removeReactions(model,I,true,true); -0992 I=~any(model.rxnGeneMat,2)&ismember(model.rxns,spontRxnsWithGenes); -0993 model=removeReactions(model,I,true,true); -0994 else -0995 %Just simply check for any new reactions without genes and remove -0996 %it -0997 fprintf('Removing reactions which after HMM search no longer have GPR rules... '); -0998 I=~any(model.rxnGeneMat,2); -0999 model=removeReactions(model,I,true,true); -1000 end -1001 fprintf('COMPLETE\n'); -1002 -1003 fprintf('Constructing GPR rules and finalizing the model... '); -1004 %Add the gene associations as 'or' -1005 for i=1:numel(model.rxns) -1006 %Find the involved genes -1007 I=find(model.rxnGeneMat(i,:)); -1008 if any(I) -1009 model.grRules{i}=['(' model.genes{I(1)}]; -1010 for j=2:numel(I) -1011 model.grRules{i}=[model.grRules{i} ' or ' model.genes{I(j)}]; -1012 end -1013 model.grRules{i}=[model.grRules{i} ')']; -1014 end -1015 end -1016 -1017 %Fix grRules and reconstruct rxnGeneMat -1018 [grRules,rxnGeneMat] = standardizeGrRules(model,false); %Give detailed output -1019 model.grRules = grRules; -1020 model.rxnGeneMat = rxnGeneMat; -1021 -1022 %Add the description to the reactions -1023 for i=1:numel(model.rxns) -1024 if ~isempty(model.rxnNotes{i}) -1025 model.rxnNotes(i)=strcat('Included by getKEGGModelForOrganism (using HMMs).',model.rxnNotes(i)); -1026 model.rxnNotes(i)=strrep(model.rxnNotes(i),'.','. '); -1027 else -1028 model.rxnNotes(i)={'Included by getKEGGModelForOrganism (using HMMs)'}; -1029 end -1030 end -1031 %Remove the temp fasta file -1032 delete(fastaFile) -1033 fprintf('COMPLETE\n\n*** Model reconstruction complete ***\n'); -1034 end -1035 -1036 function files=listFiles(directory) -1037 %Supporter function to list the files in a directory and return them as a -1038 %cell array -1039 temp=dir(directory); -1040 files=cell(numel(temp),1); -1041 for i=1:numel(temp) -1042 files{i}=temp(i,1).name; -1043 end -1044 files=strrep(files,'.fa',''); -1045 files=strrep(files,'.hmm',''); -1046 files=strrep(files,'.out',''); -1047 files=strrep(files,'.faw',''); -1048 end +0853 %***Begin retrieving the output and putting together the resulting model +0854 +0855 fprintf('Parsing the HMM search results... '); +0856 %Retrieve matched genes from the HMMs +0857 koGeneMat=zeros(numel(KOModel.rxns),3000); %Make room for 3000 genes +0858 genes=cell(3000,1); +0859 %Store the best score for a gene in a hash list (since it will be searching +0860 %many times) +0861 hTable = java.util.Hashtable; +0862 +0863 geneCounter=0; +0864 for i=1:numel(KOModel.rxns) +0865 if exist(fullfile(outDir,[KOModel.rxns{i} '.out']), 'file') +0866 fid=fopen(fullfile(outDir,[KOModel.rxns{i} '.out']),'r'); +0867 beginMatches=false; +0868 while 1 +0869 %Get the next line +0870 tline = fgetl(fid); +0871 +0872 %Abort at end of file +0873 if ~ischar(tline) +0874 break; +0875 end +0876 +0877 if and(beginMatches,strcmp(tline,' ------ inclusion threshold ------')) +0878 break; +0879 end +0880 +0881 if beginMatches==false +0882 %This is how the listing of matches begins +0883 if any(strfind(tline,'E-value ')) +0884 %Read one more line that is only padding +0885 tline = fgetl(fid); +0886 beginMatches=true; +0887 end +0888 else +0889 %If matches should be read +0890 if ~strcmp(tline,' [No hits detected that satisfy reporting thresholds]') && ~isempty(tline) +0891 elements=regexp(tline,' ','split'); +0892 elements=elements(cellfun(@any,elements)); +0893 +0894 %Check if the match is below the treshhold +0895 score=str2double(elements{1}); +0896 gene=elements{9}; +0897 if score<=cutOff +0898 %If the score is exactly 0, change it to a very +0899 %small value to avoid NaN +0900 if score==0 +0901 score=10^-250; +0902 end +0903 %Check if the gene is added already and, is so, get +0904 %the best score for it +0905 I=hTable.get(gene); +0906 if any(I) +0907 koGeneMat(i,I)=score; +0908 else +0909 geneCounter=geneCounter+1; +0910 %The gene was not present yet so add it +0911 hTable.put(gene,geneCounter); +0912 genes{geneCounter}=gene; +0913 koGeneMat(i,geneCounter)=score; +0914 end +0915 end +0916 else +0917 break; +0918 end +0919 end +0920 end +0921 fclose(fid); +0922 end +0923 end +0924 fprintf('COMPLETE\n'); +0925 +0926 fprintf('Removing gene, KEGG Orthology associations below minScoreRatioKO, minScoreRatioG... '); +0927 koGeneMat=koGeneMat(:,1:geneCounter); +0928 +0929 %Remove the genes for each KO that are below minScoreRatioKO. +0930 for i=1:size(koGeneMat,1) +0931 J=find(koGeneMat(i,:)); +0932 if any(J) +0933 koGeneMat(i,J(log(koGeneMat(i,J))/log(min(koGeneMat(i,J)))<minScoreRatioKO))=0; +0934 end +0935 end +0936 +0937 %Remove the KOs for each gene that are below minScoreRatioG +0938 for i=1:size(koGeneMat,2) +0939 J=find(koGeneMat(:,i)); +0940 if any(J) +0941 koGeneMat(J(log(koGeneMat(J,i))/log(min(koGeneMat(J,i)))<minScoreRatioG),i)=0; +0942 end +0943 end +0944 fprintf('COMPLETE\n'); +0945 +0946 fprintf('Adding gene annotations to the model... '); +0947 %Create the new model +0948 model.genes=genes(1:geneCounter); +0949 model.grRules=cell(numel(model.rxns),1); +0950 model.grRules(:)={''}; +0951 model.rxnGeneMat=sparse(numel(model.rxns),numel(model.genes)); +0952 +0953 %Loop through the reactions and add the corresponding genes +0954 for i=1:numel(model.rxns) +0955 if isstruct(model.rxnMiriams{i}) +0956 %Get all KOs +0957 I=find(strcmpi(model.rxnMiriams{i}.name,'kegg.orthology')); +0958 KOs=model.rxnMiriams{i}.value(I); +0959 %Find the KOs and the corresponding genes +0960 J=ismember(KOModel.rxns,KOs); +0961 [~, K]=find(koGeneMat(J,:)); +0962 +0963 if any(K) +0964 model.rxnGeneMat(i,K)=1; +0965 %Also delete KOs for which no genes were found. If no genes at +0966 %all were matched to the reaction it will be deleted later +0967 L=sum(koGeneMat(J,:),2)==0; +0968 model.rxnMiriams{i}.value(I(L))=[]; +0969 model.rxnMiriams{i}.name(I(L))=[]; +0970 end +0971 end +0972 end +0973 fprintf('COMPLETE\n'); +0974 +0975 %Find and delete all reactions without genes. This also removes genes that +0976 %are not used (which could happen because minScoreRatioG and +0977 %minScoreRatioKO). If keepSpontaneous==true, the spontaneous reactions +0978 %without genes are kept in the model. Spontaneous reactions with original +0979 %gene associations are treated in the same way, like the rest of the +0980 %reactions - if gene associations were removed during HMM search, such +0981 %reactions are deleted from the model +0982 if keepSpontaneous==true +0983 %Not the most comprise way to delete reactions without genes, but this +0984 %makes the code easier to understand. Firstly the non-spontaneous +0985 %reactions without genes are removed. After that, the second deletion +0986 %step removes spontaneous reactions, which had gene associations before +0987 %HMM search, but no longer have after it +0988 fprintf('Removing non-spontaneous reactions which after HMM search no longer have GPR rules... '); +0989 I=~any(model.rxnGeneMat,2)&~ismember(model.rxns,isSpontaneous); +0990 model=removeReactions(model,I,true,true); +0991 I=~any(model.rxnGeneMat,2)&ismember(model.rxns,spontRxnsWithGenes); +0992 model=removeReactions(model,I,true,true); +0993 else +0994 %Just simply check for any new reactions without genes and remove +0995 %it +0996 fprintf('Removing reactions which after HMM search no longer have GPR rules... '); +0997 I=~any(model.rxnGeneMat,2); +0998 model=removeReactions(model,I,true,true); +0999 end +1000 fprintf('COMPLETE\n'); +1001 +1002 fprintf('Constructing GPR rules and finalizing the model... '); +1003 %Add the gene associations as 'or' +1004 for i=1:numel(model.rxns) +1005 %Find the involved genes +1006 I=find(model.rxnGeneMat(i,:)); +1007 if any(I) +1008 model.grRules{i}=['(' model.genes{I(1)}]; +1009 for j=2:numel(I) +1010 model.grRules{i}=[model.grRules{i} ' or ' model.genes{I(j)}]; +1011 end +1012 model.grRules{i}=[model.grRules{i} ')']; +1013 end +1014 end +1015 +1016 %Fix grRules and reconstruct rxnGeneMat +1017 [grRules,rxnGeneMat] = standardizeGrRules(model,false); %Give detailed output +1018 model.grRules = grRules; +1019 model.rxnGeneMat = rxnGeneMat; +1020 +1021 %Add the description to the reactions +1022 for i=1:numel(model.rxns) +1023 if ~isempty(model.rxnNotes{i}) +1024 model.rxnNotes(i)=strcat('Included by getKEGGModelForOrganism (using HMMs).',model.rxnNotes(i)); +1025 model.rxnNotes(i)=strrep(model.rxnNotes(i),'.','. '); +1026 else +1027 model.rxnNotes(i)={'Included by getKEGGModelForOrganism (using HMMs)'}; +1028 end +1029 end +1030 %Remove the temp fasta file +1031 delete(fastaFile) +1032 fprintf('COMPLETE\n\n*** Model reconstruction complete ***\n'); +1033 end +1034 +1035 function files=listFiles(directory) +1036 %Supporter function to list the files in a directory and return them as a +1037 %cell array +1038 temp=dir(directory); +1039 files=cell(numel(temp),1); +1040 for i=1:numel(temp) +1041 files{i}=temp(i,1).name; +1042 end +1043 files=strrep(files,'.fa',''); +1044 files=strrep(files,'.hmm',''); +1045 files=strrep(files,'.out',''); +1046 files=strrep(files,'.faw',''); +1047 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/kegg/getMetsFromKEGG.html b/doc/external/kegg/getMetsFromKEGG.html index b5a7ac88..659d38ef 100644 --- a/doc/external/kegg/getMetsFromKEGG.html +++ b/doc/external/kegg/getMetsFromKEGG.html @@ -168,223 +168,224 @@

    SOURCE CODE ^if nargin<1 0066 keggPath='RAVEN/external/kegg'; -0067 end -0068 -0069 [ST, I]=dbstack('-completenames'); -0070 ravenPath=fileparts(fileparts(fileparts(ST(I).file))); -0071 metsFile=fullfile(ravenPath,'external','kegg','keggMets.mat'); -0072 if exist(metsFile, 'file') -0073 fprintf(['Importing KEGG metabolites from ' strrep(metsFile,'\','/') '... ']); -0074 load(metsFile); -0075 else -0076 fprintf(['NOTE: Cannot locate ' strrep(metsFile,'\','/') ', it will therefore be generated from the local KEGG database\n']); -0077 if ~exist(fullfile(keggPath,'compound'),'file') || ~exist(fullfile(keggPath,'compound.inchi'),'file') -0078 EM=fprintf(['The files ''compound'' and ''compound.inchi'' cannot be located at ' strrep(keggPath,'\','/') '/ and should be downloaded from the KEGG FTP.\n']); -0079 dispEM(EM); -0080 else -0081 fprintf('Generating keggMets.mat file... '); -0082 %Add new functionality in the order specified in models -0083 model.id='KEGG'; -0084 model.name='Automatically generated from KEGG database'; -0085 -0086 %Preallocate memory for 30000 metabolites -0087 model.mets=cell(30000,1); -0088 model.metNames=cell(30000,1); -0089 model.metFormulas=cell(30000,1); -0090 model.metMiriams=cell(30000,1); -0091 -0092 %First load information on metabolite ID, metabolite name, -0093 %composition, and ChEBI -0094 -0095 fid = fopen(fullfile(keggPath,'compound'), 'r'); -0096 -0097 %Keeps track of how many metabolites that have been added -0098 metCounter=0; -0099 -0100 %Loop through the file -0101 while 1 -0102 %Get the next line -0103 tline = fgetl(fid); -0104 -0105 %Abort at end of file -0106 if ~ischar(tline) -0107 break; -0108 end -0109 -0110 %Skip '///' -0111 if numel(tline)<12 -0112 continue; -0113 end -0114 -0115 %Check if it's a new reaction -0116 if strcmp(tline(1:12),'ENTRY ') -0117 metCounter=metCounter+1; -0118 -0119 %Add empty strings where there should be such -0120 model.metNames{metCounter}=''; -0121 model.metFormulas{metCounter}=''; -0122 -0123 %Add compound ID (always 6 characters) -0124 model.mets{metCounter}=tline(13:18); -0125 -0126 %Add the KEGG id as metMiriams -0127 if length(model.mets{metCounter})==6 -0128 miriamStruct=model.metMiriams{metCounter}; -0129 if strcmp('G',model.mets{metCounter}(1)) -0130 miriamStruct.name{1,1}='kegg.glycan'; -0131 else -0132 miriamStruct.name{1,1}='kegg.compound'; -0133 end -0134 miriamStruct.value{1,1}=tline(13:18); -0135 model.metMiriams{metCounter}=miriamStruct; -0136 end -0137 end -0138 -0139 %Add name -0140 if strcmp(tline(1:12),'NAME ') -0141 %If there are synonyms, then the last character is ';' -0142 if strcmp(tline(end),';') -0143 model.metNames{metCounter}=tline(13:end-1); -0144 %Semicolon can also occur in the middle, separating -0145 %several synonims in the same line -0146 model.metNames{metCounter} = regexprep(model.metNames{metCounter},';.+',''); -0147 elseif regexp(tline,';') -0148 model.metNames{metCounter}=tline(13:end); -0149 model.metNames{metCounter} = regexprep(model.metNames{metCounter},';.+',''); -0150 else -0151 model.metNames{metCounter}=tline(13:end); -0152 end -0153 end -0154 -0155 %Add composition -0156 if strcmp(tline(1:12),'FORMULA ') -0157 model.metFormulas{metCounter}=tline(13:end); -0158 end -0159 -0160 %Add PubChem id -0161 if numel(tline)>21 -0162 if strcmp(tline(13:21),'PubChem: ') -0163 if isstruct(model.metMiriams{metCounter}) -0164 addToIndex=numel(model.metMiriams{metCounter}.name)+1; -0165 else -0166 addToIndex=1; -0167 end -0168 miriamStruct=model.metMiriams{metCounter}; -0169 miriamStruct.name{addToIndex,1}='pubchem.substance'; -0170 miriamStruct.value{addToIndex,1}=tline(22:end); -0171 model.metMiriams{metCounter}=miriamStruct; -0172 end -0173 end -0174 -0175 %Add CHEBI id -0176 if numel(tline)>19 -0177 if strcmp(tline(13:19),'ChEBI: ') -0178 if isstruct(model.metMiriams{metCounter}) -0179 addToIndex=numel(model.metMiriams{metCounter}.name)+1; -0180 else -0181 addToIndex=1; -0182 end -0183 chebiIDs=strsplit(tline(20:end),' '); -0184 miriamStruct=model.metMiriams{metCounter}; -0185 for i=1:numel(chebiIDs) -0186 miriamStruct.name{addToIndex,1}='chebi'; -0187 miriamStruct.value{addToIndex,1}=strcat('CHEBI:',chebiIDs{i}); -0188 addToIndex=addToIndex+1; -0189 end -0190 model.metMiriams{metCounter}=miriamStruct; -0191 end -0192 end -0193 end -0194 -0195 %Close the file -0196 fclose(fid); -0197 -0198 %If too much space was allocated, shrink the model -0199 model.mets=model.mets(1:metCounter); -0200 model.metNames=model.metNames(1:metCounter); -0201 model.metFormulas=model.metFormulas(1:metCounter); -0202 model.metMiriams=model.metMiriams(1:metCounter); -0203 -0204 %Then load the InChI strings from another file. Not all metabolites -0205 %will be present in the list -0206 -0207 inchIDs=cell(numel(model.mets),1); -0208 inchis=cell(numel(model.mets),1); -0209 -0210 %The format is metID*tab*string -0211 -0212 fid = fopen(fullfile(keggPath,'compound.inchi'), 'r'); -0213 -0214 %Loop through the file -0215 counter=1; -0216 while 1 -0217 %Get the next line -0218 tline = fgetl(fid); -0219 -0220 %Abort at end of file -0221 if ~ischar(tline) -0222 break; -0223 end -0224 -0225 %Get the ID and the InChI -0226 inchIDs{counter}=tline(1:6); -0227 inchis{counter}=tline(14:end); -0228 counter=counter+1; -0229 end -0230 -0231 %Close the file -0232 fclose(fid); -0233 -0234 inchIDs=inchIDs(1:counter-1); -0235 inchis=inchis(1:counter-1); -0236 -0237 %Find the metabolites that had InChI strings and add them to the -0238 %model -0239 [a, b]=ismember(inchIDs,model.mets); -0240 -0241 %If there were mets with InChIs but that were not in the list -0242 if ~all(a) -0243 EM='Not all metabolites with InChI strings were found in the original list'; -0244 disp(EM); -0245 end -0246 -0247 model.inchis=cell(numel(model.mets),1); -0248 model.inchis(:)={''}; -0249 model.inchis(b)=inchis; -0250 -0251 %Remove composition if InChI was found -0252 model.metFormulas(b)={''}; -0253 -0254 %Ensuring that all model.metMiriams.value consist only of strings, -0255 %no double -0256 for i=1:(numel(model.mets)) -0257 for j=1:(numel(model.metMiriams{i})) -0258 if isa(model.metMiriams{i}.value{j},'double') -0259 model.metMiriams{i}.value{j}=num2str(model.metMiriams{i}.value{j}); -0260 end -0261 end -0262 end -0263 -0264 %Removing fronting and trailing whitespace from metNames -0265 model.metNames = deblank(model.metNames); -0266 -0267 %Fixing redundant metNames. The first occurence of particular -0268 %metabolite name is not changed, but starting from the second -0269 %occurence, original metabolite name is concatenated with KEGG -0270 %COMPOUND id between the brackets -0271 for i=1:(numel(model.metNames)) -0272 if ~isempty(model.metNames{i}) -0273 if sum(ismember(model.metNames(1:i-1),model.metNames(i)))>=1 -0274 model.metNames(i) = strcat(model.metNames(i), ' (', model.mets(i),')'); -0275 end -0276 end -0277 end -0278 %Saves the model -0279 save(metsFile,'model'); -0280 end -0281 end -0282 fprintf('COMPLETE\n'); -0283 end +0067 else +0068 keggPath=char(keggPath); +0069 end +0070 +0071 ravenPath=findRAVENroot(); +0072 metsFile=fullfile(ravenPath,'external','kegg','keggMets.mat'); +0073 if exist(metsFile, 'file') +0074 fprintf(['Importing KEGG metabolites from ' strrep(metsFile,'\','/') '... ']); +0075 load(metsFile); +0076 else +0077 fprintf(['NOTE: Cannot locate ' strrep(metsFile,'\','/') ', it will therefore be generated from the local KEGG database\n']); +0078 if ~exist(fullfile(keggPath,'compound'),'file') || ~exist(fullfile(keggPath,'compound.inchi'),'file') +0079 EM=fprintf(['The files ''compound'' and ''compound.inchi'' cannot be located at ' strrep(keggPath,'\','/') '/ and should be downloaded from the KEGG FTP.\n']); +0080 dispEM(EM); +0081 else +0082 fprintf('Generating keggMets.mat file... '); +0083 %Add new functionality in the order specified in models +0084 model.id='KEGG'; +0085 model.name='Automatically generated from KEGG database'; +0086 +0087 %Preallocate memory for 30000 metabolites +0088 model.mets=cell(30000,1); +0089 model.metNames=cell(30000,1); +0090 model.metFormulas=cell(30000,1); +0091 model.metMiriams=cell(30000,1); +0092 +0093 %First load information on metabolite ID, metabolite name, +0094 %composition, and ChEBI +0095 +0096 fid = fopen(fullfile(keggPath,'compound'), 'r'); +0097 +0098 %Keeps track of how many metabolites that have been added +0099 metCounter=0; +0100 +0101 %Loop through the file +0102 while 1 +0103 %Get the next line +0104 tline = fgetl(fid); +0105 +0106 %Abort at end of file +0107 if ~ischar(tline) +0108 break; +0109 end +0110 +0111 %Skip '///' +0112 if numel(tline)<12 +0113 continue; +0114 end +0115 +0116 %Check if it's a new reaction +0117 if strcmp(tline(1:12),'ENTRY ') +0118 metCounter=metCounter+1; +0119 +0120 %Add empty strings where there should be such +0121 model.metNames{metCounter}=''; +0122 model.metFormulas{metCounter}=''; +0123 +0124 %Add compound ID (always 6 characters) +0125 model.mets{metCounter}=tline(13:18); +0126 +0127 %Add the KEGG id as metMiriams +0128 if length(model.mets{metCounter})==6 +0129 miriamStruct=model.metMiriams{metCounter}; +0130 if strcmp('G',model.mets{metCounter}(1)) +0131 miriamStruct.name{1,1}='kegg.glycan'; +0132 else +0133 miriamStruct.name{1,1}='kegg.compound'; +0134 end +0135 miriamStruct.value{1,1}=tline(13:18); +0136 model.metMiriams{metCounter}=miriamStruct; +0137 end +0138 end +0139 +0140 %Add name +0141 if strcmp(tline(1:12),'NAME ') +0142 %If there are synonyms, then the last character is ';' +0143 if strcmp(tline(end),';') +0144 model.metNames{metCounter}=tline(13:end-1); +0145 %Semicolon can also occur in the middle, separating +0146 %several synonims in the same line +0147 model.metNames{metCounter} = regexprep(model.metNames{metCounter},';.+',''); +0148 elseif regexp(tline,';') +0149 model.metNames{metCounter}=tline(13:end); +0150 model.metNames{metCounter} = regexprep(model.metNames{metCounter},';.+',''); +0151 else +0152 model.metNames{metCounter}=tline(13:end); +0153 end +0154 end +0155 +0156 %Add composition +0157 if strcmp(tline(1:12),'FORMULA ') +0158 model.metFormulas{metCounter}=tline(13:end); +0159 end +0160 +0161 %Add PubChem id +0162 if numel(tline)>21 +0163 if strcmp(tline(13:21),'PubChem: ') +0164 if isstruct(model.metMiriams{metCounter}) +0165 addToIndex=numel(model.metMiriams{metCounter}.name)+1; +0166 else +0167 addToIndex=1; +0168 end +0169 miriamStruct=model.metMiriams{metCounter}; +0170 miriamStruct.name{addToIndex,1}='pubchem.substance'; +0171 miriamStruct.value{addToIndex,1}=tline(22:end); +0172 model.metMiriams{metCounter}=miriamStruct; +0173 end +0174 end +0175 +0176 %Add CHEBI id +0177 if numel(tline)>19 +0178 if strcmp(tline(13:19),'ChEBI: ') +0179 if isstruct(model.metMiriams{metCounter}) +0180 addToIndex=numel(model.metMiriams{metCounter}.name)+1; +0181 else +0182 addToIndex=1; +0183 end +0184 chebiIDs=strsplit(tline(20:end),' '); +0185 miriamStruct=model.metMiriams{metCounter}; +0186 for i=1:numel(chebiIDs) +0187 miriamStruct.name{addToIndex,1}='chebi'; +0188 miriamStruct.value{addToIndex,1}=strcat('CHEBI:',chebiIDs{i}); +0189 addToIndex=addToIndex+1; +0190 end +0191 model.metMiriams{metCounter}=miriamStruct; +0192 end +0193 end +0194 end +0195 +0196 %Close the file +0197 fclose(fid); +0198 +0199 %If too much space was allocated, shrink the model +0200 model.mets=model.mets(1:metCounter); +0201 model.metNames=model.metNames(1:metCounter); +0202 model.metFormulas=model.metFormulas(1:metCounter); +0203 model.metMiriams=model.metMiriams(1:metCounter); +0204 +0205 %Then load the InChI strings from another file. Not all metabolites +0206 %will be present in the list +0207 +0208 inchIDs=cell(numel(model.mets),1); +0209 inchis=cell(numel(model.mets),1); +0210 +0211 %The format is metID*tab*string +0212 +0213 fid = fopen(fullfile(keggPath,'compound.inchi'), 'r'); +0214 +0215 %Loop through the file +0216 counter=1; +0217 while 1 +0218 %Get the next line +0219 tline = fgetl(fid); +0220 +0221 %Abort at end of file +0222 if ~ischar(tline) +0223 break; +0224 end +0225 +0226 %Get the ID and the InChI +0227 inchIDs{counter}=tline(1:6); +0228 inchis{counter}=tline(14:end); +0229 counter=counter+1; +0230 end +0231 +0232 %Close the file +0233 fclose(fid); +0234 +0235 inchIDs=inchIDs(1:counter-1); +0236 inchis=inchis(1:counter-1); +0237 +0238 %Find the metabolites that had InChI strings and add them to the +0239 %model +0240 [a, b]=ismember(inchIDs,model.mets); +0241 +0242 %If there were mets with InChIs but that were not in the list +0243 if ~all(a) +0244 EM='Not all metabolites with InChI strings were found in the original list'; +0245 disp(EM); +0246 end +0247 +0248 model.inchis=cell(numel(model.mets),1); +0249 model.inchis(:)={''}; +0250 model.inchis(b)=inchis; +0251 +0252 %Remove composition if InChI was found +0253 model.metFormulas(b)={''}; +0254 +0255 %Ensuring that all model.metMiriams.value consist only of strings, +0256 %no double +0257 for i=1:(numel(model.mets)) +0258 for j=1:(numel(model.metMiriams{i})) +0259 if isa(model.metMiriams{i}.value{j},'double') +0260 model.metMiriams{i}.value{j}=num2str(model.metMiriams{i}.value{j}); +0261 end +0262 end +0263 end +0264 +0265 %Removing fronting and trailing whitespace from metNames +0266 model.metNames = deblank(model.metNames); +0267 +0268 %Fixing redundant metNames. The first occurence of particular +0269 %metabolite name is not changed, but starting from the second +0270 %occurence, original metabolite name is concatenated with KEGG +0271 %COMPOUND id between the brackets +0272 for i=1:(numel(model.metNames)) +0273 if ~isempty(model.metNames{i}) +0274 if sum(ismember(model.metNames(1:i-1),model.metNames(i)))>=1 +0275 model.metNames(i) = strcat(model.metNames(i), ' (', model.mets(i),')'); +0276 end +0277 end +0278 end +0279 %Saves the model +0280 save(metsFile,'model'); +0281 end +0282 end +0283 fprintf('COMPLETE\n'); +0284 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/kegg/getModelFromKEGG.html b/doc/external/kegg/getModelFromKEGG.html index 0a6dc9f0..90800f00 100644 --- a/doc/external/kegg/getModelFromKEGG.html +++ b/doc/external/kegg/getModelFromKEGG.html @@ -134,242 +134,243 @@

    SOURCE CODE ^if nargin<1 0048 keggPath='RAVEN/external/kegg'; -0049 end -0050 if nargin<2 -0051 keepSpontaneous=true; -0052 end -0053 if nargin<3 -0054 keepUndefinedStoich=true; -0055 end -0056 if nargin<4 -0057 keepIncomplete=true; -0058 end -0059 if nargin<5 -0060 keepGeneral=false; -0061 end -0062 -0063 [ST, I]=dbstack('-completenames'); -0064 ravenPath=fileparts(fileparts(fileparts(ST(I).file))); -0065 modelFile=fullfile(ravenPath,'external','kegg','keggModel.mat'); -0066 if exist(modelFile, 'file') && isNewestFile(ravenPath) -0067 fprintf(['Importing the global KEGG model from ' strrep(modelFile,'\','/') '... ']); -0068 load(modelFile); -0069 fprintf('COMPLETE\n'); -0070 else -0071 fprintf(['NOTE: The file ' strrep(modelFile,'\','/') ' does not exist or is out-of-date and therefore will be (re)generated\n']); -0072 %First get all reactions -0073 [model,isSpontaneous,isUndefinedStoich,isIncomplete,isGeneral]=getRxnsFromKEGG(keggPath); -0074 -0075 %Get the KO ids that are associated with any of the reactions. They -0076 %will be used later on to create a rxn-gene matrix -0077 KOs=cell(numel(model.rxns)*2,1); -0078 %Make room for two KO ids per reaction -0079 -0080 addToIndex=1; -0081 %Add all KO ids that are used -0082 for i=1:numel(model.rxns) -0083 if isstruct(model.rxnMiriams{i}) -0084 for j=1:numel(model.rxnMiriams{i}.name) -0085 if strcmpi('kegg.orthology',model.rxnMiriams{i}.name{j}) -0086 %Add the KO id -0087 KOs(addToIndex)=model.rxnMiriams{i}.value(j); -0088 addToIndex=addToIndex+1; -0089 end -0090 end -0091 end -0092 end -0093 -0094 KOs=KOs(1:addToIndex-1); -0095 KOs=unique(KOs); -0096 -0097 %Get all genes from any organism in KEGG that is associated with any of -0098 %the KOs -0099 KOModel=getGenesFromKEGG(keggPath,KOs); -0100 -0101 fprintf('Pruning the global KEGG model from the partially annotated, lumped KEGG Orthology entries... ') -0102 model.genes=KOModel.genes; -0103 -0104 %It can be that there are KOs from the reactions that have no database -0105 %entry. These are (as far as I have seen) lumped versions of other KOs -0106 %and should be removed -0107 KOsToRemove=setdiff(KOs, KOModel.rxns); -0108 -0109 %Loop through all reactions and delete the KOs that were not found -0110 for i=1:numel(model.rxns) -0111 if isstruct(model.rxnMiriams{i}) -0112 for j=1:numel(model.rxnMiriams{i}.name) -0113 toDel=[]; -0114 if strcmp(model.rxnMiriams{i}.name{j},'kegg.orthology') -0115 if ismember(model.rxnMiriams{i}.value{j},KOsToRemove) -0116 toDel=[toDel;j]; -0117 end -0118 end -0119 end -0120 %Delete the KOs -0121 if any(toDel) -0122 %If all posts are deleted, then delete the whole structure -0123 if numel(toDel)==j -0124 model.rxnMiriams{i}=[]; -0125 else -0126 model.rxnMiriams{i}.name(toDel)=[]; -0127 model.rxnMiriams{i}.value(toDel)=[]; -0128 end -0129 end -0130 end -0131 end -0132 fprintf('COMPLETE\n'); -0133 -0134 fprintf('Constructing the rxnGeneMat for the global KEGG model... 0%% complete'); -0135 %Create the rxnGeneMat for the reactions. This is simply done by -0136 %merging the gene associations for all the involved KOs -0137 r=zeros(10000000,1); -0138 %Store the positions since it's slow to write to a sparse array in a -0139 %loop -0140 c=zeros(10000000,1); -0141 counter=1; -0142 for i=1:numel(model.rxns) -0143 if isstruct(model.rxnMiriams{i}) -0144 I=strncmp('kegg.orthology',model.rxnMiriams{i}.name,18); -0145 if any(I) -0146 [J, K]=ismember(model.rxnMiriams{i}.value(I),KOModel.rxns); -0147 %Find all gene indexes that correspond to any of these KOs -0148 [~, L]=find(KOModel.rxnGeneMat(K(J),:)); -0149 if any(L) -0150 %Allocate room for more elements if needed -0151 if counter+numel(L)-1>=numel(r) -0152 r=[r;zeros(numel(r),1)]; -0153 c=[c;zeros(numel(c),1)]; -0154 end -0155 r(counter:counter+numel(L)-1)=ones(numel(L),1)*i; -0156 c(counter:counter+numel(L)-1)=L(:); -0157 counter=counter+numel(L); -0158 end -0159 end -0160 end -0161 if rem(i-1,100) == 0 -0162 progress=pad(num2str(floor(i/numel(model.rxns)*100)),3,'left'); -0163 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); -0164 end -0165 end -0166 -0167 model.rxnGeneMat=sparse(r(1:counter-1),c(1:counter-1),ones(counter-1,1)); -0168 if size(model.rxnGeneMat,1)~=numel(model.rxns) || size(model.rxnGeneMat,2)~=numel(KOModel.genes) -0169 model.rxnGeneMat(numel(model.rxns),numel(KOModel.genes))=0; -0170 end -0171 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); -0172 -0173 %Then get all metabolites -0174 metModel=getMetsFromKEGG(keggPath); -0175 -0176 fprintf('Finalizing the global KEGG model... '); -0177 %Add information about all metabolites to the model -0178 [a, b]=ismember(model.mets,metModel.mets); -0179 a=find(a); -0180 b=b(a); -0181 -0182 if ~isfield(model,'metNames') -0183 model.metNames=cell(numel(model.mets),1); -0184 model.metNames(:)={''}; -0185 end -0186 model.metNames(a)=metModel.metNames(b); -0187 -0188 if ~isfield(model,'metFormulas') -0189 model.metFormulas=cell(numel(model.mets),1); -0190 model.metFormulas(:)={''}; -0191 end -0192 model.metFormulas(a)=metModel.metFormulas(b); -0193 -0194 if ~isfield(model,'inchis') -0195 model.inchis=cell(numel(model.mets),1); -0196 model.inchis(:)={''}; -0197 end -0198 model.inchis(a)=metModel.inchis(b); -0199 -0200 if ~isfield(model,'metMiriams') -0201 model.metMiriams=cell(numel(model.mets),1); -0202 end -0203 model.metMiriams(a)=metModel.metMiriams(b); -0204 -0205 %The composition should be loaded from InChIs when available -0206 I=find(~cellfun(@isempty,model.inchis)); -0207 for i=1:numel(I) -0208 S=regexp(model.inchis(I(i)),'/','split'); -0209 S=S{1}; -0210 if numel(S)>=2 -0211 %Don't copy if it doesn't look good -0212 model.metFormulas(I(i))=S(2); -0213 end -0214 end -0215 -0216 %Put all metabolites in one compartment called 's' (for system). This -0217 %is done just to be more compatible with the rest of the code -0218 model.comps={'s'}; -0219 model.compNames={'System'}; -0220 model.metComps=ones(numel(model.mets),1); -0221 -0222 %If reactions with undefined stoichiometry are kept, then the -0223 %corresponding metabolites will have ids such as "(n+1) C00001" and -0224 %their names will be empty. These ids are not valid SBML identifiers -0225 %and are therefore replaced with "undefined1, undefined2...". The -0226 %former ids are stored as the new names -0227 I=find(cellfun(@any,strfind(model.mets,'n')) | cellfun(@any,strfind(model.mets,'m'))); -0228 model.metNames(I)=model.mets(I); -0229 repNums=1:numel(I); -0230 repIDs=strcat('undefined_',cellfun(@num2str,num2cell(repNums(:)),'UniformOutput',false)); -0231 model.mets(I)=repIDs; -0232 -0233 %It could also be that the metabolite names are empty for some other -0234 %reason. In that case, use the ID instead -0235 I=cellfun(@isempty,model.metNames); -0236 model.metNames(I)=model.mets(I); -0237 -0238 %Save the model structure -0239 save(modelFile,'model','KOModel','isGeneral','isIncomplete','isUndefinedStoich','isSpontaneous'); -0240 fprintf('COMPLETE\n'); -0241 end -0242 -0243 %Delete reactions which are labeled as "incomplete", "erroneous", -0244 %"unclear", "general reaction" or having undefined stoichiometry (depending -0245 %on settings) -0246 if keepSpontaneous==false -0247 model=removeReactions(model,intersect(isSpontaneous,model.rxns),true,true); -0248 end -0249 if keepUndefinedStoich==false -0250 model=removeReactions(model,intersect(isUndefinedStoich,model.rxns),true,true); -0251 end -0252 if keepIncomplete==false -0253 model=removeReactions(model,intersect(isIncomplete,model.rxns),true,true); -0254 end -0255 if keepGeneral==false -0256 model=removeReactions(model,intersect(isGeneral,model.rxns),true,true); -0257 end -0258 -0259 end -0260 -0261 function output = isNewestFile(ravenPath) -0262 %The ad hoc function, which checks whether keggModel.mat is the more -0263 %recently modified than keggRxns.mat, keggGenes.mat and keggRxns.mat -0264 modelFile=fullfile(ravenPath,'external','kegg','keggModel.mat'); -0265 rxnsFile=fullfile(ravenPath,'external','kegg','keggRxns.mat'); -0266 genesFile=fullfile(ravenPath,'external','kegg','keggGenes.mat'); -0267 metsFile=fullfile(ravenPath,'external','kegg','keggMets.mat'); -0268 if (getFileTime(modelFile)>getFileTime(rxnsFile))&&... -0269 (getFileTime(modelFile)>getFileTime(genesFile))&&... -0270 (getFileTime(modelFile)>getFileTime(metsFile)) -0271 output=1; -0272 else -0273 output=0; -0274 end +0049 else +0050 keggPath=char(keggPath); +0051 end +0052 if nargin<2 +0053 keepSpontaneous=true; +0054 end +0055 if nargin<3 +0056 keepUndefinedStoich=true; +0057 end +0058 if nargin<4 +0059 keepIncomplete=true; +0060 end +0061 if nargin<5 +0062 keepGeneral=false; +0063 end +0064 +0065 ravenPath=findRAVENroot(); +0066 modelFile=fullfile(ravenPath,'external','kegg','keggModel.mat'); +0067 if exist(modelFile, 'file') && isNewestFile(ravenPath) +0068 fprintf(['Importing the global KEGG model from ' strrep(modelFile,'\','/') '... ']); +0069 load(modelFile); +0070 fprintf('COMPLETE\n'); +0071 else +0072 fprintf(['NOTE: The file ' strrep(modelFile,'\','/') ' does not exist or is out-of-date and therefore will be (re)generated\n']); +0073 %First get all reactions +0074 [model,isSpontaneous,isUndefinedStoich,isIncomplete,isGeneral]=getRxnsFromKEGG(keggPath); +0075 +0076 %Get the KO ids that are associated with any of the reactions. They +0077 %will be used later on to create a rxn-gene matrix +0078 KOs=cell(numel(model.rxns)*2,1); +0079 %Make room for two KO ids per reaction +0080 +0081 addToIndex=1; +0082 %Add all KO ids that are used +0083 for i=1:numel(model.rxns) +0084 if isstruct(model.rxnMiriams{i}) +0085 for j=1:numel(model.rxnMiriams{i}.name) +0086 if strcmpi('kegg.orthology',model.rxnMiriams{i}.name{j}) +0087 %Add the KO id +0088 KOs(addToIndex)=model.rxnMiriams{i}.value(j); +0089 addToIndex=addToIndex+1; +0090 end +0091 end +0092 end +0093 end +0094 +0095 KOs=KOs(1:addToIndex-1); +0096 KOs=unique(KOs); +0097 +0098 %Get all genes from any organism in KEGG that is associated with any of +0099 %the KOs +0100 KOModel=getGenesFromKEGG(keggPath,KOs); +0101 +0102 fprintf('Pruning the global KEGG model from the partially annotated, lumped KEGG Orthology entries... ') +0103 model.genes=KOModel.genes; +0104 +0105 %It can be that there are KOs from the reactions that have no database +0106 %entry. These are (as far as I have seen) lumped versions of other KOs +0107 %and should be removed +0108 KOsToRemove=setdiff(KOs, KOModel.rxns); +0109 +0110 %Loop through all reactions and delete the KOs that were not found +0111 for i=1:numel(model.rxns) +0112 if isstruct(model.rxnMiriams{i}) +0113 for j=1:numel(model.rxnMiriams{i}.name) +0114 toDel=[]; +0115 if strcmp(model.rxnMiriams{i}.name{j},'kegg.orthology') +0116 if ismember(model.rxnMiriams{i}.value{j},KOsToRemove) +0117 toDel=[toDel;j]; +0118 end +0119 end +0120 end +0121 %Delete the KOs +0122 if any(toDel) +0123 %If all posts are deleted, then delete the whole structure +0124 if numel(toDel)==j +0125 model.rxnMiriams{i}=[]; +0126 else +0127 model.rxnMiriams{i}.name(toDel)=[]; +0128 model.rxnMiriams{i}.value(toDel)=[]; +0129 end +0130 end +0131 end +0132 end +0133 fprintf('COMPLETE\n'); +0134 +0135 fprintf('Constructing the rxnGeneMat for the global KEGG model... 0%% complete'); +0136 %Create the rxnGeneMat for the reactions. This is simply done by +0137 %merging the gene associations for all the involved KOs +0138 r=zeros(10000000,1); +0139 %Store the positions since it's slow to write to a sparse array in a +0140 %loop +0141 c=zeros(10000000,1); +0142 counter=1; +0143 for i=1:numel(model.rxns) +0144 if isstruct(model.rxnMiriams{i}) +0145 I=strncmp('kegg.orthology',model.rxnMiriams{i}.name,18); +0146 if any(I) +0147 [J, K]=ismember(model.rxnMiriams{i}.value(I),KOModel.rxns); +0148 %Find all gene indexes that correspond to any of these KOs +0149 [~, L]=find(KOModel.rxnGeneMat(K(J),:)); +0150 if any(L) +0151 %Allocate room for more elements if needed +0152 if counter+numel(L)-1>=numel(r) +0153 r=[r;zeros(numel(r),1)]; +0154 c=[c;zeros(numel(c),1)]; +0155 end +0156 r(counter:counter+numel(L)-1)=ones(numel(L),1)*i; +0157 c(counter:counter+numel(L)-1)=L(:); +0158 counter=counter+numel(L); +0159 end +0160 end +0161 end +0162 if rem(i-1,100) == 0 +0163 progress=pad(num2str(floor(i/numel(model.rxns)*100)),3,'left'); +0164 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); +0165 end +0166 end +0167 +0168 model.rxnGeneMat=sparse(r(1:counter-1),c(1:counter-1),ones(counter-1,1)); +0169 if size(model.rxnGeneMat,1)~=numel(model.rxns) || size(model.rxnGeneMat,2)~=numel(KOModel.genes) +0170 model.rxnGeneMat(numel(model.rxns),numel(KOModel.genes))=0; +0171 end +0172 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); +0173 +0174 %Then get all metabolites +0175 metModel=getMetsFromKEGG(keggPath); +0176 +0177 fprintf('Finalizing the global KEGG model... '); +0178 %Add information about all metabolites to the model +0179 [a, b]=ismember(model.mets,metModel.mets); +0180 a=find(a); +0181 b=b(a); +0182 +0183 if ~isfield(model,'metNames') +0184 model.metNames=cell(numel(model.mets),1); +0185 model.metNames(:)={''}; +0186 end +0187 model.metNames(a)=metModel.metNames(b); +0188 +0189 if ~isfield(model,'metFormulas') +0190 model.metFormulas=cell(numel(model.mets),1); +0191 model.metFormulas(:)={''}; +0192 end +0193 model.metFormulas(a)=metModel.metFormulas(b); +0194 +0195 if ~isfield(model,'inchis') +0196 model.inchis=cell(numel(model.mets),1); +0197 model.inchis(:)={''}; +0198 end +0199 model.inchis(a)=metModel.inchis(b); +0200 +0201 if ~isfield(model,'metMiriams') +0202 model.metMiriams=cell(numel(model.mets),1); +0203 end +0204 model.metMiriams(a)=metModel.metMiriams(b); +0205 +0206 %The composition should be loaded from InChIs when available +0207 I=find(~cellfun(@isempty,model.inchis)); +0208 for i=1:numel(I) +0209 S=regexp(model.inchis(I(i)),'/','split'); +0210 S=S{1}; +0211 if numel(S)>=2 +0212 %Don't copy if it doesn't look good +0213 model.metFormulas(I(i))=S(2); +0214 end +0215 end +0216 +0217 %Put all metabolites in one compartment called 's' (for system). This +0218 %is done just to be more compatible with the rest of the code +0219 model.comps={'s'}; +0220 model.compNames={'System'}; +0221 model.metComps=ones(numel(model.mets),1); +0222 +0223 %If reactions with undefined stoichiometry are kept, then the +0224 %corresponding metabolites will have ids such as "(n+1) C00001" and +0225 %their names will be empty. These ids are not valid SBML identifiers +0226 %and are therefore replaced with "undefined1, undefined2...". The +0227 %former ids are stored as the new names +0228 I=find(cellfun(@any,strfind(model.mets,'n')) | cellfun(@any,strfind(model.mets,'m'))); +0229 model.metNames(I)=model.mets(I); +0230 repNums=1:numel(I); +0231 repIDs=strcat('undefined_',cellfun(@num2str,num2cell(repNums(:)),'UniformOutput',false)); +0232 model.mets(I)=repIDs; +0233 +0234 %It could also be that the metabolite names are empty for some other +0235 %reason. In that case, use the ID instead +0236 I=cellfun(@isempty,model.metNames); +0237 model.metNames(I)=model.mets(I); +0238 +0239 %Save the model structure +0240 save(modelFile,'model','KOModel','isGeneral','isIncomplete','isUndefinedStoich','isSpontaneous'); +0241 fprintf('COMPLETE\n'); +0242 end +0243 +0244 %Delete reactions which are labeled as "incomplete", "erroneous", +0245 %"unclear", "general reaction" or having undefined stoichiometry (depending +0246 %on settings) +0247 if keepSpontaneous==false +0248 model=removeReactions(model,intersect(isSpontaneous,model.rxns),true,true); +0249 end +0250 if keepUndefinedStoich==false +0251 model=removeReactions(model,intersect(isUndefinedStoich,model.rxns),true,true); +0252 end +0253 if keepIncomplete==false +0254 model=removeReactions(model,intersect(isIncomplete,model.rxns),true,true); +0255 end +0256 if keepGeneral==false +0257 model=removeReactions(model,intersect(isGeneral,model.rxns),true,true); +0258 end +0259 +0260 end +0261 +0262 function output = isNewestFile(ravenPath) +0263 %The ad hoc function, which checks whether keggModel.mat is the more +0264 %recently modified than keggRxns.mat, keggGenes.mat and keggRxns.mat +0265 modelFile=fullfile(ravenPath,'external','kegg','keggModel.mat'); +0266 rxnsFile=fullfile(ravenPath,'external','kegg','keggRxns.mat'); +0267 genesFile=fullfile(ravenPath,'external','kegg','keggGenes.mat'); +0268 metsFile=fullfile(ravenPath,'external','kegg','keggMets.mat'); +0269 if (getFileTime(modelFile)>getFileTime(rxnsFile))&&... +0270 (getFileTime(modelFile)>getFileTime(genesFile))&&... +0271 (getFileTime(modelFile)>getFileTime(metsFile)) +0272 output=1; +0273 else +0274 output=0; 0275 end -0276 -0277 function modTime = getFileTime(fileName) -0278 %Gets a last modification time for a particular file in datenum format that -0279 %the numbers could be easily compared for different files -0280 listing = dir(fileName); -0281 assert(numel(listing) == 1, 'No such file: %s', fileName); -0282 modTime = listing.datenum; -0283 format long; -0284 end +0276 end +0277 +0278 function modTime = getFileTime(fileName) +0279 %Gets a last modification time for a particular file in datenum format that +0280 %the numbers could be easily compared for different files +0281 listing = dir(fileName); +0282 assert(numel(listing) == 1, 'No such file: %s', fileName); +0283 modTime = listing.datenum; +0284 format long; +0285 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/kegg/getPhylDist.html b/doc/external/kegg/getPhylDist.html index 3fd2bc21..71e5d44f 100644 --- a/doc/external/kegg/getPhylDist.html +++ b/doc/external/kegg/getPhylDist.html @@ -85,120 +85,121 @@

    SOURCE CODE ^if nargin<1 0024 keggPath='RAVEN/external/kegg'; -0025 end -0026 if nargin<2 -0027 onlyInKingdom=false; -0028 end -0029 -0030 %Check if the reactions have been parsed before and saved. If so, load the -0031 %model -0032 [ST, I]=dbstack('-completenames'); -0033 ravenPath=fileparts(fileparts(fileparts(ST(I).file))); -0034 distFile=fullfile(ravenPath,'external','kegg','keggPhylDist.mat'); -0035 if exist(distFile, 'file') -0036 fprintf(['Importing the KEGG phylogenetic distance matrix from ' strrep(distFile,'\','/') '... ']); -0037 load(distFile); -0038 fprintf('COMPLETE\n'); -0039 else -0040 fprintf(['Cannot locate ' strrep(distFile,'\','/') '\n']); -0041 if ~exist(fullfile(keggPath,'taxonomy'),'file') -0042 EM=fprintf(['The file ''taxonomy'' cannot be located at ' strrep(keggPath,'\','/') '/ and should be downloaded from the KEGG FTP.\n']); -0043 dispEM(EM); -0044 else -0045 fprintf(['Generating the KEGG phylogenetic distance matrix from ' fullfile(keggPath,'taxonomy') '... ']); -0046 %Open the file that describes the naming of the species -0047 fid = fopen(fullfile(keggPath,'taxonomy'), 'r'); -0048 -0049 phylDistStruct.ids={}; -0050 -0051 %Keeps the categories for each organism -0052 orgCat={}; -0053 -0054 currentCat={}; -0055 %Keeps track of the current category -0056 -0057 depth=0; -0058 %Keeps track of the current tree depth -0059 -0060 %Loop through the file -0061 orgCounter=0; -0062 while 1 -0063 %Get the next line -0064 tline = fgetl(fid); -0065 -0066 %Abort at end of file -0067 if ~ischar(tline) -0068 break; -0069 end -0070 -0071 if any(tline) -0072 %Check if it's a new category -0073 if tline(1)=='#' -0074 %Find the first space (=depth +1) -0075 sPos=strfind(tline,' ')-1; -0076 %Should always exist -0077 -0078 sPos=sPos(1); -0079 -0080 %If we have stepped back one step in the tree -0081 if sPos<depth -0082 currentCat=currentCat(1:sPos); -0083 end -0084 depth=sPos; -0085 -0086 currentCat{depth}=tline(sPos+2:end); -0087 else -0088 orgCounter=orgCounter+1; -0089 %It is an organism Get the id between first and second -0090 %white space -0091 sPos=find(isstrprop(tline, 'wspace')); -0092 %Should always exist -0093 -0094 phylDistStruct.ids{orgCounter}=tline(sPos(1)+1:sPos(2)-1); -0095 orgCat{orgCounter}=currentCat; -0096 end -0097 end -0098 end -0099 -0100 %Generate a distance matrix (very straight forward here, not neat) -0101 phylDistStruct.distMat=zeros(numel(phylDistStruct.ids)); -0102 for i=1:numel(phylDistStruct.ids) -0103 for j=1:numel(phylDistStruct.ids) -0104 if onlyInKingdom==true -0105 if ~strcmp(orgCat{i}(1),orgCat{j}(1)) -0106 phylDistStruct.distMat(i,j)=Inf; -0107 continue; -0108 end -0109 end -0110 %Calculate the distance between then -0111 dist=numel(orgCat{i})-numel(orgCat{j}); -0112 if dist>0 -0113 aCat=orgCat{i}(1:end-dist); -0114 else -0115 aCat=orgCat{i}; -0116 end -0117 if dist<0 -0118 bCat=orgCat{j}(1:end+dist); -0119 else -0120 bCat=orgCat{j}; -0121 end -0122 -0123 %Loop through the categories and stop when they are the -0124 %same -0125 for k=numel(aCat):-1:1 -0126 if strcmp(aCat{k},bCat{k}) -0127 break; -0128 end -0129 end -0130 phylDistStruct.distMat(i,j)=dist+numel(aCat)-k; -0131 end -0132 end -0133 %Save the structure -0134 save(distFile,'phylDistStruct'); -0135 fprintf('COMPLETE\n'); -0136 end -0137 end -0138 end +0025 else +0026 keggPath=char(keggPath); +0027 end +0028 if nargin<2 +0029 onlyInKingdom=false; +0030 end +0031 +0032 %Check if the reactions have been parsed before and saved. If so, load the +0033 %model +0034 ravenPath=findRAVENroot(); +0035 distFile=fullfile(ravenPath,'external','kegg','keggPhylDist.mat'); +0036 if exist(distFile, 'file') +0037 fprintf(['Importing the KEGG phylogenetic distance matrix from ' strrep(distFile,'\','/') '... ']); +0038 load(distFile); +0039 fprintf('COMPLETE\n'); +0040 else +0041 fprintf(['Cannot locate ' strrep(distFile,'\','/') '\n']); +0042 if ~exist(fullfile(keggPath,'taxonomy'),'file') +0043 EM=fprintf(['The file ''taxonomy'' cannot be located at ' strrep(keggPath,'\','/') '/ and should be downloaded from the KEGG FTP.\n']); +0044 dispEM(EM); +0045 else +0046 fprintf(['Generating the KEGG phylogenetic distance matrix from ' fullfile(keggPath,'taxonomy') '... ']); +0047 %Open the file that describes the naming of the species +0048 fid = fopen(fullfile(keggPath,'taxonomy'), 'r'); +0049 +0050 phylDistStruct.ids={}; +0051 +0052 %Keeps the categories for each organism +0053 orgCat={}; +0054 +0055 currentCat={}; +0056 %Keeps track of the current category +0057 +0058 depth=0; +0059 %Keeps track of the current tree depth +0060 +0061 %Loop through the file +0062 orgCounter=0; +0063 while 1 +0064 %Get the next line +0065 tline = fgetl(fid); +0066 +0067 %Abort at end of file +0068 if ~ischar(tline) +0069 break; +0070 end +0071 +0072 if any(tline) +0073 %Check if it's a new category +0074 if tline(1)=='#' +0075 %Find the first space (=depth +1) +0076 sPos=strfind(tline,' ')-1; +0077 %Should always exist +0078 +0079 sPos=sPos(1); +0080 +0081 %If we have stepped back one step in the tree +0082 if sPos<depth +0083 currentCat=currentCat(1:sPos); +0084 end +0085 depth=sPos; +0086 +0087 currentCat{depth}=tline(sPos+2:end); +0088 else +0089 orgCounter=orgCounter+1; +0090 %It is an organism Get the id between first and second +0091 %white space +0092 sPos=find(isstrprop(tline, 'wspace')); +0093 %Should always exist +0094 +0095 phylDistStruct.ids{orgCounter}=tline(sPos(1)+1:sPos(2)-1); +0096 orgCat{orgCounter}=currentCat; +0097 end +0098 end +0099 end +0100 +0101 %Generate a distance matrix (very straight forward here, not neat) +0102 phylDistStruct.distMat=zeros(numel(phylDistStruct.ids)); +0103 for i=1:numel(phylDistStruct.ids) +0104 for j=1:numel(phylDistStruct.ids) +0105 if onlyInKingdom==true +0106 if ~strcmp(orgCat{i}(1),orgCat{j}(1)) +0107 phylDistStruct.distMat(i,j)=Inf; +0108 continue; +0109 end +0110 end +0111 %Calculate the distance between then +0112 dist=numel(orgCat{i})-numel(orgCat{j}); +0113 if dist>0 +0114 aCat=orgCat{i}(1:end-dist); +0115 else +0116 aCat=orgCat{i}; +0117 end +0118 if dist<0 +0119 bCat=orgCat{j}(1:end+dist); +0120 else +0121 bCat=orgCat{j}; +0122 end +0123 +0124 %Loop through the categories and stop when they are the +0125 %same +0126 for k=numel(aCat):-1:1 +0127 if strcmp(aCat{k},bCat{k}) +0128 break; +0129 end +0130 end +0131 phylDistStruct.distMat(i,j)=dist+numel(aCat)-k; +0132 end +0133 end +0134 %Save the structure +0135 save(distFile,'phylDistStruct'); +0136 fprintf('COMPLETE\n'); +0137 end +0138 end +0139 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/kegg/getRxnsFromKEGG.html b/doc/external/kegg/getRxnsFromKEGG.html index d23de2a4..5b48f54d 100644 --- a/doc/external/kegg/getRxnsFromKEGG.html +++ b/doc/external/kegg/getRxnsFromKEGG.html @@ -179,433 +179,434 @@

    SOURCE CODE ^if nargin<1 0072 keggPath='RAVEN/external/kegg'; -0073 end -0074 -0075 %Check if the reactions have been parsed before and saved. If so, load the -0076 %model -0077 [ST, I]=dbstack('-completenames'); -0078 ravenPath=fileparts(fileparts(fileparts(ST(I).file))); -0079 rxnsFile=fullfile(ravenPath,'external','kegg','keggRxns.mat'); -0080 if exist(rxnsFile, 'file') -0081 fprintf(['Importing KEGG reactions from ' strrep(rxnsFile,'\','/') '... ']); -0082 load(rxnsFile); -0083 else -0084 fprintf(['NOTE: Cannot locate ' strrep(rxnsFile,'\','/') ', it will therefore be generated from the local KEGG database\n']); -0085 if ~exist(fullfile(keggPath,'reaction'),'file') || ~exist(fullfile(keggPath,'reaction.lst'),'file') || ~exist(fullfile(keggPath,'reaction_mapformula.lst'),'file') -0086 EM=fprintf(['The files ''reaction'', ''reaction.lst'' and ''reaction_mapformula.lst'' cannot be located at ' strrep(keggPath,'\','/') '/ and should be downloaded from the KEGG FTP\n']); -0087 dispEM(EM); -0088 else -0089 fprintf('Generating keggRxns.mat file... '); -0090 %Add new functionality in the order specified in models -0091 model.id='KEGG'; -0092 model.name='Automatically generated from KEGG database'; -0093 -0094 %Preallocate memory for 15000 reactions -0095 model.rxns=cell(15000,1); -0096 model.rxnNames=cell(15000,1); -0097 model.eccodes=cell(15000,1); -0098 model.subSystems=cell(15000,1); -0099 model.rxnMiriams=cell(15000,1); -0100 model.rxnNotes=cell(15000,1); -0101 equations=cell(15000,1); -0102 %Temporarily store the equations -0103 -0104 isSpontaneous=false(15000,1); -0105 isIncomplete=false(15000,1); -0106 isGeneral=false(15000,1); -0107 -0108 %First load information on reaction ID, reaction name, KO, pathway, -0109 %and ec-number -0110 fid = fopen(fullfile(keggPath,'reaction'), 'r'); -0111 -0112 %Keep track of how many reactions have been added -0113 rxnCounter=0; -0114 -0115 %Loop through the file -0116 orthology=false; -0117 pathway=false; -0118 module=false; -0119 while 1 -0120 %Get the next line -0121 tline = fgetl(fid); -0122 -0123 %Abort at end of file -0124 if ~ischar(tline) -0125 break; -0126 end -0127 -0128 %Skip '///' -0129 if numel(tline)<12 -0130 continue; -0131 end -0132 -0133 %Check if it's a new reaction -0134 if strcmp(tline(1:12),'ENTRY ') -0135 rxnCounter=rxnCounter+1; -0136 -0137 %Add empty strings where there should be such -0138 model.rxnNames{rxnCounter}=''; -0139 model.eccodes{rxnCounter}=''; -0140 %model.subSystems{rxnCounter}=''; %remain empty cell -0141 model.rxnNotes{rxnCounter}=''; -0142 equations{rxnCounter}=''; -0143 -0144 %Add reaction ID (always 6 characters) -0145 model.rxns{rxnCounter}=tline(13:18); -0146 orthology=false; -0147 pathway=false; -0148 module=false; -0149 -0150 %Add KEGG reaction ID miriam -0151 tempStruct=model.rxnMiriams{rxnCounter}; -0152 tempStruct.name{1,1}='kegg.reaction'; -0153 tempStruct.value{1,1}=tline(13:18); -0154 model.rxnMiriams{rxnCounter}=tempStruct; -0155 end -0156 -0157 %Add name -0158 if strcmp(tline(1:12),'NAME ') -0159 model.rxnNames{rxnCounter}=tline(13:end); -0160 end -0161 -0162 %Add whether the comment includes "incomplete", "erroneous" or -0163 %"unclear" -0164 if strcmp(tline(1:12),'COMMENT ') -0165 %Read all text until '///', 'RPAIR', 'ENZYME', 'PATHWAY' or 'RCLASS' -0166 commentText=tline(13:end); -0167 while 1 -0168 tline = fgetl(fid); -0169 if ~strcmp(tline(1:3),'///') && ~strcmp(tline(1:3),'RPA') && ~strcmp(tline(1:3),'ENZ') && ~strcmp(tline(1:3),'PAT') && ~strcmp(tline(1:3),'RCL') -0170 commentText=[commentText ' ' strtrim(tline)]; -0171 else -0172 break; -0173 end -0174 end -0175 if any(regexpi(commentText,'SPONTANEOUS')) -0176 %It should start this way -0177 isSpontaneous(rxnCounter)=true; -0178 end -0179 if any(regexpi(commentText,'INCOMPLETE')) || any(regexpi(commentText,'ERRONEOUS')) || any(regexpi(commentText,'UNCLEAR')) -0180 isIncomplete(rxnCounter)=true; -0181 end -0182 if any(regexpi(commentText,'GENERAL REACTION')) -0183 %It should start this way -0184 isGeneral(rxnCounter)=true; -0185 end -0186 -0187 %Go to next iteration if it is '///' -0188 if numel(tline)<12 -0189 continue; -0190 end -0191 end -0192 -0193 %Add ec-number -0194 if strcmp(tline(1:12),'ENZYME ') -0195 model.eccodes{rxnCounter}=tline(13:end); -0196 model.eccodes{rxnCounter}=deblank(model.eccodes{rxnCounter}); -0197 model.eccodes{rxnCounter}=strcat('ec-code/',model.eccodes{rxnCounter}); -0198 model.eccodes{rxnCounter}=regexprep(model.eccodes{rxnCounter},'\s+',';ec-code/'); -0199 end -0200 if numel(tline)>8 -0201 if strcmp(tline(1:9),'REFERENCE') -0202 pathway=false; -0203 orthology=false; -0204 end -0205 end -0206 -0207 %Add module ids -0208 if numel(tline)>18 -0209 if strcmp(tline(1:12),'MODULE ') || module==true -0210 pathway=false; -0211 orthology=false; -0212 if isstruct(model.rxnMiriams{rxnCounter}) -0213 addToIndex=numel(model.rxnMiriams{rxnCounter}.name)+1; -0214 else -0215 addToIndex=1; -0216 end -0217 tempStruct=model.rxnMiriams{rxnCounter}; -0218 tempStruct.name{addToIndex,1}='kegg.module'; -0219 tempStruct.value{addToIndex,1}=tline(13:18); -0220 model.rxnMiriams{rxnCounter}=tempStruct; -0221 end -0222 end -0223 -0224 %Add RHEA id -0225 if numel(tline)>18 -0226 if strcmp(tline(1:18),'DBLINKS RHEA: ') -0227 pathway=false; -0228 orthology=false; -0229 module=false; -0230 if isstruct(model.rxnMiriams{rxnCounter}) -0231 addToIndex=numel(model.rxnMiriams{rxnCounter}.name)+1; -0232 else -0233 addToIndex=1; -0234 end -0235 tempStruct=model.rxnMiriams{rxnCounter}; -0236 tempStruct.name{addToIndex,1}='rhea'; -0237 tempStruct.value{addToIndex,1}=tline(19:end); -0238 model.rxnMiriams{rxnCounter}=tempStruct; -0239 end -0240 end -0241 -0242 %Add KO-ids -0243 if numel(tline)>16 -0244 if strcmp(tline(1:16),'ORTHOLOGY KO: ') || strcmp(tline(1:16),' KO: ') || strcmp(tline(1:12),'ORTHOLOGY ') || orthology==true -0245 pathway=false; -0246 module=false; -0247 %Check if KO has been added already (each reaction may -0248 %belong to several) -0249 if isstruct(model.rxnMiriams{rxnCounter}) -0250 addToIndex=numel(model.rxnMiriams{rxnCounter}.name)+1; -0251 else -0252 addToIndex=1; -0253 end -0254 -0255 tempStruct=model.rxnMiriams{rxnCounter}; -0256 tempStruct.name{addToIndex,1}='kegg.orthology'; -0257 if strcmp(tline(13:16),'KO:') -0258 %This is in the old version -0259 tempStruct.value{addToIndex,1}=tline(17:22); -0260 else -0261 %This means that it found one KO in the new format -0262 %and that subsequent lines might be other KOs -0263 orthology=true; -0264 tempStruct.value{addToIndex,1}=tline(13:18); -0265 end -0266 model.rxnMiriams{rxnCounter}=tempStruct; -0267 end -0268 end -0269 -0270 %Add pathways -0271 if numel(tline)>18 -0272 if strcmp(tline(1:18),'PATHWAY PATH: ') || strcmp(tline(1:18),' PATH: ') || strcmp(tline(1:12),'PATHWAY ') || pathway==true -0273 orthology=false; -0274 module=false; -0275 %Check if annotation has been added already -0276 if isstruct(model.rxnMiriams{rxnCounter}) -0277 addToIndex=numel(model.rxnMiriams{rxnCounter}.name)+1; -0278 else -0279 addToIndex=1; -0280 end -0281 -0282 tempStruct=model.rxnMiriams{rxnCounter}; -0283 tempStruct.name{addToIndex,1}='kegg.pathway'; -0284 %If it is the old version -0285 if strcmp(tline(14:17),'PATH:') -0286 tempStruct.value{addToIndex,1}=tline(19:25); -0287 else -0288 %If it is the new version -0289 tempStruct.value{addToIndex,1}=tline(13:19); -0290 pathway=true; -0291 end -0292 -0293 %Do not save global or overview pathways. The ids for -0294 %such pathways begin with rn011 or rn012 -0295 if ~strcmp('rn011',tempStruct.value{addToIndex,1}(1:5)) && ~strcmp('rn012',tempStruct.value{addToIndex,1}(1:5)) -0296 model.rxnMiriams{rxnCounter}=tempStruct; -0297 -0298 %Also save the subSystems names. For the old KEGG -0299 %format, only the first mentioned subsystem is -0300 %picked. Use the newer KEGG format to fetch all the -0301 %subsystems -0302 if strcmp(tline(14:17),'PATH:') -0303 %The old format -0304 model.subSystems{rxnCounter}=tline(28:end); -0305 else -0306 %The new format -0307 model.subSystems{rxnCounter,1}{1,numel(model.subSystems{rxnCounter,1})+1}=tline(22:end); -0308 end -0309 end -0310 end -0311 end -0312 end -0313 -0314 %Close the file -0315 fclose(fid); -0316 -0317 %This is done here since the the indexes won't match since some -0318 %reactions are removed along the way -0319 isIncomplete=model.rxns(isIncomplete); -0320 isGeneral=model.rxns(isGeneral); -0321 isSpontaneous=model.rxns(isSpontaneous); -0322 -0323 %If too much space was allocated, shrink the model -0324 model.rxns=model.rxns(1:rxnCounter); -0325 model.rxnNames=model.rxnNames(1:rxnCounter); -0326 model.eccodes=model.eccodes(1:rxnCounter); -0327 equations=equations(1:rxnCounter); -0328 model.rxnMiriams=model.rxnMiriams(1:rxnCounter); -0329 model.rxnNotes=model.rxnNotes(1:rxnCounter); -0330 model.subSystems=model.subSystems(1:rxnCounter); -0331 -0332 %Then load the equations from another file. This is because the -0333 %equations are easier to retrieve from there -0334 -0335 %The format is rxnID: equation The reactions should have been -0336 %loaded in the exact same order -0337 fid = fopen(fullfile(keggPath,'reaction.lst'), 'r'); -0338 -0339 %Loop through the file -0340 for i=1:rxnCounter -0341 %Get the next line -0342 tline = fgetl(fid); -0343 -0344 equations{i}=tline(9:end); -0345 end -0346 -0347 %Close the file -0348 fclose(fid); -0349 -0350 %Several equations may have two whitespaces between the last -0351 %reactant and the reversible arrow sign. The number of whitespaces -0352 %is thus reduced to one -0353 equations = regexprep(equations,' <=>', ' <=>'); -0354 -0355 %Construct the S matrix and list of metabolites -0356 [S, mets, badRxns]=constructS(equations); -0357 model.S=S; -0358 model.mets=mets; -0359 -0360 %There is some limited evidence for directionality in -0361 %reaction_mapformula.lst. The information there concerns how the -0362 %reactions are drawn in the KEGG maps. If a reaction is -0363 %irreversible in the same direction for all maps, then I consider -0364 %is irreversible, otherwise reversible. Also, not all reactions are -0365 %present in the maps, so not all will have directionality. They -0366 %will be considered to be reversible -0367 -0368 %The format is R00005: 00330: C01010 => C00011 Generate a -0369 %reversibility structure with the fields: *rxns: reaction ids -0370 %*product: one met id that is a product. This is because the -0371 %*reactions might be written in another direction compared to in -0372 % the reactions.lst file -0373 %*rev: 1 if reversible, otherwise 0 -0374 reversibility.rxns={}; -0375 reversibility.product={}; -0376 reversibility.rev=[]; -0377 -0378 fid = fopen(fullfile(keggPath,'reaction_mapformula.lst'), 'r'); -0379 while 1 -0380 %Get the next line -0381 tline = fgetl(fid); -0382 -0383 %Abort at end of file -0384 if ~ischar(tline) -0385 break; -0386 end -0387 -0388 rxn=tline(1:6); -0389 prod=tline(end-5:end); -0390 rev=any(strfind(tline,'<=>')); -0391 if isempty(reversibility.rxns) -0392 reversibility.rxns{1}=rxn; -0393 reversibility.product{1}=prod; -0394 reversibility.rev(1)=rev; -0395 elseif strcmp(reversibility.rxns(end),rxn) -0396 %Check if the reaction was added before. It's an ordered -0397 %list, so only check the last element If it's reversible in -0398 %the new reaction or reversible in the old reaction then -0399 %set (keep) to be reversible -0400 if rev==1 || reversibility.rev(end)==1 -0401 reversibility.rev(end)=1; -0402 else -0403 %This means that the reaction was already loaded, that -0404 %it was irreversible before and irreversible in the new -0405 %reaction. However, it could be that they are written -0406 %in diferent directions. If the product differ, then -0407 %set to be reversible. This assumes that the reactions -0408 %are written with the same metabolite as the last one -0409 %if they are in the same direction -0410 if ~strcmp(prod,reversibility.product(end)) -0411 reversibility.rev(end)=1; -0412 end -0413 end -0414 else -0415 reversibility.rxns=[reversibility.rxns;rxn]; -0416 reversibility.product=[reversibility.product;prod]; -0417 reversibility.rev=[reversibility.rev;rev]; -0418 end -0419 end -0420 fclose(fid); -0421 -0422 %Update the reversibility -0423 model.rev=ones(rxnCounter,1); -0424 %Match the reaction ids -0425 irrevIDs=find(reversibility.rev==0); -0426 [~, I]=ismember(reversibility.rxns(irrevIDs),model.rxns); -0427 [~, prodMetIDs]=ismember(reversibility.product(irrevIDs),model.mets); -0428 model.rev(I)=0; -0429 -0430 %See if the reactions are written in the same order in model.S -0431 linearInd=sub2ind(size(model.S), prodMetIDs, I); -0432 changeOrder=I(model.S(linearInd)<0); -0433 %Change the order of these reactions -0434 model.S(:,changeOrder)=model.S(:,changeOrder).*-1; -0435 -0436 %Add some stuff to get a correct model structure -0437 model.ub=ones(rxnCounter,1)*1000; -0438 model.lb=model.rev*-1000; -0439 model.c=zeros(rxnCounter,1); -0440 model.b=zeros(numel(model.mets),1); -0441 model=removeReactions(model,badRxns,true,true); -0442 -0443 %Identify reactions with undefined stoichiometry. Such -0444 %reactions involve metabolites with an ID containing the letter "n" -0445 %or "m" -0446 I=cellfun(@any,strfind(model.mets,'n')) | cellfun(@any,strfind(model.mets,'m')); -0447 [~, J]=find(model.S(I,:)); -0448 isUndefinedStoich=model.rxns(unique(J)); -0449 %Sort model that metabolites with undefined stoichiometry would -0450 %appear in the end of metabolites list -0451 metList=[model.mets(~I);model.mets(I)]; -0452 [~,metIndexes]=ismember(metList,model.mets); -0453 model=permuteModel(model,metIndexes,'mets'); -0454 -0455 %Sort model that i) spontaneous, ii) with undefined -0456 %stoichiometry, iii) incomplete and iv) general reactions would bve -0457 %ranked in the end of the model -0458 endRxnList=unique([model.rxns(ismember(model.rxns,isSpontaneous));model.rxns(ismember(model.rxns,isUndefinedStoich));model.rxns(ismember(model.rxns,isIncomplete));model.rxns(ismember(model.rxns,isGeneral))],'stable'); -0459 rxnList=[model.rxns(~ismember(model.rxns,endRxnList));endRxnList]; -0460 [~,rxnIndexes]=ismember(rxnList,model.rxns); -0461 model=permuteModel(model,rxnIndexes,'rxns'); -0462 -0463 %Add information in rxnNotes, whether reaction belongs to any of -0464 %type i-iv mentioned a few lines above -0465 for i=(numel(rxnList)-numel(endRxnList)+1):numel(model.rxns) -0466 if ismember(model.rxns(i),isSpontaneous) -0467 model.rxnNotes(i)=strcat(model.rxnNotes(i),'Spontaneous'); -0468 end -0469 if ismember(model.rxns(i),isUndefinedStoich) -0470 if isempty(model.rxnNotes{i}) -0471 model.rxnNotes(i)=strcat(model.rxnNotes(i),'With undefined stoichiometry'); -0472 else -0473 model.rxnNotes(i)=strcat(model.rxnNotes(i),', with undefined stoichiometry'); -0474 end -0475 end -0476 if ismember(model.rxns(i),isIncomplete) -0477 if isempty(model.rxnNotes{i}) -0478 model.rxnNotes(i)=strcat(model.rxnNotes(i),'Incomplete'); -0479 else -0480 model.rxnNotes(i)=strcat(model.rxnNotes(i),', incomplete'); -0481 end -0482 end -0483 if ismember(model.rxns(i),isGeneral) -0484 if isempty(model.rxnNotes{i}) -0485 model.rxnNotes(i)=strcat(model.rxnNotes(i),'General'); -0486 else -0487 model.rxnNotes(i)=strcat(model.rxnNotes(i),', general'); -0488 end -0489 end -0490 model.rxnNotes(i)=strcat(model.rxnNotes(i),' reaction'); -0491 end -0492 -0493 %Save the model structure -0494 save(rxnsFile,'model','isGeneral','isIncomplete','isUndefinedStoich','isSpontaneous'); -0495 end -0496 end -0497 fprintf('COMPLETE\n'); -0498 -0499 end +0073 else +0074 keggPath=char(keggPath); +0075 end +0076 +0077 %Check if the reactions have been parsed before and saved. If so, load the +0078 %model +0079 ravenPath=findRAVENroot(); +0080 rxnsFile=fullfile(ravenPath,'external','kegg','keggRxns.mat'); +0081 if exist(rxnsFile, 'file') +0082 fprintf(['Importing KEGG reactions from ' strrep(rxnsFile,'\','/') '... ']); +0083 load(rxnsFile); +0084 else +0085 fprintf(['NOTE: Cannot locate ' strrep(rxnsFile,'\','/') ', it will therefore be generated from the local KEGG database\n']); +0086 if ~exist(fullfile(keggPath,'reaction'),'file') || ~exist(fullfile(keggPath,'reaction.lst'),'file') || ~exist(fullfile(keggPath,'reaction_mapformula.lst'),'file') +0087 EM=fprintf(['The files ''reaction'', ''reaction.lst'' and ''reaction_mapformula.lst'' cannot be located at ' strrep(keggPath,'\','/') '/ and should be downloaded from the KEGG FTP\n']); +0088 dispEM(EM); +0089 else +0090 fprintf('Generating keggRxns.mat file... '); +0091 %Add new functionality in the order specified in models +0092 model.id='KEGG'; +0093 model.name='Automatically generated from KEGG database'; +0094 +0095 %Preallocate memory for 15000 reactions +0096 model.rxns=cell(15000,1); +0097 model.rxnNames=cell(15000,1); +0098 model.eccodes=cell(15000,1); +0099 model.subSystems=cell(15000,1); +0100 model.rxnMiriams=cell(15000,1); +0101 model.rxnNotes=cell(15000,1); +0102 equations=cell(15000,1); +0103 %Temporarily store the equations +0104 +0105 isSpontaneous=false(15000,1); +0106 isIncomplete=false(15000,1); +0107 isGeneral=false(15000,1); +0108 +0109 %First load information on reaction ID, reaction name, KO, pathway, +0110 %and ec-number +0111 fid = fopen(fullfile(keggPath,'reaction'), 'r'); +0112 +0113 %Keep track of how many reactions have been added +0114 rxnCounter=0; +0115 +0116 %Loop through the file +0117 orthology=false; +0118 pathway=false; +0119 module=false; +0120 while 1 +0121 %Get the next line +0122 tline = fgetl(fid); +0123 +0124 %Abort at end of file +0125 if ~ischar(tline) +0126 break; +0127 end +0128 +0129 %Skip '///' +0130 if numel(tline)<12 +0131 continue; +0132 end +0133 +0134 %Check if it's a new reaction +0135 if strcmp(tline(1:12),'ENTRY ') +0136 rxnCounter=rxnCounter+1; +0137 +0138 %Add empty strings where there should be such +0139 model.rxnNames{rxnCounter}=''; +0140 model.eccodes{rxnCounter}=''; +0141 %model.subSystems{rxnCounter}=''; %remain empty cell +0142 model.rxnNotes{rxnCounter}=''; +0143 equations{rxnCounter}=''; +0144 +0145 %Add reaction ID (always 6 characters) +0146 model.rxns{rxnCounter}=tline(13:18); +0147 orthology=false; +0148 pathway=false; +0149 module=false; +0150 +0151 %Add KEGG reaction ID miriam +0152 tempStruct=model.rxnMiriams{rxnCounter}; +0153 tempStruct.name{1,1}='kegg.reaction'; +0154 tempStruct.value{1,1}=tline(13:18); +0155 model.rxnMiriams{rxnCounter}=tempStruct; +0156 end +0157 +0158 %Add name +0159 if strcmp(tline(1:12),'NAME ') +0160 model.rxnNames{rxnCounter}=tline(13:end); +0161 end +0162 +0163 %Add whether the comment includes "incomplete", "erroneous" or +0164 %"unclear" +0165 if strcmp(tline(1:12),'COMMENT ') +0166 %Read all text until '///', 'RPAIR', 'ENZYME', 'PATHWAY' or 'RCLASS' +0167 commentText=tline(13:end); +0168 while 1 +0169 tline = fgetl(fid); +0170 if ~strcmp(tline(1:3),'///') && ~strcmp(tline(1:3),'RPA') && ~strcmp(tline(1:3),'ENZ') && ~strcmp(tline(1:3),'PAT') && ~strcmp(tline(1:3),'RCL') +0171 commentText=[commentText ' ' strtrim(tline)]; +0172 else +0173 break; +0174 end +0175 end +0176 if any(regexpi(commentText,'SPONTANEOUS')) +0177 %It should start this way +0178 isSpontaneous(rxnCounter)=true; +0179 end +0180 if any(regexpi(commentText,'INCOMPLETE')) || any(regexpi(commentText,'ERRONEOUS')) || any(regexpi(commentText,'UNCLEAR')) +0181 isIncomplete(rxnCounter)=true; +0182 end +0183 if any(regexpi(commentText,'GENERAL REACTION')) +0184 %It should start this way +0185 isGeneral(rxnCounter)=true; +0186 end +0187 +0188 %Go to next iteration if it is '///' +0189 if numel(tline)<12 +0190 continue; +0191 end +0192 end +0193 +0194 %Add ec-number +0195 if strcmp(tline(1:12),'ENZYME ') +0196 model.eccodes{rxnCounter}=tline(13:end); +0197 model.eccodes{rxnCounter}=deblank(model.eccodes{rxnCounter}); +0198 model.eccodes{rxnCounter}=strcat('ec-code/',model.eccodes{rxnCounter}); +0199 model.eccodes{rxnCounter}=regexprep(model.eccodes{rxnCounter},'\s+',';ec-code/'); +0200 end +0201 if numel(tline)>8 +0202 if strcmp(tline(1:9),'REFERENCE') +0203 pathway=false; +0204 orthology=false; +0205 end +0206 end +0207 +0208 %Add module ids +0209 if numel(tline)>18 +0210 if strcmp(tline(1:12),'MODULE ') || module==true +0211 pathway=false; +0212 orthology=false; +0213 if isstruct(model.rxnMiriams{rxnCounter}) +0214 addToIndex=numel(model.rxnMiriams{rxnCounter}.name)+1; +0215 else +0216 addToIndex=1; +0217 end +0218 tempStruct=model.rxnMiriams{rxnCounter}; +0219 tempStruct.name{addToIndex,1}='kegg.module'; +0220 tempStruct.value{addToIndex,1}=tline(13:18); +0221 model.rxnMiriams{rxnCounter}=tempStruct; +0222 end +0223 end +0224 +0225 %Add RHEA id +0226 if numel(tline)>18 +0227 if strcmp(tline(1:18),'DBLINKS RHEA: ') +0228 pathway=false; +0229 orthology=false; +0230 module=false; +0231 if isstruct(model.rxnMiriams{rxnCounter}) +0232 addToIndex=numel(model.rxnMiriams{rxnCounter}.name)+1; +0233 else +0234 addToIndex=1; +0235 end +0236 tempStruct=model.rxnMiriams{rxnCounter}; +0237 tempStruct.name{addToIndex,1}='rhea'; +0238 tempStruct.value{addToIndex,1}=tline(19:end); +0239 model.rxnMiriams{rxnCounter}=tempStruct; +0240 end +0241 end +0242 +0243 %Add KO-ids +0244 if numel(tline)>16 +0245 if strcmp(tline(1:16),'ORTHOLOGY KO: ') || strcmp(tline(1:16),' KO: ') || strcmp(tline(1:12),'ORTHOLOGY ') || orthology==true +0246 pathway=false; +0247 module=false; +0248 %Check if KO has been added already (each reaction may +0249 %belong to several) +0250 if isstruct(model.rxnMiriams{rxnCounter}) +0251 addToIndex=numel(model.rxnMiriams{rxnCounter}.name)+1; +0252 else +0253 addToIndex=1; +0254 end +0255 +0256 tempStruct=model.rxnMiriams{rxnCounter}; +0257 tempStruct.name{addToIndex,1}='kegg.orthology'; +0258 if strcmp(tline(13:16),'KO:') +0259 %This is in the old version +0260 tempStruct.value{addToIndex,1}=tline(17:22); +0261 else +0262 %This means that it found one KO in the new format +0263 %and that subsequent lines might be other KOs +0264 orthology=true; +0265 tempStruct.value{addToIndex,1}=tline(13:18); +0266 end +0267 model.rxnMiriams{rxnCounter}=tempStruct; +0268 end +0269 end +0270 +0271 %Add pathways +0272 if numel(tline)>18 +0273 if strcmp(tline(1:18),'PATHWAY PATH: ') || strcmp(tline(1:18),' PATH: ') || strcmp(tline(1:12),'PATHWAY ') || pathway==true +0274 orthology=false; +0275 module=false; +0276 %Check if annotation has been added already +0277 if isstruct(model.rxnMiriams{rxnCounter}) +0278 addToIndex=numel(model.rxnMiriams{rxnCounter}.name)+1; +0279 else +0280 addToIndex=1; +0281 end +0282 +0283 tempStruct=model.rxnMiriams{rxnCounter}; +0284 tempStruct.name{addToIndex,1}='kegg.pathway'; +0285 %If it is the old version +0286 if strcmp(tline(14:17),'PATH:') +0287 tempStruct.value{addToIndex,1}=tline(19:25); +0288 else +0289 %If it is the new version +0290 tempStruct.value{addToIndex,1}=tline(13:19); +0291 pathway=true; +0292 end +0293 +0294 %Do not save global or overview pathways. The ids for +0295 %such pathways begin with rn011 or rn012 +0296 if ~strcmp('rn011',tempStruct.value{addToIndex,1}(1:5)) && ~strcmp('rn012',tempStruct.value{addToIndex,1}(1:5)) +0297 model.rxnMiriams{rxnCounter}=tempStruct; +0298 +0299 %Also save the subSystems names. For the old KEGG +0300 %format, only the first mentioned subsystem is +0301 %picked. Use the newer KEGG format to fetch all the +0302 %subsystems +0303 if strcmp(tline(14:17),'PATH:') +0304 %The old format +0305 model.subSystems{rxnCounter}=tline(28:end); +0306 else +0307 %The new format +0308 model.subSystems{rxnCounter,1}{1,numel(model.subSystems{rxnCounter,1})+1}=tline(22:end); +0309 end +0310 end +0311 end +0312 end +0313 end +0314 +0315 %Close the file +0316 fclose(fid); +0317 +0318 %This is done here since the the indexes won't match since some +0319 %reactions are removed along the way +0320 isIncomplete=model.rxns(isIncomplete); +0321 isGeneral=model.rxns(isGeneral); +0322 isSpontaneous=model.rxns(isSpontaneous); +0323 +0324 %If too much space was allocated, shrink the model +0325 model.rxns=model.rxns(1:rxnCounter); +0326 model.rxnNames=model.rxnNames(1:rxnCounter); +0327 model.eccodes=model.eccodes(1:rxnCounter); +0328 equations=equations(1:rxnCounter); +0329 model.rxnMiriams=model.rxnMiriams(1:rxnCounter); +0330 model.rxnNotes=model.rxnNotes(1:rxnCounter); +0331 model.subSystems=model.subSystems(1:rxnCounter); +0332 +0333 %Then load the equations from another file. This is because the +0334 %equations are easier to retrieve from there +0335 +0336 %The format is rxnID: equation The reactions should have been +0337 %loaded in the exact same order +0338 fid = fopen(fullfile(keggPath,'reaction.lst'), 'r'); +0339 +0340 %Loop through the file +0341 for i=1:rxnCounter +0342 %Get the next line +0343 tline = fgetl(fid); +0344 +0345 equations{i}=tline(9:end); +0346 end +0347 +0348 %Close the file +0349 fclose(fid); +0350 +0351 %Several equations may have two whitespaces between the last +0352 %reactant and the reversible arrow sign. The number of whitespaces +0353 %is thus reduced to one +0354 equations = regexprep(equations,' <=>', ' <=>'); +0355 +0356 %Construct the S matrix and list of metabolites +0357 [S, mets, badRxns]=constructS(equations); +0358 model.S=S; +0359 model.mets=mets; +0360 +0361 %There is some limited evidence for directionality in +0362 %reaction_mapformula.lst. The information there concerns how the +0363 %reactions are drawn in the KEGG maps. If a reaction is +0364 %irreversible in the same direction for all maps, then I consider +0365 %is irreversible, otherwise reversible. Also, not all reactions are +0366 %present in the maps, so not all will have directionality. They +0367 %will be considered to be reversible +0368 +0369 %The format is R00005: 00330: C01010 => C00011 Generate a +0370 %reversibility structure with the fields: *rxns: reaction ids +0371 %*product: one met id that is a product. This is because the +0372 %*reactions might be written in another direction compared to in +0373 % the reactions.lst file +0374 %*rev: 1 if reversible, otherwise 0 +0375 reversibility.rxns={}; +0376 reversibility.product={}; +0377 reversibility.rev=[]; +0378 +0379 fid = fopen(fullfile(keggPath,'reaction_mapformula.lst'), 'r'); +0380 while 1 +0381 %Get the next line +0382 tline = fgetl(fid); +0383 +0384 %Abort at end of file +0385 if ~ischar(tline) +0386 break; +0387 end +0388 +0389 rxn=tline(1:6); +0390 prod=tline(end-5:end); +0391 rev=any(strfind(tline,'<=>')); +0392 if isempty(reversibility.rxns) +0393 reversibility.rxns{1}=rxn; +0394 reversibility.product{1}=prod; +0395 reversibility.rev(1)=rev; +0396 elseif strcmp(reversibility.rxns(end),rxn) +0397 %Check if the reaction was added before. It's an ordered +0398 %list, so only check the last element If it's reversible in +0399 %the new reaction or reversible in the old reaction then +0400 %set (keep) to be reversible +0401 if rev==1 || reversibility.rev(end)==1 +0402 reversibility.rev(end)=1; +0403 else +0404 %This means that the reaction was already loaded, that +0405 %it was irreversible before and irreversible in the new +0406 %reaction. However, it could be that they are written +0407 %in diferent directions. If the product differ, then +0408 %set to be reversible. This assumes that the reactions +0409 %are written with the same metabolite as the last one +0410 %if they are in the same direction +0411 if ~strcmp(prod,reversibility.product(end)) +0412 reversibility.rev(end)=1; +0413 end +0414 end +0415 else +0416 reversibility.rxns=[reversibility.rxns;rxn]; +0417 reversibility.product=[reversibility.product;prod]; +0418 reversibility.rev=[reversibility.rev;rev]; +0419 end +0420 end +0421 fclose(fid); +0422 +0423 %Update the reversibility +0424 model.rev=ones(rxnCounter,1); +0425 %Match the reaction ids +0426 irrevIDs=find(reversibility.rev==0); +0427 [~, I]=ismember(reversibility.rxns(irrevIDs),model.rxns); +0428 [~, prodMetIDs]=ismember(reversibility.product(irrevIDs),model.mets); +0429 model.rev(I)=0; +0430 +0431 %See if the reactions are written in the same order in model.S +0432 linearInd=sub2ind(size(model.S), prodMetIDs, I); +0433 changeOrder=I(model.S(linearInd)<0); +0434 %Change the order of these reactions +0435 model.S(:,changeOrder)=model.S(:,changeOrder).*-1; +0436 +0437 %Add some stuff to get a correct model structure +0438 model.ub=ones(rxnCounter,1)*1000; +0439 model.lb=model.rev*-1000; +0440 model.c=zeros(rxnCounter,1); +0441 model.b=zeros(numel(model.mets),1); +0442 model=removeReactions(model,badRxns,true,true); +0443 +0444 %Identify reactions with undefined stoichiometry. Such +0445 %reactions involve metabolites with an ID containing the letter "n" +0446 %or "m" +0447 I=cellfun(@any,strfind(model.mets,'n')) | cellfun(@any,strfind(model.mets,'m')); +0448 [~, J]=find(model.S(I,:)); +0449 isUndefinedStoich=model.rxns(unique(J)); +0450 %Sort model that metabolites with undefined stoichiometry would +0451 %appear in the end of metabolites list +0452 metList=[model.mets(~I);model.mets(I)]; +0453 [~,metIndexes]=ismember(metList,model.mets); +0454 model=permuteModel(model,metIndexes,'mets'); +0455 +0456 %Sort model that i) spontaneous, ii) with undefined +0457 %stoichiometry, iii) incomplete and iv) general reactions would bve +0458 %ranked in the end of the model +0459 endRxnList=unique([model.rxns(ismember(model.rxns,isSpontaneous));model.rxns(ismember(model.rxns,isUndefinedStoich));model.rxns(ismember(model.rxns,isIncomplete));model.rxns(ismember(model.rxns,isGeneral))],'stable'); +0460 rxnList=[model.rxns(~ismember(model.rxns,endRxnList));endRxnList]; +0461 [~,rxnIndexes]=ismember(rxnList,model.rxns); +0462 model=permuteModel(model,rxnIndexes,'rxns'); +0463 +0464 %Add information in rxnNotes, whether reaction belongs to any of +0465 %type i-iv mentioned a few lines above +0466 for i=(numel(rxnList)-numel(endRxnList)+1):numel(model.rxns) +0467 if ismember(model.rxns(i),isSpontaneous) +0468 model.rxnNotes(i)=strcat(model.rxnNotes(i),'Spontaneous'); +0469 end +0470 if ismember(model.rxns(i),isUndefinedStoich) +0471 if isempty(model.rxnNotes{i}) +0472 model.rxnNotes(i)=strcat(model.rxnNotes(i),'With undefined stoichiometry'); +0473 else +0474 model.rxnNotes(i)=strcat(model.rxnNotes(i),', with undefined stoichiometry'); +0475 end +0476 end +0477 if ismember(model.rxns(i),isIncomplete) +0478 if isempty(model.rxnNotes{i}) +0479 model.rxnNotes(i)=strcat(model.rxnNotes(i),'Incomplete'); +0480 else +0481 model.rxnNotes(i)=strcat(model.rxnNotes(i),', incomplete'); +0482 end +0483 end +0484 if ismember(model.rxns(i),isGeneral) +0485 if isempty(model.rxnNotes{i}) +0486 model.rxnNotes(i)=strcat(model.rxnNotes(i),'General'); +0487 else +0488 model.rxnNotes(i)=strcat(model.rxnNotes(i),', general'); +0489 end +0490 end +0491 model.rxnNotes(i)=strcat(model.rxnNotes(i),' reaction'); +0492 end +0493 +0494 %Save the model structure +0495 save(rxnsFile,'model','isGeneral','isIncomplete','isUndefinedStoich','isSpontaneous'); +0496 end +0497 end +0498 fprintf('COMPLETE\n'); +0499 +0500 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/kegg/getWSLpath.html b/doc/external/kegg/getWSLpath.html index b5f665d1..51dda9d2 100644 --- a/doc/external/kegg/getWSLpath.html +++ b/doc/external/kegg/getWSLpath.html @@ -72,9 +72,12 @@

    SOURCE CODE ^% Uses the WSL function 'wslpath' to translate the path. 0015 % 0016 % Usage: path=getWSLpath(path) -0017 [~,path]=system(['wsl wslpath ''' path '''']); -0018 path=path(1:end-1);% Remove final character (line-break) -0019 end +0017 [status,path]=system(['wsl wslpath ''' path '''']); +0018 if status==-1 +0019 error('Cannot get access to Windows Subsystem for Linux, check your WSL installation') +0020 end +0021 path=path(1:end-1);% Remove final character (line-break) +0022 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/makeFakeBlastStructure.html b/doc/external/makeFakeBlastStructure.html index 4ff0d0b5..4dde45fa 100644 --- a/doc/external/makeFakeBlastStructure.html +++ b/doc/external/makeFakeBlastStructure.html @@ -92,36 +92,38 @@

    SOURCE CODE ^% running getModelFromHomology 0026 0027 if nargin<3 -0028 throw(MException('','All three parameters should be set')); +0028 error('All three parameters should be set'); 0029 end -0030 -0031 % Check whether orthologList is a cell array, with two columns, and more -0032 % than 10 rows -0033 if (~iscell(orthologList) || ~(size(orthologList,2)==2) || ~(size(orthologList,1)>=10)) -0034 throw(MException('','orthologList should be a cell array with two columns')); -0035 end -0036 -0037 blastStructure(1).fromId=sourceModelID; -0038 blastStructure(1).toId=getModelFor; -0039 blastStructure(1).fromGenes=orthologList(:,1); -0040 blastStructure(1).toGenes=orthologList(:,2); -0041 -0042 blastStructure(2).fromId=getModelFor; -0043 blastStructure(2).toId=sourceModelID; -0044 blastStructure(2).fromGenes=orthologList(:,2); -0045 blastStructure(2).toGenes=orthologList(:,1); -0046 -0047 blastStructure(1).evalue=zeros(size(orthologList,1),1); -0048 blastStructure(2).evalue=zeros(size(orthologList,1),1); -0049 blastStructure(1).identity(1:size(orthologList,1),1)=100; -0050 blastStructure(2).identity(1:size(orthologList,1),1)=100; -0051 blastStructure(1).aligLen(1:size(orthologList,1),1)=1000; -0052 blastStructure(2).aligLen(1:size(orthologList,1),1)=1000; -0053 blastStructure(1).bitscore(1:size(orthologList,1),1)=100; -0054 blastStructure(2).bitscore(1:size(orthologList,1),1)=100; -0055 blastStructure(1).ppos(1:size(orthologList,1),1)=100; -0056 blastStructure(2).ppos(1:size(orthologList,1),1)=100; -0057 end +0030 sourceModelID=char(sourceModelID); +0031 getModelFor=char(getModelFor); +0032 +0033 % Check whether orthologList is a cell array, with two columns, and more +0034 % than 10 rows +0035 if (~iscell(orthologList) || ~(size(orthologList,2)==2) || ~(size(orthologList,1)>=10)) +0036 error('orthologList should be a cell array with two columns'); +0037 end +0038 +0039 blastStructure(1).fromId=sourceModelID; +0040 blastStructure(1).toId=getModelFor; +0041 blastStructure(1).fromGenes=orthologList(:,1); +0042 blastStructure(1).toGenes=orthologList(:,2); +0043 +0044 blastStructure(2).fromId=getModelFor; +0045 blastStructure(2).toId=sourceModelID; +0046 blastStructure(2).fromGenes=orthologList(:,2); +0047 blastStructure(2).toGenes=orthologList(:,1); +0048 +0049 blastStructure(1).evalue=zeros(size(orthologList,1),1); +0050 blastStructure(2).evalue=zeros(size(orthologList,1),1); +0051 blastStructure(1).identity(1:size(orthologList,1),1)=100; +0052 blastStructure(2).identity(1:size(orthologList,1),1)=100; +0053 blastStructure(1).aligLen(1:size(orthologList,1),1)=1000; +0054 blastStructure(2).aligLen(1:size(orthologList,1),1)=1000; +0055 blastStructure(1).bitscore(1:size(orthologList,1),1)=100; +0056 blastStructure(2).bitscore(1:size(orthologList,1),1)=100; +0057 blastStructure(1).ppos(1:size(orthologList,1),1)=100; +0058 blastStructure(2).ppos(1:size(orthologList,1),1)=100; +0059 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/metacyc/addSpontaneousRxns.html b/doc/external/metacyc/addSpontaneousRxns.html index 32f58a52..a1775d4d 100644 --- a/doc/external/metacyc/addSpontaneousRxns.html +++ b/doc/external/metacyc/addSpontaneousRxns.html @@ -33,7 +33,6 @@

    DESCRIPTION ^SOURCE CODE ^% 0006 % Input: 0007 % rxnList query list of reactions in cell array -0008 % -0009 % metList query list of metabolites in cell array -0010 % -0011 % spontaneousRxnList reterieved spontaneous reactions associated to -0012 % the queried MetaCyc reactions and metabolites -0013 % -0014 % Output: -0015 % pathwayID the cell array of relevant pathways -0016 % -0017 % Usage: spontaneousRxnList=addSpontaneousRxns(rxnList, metList) -0018 -0019 if nargin<2 -0020 disp('Missing input arguments'); -0021 return; -0022 end -0023 -0024 rxnList=unique(rxnList); -0025 -0026 % Create the matrix of MetaCyc pathways and spontaneous reactions -0027 load('metaCycRxns.mat'); -0028 pathways={}; -0029 for i=1:numel(metaCycRxns.rxns) -0030 if ~isempty(metaCycRxns.pwys{i}) -0031 pathways=[pathways;transpose(strsplit(metaCycRxns.pwys{i},';'))]; -0032 end -0033 end -0034 pathways=unique(pathways); -0035 -0036 % Genearte the matirx, row: spontaneousRxns, column: pathways -0037 sprxnPwyMat=zeros(numel(isSpontaneous),numel(pathways)); -0038 for i=1:numel(isSpontaneous) -0039 [a, b]=ismember(isSpontaneous{i},metaCycRxns.rxns); -0040 if ~isempty(metaCycRxns.pwys{b}) -0041 [crap, indexes]=ismember(strsplit(metaCycRxns.pwys{b},';'),pathways); -0042 sprxnPwyMat(i,indexes)=1; -0043 end -0044 end -0045 -0046 % Go through the rxnList to obtain relevant pathways -0047 pwys={}; -0048 for i=1:numel(rxnList) -0049 [a, b]=ismember(rxnList{i},metaCycRxns.rxns); -0050 if a && ~isempty(metaCycRxns.pwys{b}) -0051 pwys=[pwys;transpose(strsplit(metaCycRxns.pwys{b},';'))]; -0052 end -0053 end -0054 pwys=unique(pwys); -0055 -0056 % Get spontaneous reactions associated with the pathways -0057 hits=[]; -0058 for i=1:numel(pwys) -0059 [a, b]=ismember(pwys{i},pathways); -0060 if ~isempty(find(sprxnPwyMat(:,b))) -0061 hits=[hits;find(sprxnPwyMat(:,b))]; -0062 end -0063 end -0064 spontaneousRxnList=isSpontaneous(unique(hits)); -0065 -0066 % Check if the reactants/products are included in metList -0067 for i=1:numel(spontaneousRxnList) -0068 [a, b]=ismember(spontaneousRxnList{i},metaCycRxns.rxns); +0008 % metList query list of metabolites in cell array +0009 % +0010 % spontaneousRxnList reterieved spontaneous reactions associated to +0011 % the queried MetaCyc reactions and metabolites +0012 % +0013 % Output: +0014 % pathwayID the cell array of relevant pathways +0015 % +0016 % Usage: spontaneousRxnList=addSpontaneousRxns(rxnList, metList) +0017 +0018 metList=convertCharArray(metList); +0019 rxnList=convertCharArray(rxnList); +0020 rxnList=unique(rxnList); +0021 +0022 % Create the matrix of MetaCyc pathways and spontaneous reactions +0023 load('metaCycRxns.mat'); +0024 pathways={}; +0025 for i=1:numel(metaCycRxns.rxns) +0026 if ~isempty(metaCycRxns.pwys{i}) +0027 pathways=[pathways;transpose(strsplit(metaCycRxns.pwys{i},';'))]; +0028 end +0029 end +0030 pathways=unique(pathways); +0031 +0032 % Genearte the matirx, row: spontaneousRxns, column: pathways +0033 sprxnPwyMat=zeros(numel(isSpontaneous),numel(pathways)); +0034 for i=1:numel(isSpontaneous) +0035 [a, b]=ismember(isSpontaneous{i},metaCycRxns.rxns); +0036 if ~isempty(metaCycRxns.pwys{b}) +0037 [crap, indexes]=ismember(strsplit(metaCycRxns.pwys{b},';'),pathways); +0038 sprxnPwyMat(i,indexes)=1; +0039 end +0040 end +0041 +0042 % Go through the rxnList to obtain relevant pathways +0043 pwys={}; +0044 for i=1:numel(rxnList) +0045 [a, b]=ismember(rxnList{i},metaCycRxns.rxns); +0046 if a && ~isempty(metaCycRxns.pwys{b}) +0047 pwys=[pwys;transpose(strsplit(metaCycRxns.pwys{b},';'))]; +0048 end +0049 end +0050 pwys=unique(pwys); +0051 +0052 % Get spontaneous reactions associated with the pathways +0053 hits=[]; +0054 for i=1:numel(pwys) +0055 [a, b]=ismember(pwys{i},pathways); +0056 if ~isempty(find(sprxnPwyMat(:,b))) +0057 hits=[hits;find(sprxnPwyMat(:,b))]; +0058 end +0059 end +0060 spontaneousRxnList=isSpontaneous(unique(hits)); +0061 +0062 % Check if the reactants/products are included in metList +0063 for i=1:numel(spontaneousRxnList) +0064 [a, b]=ismember(spontaneousRxnList{i},metaCycRxns.rxns); +0065 +0066 %Obtain the reactants and products +0067 reactants=all(ismember(metaCycRxns.mets(find(metaCycRxns.S(:,b)==-1)),metList)); +0068 products=all(ismember(metaCycRxns.mets(find(metaCycRxns.S(:,b)==1)),metList)); 0069 -0070 %Obtain the reactants and products -0071 reactants=all(ismember(metaCycRxns.mets(find(metaCycRxns.S(:,b)==-1)),metList)); -0072 products=all(ismember(metaCycRxns.mets(find(metaCycRxns.S(:,b)==1)),metList)); -0073 -0074 %Either reactants or products should be present for reversible reaction -0075 if metaCycRxns.rev(b)==1 -0076 if ~(reactants || products) -0077 spontaneousRxnList{i}=[]; -0078 end -0079 %Reactants should be present for irreversible reactions -0080 else -0081 if ~reactants -0082 spontaneousRxnList{i}=[]; -0083 end -0084 end -0085 end -0086 spontaneousRxnList=spontaneousRxnList(~cellfun(@isempty, spontaneousRxnList)); -0087 -0088 % Remove the spontaneousRxns that have already been included -0089 spontaneousRxnList=setdiff(spontaneousRxnList,rxnList); -0090 -0091 % Generate the cell array of relevant pathways -0092 pathwayID=cell(numel(spontaneousRxnList),1); -0093 for i=1:numel(spontaneousRxnList) -0094 index=find(strcmp(spontaneousRxnList{i},isSpontaneous)); -0095 % locate the relevant pathways -0096 relevantpwys=intersect(pathways(find(sprxnPwyMat(index,:))),pwys); -0097 pathwayID{i}=strjoin(relevantpwys,';'); -0098 end -0099 -0100 end +0070 %Either reactants or products should be present for reversible reaction +0071 if metaCycRxns.rev(b)==1 +0072 if ~(reactants || products) +0073 spontaneousRxnList{i}=[]; +0074 end +0075 %Reactants should be present for irreversible reactions +0076 else +0077 if ~reactants +0078 spontaneousRxnList{i}=[]; +0079 end +0080 end +0081 end +0082 spontaneousRxnList=spontaneousRxnList(~cellfun(@isempty, spontaneousRxnList)); +0083 +0084 % Remove the spontaneousRxns that have already been included +0085 spontaneousRxnList=setdiff(spontaneousRxnList,rxnList); +0086 +0087 % Generate the cell array of relevant pathways +0088 pathwayID=cell(numel(spontaneousRxnList),1); +0089 for i=1:numel(spontaneousRxnList) +0090 index=find(strcmp(spontaneousRxnList{i},isSpontaneous)); +0091 % locate the relevant pathways +0092 relevantpwys=intersect(pathways(find(sprxnPwyMat(index,:))),pwys); +0093 pathwayID{i}=strjoin(relevantpwys,';'); +0094 end +0095 +0096 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/metacyc/getEnzymesFromMetaCyc.html b/doc/external/metacyc/getEnzymesFromMetaCyc.html index 580654e1..2fbbf617 100644 --- a/doc/external/metacyc/getEnzymesFromMetaCyc.html +++ b/doc/external/metacyc/getEnzymesFromMetaCyc.html @@ -133,229 +133,234 @@

    SOURCE CODE ^% A line that contains only '//' separates each object. 0060 -0061 %Check if the enzymatic proteins have been parsed before and saved. If so, -0062 %load the model. -0063 [ST, I]=dbstack('-completenames'); -0064 ravenPath=fileparts(fileparts(fileparts(ST(I).file))); -0065 enzymesFile=fullfile(ravenPath,'external','metacyc','metaCycEnzymes.mat'); -0066 metaCycProteinFile='proteins.dat'; -0067 metaCycEnzrxnsFile='enzrxns.dat'; -0068 -0069 if exist(enzymesFile, 'file') -0070 fprintf(['Importing MetaCyc enzymes and reaction-enzyme association from ' strrep(enzymesFile,'\','/') '... ']); -0071 load(enzymesFile); -0072 fprintf('done\n'); -0073 else -0074 fprintf(['Cannot locate ' strrep(enzymesFile,'\','/') '\nNow try to generate it from local MetaCyc data files...\n']); -0075 if ~exist(fullfile(metacycPath,metaCycProteinFile),'file') || ~exist(fullfile(metacycPath,metaCycEnzrxnsFile),'file') -0076 EM=fprintf(['The files of enzymes or proteins cannot be located, and should be downloaded from MetaCyc.\n']); -0077 dispEM(EM); -0078 else -0079 metaCycEnzymes.id='MetaCyc'; -0080 metaCycEnzymes.name='Automatically generated from MetaCyc database'; -0081 -0082 %Reserve space for 10000 enzyme complexs -0083 metaCycEnzymes.cplxs=cell(10000,1); -0084 metaCycEnzymes.cplxComp=cell(10000,1); -0085 metaCycEnzymes.enzymes=cell(50000,1); +0061 if nargin<1 +0062 ravenPath=findRAVENroot(); +0063 metacycPath=fullfile(ravenPath,'external','metacyc'); +0064 else +0065 metacycPath=char(metacycPath); +0066 end +0067 +0068 %Check if the enzymatic proteins have been parsed before and saved. If so, +0069 %load the model. +0070 enzymesFile=fullfile(metacycPath,'metaCycEnzymes.mat'); +0071 metaCycProteinFile='proteins.dat'; +0072 metaCycEnzrxnsFile='enzrxns.dat'; +0073 +0074 try +0075 (['Importing MetaCyc enzymes and reaction-enzyme association from ' strrep(enzymesFile,'\','/') '... ']); +0076 load(enzymesFile); +0077 fprintf('done\n'); +0078 catch +0079 fprintf(['Cannot locate ' strrep(enzymesFile,'\','/') '\nNow try to generate it from local MetaCyc data files...\n']); +0080 if ~exist(fullfile(metacycPath,metaCycProteinFile),'file') || ~exist(fullfile(metacycPath,metaCycEnzrxnsFile),'file') +0081 EM=fprintf(['The files of enzymes or proteins cannot be located, and should be downloaded from MetaCyc.\n']); +0082 dispEM(EM); +0083 else +0084 metaCycEnzymes.id='MetaCyc'; +0085 metaCycEnzymes.name='Automatically generated from MetaCyc database'; 0086 -0087 %Get the information of protein complexes and their components -0088 nCplx=0; -0089 enzymeCounter=0; -0090 -0091 fid = fopen(fullfile(metacycPath,metaCycProteinFile), 'r'); -0092 %Loop through the file -0093 while 1 -0094 tline = fgetl(fid); -0095 -0096 %Abort at end of file -0097 if ~ischar(tline) -0098 break; -0099 end +0087 %Reserve space for 10000 enzyme complexs +0088 metaCycEnzymes.cplxs=cell(10000,1); +0089 metaCycEnzymes.cplxComp=cell(10000,1); +0090 metaCycEnzymes.enzymes=cell(50000,1); +0091 +0092 %Get the information of protein complexes and their components +0093 nCplx=0; +0094 enzymeCounter=0; +0095 +0096 fid = fopen(fullfile(metacycPath,metaCycProteinFile), 'r'); +0097 %Loop through the file +0098 while 1 +0099 tline = fgetl(fid); 0100 -0101 %Add Enzyme id -0102 if numel(tline)>12 && strcmp(tline(1:12),'UNIQUE-ID - ') -0103 enzymeCounter=enzymeCounter+1; -0104 addMe=false; -0105 enzymeID=tline(13:end); -0106 metaCycEnzymes.enzymes{enzymeCounter}=enzymeID; -0107 end -0108 -0109 %Check if enzyme complexes -0110 if strcmp(tline(1:end),'TYPES - Protein-Complexes') -0111 nCplx=nCplx+1; -0112 nComp=0; -0113 -0114 %Reserve 100 subunits for each enzyme complex -0115 Comp.subunit=cell(100,1); -0116 metaCycEnzymes.cplxs{nCplx}=enzymeID; -0117 -0118 addMe=true; -0119 end -0120 -0121 if numel(tline)>13 && strcmp(tline(1:13),'COMPONENTS - ') -0122 if addMe -0123 nComp=nComp+1; -0124 Comp.subunit{nComp}=tline(14:end); -0125 end -0126 end -0127 -0128 if strcmp(tline(1:end),'//') -0129 if addMe -0130 Comp.subunit=Comp.subunit(1:nComp); -0131 metaCycEnzymes.cplxComp{nCplx}=Comp; -0132 addMe=false; -0133 end -0134 end -0135 end -0136 %Close the file -0137 fclose(fid); -0138 -0139 %If too much space was allocated, shrink the model -0140 metaCycEnzymes.cplxs=metaCycEnzymes.cplxs(1:nCplx); -0141 metaCycEnzymes.cplxComp=metaCycEnzymes.cplxComp(1:nCplx); -0142 metaCycEnzymes.enzymes=metaCycEnzymes.enzymes(1:enzymeCounter); +0101 %Abort at end of file +0102 if ~ischar(tline) +0103 break; +0104 end +0105 +0106 %Add Enzyme id +0107 if numel(tline)>12 && strcmp(tline(1:12),'UNIQUE-ID - ') +0108 enzymeCounter=enzymeCounter+1; +0109 addMe=false; +0110 enzymeID=tline(13:end); +0111 metaCycEnzymes.enzymes{enzymeCounter}=enzymeID; +0112 end +0113 +0114 %Check if enzyme complexes +0115 if strcmp(tline(1:end),'TYPES - Protein-Complexes') +0116 nCplx=nCplx+1; +0117 nComp=0; +0118 +0119 %Reserve 100 subunits for each enzyme complex +0120 Comp.subunit=cell(100,1); +0121 metaCycEnzymes.cplxs{nCplx}=enzymeID; +0122 +0123 addMe=true; +0124 end +0125 +0126 if numel(tline)>13 && strcmp(tline(1:13),'COMPONENTS - ') +0127 if addMe +0128 nComp=nComp+1; +0129 Comp.subunit{nComp}=tline(14:end); +0130 end +0131 end +0132 +0133 if strcmp(tline(1:end),'//') +0134 if addMe +0135 Comp.subunit=Comp.subunit(1:nComp); +0136 metaCycEnzymes.cplxComp{nCplx}=Comp; +0137 addMe=false; +0138 end +0139 end +0140 end +0141 %Close the file +0142 fclose(fid); 0143 -0144 % Iteratively go through the components of each complex -0145 for i=1:numel(metaCycEnzymes.cplxComp) -0146 -0147 %replace all complex-type components with their subunits -0148 checkCplx=true; -0149 while checkCplx -0150 x=0; -0151 mat=[]; %Matrix for component of protein-complexs -0152 for j=1:numel(metaCycEnzymes.cplxComp{i}.subunit) -0153 [a, b]=ismember(metaCycEnzymes.cplxComp{i}.subunit{j},metaCycEnzymes.cplxs); -0154 if a -0155 x=x+1; %record this value j, and the cplx id b -0156 mat(x,:)=[j b]; -0157 end -0158 end -0159 -0160 if isempty(mat) -0161 checkCplx=false; % No complexs found among components -0162 else -0163 %go through matrix JB -0164 for k=1:x -0165 %disp(metaCycEnzymes.cplxComp{i}.subunit{mat(k,1)}); -0166 metaCycEnzymes.cplxComp{i}.subunit(mat(k,1))=[]; -0167 metaCycEnzymes.cplxComp{i}.subunit=[metaCycEnzymes.cplxComp{i}.subunit; metaCycEnzymes.cplxComp{mat(k,2)}.subunit]; -0168 end -0169 end -0170 -0171 end -0172 -0173 % make sure the subunits are all included in the enzyme list -0174 % since in one case subunit was not found in enzyme dump file -0175 [a, b] = ismember(metaCycEnzymes.cplxComp{i}.subunit,metaCycEnzymes.enzymes); -0176 if ~all(a) -0177 metaCycEnzymes.cplxComp{i}.subunit = metaCycEnzymes.enzymes(b(find(a))); -0178 end -0179 end -0180 -0181 %Preallocate space for 500000 enzymatic reactions -0182 metaCycEnzymes.enzrxns=cell(50000,1); -0183 metaCycEnzymes.rxns=cell(50000,1); -0184 metaCycEnzymes.rxnNames=cell(50000,1); -0185 metaCycEnzymes.commoname=cell(50000,1); -0186 metaCycEnzymes.rxnEnzymeMat=sparse(50000,enzymeCounter); % row: rxn, column: enzymes -0187 -0188 %Load enzyme and reaction association information -0189 fid = fopen(fullfile(metacycPath,metaCycEnzrxnsFile), 'r'); -0190 -0191 %Keeps track of how many enzymes and reactions have been added -0192 enzrxnCounter=0; -0193 nRxn=0; -0194 -0195 %These contain the mapping between Reactions and Enzymes Loop -0196 %through the file -0197 while 1 -0198 tline = fgetl(fid); -0199 -0200 %Abort at end of file -0201 if ~ischar(tline) -0202 break; -0203 end -0204 -0205 % Get the version of MetaCyc database -0206 if numel(tline)>11 && strcmp(tline(1:11),'# Version: ') -0207 metaCycEnzymes.version=tline(12:end); +0144 %If too much space was allocated, shrink the model +0145 metaCycEnzymes.cplxs=metaCycEnzymes.cplxs(1:nCplx); +0146 metaCycEnzymes.cplxComp=metaCycEnzymes.cplxComp(1:nCplx); +0147 metaCycEnzymes.enzymes=metaCycEnzymes.enzymes(1:enzymeCounter); +0148 +0149 % Iteratively go through the components of each complex +0150 for i=1:numel(metaCycEnzymes.cplxComp) +0151 +0152 %replace all complex-type components with their subunits +0153 checkCplx=true; +0154 while checkCplx +0155 x=0; +0156 mat=[]; %Matrix for component of protein-complexs +0157 for j=1:numel(metaCycEnzymes.cplxComp{i}.subunit) +0158 [a, b]=ismember(metaCycEnzymes.cplxComp{i}.subunit{j},metaCycEnzymes.cplxs); +0159 if a +0160 x=x+1; %record this value j, and the cplx id b +0161 mat(x,:)=[j b]; +0162 end +0163 end +0164 +0165 if isempty(mat) +0166 checkCplx=false; % No complexs found among components +0167 else +0168 %go through matrix JB +0169 for k=1:x +0170 %disp(metaCycEnzymes.cplxComp{i}.subunit{mat(k,1)}); +0171 metaCycEnzymes.cplxComp{i}.subunit(mat(k,1))=[]; +0172 metaCycEnzymes.cplxComp{i}.subunit=[metaCycEnzymes.cplxComp{i}.subunit; metaCycEnzymes.cplxComp{mat(k,2)}.subunit]; +0173 end +0174 end +0175 +0176 end +0177 +0178 % make sure the subunits are all included in the enzyme list +0179 % since in one case subunit was not found in enzyme dump file +0180 [a, b] = ismember(metaCycEnzymes.cplxComp{i}.subunit,metaCycEnzymes.enzymes); +0181 if ~all(a) +0182 metaCycEnzymes.cplxComp{i}.subunit = metaCycEnzymes.enzymes(b(find(a))); +0183 end +0184 end +0185 +0186 %Preallocate space for 500000 enzymatic reactions +0187 metaCycEnzymes.enzrxns=cell(50000,1); +0188 metaCycEnzymes.rxns=cell(50000,1); +0189 metaCycEnzymes.rxnNames=cell(50000,1); +0190 metaCycEnzymes.commoname=cell(50000,1); +0191 metaCycEnzymes.rxnEnzymeMat=sparse(50000,enzymeCounter); % row: rxn, column: enzymes +0192 +0193 %Load enzyme and reaction association information +0194 fid = fopen(fullfile(metacycPath,metaCycEnzrxnsFile), 'r'); +0195 +0196 %Keeps track of how many enzymes and reactions have been added +0197 enzrxnCounter=0; +0198 nRxn=0; +0199 +0200 %These contain the mapping between Reactions and Enzymes Loop +0201 %through the file +0202 while 1 +0203 tline = fgetl(fid); +0204 +0205 %Abort at end of file +0206 if ~ischar(tline) +0207 break; 0208 end 0209 -0210 %Check if it is a new enzymatic reaction -0211 if numel(tline)>12 && strcmp(tline(1:12),'UNIQUE-ID - ') -0212 enzrxnCounter=enzrxnCounter+1; -0213 metaCycEnzymes.enzrxns{enzrxnCounter}=tline(13:end); -0214 metaCycEnzymes.commoname{enzrxnCounter}=''; -0215 end -0216 -0217 %Add common name of enzymatic reactions -0218 if numel(tline)>14 && strcmp(tline(1:14),'COMMON-NAME - ') -0219 metaCycEnzymes.commoname{enzrxnCounter}=tline(15:end); -0220 -0221 %Remove HTML symobls -0222 metaCycEnzymes.commoname{enzrxnCounter}=regexprep(metaCycEnzymes.commoname{enzrxnCounter},'<(\w+)>',''); -0223 metaCycEnzymes.commoname{enzrxnCounter}=regexprep(metaCycEnzymes.commoname{enzrxnCounter},'</(\w+)>',''); -0224 metaCycEnzymes.commoname{enzrxnCounter}=regexprep(metaCycEnzymes.commoname{enzrxnCounter},'[&;]',''); -0225 end -0226 -0227 % I add one cell array rxns for checking existing ones by -0228 % ismember because I cannot manage field rxns in this function -0229 -0230 %Add enzyme name -0231 if numel(tline)>9 && strcmp(tline(1:9),'ENZYME - ') -0232 -0233 %Save the index in enzymes field to nEnzyme -0234 [x, nEnzyme]=ismember(tline(10:end),metaCycEnzymes.enzymes); -0235 if ~x -0236 %disp(tline(10:end)); -0237 end -0238 end -0239 -0240 %Add reaction id, and rxnNames by concatenating unique common -0241 %names -0242 if numel(tline)>11 && strcmp(tline(1:11),'REACTION - ') -0243 nRxn=nRxn+1; -0244 rxns{nRxn}=''; -0245 rxnID=tline(12:end); -0246 [c, d]=ismember(rxnID,rxns); -0247 if c -0248 nRxn=nRxn-1; -0249 -0250 %Check if this common name has been included by -0251 %rxnNames -0252 k=strfind(metaCycEnzymes.rxnNames{d},metaCycEnzymes.commoname{enzrxnCounter}); -0253 if isempty(k) -0254 metaCycEnzymes.rxnNames{d}=strcat(metaCycEnzymes.rxnNames{d},';',metaCycEnzymes.commoname{enzrxnCounter}); -0255 end -0256 metaCycEnzymes.rxnEnzymeMat(d,nEnzyme)=1; -0257 else -0258 metaCycEnzymes.rxns{nRxn}=rxnID; -0259 metaCycEnzymes.rxnNames{nRxn}=metaCycEnzymes.commoname{enzrxnCounter}; -0260 rxns{nRxn}=rxnID; -0261 metaCycEnzymes.rxnEnzymeMat(nRxn,nEnzyme)=1; -0262 end -0263 end -0264 -0265 end -0266 -0267 %Close the file -0268 fclose(fid); -0269 -0270 %Shrink the sizes -0271 metaCycEnzymes.enzrxns=metaCycEnzymes.enzrxns(1:enzrxnCounter); -0272 metaCycEnzymes.commoname=metaCycEnzymes.commoname(1:enzrxnCounter); -0273 metaCycEnzymes.rxns=metaCycEnzymes.rxns(1:nRxn); -0274 metaCycEnzymes.rxnNames=metaCycEnzymes.rxnNames(1:nRxn); -0275 metaCycEnzymes.rxnEnzymeMat=metaCycEnzymes.rxnEnzymeMat(1:nRxn,:); -0276 -0277 %Save the model structure -0278 save(enzymesFile,'metaCycEnzymes'); -0279 fprintf(['New metaCycEnzymes.mat has been successfully updated!\n\n']); -0280 end -0281 -0282 end -0283 end +0210 % Get the version of MetaCyc database +0211 if numel(tline)>11 && strcmp(tline(1:11),'# Version: ') +0212 metaCycEnzymes.version=tline(12:end); +0213 end +0214 +0215 %Check if it is a new enzymatic reaction +0216 if numel(tline)>12 && strcmp(tline(1:12),'UNIQUE-ID - ') +0217 enzrxnCounter=enzrxnCounter+1; +0218 metaCycEnzymes.enzrxns{enzrxnCounter}=tline(13:end); +0219 metaCycEnzymes.commoname{enzrxnCounter}=''; +0220 end +0221 +0222 %Add common name of enzymatic reactions +0223 if numel(tline)>14 && strcmp(tline(1:14),'COMMON-NAME - ') +0224 metaCycEnzymes.commoname{enzrxnCounter}=tline(15:end); +0225 +0226 %Remove HTML symobls +0227 metaCycEnzymes.commoname{enzrxnCounter}=regexprep(metaCycEnzymes.commoname{enzrxnCounter},'<(\w+)>',''); +0228 metaCycEnzymes.commoname{enzrxnCounter}=regexprep(metaCycEnzymes.commoname{enzrxnCounter},'</(\w+)>',''); +0229 metaCycEnzymes.commoname{enzrxnCounter}=regexprep(metaCycEnzymes.commoname{enzrxnCounter},'[&;]',''); +0230 end +0231 +0232 % I add one cell array rxns for checking existing ones by +0233 % ismember because I cannot manage field rxns in this function +0234 +0235 %Add enzyme name +0236 if numel(tline)>9 && strcmp(tline(1:9),'ENZYME - ') +0237 +0238 %Save the index in enzymes field to nEnzyme +0239 [x, nEnzyme]=ismember(tline(10:end),metaCycEnzymes.enzymes); +0240 if ~x +0241 %disp(tline(10:end)); +0242 end +0243 end +0244 +0245 %Add reaction id, and rxnNames by concatenating unique common +0246 %names +0247 if numel(tline)>11 && strcmp(tline(1:11),'REACTION - ') +0248 nRxn=nRxn+1; +0249 rxns{nRxn}=''; +0250 rxnID=tline(12:end); +0251 [c, d]=ismember(rxnID,rxns); +0252 if c +0253 nRxn=nRxn-1; +0254 +0255 %Check if this common name has been included by +0256 %rxnNames +0257 k=strfind(metaCycEnzymes.rxnNames{d},metaCycEnzymes.commoname{enzrxnCounter}); +0258 if isempty(k) +0259 metaCycEnzymes.rxnNames{d}=strcat(metaCycEnzymes.rxnNames{d},';',metaCycEnzymes.commoname{enzrxnCounter}); +0260 end +0261 metaCycEnzymes.rxnEnzymeMat(d,nEnzyme)=1; +0262 else +0263 metaCycEnzymes.rxns{nRxn}=rxnID; +0264 metaCycEnzymes.rxnNames{nRxn}=metaCycEnzymes.commoname{enzrxnCounter}; +0265 rxns{nRxn}=rxnID; +0266 metaCycEnzymes.rxnEnzymeMat(nRxn,nEnzyme)=1; +0267 end +0268 end +0269 +0270 end +0271 +0272 %Close the file +0273 fclose(fid); +0274 +0275 %Shrink the sizes +0276 metaCycEnzymes.enzrxns=metaCycEnzymes.enzrxns(1:enzrxnCounter); +0277 metaCycEnzymes.commoname=metaCycEnzymes.commoname(1:enzrxnCounter); +0278 metaCycEnzymes.rxns=metaCycEnzymes.rxns(1:nRxn); +0279 metaCycEnzymes.rxnNames=metaCycEnzymes.rxnNames(1:nRxn); +0280 metaCycEnzymes.rxnEnzymeMat=metaCycEnzymes.rxnEnzymeMat(1:nRxn,:); +0281 +0282 %Save the model structure +0283 save(enzymesFile,'metaCycEnzymes'); +0284 fprintf(['New metaCycEnzymes.mat has been successfully updated!\n\n']); +0285 end +0286 +0287 end +0288 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/metacyc/getMetaCycModelForOrganism.html b/doc/external/metacyc/getMetaCycModelForOrganism.html index 41d92407..5dffd54e 100644 --- a/doc/external/metacyc/getMetaCycModelForOrganism.html +++ b/doc/external/metacyc/getMetaCycModelForOrganism.html @@ -102,226 +102,228 @@

    SOURCE CODE ^% Usage: model=getMetaCycModelForOrganism(organismID,fastaFile,... 0031 % keepTransportRxns,keepUnbalanced,keepUndetermined,minScore,minPositives,useDiamond) 0032 -0033 if nargin<2 -0034 EM='No query protein fasta file is specified'; -0035 dispEM(EM); -0036 end -0037 if nargin<3 -0038 keepTransportRxns=false; +0033 organismID=char(organismID); +0034 if nargin<2 +0035 EM='No query protein fasta file is specified'; +0036 dispEM(EM); +0037 else +0038 fastaFile=char(fastaFile); 0039 end -0040 if nargin<4 -0041 keepUnbalanced=false; +0040 if nargin<3 +0041 keepTransportRxns=false; 0042 end -0043 if nargin<5 -0044 keepUndetermined=false; +0043 if nargin<4 +0044 keepUnbalanced=false; 0045 end -0046 if nargin<6 -0047 minScore=100; +0046 if nargin<5 +0047 keepUndetermined=false; 0048 end -0049 if nargin<7 -0050 minPositives=45; +0049 if nargin<6 +0050 minScore=100; 0051 end -0052 if nargin<8 -0053 useDiamond=true; +0052 if nargin<7 +0053 minPositives=45; 0054 end -0055 -0056 if isempty(fastaFile) -0057 error('*** The query FASTA filename cannot be empty! ***'); -0058 else -0059 fprintf('\nChecking existence of query FASTA file... '); -0060 %Check if query fasta exists -0061 fastaFile=checkFileExistence(fastaFile,2); %Copy file to temp dir -0062 fprintf('done\n'); -0063 end -0064 -0065 %First generate the full MetaCyc model -0066 metaCycModel=getModelFromMetaCyc([],keepTransportRxns,keepUnbalanced,keepUndetermined); -0067 fprintf('The full MetaCyc model loaded\n'); -0068 -0069 %Create the draft model from MetaCyc super model model=metaCycModel; -0070 model.id=organismID; -0071 model.name='Generated by homology with MetaCyc database'; -0072 model.rxns=metaCycModel.rxns; -0073 model.rxnNames=metaCycModel.rxnNames; -0074 model.eccodes=metaCycModel.eccodes; -0075 model.subSystems=metaCycModel.subSystems; -0076 model.rxnMiriams=metaCycModel.rxnMiriams; -0077 model.rxnReferences=metaCycModel.rxnReferences; -0078 model.lb=metaCycModel.lb; -0079 model.ub=metaCycModel.ub; -0080 model.rev=metaCycModel.rev; -0081 model.c=metaCycModel.c; -0082 model.equations=metaCycModel.equations; -0083 -0084 %Get the 'external' directory for RAVEN Toolbox. -0085 [ST I]=dbstack('-completenames'); -0086 ravenPath=fileparts(fileparts(ST(I).file)); -0087 -0088 %Generate blast strcture by either DIAMOND or BLASTP -0089 if useDiamond -0090 blastStruc=getDiamond(organismID,fastaFile,{'MetaCyc'},fullfile(ravenPath,'metacyc','protseq.fsa')); -0091 else -0092 blastStruc=getBlast(organismID,fastaFile,{'MetaCyc'},fullfile(ravenPath,'metacyc','protseq.fsa')); -0093 end -0094 -0095 %Only look the query -0096 blastStructure=blastStruc(2); -0097 -0098 %Remove all blast hits that are below the cutoffs -0099 indexes=blastStructure.bitscore>=minScore & blastStructure.ppos>=minPositives; -0100 blastStructure.toGenes(~indexes)=[]; -0101 blastStructure.fromGenes(~indexes)=[]; -0102 blastStructure.evalue(~indexes)=[]; -0103 blastStructure.aligLen(~indexes)=[]; -0104 blastStructure.identity(~indexes)=[]; -0105 blastStructure.bitscore(~indexes)=[]; -0106 blastStructure.ppos(~indexes)=[]; -0107 fprintf('Completed searching against MetaCyc protein sequences.\n'); -0108 -0109 % Get the qualified genes of query organism from blast structure -0110 model.genes=cell(10000,1); -0111 model.proteins=cell(10000,1); -0112 model.bitscore=zeros(10000,1); -0113 model.ppos=zeros(10000,1); -0114 num=1; -0115 -0116 %Go through the strucutre and find out the hit with the best bit score -0117 for i=1:numel(blastStructure.fromGenes) -0118 if num==1 -0119 model.genes(num)=blastStructure.fromGenes(i); -0120 model.proteins(num)=strrep(blastStructure.toGenes(i), 'gnl|META|', ''); -0121 model.bitscore(num)=blastStructure.bitscore(i); -0122 model.ppos(num)=blastStructure.ppos(i); -0123 num=num+1; -0124 lastGene=blastStructure.fromGenes(i); -0125 else -0126 if ~isequal(lastGene,blastStructure.fromGenes(i)) -0127 model.genes(num)=blastStructure.fromGenes(i); -0128 model.proteins(num)=strrep(blastStructure.toGenes(i), 'gnl|META|', ''); -0129 model.bitscore(num)=blastStructure.bitscore(i); -0130 model.ppos(num)=blastStructure.ppos(i); -0131 num=num+1; -0132 lastGene=blastStructure.fromGenes(i); -0133 else -0134 if model.bitscore(num)<blastStructure.bitscore(i) -0135 model.bitscore(num)=blastStructure.bitscore(i); -0136 model.proteins(num)=strrep(blastStructure.toGenes(i), 'gnl|META|', ''); -0137 model.ppos(num)=blastStructure.ppos(i); -0138 end -0139 end -0140 end -0141 end -0142 model.genes=model.genes(1:num-1); -0143 model.proteins=model.proteins(1:num-1); -0144 model.bitscore=model.bitscore(1:num-1); -0145 model.ppos=model.ppos(1:num-1); -0146 -0147 % Get the indexes of matched genes in the metaCycModel -0148 % because some enzymes in the FASTA file cannot be found in the dump file -0149 [hits, indexes]=ismember(model.proteins,metaCycModel.genes); -0150 found = find(hits); -0151 model.genes=model.genes(found); -0152 -0153 % Restructure the rxnGeneMat matrix -0154 model.rxnGeneMat=sparse(metaCycModel.rxnGeneMat(:,indexes(found))); -0155 -0156 %Remove all reactions without genes -0157 hasGenes=any(model.rxnGeneMat,2); -0158 model=removeReactions(model,~hasGenes,true); -0159 -0160 %Generate grRules, only consider the or relationship here Matched enzymes -0161 %are stored in field rxnScores, -0162 rxnNum=numel(model.rxns); -0163 model.rxnConfidenceScores=NaN(rxnNum,1); -0164 model.rxnConfidenceScores(:)=2; -0165 model.grRules=cell(rxnNum,1); -0166 %model.rxnScores=cell(rxnNum,1); -0167 for j=1:rxnNum -0168 model.grRules{j}=''; -0169 I=find(model.rxnGeneMat(j,:)); -0170 for k=1:numel(I) -0171 if isempty(model.grRules{j}) -0172 model.grRules(j)=model.genes(I(k)); -0173 %model.rxnScores(j)=model.proteins(I(k)); -0174 else -0175 model.grRules(j)=strcat(model.grRules(j),{' or '},model.genes(I(k))); -0176 %model.rxnScores(j)=strcat(model.rxnScores(j),{' or -0177 %'},model.proteins(I(k))); -0178 end -0179 end -0180 end -0181 %update genes field -0182 model.genes=model.genes(any(model.rxnGeneMat)); -0183 -0184 %Construct the S matrix and list of metabolites -0185 [S, mets, badRxns]=constructS(model.equations); -0186 model.S=S; -0187 model.mets=mets; -0188 -0189 %model=removeReactions(model,badRxns,true,true); +0055 if nargin<8 +0056 useDiamond=true; +0057 end +0058 +0059 if isempty(fastaFile) +0060 error('*** The query FASTA filename cannot be empty! ***'); +0061 else +0062 fprintf('\nChecking existence of query FASTA file... '); +0063 %Check if query fasta exists +0064 fastaFile=checkFileExistence(fastaFile,2); %Copy file to temp dir +0065 fprintf('done\n'); +0066 end +0067 +0068 %First generate the full MetaCyc model +0069 metaCycModel=getModelFromMetaCyc([],keepTransportRxns,keepUnbalanced,keepUndetermined); +0070 fprintf('The full MetaCyc model loaded\n'); +0071 +0072 %Create the draft model from MetaCyc super model model=metaCycModel; +0073 model.id=organismID; +0074 model.name='Generated by homology with MetaCyc database'; +0075 model.rxns=metaCycModel.rxns; +0076 model.rxnNames=metaCycModel.rxnNames; +0077 model.eccodes=metaCycModel.eccodes; +0078 model.subSystems=metaCycModel.subSystems; +0079 model.rxnMiriams=metaCycModel.rxnMiriams; +0080 model.rxnReferences=metaCycModel.rxnReferences; +0081 model.lb=metaCycModel.lb; +0082 model.ub=metaCycModel.ub; +0083 model.rev=metaCycModel.rev; +0084 model.c=metaCycModel.c; +0085 model.equations=metaCycModel.equations; +0086 +0087 %Get the root directory for RAVEN Toolbox. +0088 ravenPath=findRAVENroot(); +0089 +0090 %Generate blast strcture by either DIAMOND or BLASTP +0091 if useDiamond +0092 blastStruc=getDiamond(organismID,fastaFile,{'MetaCyc'},fullfile(ravenPath,'external','metacyc','protseq.fsa')); +0093 else +0094 blastStruc=getBlast(organismID,fastaFile,{'MetaCyc'},fullfile(ravenPath,'external','metacyc','protseq.fsa')); +0095 end +0096 +0097 %Only look the query +0098 blastStructure=blastStruc(2); +0099 +0100 %Remove all blast hits that are below the cutoffs +0101 indexes=blastStructure.bitscore>=minScore & blastStructure.ppos>=minPositives; +0102 blastStructure.toGenes(~indexes)=[]; +0103 blastStructure.fromGenes(~indexes)=[]; +0104 blastStructure.evalue(~indexes)=[]; +0105 blastStructure.aligLen(~indexes)=[]; +0106 blastStructure.identity(~indexes)=[]; +0107 blastStructure.bitscore(~indexes)=[]; +0108 blastStructure.ppos(~indexes)=[]; +0109 fprintf('Completed searching against MetaCyc protein sequences.\n'); +0110 +0111 % Get the qualified genes of query organism from blast structure +0112 model.genes=cell(10000,1); +0113 model.proteins=cell(10000,1); +0114 model.bitscore=zeros(10000,1); +0115 model.ppos=zeros(10000,1); +0116 num=1; +0117 +0118 %Go through the strucutre and find out the hit with the best bit score +0119 for i=1:numel(blastStructure.fromGenes) +0120 if num==1 +0121 model.genes(num)=blastStructure.fromGenes(i); +0122 model.proteins(num)=strrep(blastStructure.toGenes(i), 'gnl|META|', ''); +0123 model.bitscore(num)=blastStructure.bitscore(i); +0124 model.ppos(num)=blastStructure.ppos(i); +0125 num=num+1; +0126 lastGene=blastStructure.fromGenes(i); +0127 else +0128 if ~isequal(lastGene,blastStructure.fromGenes(i)) +0129 model.genes(num)=blastStructure.fromGenes(i); +0130 model.proteins(num)=strrep(blastStructure.toGenes(i), 'gnl|META|', ''); +0131 model.bitscore(num)=blastStructure.bitscore(i); +0132 model.ppos(num)=blastStructure.ppos(i); +0133 num=num+1; +0134 lastGene=blastStructure.fromGenes(i); +0135 else +0136 if model.bitscore(num)<blastStructure.bitscore(i) +0137 model.bitscore(num)=blastStructure.bitscore(i); +0138 model.proteins(num)=strrep(blastStructure.toGenes(i), 'gnl|META|', ''); +0139 model.ppos(num)=blastStructure.ppos(i); +0140 end +0141 end +0142 end +0143 end +0144 model.genes=model.genes(1:num-1); +0145 model.proteins=model.proteins(1:num-1); +0146 model.bitscore=model.bitscore(1:num-1); +0147 model.ppos=model.ppos(1:num-1); +0148 +0149 % Get the indexes of matched genes in the metaCycModel +0150 % because some enzymes in the FASTA file cannot be found in the dump file +0151 [hits, indexes]=ismember(model.proteins,metaCycModel.genes); +0152 found = find(hits); +0153 model.genes=model.genes(found); +0154 +0155 % Restructure the rxnGeneMat matrix +0156 model.rxnGeneMat=sparse(metaCycModel.rxnGeneMat(:,indexes(found))); +0157 +0158 %Remove all reactions without genes +0159 hasGenes=any(model.rxnGeneMat,2); +0160 model=removeReactions(model,~hasGenes,true); +0161 +0162 %Generate grRules, only consider the or relationship here Matched enzymes +0163 %are stored in field rxnScores, +0164 rxnNum=numel(model.rxns); +0165 model.rxnConfidenceScores=NaN(rxnNum,1); +0166 model.rxnConfidenceScores(:)=2; +0167 model.grRules=cell(rxnNum,1); +0168 %model.rxnScores=cell(rxnNum,1); +0169 for j=1:rxnNum +0170 model.grRules{j}=''; +0171 I=find(model.rxnGeneMat(j,:)); +0172 for k=1:numel(I) +0173 if isempty(model.grRules{j}) +0174 model.grRules(j)=model.genes(I(k)); +0175 %model.rxnScores(j)=model.proteins(I(k)); +0176 else +0177 model.grRules(j)=strcat(model.grRules(j),{' or '},model.genes(I(k))); +0178 %model.rxnScores(j)=strcat(model.rxnScores(j),{' or +0179 %'},model.proteins(I(k))); +0180 end +0181 end +0182 end +0183 %update genes field +0184 model.genes=model.genes(any(model.rxnGeneMat)); +0185 +0186 %Construct the S matrix and list of metabolites +0187 [S, mets, badRxns]=constructS(model.equations); +0188 model.S=S; +0189 model.mets=mets; 0190 -0191 %Then match up metabolites -0192 metaCycMets=getMetsFromMetaCyc([]); -0193 -0194 %Add information about all metabolites to the model -0195 [a, b]=ismember(model.mets,metaCycMets.mets); -0196 a=find(a); -0197 b=b(a); -0198 -0199 if ~isfield(model,'metNames') -0200 model.metNames=cell(numel(model.mets),1); -0201 model.metNames(:)={''}; -0202 end -0203 model.metNames(a)=metaCycMets.metNames(b); -0204 -0205 if ~isfield(model,'metFormulas') -0206 model.metFormulas=cell(numel(model.mets),1); -0207 model.metFormulas(:)={''}; -0208 end -0209 model.metFormulas(a)=metaCycMets.metFormulas(b); -0210 -0211 if ~isfield(model,'metCharges') -0212 model.metCharges=zeros(numel(model.mets),1); -0213 end -0214 model.metCharges(a)=metaCycMets.metCharges(b); -0215 -0216 if ~isfield(model,'b') -0217 model.b=zeros(numel(model.mets),1); -0218 end -0219 %model.b(a)=metaCycMets.b(b); -0220 -0221 if ~isfield(model,'inchis') -0222 model.inchis=cell(numel(model.mets),1); -0223 model.inchis(:)={''}; -0224 end -0225 model.inchis(a)=metaCycMets.inchis(b); -0226 -0227 if ~isfield(model,'metMiriams') -0228 model.metMiriams=cell(numel(model.mets),1); -0229 end -0230 model.metMiriams(a)=metaCycMets.metMiriams(b); -0231 -0232 %Put all metabolites in one compartment called 's' (for system). This is -0233 %done just to be more compatible with the rest of the code -0234 model.comps={'s'}; -0235 model.compNames={'System'}; -0236 model.metComps=ones(numel(model.mets),1); -0237 -0238 %It could also be that the metabolite names are empty for some reason In -0239 %that case, use the ID instead -0240 I=cellfun(@isempty,model.metNames); -0241 model.metNames(I)=model.mets(I); -0242 -0243 %Remove additional fields -0244 model=rmfield(model,{'proteins','bitscore','ppos'}); -0245 -0246 %In the end fix grRules and rxnGeneMat -0247 [grRules,rxnGeneMat] = standardizeGrRules(model,false); %Get detailed output -0248 model.grRules = grRules; -0249 model.rxnGeneMat = rxnGeneMat; -0250 %Remove the temp fasta file -0251 delete(fastaFile) -0252 end +0191 %model=removeReactions(model,badRxns,true,true); +0192 +0193 %Then match up metabolites +0194 metaCycMets=getMetsFromMetaCyc([]); +0195 +0196 %Add information about all metabolites to the model +0197 [a, b]=ismember(model.mets,metaCycMets.mets); +0198 a=find(a); +0199 b=b(a); +0200 +0201 if ~isfield(model,'metNames') +0202 model.metNames=cell(numel(model.mets),1); +0203 model.metNames(:)={''}; +0204 end +0205 model.metNames(a)=metaCycMets.metNames(b); +0206 +0207 if ~isfield(model,'metFormulas') +0208 model.metFormulas=cell(numel(model.mets),1); +0209 model.metFormulas(:)={''}; +0210 end +0211 model.metFormulas(a)=metaCycMets.metFormulas(b); +0212 +0213 if ~isfield(model,'metCharges') +0214 model.metCharges=zeros(numel(model.mets),1); +0215 end +0216 model.metCharges(a)=metaCycMets.metCharges(b); +0217 +0218 if ~isfield(model,'b') +0219 model.b=zeros(numel(model.mets),1); +0220 end +0221 %model.b(a)=metaCycMets.b(b); +0222 +0223 if ~isfield(model,'inchis') +0224 model.inchis=cell(numel(model.mets),1); +0225 model.inchis(:)={''}; +0226 end +0227 model.inchis(a)=metaCycMets.inchis(b); +0228 +0229 if ~isfield(model,'metMiriams') +0230 model.metMiriams=cell(numel(model.mets),1); +0231 end +0232 model.metMiriams(a)=metaCycMets.metMiriams(b); +0233 +0234 %Put all metabolites in one compartment called 's' (for system). This is +0235 %done just to be more compatible with the rest of the code +0236 model.comps={'s'}; +0237 model.compNames={'System'}; +0238 model.metComps=ones(numel(model.mets),1); +0239 +0240 %It could also be that the metabolite names are empty for some reason In +0241 %that case, use the ID instead +0242 I=cellfun(@isempty,model.metNames); +0243 model.metNames(I)=model.mets(I); +0244 +0245 %Remove additional fields +0246 model=rmfield(model,{'proteins','bitscore','ppos'}); +0247 +0248 %In the end fix grRules and rxnGeneMat +0249 [grRules,rxnGeneMat] = standardizeGrRules(model,false); %Get detailed output +0250 model.grRules = grRules; +0251 model.rxnGeneMat = rxnGeneMat; +0252 %Remove the temp fasta file +0253 delete(fastaFile) +0254 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/metacyc/getMetsFromMetaCyc.html b/doc/external/metacyc/getMetsFromMetaCyc.html index 86d2cb8a..8179f5f4 100644 --- a/doc/external/metacyc/getMetsFromMetaCyc.html +++ b/doc/external/metacyc/getMetsFromMetaCyc.html @@ -131,227 +131,232 @@

    SOURCE CODE ^% Check if the metabolites have been parsed before and saved. If so, load 0059 % the model. -0060 [ST, I]=dbstack('-completenames'); -0061 ravenPath=fileparts(fileparts(fileparts(ST(I).file))); -0062 metsFile=fullfile(ravenPath,'external','metacyc','metaCycMets.mat'); -0063 metaCycMetFile='compounds.dat'; -0064 -0065 if exist(metsFile, 'file') -0066 fprintf(['Importing MetaCyc metabolites from ' strrep(metsFile,'\','/') '... ']); -0067 load(metsFile); -0068 fprintf('done\n'); -0069 else -0070 fprintf(['Cannot locate ' strrep(metsFile,'\','/') '\nNow try to generate it from local MetaCyc data files...\n']); -0071 if ~exist(fullfile(metacycPath,metaCycMetFile),'file') -0072 EM=fprintf(['The file of metabolites cannot be located, and should be downloaded from MetaCyc.\n']); -0073 dispEM(EM); -0074 else -0075 %Add new functionality in the order specified in models -0076 metaCycMets.id='MetaCyc'; -0077 metaCycMets.name='Automatically generated from MetaCyc database'; -0078 -0079 %Preallocate memory for 50000 metabolites -0080 metaCycMets.mets=cell(50000,1); -0081 metaCycMets.metNames=cell(50000,1); -0082 metaCycMets.metFormulas=cell(50000,1); -0083 metaCycMets.inchis=cell(50000,1); -0084 metaCycMets.metCharges=zeros(50000,1); -0085 metaCycMets.metMiriams=cell(50000,1); -0086 metaCycMets.keggid=cell(50000,1); -0087 -0088 %First load information on metabolite ID, name, formula, and others -0089 fid = fopen(fullfile(metacycPath,metaCycMetFile), 'r'); -0090 -0091 %Keeps track of how many metabolites that have been added -0092 metCounter=0; -0093 -0094 %Loop through the file -0095 while 1 -0096 %Get the next line -0097 tline = fgetl(fid); -0098 %disp(tline); -0099 -0100 % Abort at end of file -0101 if ~ischar(tline) -0102 break; -0103 end +0060 if nargin<1 +0061 ravenPath=findRAVENroot(); +0062 metacycPath=fullfile(ravenPath,'external','metacyc'); +0063 else +0064 metacycPath=char(metacycPath); +0065 end +0066 +0067 metsFile=fullfile(metacycPath,'metaCycMets.mat'); +0068 metaCycMetFile='compounds.dat'; +0069 +0070 if exist(metsFile, 'file') +0071 fprintf(['Importing MetaCyc metabolites from ' strrep(metsFile,'\','/') '... ']); +0072 load(metsFile); +0073 fprintf('done\n'); +0074 else +0075 fprintf(['Cannot locate ' strrep(metsFile,'\','/') '\nNow try to generate it from local MetaCyc data files...\n']); +0076 if ~exist(fullfile(metacycPath,metaCycMetFile),'file') +0077 EM=fprintf(['The file of metabolites cannot be located, and should be downloaded from MetaCyc.\n']); +0078 dispEM(EM); +0079 else +0080 %Add new functionality in the order specified in models +0081 metaCycMets.id='MetaCyc'; +0082 metaCycMets.name='Automatically generated from MetaCyc database'; +0083 +0084 %Preallocate memory for 50000 metabolites +0085 metaCycMets.mets=cell(50000,1); +0086 metaCycMets.metNames=cell(50000,1); +0087 metaCycMets.metFormulas=cell(50000,1); +0088 metaCycMets.inchis=cell(50000,1); +0089 metaCycMets.metCharges=zeros(50000,1); +0090 metaCycMets.metMiriams=cell(50000,1); +0091 metaCycMets.keggid=cell(50000,1); +0092 +0093 %First load information on metabolite ID, name, formula, and others +0094 fid = fopen(fullfile(metacycPath,metaCycMetFile), 'r'); +0095 +0096 %Keeps track of how many metabolites that have been added +0097 metCounter=0; +0098 +0099 %Loop through the file +0100 while 1 +0101 %Get the next line +0102 tline = fgetl(fid); +0103 %disp(tline); 0104 -0105 % Get the version of MetaCyc database -0106 if numel(tline)>11 && strcmp(tline(1:11),'# Version: ') -0107 metaCycMets.version=tline(12:end); +0105 % Abort at end of file +0106 if ~ischar(tline) +0107 break; 0108 end -0109 -0110 %Check if it is a new entry -0111 if numel(tline)>12 && strcmp(tline(1:12),'UNIQUE-ID - ') -0112 metCounter=metCounter+1; -0113 -0114 %Add empty strings as initial values -0115 metaCycMets.metNames{metCounter}=''; -0116 metaCycMets.metFormulas{metCounter}=''; -0117 metaCycMets.inchis{metCounter}=''; -0118 %metaCycMets.smiles{metCounter}=''; -0119 %metaCycMets.pubchem{metCounter}=''; -0120 metaCycMets.keggid{metCounter}=''; -0121 nonStandardInchis = ''; -0122 -0123 %Add compound ID -0124 metaCycMets.mets{metCounter}=tline(13:end); -0125 end -0126 -0127 -0128 %Add name -0129 if numel(tline)>14 && strcmp(tline(1:14),'COMMON-NAME - ') -0130 metaCycMets.metNames{metCounter}=tline(15:end); -0131 -0132 %Romve HTML symbols -0133 metaCycMets.metNames{metCounter}=regexprep(metaCycMets.metNames{metCounter},'<(\w+)>',''); -0134 metaCycMets.metNames{metCounter}=regexprep(metaCycMets.metNames{metCounter},'</(\w+)>',''); -0135 metaCycMets.metNames{metCounter}=regexprep(metaCycMets.metNames{metCounter},'[&;]',''); -0136 end -0137 -0138 %Add charge -0139 if numel(tline)>16 && strcmp(tline(1:16),'ATOM-CHARGES - (') -0140 atomCharge=tline(17:end-1); -0141 -0142 s=strfind(atomCharge,' '); -0143 if any(s) -0144 atomCharge=atomCharge(s+1:end); -0145 metaCycMets.metCharges(metCounter,1)=metaCycMets.metCharges(metCounter,1)+str2num(atomCharge); -0146 end -0147 end -0148 -0149 %Add inchis -0150 if numel(tline)>14 && strcmp(tline(1:14),'INCHI - InChI=') -0151 metaCycMets.inchis{metCounter}=tline(15:end); +0109 +0110 % Get the version of MetaCyc database +0111 if numel(tline)>11 && strcmp(tline(1:11),'# Version: ') +0112 metaCycMets.version=tline(12:end); +0113 end +0114 +0115 %Check if it is a new entry +0116 if numel(tline)>12 && strcmp(tline(1:12),'UNIQUE-ID - ') +0117 metCounter=metCounter+1; +0118 +0119 %Add empty strings as initial values +0120 metaCycMets.metNames{metCounter}=''; +0121 metaCycMets.metFormulas{metCounter}=''; +0122 metaCycMets.inchis{metCounter}=''; +0123 %metaCycMets.smiles{metCounter}=''; +0124 %metaCycMets.pubchem{metCounter}=''; +0125 metaCycMets.keggid{metCounter}=''; +0126 nonStandardInchis = ''; +0127 +0128 %Add compound ID +0129 metaCycMets.mets{metCounter}=tline(13:end); +0130 end +0131 +0132 +0133 %Add name +0134 if numel(tline)>14 && strcmp(tline(1:14),'COMMON-NAME - ') +0135 metaCycMets.metNames{metCounter}=tline(15:end); +0136 +0137 %Romve HTML symbols +0138 metaCycMets.metNames{metCounter}=regexprep(metaCycMets.metNames{metCounter},'<(\w+)>',''); +0139 metaCycMets.metNames{metCounter}=regexprep(metaCycMets.metNames{metCounter},'</(\w+)>',''); +0140 metaCycMets.metNames{metCounter}=regexprep(metaCycMets.metNames{metCounter},'[&;]',''); +0141 end +0142 +0143 %Add charge +0144 if numel(tline)>16 && strcmp(tline(1:16),'ATOM-CHARGES - (') +0145 atomCharge=tline(17:end-1); +0146 +0147 s=strfind(atomCharge,' '); +0148 if any(s) +0149 atomCharge=atomCharge(s+1:end); +0150 metaCycMets.metCharges(metCounter,1)=metaCycMets.metCharges(metCounter,1)+str2num(atomCharge); +0151 end 0152 end 0153 -0154 %Add non-standard inchis -0155 if numel(tline)>27 && strcmp(tline(1:27),'NON-STANDARD-INCHI - InChI=') -0156 nonStandardInchis=tline(28:end); +0154 %Add inchis +0155 if numel(tline)>14 && strcmp(tline(1:14),'INCHI - InChI=') +0156 metaCycMets.inchis{metCounter}=tline(15:end); 0157 end 0158 -0159 %Add SMILES -0160 if numel(tline)>9 && strcmp(tline(1:9),'SMILES - ') -0161 -0162 if isstruct(metaCycMets.metMiriams{metCounter}) -0163 addToIndex=numel(metaCycMets.metMiriams{metCounter}.name)+1; -0164 else -0165 addToIndex=1; -0166 end -0167 tempStruct=metaCycMets.metMiriams{metCounter}; -0168 tempStruct.name{addToIndex,1}='SMILES'; -0169 tempStruct.value{addToIndex,1}=tline(10:end); -0170 metaCycMets.metMiriams{metCounter}=tempStruct; -0171 end -0172 -0173 %Add formula -0174 if numel(tline)>20 && strcmp(tline(1:20),'CHEMICAL-FORMULA - (') -0175 metaCycMets.metFormulas{metCounter}=strcat(metaCycMets.metFormulas{metCounter},tline(21:end-1)); -0176 metaCycMets.metFormulas{metCounter}(isspace(metaCycMets.metFormulas{metCounter})) = []; -0177 end -0178 -0179 %Add KEGG id -0180 if numel(tline)>23 && strcmp(tline(1:23),'DBLINKS - (LIGAND-CPD "') -0181 keggid=tline(24:end); -0182 -0183 s=strfind(keggid,'"'); -0184 if any(s) -0185 keggid=keggid(1:s-1); -0186 end +0159 %Add non-standard inchis +0160 if numel(tline)>27 && strcmp(tline(1:27),'NON-STANDARD-INCHI - InChI=') +0161 nonStandardInchis=tline(28:end); +0162 end +0163 +0164 %Add SMILES +0165 if numel(tline)>9 && strcmp(tline(1:9),'SMILES - ') +0166 +0167 if isstruct(metaCycMets.metMiriams{metCounter}) +0168 addToIndex=numel(metaCycMets.metMiriams{metCounter}.name)+1; +0169 else +0170 addToIndex=1; +0171 end +0172 tempStruct=metaCycMets.metMiriams{metCounter}; +0173 tempStruct.name{addToIndex,1}='SMILES'; +0174 tempStruct.value{addToIndex,1}=tline(10:end); +0175 metaCycMets.metMiriams{metCounter}=tempStruct; +0176 end +0177 +0178 %Add formula +0179 if numel(tline)>20 && strcmp(tline(1:20),'CHEMICAL-FORMULA - (') +0180 metaCycMets.metFormulas{metCounter}=strcat(metaCycMets.metFormulas{metCounter},tline(21:end-1)); +0181 metaCycMets.metFormulas{metCounter}(isspace(metaCycMets.metFormulas{metCounter})) = []; +0182 end +0183 +0184 %Add KEGG id +0185 if numel(tline)>23 && strcmp(tline(1:23),'DBLINKS - (LIGAND-CPD "') +0186 keggid=tline(24:end); 0187 -0188 metaCycMets.keggid{metCounter}=keggid; -0189 end -0190 -0191 %Add CHEBI id -0192 if numel(tline)>18 && strcmp(tline(1:18),'DBLINKS - (CHEBI "') -0193 chebiID=tline(20:end); %This is because there is sometimes more than one CHEBI index -0194 -0195 s=strfind(chebiID,'"'); -0196 if any(s) -0197 chebiID=chebiID(1:s-1); -0198 end +0188 s=strfind(keggid,'"'); +0189 if any(s) +0190 keggid=keggid(1:s-1); +0191 end +0192 +0193 metaCycMets.keggid{metCounter}=keggid; +0194 end +0195 +0196 %Add CHEBI id +0197 if numel(tline)>18 && strcmp(tline(1:18),'DBLINKS - (CHEBI "') +0198 chebiID=tline(20:end); %This is because there is sometimes more than one CHEBI index 0199 -0200 if isstruct(metaCycMets.metMiriams{metCounter}) -0201 addToIndex=numel(metaCycMets.metMiriams{metCounter}.name)+1; -0202 else -0203 addToIndex=1; -0204 end -0205 tempStruct=metaCycMets.metMiriams{metCounter}; -0206 tempStruct.name{addToIndex,1}='chebi'; -0207 tempStruct.value{addToIndex,1}=strcat('CHEBI:',chebiID); -0208 metaCycMets.metMiriams{metCounter}=tempStruct; -0209 end -0210 -0211 %Add PubChem -0212 if numel(tline)>20 && strcmp(tline(1:20),'DBLINKS - (PUBCHEM "') -0213 pubchemID=tline(21:end); -0214 -0215 s=strfind(pubchemID,'"'); -0216 if any(s) -0217 pubchemID=pubchemID(1:s-1); -0218 end +0200 s=strfind(chebiID,'"'); +0201 if any(s) +0202 chebiID=chebiID(1:s-1); +0203 end +0204 +0205 if isstruct(metaCycMets.metMiriams{metCounter}) +0206 addToIndex=numel(metaCycMets.metMiriams{metCounter}.name)+1; +0207 else +0208 addToIndex=1; +0209 end +0210 tempStruct=metaCycMets.metMiriams{metCounter}; +0211 tempStruct.name{addToIndex,1}='chebi'; +0212 tempStruct.value{addToIndex,1}=strcat('CHEBI:',chebiID); +0213 metaCycMets.metMiriams{metCounter}=tempStruct; +0214 end +0215 +0216 %Add PubChem +0217 if numel(tline)>20 && strcmp(tline(1:20),'DBLINKS - (PUBCHEM "') +0218 pubchemID=tline(21:end); 0219 -0220 if isstruct(metaCycMets.metMiriams{metCounter}) -0221 addToIndex=numel(metaCycMets.metMiriams{metCounter}.name)+1; -0222 else -0223 addToIndex=1; -0224 end -0225 tempStruct=metaCycMets.metMiriams{metCounter}; -0226 tempStruct.name{addToIndex,1}='pubchem.compound'; -0227 tempStruct.value{addToIndex,1}=pubchemID; -0228 metaCycMets.metMiriams{metCounter}=tempStruct; -0229 end -0230 -0231 %Add non-standard inchis when standard one is unavailable -0232 if strcmp(tline,'//') && strcmp(metaCycMets.inchis{metCounter},'') -0233 metaCycMets.inchis{metCounter}=nonStandardInchis; -0234 nonStandardInchis = ''; -0235 -0236 %Refine formula from inchis -0237 s=strfind(metaCycMets.inchis{metCounter},'/'); -0238 if any(s) -0239 inchiFormula=metaCycMets.inchis{metCounter}(s(1)+1:s(2)-1); -0240 -0241 %And remove dot characters -0242 inchiFormula(regexp(inchiFormula,'[.]'))=[]; -0243 if ~strcmp(metaCycMets.metFormulas{metCounter},inchiFormula) -0244 metaCycMets.metFormulas{metCounter}=inchiFormula; -0245 end -0246 end -0247 -0248 end -0249 -0250 end -0251 -0252 %Close the file -0253 fclose(fid); -0254 -0255 %If too much space was allocated, shrink the model -0256 metaCycMets.mets=metaCycMets.mets(1:metCounter); -0257 metaCycMets.metNames=metaCycMets.metNames(1:metCounter); -0258 metaCycMets.metFormulas=metaCycMets.metFormulas(1:metCounter); -0259 metaCycMets.metMiriams=metaCycMets.metMiriams(1:metCounter); -0260 metaCycMets.inchis=metaCycMets.inchis(1:metCounter); -0261 metaCycMets.metCharges=metaCycMets.metCharges(1:metCounter,:); -0262 %metaCycMets.smiles=metaCycMets.smiles(1:metCounter); -0263 %metaCycMets.pubchem=metaCycMets.pubchem(1:metCounter); -0264 metaCycMets.keggid=metaCycMets.keggid(1:metCounter); -0265 -0266 %If the metMiriams structure is empty, use MetaCyc id as metMiriams -0267 for i=1:numel(metaCycMets.mets) -0268 if ~isstruct(metaCycMets.metMiriams{i}) -0269 miriamStruct.name{1}='metacyc.compound'; -0270 miriamStruct.value{1}=metaCycMets.mets{i}; -0271 metaCycMets.metMiriams{i}=miriamStruct; -0272 end -0273 end -0274 -0275 %Saves the model -0276 save(metsFile,'metaCycMets'); -0277 fprintf(['New metaCycMets.mat has been successfully updated!\n\n']); -0278 end -0279 end -0280 end +0220 s=strfind(pubchemID,'"'); +0221 if any(s) +0222 pubchemID=pubchemID(1:s-1); +0223 end +0224 +0225 if isstruct(metaCycMets.metMiriams{metCounter}) +0226 addToIndex=numel(metaCycMets.metMiriams{metCounter}.name)+1; +0227 else +0228 addToIndex=1; +0229 end +0230 tempStruct=metaCycMets.metMiriams{metCounter}; +0231 tempStruct.name{addToIndex,1}='pubchem.compound'; +0232 tempStruct.value{addToIndex,1}=pubchemID; +0233 metaCycMets.metMiriams{metCounter}=tempStruct; +0234 end +0235 +0236 %Add non-standard inchis when standard one is unavailable +0237 if strcmp(tline,'//') && strcmp(metaCycMets.inchis{metCounter},'') +0238 metaCycMets.inchis{metCounter}=nonStandardInchis; +0239 nonStandardInchis = ''; +0240 +0241 %Refine formula from inchis +0242 s=strfind(metaCycMets.inchis{metCounter},'/'); +0243 if any(s) +0244 inchiFormula=metaCycMets.inchis{metCounter}(s(1)+1:s(2)-1); +0245 +0246 %And remove dot characters +0247 inchiFormula(regexp(inchiFormula,'[.]'))=[]; +0248 if ~strcmp(metaCycMets.metFormulas{metCounter},inchiFormula) +0249 metaCycMets.metFormulas{metCounter}=inchiFormula; +0250 end +0251 end +0252 +0253 end +0254 +0255 end +0256 +0257 %Close the file +0258 fclose(fid); +0259 +0260 %If too much space was allocated, shrink the model +0261 metaCycMets.mets=metaCycMets.mets(1:metCounter); +0262 metaCycMets.metNames=metaCycMets.metNames(1:metCounter); +0263 metaCycMets.metFormulas=metaCycMets.metFormulas(1:metCounter); +0264 metaCycMets.metMiriams=metaCycMets.metMiriams(1:metCounter); +0265 metaCycMets.inchis=metaCycMets.inchis(1:metCounter); +0266 metaCycMets.metCharges=metaCycMets.metCharges(1:metCounter,:); +0267 %metaCycMets.smiles=metaCycMets.smiles(1:metCounter); +0268 %metaCycMets.pubchem=metaCycMets.pubchem(1:metCounter); +0269 metaCycMets.keggid=metaCycMets.keggid(1:metCounter); +0270 +0271 %If the metMiriams structure is empty, use MetaCyc id as metMiriams +0272 for i=1:numel(metaCycMets.mets) +0273 if ~isstruct(metaCycMets.metMiriams{i}) +0274 miriamStruct.name{1}='metacyc.compound'; +0275 miriamStruct.value{1}=metaCycMets.mets{i}; +0276 metaCycMets.metMiriams{i}=miriamStruct; +0277 end +0278 end +0279 +0280 %Saves the model +0281 save(metsFile,'metaCycMets'); +0282 fprintf(['New metaCycMets.mat has been successfully updated!\n\n']); +0283 end +0284 end +0285 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/metacyc/getModelFromMetaCyc.html b/doc/external/metacyc/getModelFromMetaCyc.html index b7b65e29..93f99558 100644 --- a/doc/external/metacyc/getModelFromMetaCyc.html +++ b/doc/external/metacyc/getModelFromMetaCyc.html @@ -110,149 +110,152 @@

    SOURCE CODE ^% Usage: getModelFromMetaCyc(metacycPath,keepTransportRxns,keepUnbalanced,keepUndetermined) 0035 0036 if nargin<1 -0037 metacycPath=''; -0038 end -0039 if nargin<2 -0040 keepTransportRxns=false; +0037 ravenPath=findRAVENroot(); +0038 metacycPath=fullfile(ravenPath,'external','metacyc'); +0039 else +0040 metacycPath=char(metacycPath); 0041 end -0042 if nargin<3 -0043 keepUnbalanced=false; +0042 if nargin<2 +0043 keepTransportRxns=false; 0044 end -0045 if nargin<4 -0046 keepUndetermined=false; +0045 if nargin<3 +0046 keepUnbalanced=false; 0047 end -0048 -0049 %First get all reactions -0050 metaCycModel=getRxnsFromMetaCyc(metacycPath,keepTransportRxns,keepUnbalanced,keepUndetermined); +0048 if nargin<4 +0049 keepUndetermined=false; +0050 end 0051 -0052 %Get reaction and enzyme association -0053 metaCycEnzymes=getEnzymesFromMetaCyc(metacycPath); +0052 %First get all reactions +0053 metaCycModel=getRxnsFromMetaCyc(metacycPath,keepTransportRxns,keepUnbalanced,keepUndetermined); 0054 -0055 %Replace rxnNames with those from metaCycEnzymes -0056 [a, b]=ismember(metaCycModel.rxns,metaCycEnzymes.rxns); -0057 a=find(a); -0058 b=b(a); -0059 metaCycModel.rxnNames(a)=metaCycEnzymes.rxnNames(b); -0060 -0061 fprintf('Reorganizing reaction-enzyme associations... ') -0062 %Create the rxnGeneMat for the reactions, by geting all enzymes and -0063 %corresponding subunits -0064 rxnNum=numel(metaCycModel.rxns); -0065 metaCycModel.genes=metaCycEnzymes.enzymes; -0066 metaCycModel.rxnGeneMat=sparse(rxnNum,numel(metaCycEnzymes.enzymes)); -0067 metaCycModel.grRules=cell(rxnNum,1); -0068 -0069 %Loop through all reactions to generate rxnGeneMat matrix and grRules This -0070 %step also cross-link reactions to their catalyzing enzymes -0071 for i=1:rxnNum -0072 -0073 metaCycModel.grRules{i}=''; -0074 %Find out if this is an enzymatic reaction -0075 [a, b]=ismember(metaCycModel.rxns(i),metaCycEnzymes.rxns); -0076 if a -0077 I=[]; %Find out all catalyzing enzymes, which are treated as isoenzymes -0078 I=find(metaCycEnzymes.rxnEnzymeMat(b,:)); -0079 if ~isempty(I) -0080 -0081 grRule=''; -0082 for j=1:numel(I) -0083 -0084 subgrRule=''; %Find out if enzyme complex -0085 [c, d]=ismember(metaCycEnzymes.enzymes(I(j)),metaCycEnzymes.cplxs); -0086 if c %In cases of an enzyme complex -0087 %With single subunit -0088 if numel(metaCycEnzymes.cplxComp{d}.subunit)==1 -0089 subgrRule=metaCycEnzymes.cplxComp{d}.subunit{1}; -0090 %With multiple subunits -0091 else -0092 subgrRule=strjoin(metaCycEnzymes.cplxComp{d}.subunit,' and '); -0093 subgrRule=strcat('(',subgrRule,')'); -0094 end -0095 [x, geneIndex]=ismember(metaCycEnzymes.cplxComp{d}.subunit,metaCycModel.genes); -0096 metaCycModel.rxnGeneMat(i,geneIndex)=1; -0097 -0098 else %In cases of NOT an enzyme complex -0099 subgrRule=metaCycEnzymes.enzymes(I(j)); -0100 metaCycModel.rxnGeneMat(i,I(j))=1; -0101 end -0102 -0103 %Generating grRules -0104 if ~strcmp(subgrRule,'') -0105 if ~strcmp(grRule,'') -0106 grRule=strcat(grRule,{' or '},subgrRule); -0107 else -0108 grRule=subgrRule; -0109 end -0110 end -0111 -0112 end -0113 if iscell(grRule) -0114 metaCycModel.grRules{i}=grRule{1}; -0115 else -0116 metaCycModel.grRules{i}=grRule; -0117 end -0118 -0119 end -0120 -0121 end -0122 end -0123 fprintf('done\n') -0124 %Then get all metabolites -0125 metaCycMets=getMetsFromMetaCyc(metacycPath); -0126 -0127 %Add information about all metabolites to the model -0128 [a, b]=ismember(metaCycModel.mets,metaCycMets.mets); -0129 a=find(a); -0130 b=b(a); -0131 -0132 if ~isfield(metaCycModel,'metNames') -0133 metaCycModel.metNames=cell(numel(metaCycModel.mets),1); -0134 metaCycModel.metNames(:)={''}; -0135 end -0136 metaCycModel.metNames(a)=metaCycMets.metNames(b); -0137 -0138 if ~isfield(metaCycModel,'metFormulas') -0139 metaCycModel.metFormulas=cell(numel(metaCycModel.mets),1); -0140 metaCycModel.metFormulas(:)={''}; -0141 end -0142 metaCycModel.metFormulas(a)=metaCycMets.metFormulas(b); -0143 -0144 if ~isfield(metaCycModel,'metCharges') -0145 metaCycModel.metCharges=zeros(numel(metaCycModel.mets),1); -0146 end -0147 metaCycModel.metCharges(a)=metaCycMets.metCharges(b); -0148 -0149 if ~isfield(metaCycModel,'inchis') -0150 metaCycModel.inchis=cell(numel(metaCycModel.mets),1); -0151 metaCycModel.inchis(:)={''}; -0152 end -0153 metaCycModel.inchis(a)=metaCycMets.inchis(b); -0154 -0155 if ~isfield(metaCycModel,'metMiriams') -0156 metaCycModel.metMiriams=cell(numel(metaCycModel.mets),1); -0157 end -0158 metaCycModel.metMiriams(a)=metaCycMets.metMiriams(b); -0159 -0160 if ~isfield(metaCycModel,'keggid') -0161 metaCycModel.keggid=cell(numel(metaCycModel.mets),1); -0162 end -0163 metaCycModel.keggid(a)=metaCycMets.keggid(b); -0164 -0165 %Put all metabolites in one compartment called 's' (for system). This is -0166 %done just to be more compatible with the rest of the code -0167 metaCycModel.comps={'s'}; -0168 metaCycModel.compNames={'System'}; -0169 metaCycModel.metComps=ones(numel(metaCycModel.mets),1); -0170 -0171 -0172 %It could also be that the metabolite and reaction names are empty for some -0173 %reasons. In that case, use the ID instead -0174 I=cellfun(@isempty,metaCycModel.metNames); -0175 metaCycModel.metNames(I)=metaCycModel.mets(I); -0176 I=cellfun(@isempty,metaCycModel.rxnNames); -0177 metaCycModel.rxnNames(I)=metaCycModel.rxns(I); -0178 -0179 end +0055 %Get reaction and enzyme association +0056 metaCycEnzymes=getEnzymesFromMetaCyc(metacycPath); +0057 +0058 %Replace rxnNames with those from metaCycEnzymes +0059 [a, b]=ismember(metaCycModel.rxns,metaCycEnzymes.rxns); +0060 a=find(a); +0061 b=b(a); +0062 metaCycModel.rxnNames(a)=metaCycEnzymes.rxnNames(b); +0063 +0064 fprintf('Reorganizing reaction-enzyme associations... ') +0065 %Create the rxnGeneMat for the reactions, by geting all enzymes and +0066 %corresponding subunits +0067 rxnNum=numel(metaCycModel.rxns); +0068 metaCycModel.genes=metaCycEnzymes.enzymes; +0069 metaCycModel.rxnGeneMat=sparse(rxnNum,numel(metaCycEnzymes.enzymes)); +0070 metaCycModel.grRules=cell(rxnNum,1); +0071 +0072 %Loop through all reactions to generate rxnGeneMat matrix and grRules This +0073 %step also cross-link reactions to their catalyzing enzymes +0074 for i=1:rxnNum +0075 +0076 metaCycModel.grRules{i}=''; +0077 %Find out if this is an enzymatic reaction +0078 [a, b]=ismember(metaCycModel.rxns(i),metaCycEnzymes.rxns); +0079 if a +0080 I=[]; %Find out all catalyzing enzymes, which are treated as isoenzymes +0081 I=find(metaCycEnzymes.rxnEnzymeMat(b,:)); +0082 if ~isempty(I) +0083 +0084 grRule=''; +0085 for j=1:numel(I) +0086 +0087 subgrRule=''; %Find out if enzyme complex +0088 [c, d]=ismember(metaCycEnzymes.enzymes(I(j)),metaCycEnzymes.cplxs); +0089 if c %In cases of an enzyme complex +0090 %With single subunit +0091 if numel(metaCycEnzymes.cplxComp{d}.subunit)==1 +0092 subgrRule=metaCycEnzymes.cplxComp{d}.subunit{1}; +0093 %With multiple subunits +0094 else +0095 subgrRule=strjoin(metaCycEnzymes.cplxComp{d}.subunit,' and '); +0096 subgrRule=strcat('(',subgrRule,')'); +0097 end +0098 [x, geneIndex]=ismember(metaCycEnzymes.cplxComp{d}.subunit,metaCycModel.genes); +0099 metaCycModel.rxnGeneMat(i,geneIndex)=1; +0100 +0101 else %In cases of NOT an enzyme complex +0102 subgrRule=metaCycEnzymes.enzymes(I(j)); +0103 metaCycModel.rxnGeneMat(i,I(j))=1; +0104 end +0105 +0106 %Generating grRules +0107 if ~strcmp(subgrRule,'') +0108 if ~strcmp(grRule,'') +0109 grRule=strcat(grRule,{' or '},subgrRule); +0110 else +0111 grRule=subgrRule; +0112 end +0113 end +0114 +0115 end +0116 if iscell(grRule) +0117 metaCycModel.grRules{i}=grRule{1}; +0118 else +0119 metaCycModel.grRules{i}=grRule; +0120 end +0121 +0122 end +0123 +0124 end +0125 end +0126 fprintf('done\n') +0127 %Then get all metabolites +0128 metaCycMets=getMetsFromMetaCyc(metacycPath); +0129 +0130 %Add information about all metabolites to the model +0131 [a, b]=ismember(metaCycModel.mets,metaCycMets.mets); +0132 a=find(a); +0133 b=b(a); +0134 +0135 if ~isfield(metaCycModel,'metNames') +0136 metaCycModel.metNames=cell(numel(metaCycModel.mets),1); +0137 metaCycModel.metNames(:)={''}; +0138 end +0139 metaCycModel.metNames(a)=metaCycMets.metNames(b); +0140 +0141 if ~isfield(metaCycModel,'metFormulas') +0142 metaCycModel.metFormulas=cell(numel(metaCycModel.mets),1); +0143 metaCycModel.metFormulas(:)={''}; +0144 end +0145 metaCycModel.metFormulas(a)=metaCycMets.metFormulas(b); +0146 +0147 if ~isfield(metaCycModel,'metCharges') +0148 metaCycModel.metCharges=zeros(numel(metaCycModel.mets),1); +0149 end +0150 metaCycModel.metCharges(a)=metaCycMets.metCharges(b); +0151 +0152 if ~isfield(metaCycModel,'inchis') +0153 metaCycModel.inchis=cell(numel(metaCycModel.mets),1); +0154 metaCycModel.inchis(:)={''}; +0155 end +0156 metaCycModel.inchis(a)=metaCycMets.inchis(b); +0157 +0158 if ~isfield(metaCycModel,'metMiriams') +0159 metaCycModel.metMiriams=cell(numel(metaCycModel.mets),1); +0160 end +0161 metaCycModel.metMiriams(a)=metaCycMets.metMiriams(b); +0162 +0163 if ~isfield(metaCycModel,'keggid') +0164 metaCycModel.keggid=cell(numel(metaCycModel.mets),1); +0165 end +0166 metaCycModel.keggid(a)=metaCycMets.keggid(b); +0167 +0168 %Put all metabolites in one compartment called 's' (for system). This is +0169 %done just to be more compatible with the rest of the code +0170 metaCycModel.comps={'s'}; +0171 metaCycModel.compNames={'System'}; +0172 metaCycModel.metComps=ones(numel(metaCycModel.mets),1); +0173 +0174 +0175 %It could also be that the metabolite and reaction names are empty for some +0176 %reasons. In that case, use the ID instead +0177 I=cellfun(@isempty,metaCycModel.metNames); +0178 metaCycModel.metNames(I)=metaCycModel.mets(I); +0179 I=cellfun(@isempty,metaCycModel.rxnNames); +0180 metaCycModel.rxnNames(I)=metaCycModel.rxns(I); +0181 +0182 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/metacyc/getRxnsFromMetaCyc.html b/doc/external/metacyc/getRxnsFromMetaCyc.html index 9376281a..8234ed88 100644 --- a/doc/external/metacyc/getRxnsFromMetaCyc.html +++ b/doc/external/metacyc/getRxnsFromMetaCyc.html @@ -160,467 +160,470 @@

    SOURCE CODE ^% // 0069 0070 % A line that contains only '//' separates each object. -0071 -0072 if nargin<2 -0073 keepTransportRxns=false; -0074 end -0075 if nargin<3 -0076 keepUnbalanced=false; -0077 end -0078 if nargin<4 -0079 keepUndetermined=false; -0080 end -0081 -0082 %Check if the reactions have been parsed before and saved. Directly load -0083 %the model if so. -0084 [ST, I]=dbstack('-completenames'); -0085 ravenPath=fileparts(fileparts(fileparts(ST(I).file))); -0086 rxnsFile=fullfile(ravenPath,'external','metacyc','metaCycRxns.mat'); -0087 metaCycRxnFile='reactions.dat'; -0088 metaCycPwyFile='pathway-links.dat'; -0089 -0090 if exist(rxnsFile, 'file') -0091 fprintf(['Importing MetaCyc reactions from ' strrep(rxnsFile,'\','/') '... ']); -0092 load(rxnsFile); -0093 fprintf('done\n'); -0094 else -0095 fprintf(['Cannot locate ' strrep(rxnsFile,'\','/') '\nNow try to generate it from local MetaCyc data files...\n']); -0096 if ~exist(fullfile(metacycPath,metaCycRxnFile),'file') || ~exist(fullfile(metacycPath,metaCycPwyFile),'file') -0097 EM=fprintf(['The files of reactions or pathways cannot be located, and should be downloaded from MetaCyc.\n']); -0098 dispEM(EM); -0099 else -0100 metaCycRxns.id='MetaCyc'; -0101 metaCycRxns.name='Automatically generated from MetaCyc database'; -0102 -0103 %Get pathway names and add them to the field of subSystems -0104 fid = fopen(fullfile(metacycPath,metaCycPwyFile), 'r'); +0071 if nargin<1 +0072 ravenPath=findRAVENroot(); +0073 metacycPath=fullfile(ravenPath,'external','metacyc'); +0074 else +0075 metacycPath=char(metacycPath); +0076 end +0077 if nargin<2 +0078 keepTransportRxns=false; +0079 end +0080 if nargin<3 +0081 keepUnbalanced=false; +0082 end +0083 if nargin<4 +0084 keepUndetermined=false; +0085 end +0086 +0087 %Check if the reactions have been parsed before and saved. Directly load +0088 %the model if so. +0089 rxnsFile=fullfile(metacycPath,'metaCycRxns.mat'); +0090 metaCycRxnFile='reactions.dat'; +0091 metaCycPwyFile='pathway-links.dat'; +0092 +0093 if exist(rxnsFile, 'file') +0094 fprintf(['Importing MetaCyc reactions from ' strrep(rxnsFile,'\','/') '... ']); +0095 load(rxnsFile); +0096 fprintf('done\n'); +0097 else +0098 fprintf(['Cannot locate ' strrep(rxnsFile,'\','/') '\nNow try to generate it from local MetaCyc data files...\n']); +0099 if ~exist(fullfile(metacycPath,metaCycRxnFile),'file') || ~exist(fullfile(metacycPath,metaCycPwyFile),'file') +0100 EM=fprintf(['The files of reactions or pathways cannot be located, and should be downloaded from MetaCyc.\n']); +0101 dispEM(EM); +0102 else +0103 metaCycRxns.id='MetaCyc'; +0104 metaCycRxns.name='Automatically generated from MetaCyc database'; 0105 -0106 %Keeps track of how many pathways that have been added -0107 pwyCounter=0; -0108 pwys=cell(10000,1); -0109 pwyNames=cell(10000,1); -0110 -0111 %Loop through the file -0112 while 1 -0113 %Get the next line -0114 tline = fgetl(fid); -0115 -0116 %Abort at end of file -0117 if ~ischar(tline) -0118 break; -0119 end -0120 -0121 %Read in pathway ids and names -0122 if ~strcmp(tline(1),'#') -0123 pwyCounter=pwyCounter+1; -0124 vars = regexp(tline, '\t', 'split'); -0125 pwys{pwyCounter}=vars{1}; -0126 pwyNames{pwyCounter}=vars{2}; -0127 -0128 %Romve HTML symbols -0129 pwyNames{pwyCounter}=removeHTMLcodes(pwyNames{pwyCounter}); +0106 %Get pathway names and add them to the field of subSystems +0107 fid = fopen(fullfile(metacycPath,metaCycPwyFile), 'r'); +0108 +0109 %Keeps track of how many pathways that have been added +0110 pwyCounter=0; +0111 pwys=cell(10000,1); +0112 pwyNames=cell(10000,1); +0113 +0114 %Loop through the file +0115 while 1 +0116 %Get the next line +0117 tline = fgetl(fid); +0118 +0119 %Abort at end of file +0120 if ~ischar(tline) +0121 break; +0122 end +0123 +0124 %Read in pathway ids and names +0125 if ~strcmp(tline(1),'#') +0126 pwyCounter=pwyCounter+1; +0127 vars = regexp(tline, '\t', 'split'); +0128 pwys{pwyCounter}=vars{1}; +0129 pwyNames{pwyCounter}=vars{2}; 0130 -0131 end -0132 end -0133 fclose(fid); -0134 pwys=pwys(1:pwyCounter); -0135 pwyNames=pwyNames(1:pwyCounter); -0136 -0137 %Preallocate memory for 50000 reactions -0138 metaCycRxns.rxns=cell(50000,1); -0139 metaCycRxns.rxnNames=cell(50000,1); -0140 metaCycRxns.eccodes=cell(50000,1); -0141 metaCycRxns.subSystems=cell(50000,1); -0142 metaCycRxns.pwys=cell(50000,1); -0143 metaCycRxns.rxnMiriams=cell(50000,1); -0144 metaCycRxns.rxnReferences=cell(50000,1); -0145 metaCycRxns.rev=ones(50000,1); %reversibility; -0146 -0147 rxnLinks.metacyc=cell(10000,1); -0148 rxnLinks.kegg=cell(10000,1); -0149 rxnLinks.check=cell(10000,1); -0150 isSpontaneous=false(10000,1); %spontaneous; -0151 UNBALANCED=false(10000,1); -0152 UNDETERMINED=false(10000,1); -0153 TRANSPORT={}; %transport reactions; -0154 -0155 metaCycRxns.equations=cell(50000,1); %reaction equations -0156 left=cell(50000,1); %Temporarily stores the equations -0157 right=cell(50000,1); %Temporarily stores the equations -0158 -0159 %First load information on reaction ID, reaction name,, pathway, -0160 %and ec-number -0161 fid = fopen(fullfile(metacycPath,metaCycRxnFile), 'r'); -0162 -0163 %Keeps track of how many reactions that have been added -0164 rxnCounter=0; -0165 addSpont=false; -0166 dbLinkCounter=0; -0167 -0168 %Loop through the file -0169 while 1 -0170 %Get the next line -0171 tline = fgetl(fid); -0172 -0173 %Abort at end of file -0174 if ~ischar(tline) -0175 break; -0176 end -0177 -0178 % Get the version of MetaCyc database -0179 if numel(tline)>11 && strcmp(tline(1:11),'# Version: ') -0180 version=tline(12:end); -0181 end -0182 -0183 %Check if it is a new reaction -0184 if numel(tline)>12 && strcmp(tline(1:12),'UNIQUE-ID - ') -0185 rxnCounter=rxnCounter+1; -0186 nPwys=0; -0187 -0188 %Add empty strings where there should be such -0189 metaCycRxns.rxnNames{rxnCounter}=''; -0190 metaCycRxns.eccodes{rxnCounter}=''; -0191 metaCycRxns.subSystems{rxnCounter}=''; -0192 metaCycRxns.pwys{rxnCounter}=''; -0193 metaCycRxns.equations{rxnCounter}=''; -0194 metaCycRxns.rxnReferences{rxnCounter}=''; -0195 reverse=0; %Value for reversing the equation when necessary -0196 -0197 % A complex evaluation system for generating the equations -0198 left{rxnCounter}=''; -0199 right{rxnCounter}=''; -0200 coefficient=''; -0201 templeft=''; -0202 tempright=''; -0203 % might be simplified with a better algorithem -0204 -0205 %Add reaction ID -0206 metaCycRxns.rxns{rxnCounter}=tline(13:end); +0131 %Romve HTML symbols +0132 pwyNames{pwyCounter}=removeHTMLcodes(pwyNames{pwyCounter}); +0133 +0134 end +0135 end +0136 fclose(fid); +0137 pwys=pwys(1:pwyCounter); +0138 pwyNames=pwyNames(1:pwyCounter); +0139 +0140 %Preallocate memory for 50000 reactions +0141 metaCycRxns.rxns=cell(50000,1); +0142 metaCycRxns.rxnNames=cell(50000,1); +0143 metaCycRxns.eccodes=cell(50000,1); +0144 metaCycRxns.subSystems=cell(50000,1); +0145 metaCycRxns.pwys=cell(50000,1); +0146 metaCycRxns.rxnMiriams=cell(50000,1); +0147 metaCycRxns.rxnReferences=cell(50000,1); +0148 metaCycRxns.rev=ones(50000,1); %reversibility; +0149 +0150 rxnLinks.metacyc=cell(10000,1); +0151 rxnLinks.kegg=cell(10000,1); +0152 rxnLinks.check=cell(10000,1); +0153 isSpontaneous=false(10000,1); %spontaneous; +0154 UNBALANCED=false(10000,1); +0155 UNDETERMINED=false(10000,1); +0156 TRANSPORT={}; %transport reactions; +0157 +0158 metaCycRxns.equations=cell(50000,1); %reaction equations +0159 left=cell(50000,1); %Temporarily stores the equations +0160 right=cell(50000,1); %Temporarily stores the equations +0161 +0162 %First load information on reaction ID, reaction name,, pathway, +0163 %and ec-number +0164 fid = fopen(fullfile(metacycPath,metaCycRxnFile), 'r'); +0165 +0166 %Keeps track of how many reactions that have been added +0167 rxnCounter=0; +0168 addSpont=false; +0169 dbLinkCounter=0; +0170 +0171 %Loop through the file +0172 while 1 +0173 %Get the next line +0174 tline = fgetl(fid); +0175 +0176 %Abort at end of file +0177 if ~ischar(tline) +0178 break; +0179 end +0180 +0181 % Get the version of MetaCyc database +0182 if numel(tline)>11 && strcmp(tline(1:11),'# Version: ') +0183 version=tline(12:end); +0184 end +0185 +0186 %Check if it is a new reaction +0187 if numel(tline)>12 && strcmp(tline(1:12),'UNIQUE-ID - ') +0188 rxnCounter=rxnCounter+1; +0189 nPwys=0; +0190 +0191 %Add empty strings where there should be such +0192 metaCycRxns.rxnNames{rxnCounter}=''; +0193 metaCycRxns.eccodes{rxnCounter}=''; +0194 metaCycRxns.subSystems{rxnCounter}=''; +0195 metaCycRxns.pwys{rxnCounter}=''; +0196 metaCycRxns.equations{rxnCounter}=''; +0197 metaCycRxns.rxnReferences{rxnCounter}=''; +0198 reverse=0; %Value for reversing the equation when necessary +0199 +0200 % A complex evaluation system for generating the equations +0201 left{rxnCounter}=''; +0202 right{rxnCounter}=''; +0203 coefficient=''; +0204 templeft=''; +0205 tempright=''; +0206 % might be simplified with a better algorithem 0207 -0208 end -0209 -0210 %Add name -0211 if numel(tline)>14 && strcmp(tline(1:14),'COMMON-NAME - ') -0212 metaCycRxns.rxnNames{rxnCounter}=tline(15:end); -0213 -0214 %Romve HTML symbols -0215 metaCycRxns.rxnNames{rxnCounter}=removeHTMLcodes(metaCycRxns.rxnNames{rxnCounter}); -0216 end -0217 -0218 %Add eccodes -0219 if numel(tline)>15 && strcmp(tline(1:15),'EC-NUMBER - EC-') -0220 if isempty(metaCycRxns.eccodes{rxnCounter}) -0221 metaCycRxns.eccodes{rxnCounter}=strcat('ec-code/',tline(16:end)); -0222 else -0223 metaCycRxns.eccodes{rxnCounter}=strcat(metaCycRxns.eccodes{rxnCounter},';ec-code/',tline(16:end)); -0224 end -0225 end -0226 if numel(tline)>16 && strcmp(tline(1:16),'EC-NUMBER - |EC-') -0227 if isempty(metaCycRxns.eccodes{rxnCounter}) -0228 metaCycRxns.eccodes{rxnCounter}=strcat('ec-code/',tline(17:end-1)); -0229 else -0230 metaCycRxns.eccodes{rxnCounter}=strcat(metaCycRxns.eccodes{rxnCounter},';ec-code/',tline(17:end-1)); -0231 end -0232 end -0233 -0234 %Add pathway id and assign pathway name to subSystem field -0235 if numel(tline)>13 && strcmp(tline(1:13),'IN-PATHWAY - ') -0236 if isempty(metaCycRxns.pwys{rxnCounter}) -0237 metaCycRxns.pwys{rxnCounter}=tline(14:end); -0238 else -0239 metaCycRxns.pwys{rxnCounter}=strcat(metaCycRxns.pwys{rxnCounter},';',tline(14:end)); -0240 end -0241 -0242 [x, y]=ismember(tline(14:end),pwys); -0243 if x -0244 metaCycRxns.subSystems{rxnCounter,1}{1,numel(metaCycRxns.subSystems{rxnCounter,1})+1}=pwyNames{y}; -0245 end -0246 end -0247 -0248 %Add references (pubmed ids) -0249 if numel(tline)>12 && strcmp(tline(1:12),'CITATIONS - ') -0250 if isempty(metaCycRxns.rxnReferences{rxnCounter}) -0251 metaCycRxns.rxnReferences{rxnCounter}=strcat('pubmed/',tline(13:end)); -0252 else -0253 metaCycRxns.rxnReferences{rxnCounter}=strcat(metaCycRxns.rxnReferences{rxnCounter},';pubmed/',tline(13:end)); -0254 end -0255 end -0256 -0257 %Add Miriam info (cross-links other database) -0258 if numel(tline)>11 && strcmp(tline(1:11),'DBLINKS - (') -0259 dblink=tline(12:end); -0260 %KEGG reaction id -0261 if strcmp(dblink(1:12),'LIGAND-RXN "') -0262 dblink=dblink(13:end); -0263 s=strfind(dblink,'"'); -0264 if any(s) -0265 dblink=dblink(1:s-1); -0266 end -0267 -0268 if isstruct(metaCycRxns.rxnMiriams{rxnCounter}) -0269 addToIndex=numel(metaCycRxns.rxnMiriams{rxnCounter}.name)+1; -0270 else -0271 addToIndex=1; -0272 end -0273 tempStruct=metaCycRxns.rxnMiriams{rxnCounter}; -0274 tempStruct.name{addToIndex,1}='kegg.reaction'; -0275 tempStruct.value{addToIndex,1}=dblink; -0276 metaCycRxns.rxnMiriams{rxnCounter}=tempStruct; -0277 -0278 %For generating the rxnLinks structure -0279 dbLinkCounter=dbLinkCounter+1; -0280 rxnLinks.metacyc{dbLinkCounter}=metaCycRxns.rxns{rxnCounter}; -0281 rxnLinks.kegg{dbLinkCounter}=dblink; -0282 rxnLinks.check{dbLinkCounter}=strcat(metaCycRxns.rxns{rxnCounter},dblink); -0283 end -0284 -0285 %RHEA reaction id -0286 if strcmp(dblink(1:6),'RHEA "') -0287 dblink=dblink(7:end); -0288 s=strfind(dblink,'"'); -0289 if any(s) -0290 dblink=dblink(1:s-1); -0291 end -0292 -0293 if isstruct(metaCycRxns.rxnMiriams{rxnCounter}) -0294 addToIndex=numel(metaCycRxns.rxnMiriams{rxnCounter}.name)+1; -0295 else -0296 addToIndex=1; -0297 end -0298 tempStruct=metaCycRxns.rxnMiriams{rxnCounter}; -0299 tempStruct.name{addToIndex,1}='rhea'; -0300 tempStruct.value{addToIndex,1}=dblink; -0301 metaCycRxns.rxnMiriams{rxnCounter}=tempStruct; -0302 end -0303 end -0304 -0305 if numel(tline)>21 && strcmp(tline(1:21),'REACTION-DIRECTION - ') -0306 rxnDirection=tline(22:end); -0307 switch(rxnDirection) -0308 case 'IRREVERSIBLE-LEFT-TO-RIGHT' -0309 metaCycRxns.rev(rxnCounter,1)=0; -0310 case 'LEFT-TO-RIGHT' -0311 metaCycRxns.rev(rxnCounter,1)=0; -0312 case 'PHYSIOL-LEFT-TO-RIGHT' -0313 metaCycRxns.rev(rxnCounter,1)=0; -0314 case 'IRREVERSIBLE-RIGHT-TO-LEFT' -0315 metaCycRxns.rev(rxnCounter,1)=0; -0316 reverse=1; -0317 case 'RIGHT-TO-LEFT' +0208 %Add reaction ID +0209 metaCycRxns.rxns{rxnCounter}=tline(13:end); +0210 +0211 end +0212 +0213 %Add name +0214 if numel(tline)>14 && strcmp(tline(1:14),'COMMON-NAME - ') +0215 metaCycRxns.rxnNames{rxnCounter}=tline(15:end); +0216 +0217 %Romve HTML symbols +0218 metaCycRxns.rxnNames{rxnCounter}=removeHTMLcodes(metaCycRxns.rxnNames{rxnCounter}); +0219 end +0220 +0221 %Add eccodes +0222 if numel(tline)>15 && strcmp(tline(1:15),'EC-NUMBER - EC-') +0223 if isempty(metaCycRxns.eccodes{rxnCounter}) +0224 metaCycRxns.eccodes{rxnCounter}=strcat('ec-code/',tline(16:end)); +0225 else +0226 metaCycRxns.eccodes{rxnCounter}=strcat(metaCycRxns.eccodes{rxnCounter},';ec-code/',tline(16:end)); +0227 end +0228 end +0229 if numel(tline)>16 && strcmp(tline(1:16),'EC-NUMBER - |EC-') +0230 if isempty(metaCycRxns.eccodes{rxnCounter}) +0231 metaCycRxns.eccodes{rxnCounter}=strcat('ec-code/',tline(17:end-1)); +0232 else +0233 metaCycRxns.eccodes{rxnCounter}=strcat(metaCycRxns.eccodes{rxnCounter},';ec-code/',tline(17:end-1)); +0234 end +0235 end +0236 +0237 %Add pathway id and assign pathway name to subSystem field +0238 if numel(tline)>13 && strcmp(tline(1:13),'IN-PATHWAY - ') +0239 if isempty(metaCycRxns.pwys{rxnCounter}) +0240 metaCycRxns.pwys{rxnCounter}=tline(14:end); +0241 else +0242 metaCycRxns.pwys{rxnCounter}=strcat(metaCycRxns.pwys{rxnCounter},';',tline(14:end)); +0243 end +0244 +0245 [x, y]=ismember(tline(14:end),pwys); +0246 if x +0247 metaCycRxns.subSystems{rxnCounter,1}{1,numel(metaCycRxns.subSystems{rxnCounter,1})+1}=pwyNames{y}; +0248 end +0249 end +0250 +0251 %Add references (pubmed ids) +0252 if numel(tline)>12 && strcmp(tline(1:12),'CITATIONS - ') +0253 if isempty(metaCycRxns.rxnReferences{rxnCounter}) +0254 metaCycRxns.rxnReferences{rxnCounter}=strcat('pubmed/',tline(13:end)); +0255 else +0256 metaCycRxns.rxnReferences{rxnCounter}=strcat(metaCycRxns.rxnReferences{rxnCounter},';pubmed/',tline(13:end)); +0257 end +0258 end +0259 +0260 %Add Miriam info (cross-links other database) +0261 if numel(tline)>11 && strcmp(tline(1:11),'DBLINKS - (') +0262 dblink=tline(12:end); +0263 %KEGG reaction id +0264 if strcmp(dblink(1:12),'LIGAND-RXN "') +0265 dblink=dblink(13:end); +0266 s=strfind(dblink,'"'); +0267 if any(s) +0268 dblink=dblink(1:s-1); +0269 end +0270 +0271 if isstruct(metaCycRxns.rxnMiriams{rxnCounter}) +0272 addToIndex=numel(metaCycRxns.rxnMiriams{rxnCounter}.name)+1; +0273 else +0274 addToIndex=1; +0275 end +0276 tempStruct=metaCycRxns.rxnMiriams{rxnCounter}; +0277 tempStruct.name{addToIndex,1}='kegg.reaction'; +0278 tempStruct.value{addToIndex,1}=dblink; +0279 metaCycRxns.rxnMiriams{rxnCounter}=tempStruct; +0280 +0281 %For generating the rxnLinks structure +0282 dbLinkCounter=dbLinkCounter+1; +0283 rxnLinks.metacyc{dbLinkCounter}=metaCycRxns.rxns{rxnCounter}; +0284 rxnLinks.kegg{dbLinkCounter}=dblink; +0285 rxnLinks.check{dbLinkCounter}=strcat(metaCycRxns.rxns{rxnCounter},dblink); +0286 end +0287 +0288 %RHEA reaction id +0289 if strcmp(dblink(1:6),'RHEA "') +0290 dblink=dblink(7:end); +0291 s=strfind(dblink,'"'); +0292 if any(s) +0293 dblink=dblink(1:s-1); +0294 end +0295 +0296 if isstruct(metaCycRxns.rxnMiriams{rxnCounter}) +0297 addToIndex=numel(metaCycRxns.rxnMiriams{rxnCounter}.name)+1; +0298 else +0299 addToIndex=1; +0300 end +0301 tempStruct=metaCycRxns.rxnMiriams{rxnCounter}; +0302 tempStruct.name{addToIndex,1}='rhea'; +0303 tempStruct.value{addToIndex,1}=dblink; +0304 metaCycRxns.rxnMiriams{rxnCounter}=tempStruct; +0305 end +0306 end +0307 +0308 if numel(tline)>21 && strcmp(tline(1:21),'REACTION-DIRECTION - ') +0309 rxnDirection=tline(22:end); +0310 switch(rxnDirection) +0311 case 'IRREVERSIBLE-LEFT-TO-RIGHT' +0312 metaCycRxns.rev(rxnCounter,1)=0; +0313 case 'LEFT-TO-RIGHT' +0314 metaCycRxns.rev(rxnCounter,1)=0; +0315 case 'PHYSIOL-LEFT-TO-RIGHT' +0316 metaCycRxns.rev(rxnCounter,1)=0; +0317 case 'IRREVERSIBLE-RIGHT-TO-LEFT' 0318 metaCycRxns.rev(rxnCounter,1)=0; 0319 reverse=1; -0320 case 'PHYSIOL-RIGHT-TO-LEFT' +0320 case 'RIGHT-TO-LEFT' 0321 metaCycRxns.rev(rxnCounter,1)=0; 0322 reverse=1; -0323 end -0324 end -0325 -0326 %Tag transport reactions -0327 if strcmp(tline,'TYPES - Transport-Reactions') -0328 TRANSPORT=[TRANSPORT;metaCycRxns.rxns{rxnCounter}]; -0329 end -0330 -0331 %Add spontaneous -0332 if strcmp(tline,'SPONTANEOUS? - T') -0333 %metaCycRxns.spontaneous(rxnCounter,1)=1; -0334 isSpontaneous(rxnCounter)=true; -0335 end -0336 -0337 %Extract mass-balance status -0338 if numel(tline)>27 && strcmp(tline(1:27),'REACTION-BALANCE-STATUS - :') -0339 if isequal(tline(28:35), 'UNBALANC') -0340 UNBALANCED(rxnCounter)=true; -0341 elseif isequal(tline(28:35), 'UNDETERM') -0342 UNDETERMINED(rxnCounter)=true; -0343 end -0344 end -0345 -0346 %Add left side equation -0347 if numel(tline)>7 && strcmp(tline(1:7),'LEFT - ') -0348 if strcmp(left{rxnCounter},'') -0349 if strcmp(templeft,'') -0350 templeft=tline(8:end); % this is the real first, save to a temp variable -0351 else % count in the coefficient here -0352 if strcmp(coefficient,'') -0353 left{rxnCounter}=templeft; -0354 else -0355 left{rxnCounter}=strcat(coefficient,32,templeft); -0356 coefficient=''; -0357 end -0358 templeft=tline(8:end); -0359 end -0360 else -0361 if strcmp(coefficient,'') -0362 left{rxnCounter}=strcat(left{rxnCounter},' +',32,templeft); -0363 else -0364 left{rxnCounter}=strcat(left{rxnCounter},' +',32,coefficient,32,templeft); -0365 coefficient=''; -0366 end -0367 templeft=tline(8:end); -0368 end -0369 end -0370 -0371 %Add right side equation -0372 if numel(tline)>8 && strcmp(tline(1:8),'RIGHT - ') -0373 if strcmp(right{rxnCounter},'') -0374 if strcmp(tempright,'') -0375 -0376 % a complicated process for the last left -0377 % metabolite -0378 if strcmp(coefficient,'') -0379 if strcmp(left{rxnCounter},'') -0380 left{rxnCounter}=templeft; -0381 else -0382 left{rxnCounter}=strcat(left{rxnCounter},' +',32,templeft); -0383 end -0384 -0385 else -0386 if strcmp(left{rxnCounter},'') -0387 left{rxnCounter}=strcat(coefficient,32,templeft); -0388 else -0389 left{rxnCounter}=strcat(left{rxnCounter},' +',32,coefficient,32,templeft); -0390 end -0391 coefficient=''; -0392 end -0393 % process end -0394 -0395 tempright=tline(9:end); % this is the real first, save to a temp variable -0396 else -0397 if strcmp(coefficient,'') -0398 right{rxnCounter}=tempright; -0399 else -0400 right{rxnCounter}=strcat(coefficient,32,tempright); -0401 coefficient=''; -0402 end -0403 tempright=tline(9:end); -0404 end -0405 else -0406 if strcmp(coefficient,'') -0407 right{rxnCounter}=strcat(right{rxnCounter},' +',32,tempright); -0408 else -0409 right{rxnCounter}=strcat(right{rxnCounter},' +',32,coefficient,32,tempright); -0410 coefficient=''; -0411 end -0412 tempright=tline(9:end); -0413 end -0414 -0415 end -0416 -0417 if numel(tline)>15 && strcmp(tline(1:15),'^COEFFICIENT - ') -0418 coefficient=tline(16:end); -0419 end -0420 -0421 %Generate equation at the end of each object section -0422 if strcmp(tline,'//') -0423 -0424 % a complicated process for the last right metabolite, -0425 % sub-function is needed here -0426 if strcmp(coefficient,'') -0427 if strcmp(right{rxnCounter},'') -0428 right{rxnCounter}=tempright; -0429 else -0430 right{rxnCounter}=strcat(right{rxnCounter},' +',32,tempright); -0431 end -0432 -0433 else -0434 if strcmp(right{rxnCounter},'') -0435 right{rxnCounter}=strcat(coefficient,32,tempright); -0436 else -0437 right{rxnCounter}=strcat(right{rxnCounter},' +',32,coefficient,32,tempright); -0438 end -0439 coefficient=''; -0440 end -0441 % process end -0442 -0443 %get the right direction symbol -0444 if metaCycRxns.rev(rxnCounter,1) -0445 symbol = ' <=>'; -0446 else -0447 symbol = ' =>'; -0448 end -0449 -0450 if reverse -0451 metaCycRxns.equations{rxnCounter}=strcat(right{rxnCounter},symbol,32,left{rxnCounter}); -0452 else -0453 metaCycRxns.equations{rxnCounter}=strcat(left{rxnCounter},symbol,32,right{rxnCounter}); -0454 end -0455 -0456 %Final equation check -0457 if strcmp(left{rxnCounter},'') || strcmp(right{rxnCounter},'') -0458 rxnCounter=rxnCounter-1; -0459 -0460 end -0461 -0462 end -0463 -0464 end -0465 %Close the file -0466 fclose(fid); -0467 -0468 %=== -0469 UNBALANCED=metaCycRxns.rxns(UNBALANCED); -0470 UNDETERMINED=metaCycRxns.rxns(UNDETERMINED); -0471 isSpontaneous=metaCycRxns.rxns(isSpontaneous); -0472 -0473 %If too much space was allocated, shrink the model -0474 metaCycRxns.rxns=metaCycRxns.rxns(1:rxnCounter); -0475 metaCycRxns.rxnNames=metaCycRxns.rxnNames(1:rxnCounter); -0476 metaCycRxns.eccodes=metaCycRxns.eccodes(1:rxnCounter); -0477 metaCycRxns.equations=metaCycRxns.equations(1:rxnCounter); -0478 metaCycRxns.rxnMiriams=metaCycRxns.rxnMiriams(1:rxnCounter); -0479 metaCycRxns.rxnReferences=metaCycRxns.rxnReferences(1:rxnCounter); -0480 metaCycRxns.subSystems=metaCycRxns.subSystems(1:rxnCounter); -0481 metaCycRxns.pwys=metaCycRxns.pwys(1:rxnCounter); -0482 metaCycRxns.rev=metaCycRxns.rev(1:rxnCounter,:); -0483 -0484 rxnLinks.kegg=rxnLinks.kegg(1:dbLinkCounter); -0485 rxnLinks.metacyc=rxnLinks.metacyc(1:dbLinkCounter); -0486 rxnLinks.check=rxnLinks.check(1:dbLinkCounter); -0487 [~,index]=unique(rxnLinks.check); -0488 rxnLinks.kegg=rxnLinks.kegg(index); -0489 rxnLinks.metacyc=rxnLinks.metacyc(index); -0490 rxnLinks=rmfield(rxnLinks,'check'); -0491 -0492 %Construct the S matrix and list of metabolites -0493 [S, mets, badRxns]=constructS(metaCycRxns.equations); -0494 metaCycRxns.S=S; -0495 metaCycRxns.mets=mets; -0496 -0497 %Add some stuff to get a correct model structure -0498 metaCycRxns.ub=ones(rxnCounter,1)*1000; -0499 metaCycRxns.lb=metaCycRxns.rev*-1000; -0500 metaCycRxns.c=zeros(rxnCounter,1); -0501 metaCycRxns.b=zeros(numel(metaCycRxns.mets),1); -0502 metaCycRxns.version=version; -0503 -0504 %Save the model structure -0505 save(rxnsFile,'metaCycRxns','rxnLinks','TRANSPORT','UNBALANCED','UNDETERMINED','isSpontaneous'); -0506 fprintf(['New metaCycRxns.mat has been successfully updated!\n\n']); -0507 end -0508 end -0509 -0510 %Deal with reactions that are labeled as "TRANSPORT", "UNBALANCED", or -0511 %"UNDETERMINED" (depending on settings). -0512 model=metaCycRxns; -0513 if keepTransportRxns==false -0514 model=removeReactions(model,intersect(TRANSPORT,model.rxns),true,true); -0515 end -0516 if keepUnbalanced==false -0517 model=removeReactions(model,intersect(UNBALANCED,model.rxns),true,true); +0323 case 'PHYSIOL-RIGHT-TO-LEFT' +0324 metaCycRxns.rev(rxnCounter,1)=0; +0325 reverse=1; +0326 end +0327 end +0328 +0329 %Tag transport reactions +0330 if strcmp(tline,'TYPES - Transport-Reactions') +0331 TRANSPORT=[TRANSPORT;metaCycRxns.rxns{rxnCounter}]; +0332 end +0333 +0334 %Add spontaneous +0335 if strcmp(tline,'SPONTANEOUS? - T') +0336 %metaCycRxns.spontaneous(rxnCounter,1)=1; +0337 isSpontaneous(rxnCounter)=true; +0338 end +0339 +0340 %Extract mass-balance status +0341 if numel(tline)>27 && strcmp(tline(1:27),'REACTION-BALANCE-STATUS - :') +0342 if isequal(tline(28:35), 'UNBALANC') +0343 UNBALANCED(rxnCounter)=true; +0344 elseif isequal(tline(28:35), 'UNDETERM') +0345 UNDETERMINED(rxnCounter)=true; +0346 end +0347 end +0348 +0349 %Add left side equation +0350 if numel(tline)>7 && strcmp(tline(1:7),'LEFT - ') +0351 if strcmp(left{rxnCounter},'') +0352 if strcmp(templeft,'') +0353 templeft=tline(8:end); % this is the real first, save to a temp variable +0354 else % count in the coefficient here +0355 if strcmp(coefficient,'') +0356 left{rxnCounter}=templeft; +0357 else +0358 left{rxnCounter}=strcat(coefficient,32,templeft); +0359 coefficient=''; +0360 end +0361 templeft=tline(8:end); +0362 end +0363 else +0364 if strcmp(coefficient,'') +0365 left{rxnCounter}=strcat(left{rxnCounter},' +',32,templeft); +0366 else +0367 left{rxnCounter}=strcat(left{rxnCounter},' +',32,coefficient,32,templeft); +0368 coefficient=''; +0369 end +0370 templeft=tline(8:end); +0371 end +0372 end +0373 +0374 %Add right side equation +0375 if numel(tline)>8 && strcmp(tline(1:8),'RIGHT - ') +0376 if strcmp(right{rxnCounter},'') +0377 if strcmp(tempright,'') +0378 +0379 % a complicated process for the last left +0380 % metabolite +0381 if strcmp(coefficient,'') +0382 if strcmp(left{rxnCounter},'') +0383 left{rxnCounter}=templeft; +0384 else +0385 left{rxnCounter}=strcat(left{rxnCounter},' +',32,templeft); +0386 end +0387 +0388 else +0389 if strcmp(left{rxnCounter},'') +0390 left{rxnCounter}=strcat(coefficient,32,templeft); +0391 else +0392 left{rxnCounter}=strcat(left{rxnCounter},' +',32,coefficient,32,templeft); +0393 end +0394 coefficient=''; +0395 end +0396 % process end +0397 +0398 tempright=tline(9:end); % this is the real first, save to a temp variable +0399 else +0400 if strcmp(coefficient,'') +0401 right{rxnCounter}=tempright; +0402 else +0403 right{rxnCounter}=strcat(coefficient,32,tempright); +0404 coefficient=''; +0405 end +0406 tempright=tline(9:end); +0407 end +0408 else +0409 if strcmp(coefficient,'') +0410 right{rxnCounter}=strcat(right{rxnCounter},' +',32,tempright); +0411 else +0412 right{rxnCounter}=strcat(right{rxnCounter},' +',32,coefficient,32,tempright); +0413 coefficient=''; +0414 end +0415 tempright=tline(9:end); +0416 end +0417 +0418 end +0419 +0420 if numel(tline)>15 && strcmp(tline(1:15),'^COEFFICIENT - ') +0421 coefficient=tline(16:end); +0422 end +0423 +0424 %Generate equation at the end of each object section +0425 if strcmp(tline,'//') +0426 +0427 % a complicated process for the last right metabolite, +0428 % sub-function is needed here +0429 if strcmp(coefficient,'') +0430 if strcmp(right{rxnCounter},'') +0431 right{rxnCounter}=tempright; +0432 else +0433 right{rxnCounter}=strcat(right{rxnCounter},' +',32,tempright); +0434 end +0435 +0436 else +0437 if strcmp(right{rxnCounter},'') +0438 right{rxnCounter}=strcat(coefficient,32,tempright); +0439 else +0440 right{rxnCounter}=strcat(right{rxnCounter},' +',32,coefficient,32,tempright); +0441 end +0442 coefficient=''; +0443 end +0444 % process end +0445 +0446 %get the right direction symbol +0447 if metaCycRxns.rev(rxnCounter,1) +0448 symbol = ' <=>'; +0449 else +0450 symbol = ' =>'; +0451 end +0452 +0453 if reverse +0454 metaCycRxns.equations{rxnCounter}=strcat(right{rxnCounter},symbol,32,left{rxnCounter}); +0455 else +0456 metaCycRxns.equations{rxnCounter}=strcat(left{rxnCounter},symbol,32,right{rxnCounter}); +0457 end +0458 +0459 %Final equation check +0460 if strcmp(left{rxnCounter},'') || strcmp(right{rxnCounter},'') +0461 rxnCounter=rxnCounter-1; +0462 +0463 end +0464 +0465 end +0466 +0467 end +0468 %Close the file +0469 fclose(fid); +0470 +0471 %=== +0472 UNBALANCED=metaCycRxns.rxns(UNBALANCED); +0473 UNDETERMINED=metaCycRxns.rxns(UNDETERMINED); +0474 isSpontaneous=metaCycRxns.rxns(isSpontaneous); +0475 +0476 %If too much space was allocated, shrink the model +0477 metaCycRxns.rxns=metaCycRxns.rxns(1:rxnCounter); +0478 metaCycRxns.rxnNames=metaCycRxns.rxnNames(1:rxnCounter); +0479 metaCycRxns.eccodes=metaCycRxns.eccodes(1:rxnCounter); +0480 metaCycRxns.equations=metaCycRxns.equations(1:rxnCounter); +0481 metaCycRxns.rxnMiriams=metaCycRxns.rxnMiriams(1:rxnCounter); +0482 metaCycRxns.rxnReferences=metaCycRxns.rxnReferences(1:rxnCounter); +0483 metaCycRxns.subSystems=metaCycRxns.subSystems(1:rxnCounter); +0484 metaCycRxns.pwys=metaCycRxns.pwys(1:rxnCounter); +0485 metaCycRxns.rev=metaCycRxns.rev(1:rxnCounter,:); +0486 +0487 rxnLinks.kegg=rxnLinks.kegg(1:dbLinkCounter); +0488 rxnLinks.metacyc=rxnLinks.metacyc(1:dbLinkCounter); +0489 rxnLinks.check=rxnLinks.check(1:dbLinkCounter); +0490 [~,index]=unique(rxnLinks.check); +0491 rxnLinks.kegg=rxnLinks.kegg(index); +0492 rxnLinks.metacyc=rxnLinks.metacyc(index); +0493 rxnLinks=rmfield(rxnLinks,'check'); +0494 +0495 %Construct the S matrix and list of metabolites +0496 [S, mets, badRxns]=constructS(metaCycRxns.equations); +0497 metaCycRxns.S=S; +0498 metaCycRxns.mets=mets; +0499 +0500 %Add some stuff to get a correct model structure +0501 metaCycRxns.ub=ones(rxnCounter,1)*1000; +0502 metaCycRxns.lb=metaCycRxns.rev*-1000; +0503 metaCycRxns.c=zeros(rxnCounter,1); +0504 metaCycRxns.b=zeros(numel(metaCycRxns.mets),1); +0505 metaCycRxns.version=version; +0506 +0507 %Save the model structure +0508 save(rxnsFile,'metaCycRxns','rxnLinks','TRANSPORT','UNBALANCED','UNDETERMINED','isSpontaneous'); +0509 fprintf(['New metaCycRxns.mat has been successfully updated!\n\n']); +0510 end +0511 end +0512 +0513 %Deal with reactions that are labeled as "TRANSPORT", "UNBALANCED", or +0514 %"UNDETERMINED" (depending on settings). +0515 model=metaCycRxns; +0516 if keepTransportRxns==false +0517 model=removeReactions(model,intersect(TRANSPORT,model.rxns),true,true); 0518 end -0519 if keepUndetermined==false -0520 model=removeReactions(model,intersect(UNDETERMINED,model.rxns),true,true); +0519 if keepUnbalanced==false +0520 model=removeReactions(model,intersect(UNBALANCED,model.rxns),true,true); 0521 end -0522 end -0523 -0524 %Sub function for romving HTML symbols from the names of reaction and -0525 %pathway -0526 function newString=removeHTMLcodes(string) -0527 string=regexprep(string,'<(\w+)>',''); -0528 string=regexprep(string,'</(\w+)>',''); -0529 string=regexprep(string,'[&;]',''); -0530 newString=string; -0531 end +0522 if keepUndetermined==false +0523 model=removeReactions(model,intersect(UNDETERMINED,model.rxns),true,true); +0524 end +0525 end +0526 +0527 %Sub function for romving HTML symbols from the names of reaction and +0528 %pathway +0529 function newString=removeHTMLcodes(string) +0530 string=regexprep(string,'<(\w+)>',''); +0531 string=regexprep(string,'</(\w+)>',''); +0532 string=regexprep(string,'[&;]',''); +0533 newString=string; +0534 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/metacyc/linkMetaCycKEGGRxns.html b/doc/external/metacyc/linkMetaCycKEGGRxns.html index 7a93c47d..17ebf991 100644 --- a/doc/external/metacyc/linkMetaCycKEGGRxns.html +++ b/doc/external/metacyc/linkMetaCycKEGGRxns.html @@ -148,13 +148,12 @@

    SOURCE CODE ^'check'); 0099 0100 %Get the MetaCyc path and update the metaCycRxns.mat -0101 [ST, I]=dbstack('-completenames'); -0102 metaCycPath=fileparts(ST(I).file); -0103 rxnsFile=fullfile(metaCycPath,'metaCycRxns.mat'); -0104 save(rxnsFile,'metaCycRxns','rxnLinks','TRANSPORT','UNBALANCED','UNDETERMINED','isSpontaneous'); -0105 fprintf(['Reaction associations between MetaCyc and KEGG have been successfully updated!\n\n']); -0106 -0107 end +0101 ravenPath=findRAVENroot(); +0102 rxnsFile=fullfile(ravenPath,'external','metacyc','metaCycRxns.mat'); +0103 save(rxnsFile,'metaCycRxns','rxnLinks','TRANSPORT','UNBALANCED','UNDETERMINED','isSpontaneous'); +0104 fprintf(['Reaction associations between MetaCyc and KEGG have been successfully updated!\n\n']); +0105 +0106 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/parseScores.html b/doc/external/parseScores.html index 8c822574..19c22f04 100644 --- a/doc/external/parseScores.html +++ b/doc/external/parseScores.html @@ -75,113 +75,115 @@

    SOURCE CODE ^if nargin<2 0019 predictor='wolf'; -0020 end -0021 -0022 fid=fopen(inputFile,'r'); +0020 else +0021 predictor=char(predictor); +0022 end 0023 -0024 if fid<1 -0025 EM='Could not open file'; -0026 dispEM(EM); -0027 end -0028 -0029 if strcmpi(predictor,'wolf') -0030 A=textscan(fid,'%s','Delimiter','\n','CommentStyle','#'); -0031 -0032 %Each element should be for one gene, but some of them are on the form -0033 %"Pc20g11350: treating 9 X's as Glycines". Those should be removed -0034 I=~cellfun(@any,strfind(A{1},'treating')); -0035 -0036 B=regexp(A{1}(I),' ','split'); +0024 fid=fopen(inputFile,'r'); +0025 +0026 if fid<1 +0027 EM='Could not open file'; +0028 dispEM(EM); +0029 end +0030 +0031 if strcmpi(predictor,'wolf') +0032 A=textscan(fid,'%s','Delimiter','\n','CommentStyle','#'); +0033 +0034 %Each element should be for one gene, but some of them are on the form +0035 %"Pc20g11350: treating 9 X's as Glycines". Those should be removed +0036 I=~cellfun(@any,strfind(A{1},'treating')); 0037 -0038 %Reserve space for stuff -0039 GSS.compartments={}; -0040 GSS.scores=[]; %Do not know number of comps yet -0041 GSS.genes=cell(numel(B),1); -0042 -0043 %Parsing is a bit cumbersome as ', ' is used as a delimiter in some -0044 %cases and ' ' in others. Use strrep to get rid of ',' -0045 for i=1:numel(B) -0046 b=strrep(B{i},',',''); -0047 GSS.genes{i}=b{1}; -0048 -0049 %Then go through the compartments and add new ones as they are -0050 %found -0051 for j=2:2:numel(b)-1 -0052 [~, J]=ismember(b(j),GSS.compartments); -0053 -0054 %Add new compartment if it does not exist -0055 if J==0 -0056 GSS.compartments=[GSS.compartments;b(j)]; -0057 J=numel(GSS.compartments); -0058 GSS.scores=[GSS.scores zeros(numel(B),1)]; -0059 end -0060 -0061 GSS.scores(i,J)=str2double(b(j+1)); -0062 end -0063 end -0064 elseif strcmpi(predictor,'cello') -0065 fid=fopen(inputFile,'r'); -0066 %Read the title line and fetch the list of compartments -0067 tline = fgetl(fid); -0068 tline=regexprep(tline,'^.+#Combined:\t',''); -0069 tline=regexprep(tline,'\t#Most-likely-Location.+',''); -0070 GSS.compartments=transpose(regexp(tline,'\t','split')); -0071 -0072 %Now iterate through the following lines in the file. Each row -0073 %corresponds to one gene and it consists of the scores for -0074 %compartments. Gene name is in the end of each line -0075 row=0; -0076 while 1 -0077 row=row+1; -0078 tline = fgetl(fid); -0079 if ~ischar(tline) -0080 break; -0081 end -0082 tline=regexprep(tline,'^.+:\t',''); -0083 tline=regexprep(tline,' .+',''); -0084 tline=regexp(tline,'\t','split'); -0085 GSS.scores(row,:)=str2double(tline(1:numel(GSS.compartments))); -0086 GSS.genes{row,1}=tline{1,end}; -0087 end -0088 elseif strcmpi(predictor,'deeploc') -0089 fid=fopen(inputFile,'r'); -0090 %Read the title line and fetch the list of compartments -0091 tline = fgetl(fid); -0092 GSS.compartments=regexp(tline,'\t','split'); -0093 GSS.compartments=GSS.compartments(3:end); -0094 -0095 %Now iterate through the following lines in the file. Each row -0096 %corresponds to one gene and it consists of the scores for -0097 %compartments. Gene name is in the end of each line -0098 row=0; -0099 while 1 -0100 row=row+1; -0101 tline = fgetl(fid); -0102 if ~ischar(tline) -0103 break; -0104 end -0105 tline=regexp(tline,'\t','split'); -0106 GSS.scores(row,:)=str2double(tline(3:end)); -0107 GSS.genes{row,1}=tline{1,1}; -0108 end -0109 end -0110 -0111 %Check if there are duplicate genes -0112 [~, J, K]=unique(GSS.genes); -0113 -0114 if numel(J)~=numel(K) -0115 EM='There are duplicate genes in the input file'; -0116 dispEM(EM,false); -0117 GSS.genes=GSS.genes(J); -0118 GSS.scores=GSS.scores(J,:); -0119 end -0120 -0121 %Normalize -0122 I=max(GSS.scores,[],2); -0123 GSS.scores=bsxfun(@times, GSS.scores, 1./I); -0124 -0125 fclose(fid); -0126 end +0038 B=regexp(A{1}(I),' ','split'); +0039 +0040 %Reserve space for stuff +0041 GSS.compartments={}; +0042 GSS.scores=[]; %Do not know number of comps yet +0043 GSS.genes=cell(numel(B),1); +0044 +0045 %Parsing is a bit cumbersome as ', ' is used as a delimiter in some +0046 %cases and ' ' in others. Use strrep to get rid of ',' +0047 for i=1:numel(B) +0048 b=strrep(B{i},',',''); +0049 GSS.genes{i}=b{1}; +0050 +0051 %Then go through the compartments and add new ones as they are +0052 %found +0053 for j=2:2:numel(b)-1 +0054 [~, J]=ismember(b(j),GSS.compartments); +0055 +0056 %Add new compartment if it does not exist +0057 if J==0 +0058 GSS.compartments=[GSS.compartments;b(j)]; +0059 J=numel(GSS.compartments); +0060 GSS.scores=[GSS.scores zeros(numel(B),1)]; +0061 end +0062 +0063 GSS.scores(i,J)=str2double(b(j+1)); +0064 end +0065 end +0066 elseif strcmpi(predictor,'cello') +0067 fid=fopen(inputFile,'r'); +0068 %Read the title line and fetch the list of compartments +0069 tline = fgetl(fid); +0070 tline=regexprep(tline,'^.+#Combined:\t',''); +0071 tline=regexprep(tline,'\t#Most-likely-Location.+',''); +0072 GSS.compartments=transpose(regexp(tline,'\t','split')); +0073 +0074 %Now iterate through the following lines in the file. Each row +0075 %corresponds to one gene and it consists of the scores for +0076 %compartments. Gene name is in the end of each line +0077 row=0; +0078 while 1 +0079 row=row+1; +0080 tline = fgetl(fid); +0081 if ~ischar(tline) +0082 break; +0083 end +0084 tline=regexprep(tline,'^.+:\t',''); +0085 tline=regexprep(tline,' .+',''); +0086 tline=regexp(tline,'\t','split'); +0087 GSS.scores(row,:)=str2double(tline(1:numel(GSS.compartments))); +0088 GSS.genes{row,1}=tline{1,end}; +0089 end +0090 elseif strcmpi(predictor,'deeploc') +0091 fid=fopen(inputFile,'r'); +0092 %Read the title line and fetch the list of compartments +0093 tline = fgetl(fid); +0094 GSS.compartments=regexp(tline,'\t','split'); +0095 GSS.compartments=GSS.compartments(3:end); +0096 +0097 %Now iterate through the following lines in the file. Each row +0098 %corresponds to one gene and it consists of the scores for +0099 %compartments. Gene name is in the end of each line +0100 row=0; +0101 while 1 +0102 row=row+1; +0103 tline = fgetl(fid); +0104 if ~ischar(tline) +0105 break; +0106 end +0107 tline=regexp(tline,'\t','split'); +0108 GSS.scores(row,:)=str2double(tline(3:end)); +0109 GSS.genes{row,1}=tline{1,1}; +0110 end +0111 end +0112 +0113 %Check if there are duplicate genes +0114 [~, J, K]=unique(GSS.genes); +0115 +0116 if numel(J)~=numel(K) +0117 EM='There are duplicate genes in the input file'; +0118 dispEM(EM,false); +0119 GSS.genes=GSS.genes(J); +0120 GSS.scores=GSS.scores(J,:); +0121 end +0122 +0123 %Normalize +0124 I=max(GSS.scores,[],2); +0125 GSS.scores=bsxfun(@times, GSS.scores, 1./I); +0126 +0127 fclose(fid); +0128 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/external/updateDocumentation.html b/doc/external/updateDocumentation.html index 36209fd7..2399adea 100644 --- a/doc/external/updateDocumentation.html +++ b/doc/external/updateDocumentation.html @@ -54,36 +54,35 @@

    SOURCE CODE ^% Usage: updateDocumentation() 0007 0008 %Get the RAVEN path -0009 [ST, I]=dbstack('-completenames'); -0010 [ravenDir,~,~]=fileparts(fileparts(ST(I).file)); -0011 %Make sure that RAVEN-provided m2html is used -0012 path(fullfile(ravenDir,'software','m2html'),path); -0013 %Get a non-redundant list of RAVEN subdirectories containing MATLAB -0014 %functions. Absolute paths are not compatible with M2HTML, so convert them -0015 %to the relative paths instead. -0016 ravenDirs_temp=dir(fullfile(ravenDir,'**/*.m')); -0017 ravenDirs=regexprep(unique({ravenDirs_temp.folder}),'^.+RAVEN.{1,1}',''); -0018 -0019 %Get rid of MATLAB functions from external software -0020 ravenDirs(:,contains(ravenDirs(1,:),'software'))=[]; -0021 -0022 %Remove keggModel.mat if it exists -0023 if exist(fullfile(ravenDir,'external','kegg','keggModel.mat'), 'file') == 2 -0024 delete(fullfile(ravenDir,'external','kegg','keggModel.mat')); -0025 end -0026 -0027 %Remove existing "doc" directory from RAVEN -0028 rmdir(fullfile(ravenDir,'doc'),'s'); -0029 -0030 %Save the current working directory and go to RAVEN root directory -0031 originalDir=pwd; -0032 cd(ravenDir); -0033 %Generate HTML documentation files for RAVEN MATLAB functions -0034 m2html('mFiles',ravenDirs,'htmldir','doc'); -0035 %Go back to the original working directory -0036 cd(originalDir); -0037 -0038 end +0009 ravenDir=findRAVENroot(); +0010 %Make sure that RAVEN-provided m2html is used +0011 path(fullfile(ravenDir,'software','m2html'),path); +0012 %Get a non-redundant list of RAVEN subdirectories containing MATLAB +0013 %functions. Absolute paths are not compatible with M2HTML, so convert them +0014 %to the relative paths instead. +0015 ravenDirs_temp=dir(fullfile(ravenDir,'**/*.m')); +0016 ravenDirs=regexprep(unique({ravenDirs_temp.folder}),'^.+RAVEN.{1,1}',''); +0017 +0018 %Get rid of MATLAB functions from external software +0019 ravenDirs(:,contains(ravenDirs(1,:),'software'))=[]; +0020 +0021 %Remove keggModel.mat if it exists +0022 if exist(fullfile(ravenDir,'external','kegg','keggModel.mat'), 'file') == 2 +0023 delete(fullfile(ravenDir,'external','kegg','keggModel.mat')); +0024 end +0025 +0026 %Remove existing "doc" directory from RAVEN +0027 rmdir(fullfile(ravenDir,'doc'),'s'); +0028 +0029 %Save the current working directory and go to RAVEN root directory +0030 originalDir=pwd; +0031 cd(ravenDir); +0032 %Generate HTML documentation files for RAVEN MATLAB functions +0033 m2html('mFiles',ravenDirs,'htmldir','doc'); +0034 %Go back to the original working directory +0035 cd(originalDir); +0036 +0037 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/hpa/parseHPA.html b/doc/hpa/parseHPA.html index f28de86c..bd8def9b 100644 --- a/doc/hpa/parseHPA.html +++ b/doc/hpa/parseHPA.html @@ -119,69 +119,70 @@

    SOURCE CODE ^%Change this and add code for more versions when the current HPA version is increased and the format is changed 0041 end 0042 -0043 if ~(exist(fileName,'file')==2) -0044 error('HPA file %s cannot be found',string(fileName)); -0045 end -0046 -0047 if (version >= 17) -0048 fid=fopen(fileName,'r'); -0049 hpa=textscan(fid,'%q %q %q %q %q %q','Delimiter','\t'); -0050 fclose(fid); -0051 -0052 %Go through and see if the headers match what was expected -0053 headers={'Gene' 'Gene name' 'Tissue' 'Cell type' 'Level' 'Reliability'}; -0054 for i=1:numel(headers) -0055 if ~strcmpi(headers(i),hpa{i}(1)) -0056 EM=['Could not find the header "' headers{i} '". Make sure that the input file matches the format specified at http://www.proteinatlas.org/about/download']; -0057 dispEM(EM); -0058 end -0059 %Remove the header line here -0060 hpa{i}(1)=[]; -0061 end -0062 -0063 %Get the unique values of each data type -0064 [hpaData.genes, P, I]=unique(hpa{1}); -0065 hpaData.geneNames=hpa{2}(P); %make this vector use the index as genes -0066 [~, J, K]=unique(strcat(hpa{3},'€',hpa{4})); -0067 hpaData.tissues=hpa{3}(J); -0068 hpaData.celltypes=hpa{4}(J); -0069 [hpaData.levels, ~, L]=unique(hpa{5}); -0070 [hpaData.reliabilities, ~, N]=unique(hpa{6}); -0071 -0072 %Map the data to be sparse matrises instead -0073 hpaData.gene2Level=sparse(I,K,L,numel(hpaData.genes),numel(hpaData.tissues)); -0074 hpaData.gene2Reliability=sparse(I,K,N,numel(hpaData.genes),numel(hpaData.tissues)); -0075 else -0076 fid=fopen(fileName,'r'); -0077 hpa=textscan(fid,'%q %q %q %q %q %q','Delimiter',','); -0078 fclose(fid); -0079 -0080 %Go through and see if the headers match what was expected -0081 headers={'Gene' 'Tissue' 'Cell type' 'Level' 'Expression type' 'Reliability'}; -0082 for i=1:numel(headers) -0083 if ~strcmpi(headers(i),hpa{i}(1)) -0084 EM=['Could not find the header "' headers{i} '". Make sure that the input file matches the format specified at http://www.proteinatlas.org/about/download']; -0085 dispEM(EM); -0086 end -0087 %Remove the header line here -0088 hpa{i}(1)=[]; -0089 end -0090 -0091 %Get the unique values of each data type -0092 [hpaData.genes, ~, I]=unique(hpa{1}); -0093 [~, J, K]=unique(strcat(hpa{2},'€',hpa{3})); -0094 hpaData.tissues=hpa{2}(J); -0095 hpaData.celltypes=hpa{3}(J); -0096 [hpaData.levels, ~, L]=unique(hpa{4}); -0097 [hpaData.types, ~, M]=unique(hpa{5}); -0098 [hpaData.reliabilities, ~, N]=unique(hpa{6}); -0099 -0100 %Map the data to be sparse matrises instead -0101 hpaData.gene2Level=sparse(I,K,L,numel(hpaData.genes),numel(hpaData.tissues)); -0102 hpaData.gene2Type=sparse(I,K,M,numel(hpaData.genes),numel(hpaData.tissues)); -0103 hpaData.gene2Reliability=sparse(I,K,N,numel(hpaData.genes),numel(hpaData.tissues)); -0104 end -0105 end +0043 fileName=char(fileName); +0044 if ~(exist(fileName,'file')==2) +0045 error('HPA file %s cannot be found',string(fileName)); +0046 end +0047 +0048 if (version >= 17) +0049 fid=fopen(fileName,'r'); +0050 hpa=textscan(fid,'%q %q %q %q %q %q','Delimiter','\t'); +0051 fclose(fid); +0052 +0053 %Go through and see if the headers match what was expected +0054 headers={'Gene' 'Gene name' 'Tissue' 'Cell type' 'Level' 'Reliability'}; +0055 for i=1:numel(headers) +0056 if ~strcmpi(headers(i),hpa{i}(1)) +0057 EM=['Could not find the header "' headers{i} '". Make sure that the input file matches the format specified at http://www.proteinatlas.org/about/download']; +0058 dispEM(EM); +0059 end +0060 %Remove the header line here +0061 hpa{i}(1)=[]; +0062 end +0063 +0064 %Get the unique values of each data type +0065 [hpaData.genes, P, I]=unique(hpa{1}); +0066 hpaData.geneNames=hpa{2}(P); %make this vector use the index as genes +0067 [~, J, K]=unique(strcat(hpa{3},'€',hpa{4})); +0068 hpaData.tissues=hpa{3}(J); +0069 hpaData.celltypes=hpa{4}(J); +0070 [hpaData.levels, ~, L]=unique(hpa{5}); +0071 [hpaData.reliabilities, ~, N]=unique(hpa{6}); +0072 +0073 %Map the data to be sparse matrises instead +0074 hpaData.gene2Level=sparse(I,K,L,numel(hpaData.genes),numel(hpaData.tissues)); +0075 hpaData.gene2Reliability=sparse(I,K,N,numel(hpaData.genes),numel(hpaData.tissues)); +0076 else +0077 fid=fopen(fileName,'r'); +0078 hpa=textscan(fid,'%q %q %q %q %q %q','Delimiter',','); +0079 fclose(fid); +0080 +0081 %Go through and see if the headers match what was expected +0082 headers={'Gene' 'Tissue' 'Cell type' 'Level' 'Expression type' 'Reliability'}; +0083 for i=1:numel(headers) +0084 if ~strcmpi(headers(i),hpa{i}(1)) +0085 EM=['Could not find the header "' headers{i} '". Make sure that the input file matches the format specified at http://www.proteinatlas.org/about/download']; +0086 dispEM(EM); +0087 end +0088 %Remove the header line here +0089 hpa{i}(1)=[]; +0090 end +0091 +0092 %Get the unique values of each data type +0093 [hpaData.genes, ~, I]=unique(hpa{1}); +0094 [~, J, K]=unique(strcat(hpa{2},'€',hpa{3})); +0095 hpaData.tissues=hpa{2}(J); +0096 hpaData.celltypes=hpa{3}(J); +0097 [hpaData.levels, ~, L]=unique(hpa{4}); +0098 [hpaData.types, ~, M]=unique(hpa{5}); +0099 [hpaData.reliabilities, ~, N]=unique(hpa{6}); +0100 +0101 %Map the data to be sparse matrises instead +0102 hpaData.gene2Level=sparse(I,K,L,numel(hpaData.genes),numel(hpaData.tissues)); +0103 hpaData.gene2Type=sparse(I,K,M,numel(hpaData.genes),numel(hpaData.tissues)); +0104 hpaData.gene2Reliability=sparse(I,K,N,numel(hpaData.genes),numel(hpaData.tissues)); +0105 end +0106 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/hpa/parseHPArna.html b/doc/hpa/parseHPArna.html index 7588a60d..8bafa322 100644 --- a/doc/hpa/parseHPArna.html +++ b/doc/hpa/parseHPArna.html @@ -89,47 +89,48 @@

    SOURCE CODE ^end 0028 -0029 if ~(exist(fileName,'file')==2) -0030 error('HPA file %s cannot be found', string(fileName)); -0031 end -0032 -0033 %NOTE! This function assumes that the first 4 columns contain (in order): -0034 % (1) gene ensembl ID, (2) gene abbrev, (3) tissue name, (4) TPM value -0035 if (version == 19) -0036 headers={'Gene' 'Gene name' 'Tissue' 'TPM' 'pTPM' 'NX'}; -0037 elseif (version == 18) -0038 headers={'Gene' 'Gene name' 'Sample' 'Value' 'Unit'}; -0039 else -0040 error('Only HPA versions 18 and 19 are currently supported.'); -0041 end -0042 -0043 %extract data from file -0044 formatSpec = strip(repmat('%q ', 1, numel(headers))); -0045 fid=fopen(fileName, 'r'); -0046 hpa=textscan(fid, formatSpec, 'Delimiter', '\t'); -0047 fclose(fid); -0048 -0049 %Go through and see if the headers match what was expected -0050 for i=1:numel(headers) -0051 if ~strcmpi(headers(i),hpa{i}(1)) -0052 EM=['Could not find the header "' headers{i} '". Make sure that the input file matches the format specified at http://www.proteinatlas.org/about/download']; -0053 dispEM(EM); -0054 end -0055 %Remove the header line here -0056 hpa{i}(1)=[]; -0057 end -0058 -0059 %Get unique gene IDs and tissue names -0060 [arrayData.genes, P, I] = unique(hpa{1}); -0061 arrayData.geneNames = hpa{2}(P); % retrieve corresponding gene names -0062 [arrayData.tissues, ~, J] = unique(hpa{3}); -0063 -0064 %Now extract the gene levels and organize into matrix -0065 arrayData.levels = NaN(max(I),max(J)); -0066 linearInd = sub2ind(size(arrayData.levels),I,J); -0067 arrayData.levels(linearInd) = str2double(hpa{4}); -0068 -0069 +0029 fileName=char(fileName); +0030 if ~(exist(fileName,'file')==2) +0031 error('HPA file %s cannot be found', string(fileName)); +0032 end +0033 +0034 %NOTE! This function assumes that the first 4 columns contain (in order): +0035 % (1) gene ensembl ID, (2) gene abbrev, (3) tissue name, (4) TPM value +0036 if (version == 19) +0037 headers={'Gene' 'Gene name' 'Tissue' 'TPM' 'pTPM' 'NX'}; +0038 elseif (version == 18) +0039 headers={'Gene' 'Gene name' 'Sample' 'Value' 'Unit'}; +0040 else +0041 error('Only HPA versions 18 and 19 are currently supported.'); +0042 end +0043 +0044 %extract data from file +0045 formatSpec = strip(repmat('%q ', 1, numel(headers))); +0046 fid=fopen(fileName, 'r'); +0047 hpa=textscan(fid, formatSpec, 'Delimiter', '\t'); +0048 fclose(fid); +0049 +0050 %Go through and see if the headers match what was expected +0051 for i=1:numel(headers) +0052 if ~strcmpi(headers(i),hpa{i}(1)) +0053 EM=['Could not find the header "' headers{i} '". Make sure that the input file matches the format specified at http://www.proteinatlas.org/about/download']; +0054 dispEM(EM); +0055 end +0056 %Remove the header line here +0057 hpa{i}(1)=[]; +0058 end +0059 +0060 %Get unique gene IDs and tissue names +0061 [arrayData.genes, P, I] = unique(hpa{1}); +0062 arrayData.geneNames = hpa{2}(P); % retrieve corresponding gene names +0063 [arrayData.tissues, ~, J] = unique(hpa{3}); +0064 +0065 %Now extract the gene levels and organize into matrix +0066 arrayData.levels = NaN(max(I),max(J)); +0067 linearInd = sub2ind(size(arrayData.levels),I,J); +0068 arrayData.levels(linearInd) = str2double(hpa{4}); +0069 +0070
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/hpa/scoreModel.html b/doc/hpa/scoreModel.html index 60440372..a41ec927 100644 --- a/doc/hpa/scoreModel.html +++ b/doc/hpa/scoreModel.html @@ -162,261 +162,267 @@

    SOURCE CODE ^end 0062 if nargin<5 0063 celltype=[]; -0064 end -0065 if nargin<6 -0066 noGeneScore=-2; -0067 end -0068 if nargin<7 -0069 multipleGeneScoring='best'; -0070 end -0071 if nargin<8 -0072 multipleCellScoring='best'; -0073 end -0074 if nargin<9 -0075 %The first four are for APE, the other ones for staining -0076 hpaLevelScores.names={'High' 'Medium' 'Low' 'None' 'Strong' 'Moderate' 'Weak' 'Negative' 'Not detected'}; -0077 hpaLevelScores.scores=[20 15 10 -8 20 15 10 -8 -8]; -0078 end -0079 -0080 if isempty(hpaData) && isempty(arrayData) -0081 EM='Must supply hpaData, arrayData or both'; -0082 dispEM(EM); -0083 end -0084 if ~strcmpi(multipleGeneScoring,'best') && ~strcmpi(multipleGeneScoring,'average') -0085 EM='Valid options for multipleGeneScoring are "best" or "average"'; -0086 dispEM(EM); -0087 end -0088 if ~strcmpi(multipleCellScoring,'best') && ~strcmpi(multipleCellScoring,'average') -0089 EM='Valid options for multipleCellScoring are "best" or "average"'; -0090 dispEM(EM); -0091 end -0092 -0093 -0094 %Throw an error if array data for only one tissue is supplied without -0095 %specifying threshold values -0096 if ~isempty(arrayData) -0097 if numel(unique(arrayData.tissues))<2 -0098 if ~isfield(arrayData,'threshold') || isempty(arrayData.threshold) -0099 EM='arrayData must contain measurements for at least two celltypes/tissues since the score is calculated based on the expression level compared to the overall average'; -0100 dispEM(EM); -0101 end -0102 end -0103 end -0104 -0105 %Process arrayData.threshold if necessary -0106 if isfield(arrayData,'threshold') && (numel(arrayData.threshold) == 1) -0107 % if only a single gene threshold value is provided, then just -0108 % duplicate this value for all genes. -0109 arrayData.threshold = arrayData.threshold*ones(size(arrayData.genes)); -0110 end -0111 -0112 %This is so that the code can ignore which combination of input data that is -0113 %used -0114 if isempty(arrayData) -0115 arrayData.genes={}; -0116 arrayData.tissues={}; -0117 arrayData.celltypes={}; -0118 arrayData.levels=[]; -0119 arrayData.threshold=[]; -0120 end -0121 if isempty(hpaData) -0122 hpaData.genes={}; -0123 hpaData.tissues={}; -0124 hpaData.celltypes={}; -0125 hpaData.levels={}; -0126 hpaData.types={}; -0127 hpaData.reliabilities={}; -0128 hpaData.gene2Level=[]; -0129 hpaData.gene2Type=[]; -0130 hpaData.gene2Reliability=[]; -0131 end -0132 -0133 %Check that the tissue exists -0134 if ~ismember(upper(tissue),upper(hpaData.tissues)) && ~ismember(upper(tissue),upper(arrayData.tissues)) -0135 EM='The tissue name does not match'; -0136 dispEM(EM); +0064 else +0065 celltype=char(celltype); +0066 end +0067 if nargin<6 +0068 noGeneScore=-2; +0069 end +0070 if nargin<7 +0071 multipleGeneScoring='best'; +0072 else +0073 multipleGeneScoring=char(multipleGeneScoring); +0074 end +0075 if nargin<8 +0076 multipleCellScoring='best'; +0077 else +0078 multipleCellScoring=char(multipleCellScoring); +0079 end +0080 if nargin<9 +0081 %The first four are for APE, the other ones for staining +0082 hpaLevelScores.names={'High' 'Medium' 'Low' 'None' 'Strong' 'Moderate' 'Weak' 'Negative' 'Not detected'}; +0083 hpaLevelScores.scores=[20 15 10 -8 20 15 10 -8 -8]; +0084 end +0085 +0086 if isempty(hpaData) && isempty(arrayData) +0087 EM='Must supply hpaData, arrayData or both'; +0088 dispEM(EM); +0089 end +0090 if ~strcmpi(multipleGeneScoring,'best') && ~strcmpi(multipleGeneScoring,'average') +0091 EM='Valid options for multipleGeneScoring are "best" or "average"'; +0092 dispEM(EM); +0093 end +0094 if ~strcmpi(multipleCellScoring,'best') && ~strcmpi(multipleCellScoring,'average') +0095 EM='Valid options for multipleCellScoring are "best" or "average"'; +0096 dispEM(EM); +0097 end +0098 +0099 +0100 %Throw an error if array data for only one tissue is supplied without +0101 %specifying threshold values +0102 if ~isempty(arrayData) +0103 if numel(unique(arrayData.tissues))<2 +0104 if ~isfield(arrayData,'threshold') || isempty(arrayData.threshold) +0105 EM='arrayData must contain measurements for at least two celltypes/tissues since the score is calculated based on the expression level compared to the overall average'; +0106 dispEM(EM); +0107 end +0108 end +0109 end +0110 +0111 %Process arrayData.threshold if necessary +0112 if isfield(arrayData,'threshold') && (numel(arrayData.threshold) == 1) +0113 % if only a single gene threshold value is provided, then just +0114 % duplicate this value for all genes. +0115 arrayData.threshold = arrayData.threshold*ones(size(arrayData.genes)); +0116 end +0117 +0118 %This is so that the code can ignore which combination of input data that is +0119 %used +0120 if isempty(arrayData) +0121 arrayData.genes={}; +0122 arrayData.tissues={}; +0123 arrayData.celltypes={}; +0124 arrayData.levels=[]; +0125 arrayData.threshold=[]; +0126 end +0127 if isempty(hpaData) +0128 hpaData.genes={}; +0129 hpaData.tissues={}; +0130 hpaData.celltypes={}; +0131 hpaData.levels={}; +0132 hpaData.types={}; +0133 hpaData.reliabilities={}; +0134 hpaData.gene2Level=[]; +0135 hpaData.gene2Type=[]; +0136 hpaData.gene2Reliability=[]; 0137 end -0138 if any(celltype) -0139 %Check that both data types has cell type defined if that is to be used -0140 if ~isfield(hpaData,'celltypes') || ~isfield(arrayData,'celltypes') -0141 EM='Both hpaData and arrayData must contain cell type information if cell type is to be used'; -0142 dispEM(EM); -0143 end -0144 if ~ismember(upper(celltype),upper(hpaData.celltypes)) && ~ismember(upper(celltype),upper(arrayData.celltypes)) -0145 EM='The cell type name does not match'; -0146 dispEM(EM); -0147 end -0148 end -0149 -0150 %Some preprocessing of the structures to speed up a little Remove all -0151 %tissues that are not the correct one -0152 J=~strcmpi(hpaData.tissues,tissue); -0153 -0154 %If cell type is supplied, then only keep that cell type -0155 if any(celltype) -0156 J=J | ~strcmpi(hpaData.celltypes,celltype); -0157 end -0158 -0159 hpaData.tissues(J)=[]; -0160 if isfield(hpaData,'celltypes') -0161 hpaData.celltypes(J)=[]; -0162 end -0163 if isfield(hpaData,'gene2Level') -0164 hpaData.gene2Level(:,J)=[]; -0165 end -0166 if isfield(hpaData,'gene2Type') -0167 hpaData.gene2Type(:,J)=[]; +0138 +0139 %Check that the tissue exists +0140 if ~ismember(upper(tissue),upper(hpaData.tissues)) && ~ismember(upper(tissue),upper(arrayData.tissues)) +0141 EM='The tissue name does not match'; +0142 dispEM(EM); +0143 end +0144 if any(celltype) +0145 %Check that both data types has cell type defined if that is to be used +0146 if ~isfield(hpaData,'celltypes') || ~isfield(arrayData,'celltypes') +0147 EM='Both hpaData and arrayData must contain cell type information if cell type is to be used'; +0148 dispEM(EM); +0149 end +0150 if ~ismember(upper(celltype),upper(hpaData.celltypes)) && ~ismember(upper(celltype),upper(arrayData.celltypes)) +0151 EM='The cell type name does not match'; +0152 dispEM(EM); +0153 end +0154 end +0155 +0156 %Some preprocessing of the structures to speed up a little Remove all +0157 %tissues that are not the correct one +0158 J=~strcmpi(hpaData.tissues,tissue); +0159 +0160 %If cell type is supplied, then only keep that cell type +0161 if any(celltype) +0162 J=J | ~strcmpi(hpaData.celltypes,celltype); +0163 end +0164 +0165 hpaData.tissues(J)=[]; +0166 if isfield(hpaData,'celltypes') +0167 hpaData.celltypes(J)=[]; 0168 end -0169 if isfield(hpaData,'gene2Reliability') -0170 hpaData.gene2Reliability(:,J)=[]; +0169 if isfield(hpaData,'gene2Level') +0170 hpaData.gene2Level(:,J)=[]; 0171 end -0172 -0173 %Remove all genes from the structures that are not in model or that aren't -0174 %measured in the tissue -0175 if ~isempty(hpaData.genes) %This should not be necessary, but the summation is a 0x1 matrix and the other is [] -0176 I=~ismember(hpaData.genes,model.genes) | sum(hpaData.gene2Level,2)==0; -0177 else -0178 I=[]; -0179 end -0180 hpaData.genes(I)=[]; -0181 if isfield(hpaData,'gene2Level') -0182 hpaData.gene2Level(I,:)=[]; -0183 end -0184 if isfield(hpaData,'gene2Type') -0185 hpaData.gene2Type(I,:)=[]; -0186 end -0187 if isfield(hpaData,'gene2Reliability') -0188 hpaData.gene2Reliability(I,:)=[]; +0172 if isfield(hpaData,'gene2Type') +0173 hpaData.gene2Type(:,J)=[]; +0174 end +0175 if isfield(hpaData,'gene2Reliability') +0176 hpaData.gene2Reliability(:,J)=[]; +0177 end +0178 +0179 %Remove all genes from the structures that are not in model or that aren't +0180 %measured in the tissue +0181 if ~isempty(hpaData.genes) %This should not be necessary, but the summation is a 0x1 matrix and the other is [] +0182 I=~ismember(hpaData.genes,model.genes) | sum(hpaData.gene2Level,2)==0; +0183 else +0184 I=[]; +0185 end +0186 hpaData.genes(I)=[]; +0187 if isfield(hpaData,'gene2Level') +0188 hpaData.gene2Level(I,:)=[]; 0189 end -0190 -0191 I=strcmpi(arrayData.tissues,tissue); -0192 %If cell type is supplied, then only keep that cell type -0193 if any(celltype) -0194 I=I & strcmpi(arrayData.celltypes,celltype); +0190 if isfield(hpaData,'gene2Type') +0191 hpaData.gene2Type(I,:)=[]; +0192 end +0193 if isfield(hpaData,'gene2Reliability') +0194 hpaData.gene2Reliability(I,:)=[]; 0195 end 0196 -0197 %Remove all genes from the structures that are not in model or that aren't -0198 %measured in the tissue -0199 J=~ismember(arrayData.genes,model.genes) | myAll(isnan(arrayData.levels(:,I)),2); -0200 arrayData.genes(J)=[]; -0201 arrayData.levels(J,:)=[]; -0202 if isfield(arrayData,'threshold') -0203 arrayData.threshold(J) = []; -0204 end -0205 -0206 %Calculate the scores for the arrayData. These scores are calculated for -0207 %each genes from its fold change between the tissue/celltype(s) in question -0208 %and all other celltypes. This is a lower quality data than protein -0209 %abundance, since a gene that is equally highly expressed in all cell types -0210 %will have a score of 0.0. These scores are therefore only used for genes -0211 %for which there is no HPA data available. The fold changes are transformed -0212 %as min(log(x),10) for x>1 and max(log(x),-5) for x<1 in order to have -0213 %negative scores for lower expressed genes and to scale the scrores to have -0214 %somewhat lower weights than the HPA scores -0215 tempArrayLevels=arrayData.levels; -0216 tempArrayLevels(isnan(tempArrayLevels))=0; -0217 if isfield(arrayData,'threshold') && ~isempty(arrayData.threshold) -0218 % if provided, the user-supplied expression threshold value(s) will be -0219 % used as the "average" expression level to which each gene is -0220 % compared. -0221 average=arrayData.threshold; -0222 else -0223 average=sum(tempArrayLevels,2)./sum(~isnan(arrayData.levels),2); -0224 end -0225 if strcmpi(multipleCellScoring,'best') -0226 current=max(tempArrayLevels(:,I),[],2); -0227 else -0228 current=sum(tempArrayLevels(:,I),2)./sum(~isnan(arrayData.levels(:,I)),2); -0229 end -0230 if ~isempty(current) -0231 aScores=5*log(current./average); -0232 else -0233 aScores=[]; -0234 end -0235 aScores(aScores>0)=min(aScores(aScores>0),10); -0236 aScores(aScores<0)=max(aScores(aScores<0),-5); -0237 aScores(isnan(aScores)) = -5; % NaNs occur when gene expression is zero across all tissues -0238 -0239 %Map the HPA levels to scores -0240 [I, J]=ismember(upper(hpaData.levels),upper(hpaLevelScores.names)); -0241 if ~all(I) -0242 EM='There are expression level categories that do not match to hpaLevelScores'; -0243 dispEM(EM); -0244 end -0245 [K, L, M]=find(hpaData.gene2Level); -0246 scores=hpaLevelScores.scores(J); -0247 if strcmpi(multipleCellScoring,'best') -0248 hScores=max(sparse(K,L,scores(M),numel(hpaData.genes),numel(hpaData.tissues)),[],2); -0249 else -0250 hScores=mean(sparse(K,L,scores(M),numel(hpaData.genes),numel(hpaData.tissues)),2); -0251 end -0252 -0253 %Get the scores for the genes, only use HPA if available -0254 geneScores=inf(numel(model.genes),1)*-1; -0255 hpaScores=geneScores; -0256 arrayScores=geneScores; -0257 -0258 [I, J]=ismember(model.genes,hpaData.genes); -0259 hpaScores(I)=hScores(J(I)); -0260 geneScores(I)=hScores(J(I)); -0261 [I, J]=ismember(model.genes,arrayData.genes); -0262 arrayScores(I)=aScores(J(I)); -0263 geneScores(I & myIsInf(geneScores))=aScores(J(I & myIsInf(geneScores))); -0264 -0265 %Remove the genes that have no data from the model -0266 I=ismember(model.genes,hpaData.genes) | ismember(model.genes,arrayData.genes); -0267 model.genes(~I)=[]; -0268 model.rxnGeneMat(:,~I)=[]; -0269 -0270 %Map the genes to the HPA/array genes -0271 [hpaExist, hpaMap]=ismember(model.genes,hpaData.genes); -0272 [arrayExist, arrayMap]=ismember(model.genes,arrayData.genes); -0273 -0274 %Set the default scores for reactions without genes -0275 rxnScores=ones(numel(model.rxns),1)*noGeneScore; -0276 -0277 %Loop through the reactions and calculate the scores -0278 for i=1:numel(model.rxns) -0279 %Check if it has genes -0280 I=find(model.rxnGeneMat(i,:)); -0281 if any(I) -0282 %If any of the genes exist in hpaData, then don't use arrayData -0283 if any(hpaExist(I)) -0284 %At least one gene was found in HPA -0285 if strcmpi(multipleGeneScoring,'best') -0286 rxnScores(i)=max(hScores(hpaMap(I(hpaExist(I))))); -0287 else -0288 rxnScores(i)=mean(hScores(hpaMap(I(hpaExist(I))))); -0289 end -0290 else -0291 %Use array data -0292 if any(arrayExist(I)) -0293 %At least one gene was found in the array data -0294 if strcmpi(multipleGeneScoring,'best') -0295 rxnScores(i)=max(aScores(arrayMap(I(arrayExist(I))))); -0296 else -0297 rxnScores(i)=mean(aScores(arrayMap(I(arrayExist(I))))); -0298 end -0299 end -0300 end -0301 end -0302 end -0303 end -0304 -0305 %This is because isinf and all returns 0x1 for empty set, which gives a -0306 %concatenation error. Do like this instead of having many if statements -0307 function y=myIsInf(x) -0308 y=isinf(x); -0309 if isempty(y) -0310 y=[]; -0311 end -0312 end -0313 function y=myAll(x,dim) -0314 y=all(x,dim); +0197 I=strcmpi(arrayData.tissues,tissue); +0198 %If cell type is supplied, then only keep that cell type +0199 if any(celltype) +0200 I=I & strcmpi(arrayData.celltypes,celltype); +0201 end +0202 +0203 %Remove all genes from the structures that are not in model or that aren't +0204 %measured in the tissue +0205 J=~ismember(arrayData.genes,model.genes) | myAll(isnan(arrayData.levels(:,I)),2); +0206 arrayData.genes(J)=[]; +0207 arrayData.levels(J,:)=[]; +0208 if isfield(arrayData,'threshold') +0209 arrayData.threshold(J) = []; +0210 end +0211 +0212 %Calculate the scores for the arrayData. These scores are calculated for +0213 %each genes from its fold change between the tissue/celltype(s) in question +0214 %and all other celltypes. This is a lower quality data than protein +0215 %abundance, since a gene that is equally highly expressed in all cell types +0216 %will have a score of 0.0. These scores are therefore only used for genes +0217 %for which there is no HPA data available. The fold changes are transformed +0218 %as min(log(x),10) for x>1 and max(log(x),-5) for x<1 in order to have +0219 %negative scores for lower expressed genes and to scale the scrores to have +0220 %somewhat lower weights than the HPA scores +0221 tempArrayLevels=arrayData.levels; +0222 tempArrayLevels(isnan(tempArrayLevels))=0; +0223 if isfield(arrayData,'threshold') && ~isempty(arrayData.threshold) +0224 % if provided, the user-supplied expression threshold value(s) will be +0225 % used as the "average" expression level to which each gene is +0226 % compared. +0227 average=arrayData.threshold; +0228 else +0229 average=sum(tempArrayLevels,2)./sum(~isnan(arrayData.levels),2); +0230 end +0231 if strcmpi(multipleCellScoring,'best') +0232 current=max(tempArrayLevels(:,I),[],2); +0233 else +0234 current=sum(tempArrayLevels(:,I),2)./sum(~isnan(arrayData.levels(:,I)),2); +0235 end +0236 if ~isempty(current) +0237 aScores=5*log(current./average); +0238 else +0239 aScores=[]; +0240 end +0241 aScores(aScores>0)=min(aScores(aScores>0),10); +0242 aScores(aScores<0)=max(aScores(aScores<0),-5); +0243 aScores(isnan(aScores)) = -5; % NaNs occur when gene expression is zero across all tissues +0244 +0245 %Map the HPA levels to scores +0246 [I, J]=ismember(upper(hpaData.levels),upper(hpaLevelScores.names)); +0247 if ~all(I) +0248 EM='There are expression level categories that do not match to hpaLevelScores'; +0249 dispEM(EM); +0250 end +0251 [K, L, M]=find(hpaData.gene2Level); +0252 scores=hpaLevelScores.scores(J); +0253 if strcmpi(multipleCellScoring,'best') +0254 hScores=max(sparse(K,L,scores(M),numel(hpaData.genes),numel(hpaData.tissues)),[],2); +0255 else +0256 hScores=mean(sparse(K,L,scores(M),numel(hpaData.genes),numel(hpaData.tissues)),2); +0257 end +0258 +0259 %Get the scores for the genes, only use HPA if available +0260 geneScores=inf(numel(model.genes),1)*-1; +0261 hpaScores=geneScores; +0262 arrayScores=geneScores; +0263 +0264 [I, J]=ismember(model.genes,hpaData.genes); +0265 hpaScores(I)=hScores(J(I)); +0266 geneScores(I)=hScores(J(I)); +0267 [I, J]=ismember(model.genes,arrayData.genes); +0268 arrayScores(I)=aScores(J(I)); +0269 geneScores(I & myIsInf(geneScores))=aScores(J(I & myIsInf(geneScores))); +0270 +0271 %Remove the genes that have no data from the model +0272 I=ismember(model.genes,hpaData.genes) | ismember(model.genes,arrayData.genes); +0273 model.genes(~I)=[]; +0274 model.rxnGeneMat(:,~I)=[]; +0275 +0276 %Map the genes to the HPA/array genes +0277 [hpaExist, hpaMap]=ismember(model.genes,hpaData.genes); +0278 [arrayExist, arrayMap]=ismember(model.genes,arrayData.genes); +0279 +0280 %Set the default scores for reactions without genes +0281 rxnScores=ones(numel(model.rxns),1)*noGeneScore; +0282 +0283 %Loop through the reactions and calculate the scores +0284 for i=1:numel(model.rxns) +0285 %Check if it has genes +0286 I=find(model.rxnGeneMat(i,:)); +0287 if any(I) +0288 %If any of the genes exist in hpaData, then don't use arrayData +0289 if any(hpaExist(I)) +0290 %At least one gene was found in HPA +0291 if strcmpi(multipleGeneScoring,'best') +0292 rxnScores(i)=max(hScores(hpaMap(I(hpaExist(I))))); +0293 else +0294 rxnScores(i)=mean(hScores(hpaMap(I(hpaExist(I))))); +0295 end +0296 else +0297 %Use array data +0298 if any(arrayExist(I)) +0299 %At least one gene was found in the array data +0300 if strcmpi(multipleGeneScoring,'best') +0301 rxnScores(i)=max(aScores(arrayMap(I(arrayExist(I))))); +0302 else +0303 rxnScores(i)=mean(aScores(arrayMap(I(arrayExist(I))))); +0304 end +0305 end +0306 end +0307 end +0308 end +0309 end +0310 +0311 %This is because isinf and all returns 0x1 for empty set, which gives a +0312 %concatenation error. Do like this instead of having many if statements +0313 function y=myIsInf(x) +0314 y=isinf(x); 0315 if isempty(y) 0316 y=[]; 0317 end -0318 end +0318 end +0319 function y=myAll(x,dim) +0320 y=all(x,dim); +0321 if isempty(y) +0322 y=[]; +0323 end +0324 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/index.html b/doc/index.html index 4fa9cd5b..9e0b5575 100644 --- a/doc/index.html +++ b/doc/index.html @@ -3,8 +3,8 @@ Matlab Index - - + + @@ -15,55 +15,56 @@

    Matlab Index

    Matlab Directories

    +
  • INIT
  • core
  • external
  • external\kegg
  • external\metacyc
  • hpa
  • installation
  • io
  • legacy\core
  • legacy\external
  • pathway
  • plotting
  • solver
  • struct_conversion
  • testing\unit_tests
  • tutorial
  • Matlab Files found in these Directories

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FSEOF deleteUnusedGenes getMinNrFluxes printModel
    SBMLFromExcel diamondTests getModelFromHomology printModelStats
    addExchangeRxns dispEM getModelFromKEGG qMOMA
    addGenesRaven drawMap getModelFromMetaCyc randomSampling
    addJavaPaths drawPathway getObjectiveString ravenCobraWrapper
    addMets editMiriam getPathwayDimensions removeBadRxns
    addRavenToUserPath expandModel getPhylDist removeGenes
    addRxns exportForGit getRxnsFromKEGG removeMets
    addRxnsGenesMets exportModel getRxnsFromMetaCyc removeReactions
    addSpontaneousRxns exportModelToSIF getRxnsInComp replaceMets
    addTransport exportToExcelFormat getToolboxVersion reporterMetabolites
    analyzeSampling exportToTabDelimited getTransportRxns runINIT
    blastPlusTests extractMiriam getWSLpath scoreModel
    buildEquation fillGaps getWoLFScores setColorToMapRxns
    canConsume findGeneDeletions guessComposition setExchangeBounds
    canProduce fitParameters gurobiToCobraRes setOmicDataToRxns
    cdhitTests fitTasks haveFlux setParam
    changeGeneAssoc followChanged hmmerTests setRavenSolver
    changeGrRules followFluxes importExcelModel setTitle
    changeRxns gapReport importModel simplifyModel
    checkFileExistence generateNewIds linkMetaCycKEGGRxns solveLP
    checkFunctionUniqueness getAllRxnsFromGenes loadSheet solveQP
    checkInstallation getAllSubGraphs loadWorkbook sortIdentifiers
    checkModelStruct getAllowedBounds mafftTests sortIdentifiers_and_permuteModelTests
    checkProduction getBlast makeFakeBlastStructure sortModel
    checkRxn getBlastFromExcel makeSomething standardizeGrRules
    checkSolution getColorCodes mapCompartments standardizeModelFieldOrder
    checkTasks getDiamond mapPathwayRxnNames startup
    cleanSheet getElementalBalance markPathwayWithExpression tinitTests
    closeModel getEnzymesFromMetaCyc markPathwayWithFluxes trimPathway
    cobraToGurobiProb getEssentialRxns mergeCompartments tutorial1
    cobraToMosekRes getExchangeRxns mergeModels tutorial2
    colorPathway getExpressionStructure miriamTests tutorial2_solutions
    colorSubsystem getFluxZ optimizeProb tutorial3
    combineMetaCycKEGGModels getFullPath parseFormulas tutorial3_solutions
    compareMultipleModels getGenesFromKEGG parseHPA tutorial4
    compareRxnsGenesMetsComps getINITModel parseHPArna tutorial4_solutions
    constructEquations getIndexes parseRxnEqu tutorial5
    constructMultiFasta getKEGGModelForOrganism parseScores tutorial6
    constructPathwayFromCelldesigner getMD5Hash parseTaskList updateDocumentation
    constructS getMILPParams permuteModel writeSheet
    consumeSomething getMetaCycModelForOrganism plotAdditionalInfo writeYaml
    contractModel getMetsFromKEGG plotLabels
    convertToIrrev getMetsFromMetaCyc predictLocalization
    copyToComps getMetsInComp printFluxes
    + FSEOF dispEM getModelFromHomology printFluxes + SBMLFromExcel drawMap getModelFromKEGG printModel + addExchangeRxns drawPathway getModelFromMetaCyc printModelStats + addGenesRaven editMiriam getObjectiveString qMOMA + addJavaPaths expandModel getPathwayDimensions randomSampling + addMets exportForGit getPhylDist ravenCobraWrapper + addRavenToUserPath exportModel getRxnsFromKEGG removeBadRxns + addRxns exportModelToSIF getRxnsFromMetaCyc removeGenes + addRxnsGenesMets exportToExcelFormat getRxnsInComp removeMets + addSpontaneousRxns exportToTabDelimited getToolboxVersion removeReactions + addTransport extractMiriam getTransportRxns replaceMets + analyzeSampling fillGaps getWSLpath reporterMetabolites + blastPlusTests fillGapsLargeTests getWoLFScores runINIT + buildEquation fillGapsSmallTests guessComposition scoreModel + canConsume findGeneDeletions haveFlux setColorToMapRxns + canProduce findRAVENroot hmmerTests setExchangeBounds + cdhitTests fitParameters importExcelModel setOmicDataToRxns + changeGeneAssoc fitTasks importExportTests setParam + changeGrRules followChanged importModel setRavenSolver + changeRxns followFluxes linkMetaCycKEGGRxns setTitle + checkFileExistence gapReport loadSheet simplifyModel + checkFunctionUniqueness generateNewIds loadWorkbook solveLP + checkInstallation getAllRxnsFromGenes mafftTests solveQP + checkModelStruct getAllSubGraphs makeFakeBlastStructure solverTests + checkProduction getAllowedBounds makeSomething sortIdentifiers + checkRxn getBlast mapCompartments sortIdentifiers_and_permuteModelTests + checkSolution getBlastFromExcel mapPathwayRxnNames sortModel + checkTasks getColorCodes markPathwayWithExpression standardizeGrRules + cleanSheet getDiamond markPathwayWithFluxes standardizeModelFieldOrder + closeModel getElementalBalance mergeCompartments startup + colorPathway getEnzymesFromMetaCyc mergeModels tinitTests + colorSubsystem getEssentialRxns miriamTests trimPathway + combineMetaCycKEGGModels getExchangeRxns modelAbilitiesTests tutorial1 + compareMultipleModels getExpressionStructure modelConversionTests tutorial2 + compareRxnsGenesMetsComps getFluxZ modelCurationTests tutorial2_solutions + constructEquations getFullPath optimizeProb tutorial3 + constructMultiFasta getGenesFromKEGG parseFormulas tutorial3_solutions + constructPathwayFromCelldesigner getINITModel parseHPA tutorial4 + constructS getIndexes parseHPArna tutorial4_solutions + consumeSomething getKEGGModelForOrganism parseRxnEqu tutorial5 + contractModel getMD5Hash parseScores tutorial6 + convertCharArray getMetaCycModelForOrganism parseTaskList updateDocumentation + convertToIrrev getMetsFromKEGG permuteModel writeSheet + copyToComps getMetsFromMetaCyc plotAdditionalInfo writeYaml + deleteUnusedGenes getMetsInComp plotLabels + diamondTests getMinNrFluxes predictLocalization
    Generated by m2html © 2005
    diff --git a/doc/installation/addRavenToUserPath.html b/doc/installation/addRavenToUserPath.html index a990834e..e846996d 100644 --- a/doc/installation/addRavenToUserPath.html +++ b/doc/installation/addRavenToUserPath.html @@ -68,32 +68,31 @@

    SOURCE CODE ^end 0016 0017 % Get current RAVEN directory -0018 [ST, I]=dbstack('-completenames'); -0019 [ravenDir,~,~]=fileparts(fileparts(ST(I).file)); -0020 -0021 % Lists all subdirectories -0022 subpath=regexp(genpath(ravenDir),pathsep,'split'); -0023 % Remove .git and doc folders -0024 pathsToKeep=cellfun(@(x) isempty(strfind(x,'.git')),subpath) & cellfun(@(x) isempty(strfind(x,'doc')),subpath); -0025 % Only keep useful paths -0026 subpath = subpath(pathsToKeep); -0027 subpath = subpath(1:end-1); % Remove last entry, is empty field -0028 -0029 % Write startup.m file -0030 if overwrite -0031 fid=fopen(fullfile(userpath,'startup.m'),'w'); -0032 fprintf(fid,'%sn','%%% RAVEN path'); -0033 else -0034 fid=fopen(fullfile(userpath,'startup.m'),'a'); -0035 fprintf(fid,'n%sn','%%% RAVEN path'); -0036 end -0037 fprintf(fid,'%sn',strcat('addpath(''',subpath{1},''',...')); -0038 for i=2(length(subpath)-1) -0039 fprintf(fid,'t%sn',strcat('''',subpath{i},''',...')); -0040 end -0041 fprintf(fid,'t%s',strcat('''',subpath{length(subpath)},''');')); -0042 fclose(fid); -0043 end +0018 ravenDir=findRAVENroot(); +0019 +0020 % Lists all subdirectories +0021 subpath=regexp(genpath(ravenDir),pathsep,'split'); +0022 % Remove .git and doc folders +0023 pathsToKeep=cellfun(@(x) isempty(strfind(x,'.git')),subpath) & cellfun(@(x) isempty(strfind(x,'doc')),subpath); +0024 % Only keep useful paths +0025 subpath = subpath(pathsToKeep); +0026 subpath = subpath(1:end-1); % Remove last entry, is empty field +0027 +0028 % Write startup.m file +0029 if overwrite +0030 fid=fopen(fullfile(userpath,'startup.m'),'w'); +0031 fprintf(fid,'%sn','%%% RAVEN path'); +0032 else +0033 fid=fopen(fullfile(userpath,'startup.m'),'a'); +0034 fprintf(fid,'n%sn','%%% RAVEN path'); +0035 end +0036 fprintf(fid,'%sn',strcat('addpath(''',subpath{1},''',...')); +0037 for i=2(length(subpath)-1) +0038 fprintf(fid,'t%sn',strcat('''',subpath{i},''',...')); +0039 end +0040 fprintf(fid,'t%s',strcat('''',subpath{length(subpath)},''');')); +0041 fclose(fid); +0042 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/installation/checkFunctionUniqueness.html b/doc/installation/checkFunctionUniqueness.html index 7348b95a..56e6bb10 100644 --- a/doc/installation/checkFunctionUniqueness.html +++ b/doc/installation/checkFunctionUniqueness.html @@ -54,56 +54,56 @@

    SOURCE CODE ^% Usage: checkFunctionUniqueness() 0007 0008 %Get the RAVEN path -0009 [ST, I]=dbstack('-completenames'); -0010 [ravenDir,~,~]=fileparts(fileparts(ST(I).file)); -0011 -0012 %Now getting all RAVEN functions recursively; -0013 temp_res1=dir([ravenDir '/*/*.m']); -0014 temp_res2=dir([ravenDir '/*/*/*.m']); -0015 -0016 ravenFunctions={temp_res1.name,temp_res2.name}'; -0017 %startup.m is not a normal function, any startup.m in the path should run -0018 %during startup, so duplicate use of this name is fine -0019 ravenFunctions=ravenFunctions(~ismember(ravenFunctions,'startup.m')); -0020 -0021 %Getting all the paths added to Matlab -0022 if ispc -0023 matlabPaths=regexp(path, ';', 'split')'; -0024 elseif isunix -0025 matlabPaths=regexp(path, ':', 'split')'; -0026 end -0027 -0028 hasConflicts=false; -0029 -0030 for i=1:numel(matlabPaths) -0031 if ~any(strfind(matlabPaths{i},ravenDir)) -0032 temp_res=dir([matlabPaths{i} '/*.m']); -0033 if ~isempty(temp_res) -0034 pathFunctions={temp_res.name}'; -0035 else -0036 pathFunctions=''; -0037 end -0038 if ~isempty(pathFunctions) && ~any(ismember('Contents.m',pathFunctions)) -0039 if any(ismember(ravenFunctions,pathFunctions)) -0040 fprintf('Not OK\n'); -0041 if sum(ismember(ravenFunctions,pathFunctions))>(numel(ravenFunctions)/4) -0042 EM='Multiple RAVEN versions detected in MATLAB path. Leave only one RAVEN version in MATLAB path and re-run checkInstallation\n'; -0043 dispEM(EM); -0044 else -0045 disp(['WARNING: Duplicate functions in ',matlabPaths{i},': ']); -0046 ovrlpFunctions=ravenFunctions(ismember(ravenFunctions,pathFunctions)); -0047 disp(ovrlpFunctions); -0048 hasConflicts=true; -0049 end -0050 end -0051 end -0052 end -0053 end -0054 -0055 if hasConflicts -0056 fprintf('It is strongly recommended to resolve conflicting functions as this may compromise RAVEN functionality\n'); +0009 ravenDir=findRAVENroot(); +0010 +0011 %Now getting all RAVEN functions recursively; +0012 temp_res1=dir([ravenDir '/*/*.m']); +0013 temp_res2=dir([ravenDir '/*/*/*.m']); +0014 +0015 ravenFunctions={temp_res1.name,temp_res2.name}'; +0016 %startup.m is not a normal function, any startup.m in the path should run +0017 %during startup, so duplicate use of this name is fine +0018 ravenFunctions=ravenFunctions(~ismember(ravenFunctions,'startup.m')); +0019 +0020 %Getting all the paths added to Matlab +0021 if ispc +0022 matlabPaths=regexp(path, ';', 'split')'; +0023 elseif isunix +0024 matlabPaths=regexp(path, ':', 'split')'; +0025 end +0026 +0027 hasConflicts=false; +0028 +0029 for i=1:numel(matlabPaths) +0030 if ~any(strfind(matlabPaths{i},ravenDir)) +0031 temp_res=dir([matlabPaths{i} '/*.m']); +0032 if ~isempty(temp_res) +0033 pathFunctions={temp_res.name}'; +0034 else +0035 pathFunctions=''; +0036 end +0037 if ~isempty(pathFunctions) && ~any(ismember('Contents.m',pathFunctions)) +0038 if any(ismember(ravenFunctions,pathFunctions)) +0039 fprintf('Not OK\n'); +0040 if sum(ismember(ravenFunctions,pathFunctions))>(numel(ravenFunctions)/4) +0041 EM='Multiple RAVEN versions detected in MATLAB path. Leave only one RAVEN version in MATLAB path and re-run checkInstallation\n'; +0042 dispEM(EM); +0043 else +0044 disp(['WARNING: Duplicate functions in ',matlabPaths{i},': ']); +0045 ovrlpFunctions=ravenFunctions(ismember(ravenFunctions,pathFunctions)); +0046 disp(ovrlpFunctions); +0047 hasConflicts=true; +0048 end +0049 end +0050 end +0051 end +0052 end +0053 +0054 if hasConflicts +0055 fprintf('Fail\n') +0056 fprintf(' It is strongly recommended to resolve conflicting functions as this may compromise RAVEN functionality\n'); 0057 else -0058 fprintf('OK\n'); +0058 fprintf('Pass\n'); 0059 end 0060 0061 end diff --git a/doc/installation/checkInstallation.html b/doc/installation/checkInstallation.html index a94a1a7b..230bec6d 100644 --- a/doc/installation/checkInstallation.html +++ b/doc/installation/checkInstallation.html @@ -52,7 +52,7 @@

    CROSS-REFERENCE INFORMATION ^
 
 <h2><a name=SUBFUNCTIONS ^

    +
  • function interpretResults(results)
  • function str = myStr(InputStr,len)
  • SOURCE CODE ^

    0001 function checkInstallation(develMode)
    @@ -81,150 +81,221 @@ 

    SOURCE CODE ^'-completenames'); 0025 [ravenDir,~,~]=fileparts(fileparts(ST(I).file)); 0026 -0027 %Print the RAVEN version if it is not the development version -0028 if exist(fullfile(ravenDir,'version.txt'), 'file') == 2 -0029 fprintf(['\n*** THE RAVEN TOOLBOX v.' fgetl(fopen(fullfile(ravenDir,'version.txt'))) ' ***\n\n']); -0030 fclose('all'); -0031 else -0032 fprintf('\n*** THE RAVEN TOOLBOX - DEVELOPMENT VERSION ***\n\n'); -0033 end -0034 -0035 fprintf(['MATLAB R' version('-release') ' detected\n\n']); -0036 -0037 fprintf('Checking if RAVEN is on the MATLAB path...\t\t\t\t\t\t\t\t\t'); -0038 if ismember(ravenDir,paths) -0039 fprintf('OK\n'); -0040 else -0041 fprintf('OK (just added)\n'); -0042 subpath=regexp(genpath(ravenDir),pathsep,'split'); %List all subdirectories -0043 pathsToKeep=cellfun(@(x) isempty(strfind(x,'.git')),subpath) & cellfun(@(x) isempty(strfind(x,'doc')),subpath); -0044 addpath(strjoin(subpath(pathsToKeep),pathsep)); -0045 savepath -0046 end -0047 -0048 %Add the required classes to the static Java path if not already added -0049 addJavaPaths(); -0050 -0051 excelFile=fullfile(ravenDir,'tutorial','empty.xlsx'); -0052 xmlFile=fullfile(ravenDir,'tutorial','empty.xml'); -0053 matFile=fullfile(ravenDir,'tutorial','empty.mat'); -0054 -0055 %Check if it is possible to parse an Excel file -0056 fprintf('Checking if it is possible to parse a model in Microsoft Excel format...\t'); -0057 try -0058 importExcelModel(excelFile,false,false,true); -0059 fprintf('OK\n'); -0060 catch -0061 fprintf('Not OK\n'); -0062 end -0063 -0064 %Check if it is possible to import an SBML model using libSBML -0065 fprintf('Checking if it is possible to import an SBML model using libSBML...\t\t\t'); -0066 try -0067 importModel(xmlFile); -0068 try -0069 libSBMLver=OutputSBML; % Only works in libSBML 5.17.0+ -0070 fprintf('OK\n'); -0071 catch -0072 fprintf(['Not OK\n\n'... -0073 'An older libSBML version was found, update to version 5.17.0 or higher\n'... -0074 'for a significant improvement of model import\n\n']); -0075 end -0076 catch -0077 fprintf(['Not OK\nTo import SBML models, download libSBML from\n'... -0078 'http://sbml.org/Software/libSBML/Downloading_libSBML and add to MATLAB path\n']); -0079 end -0080 -0081 %Define values for keepSolver and workingSolvers, needed for solver -0082 %functionality check -0083 keepSolver=false; -0084 workingSolvers=''; -0085 %Get current solver. Set it to 'none', if it is not set -0086 if ~ispref('RAVEN','solver') -0087 fprintf('Solver found in preferences... NONE\n'); -0088 setRavenSolver('none'); -0089 curSolv=getpref('RAVEN','solver'); -0090 else -0091 curSolv=getpref('RAVEN','solver'); -0092 fprintf(['Solver found in preferences... ',curSolv,'\n']); -0093 end -0094 -0095 %Check if it is possible to solve an LP problem using different solvers -0096 solver={'gurobi','cobra'}; -0097 -0098 for i=1:numel(solver) -0099 fprintf(['Checking if it is possible to solve an LP problem using ',solver{i},'...\t\t\t']); -0100 try -0101 setRavenSolver(solver{i}); -0102 load(matFile); -0103 solveLP(emptyModel); -0104 workingSolvers=strcat(workingSolvers,';',solver{i}); -0105 fprintf('OK\n'); -0106 if strcmp(curSolv,solver{i}) -0107 keepSolver=true; -0108 end -0109 catch -0110 fprintf('Not OK\n'); -0111 end -0112 end -0113 -0114 if keepSolver -0115 %The solver set in curSolv is functional, so the settings are restored -0116 %to the ones which were set before running checkInstallation -0117 setRavenSolver(curSolv); -0118 fprintf(['Preferred solver... KEPT\nSolver saved as preference... ',curSolv,'\n\n']); -0119 elseif ~isempty(workingSolvers) -0120 %There are working solvers, but the none of them is the solver defined -0121 %by curSolv. The first working solver is therefore set as RAVEN solver -0122 workingSolvers=regexprep(workingSolvers,'^;',''); -0123 workingSolvers=regexprep(workingSolvers,';.+$',''); -0124 %Only one working solver should be left by now in workingSolvers -0125 setRavenSolver(workingSolvers); -0126 fprintf(['Preferred solver... NEW\nSolver saved as preference... ',workingSolvers,'\n\n']); -0127 else -0128 %No functional solvers were found, so the setting is restored back to -0129 %original -0130 setRavenSolver(curSolv); -0131 fprintf(['WARNING: No working solver was found!\n'... -0132 'Install the solver, set it using setRavenSolver(''solverName'') and run checkInstallation again\n'... -0133 'Available solverName options are ''gurobi'' and ''cobra''\n\n']); -0134 end -0135 -0136 fprintf('Checking essential binary executables:\n'); -0137 -0138 fprintf('\tBLAST+... '); -0139 res=runtests('blastPlusTests.m','OutputDetail',0); -0140 interpretResults(res); -0141 fprintf('\tDIAMOND... '); -0142 res=runtests('diamondTests.m','OutputDetail',0); -0143 interpretResults(res); -0144 fprintf('\tHMMER... '); -0145 res=runtests('hmmerTests.m','OutputDetail',0); -0146 interpretResults(res); -0147 -0148 if develMode -0149 fprintf('NOTE: Only fix these binaries if planning to use KEGG FTP dump files in getKEGGModelForOrganism\n'); -0150 fprintf('\tCD-HIT... '); -0151 res=runtests('cdhitTests.m','OutputDetail',0); -0152 interpretResults(res); -0153 fprintf('\tMAFFT... '); -0154 res=runtests('mafftTests.m','OutputDetail',0); -0155 interpretResults(res); -0156 end -0157 -0158 fprintf('Checking whether RAVEN functions are non-redundant across MATLAB path...\t'); -0159 checkFunctionUniqueness(); -0160 -0161 fprintf('\n*** checkInstallation complete ***\n\n'); -0162 end -0163 -0164 function interpretResults(results) -0165 if results.Failed==0 && results.Incomplete==0 -0166 fprintf('OK\n'); -0167 else -0168 fprintf('Not OK! Download/compile the binary and rerun checkInstallation\n'); -0169 end -0170 end

    +0027 fprintf('\n*** THE RAVEN TOOLBOX ***\n\n'); +0028 %Print the RAVEN version if it is not the development version +0029 fprintf([myStr(' > Checking RAVEN release:',40) '%f']) +0030 if exist(fullfile(ravenDir,'version.txt'), 'file') == 2 +0031 fprintf([fgetl(fopen(fullfile(ravenDir,'version.txt'))) '\n']); +0032 fclose('all'); +0033 else +0034 fprintf('DEVELOPMENT\n'); +0035 end +0036 fprintf([myStr(' > Checking MATLAB release:',40) '%f']) +0037 fprintf([version('-release') '\n']) +0038 fprintf([myStr(' > Set RAVEN in MATLAB path:',40) '%f']) +0039 subpath=regexp(genpath(ravenDir),pathsep,'split'); %List all subdirectories +0040 pathsToKeep=cellfun(@(x) isempty(strfind(x,'.git')),subpath) & cellfun(@(x) isempty(strfind(x,'doc')),subpath); +0041 addpath(strjoin(subpath(pathsToKeep),pathsep)); +0042 savepath +0043 fprintf('Pass\n'); +0044 +0045 %Check if it is possible to parse an Excel file +0046 fprintf('\n=== Model import and export ===\n'); +0047 fprintf([myStr(' > Add Java paths for Excel format:',40) '%f']) +0048 try +0049 %Add the required classes to the static Java path if not already added +0050 addJavaPaths(); +0051 fprintf('Pass\n') +0052 catch +0053 fprintf('Fail\n') +0054 end +0055 fprintf([myStr(' > Check libSBML version:',40) '%f']) +0056 try +0057 evalc('importModel(fullfile(ravenDir,''tutorial'',''empty.xml''))'); +0058 try +0059 libSBMLver=OutputSBML; % Only works in libSBML 5.17.0+ +0060 fprintf([libSBMLver.libSBML_version_string '\n']); +0061 catch +0062 fprintf('Fail\n') +0063 fprintf(' An older libSBML version was found, update to version 5.17.0 or higher for a significant improvement of model import\n'); +0064 end +0065 catch +0066 fprintf('Fail\n') +0067 fprintf(' Download libSBML from http://sbml.org/Software/libSBML/Downloading_libSBML and add to MATLAB path\n'); +0068 end +0069 fprintf(' > Checking model import and export:\n') +0070 res=runtests('importExportTests.m','OutputDetail',0); +0071 +0072 fprintf([myStr(' > Import Excel format:',40) '%f']) +0073 if res(1).Passed == 1 +0074 fprintf('Pass\n') +0075 else +0076 fprintf('Fail\n') +0077 end +0078 +0079 fprintf([myStr(' > Export Excel format:',40) '%f']) +0080 if res(3).Passed == 1 +0081 fprintf('Pass\n') +0082 else +0083 fprintf('Fail\n') +0084 end +0085 +0086 fprintf([myStr(' > Import SBML format:',40) '%f']) +0087 if res(2).Passed == 1 +0088 fprintf('Pass\n') +0089 else +0090 fprintf('Fail\n') +0091 end +0092 +0093 fprintf([myStr(' > Export SBML format:',40) '%f']) +0094 if res(4).Passed == 1 +0095 fprintf('Pass\n') +0096 else +0097 fprintf('Fail\n') +0098 end +0099 +0100 if res(1).Passed~=1 && res(3).Passed~=1 && exist('vaderSentimentScores.m')==2 +0101 fprintf([' > MATLAB Text Analytics Toolbox found. This should be\n'... +0102 ' uninstalled if you want to read/write Excel files.\n'... +0103 ' See RAVEN GitHub Issues page for instructions.\n']) +0104 end +0105 +0106 %Check if it is possible to import an YAML model +0107 % fprintf(' > Checking import of model in YAML format:\t\t\t'); +0108 % try +0109 % readYaml(ymlFile,true); +0110 % fprintf('Pass\n'); +0111 % catch +0112 % fprintf('Fail\n'); +0113 % end +0114 +0115 fprintf('\n=== Model solvers ===\n'); +0116 +0117 %Get current solver. Set it to 'none', if it is not set +0118 fprintf(' > Checking for functional LP solvers:\n') +0119 res=runtests('solverTests.m','OutputDetail',0); +0120 +0121 fprintf([myStr(' > glpk:',40) '%f']) +0122 if res(1).Passed == 1 +0123 fprintf('Pass\n') +0124 else +0125 fprintf('Fail\n') +0126 end +0127 +0128 fprintf([myStr(' > gurobi:',40) '%f']) +0129 if res(2).Passed == 1 +0130 fprintf('Pass\n') +0131 else +0132 fprintf('Fail\n') +0133 end +0134 +0135 fprintf([myStr(' > cobra:',40) '%f']) +0136 if res(3).Passed == 1 +0137 fprintf('Pass\n') +0138 else +0139 fprintf('Fail\n') +0140 end +0141 +0142 fprintf(' > Checking for functional MILP solvers:\n') +0143 res=runtests('fillGapsSmallTests.m','OutputDetail',0); +0144 +0145 fprintf([myStr(' > glpk:',40) '%f']) +0146 if res(1).Passed == 1 +0147 fprintf('Pass\n') +0148 else +0149 fprintf('Fail\n') +0150 end +0151 +0152 fprintf([myStr(' > gurobi:',40) '%f']) +0153 if res(2).Passed == 1 +0154 fprintf('Pass\n') +0155 else +0156 fprintf('Fail\n') +0157 end +0158 +0159 fprintf([myStr(' > cobra:',40) '%f']) +0160 if res(3).Passed == 1 +0161 fprintf('Pass\n') +0162 else +0163 fprintf('Fail\n') +0164 end +0165 +0166 fprintf([myStr(' > Set RAVEN solver:',40) '%f']) +0167 try +0168 oldSolver=getpref('RAVEN','solver'); +0169 solverIdx=find(strcmp(oldSolver,{'glpk','gurobi','cobra'})); +0170 catch +0171 solverIdx=0; +0172 end +0173 % Do not change old solver if functional +0174 if solverIdx~=0 && res(solverIdx).Passed == 1 +0175 fprintf([oldSolver '\n']) +0176 % Order of preference: gurobi > glpk > cobra +0177 elseif res(2).Passed == 1 +0178 fprintf('gurobi\n') +0179 setRavenSolver('gurobi'); +0180 elseif res(1).Passed == 1 +0181 fprintf('glpk\n') +0182 setRavenSolver('glpk'); +0183 elseif res(3).Passed == 1 +0184 fprintf('cobra\n') +0185 setRavenSolver('cobra'); +0186 else +0187 fprintf('None, no functional solvers\n') +0188 fprintf(' The glpk should always be working, check your RAVEN installation to make sure all files are present\n') +0189 end +0190 +0191 fprintf('\n=== Essential binary executables ===\n'); +0192 fprintf([myStr(' > Checking BLAST+:',40) '%f']) +0193 res=runtests('blastPlusTests.m','OutputDetail',0); +0194 interpretResults(res); +0195 +0196 fprintf([myStr(' > Checking DIAMOND:',40) '%f']) +0197 res=runtests('diamondTests.m','OutputDetail',0); +0198 interpretResults(res); +0199 +0200 fprintf([myStr(' > Checking HMMER:',40) '%f']) +0201 res=runtests('hmmerTests.m','OutputDetail',0); +0202 interpretResults(res); +0203 +0204 if develMode +0205 fprintf('\n=== Development binary executables ===\n'); +0206 fprintf('NOTE: These binaries are only required when using KEGG FTP dump files in getKEGGModelForOrganism\n'); +0207 +0208 fprintf([myStr(' > Checking CD-HIT:',40) '%f']) +0209 res=runtests('cdhitTests.m','OutputDetail',0); +0210 interpretResults(res); +0211 +0212 fprintf([myStr(' > Checking MAFFT:',40) '%f']) +0213 res=runtests('mafftTests.m','OutputDetail',0); +0214 interpretResults(res); +0215 end +0216 +0217 fprintf('\n=== Compatibility ===\n'); +0218 fprintf([myStr(' > Checking function uniqueness:',40) '%f']) +0219 checkFunctionUniqueness(); +0220 +0221 fprintf('\n*** checkInstallation complete ***\n\n'); +0222 end +0223 +0224 function interpretResults(results) +0225 if results.Failed==0 && results.Incomplete==0 +0226 fprintf('Pass\n'); +0227 else +0228 fprintf('Fail\n') +0229 fprintf(' Download/compile the binary and rerun checkInstallation\n'); +0230 end +0231 end +0232 +0233 function str = myStr(InputStr,len) +0234 str=InputStr; +0235 lenDiff = len - length(str); +0236 if lenDiff < 0 +0237 warning('String too long'); +0238 else +0239 str = [str blanks(lenDiff)]; +0240 end +0241 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/SBMLFromExcel.html b/doc/io/SBMLFromExcel.html index 34b74dae..6254368a 100644 --- a/doc/io/SBMLFromExcel.html +++ b/doc/io/SBMLFromExcel.html @@ -76,18 +76,19 @@

    SOURCE CODE ^% 0017 % NOTE: This is just a wrapper function for importExcelModel, printModelStats 0018 % and exportModel. Use those functions directly for greater control. -0019 -0020 if nargin<3 -0021 toCOBRA=false; -0022 end -0023 if nargin<4 -0024 printWarnings=true; -0025 end -0026 -0027 model=importExcelModel(fileName,false,printWarnings); -0028 printModelStats(model,printWarnings,false); -0029 exportModel(model,outputFileName,toCOBRA,true); -0030 end +0019 fileName=char(fileName); +0020 outputFileName=char(outputFileName); +0021 if nargin<3 +0022 toCOBRA=false; +0023 end +0024 if nargin<4 +0025 printWarnings=true; +0026 end +0027 +0028 model=importExcelModel(fileName,false,printWarnings); +0029 printModelStats(model,printWarnings,false); +0030 exportModel(model,outputFileName,toCOBRA,true); +0031 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/addJavaPaths.html b/doc/io/addJavaPaths.html index 6bcc68f8..69eed9f6 100644 --- a/doc/io/addJavaPaths.html +++ b/doc/io/addJavaPaths.html @@ -52,26 +52,25 @@

    SOURCE CODE ^function addJavaPaths() 0007 %Get the path to Apache POI -0008 [ST, I]=dbstack('-completenames'); -0009 ravenPath=fileparts(fileparts(ST(I).file)); -0010 poiPATH=fullfile(ravenPath,'software','apache-poi'); -0011 -0012 toAdd={fullfile(poiPATH,'dom4j-1.6.1.jar'); -0013 fullfile(poiPATH,'poi-3.8-20120326.jar'); -0014 fullfile(poiPATH,'poi-ooxml-3.8-20120326.jar'); -0015 fullfile(poiPATH,'poi-ooxml-schemas-3.8-20120326.jar'); -0016 fullfile(poiPATH,'xmlbeans-2.3.0.jar'); -0017 fullfile(poiPATH,'stax-api-1.0.1.jar')}; -0018 -0019 existingPaths=javaclasspath(); -0020 -0021 %Add the paths that are not already present -0022 for i=1:numel(toAdd) -0023 if ~any(ismember(existingPaths,toAdd{i})) -0024 javaaddpath(toAdd{i}); -0025 end -0026 end -0027 end +0008 ravenPath=findRAVENroot(); +0009 poiPATH=fullfile(ravenPath,'software','apache-poi'); +0010 +0011 toAdd={fullfile(poiPATH,'dom4j-1.6.1.jar'); +0012 fullfile(poiPATH,'poi-3.8-20120326.jar'); +0013 fullfile(poiPATH,'poi-ooxml-3.8-20120326.jar'); +0014 fullfile(poiPATH,'poi-ooxml-schemas-3.8-20120326.jar'); +0015 fullfile(poiPATH,'xmlbeans-2.3.0.jar'); +0016 fullfile(poiPATH,'stax-api-1.0.1.jar')}; +0017 +0018 existingPaths=javaclasspath(); +0019 +0020 %Add the paths that are not already present +0021 for i=1:numel(toAdd) +0022 if ~any(ismember(existingPaths,toAdd{i})) +0023 javaaddpath(toAdd{i}); +0024 end +0025 end +0026 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/checkFileExistence.html b/doc/io/checkFileExistence.html index 7e61f5d9..41baecbe 100644 --- a/doc/io/checkFileExistence.html +++ b/doc/io/checkFileExistence.html @@ -24,7 +24,7 @@

    PURPOSE ^checkFileExistence

    SYNOPSIS ^

    -
    function files=checkFileExistence(files,fullOrTemp,allowSpace)
    +
    function files=checkFileExistence(files,fullOrTemp,allowSpace,checkExist)

    DESCRIPTION ^

     checkFileExistence
    @@ -42,13 +42,17 @@ 

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    @@ -57,13 +61,13 @@

    CROSS-REFERENCE INFORMATION ^
 </ul>
 This function is called by:
 <ul style= -
  • getMD5Hash getMD5Hash
  • +
  • exportModel exportModel
  • getMD5Hash getMD5Hash
  • importModel importModel
  • SOURCE CODE ^

    -
    0001 function files=checkFileExistence(files,fullOrTemp,allowSpace)
    +
    0001 function files=checkFileExistence(files,fullOrTemp,allowSpace,checkExist)
     0002 % checkFileExistence
     0003 %   Check whether files exist. If no full path is given a file should be
     0004 %   located in the current folder, which by default is appended to the
    @@ -79,62 +83,70 @@ 

    SOURCE CODE ^% (opt, default 0) 0015 % allowSpace logical, whether 'space' character is allowed in the 0016 % path (opt, default true) -0017 % -0018 % Output: -0019 % files string or cell array of strings with updated paths if -0020 % fullOrTemp was set as 1 or 2, otherwise original paths -0021 % are returned -0022 % -0023 % Usage: files=checkFileExistence(files,fullOrTemp,allowSpace) -0024 -0025 if nargin<2 -0026 fullOrTemp = 0; -0027 end -0028 if nargin<3 -0029 allowSpace = true; -0030 end -0031 -0032 if isstr(files) -0033 oneFile=true; -0034 files={files}; -0035 else -0036 oneFile=false; +0017 % checkExist logical, whether file existence should really be +0018 % checked, as this function can also be used to return +0019 % the full path to a new file (opt, default true). Can +0020 % only be set to false if fullOrTemp is set to 1. +0021 % +0022 % Output: +0023 % files string or cell array of strings with updated paths if +0024 % fullOrTemp was set as 1 or 2, otherwise original paths +0025 % are returned +0026 % +0027 % Usage: files=checkFileExistence(files,fullOrTemp,allowSpace,checkExist) +0028 +0029 if nargin<2 +0030 fullOrTemp = 0; +0031 end +0032 if nargin<3 +0033 allowSpace = true; +0034 end +0035 if nargin<4 +0036 checkExist = true; 0037 end -0038 filesOriginal = files; -0039 -0040 %Make all full paths before check of file existence -0041 if ispc % full path starts like "C:\" -0042 inCurrDir = cellfun(@isempty,regexpi(files,'^[a-z]\:\\')); -0043 else %isunix full path starts like "/" -0044 inCurrDir = cellfun(@isempty,regexpi(files,'\/')); -0045 end -0046 files(inCurrDir) = fullfile(cd,files(inCurrDir)); -0047 -0048 %Check existence -0049 for i=1:numel(files) -0050 if ~exist(files{i},'file') -0051 error('File "%s" cannot be found\n',files{i}); -0052 elseif allowSpace == false & strfind(files{i},' ') -0053 error('File "%s" has an invalid space in the filename or path, please remove this before running this function\n',files{i}); -0054 end -0055 end -0056 -0057 switch fullOrTemp -0058 case 0 -0059 files = filesOriginal; -0060 case 1 -0061 % files already contains full path -0062 case 2 -0063 for i=1:numel(files) -0064 tmpFile=tempname; -0065 copyfile(files{i},tmpFile); -0066 files{i}=tmpFile; -0067 end -0068 end -0069 -0070 if oneFile == true -0071 files = files{1}; -0072 end

    +0038 files=convertCharArray(files); +0039 if numel(files)==1 +0040 oneFile=true; +0041 else +0042 oneFile=false; +0043 end +0044 filesOriginal = files; +0045 +0046 %Make all full paths before check of file existence +0047 if ispc % full path starts like "C:\" +0048 inCurrDir = cellfun(@isempty,regexpi(files,'^[a-z]\:\\')); +0049 else %isunix full path starts like "/" +0050 inCurrDir = cellfun(@isempty,regexpi(files,'\/')); +0051 end +0052 files(inCurrDir) = fullfile(cd,files(inCurrDir)); +0053 +0054 %Check existence +0055 if checkExist +0056 for i=1:numel(files) +0057 if ~exist(files{i},'file') +0058 error('File "%s" cannot be found\n',files{i}); +0059 elseif allowSpace == false & strfind(files{i},' ') +0060 error('File "%s" has an invalid space in the filename or path, please remove this before running this function\n',files{i}); +0061 end +0062 end +0063 end +0064 +0065 switch fullOrTemp +0066 case 0 +0067 files = filesOriginal; +0068 case 1 +0069 % files already contains full path +0070 case 2 +0071 for i=1:numel(files) +0072 tmpFile=tempname; +0073 copyfile(files{i},tmpFile); +0074 files{i}=tmpFile; +0075 end +0076 end +0077 +0078 if oneFile == true +0079 files = files{1}; +0080 end

    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/exportForGit.html b/doc/io/exportForGit.html index 43f5ef74..b1bc59f7 100644 --- a/doc/io/exportForGit.html +++ b/doc/io/exportForGit.html @@ -24,7 +24,7 @@

    PURPOSE ^exportForGit

    SYNOPSIS ^

    -
    function out=exportForGit(model,prefix,path,formats,mainBranchFlag,subDirs)
    +
    function out=exportForGit(model,prefix,path,formats,mainBranchFlag,subDirs,cobraText)

    DESCRIPTION ^

     exportForGit
    @@ -41,7 +41,7 @@ 

    DESCRIPTION ^DESCRIPTION ^CROSS-REFERENCE INFORMATION ^
 
 
 <h2><a name=SOURCE CODE ^

    -
    0001 function out=exportForGit(model,prefix,path,formats,mainBranchFlag,subDirs)
    +
    0001 function out=exportForGit(model,prefix,path,formats,mainBranchFlag,subDirs,cobraText)
     0002 % exportForGit
     0003 %   Generates a directory structure and populates this with model files, ready
     0004 %   to be commited to a Git(Hub) maintained model repository. Writes the model
    @@ -80,7 +84,7 @@ 

    SOURCE CODE ^% formats cell array of strings specifying in what file formats 0014 % the model should be exported (opt, default to all 0015 % formats as {'mat', 'txt', 'xlsx', 'xml', 'yml'}) -0016 % mainBranchFlag logical, if true, function will error if RAVEN (and +0016 % mainBranchFlag logical, if true, function will error if RAVEN (and 0017 % COBRA if detected) is/are not on the main branch. 0018 % (opt, default false) 0019 % subDirs logical, whether model files for each file format @@ -88,119 +92,137 @@

    SOURCE CODE ^% 'model' as parent directory, in accordance to the 0022 % standard-GEM repository format. If false, all files 0023 % are stored in the same folder. (opt, default true) -0024 % -0025 % Usage: exportForGit(model,prefix,path,formats,mainBranchFlag) -0026 if nargin<6 -0027 subDirs=true; -0028 end -0029 if nargin<5 -0030 mainBranchFlag=false; -0031 end -0032 if nargin<4 || isempty(formats) -0033 formats={'mat', 'txt', 'xlsx', 'xml', 'yml'}; -0034 end -0035 if ischar(formats) -0036 formats={formats}; -0037 end -0038 if any(~ismember(formats, {'mat', 'txt', 'xlsx', 'xml', 'yml'})) -0039 EM='Unknown file format defined. Only mat, txt, xlsx, xml and yml are allowed file formats.'; -0040 error(EM) -0041 end -0042 if nargin<3 -0043 path='.'; -0044 end -0045 if nargin<2 -0046 prefix='model'; +0024 % cobraText logical, whether the txt file should be in COBRA +0025 % Toolbox format using metabolite IDs, instead of +0026 % metabolite names and compartments. (opt, default +0027 % false) +0028 % +0029 % Usage: exportForGit(model,prefix,path,formats,mainBranchFlag) +0030 if nargin<7 +0031 cobraText=false; +0032 end +0033 if nargin<6 +0034 subDirs=true; +0035 end +0036 if nargin<5 +0037 mainBranchFlag=false; +0038 end +0039 if nargin<4 || isempty(formats) +0040 formats={'mat', 'txt', 'xlsx', 'xml', 'yml'}; +0041 else +0042 formats=convertCharArray(formats); +0043 end +0044 if any(~ismember(formats, {'mat', 'txt', 'xlsx', 'xml', 'yml'})) +0045 EM='Unknown file format defined. Only mat, txt, xlsx, xml and yml are allowed file formats.'; +0046 error(EM) 0047 end -0048 -0049 %Sort reactions, metabolites and genes alphabetically -0050 model=sortIdentifiers(model); -0051 -0052 %Get versions or commits of toolboxes: -0053 RAVENver = getToolboxVersion('RAVEN','ravenCobraWrapper.m',mainBranchFlag); -0054 COBRAver = getToolboxVersion('COBRA','initCobraToolbox.m',mainBranchFlag); -0055 -0056 %Retrieve libSBML version: -0057 try % 5.17.0 and newer -0058 libSBMLver=OutputSBML; -0059 libSBMLver=libSBMLver.libSBML_version_string; -0060 catch % before 5.17.0 -0061 fid = fopen('tempModelForLibSBMLversion.xml','w+'); -0062 fclose(fid); -0063 evalc('[~,~,libSBMLver]=TranslateSBML(''tempModelForLibSBMLversion.xml'',0,0)'); -0064 libSBMLver=libSBMLver.libSBML_version_string; -0065 delete('tempModelForLibSBMLversion.xml'); -0066 end -0067 -0068 % Make models folder, no warnings if folder already exists -0069 if subDirs -0070 path=fullfile(path,'model'); -0071 filePath=strcat(path,filesep,{'txt','yml','mat','xlsx','xml'}); -0072 [~,~,~]=mkdir(path); -0073 for i = 1:length(formats) -0074 [~,~,~]=mkdir(fullfile(path,formats{i})); -0075 end -0076 else -0077 filePath=cell(1,5); filePath(:)={path}; +0048 if nargin<3 +0049 path='.'; +0050 else +0051 path=char(path); +0052 end +0053 if nargin<2 +0054 prefix='model'; +0055 else +0056 prefix=char(prefix); +0057 end +0058 +0059 %Sort reactions, metabolites and genes alphabetically +0060 model=sortIdentifiers(model); +0061 +0062 %Get versions or commits of toolboxes: +0063 RAVENver = getToolboxVersion('RAVEN','ravenCobraWrapper.m',mainBranchFlag); +0064 COBRAver = getToolboxVersion('COBRA','initCobraToolbox.m',mainBranchFlag); +0065 +0066 %Retrieve libSBML version: +0067 [ravenDir,prevDir]=findRAVENroot(); +0068 cd(fullfile(ravenDir,'software','libSBML')); +0069 try % 5.17.0 and newer +0070 libSBMLver=OutputSBML; +0071 libSBMLver=libSBMLver.libSBML_version_string; +0072 catch % before 5.17.0 +0073 fid = fopen('tempModelForLibSBMLversion.xml','w+'); +0074 fclose(fid); +0075 evalc('[~,~,libSBMLver]=TranslateSBML(''tempModelForLibSBMLversion.xml'',0,0)'); +0076 libSBMLver=libSBMLver.libSBML_version_string; +0077 delete('tempModelForLibSBMLversion.xml'); 0078 end -0079 +0079 cd(prevDir) 0080 -0081 % Write TXT format -0082 if ismember('txt', formats) -0083 fid=fopen(fullfile(filePath{1},strcat(prefix,'.txt')),'w'); -0084 eqns=constructEquations(model,model.rxns,false,false,false,true); -0085 eqns=strrep(eqns,' => ',' -> '); -0086 eqns=strrep(eqns,' <=> ',' <=> '); -0087 eqns=regexprep(eqns,'> $','>'); -0088 grRules=regexprep(model.grRules,'\((?!\()','( '); -0089 grRules=regexprep(grRules,'(?<!\))\)',' )'); -0090 fprintf(fid, 'Rxn name\tFormula\tGene-reaction association\tLB\tUB\tObjective\n'); -0091 for i = 1:numel(model.rxns) -0092 fprintf(fid, '%s\t', model.rxns{i}); -0093 fprintf(fid, '%s \t', eqns{i}); -0094 fprintf(fid, '%s\t', grRules{i}); -0095 fprintf(fid, '%6.2f\t%6.2f\t%6.2f\n', model.lb(i), model.ub(i), model.c(i)); -0096 end -0097 fclose(fid); -0098 end -0099 -0100 % Write YML format -0101 if ismember('yml', formats) -0102 writeYaml(model,fullfile(filePath{2},strcat(prefix,'.yml'))); -0103 end -0104 -0105 % Write MAT format -0106 if ismember('mat', formats) -0107 save(fullfile(filePath{3},strcat(prefix,'.mat')),'model'); -0108 end -0109 -0110 % Write XLSX format -0111 if ismember('xlsx', formats) -0112 exportToExcelFormat(model,fullfile(filePath{4},strcat(prefix,'.xlsx'))); -0113 end -0114 -0115 % Write XML format -0116 if ismember('xml', formats) -0117 exportModel(model,fullfile(filePath{5},strcat(prefix,'.xml'))); -0118 end -0119 -0120 %Save file with versions: -0121 fid = fopen(fullfile(path,'dependencies.txt'),'wt'); -0122 fprintf(fid,['MATLAB\t' version '\n']); -0123 fprintf(fid,['libSBML\t' libSBMLver '\n']); -0124 fprintf(fid,['RAVEN_toolbox\t' RAVENver '\n']); -0125 if ~isempty(COBRAver) -0126 fprintf(fid,['COBRA_toolbox\t' COBRAver '\n']); -0127 end -0128 if isfield(model,'modelVersion') -0129 fields = fieldnames(model.modelVersion); -0130 for i = 1:length(fields) -0131 value = model.modelVersion.(fields{i}); -0132 fprintf(fid,[fields{i} '\t' num2str(value) '\n']); -0133 end -0134 end -0135 fclose(fid); -0136 end

    +0081 % Make models folder, no warnings if folder already exists +0082 if subDirs +0083 path=fullfile(path,'model'); +0084 filePath=strcat(path,filesep,{'txt','yml','mat','xlsx','xml'}); +0085 [~,~,~]=mkdir(path); +0086 for i = 1:length(formats) +0087 [~,~,~]=mkdir(fullfile(path,formats{i})); +0088 end +0089 else +0090 filePath=cell(1,5); filePath(:)={path}; +0091 end +0092 +0093 +0094 % Write TXT format +0095 if ismember('txt', formats) +0096 fid=fopen(fullfile(filePath{1},strcat(prefix,'.txt')),'w'); +0097 if cobraText==true +0098 eqns=constructEquations(model,model.rxns,false,false,false); +0099 eqns=strrep(eqns,' => ',' -> '); +0100 eqns=strrep(eqns,' <=> ',' <=> '); +0101 eqns=regexprep(eqns,'> $','>'); +0102 grRules=regexprep(model.grRules,'\((?!\()','( '); +0103 grRules=regexprep(grRules,'(?<!\))\)',' )'); +0104 else +0105 eqns=constructEquations(model,model.rxns); +0106 grRules=model.grRules; +0107 end +0108 fprintf(fid, 'Rxn name\tFormula\tGene-reaction association\tLB\tUB\tObjective\n'); +0109 for i = 1:numel(model.rxns) +0110 fprintf(fid, '%s\t', model.rxns{i}); +0111 fprintf(fid, '%s \t', eqns{i}); +0112 fprintf(fid, '%s\t', grRules{i}); +0113 fprintf(fid, '%6.2f\t%6.2f\t%6.2f\n', model.lb(i), model.ub(i), model.c(i)); +0114 end +0115 fclose(fid); +0116 end +0117 +0118 % Write YML format +0119 if ismember('yml', formats) +0120 writeYaml(model,fullfile(filePath{2},strcat(prefix,'.yml'))); +0121 end +0122 +0123 % Write MAT format +0124 if ismember('mat', formats) +0125 save(fullfile(filePath{3},strcat(prefix,'.mat')),'model'); +0126 end +0127 +0128 % Write XLSX format +0129 if ismember('xlsx', formats) +0130 exportToExcelFormat(model,fullfile(filePath{4},strcat(prefix,'.xlsx'))); +0131 end +0132 +0133 % Write XML format +0134 if ismember('xml', formats) +0135 exportModel(model,fullfile(filePath{5},strcat(prefix,'.xml'))); +0136 end +0137 +0138 %Save file with versions: +0139 fid = fopen(fullfile(path,'dependencies.txt'),'wt'); +0140 fprintf(fid,['MATLAB\t' version '\n']); +0141 fprintf(fid,['libSBML\t' libSBMLver '\n']); +0142 fprintf(fid,['RAVEN_toolbox\t' RAVENver '\n']); +0143 if ~isempty(COBRAver) +0144 fprintf(fid,['COBRA_toolbox\t' COBRAver '\n']); +0145 end +0146 if isfield(model,'modelVersion') +0147 fields = fieldnames(model.modelVersion); +0148 for i = 1:length(fields) +0149 value = model.modelVersion.(fields{i}); +0150 fprintf(fid,[fields{i} '\t' num2str(value) '\n']); +0151 end +0152 end +0153 fclose(fid); +0154 end

    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/exportModel.html b/doc/io/exportModel.html index caa3f57b..dfd36cd4 100644 --- a/doc/io/exportModel.html +++ b/doc/io/exportModel.html @@ -48,10 +48,10 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • checkFileExistence checkFileExistence
  • sortIdentifiers exportModel
  • This function is called by: +
  • SBMLFromExcel SBMLFromExcel
  • exportForGit exportForGit
  • SUBFUNCTIONS ^

    @@ -76,780 +76,785 @@

    SOURCE CODE ^% identifiers (opt, default false) 0016 % 0017 % Usage: exportModel(model,fileName,exportGeneComplexes,supressWarnings,sortIds) -0018 if nargin<3 -0019 exportGeneComplexes=false; -0020 end -0021 if nargin<4 -0022 supressWarnings=false; -0023 end -0024 if nargin<5 -0025 sortIds=false; -0026 end -0027 if sortIds==true -0028 model=sortIdentifiers(model); -0029 end -0030 -0031 %If no subSystems are defined, then no need to use groups package -0032 if isfield(model,'subSystems') -0033 modelHasSubsystems=true; -0034 else -0035 modelHasSubsystems=false; -0036 end -0037 -0038 %The default SBML format settings, which are used as input for appropriate -0039 %libSBML functions to generate the blank SBML model structure before using -0040 %exporting in with OutputSBML to xml file -0041 sbmlLevel=3; -0042 sbmlVersion=1; -0043 sbmlPackages={'fbc'}; -0044 sbmlPackageVersions=2; -0045 if modelHasSubsystems -0046 sbmlPackages={sbmlPackages,'groups'}; -0047 sbmlPackageVersions=[sbmlPackageVersions,1]; -0048 end -0049 -0050 %Check if the "unconstrained" field is still present. This shows if -0051 %exchange metabolites have been removed -0052 if ~isfield(model,'unconstrained') -0053 model.unconstrained=zeros(numel(model.mets),1); -0054 end -0055 -0056 %If model id and name do not exist, make sure that default -0057 %strings are included -0058 if ~isfield(model,'id') -0059 fprintf('WARNING: The model is missing the "id" field. Uses "blankID". \n'); -0060 model.id='blankID'; -0061 end -0062 if ~isfield(model,'name') -0063 fprintf('WARNING: The model is missing the "name" field. Uses "blankName". \n'); -0064 model.name='blankName'; -0065 end -0066 -0067 %Check the model structure -0068 if supressWarnings==false -0069 checkModelStruct(model,false); -0070 end -0071 -0072 %Add several blank fields, if they do not exist already. This is to reduce -0073 %the number of conditions below -0074 if ~isfield(model,'compMiriams') -0075 model.compMiriams=cell(numel(model.comps),1); -0076 end -0077 if ~isfield(model,'inchis') -0078 model.inchis=cell(numel(model.mets),1); -0079 end -0080 if ~isfield(model,'metFormulas') -0081 model.metFormulas=cell(numel(model.mets),1); -0082 end -0083 if ~isfield(model,'metMiriams') -0084 model.metMiriams=cell(numel(model.mets),1); -0085 end -0086 if ~isfield(model,'geneMiriams') && isfield(model,'genes') -0087 model.geneMiriams=cell(numel(model.genes),1); -0088 end -0089 if ~isfield(model,'geneShortNames') && isfield(model,'genes') -0090 model.geneShortNames=cell(numel(model.genes),1); -0091 end -0092 if ~isfield(model,'subSystems') -0093 model.subSystems=cell(numel(model.rxns),1); -0094 end -0095 if ~isfield(model,'eccodes') -0096 model.eccodes=cell(numel(model.rxns),1); -0097 end -0098 if ~isfield(model,'rxnReferences') -0099 model.rxnReferences=cell(numel(model.rxns),1); -0100 end -0101 if ~isfield(model,'rxnConfidenceScores') -0102 model.rxnConfidenceScores=NaN(numel(model.rxns),1); -0103 end -0104 if ~isfield(model,'rxnNotes') -0105 model.rxnNotes=cell(numel(model.rxns),1); -0106 end -0107 if ~isfield(model,'rxnMiriams') -0108 model.rxnMiriams=cell(numel(model.rxns),1); -0109 end -0110 -0111 if sbmlLevel<3 -0112 %Check if genes have associated compartments -0113 if ~isfield(model,'geneComps') && isfield(model,'genes') -0114 if supressWarnings==false -0115 EM='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'; -0116 dispEM(EM,false); -0117 end -0118 model.geneComps=ones(numel(model.genes),1); -0119 end -0120 end -0121 -0122 %Convert ids to SBML-convenient format. This is to avoid the data loss when -0123 %unsupported characters are included in ids. Here we are using part from -0124 %convertSBMLID, originating from the COBRA Toolbox -0125 model.rxns=regexprep(model.rxns,'([^0-9_a-zA-Z])','__${num2str($1+0)}__'); -0126 model.mets=regexprep(model.mets,'([^0-9_a-zA-Z])','__${num2str($1+0)}__'); -0127 model.comps=regexprep(model.comps,'([^0-9_a-zA-Z])','__${num2str($1+0)}__'); -0128 if isfield(model,'genes') -0129 problemGenes=find(~cellfun('isempty',regexp(model.genes,'([^0-9_a-zA-Z])'))); -0130 originalGenes=model.genes(problemGenes); -0131 replacedGenes=regexprep(model.genes(problemGenes),'([^0-9_a-zA-Z])','__${num2str($1+0)}__'); -0132 model.genes(problemGenes)=replacedGenes; -0133 for i=1:numel(problemGenes) -0134 model.grRules = regexprep(model.grRules, ['(^|\s|\()' originalGenes{i} '($|\s|\))'], ['$1' replacedGenes{i} '$2']); -0135 end -0136 end -0137 -0138 %Generate an empty SBML structure -0139 modelSBML=getSBMLStructure(sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0140 modelSBML.metaid=model.id; -0141 modelSBML.id=model.id; -0142 modelSBML.name=model.name; -0143 -0144 if isfield(model,'annotation') -0145 if isfield(model.annotation,'note') -0146 modelSBML.notes=['<notes><body xmlns="http://www.w3.org/1999/xhtml"><p>',regexprep(model.annotation.note,'<p>|</p>',''),'</p></body></notes>']; -0147 end -0148 modelSBML.annotation=['<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="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/"><rdf:Description rdf:about="#meta_' model.id '">']; -0149 nameString=''; -0150 if isfield(model.annotation,'familyName') -0151 if ~isempty(model.annotation.familyName) -0152 nameString=['<vCard:Family>' model.annotation.familyName '</vCard:Family>']; -0153 end -0154 end -0155 if isfield(model.annotation,'givenName') -0156 if ~isempty(model.annotation.givenName) -0157 nameString=[nameString '<vCard:Given>' model.annotation.givenName '</vCard:Given>']; -0158 end -0159 end -0160 email=''; -0161 if isfield(model.annotation,'email') -0162 if ~isempty(model.annotation.email) -0163 email=['<vCard:EMAIL>' model.annotation.email '</vCard:EMAIL>']; -0164 end -0165 end -0166 org=''; -0167 if isfield(model.annotation,'organization') -0168 if ~isempty(model.annotation.organization) -0169 org=['<vCard:ORG rdf:parseType="Resource"><vCard:Orgname>' model.annotation.organization '</vCard:Orgname></vCard:ORG>']; -0170 end -0171 end -0172 if ~isempty(nameString) || ~isempty(email) || ~isempty(org) -0173 modelSBML.annotation=[modelSBML.annotation '<dc:creator><rdf:Bag><rdf:li rdf:parseType="Resource">']; -0174 if ~isempty(nameString) -0175 modelSBML.annotation=[modelSBML.annotation '<vCard:N rdf:parseType="Resource">' nameString '</vCard:N>']; -0176 end -0177 modelSBML.annotation=[modelSBML.annotation email org '</rdf:li></rdf:Bag></dc:creator>']; -0178 end -0179 if isfield(model,'annotation') -0180 if isfield(model.annotation,'taxonomy') -0181 modelSBML.annotation=[modelSBML.annotation '<bqbiol:is><rdf:Bag><rdf:li rdf:resource="https://identifiers.org/taxonomy/' regexprep(model.annotation.taxonomy,'taxonomy/','') '"/></rdf:Bag></bqbiol:is>']; -0182 end -0183 end -0184 modelSBML.annotation=[modelSBML.annotation '</rdf:Description></rdf:RDF></annotation>']; -0185 end -0186 -0187 %Prepare compartments -0188 for i=1:numel(model.comps) -0189 %Add the default values, as these will be the same in all entries -0190 if i==1 -0191 if isfield(modelSBML.compartment, 'sboTerm') -0192 modelSBML.compartment(i).sboTerm=290; -0193 end -0194 if isfield(modelSBML.compartment, 'spatialDimensions') -0195 modelSBML.compartment(i).spatialDimensions=3; -0196 end -0197 if isfield(modelSBML.compartment, 'size') -0198 modelSBML.compartment(i).size=1; -0199 end -0200 if isfield(modelSBML.compartment, 'constant') -0201 modelSBML.compartment(i).constant=1; -0202 end -0203 if isfield(modelSBML.compartment, 'isSetSize') -0204 modelSBML.compartment(i).isSetSize=1; -0205 end -0206 if isfield(modelSBML.compartment, 'isSetSpatialDimensions') -0207 modelSBML.compartment(i).isSetSpatialDimensions=1; -0208 end -0209 end -0210 %Copy the default values to the next entry as long as it is not the -0211 %last one -0212 if i<numel(model.comps) -0213 modelSBML.compartment(i+1)=modelSBML.compartment(i); -0214 end -0215 -0216 if isfield(modelSBML.compartment,'metaid') -0217 if regexp(model.comps{i},'^[^a-zA-Z_]') -0218 EM='The compartment IDs are in numeric format. For the compliance with SBML specifications, compartment IDs will be preceded with "c_" string'; -0219 dispEM(EM,false); -0220 model.comps(i)=strcat('c_',model.comps(i)); -0221 end -0222 modelSBML.compartment(i).metaid=model.comps{i}; -0223 end -0224 %Prepare Miriam strings -0225 if ~isempty(model.compMiriams{i}) -0226 [~,sbo_ind] = ismember('sbo',model.compMiriams{i}.name); -0227 if sbo_ind > 0 -0228 modelSBML.compartment(i).sboTerm=str2double(regexprep(model.compMiriams{i}.value{sbo_ind},'SBO:','','ignorecase')); -0229 % remove the SBO term from compMiriams so the information is -0230 % not duplicated in the "annotation" field later on -0231 model.compMiriams{i}.name(sbo_ind) = []; -0232 model.compMiriams{i}.value(sbo_ind) = []; -0233 end -0234 end -0235 if ~isempty(model.compMiriams{i}) && isfield(modelSBML.compartment(i),'annotation') -0236 modelSBML.compartment(i).annotation=['<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="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/"><rdf:Description rdf:about="#meta_' model.comps{i} '">']; -0237 modelSBML.compartment(i).annotation=[modelSBML.compartment(i).annotation '<bqbiol:is><rdf:Bag>']; -0238 modelSBML.compartment(i).annotation=[modelSBML.compartment(i).annotation getMiriam(model.compMiriams{i}) '</rdf:Bag></bqbiol:is></rdf:Description></rdf:RDF></annotation>']; -0239 end -0240 if isfield(modelSBML.compartment, 'name') -0241 modelSBML.compartment(i).name=model.compNames{i}; -0242 end -0243 if isfield(modelSBML.compartment, 'id') -0244 modelSBML.compartment(i).id=model.comps{i}; -0245 end -0246 -0247 end -0248 -0249 %Begin writing species -0250 for i=1:numel(model.mets) -0251 %Add the default values, as these will be the same in all entries -0252 if i==1 -0253 if isfield(modelSBML.species, 'sboTerm') -0254 modelSBML.species(i).sboTerm=247; -0255 end -0256 if isfield(modelSBML.species, 'initialAmount') -0257 modelSBML.species(i).initialAmount=1; -0258 end -0259 if isfield(modelSBML.species, 'initialConcentration') -0260 modelSBML.species(i).initialConcentration=0; -0261 end -0262 if isfield(modelSBML.species, 'isSetInitialAmount') -0263 modelSBML.species(i).isSetInitialAmount=1; -0264 end -0265 if isfield(modelSBML.species, 'isSetInitialConcentration') -0266 modelSBML.species(i).isSetInitialConcentration=1; -0267 end -0268 end -0269 %Copy the default values to the next entry as long as it is not the -0270 %last one -0271 if i<numel(model.mets) -0272 modelSBML.species(i+1)=modelSBML.species(i); -0273 end -0274 -0275 if isfield(modelSBML.species,'metaid') -0276 modelSBML.species(i).metaid=['M_' model.mets{i}]; -0277 end -0278 if isfield(modelSBML.species, 'name') -0279 modelSBML.species(i).name=model.metNames{i}; -0280 end -0281 if isfield(modelSBML.species, 'id') -0282 modelSBML.species(i).id=['M_' model.mets{i}]; -0283 end -0284 if isfield(modelSBML.species, 'compartment') -0285 modelSBML.species(i).compartment=model.comps{model.metComps(i)}; -0286 end -0287 if isfield(model,'unconstrained') -0288 if model.unconstrained(i) -0289 modelSBML.species(i).boundaryCondition=1; -0290 end -0291 end -0292 if isfield(modelSBML.species, 'fbc_charge') && isfield(model,'metCharges') -0293 if ~isnan(model.metCharges(i)) -0294 modelSBML.species(i).fbc_charge=model.metCharges(i); -0295 modelSBML.species(i).isSetfbc_charge=1; -0296 else -0297 modelSBML.species(i).isSetfbc_charge=0; -0298 end -0299 end -0300 if ~isempty(model.metMiriams{i}) -0301 [~,sbo_ind] = ismember('sbo',model.metMiriams{i}.name); -0302 if sbo_ind > 0 -0303 modelSBML.species(i).sboTerm=str2double(regexprep(model.metMiriams{i}.value{sbo_ind},'SBO:','','ignorecase')); -0304 % remove the SBO term from metMiriams so the information is -0305 % not duplicated in the "annotation" field later on -0306 model.metMiriams{i}.name(sbo_ind) = []; -0307 model.metMiriams{i}.value(sbo_ind) = []; -0308 end -0309 end -0310 if isfield(modelSBML.species,'annotation') -0311 if ~isempty(model.metMiriams{i}) || ~isempty(model.metFormulas{i}) -0312 hasInchi=false; -0313 if ~isempty(model.metFormulas{i}) -0314 %Only export formula if there is no InChI. This is because -0315 %the metFormulas field is populated by InChIs if available -0316 if ~isempty(model.inchis{i}) -0317 hasInchi=true; -0318 end -0319 if hasInchi==false -0320 modelSBML.species(i).fbc_chemicalFormula=model.metFormulas{i}; -0321 end -0322 end -0323 if ~isempty(model.metMiriams{i}) || hasInchi==true -0324 modelSBML.species(i).annotation=['<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="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/"><rdf:Description rdf:about="#meta_M_' model.mets{i} '">']; -0325 modelSBML.species(i).annotation=[modelSBML.species(i).annotation '<bqbiol:is><rdf:Bag>']; -0326 if ~isempty(model.metMiriams{i}) -0327 modelSBML.species(i).annotation=[modelSBML.species(i).annotation getMiriam(model.metMiriams{i})]; -0328 end -0329 if hasInchi==true -0330 modelSBML.species(i).annotation=[modelSBML.species(i).annotation '<rdf:li rdf:resource="https://identifiers.org/inchi/InChI=' regexprep(model.inchis{i},'^InChI=','') '"/>']; -0331 modelSBML.species(i).fbc_chemicalFormula=char(regexp(model.inchis{i}, '/(\w+)/', 'tokens', 'once')); -0332 end -0333 modelSBML.species(i).annotation=[modelSBML.species(i).annotation '</rdf:Bag></bqbiol:is></rdf:Description></rdf:RDF></annotation>']; -0334 end -0335 end -0336 end -0337 end -0338 -0339 if isfield(model,'genes') -0340 for i=1:numel(model.genes) -0341 %Add the default values, as these will be the same in all entries -0342 if i==1 -0343 if isfield(modelSBML.fbc_geneProduct, 'sboTerm') -0344 modelSBML.fbc_geneProduct(i).sboTerm=243; -0345 end -0346 end -0347 %Copy the default values to the next index as long as it is not the -0348 %last one -0349 if i<numel(model.genes) -0350 modelSBML.fbc_geneProduct(i+1)=modelSBML.fbc_geneProduct(i); -0351 end -0352 -0353 if isfield(modelSBML.fbc_geneProduct,'metaid') -0354 modelSBML.fbc_geneProduct(i).metaid=model.genes{i}; -0355 end -0356 if ~isempty(model.geneMiriams{i}) -0357 [~,sbo_ind] = ismember('sbo',model.geneMiriams{i}.name); -0358 if sbo_ind > 0 -0359 modelSBML.fbc_geneProduct(i).sboTerm=str2double(regexprep(model.geneMiriams{i}.value{sbo_ind},'SBO:','','ignorecase')); -0360 % remove the SBO term from compMiriams so the information is -0361 % not duplicated in the "annotation" field later on -0362 model.geneMiriams{i}.name(sbo_ind) = []; -0363 model.geneMiriams{i}.value(sbo_ind) = []; -0364 end -0365 end -0366 if ~isempty(model.geneMiriams{i}) && isfield(modelSBML.fbc_geneProduct(i),'annotation') -0367 modelSBML.fbc_geneProduct(i).annotation=['<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="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/"><rdf:Description rdf:about="#meta_' model.genes{i} '">']; -0368 modelSBML.fbc_geneProduct(i).annotation=[modelSBML.fbc_geneProduct(i).annotation '<bqbiol:is><rdf:Bag>']; -0369 modelSBML.fbc_geneProduct(i).annotation=[modelSBML.fbc_geneProduct(i).annotation getMiriam(model.geneMiriams{i}) '</rdf:Bag></bqbiol:is></rdf:Description></rdf:RDF></annotation>']; -0370 end -0371 if isfield(modelSBML.fbc_geneProduct, 'fbc_id') -0372 modelSBML.fbc_geneProduct(i).fbc_id=model.genes{i}; -0373 end -0374 if isfield(modelSBML.fbc_geneProduct, 'fbc_label') && isfield(model,'geneShortNames') -0375 if isempty(model.geneShortNames{i}) -0376 modelSBML.fbc_geneProduct(i).fbc_label=model.genes{i}; -0377 else -0378 modelSBML.fbc_geneProduct(i).fbc_label=model.geneShortNames{i}; -0379 end -0380 end -0381 end -0382 if exportGeneComplexes==true -0383 %Also add the complexes as genes. This is done by splitting grRules -0384 %on "or" and adding the ones which contain several genes -0385 geneComplexes={}; -0386 if isfield(model,'grRules') -0387 %Only grRules which contain " and " can be complexes -0388 uniqueRules=unique(model.grRules); -0389 I=cellfun(@any,strfind(uniqueRules,' and ')); -0390 uniqueRules(~I)=[]; -0391 uniqueRules=strrep(uniqueRules,'(',''); -0392 uniqueRules=strrep(uniqueRules,')',''); -0393 uniqueRules=strrep(uniqueRules,' and ',':'); -0394 for i=1:numel(uniqueRules) -0395 genes=regexp(uniqueRules(i),' or ','split'); -0396 genes=genes{1}(:); -0397 %Check which ones are complexes -0398 I=cellfun(@any,strfind(genes,':')); -0399 geneComplexes=[geneComplexes;genes(I)]; -0400 end -0401 end -0402 geneComplexes=unique(geneComplexes); -0403 if ~isempty(geneComplexes) -0404 %Then add them as genes. There is a possiblity that a complex -0405 %A&B is added as separate from B&A. This is not really an issue -0406 %so this is not dealt with -0407 for i=1:numel(geneComplexes) -0408 modelSBML.fbc_geneProduct(numel(model.genes)+i)=modelSBML.fbc_geneProduct(1); -0409 if isfield(modelSBML.fbc_geneProduct,'metaid') -0410 modelSBML.fbc_geneProduct(numel(model.genes)+i).metaid=geneComplexes{i}; -0411 end -0412 if isfield(modelSBML.fbc_geneProduct,'fbc_id') -0413 modelSBML.fbc_geneProduct(numel(model.genes)+i).fbc_id=geneComplexes{i}; -0414 else -0415 modelSBML.fbc_geneProduct(i).fbc_label=modelSBML.fbc_geneProduct(i).fbc_id; -0416 end -0417 end -0418 end -0419 end -0420 end -0421 -0422 %Generate a list of unique fbc_bound names -0423 totalValues=[model.lb; model.ub]; -0424 totalNames=cell(size(totalValues,1),1); -0425 -0426 listUniqueValues=unique(totalValues); -0427 -0428 for i=1:length(listUniqueValues) -0429 listUniqueNames{i,1}=['FB',num2str(i),'N',num2str(abs(round(listUniqueValues(i))))]; % create unique flux bound IDs. -0430 ind=find(ismember(totalValues,listUniqueValues(i))); -0431 totalNames(ind)=listUniqueNames(i,1); -0432 end -0433 -0434 for i=1:length(listUniqueNames) -0435 %Add the default values, as these will be the same in all entries -0436 if i==1 -0437 if isfield(modelSBML.parameter, 'constant') -0438 modelSBML.parameter(i).constant=1; -0439 end -0440 if isfield(modelSBML.parameter, 'isSetValue') -0441 modelSBML.parameter(i).isSetValue=1; -0442 end -0443 end -0444 %Copy the default values to the next index as long as it is not the -0445 %last one -0446 if i<numel(listUniqueNames) -0447 modelSBML.parameter(i+1)=modelSBML.parameter(i); -0448 end -0449 modelSBML.parameter(i).id=listUniqueNames{i}; -0450 modelSBML.parameter(i).value=listUniqueValues(i); -0451 end -0452 -0453 for i=1:numel(model.rxns) -0454 %Add the default values, as these will be the same in all entries -0455 if i==1 -0456 if isfield(modelSBML.reaction, 'sboTerm') -0457 modelSBML.reaction(i).sboTerm=176; -0458 end -0459 if isfield(modelSBML.reaction, 'isSetFast') -0460 modelSBML.reaction(i).isSetFast=1; -0461 end -0462 end -0463 %Copy the default values to the next index as long as it is not the -0464 %last one -0465 if i<numel(model.rxns) -0466 modelSBML.reaction(i+1)=modelSBML.reaction(i); -0467 end -0468 -0469 if isfield(modelSBML.reaction,'metaid') -0470 modelSBML.reaction(i).metaid=['R_' model.rxns{i}]; -0471 end -0472 -0473 %Export notes information -0474 if (~isnan(model.rxnConfidenceScores(i)) || ~isempty(model.rxnReferences{i}) || ~isempty(model.rxnNotes{i})) -0475 modelSBML.reaction(i).notes='<notes><body xmlns="http://www.w3.org/1999/xhtml">'; -0476 if ~isnan(model.rxnConfidenceScores(i)) -0477 modelSBML.reaction(i).notes=[modelSBML.reaction(i).notes '<p>Confidence Level: ' num2str(model.rxnConfidenceScores(i)) '</p>']; -0478 end -0479 if ~isempty(model.rxnReferences{i}) -0480 modelSBML.reaction(i).notes=[modelSBML.reaction(i).notes '<p>AUTHORS: ' model.rxnReferences{i} '</p>']; -0481 end -0482 if ~isempty(model.rxnNotes{i}) -0483 modelSBML.reaction(i).notes=[modelSBML.reaction(i).notes '<p>NOTES: ' model.rxnNotes{i} '</p>']; -0484 end -0485 modelSBML.reaction(i).notes=[modelSBML.reaction(i).notes '</body></notes>']; -0486 end -0487 -0488 % Export SBO terms from rxnMiriams -0489 if ~isempty(model.rxnMiriams{i}) -0490 [~,sbo_ind] = ismember('sbo',model.rxnMiriams{i}.name); -0491 if sbo_ind > 0 -0492 modelSBML.reaction(i).sboTerm=str2double(regexprep(model.rxnMiriams{i}.value{sbo_ind},'SBO:','','ignorecase')); -0493 % remove the SBO term from rxnMiriams so the information is not -0494 % duplicated in the "annotation" field later on -0495 model.rxnMiriams{i}.name(sbo_ind) = []; -0496 model.rxnMiriams{i}.value(sbo_ind) = []; -0497 end -0498 end -0499 -0500 %Export annotation information from rxnMiriams -0501 if (~isempty(model.rxnMiriams{i}) && isfield(modelSBML.reaction(i),'annotation')) || ~isempty(model.eccodes{i}) -0502 modelSBML.reaction(i).annotation=['<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="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/"><rdf:Description rdf:about="#meta_R_' model.rxns{i} '">']; -0503 modelSBML.reaction(i).annotation=[modelSBML.reaction(i).annotation '<bqbiol:is><rdf:Bag>']; -0504 if ~isempty(model.eccodes{i}) -0505 eccodes=regexp(model.eccodes{i},';','split'); -0506 for j=1:numel(eccodes) -0507 modelSBML.reaction(i).annotation=[modelSBML.reaction(i).annotation '<rdf:li rdf:resource="https://identifiers.org/ec-code/' regexprep(eccodes{j},'ec-code/|EC','') '"/>']; -0508 end -0509 end -0510 modelSBML.reaction(i).annotation=[modelSBML.reaction(i).annotation getMiriam(model.rxnMiriams{i}) '</rdf:Bag></bqbiol:is></rdf:Description></rdf:RDF></annotation>']; -0511 end -0512 -0513 if isfield(modelSBML.reaction, 'name') -0514 modelSBML.reaction(i).name=model.rxnNames{i}; -0515 end -0516 if isfield(modelSBML.reaction, 'id') -0517 modelSBML.reaction(i).id=['R_' model.rxns{i}]; -0518 end -0519 -0520 %Add the information about reactants and products -0521 involvedMets=addReactantsProducts(model,modelSBML,i); -0522 for j=1:numel(involvedMets.reactant) -0523 if j<numel(involvedMets.reactant) -0524 modelSBML.reaction(i).reactant(j+1)=modelSBML.reaction(i).reactant(j); -0525 end -0526 modelSBML.reaction(i).reactant(j).species=involvedMets.reactant(j).species; -0527 modelSBML.reaction(i).reactant(j).stoichiometry=involvedMets.reactant(j).stoichiometry; -0528 modelSBML.reaction(i).reactant(j).isSetStoichiometry=involvedMets.reactant(j).isSetStoichiometry; -0529 modelSBML.reaction(i).reactant(j).constant=involvedMets.reactant(j).constant; -0530 end -0531 if numel(involvedMets.reactant)==0 -0532 modelSBML.reaction(i).reactant=''; -0533 end -0534 for j=1:numel(involvedMets.product) -0535 if j<numel(involvedMets.product) -0536 modelSBML.reaction(i).product(j+1)=modelSBML.reaction(i).product(j); -0537 end -0538 modelSBML.reaction(i).product(j).species=involvedMets.product(j).species; -0539 modelSBML.reaction(i).product(j).stoichiometry=involvedMets.product(j).stoichiometry; -0540 modelSBML.reaction(i).product(j).isSetStoichiometry=involvedMets.product(j).isSetStoichiometry; -0541 modelSBML.reaction(i).product(j).constant=involvedMets.product(j).constant; -0542 end -0543 if numel(involvedMets.product)==0 -0544 modelSBML.reaction(i).product=''; -0545 end -0546 %Export reversibility information. Reactions are irreversible by -0547 %default -0548 if model.rev(i)==1 -0549 modelSBML.reaction(i).reversible=1; -0550 end -0551 if isfield(model, 'rxnComps') -0552 modelSBML.reaction(i).compartment=model.comps{model.rxnComps(i)}; -0553 end -0554 if isfield(model, 'grRules') -0555 modelSBML.reaction(i).fbc_geneProductAssociation.fbc_association.fbc_association=model.grRules{i}; -0556 end -0557 modelSBML.reaction(i).fbc_lowerFluxBound=totalNames{i}; -0558 modelSBML.reaction(i).fbc_upperFluxBound=totalNames{length(model.lb)+i}; -0559 end -0560 -0561 %Prepare subSystems Code taken from COBRA functions getModelSubSystems, -0562 %writeSBML, findRxnsFromSubSystem under GNU General Public License v3.0, -0563 %license file in readme/GPL.MD. Code modified for RAVEN -0564 if modelHasSubsystems -0565 modelSBML.groups_group.groups_kind = 'partonomy'; -0566 modelSBML.groups_group.sboTerm = 633; -0567 tmpStruct=modelSBML.groups_group; -0568 -0569 rxns=strcat('R_',model.rxns); -0570 if ~any(cellfun(@iscell,model.subSystems)) -0571 if ~any(~cellfun(@isempty,model.subSystems)) -0572 subSystems = {}; -0573 else -0574 subSystems = setdiff(model.subSystems,''); -0575 end -0576 else -0577 orderedSubs = cellfun(@(x) columnVector(x),model.subSystems,'UniformOUtput',false); -0578 subSystems = setdiff(vertcat(orderedSubs{:}),''); -0579 end -0580 if isempty(subSystems) -0581 subSystems = {}; -0582 end -0583 if ~isempty(subSystems) -0584 %Build the groups for the group package -0585 groupIDs = strcat('group',cellfun(@num2str, num2cell(1:length(subSystems)),'UniformOutput',false)); -0586 for i = 1:length(subSystems) -0587 cgroup = tmpStruct; -0588 if ~any(cellfun(@iscell,model.subSystems)) -0589 present = ismember(model.subSystems,subSystems{i}); -0590 else -0591 present = cellfun(@(x) any(ismember(x,subSystems{i})),model.subSystems); -0592 end -0593 groupMembers = rxns(present); -0594 for j = 1:numel(groupMembers) -0595 cMember = tmpStruct.groups_member; -0596 cMember.groups_idRef = groupMembers{j}; -0597 if j == 1 -0598 cgroup.groups_member = cMember; -0599 else -0600 cgroup.groups_member(j) = cMember; -0601 end -0602 end -0603 cgroup.groups_id = groupIDs{i}; -0604 cgroup.groups_name = subSystems{i}; -0605 if i == 1 -0606 modelSBML.groups_group = cgroup; -0607 else -0608 modelSBML.groups_group(i) = cgroup; -0609 end -0610 end -0611 end -0612 end -0613 -0614 %Prepare fbc_objective subfield -0615 -0616 modelSBML.fbc_objective.fbc_type='maximize'; -0617 modelSBML.fbc_objective.fbc_id='obj'; -0618 -0619 ind=find(model.c); -0620 -0621 if isempty(ind) -0622 modelSBML.fbc_objective.fbc_fluxObjective.fbc_coefficient=0; -0623 else -0624 for i=1:length(ind) -0625 %Copy the default values to the next index as long as it is not the -0626 %last one -0627 if i<numel(ind) -0628 modelSBML.reaction(i+1)=modelSBML.reaction(i); -0629 end -0630 values=model.c(model.c~=0); -0631 modelSBML.fbc_objective(i).fbc_fluxObjective.fbc_reaction=modelSBML.reaction(ind(i)).id; -0632 modelSBML.fbc_objective(i).fbc_fluxObjective.fbc_coefficient=values(i); -0633 modelSBML.fbc_objective(i).fbc_fluxObjective.isSetfbc_coefficient=1; -0634 end -0635 end -0636 -0637 modelSBML.fbc_activeObjective=modelSBML.fbc_objective.fbc_id; -0638 -0639 fbcStr=['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/fbc/version',num2str(sbmlPackageVersions(1))]; -0640 if modelHasSubsystems -0641 groupStr=['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/groups/version',num2str(sbmlPackageVersions(2))]; -0642 modelSBML.namespaces=struct('prefix',{'','fbc','groups'},... -0643 'uri',{['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/core'],... -0644 fbcStr,groupStr}); -0645 else -0646 modelSBML.namespaces=struct('prefix',{'','fbc'},... -0647 'uri',{['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/core'],... -0648 fbcStr}); -0649 end -0650 -0651 if sbmlPackageVersions(1) == 2 -0652 modelSBML.fbc_strict=1; -0653 end -0654 -0655 modelSBML.rule=[]; -0656 modelSBML.constraint=[]; -0657 -0658 OutputSBML(modelSBML,fileName,1,0,[1,0]); -0659 end -0660 -0661 -0662 function modelSBML=getSBMLStructure(sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions) -0663 %Returns the blank SBML model structure by using appropriate libSBML -0664 %functions. This creates structure by considering three levels +0018 fileName=char(fileName); +0019 if nargin<3 +0020 exportGeneComplexes=false; +0021 end +0022 if nargin<4 +0023 supressWarnings=false; +0024 end +0025 if nargin<5 +0026 sortIds=false; +0027 end +0028 if sortIds==true +0029 model=sortIdentifiers(model); +0030 end +0031 +0032 %If no subSystems are defined, then no need to use groups package +0033 if isfield(model,'subSystems') +0034 modelHasSubsystems=true; +0035 else +0036 modelHasSubsystems=false; +0037 end +0038 +0039 %The default SBML format settings, which are used as input for appropriate +0040 %libSBML functions to generate the blank SBML model structure before using +0041 %exporting in with OutputSBML to xml file +0042 sbmlLevel=3; +0043 sbmlVersion=1; +0044 sbmlPackages={'fbc'}; +0045 sbmlPackageVersions=2; +0046 if modelHasSubsystems +0047 sbmlPackages={sbmlPackages,'groups'}; +0048 sbmlPackageVersions=[sbmlPackageVersions,1]; +0049 end +0050 +0051 %Check if the "unconstrained" field is still present. This shows if +0052 %exchange metabolites have been removed +0053 if ~isfield(model,'unconstrained') +0054 model.unconstrained=zeros(numel(model.mets),1); +0055 end +0056 +0057 %If model id and name do not exist, make sure that default +0058 %strings are included +0059 if ~isfield(model,'id') +0060 fprintf('WARNING: The model is missing the "id" field. Uses "blankID". \n'); +0061 model.id='blankID'; +0062 end +0063 if ~isfield(model,'name') +0064 fprintf('WARNING: The model is missing the "name" field. Uses "blankName". \n'); +0065 model.name='blankName'; +0066 end +0067 +0068 %Check the model structure +0069 if supressWarnings==false +0070 checkModelStruct(model,false); +0071 end +0072 +0073 %Add several blank fields, if they do not exist already. This is to reduce +0074 %the number of conditions below +0075 if ~isfield(model,'compMiriams') +0076 model.compMiriams=cell(numel(model.comps),1); +0077 end +0078 if ~isfield(model,'inchis') +0079 model.inchis=cell(numel(model.mets),1); +0080 end +0081 if ~isfield(model,'metFormulas') +0082 model.metFormulas=cell(numel(model.mets),1); +0083 end +0084 if ~isfield(model,'metMiriams') +0085 model.metMiriams=cell(numel(model.mets),1); +0086 end +0087 if ~isfield(model,'geneMiriams') && isfield(model,'genes') +0088 model.geneMiriams=cell(numel(model.genes),1); +0089 end +0090 if ~isfield(model,'geneShortNames') && isfield(model,'genes') +0091 model.geneShortNames=cell(numel(model.genes),1); +0092 end +0093 if ~isfield(model,'subSystems') +0094 model.subSystems=cell(numel(model.rxns),1); +0095 end +0096 if ~isfield(model,'eccodes') +0097 model.eccodes=cell(numel(model.rxns),1); +0098 end +0099 if ~isfield(model,'rxnReferences') +0100 model.rxnReferences=cell(numel(model.rxns),1); +0101 end +0102 if ~isfield(model,'rxnConfidenceScores') +0103 model.rxnConfidenceScores=NaN(numel(model.rxns),1); +0104 end +0105 if ~isfield(model,'rxnNotes') +0106 model.rxnNotes=cell(numel(model.rxns),1); +0107 end +0108 if ~isfield(model,'rxnMiriams') +0109 model.rxnMiriams=cell(numel(model.rxns),1); +0110 end +0111 +0112 if sbmlLevel<3 +0113 %Check if genes have associated compartments +0114 if ~isfield(model,'geneComps') && isfield(model,'genes') +0115 if supressWarnings==false +0116 EM='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'; +0117 dispEM(EM,false); +0118 end +0119 model.geneComps=ones(numel(model.genes),1); +0120 end +0121 end +0122 +0123 %Convert ids to SBML-convenient format. This is to avoid the data loss when +0124 %unsupported characters are included in ids. Here we are using part from +0125 %convertSBMLID, originating from the COBRA Toolbox +0126 model.rxns=regexprep(model.rxns,'([^0-9_a-zA-Z])','__${num2str($1+0)}__'); +0127 model.mets=regexprep(model.mets,'([^0-9_a-zA-Z])','__${num2str($1+0)}__'); +0128 model.comps=regexprep(model.comps,'([^0-9_a-zA-Z])','__${num2str($1+0)}__'); +0129 if isfield(model,'genes') +0130 problemGenes=find(~cellfun('isempty',regexp(model.genes,'([^0-9_a-zA-Z])'))); +0131 originalGenes=model.genes(problemGenes); +0132 replacedGenes=regexprep(model.genes(problemGenes),'([^0-9_a-zA-Z])','__${num2str($1+0)}__'); +0133 model.genes(problemGenes)=replacedGenes; +0134 for i=1:numel(problemGenes) +0135 model.grRules = regexprep(model.grRules, ['(^|\s|\()' originalGenes{i} '($|\s|\))'], ['$1' replacedGenes{i} '$2']); +0136 end +0137 end +0138 +0139 %Generate an empty SBML structure +0140 modelSBML=getSBMLStructure(sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0141 modelSBML.metaid=model.id; +0142 modelSBML.id=model.id; +0143 modelSBML.name=model.name; +0144 +0145 if isfield(model,'annotation') +0146 if isfield(model.annotation,'note') +0147 modelSBML.notes=['<notes><body xmlns="http://www.w3.org/1999/xhtml"><p>',regexprep(model.annotation.note,'<p>|</p>',''),'</p></body></notes>']; +0148 end +0149 modelSBML.annotation=['<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="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/"><rdf:Description rdf:about="#meta_' model.id '">']; +0150 nameString=''; +0151 if isfield(model.annotation,'familyName') +0152 if ~isempty(model.annotation.familyName) +0153 nameString=['<vCard:Family>' model.annotation.familyName '</vCard:Family>']; +0154 end +0155 end +0156 if isfield(model.annotation,'givenName') +0157 if ~isempty(model.annotation.givenName) +0158 nameString=[nameString '<vCard:Given>' model.annotation.givenName '</vCard:Given>']; +0159 end +0160 end +0161 email=''; +0162 if isfield(model.annotation,'email') +0163 if ~isempty(model.annotation.email) +0164 email=['<vCard:EMAIL>' model.annotation.email '</vCard:EMAIL>']; +0165 end +0166 end +0167 org=''; +0168 if isfield(model.annotation,'organization') +0169 if ~isempty(model.annotation.organization) +0170 org=['<vCard:ORG rdf:parseType="Resource"><vCard:Orgname>' model.annotation.organization '</vCard:Orgname></vCard:ORG>']; +0171 end +0172 end +0173 if ~isempty(nameString) || ~isempty(email) || ~isempty(org) +0174 modelSBML.annotation=[modelSBML.annotation '<dc:creator><rdf:Bag><rdf:li rdf:parseType="Resource">']; +0175 if ~isempty(nameString) +0176 modelSBML.annotation=[modelSBML.annotation '<vCard:N rdf:parseType="Resource">' nameString '</vCard:N>']; +0177 end +0178 modelSBML.annotation=[modelSBML.annotation email org '</rdf:li></rdf:Bag></dc:creator>']; +0179 end +0180 if isfield(model,'annotation') +0181 if isfield(model.annotation,'taxonomy') +0182 modelSBML.annotation=[modelSBML.annotation '<bqbiol:is><rdf:Bag><rdf:li rdf:resource="https://identifiers.org/taxonomy/' regexprep(model.annotation.taxonomy,'taxonomy/','') '"/></rdf:Bag></bqbiol:is>']; +0183 end +0184 end +0185 modelSBML.annotation=[modelSBML.annotation '</rdf:Description></rdf:RDF></annotation>']; +0186 end +0187 +0188 %Prepare compartments +0189 for i=1:numel(model.comps) +0190 %Add the default values, as these will be the same in all entries +0191 if i==1 +0192 if isfield(modelSBML.compartment, 'sboTerm') +0193 modelSBML.compartment(i).sboTerm=290; +0194 end +0195 if isfield(modelSBML.compartment, 'spatialDimensions') +0196 modelSBML.compartment(i).spatialDimensions=3; +0197 end +0198 if isfield(modelSBML.compartment, 'size') +0199 modelSBML.compartment(i).size=1; +0200 end +0201 if isfield(modelSBML.compartment, 'constant') +0202 modelSBML.compartment(i).constant=1; +0203 end +0204 if isfield(modelSBML.compartment, 'isSetSize') +0205 modelSBML.compartment(i).isSetSize=1; +0206 end +0207 if isfield(modelSBML.compartment, 'isSetSpatialDimensions') +0208 modelSBML.compartment(i).isSetSpatialDimensions=1; +0209 end +0210 end +0211 %Copy the default values to the next entry as long as it is not the +0212 %last one +0213 if i<numel(model.comps) +0214 modelSBML.compartment(i+1)=modelSBML.compartment(i); +0215 end +0216 +0217 if isfield(modelSBML.compartment,'metaid') +0218 if regexp(model.comps{i},'^[^a-zA-Z_]') +0219 EM='The compartment IDs are in numeric format. For the compliance with SBML specifications, compartment IDs will be preceded with "c_" string'; +0220 dispEM(EM,false); +0221 model.comps(i)=strcat('c_',model.comps(i)); +0222 end +0223 modelSBML.compartment(i).metaid=model.comps{i}; +0224 end +0225 %Prepare Miriam strings +0226 if ~isempty(model.compMiriams{i}) +0227 [~,sbo_ind] = ismember('sbo',model.compMiriams{i}.name); +0228 if sbo_ind > 0 +0229 modelSBML.compartment(i).sboTerm=str2double(regexprep(model.compMiriams{i}.value{sbo_ind},'SBO:','','ignorecase')); +0230 % remove the SBO term from compMiriams so the information is +0231 % not duplicated in the "annotation" field later on +0232 model.compMiriams{i}.name(sbo_ind) = []; +0233 model.compMiriams{i}.value(sbo_ind) = []; +0234 end +0235 end +0236 if ~isempty(model.compMiriams{i}) && isfield(modelSBML.compartment(i),'annotation') +0237 modelSBML.compartment(i).annotation=['<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="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/"><rdf:Description rdf:about="#meta_' model.comps{i} '">']; +0238 modelSBML.compartment(i).annotation=[modelSBML.compartment(i).annotation '<bqbiol:is><rdf:Bag>']; +0239 modelSBML.compartment(i).annotation=[modelSBML.compartment(i).annotation getMiriam(model.compMiriams{i}) '</rdf:Bag></bqbiol:is></rdf:Description></rdf:RDF></annotation>']; +0240 end +0241 if isfield(modelSBML.compartment, 'name') +0242 modelSBML.compartment(i).name=model.compNames{i}; +0243 end +0244 if isfield(modelSBML.compartment, 'id') +0245 modelSBML.compartment(i).id=model.comps{i}; +0246 end +0247 +0248 end +0249 +0250 %Begin writing species +0251 for i=1:numel(model.mets) +0252 %Add the default values, as these will be the same in all entries +0253 if i==1 +0254 if isfield(modelSBML.species, 'sboTerm') +0255 modelSBML.species(i).sboTerm=247; +0256 end +0257 if isfield(modelSBML.species, 'initialAmount') +0258 modelSBML.species(i).initialAmount=1; +0259 end +0260 if isfield(modelSBML.species, 'initialConcentration') +0261 modelSBML.species(i).initialConcentration=0; +0262 end +0263 if isfield(modelSBML.species, 'isSetInitialAmount') +0264 modelSBML.species(i).isSetInitialAmount=1; +0265 end +0266 if isfield(modelSBML.species, 'isSetInitialConcentration') +0267 modelSBML.species(i).isSetInitialConcentration=1; +0268 end +0269 end +0270 %Copy the default values to the next entry as long as it is not the +0271 %last one +0272 if i<numel(model.mets) +0273 modelSBML.species(i+1)=modelSBML.species(i); +0274 end +0275 +0276 if isfield(modelSBML.species,'metaid') +0277 modelSBML.species(i).metaid=['M_' model.mets{i}]; +0278 end +0279 if isfield(modelSBML.species, 'name') +0280 modelSBML.species(i).name=model.metNames{i}; +0281 end +0282 if isfield(modelSBML.species, 'id') +0283 modelSBML.species(i).id=['M_' model.mets{i}]; +0284 end +0285 if isfield(modelSBML.species, 'compartment') +0286 modelSBML.species(i).compartment=model.comps{model.metComps(i)}; +0287 end +0288 if isfield(model,'unconstrained') +0289 if model.unconstrained(i) +0290 modelSBML.species(i).boundaryCondition=1; +0291 end +0292 end +0293 if isfield(modelSBML.species, 'fbc_charge') && isfield(model,'metCharges') +0294 if ~isnan(model.metCharges(i)) +0295 modelSBML.species(i).fbc_charge=model.metCharges(i); +0296 modelSBML.species(i).isSetfbc_charge=1; +0297 else +0298 modelSBML.species(i).isSetfbc_charge=0; +0299 end +0300 end +0301 if ~isempty(model.metMiriams{i}) +0302 [~,sbo_ind] = ismember('sbo',model.metMiriams{i}.name); +0303 if sbo_ind > 0 +0304 modelSBML.species(i).sboTerm=str2double(regexprep(model.metMiriams{i}.value{sbo_ind},'SBO:','','ignorecase')); +0305 % remove the SBO term from metMiriams so the information is +0306 % not duplicated in the "annotation" field later on +0307 model.metMiriams{i}.name(sbo_ind) = []; +0308 model.metMiriams{i}.value(sbo_ind) = []; +0309 end +0310 end +0311 if isfield(modelSBML.species,'annotation') +0312 if ~isempty(model.metMiriams{i}) || ~isempty(model.metFormulas{i}) +0313 hasInchi=false; +0314 if ~isempty(model.metFormulas{i}) +0315 %Only export formula if there is no InChI. This is because +0316 %the metFormulas field is populated by InChIs if available +0317 if ~isempty(model.inchis{i}) +0318 hasInchi=true; +0319 end +0320 if hasInchi==false +0321 modelSBML.species(i).fbc_chemicalFormula=model.metFormulas{i}; +0322 end +0323 end +0324 if ~isempty(model.metMiriams{i}) || hasInchi==true +0325 modelSBML.species(i).annotation=['<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="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/"><rdf:Description rdf:about="#meta_M_' model.mets{i} '">']; +0326 modelSBML.species(i).annotation=[modelSBML.species(i).annotation '<bqbiol:is><rdf:Bag>']; +0327 if ~isempty(model.metMiriams{i}) +0328 modelSBML.species(i).annotation=[modelSBML.species(i).annotation getMiriam(model.metMiriams{i})]; +0329 end +0330 if hasInchi==true +0331 modelSBML.species(i).annotation=[modelSBML.species(i).annotation '<rdf:li rdf:resource="https://identifiers.org/inchi/InChI=' regexprep(model.inchis{i},'^InChI=','') '"/>']; +0332 modelSBML.species(i).fbc_chemicalFormula=char(regexp(model.inchis{i}, '/(\w+)/', 'tokens', 'once')); +0333 end +0334 modelSBML.species(i).annotation=[modelSBML.species(i).annotation '</rdf:Bag></bqbiol:is></rdf:Description></rdf:RDF></annotation>']; +0335 end +0336 end +0337 end +0338 end +0339 +0340 if isfield(model,'genes') +0341 for i=1:numel(model.genes) +0342 %Add the default values, as these will be the same in all entries +0343 if i==1 +0344 if isfield(modelSBML.fbc_geneProduct, 'sboTerm') +0345 modelSBML.fbc_geneProduct(i).sboTerm=243; +0346 end +0347 end +0348 %Copy the default values to the next index as long as it is not the +0349 %last one +0350 if i<numel(model.genes) +0351 modelSBML.fbc_geneProduct(i+1)=modelSBML.fbc_geneProduct(i); +0352 end +0353 +0354 if isfield(modelSBML.fbc_geneProduct,'metaid') +0355 modelSBML.fbc_geneProduct(i).metaid=model.genes{i}; +0356 end +0357 if ~isempty(model.geneMiriams{i}) +0358 [~,sbo_ind] = ismember('sbo',model.geneMiriams{i}.name); +0359 if sbo_ind > 0 +0360 modelSBML.fbc_geneProduct(i).sboTerm=str2double(regexprep(model.geneMiriams{i}.value{sbo_ind},'SBO:','','ignorecase')); +0361 % remove the SBO term from compMiriams so the information is +0362 % not duplicated in the "annotation" field later on +0363 model.geneMiriams{i}.name(sbo_ind) = []; +0364 model.geneMiriams{i}.value(sbo_ind) = []; +0365 end +0366 end +0367 if ~isempty(model.geneMiriams{i}) && isfield(modelSBML.fbc_geneProduct(i),'annotation') +0368 modelSBML.fbc_geneProduct(i).annotation=['<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="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/"><rdf:Description rdf:about="#meta_' model.genes{i} '">']; +0369 modelSBML.fbc_geneProduct(i).annotation=[modelSBML.fbc_geneProduct(i).annotation '<bqbiol:is><rdf:Bag>']; +0370 modelSBML.fbc_geneProduct(i).annotation=[modelSBML.fbc_geneProduct(i).annotation getMiriam(model.geneMiriams{i}) '</rdf:Bag></bqbiol:is></rdf:Description></rdf:RDF></annotation>']; +0371 end +0372 if isfield(modelSBML.fbc_geneProduct, 'fbc_id') +0373 modelSBML.fbc_geneProduct(i).fbc_id=model.genes{i}; +0374 end +0375 if isfield(modelSBML.fbc_geneProduct, 'fbc_label') && isfield(model,'geneShortNames') +0376 if isempty(model.geneShortNames{i}) +0377 modelSBML.fbc_geneProduct(i).fbc_label=model.genes{i}; +0378 else +0379 modelSBML.fbc_geneProduct(i).fbc_label=model.geneShortNames{i}; +0380 end +0381 end +0382 end +0383 if exportGeneComplexes==true +0384 %Also add the complexes as genes. This is done by splitting grRules +0385 %on "or" and adding the ones which contain several genes +0386 geneComplexes={}; +0387 if isfield(model,'grRules') +0388 %Only grRules which contain " and " can be complexes +0389 uniqueRules=unique(model.grRules); +0390 I=cellfun(@any,strfind(uniqueRules,' and ')); +0391 uniqueRules(~I)=[]; +0392 uniqueRules=strrep(uniqueRules,'(',''); +0393 uniqueRules=strrep(uniqueRules,')',''); +0394 uniqueRules=strrep(uniqueRules,' and ',':'); +0395 for i=1:numel(uniqueRules) +0396 genes=regexp(uniqueRules(i),' or ','split'); +0397 genes=genes{1}(:); +0398 %Check which ones are complexes +0399 I=cellfun(@any,strfind(genes,':')); +0400 geneComplexes=[geneComplexes;genes(I)]; +0401 end +0402 end +0403 geneComplexes=unique(geneComplexes); +0404 if ~isempty(geneComplexes) +0405 %Then add them as genes. There is a possiblity that a complex +0406 %A&B is added as separate from B&A. This is not really an issue +0407 %so this is not dealt with +0408 for i=1:numel(geneComplexes) +0409 modelSBML.fbc_geneProduct(numel(model.genes)+i)=modelSBML.fbc_geneProduct(1); +0410 if isfield(modelSBML.fbc_geneProduct,'metaid') +0411 modelSBML.fbc_geneProduct(numel(model.genes)+i).metaid=geneComplexes{i}; +0412 end +0413 if isfield(modelSBML.fbc_geneProduct,'fbc_id') +0414 modelSBML.fbc_geneProduct(numel(model.genes)+i).fbc_id=geneComplexes{i}; +0415 else +0416 modelSBML.fbc_geneProduct(i).fbc_label=modelSBML.fbc_geneProduct(i).fbc_id; +0417 end +0418 end +0419 end +0420 end +0421 end +0422 +0423 %Generate a list of unique fbc_bound names +0424 totalValues=[model.lb; model.ub]; +0425 totalNames=cell(size(totalValues,1),1); +0426 +0427 listUniqueValues=unique(totalValues); +0428 +0429 for i=1:length(listUniqueValues) +0430 listUniqueNames{i,1}=['FB',num2str(i),'N',num2str(abs(round(listUniqueValues(i))))]; % create unique flux bound IDs. +0431 ind=find(ismember(totalValues,listUniqueValues(i))); +0432 totalNames(ind)=listUniqueNames(i,1); +0433 end +0434 +0435 for i=1:length(listUniqueNames) +0436 %Add the default values, as these will be the same in all entries +0437 if i==1 +0438 if isfield(modelSBML.parameter, 'constant') +0439 modelSBML.parameter(i).constant=1; +0440 end +0441 if isfield(modelSBML.parameter, 'isSetValue') +0442 modelSBML.parameter(i).isSetValue=1; +0443 end +0444 end +0445 %Copy the default values to the next index as long as it is not the +0446 %last one +0447 if i<numel(listUniqueNames) +0448 modelSBML.parameter(i+1)=modelSBML.parameter(i); +0449 end +0450 modelSBML.parameter(i).id=listUniqueNames{i}; +0451 modelSBML.parameter(i).value=listUniqueValues(i); +0452 end +0453 +0454 for i=1:numel(model.rxns) +0455 %Add the default values, as these will be the same in all entries +0456 if i==1 +0457 if isfield(modelSBML.reaction, 'sboTerm') +0458 modelSBML.reaction(i).sboTerm=176; +0459 end +0460 if isfield(modelSBML.reaction, 'isSetFast') +0461 modelSBML.reaction(i).isSetFast=1; +0462 end +0463 end +0464 %Copy the default values to the next index as long as it is not the +0465 %last one +0466 if i<numel(model.rxns) +0467 modelSBML.reaction(i+1)=modelSBML.reaction(i); +0468 end +0469 +0470 if isfield(modelSBML.reaction,'metaid') +0471 modelSBML.reaction(i).metaid=['R_' model.rxns{i}]; +0472 end +0473 +0474 %Export notes information +0475 if (~isnan(model.rxnConfidenceScores(i)) || ~isempty(model.rxnReferences{i}) || ~isempty(model.rxnNotes{i})) +0476 modelSBML.reaction(i).notes='<notes><body xmlns="http://www.w3.org/1999/xhtml">'; +0477 if ~isnan(model.rxnConfidenceScores(i)) +0478 modelSBML.reaction(i).notes=[modelSBML.reaction(i).notes '<p>Confidence Level: ' num2str(model.rxnConfidenceScores(i)) '</p>']; +0479 end +0480 if ~isempty(model.rxnReferences{i}) +0481 modelSBML.reaction(i).notes=[modelSBML.reaction(i).notes '<p>AUTHORS: ' model.rxnReferences{i} '</p>']; +0482 end +0483 if ~isempty(model.rxnNotes{i}) +0484 modelSBML.reaction(i).notes=[modelSBML.reaction(i).notes '<p>NOTES: ' model.rxnNotes{i} '</p>']; +0485 end +0486 modelSBML.reaction(i).notes=[modelSBML.reaction(i).notes '</body></notes>']; +0487 end +0488 +0489 % Export SBO terms from rxnMiriams +0490 if ~isempty(model.rxnMiriams{i}) +0491 [~,sbo_ind] = ismember('sbo',model.rxnMiriams{i}.name); +0492 if sbo_ind > 0 +0493 modelSBML.reaction(i).sboTerm=str2double(regexprep(model.rxnMiriams{i}.value{sbo_ind},'SBO:','','ignorecase')); +0494 % remove the SBO term from rxnMiriams so the information is not +0495 % duplicated in the "annotation" field later on +0496 model.rxnMiriams{i}.name(sbo_ind) = []; +0497 model.rxnMiriams{i}.value(sbo_ind) = []; +0498 end +0499 end +0500 +0501 %Export annotation information from rxnMiriams +0502 if (~isempty(model.rxnMiriams{i}) && isfield(modelSBML.reaction(i),'annotation')) || ~isempty(model.eccodes{i}) +0503 modelSBML.reaction(i).annotation=['<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="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/"><rdf:Description rdf:about="#meta_R_' model.rxns{i} '">']; +0504 modelSBML.reaction(i).annotation=[modelSBML.reaction(i).annotation '<bqbiol:is><rdf:Bag>']; +0505 if ~isempty(model.eccodes{i}) +0506 eccodes=regexp(model.eccodes{i},';','split'); +0507 for j=1:numel(eccodes) +0508 modelSBML.reaction(i).annotation=[modelSBML.reaction(i).annotation '<rdf:li rdf:resource="https://identifiers.org/ec-code/' regexprep(eccodes{j},'ec-code/|EC','') '"/>']; +0509 end +0510 end +0511 modelSBML.reaction(i).annotation=[modelSBML.reaction(i).annotation getMiriam(model.rxnMiriams{i}) '</rdf:Bag></bqbiol:is></rdf:Description></rdf:RDF></annotation>']; +0512 end +0513 +0514 if isfield(modelSBML.reaction, 'name') +0515 modelSBML.reaction(i).name=model.rxnNames{i}; +0516 end +0517 if isfield(modelSBML.reaction, 'id') +0518 modelSBML.reaction(i).id=['R_' model.rxns{i}]; +0519 end +0520 +0521 %Add the information about reactants and products +0522 involvedMets=addReactantsProducts(model,modelSBML,i); +0523 for j=1:numel(involvedMets.reactant) +0524 if j<numel(involvedMets.reactant) +0525 modelSBML.reaction(i).reactant(j+1)=modelSBML.reaction(i).reactant(j); +0526 end +0527 modelSBML.reaction(i).reactant(j).species=involvedMets.reactant(j).species; +0528 modelSBML.reaction(i).reactant(j).stoichiometry=involvedMets.reactant(j).stoichiometry; +0529 modelSBML.reaction(i).reactant(j).isSetStoichiometry=involvedMets.reactant(j).isSetStoichiometry; +0530 modelSBML.reaction(i).reactant(j).constant=involvedMets.reactant(j).constant; +0531 end +0532 if numel(involvedMets.reactant)==0 +0533 modelSBML.reaction(i).reactant=''; +0534 end +0535 for j=1:numel(involvedMets.product) +0536 if j<numel(involvedMets.product) +0537 modelSBML.reaction(i).product(j+1)=modelSBML.reaction(i).product(j); +0538 end +0539 modelSBML.reaction(i).product(j).species=involvedMets.product(j).species; +0540 modelSBML.reaction(i).product(j).stoichiometry=involvedMets.product(j).stoichiometry; +0541 modelSBML.reaction(i).product(j).isSetStoichiometry=involvedMets.product(j).isSetStoichiometry; +0542 modelSBML.reaction(i).product(j).constant=involvedMets.product(j).constant; +0543 end +0544 if numel(involvedMets.product)==0 +0545 modelSBML.reaction(i).product=''; +0546 end +0547 %Export reversibility information. Reactions are irreversible by +0548 %default +0549 if model.rev(i)==1 +0550 modelSBML.reaction(i).reversible=1; +0551 end +0552 if isfield(model, 'rxnComps') +0553 modelSBML.reaction(i).compartment=model.comps{model.rxnComps(i)}; +0554 end +0555 if isfield(model, 'grRules') +0556 modelSBML.reaction(i).fbc_geneProductAssociation.fbc_association.fbc_association=model.grRules{i}; +0557 end +0558 modelSBML.reaction(i).fbc_lowerFluxBound=totalNames{i}; +0559 modelSBML.reaction(i).fbc_upperFluxBound=totalNames{length(model.lb)+i}; +0560 end +0561 +0562 %Prepare subSystems Code taken from COBRA functions getModelSubSystems, +0563 %writeSBML, findRxnsFromSubSystem under GNU General Public License v3.0, +0564 %license file in readme/GPL.MD. Code modified for RAVEN +0565 if modelHasSubsystems +0566 modelSBML.groups_group.groups_kind = 'partonomy'; +0567 modelSBML.groups_group.sboTerm = 633; +0568 tmpStruct=modelSBML.groups_group; +0569 +0570 rxns=strcat('R_',model.rxns); +0571 if ~any(cellfun(@iscell,model.subSystems)) +0572 if ~any(~cellfun(@isempty,model.subSystems)) +0573 subSystems = {}; +0574 else +0575 subSystems = setdiff(model.subSystems,''); +0576 end +0577 else +0578 orderedSubs = cellfun(@(x) columnVector(x),model.subSystems,'UniformOUtput',false); +0579 subSystems = setdiff(vertcat(orderedSubs{:}),''); +0580 end +0581 if isempty(subSystems) +0582 subSystems = {}; +0583 end +0584 if ~isempty(subSystems) +0585 %Build the groups for the group package +0586 groupIDs = strcat('group',cellfun(@num2str, num2cell(1:length(subSystems)),'UniformOutput',false)); +0587 for i = 1:length(subSystems) +0588 cgroup = tmpStruct; +0589 if ~any(cellfun(@iscell,model.subSystems)) +0590 present = ismember(model.subSystems,subSystems{i}); +0591 else +0592 present = cellfun(@(x) any(ismember(x,subSystems{i})),model.subSystems); +0593 end +0594 groupMembers = rxns(present); +0595 for j = 1:numel(groupMembers) +0596 cMember = tmpStruct.groups_member; +0597 cMember.groups_idRef = groupMembers{j}; +0598 if j == 1 +0599 cgroup.groups_member = cMember; +0600 else +0601 cgroup.groups_member(j) = cMember; +0602 end +0603 end +0604 cgroup.groups_id = groupIDs{i}; +0605 cgroup.groups_name = subSystems{i}; +0606 if i == 1 +0607 modelSBML.groups_group = cgroup; +0608 else +0609 modelSBML.groups_group(i) = cgroup; +0610 end +0611 end +0612 end +0613 end +0614 +0615 %Prepare fbc_objective subfield +0616 +0617 modelSBML.fbc_objective.fbc_type='maximize'; +0618 modelSBML.fbc_objective.fbc_id='obj'; +0619 +0620 ind=find(model.c); +0621 +0622 if isempty(ind) +0623 modelSBML.fbc_objective.fbc_fluxObjective.fbc_coefficient=0; +0624 else +0625 for i=1:length(ind) +0626 %Copy the default values to the next index as long as it is not the +0627 %last one +0628 if i<numel(ind) +0629 modelSBML.reaction(i+1)=modelSBML.reaction(i); +0630 end +0631 values=model.c(model.c~=0); +0632 modelSBML.fbc_objective(i).fbc_fluxObjective.fbc_reaction=modelSBML.reaction(ind(i)).id; +0633 modelSBML.fbc_objective(i).fbc_fluxObjective.fbc_coefficient=values(i); +0634 modelSBML.fbc_objective(i).fbc_fluxObjective.isSetfbc_coefficient=1; +0635 end +0636 end +0637 +0638 modelSBML.fbc_activeObjective=modelSBML.fbc_objective.fbc_id; +0639 +0640 fbcStr=['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/fbc/version',num2str(sbmlPackageVersions(1))]; +0641 if modelHasSubsystems +0642 groupStr=['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/groups/version',num2str(sbmlPackageVersions(2))]; +0643 modelSBML.namespaces=struct('prefix',{'','fbc','groups'},... +0644 'uri',{['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/core'],... +0645 fbcStr,groupStr}); +0646 else +0647 modelSBML.namespaces=struct('prefix',{'','fbc'},... +0648 'uri',{['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/core'],... +0649 fbcStr}); +0650 end +0651 +0652 if sbmlPackageVersions(1) == 2 +0653 modelSBML.fbc_strict=1; +0654 end +0655 +0656 modelSBML.rule=[]; +0657 modelSBML.constraint=[]; +0658 +0659 [ravenDir,prevDir]=findRAVENroot(); +0660 fileName=checkFileExistence(fileName,1,true,false); +0661 cd(fullfile(ravenDir,'software','libSBML')); +0662 OutputSBML(modelSBML,fileName,1,0,[1,0]); +0663 cd(prevDir); +0664 end 0665 -0666 sbmlFieldNames=getStructureFieldnames('model',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0667 sbmlDefaultValues=getDefaultValues('model',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0668 -0669 for i=1:numel(sbmlFieldNames) -0670 modelSBML.(sbmlFieldNames{1,i})=sbmlDefaultValues{1,i}; -0671 sbmlSubfieldNames=getStructureFieldnames(sbmlFieldNames{1,i},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0672 sbmlSubfieldValues=getDefaultValues(sbmlFieldNames{1,i},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0673 if ~strcmp(sbmlFieldNames{1,i},'event') && ~strcmp(sbmlFieldNames{1,i},'functionDefinition') && ~strcmp(sbmlFieldNames{1,i},'initialAssignment') -0674 for j=1:numel(sbmlSubfieldNames) -0675 modelSBML.(sbmlFieldNames{1,i}).(sbmlSubfieldNames{1,j})=sbmlSubfieldValues{1,j}; -0676 sbmlSubsubfieldNames=getStructureFieldnames(sbmlSubfieldNames{1,j},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0677 sbmlSubsubfieldValues=getDefaultValues(sbmlSubfieldNames{1,j},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0678 if ~strcmp(sbmlSubfieldNames{1,j},'modifier') && ~strcmp(sbmlSubfieldNames{1,j},'kineticLaw') -0679 for k=1:numel(sbmlSubsubfieldNames) -0680 %'compartment' and 'species' fields are not supposed to -0681 %have their standalone structures if they are subfields -0682 %or subsubfields -0683 if ~strcmp(sbmlSubfieldNames{1,j},'compartment') && ~strcmp(sbmlSubfieldNames{1,j},'species') -0684 modelSBML.(sbmlFieldNames{1,i}).(sbmlSubfieldNames{1,j}).(sbmlSubsubfieldNames{1,k})=sbmlSubsubfieldValues{1,k}; -0685 end -0686 %If it is fbc_association in the third level, we need -0687 %to establish the fourth level, since libSBML requires -0688 %it -0689 if strcmp(sbmlSubsubfieldNames{1,k},'fbc_association') -0690 fbc_associationFieldNames=getStructureFieldnames('fbc_association',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0691 fbc_associationFieldValues=getDefaultValues('fbc_association',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0692 for l=1:numel(fbc_associationFieldNames) -0693 modelSBML.(sbmlFieldNames{1,i}).(sbmlSubfieldNames{1,j}).(sbmlSubsubfieldNames{1,k}).(fbc_associationFieldNames{1,l})=fbc_associationFieldValues{1,l}; -0694 end -0695 end -0696 end -0697 end -0698 end -0699 end -0700 if ~isstruct(modelSBML.(sbmlFieldNames{1,i})) -0701 modelSBML.(sbmlFieldNames{1,i})=sbmlDefaultValues{1,i}; -0702 end -0703 end -0704 -0705 modelSBML.unitDefinition.id='mmol_per_gDW_per_hr'; -0706 -0707 unitFieldNames=getStructureFieldnames('unit',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0708 unitDefaultValues=getDefaultValues('unit',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0666 +0667 function modelSBML=getSBMLStructure(sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions) +0668 %Returns the blank SBML model structure by using appropriate libSBML +0669 %functions. This creates structure by considering three levels +0670 +0671 sbmlFieldNames=getStructureFieldnames('model',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0672 sbmlDefaultValues=getDefaultValues('model',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0673 +0674 for i=1:numel(sbmlFieldNames) +0675 modelSBML.(sbmlFieldNames{1,i})=sbmlDefaultValues{1,i}; +0676 sbmlSubfieldNames=getStructureFieldnames(sbmlFieldNames{1,i},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0677 sbmlSubfieldValues=getDefaultValues(sbmlFieldNames{1,i},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0678 if ~strcmp(sbmlFieldNames{1,i},'event') && ~strcmp(sbmlFieldNames{1,i},'functionDefinition') && ~strcmp(sbmlFieldNames{1,i},'initialAssignment') +0679 for j=1:numel(sbmlSubfieldNames) +0680 modelSBML.(sbmlFieldNames{1,i}).(sbmlSubfieldNames{1,j})=sbmlSubfieldValues{1,j}; +0681 sbmlSubsubfieldNames=getStructureFieldnames(sbmlSubfieldNames{1,j},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0682 sbmlSubsubfieldValues=getDefaultValues(sbmlSubfieldNames{1,j},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0683 if ~strcmp(sbmlSubfieldNames{1,j},'modifier') && ~strcmp(sbmlSubfieldNames{1,j},'kineticLaw') +0684 for k=1:numel(sbmlSubsubfieldNames) +0685 %'compartment' and 'species' fields are not supposed to +0686 %have their standalone structures if they are subfields +0687 %or subsubfields +0688 if ~strcmp(sbmlSubfieldNames{1,j},'compartment') && ~strcmp(sbmlSubfieldNames{1,j},'species') +0689 modelSBML.(sbmlFieldNames{1,i}).(sbmlSubfieldNames{1,j}).(sbmlSubsubfieldNames{1,k})=sbmlSubsubfieldValues{1,k}; +0690 end +0691 %If it is fbc_association in the third level, we need +0692 %to establish the fourth level, since libSBML requires +0693 %it +0694 if strcmp(sbmlSubsubfieldNames{1,k},'fbc_association') +0695 fbc_associationFieldNames=getStructureFieldnames('fbc_association',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0696 fbc_associationFieldValues=getDefaultValues('fbc_association',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0697 for l=1:numel(fbc_associationFieldNames) +0698 modelSBML.(sbmlFieldNames{1,i}).(sbmlSubfieldNames{1,j}).(sbmlSubsubfieldNames{1,k}).(fbc_associationFieldNames{1,l})=fbc_associationFieldValues{1,l}; +0699 end +0700 end +0701 end +0702 end +0703 end +0704 end +0705 if ~isstruct(modelSBML.(sbmlFieldNames{1,i})) +0706 modelSBML.(sbmlFieldNames{1,i})=sbmlDefaultValues{1,i}; +0707 end +0708 end 0709 -0710 kinds={'mole','gram','second'}; -0711 exponents=[1 -1 -1]; -0712 scales=[-3 0 0]; -0713 multipliers=[1 1 1*60*60]; +0710 modelSBML.unitDefinition.id='mmol_per_gDW_per_hr'; +0711 +0712 unitFieldNames=getStructureFieldnames('unit',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0713 unitDefaultValues=getDefaultValues('unit',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); 0714 -0715 for i=1:numel(unitFieldNames) -0716 modelSBML.unitDefinition.unit(1).(unitFieldNames{1,i})=unitDefaultValues{1,i}; -0717 for j=1:3 -0718 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=unitDefaultValues{1,i}; -0719 if strcmp(unitFieldNames{1,i},'kind') -0720 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=kinds{j}; -0721 elseif strcmp(unitFieldNames{1,i},'exponent') -0722 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=exponents(j); -0723 elseif strcmp(unitFieldNames{1,i},'scale') -0724 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=scales(j); -0725 elseif strcmp(unitFieldNames{1,i},'multiplier') -0726 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=multipliers(j); -0727 end -0728 end -0729 end -0730 end -0731 -0732 function miriamString=getMiriam(miriamStruct) -0733 %Returns a string with list elements for a miriam structure ('<rdf:li -0734 %rdf:resource="https://identifiers.org/go/GO:0005739"/>' for example). This -0735 %is just to speed up things since this is done many times during the -0736 %exporting -0737 -0738 miriamString=''; -0739 if isfield(miriamStruct,'name') -0740 for i=1:numel(miriamStruct.name) -0741 miriamString=[miriamString '<rdf:li rdf:resource="https://identifiers.org/' miriamStruct.name{i} '/' miriamStruct.value{i} '"/>']; -0742 end -0743 end -0744 end -0745 -0746 function [tmp_Rxn]=addReactantsProducts(model,sbmlModel,i) -0747 %This function provides reactants and products for particular reaction. The -0748 %function was 'borrowed' from writeSBML in COBRA toolbox, lines 663-679 -0749 -0750 met_idx = find(model.S(:, i)); -0751 tmp_Rxn.product=[]; -0752 tmp_Rxn.reactant=[]; -0753 for j_met=1:size(met_idx,1) -0754 tmp_idx = met_idx(j_met,1); -0755 sbml_tmp_species_ref.species = sbmlModel.species(tmp_idx).id; -0756 met_stoich = model.S(tmp_idx, i); -0757 sbml_tmp_species_ref.stoichiometry = abs(met_stoich); -0758 sbml_tmp_species_ref.isSetStoichiometry=1; -0759 sbml_tmp_species_ref.constant=1; -0760 if (met_stoich > 0) -0761 tmp_Rxn.product = [ tmp_Rxn.product, sbml_tmp_species_ref ]; -0762 else -0763 tmp_Rxn.reactant = [ tmp_Rxn.reactant, sbml_tmp_species_ref]; -0764 end -0765 end -0766 end -0767 -0768 function vecT = columnVector(vec) -0769 % Code below taken from COBRA Toolbox under GNU General Public License v3.0 -0770 % license file in readme/GPL.MD. -0771 % -0772 % Converts a vector to a column vector -0773 % -0774 % USAGE: -0775 % -0776 % vecT = columnVector(vec) -0777 % -0778 % INPUT: -0779 % vec: a vector +0715 kinds={'mole','gram','second'}; +0716 exponents=[1 -1 -1]; +0717 scales=[-3 0 0]; +0718 multipliers=[1 1 1*60*60]; +0719 +0720 for i=1:numel(unitFieldNames) +0721 modelSBML.unitDefinition.unit(1).(unitFieldNames{1,i})=unitDefaultValues{1,i}; +0722 for j=1:3 +0723 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=unitDefaultValues{1,i}; +0724 if strcmp(unitFieldNames{1,i},'kind') +0725 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=kinds{j}; +0726 elseif strcmp(unitFieldNames{1,i},'exponent') +0727 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=exponents(j); +0728 elseif strcmp(unitFieldNames{1,i},'scale') +0729 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=scales(j); +0730 elseif strcmp(unitFieldNames{1,i},'multiplier') +0731 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=multipliers(j); +0732 end +0733 end +0734 end +0735 end +0736 +0737 function miriamString=getMiriam(miriamStruct) +0738 %Returns a string with list elements for a miriam structure ('<rdf:li +0739 %rdf:resource="https://identifiers.org/go/GO:0005739"/>' for example). This +0740 %is just to speed up things since this is done many times during the +0741 %exporting +0742 +0743 miriamString=''; +0744 if isfield(miriamStruct,'name') +0745 for i=1:numel(miriamStruct.name) +0746 miriamString=[miriamString '<rdf:li rdf:resource="https://identifiers.org/' miriamStruct.name{i} '/' miriamStruct.value{i} '"/>']; +0747 end +0748 end +0749 end +0750 +0751 function [tmp_Rxn]=addReactantsProducts(model,sbmlModel,i) +0752 %This function provides reactants and products for particular reaction. The +0753 %function was 'borrowed' from writeSBML in COBRA toolbox, lines 663-679 +0754 +0755 met_idx = find(model.S(:, i)); +0756 tmp_Rxn.product=[]; +0757 tmp_Rxn.reactant=[]; +0758 for j_met=1:size(met_idx,1) +0759 tmp_idx = met_idx(j_met,1); +0760 sbml_tmp_species_ref.species = sbmlModel.species(tmp_idx).id; +0761 met_stoich = model.S(tmp_idx, i); +0762 sbml_tmp_species_ref.stoichiometry = abs(met_stoich); +0763 sbml_tmp_species_ref.isSetStoichiometry=1; +0764 sbml_tmp_species_ref.constant=1; +0765 if (met_stoich > 0) +0766 tmp_Rxn.product = [ tmp_Rxn.product, sbml_tmp_species_ref ]; +0767 else +0768 tmp_Rxn.reactant = [ tmp_Rxn.reactant, sbml_tmp_species_ref]; +0769 end +0770 end +0771 end +0772 +0773 function vecT = columnVector(vec) +0774 % Code below taken from COBRA Toolbox under GNU General Public License v3.0 +0775 % license file in readme/GPL.MD. +0776 % +0777 % Converts a vector to a column vector +0778 % +0779 % USAGE: 0780 % -0781 % OUTPUT: -0782 % vecT: a column vector -0783 -0784 [n, m] = size(vec); -0785 -0786 if n < m -0787 vecT = vec'; -0788 else -0789 vecT = vec; -0790 end -0791 end

    +0781 % vecT = columnVector(vec) +0782 % +0783 % INPUT: +0784 % vec: a vector +0785 % +0786 % OUTPUT: +0787 % vecT: a column vector +0788 +0789 [n, m] = size(vec); +0790 +0791 if n < m +0792 vecT = vec'; +0793 else +0794 vecT = vec; +0795 end +0796 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/exportModelToSIF.html b/doc/io/exportModelToSIF.html index f0307ed4..dcbebc89 100644 --- a/doc/io/exportModelToSIF.html +++ b/doc/io/exportModelToSIF.html @@ -72,22 +72,22 @@

    SOURCE CODE ^% model.mets) 0015 % 0016 % Usage: exportModelToSIF(model,fileName,graphType,rxnLabels,metLabels) -0017 +0017 fileName=char(fileName); 0018 if nargin<3 0019 graphType='rc'; -0020 end -0021 -0022 if nargin<4 -0023 rxnLabels=model.rxns; -0024 end -0025 if nargin<5 -0026 metLabels=model.mets; -0027 end -0028 if isempty(rxnLabels) -0029 rxnLabels=model.rxns; -0030 end -0031 if isempty(metLabels) -0032 metLabels=model.mets; +0020 else +0021 graphType=char(graphType); +0022 end +0023 +0024 if nargin<4 || isempty(rxnLabels) +0025 rxnLabels=model.rxns; +0026 else +0027 rxnLabels=convertCharArray(rxnLabels); +0028 end +0029 if nargin<5 || isempty(metLabels) +0030 metLabels=model.mets; +0031 else +0032 metLabels=convertCharArray(metLabels); 0033 end 0034 0035 if ~strcmpi(graphType,'rc') && ~strcmpi(graphType,'rr') && ~strcmpi(graphType,'cc') diff --git a/doc/io/exportToExcelFormat.html b/doc/io/exportToExcelFormat.html index 35004a4e..e068c2a1 100644 --- a/doc/io/exportToExcelFormat.html +++ b/doc/io/exportToExcelFormat.html @@ -55,7 +55,7 @@

    CROSS-REFERENCE INFORMATION ^
 <li><a href=exportToTabDelimited exportToTabDelimited
  • loadWorkbook loadWorkbook
  • sortIdentifiers exportModel
  • writeSheet writeSheet
  • This function is called by: +
  • exportForGit exportForGit
  • @@ -82,367 +82,368 @@

    SOURCE CODE ^% checkModelStruct to identify problems in the model structure 0020 % 0021 % Usage: exportToExcelFormat(model,filename,sortIds) -0022 if nargin<3 -0023 sortIds=false; -0024 end -0025 if sortIds==true -0026 model=sortIdentifiers(model); -0027 end -0028 -0029 [~, A, B]=fileparts(filename); -0030 -0031 %If a path was used call on exportToTabDelimited instead -0032 if ~any(A) || ~any(B) -0033 exportToTabDelimited(model,filename); -0034 return; -0035 end -0036 -0037 if ~strcmpi(B,'.xlsx') -0038 EM='As of RAVEN version 1.9, only export to xlsx format is supported'; -0039 dispEM(EM); -0040 end -0041 -0042 import java.io.File; -0043 import java.io.FileOutputStream; -0044 import java.io.IOException; -0045 -0046 %Remove the output file if it already exists -0047 if exist(filename,'file') -0048 delete(filename); -0049 end -0050 -0051 %Load an empty workbook -0052 wb=loadWorkbook(filename,true); -0053 -0054 %Construct equations -0055 model.equations=constructEquations(model,model.rxns,true); -0056 -0057 %Check if it should print genes -0058 if isfield(model,'grRules') -0059 rules=model.grRules; -0060 else -0061 rules=[]; -0062 end -0063 -0064 %Check if the model has default upper/lower bounds. This determines if -0065 %those values should be printed or not -0066 hasDefaultLB=false; -0067 hasDefaultUB=false; -0068 if isfield(model,'annotation') -0069 if isfield(model.annotation,'defaultLB') -0070 hasDefaultLB=true; -0071 end -0072 if isfield(model.annotation,'defaultUB') -0073 hasDefaultUB=true; -0074 end -0075 end -0076 -0077 %Add the RXNS sheet -0078 -0079 %Create the header row -0080 headers={'#';'ID';'NAME';'EQUATION';'EC-NUMBER';'GENE ASSOCIATION';'LOWER BOUND';'UPPER BOUND';'OBJECTIVE';'COMPARTMENT';'MIRIAM';'SUBSYSTEM';'REPLACEMENT ID';'NOTE';'REFERENCE';'CONFIDENCE SCORE'}; -0081 -0082 %Add empty comments -0083 emptyColumn=cell(numel(model.rxns),1); -0084 rxnSheet=emptyColumn; -0085 -0086 %Add the model fields -0087 rxnSheet=[rxnSheet model.rxns]; -0088 -0089 if isfield(model,'rxnNames') -0090 rxnSheet=[rxnSheet model.rxnNames]; -0091 else -0092 rxnSheet=[rxnSheet emptyColumn]; -0093 end -0094 -0095 rxnSheet=[rxnSheet model.equations]; -0096 -0097 if isfield(model,'eccodes') -0098 rxnSheet=[rxnSheet model.eccodes]; -0099 else -0100 rxnSheet=[rxnSheet emptyColumn]; -0101 end -0102 -0103 if ~isempty(rules) -0104 rxnSheet=[rxnSheet rules]; -0105 else -0106 rxnSheet=[rxnSheet emptyColumn]; -0107 end -0108 -0109 lb=emptyColumn; -0110 ub=emptyColumn; -0111 objective=emptyColumn; -0112 rxnMiriams=emptyColumn; -0113 -0114 for i=1:numel(model.rxns) -0115 if isfield(model,'lb') -0116 if hasDefaultLB==true -0117 if model.rev(i)==1 -0118 %If reversible, print only if different than defaultLB -0119 if model.lb(i) ~= model.annotation.defaultLB -0120 lb{i}=model.lb(i); -0121 end -0122 else -0123 %If irreversible, print only for non-zero values -0124 if model.lb(i)~=0 -0125 lb{i}=model.lb(i); -0126 end -0127 end -0128 else -0129 lb{i}=model.lb(i); -0130 end -0131 end -0132 -0133 if isfield(model,'ub') -0134 if hasDefaultUB==true -0135 if model.ub(i) ~= model.annotation.defaultUB -0136 ub{i}=model.ub(i); -0137 end -0138 else -0139 ub{i}=model.ub(i); -0140 end -0141 end -0142 -0143 if isfield(model,'c') -0144 if model.c(i)~=0 -0145 objective{i}=model.c(i); -0146 end -0147 end -0148 -0149 if isfield(model,'rxnMiriams') -0150 if ~isempty(model.rxnMiriams{i}) -0151 toPrint=[]; -0152 for j=1:numel(model.rxnMiriams{i}.name) -0153 toPrint=[toPrint strtrim(model.rxnMiriams{i}.name{j}) '/' strtrim(model.rxnMiriams{i}.value{j}) ';']; -0154 end -0155 rxnMiriams{i}=toPrint(1:end-1); -0156 end -0157 end -0158 end -0159 -0160 rxnSheet=[rxnSheet lb]; -0161 rxnSheet=[rxnSheet ub]; -0162 rxnSheet=[rxnSheet objective]; -0163 -0164 if isfield(model,'rxnComps') -0165 rxnSheet=[rxnSheet model.comps(model.rxnComps)]; -0166 else -0167 rxnSheet=[rxnSheet emptyColumn]; -0168 end -0169 -0170 rxnSheet=[rxnSheet rxnMiriams]; -0171 -0172 subsystems=''; -0173 if isfield(model,'subSystems') -0174 for i=1:numel(model.subSystems) -0175 if ~isempty(model.subSystems{i,1}) -0176 subsystems{i,1}=strjoin(model.subSystems{i,1},';'); -0177 else -0178 subsystems{i,1}=''; -0179 end -0180 end -0181 rxnSheet=[rxnSheet subsystems]; -0182 else -0183 rxnSheet=[rxnSheet emptyColumn]; -0184 end -0185 -0186 %For REPLACEMENT ID which isn't in the model -0187 rxnSheet=[rxnSheet emptyColumn]; -0188 -0189 if isfield(model,'rxnNotes') -0190 rxnSheet=[rxnSheet model.rxnNotes]; -0191 else -0192 rxnSheet=[rxnSheet emptyColumn]; -0193 end -0194 -0195 if isfield(model,'rxnReferences') -0196 rxnSheet=[rxnSheet model.rxnReferences]; -0197 else -0198 rxnSheet=[rxnSheet emptyColumn]; -0199 end -0200 -0201 if isfield(model,'rxnConfidenceScores') -0202 rxnSheet=[rxnSheet num2cell(model.rxnConfidenceScores)]; -0203 else -0204 rxnSheet=[rxnSheet emptyColumn]; -0205 end -0206 -0207 wb=writeSheet(wb,'RXNS',0,headers,[],rxnSheet); -0208 -0209 headers={'#';'ID';'NAME';'UNCONSTRAINED';'MIRIAM';'COMPOSITION';'InChI';'COMPARTMENT';'REPLACEMENT ID';'CHARGE'}; -0210 -0211 metSheet=cell(numel(model.mets),numel(headers)); -0212 -0213 for i=1:numel(model.mets) -0214 metSheet{i,2}=[model.metNames{i} '[' model.comps{model.metComps(i)} ']']; -0215 -0216 if isfield(model,'metNames') -0217 metSheet(i,3)=model.metNames(i); -0218 end -0219 -0220 if isfield(model,'unconstrained') -0221 if model.unconstrained(i)~=0 -0222 metSheet{i,4}=true; -0223 end -0224 end -0225 -0226 if isfield(model,'metMiriams') -0227 if ~isempty(model.metMiriams{i}) -0228 toPrint=[]; -0229 for j=1:numel(model.metMiriams{i}.name) -0230 toPrint=[toPrint strtrim(model.metMiriams{i}.name{j}) '/' strtrim(model.metMiriams{i}.value{j}) ';']; -0231 end -0232 metSheet{i,5}=toPrint(1:end-1); -0233 end -0234 end -0235 -0236 % Making sure that only these metFormulas are exported, which don't -0237 % have InChI strings -0238 if isfield(model,'metFormulas') -0239 if isfield(model,'inchis') -0240 if isempty(model.inchis{i}) -0241 metSheet(i,6)=model.metFormulas(i); -0242 end -0243 else -0244 metSheet(i,6)=model.metFormulas(i); -0245 end -0246 end -0247 -0248 if isfield(model,'inchis') -0249 metSheet(i,7)=model.inchis(i); -0250 end -0251 -0252 if isfield(model,'metComps') -0253 metSheet(i,8)=model.comps(model.metComps(i)); -0254 end -0255 -0256 metSheet(i,9)=model.mets(i); -0257 -0258 if isfield(model,'metCharges') -0259 metSheet{i,10}=model.metCharges(i); -0260 end -0261 end -0262 -0263 wb=writeSheet(wb,'METS',1,headers,[],metSheet); -0264 -0265 %Add the COMPS sheet -0266 -0267 %Create the header row -0268 headers={'#';'ABBREVIATION';'NAME';'INSIDE';'MIRIAM'}; -0269 -0270 compSheet=cell(numel(model.comps),numel(headers)); -0271 -0272 for i=1:numel(model.comps) -0273 compSheet(i,2)=model.comps(i); -0274 -0275 if isfield(model,'compNames') -0276 compSheet(i,3)=model.compNames(i); -0277 end -0278 -0279 if isfield(model,'compOutside') -0280 compSheet(i,4)=model.compOutside(i); -0281 end -0282 -0283 if isfield(model,'compMiriams') -0284 if ~isempty(model.compMiriams{i}) -0285 toPrint=[]; -0286 for j=1:numel(model.compMiriams{i}.name) -0287 toPrint=[toPrint strtrim(model.compMiriams{i}.name{j}) '/' strtrim(model.compMiriams{i}.value{j}) ';']; -0288 end -0289 compSheet{i,5}=toPrint(1:end-1); -0290 end -0291 end -0292 end -0293 -0294 wb=writeSheet(wb,'COMPS',2,headers,[],compSheet); -0295 -0296 %Add the GENES sheet -0297 if isfield(model,'genes') -0298 %Create the header row -0299 headers={'#';'NAME';'MIRIAM';'SHORT NAME';'COMPARTMENT'}; -0300 -0301 geneSheet=cell(numel(model.genes),numel(headers)); -0302 -0303 for i=1:numel(model.genes) -0304 geneSheet(i,2)=model.genes(i); -0305 -0306 if isfield(model,'geneMiriams') -0307 if ~isempty(model.geneMiriams{i}) -0308 toPrint=[]; -0309 for j=1:numel(model.geneMiriams{i}.name) -0310 toPrint=[toPrint strtrim(model.geneMiriams{i}.name{j}) '/' strtrim(model.geneMiriams{i}.value{j}) ';']; -0311 end -0312 geneSheet{i,3}=toPrint(1:end-1); -0313 end -0314 end -0315 if isfield(model,'geneShortNames') -0316 geneSheet(i,4)=model.geneShortNames(i); -0317 end -0318 if isfield(model,'geneComps') -0319 geneSheet(i,5)=model.comps(model.geneComps(i)); -0320 end -0321 end -0322 -0323 wb=writeSheet(wb,'GENES',3,headers,[],geneSheet); -0324 end -0325 -0326 %Add the MODEL sheet -0327 -0328 %Create the header row -0329 headers={'#';'ID';'NAME';'TAXONOMY';'DEFAULT LOWER';'DEFAULT UPPER';'CONTACT GIVEN NAME';'CONTACT FAMILY NAME';'CONTACT EMAIL';'ORGANIZATION';'NOTES'}; -0330 -0331 modelSheet=cell(1,numel(headers)); -0332 -0333 if ~isfield(model,'annotation') -0334 model.annotation = []; -0335 end -0336 -0337 if isfield(model,'id') -0338 modelSheet{1,2}=model.id; -0339 else -0340 modelSheet{1,2}='blankID'; -0341 end -0342 if isfield(model,'name') -0343 modelSheet{1,3}=model.name; -0344 else -0345 modelSheet{1,3}='blankName'; -0346 end -0347 if isfield(model.annotation,'taxonomy') -0348 modelSheet{1,4}=model.annotation.taxonomy; -0349 end -0350 if isfield(model.annotation,'defaultLB') -0351 modelSheet{1,5}=model.annotation.defaultLB; -0352 end -0353 if isfield(model.annotation,'defaultUB') -0354 modelSheet{1,6}=model.annotation.defaultUB; -0355 end -0356 if isfield(model.annotation,'givenName') -0357 modelSheet{1,7}=model.annotation.givenName; -0358 end -0359 if isfield(model.annotation,'familyName') -0360 modelSheet{1,8}=model.annotation.familyName; -0361 end -0362 if isfield(model.annotation,'email') -0363 modelSheet{1,9}=model.annotation.email; -0364 end -0365 if isfield(model.annotation,'organization') -0366 modelSheet{1,10}=model.annotation.organization; -0367 end -0368 if isfield(model.annotation,'note') -0369 modelSheet{1,11}=model.annotation.note; -0370 end -0371 -0372 if isfield(model,'genes') -0373 wb=writeSheet(wb,'MODEL',4,headers,[],modelSheet); -0374 else -0375 wb=writeSheet(wb,'MODEL',3,headers,[],modelSheet); -0376 end -0377 -0378 %Open the output stream -0379 out = FileOutputStream(filename); -0380 wb.write(out); -0381 out.close(); -0382 end +0022 filename=char(filename); +0023 if nargin<3 +0024 sortIds=false; +0025 end +0026 if sortIds==true +0027 model=sortIdentifiers(model); +0028 end +0029 +0030 [~, A, B]=fileparts(filename); +0031 +0032 %If a path was used call on exportToTabDelimited instead +0033 if ~any(A) || ~any(B) +0034 exportToTabDelimited(model,filename); +0035 return; +0036 end +0037 +0038 if ~strcmpi(B,'.xlsx') +0039 EM='As of RAVEN version 1.9, only export to xlsx format is supported'; +0040 dispEM(EM); +0041 end +0042 +0043 import java.io.File; +0044 import java.io.FileOutputStream; +0045 import java.io.IOException; +0046 +0047 %Remove the output file if it already exists +0048 if exist(filename,'file') +0049 delete(filename); +0050 end +0051 +0052 %Load an empty workbook +0053 wb=loadWorkbook(filename,true); +0054 +0055 %Construct equations +0056 model.equations=constructEquations(model,model.rxns,true); +0057 +0058 %Check if it should print genes +0059 if isfield(model,'grRules') +0060 rules=model.grRules; +0061 else +0062 rules=[]; +0063 end +0064 +0065 %Check if the model has default upper/lower bounds. This determines if +0066 %those values should be printed or not +0067 hasDefaultLB=false; +0068 hasDefaultUB=false; +0069 if isfield(model,'annotation') +0070 if isfield(model.annotation,'defaultLB') +0071 hasDefaultLB=true; +0072 end +0073 if isfield(model.annotation,'defaultUB') +0074 hasDefaultUB=true; +0075 end +0076 end +0077 +0078 %Add the RXNS sheet +0079 +0080 %Create the header row +0081 headers={'#';'ID';'NAME';'EQUATION';'EC-NUMBER';'GENE ASSOCIATION';'LOWER BOUND';'UPPER BOUND';'OBJECTIVE';'COMPARTMENT';'MIRIAM';'SUBSYSTEM';'REPLACEMENT ID';'NOTE';'REFERENCE';'CONFIDENCE SCORE'}; +0082 +0083 %Add empty comments +0084 emptyColumn=cell(numel(model.rxns),1); +0085 rxnSheet=emptyColumn; +0086 +0087 %Add the model fields +0088 rxnSheet=[rxnSheet model.rxns]; +0089 +0090 if isfield(model,'rxnNames') +0091 rxnSheet=[rxnSheet model.rxnNames]; +0092 else +0093 rxnSheet=[rxnSheet emptyColumn]; +0094 end +0095 +0096 rxnSheet=[rxnSheet model.equations]; +0097 +0098 if isfield(model,'eccodes') +0099 rxnSheet=[rxnSheet model.eccodes]; +0100 else +0101 rxnSheet=[rxnSheet emptyColumn]; +0102 end +0103 +0104 if ~isempty(rules) +0105 rxnSheet=[rxnSheet rules]; +0106 else +0107 rxnSheet=[rxnSheet emptyColumn]; +0108 end +0109 +0110 lb=emptyColumn; +0111 ub=emptyColumn; +0112 objective=emptyColumn; +0113 rxnMiriams=emptyColumn; +0114 +0115 for i=1:numel(model.rxns) +0116 if isfield(model,'lb') +0117 if hasDefaultLB==true +0118 if model.rev(i)==1 +0119 %If reversible, print only if different than defaultLB +0120 if model.lb(i) ~= model.annotation.defaultLB +0121 lb{i}=model.lb(i); +0122 end +0123 else +0124 %If irreversible, print only for non-zero values +0125 if model.lb(i)~=0 +0126 lb{i}=model.lb(i); +0127 end +0128 end +0129 else +0130 lb{i}=model.lb(i); +0131 end +0132 end +0133 +0134 if isfield(model,'ub') +0135 if hasDefaultUB==true +0136 if model.ub(i) ~= model.annotation.defaultUB +0137 ub{i}=model.ub(i); +0138 end +0139 else +0140 ub{i}=model.ub(i); +0141 end +0142 end +0143 +0144 if isfield(model,'c') +0145 if model.c(i)~=0 +0146 objective{i}=model.c(i); +0147 end +0148 end +0149 +0150 if isfield(model,'rxnMiriams') +0151 if ~isempty(model.rxnMiriams{i}) +0152 toPrint=[]; +0153 for j=1:numel(model.rxnMiriams{i}.name) +0154 toPrint=[toPrint strtrim(model.rxnMiriams{i}.name{j}) '/' strtrim(model.rxnMiriams{i}.value{j}) ';']; +0155 end +0156 rxnMiriams{i}=toPrint(1:end-1); +0157 end +0158 end +0159 end +0160 +0161 rxnSheet=[rxnSheet lb]; +0162 rxnSheet=[rxnSheet ub]; +0163 rxnSheet=[rxnSheet objective]; +0164 +0165 if isfield(model,'rxnComps') +0166 rxnSheet=[rxnSheet model.comps(model.rxnComps)]; +0167 else +0168 rxnSheet=[rxnSheet emptyColumn]; +0169 end +0170 +0171 rxnSheet=[rxnSheet rxnMiriams]; +0172 +0173 subsystems=''; +0174 if isfield(model,'subSystems') +0175 for i=1:numel(model.subSystems) +0176 if ~isempty(model.subSystems{i,1}) +0177 subsystems{i,1}=strjoin(model.subSystems{i,1},';'); +0178 else +0179 subsystems{i,1}=''; +0180 end +0181 end +0182 rxnSheet=[rxnSheet subsystems]; +0183 else +0184 rxnSheet=[rxnSheet emptyColumn]; +0185 end +0186 +0187 %For REPLACEMENT ID which isn't in the model +0188 rxnSheet=[rxnSheet emptyColumn]; +0189 +0190 if isfield(model,'rxnNotes') +0191 rxnSheet=[rxnSheet model.rxnNotes]; +0192 else +0193 rxnSheet=[rxnSheet emptyColumn]; +0194 end +0195 +0196 if isfield(model,'rxnReferences') +0197 rxnSheet=[rxnSheet model.rxnReferences]; +0198 else +0199 rxnSheet=[rxnSheet emptyColumn]; +0200 end +0201 +0202 if isfield(model,'rxnConfidenceScores') +0203 rxnSheet=[rxnSheet num2cell(model.rxnConfidenceScores)]; +0204 else +0205 rxnSheet=[rxnSheet emptyColumn]; +0206 end +0207 +0208 wb=writeSheet(wb,'RXNS',0,headers,[],rxnSheet); +0209 +0210 headers={'#';'ID';'NAME';'UNCONSTRAINED';'MIRIAM';'COMPOSITION';'InChI';'COMPARTMENT';'REPLACEMENT ID';'CHARGE'}; +0211 +0212 metSheet=cell(numel(model.mets),numel(headers)); +0213 +0214 for i=1:numel(model.mets) +0215 metSheet{i,2}=[model.metNames{i} '[' model.comps{model.metComps(i)} ']']; +0216 +0217 if isfield(model,'metNames') +0218 metSheet(i,3)=model.metNames(i); +0219 end +0220 +0221 if isfield(model,'unconstrained') +0222 if model.unconstrained(i)~=0 +0223 metSheet{i,4}=true; +0224 end +0225 end +0226 +0227 if isfield(model,'metMiriams') +0228 if ~isempty(model.metMiriams{i}) +0229 toPrint=[]; +0230 for j=1:numel(model.metMiriams{i}.name) +0231 toPrint=[toPrint strtrim(model.metMiriams{i}.name{j}) '/' strtrim(model.metMiriams{i}.value{j}) ';']; +0232 end +0233 metSheet{i,5}=toPrint(1:end-1); +0234 end +0235 end +0236 +0237 % Making sure that only these metFormulas are exported, which don't +0238 % have InChI strings +0239 if isfield(model,'metFormulas') +0240 if isfield(model,'inchis') +0241 if isempty(model.inchis{i}) +0242 metSheet(i,6)=model.metFormulas(i); +0243 end +0244 else +0245 metSheet(i,6)=model.metFormulas(i); +0246 end +0247 end +0248 +0249 if isfield(model,'inchis') +0250 metSheet(i,7)=model.inchis(i); +0251 end +0252 +0253 if isfield(model,'metComps') +0254 metSheet(i,8)=model.comps(model.metComps(i)); +0255 end +0256 +0257 metSheet(i,9)=model.mets(i); +0258 +0259 if isfield(model,'metCharges') +0260 metSheet{i,10}=model.metCharges(i); +0261 end +0262 end +0263 +0264 wb=writeSheet(wb,'METS',1,headers,[],metSheet); +0265 +0266 %Add the COMPS sheet +0267 +0268 %Create the header row +0269 headers={'#';'ABBREVIATION';'NAME';'INSIDE';'MIRIAM'}; +0270 +0271 compSheet=cell(numel(model.comps),numel(headers)); +0272 +0273 for i=1:numel(model.comps) +0274 compSheet(i,2)=model.comps(i); +0275 +0276 if isfield(model,'compNames') +0277 compSheet(i,3)=model.compNames(i); +0278 end +0279 +0280 if isfield(model,'compOutside') +0281 compSheet(i,4)=model.compOutside(i); +0282 end +0283 +0284 if isfield(model,'compMiriams') +0285 if ~isempty(model.compMiriams{i}) +0286 toPrint=[]; +0287 for j=1:numel(model.compMiriams{i}.name) +0288 toPrint=[toPrint strtrim(model.compMiriams{i}.name{j}) '/' strtrim(model.compMiriams{i}.value{j}) ';']; +0289 end +0290 compSheet{i,5}=toPrint(1:end-1); +0291 end +0292 end +0293 end +0294 +0295 wb=writeSheet(wb,'COMPS',2,headers,[],compSheet); +0296 +0297 %Add the GENES sheet +0298 if isfield(model,'genes') +0299 %Create the header row +0300 headers={'#';'NAME';'MIRIAM';'SHORT NAME';'COMPARTMENT'}; +0301 +0302 geneSheet=cell(numel(model.genes),numel(headers)); +0303 +0304 for i=1:numel(model.genes) +0305 geneSheet(i,2)=model.genes(i); +0306 +0307 if isfield(model,'geneMiriams') +0308 if ~isempty(model.geneMiriams{i}) +0309 toPrint=[]; +0310 for j=1:numel(model.geneMiriams{i}.name) +0311 toPrint=[toPrint strtrim(model.geneMiriams{i}.name{j}) '/' strtrim(model.geneMiriams{i}.value{j}) ';']; +0312 end +0313 geneSheet{i,3}=toPrint(1:end-1); +0314 end +0315 end +0316 if isfield(model,'geneShortNames') +0317 geneSheet(i,4)=model.geneShortNames(i); +0318 end +0319 if isfield(model,'geneComps') +0320 geneSheet(i,5)=model.comps(model.geneComps(i)); +0321 end +0322 end +0323 +0324 wb=writeSheet(wb,'GENES',3,headers,[],geneSheet); +0325 end +0326 +0327 %Add the MODEL sheet +0328 +0329 %Create the header row +0330 headers={'#';'ID';'NAME';'TAXONOMY';'DEFAULT LOWER';'DEFAULT UPPER';'CONTACT GIVEN NAME';'CONTACT FAMILY NAME';'CONTACT EMAIL';'ORGANIZATION';'NOTES'}; +0331 +0332 modelSheet=cell(1,numel(headers)); +0333 +0334 if ~isfield(model,'annotation') +0335 model.annotation = []; +0336 end +0337 +0338 if isfield(model,'id') +0339 modelSheet{1,2}=model.id; +0340 else +0341 modelSheet{1,2}='blankID'; +0342 end +0343 if isfield(model,'name') +0344 modelSheet{1,3}=model.name; +0345 else +0346 modelSheet{1,3}='blankName'; +0347 end +0348 if isfield(model.annotation,'taxonomy') +0349 modelSheet{1,4}=model.annotation.taxonomy; +0350 end +0351 if isfield(model.annotation,'defaultLB') +0352 modelSheet{1,5}=model.annotation.defaultLB; +0353 end +0354 if isfield(model.annotation,'defaultUB') +0355 modelSheet{1,6}=model.annotation.defaultUB; +0356 end +0357 if isfield(model.annotation,'givenName') +0358 modelSheet{1,7}=model.annotation.givenName; +0359 end +0360 if isfield(model.annotation,'familyName') +0361 modelSheet{1,8}=model.annotation.familyName; +0362 end +0363 if isfield(model.annotation,'email') +0364 modelSheet{1,9}=model.annotation.email; +0365 end +0366 if isfield(model.annotation,'organization') +0367 modelSheet{1,10}=model.annotation.organization; +0368 end +0369 if isfield(model.annotation,'note') +0370 modelSheet{1,11}=model.annotation.note; +0371 end +0372 +0373 if isfield(model,'genes') +0374 wb=writeSheet(wb,'MODEL',4,headers,[],modelSheet); +0375 else +0376 wb=writeSheet(wb,'MODEL',3,headers,[],modelSheet); +0377 end +0378 +0379 %Open the output stream +0380 out = FileOutputStream(filename); +0381 wb.write(out); +0382 out.close(); +0383 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/getMD5Hash.html b/doc/io/getMD5Hash.html index 6dbdb0ba..e061b39d 100644 --- a/doc/io/getMD5Hash.html +++ b/doc/io/getMD5Hash.html @@ -48,7 +48,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • checkFileExistence checkFileExistence
  • This function is called by: @@ -74,44 +74,45 @@

    SOURCE CODE ^% md5Hash string containing an MD5 hash for inputFile 0016 % 0017 % Usage: md5Hash=getMD5Hash(inputFile,binEnd) -0018 -0019 if nargin<2 -0020 if isunix -0021 if ismac -0022 binEnd='.mac'; -0023 else -0024 binEnd=''; -0025 end -0026 elseif ispc -0027 binEnd='.exe'; -0028 else -0029 dispEM('Unknown OS, exiting.') -0030 return +0018 inputFile=char(inputFile); +0019 +0020 if nargin<2 +0021 if isunix +0022 if ismac +0023 binEnd='.mac'; +0024 else +0025 binEnd=''; +0026 end +0027 elseif ispc +0028 binEnd='.exe'; +0029 else +0030 error('Unknown OS, exiting.') 0031 end -0032 end -0033 -0034 %Check if binEnd is valid -0035 if ~strcmp(binEnd,'.mac') && ~strcmp(binEnd,'') && ~strcmp(binEnd,'.exe') -0036 dispEM('Unknown OS, exiting.') -0037 return -0038 end -0039 -0040 %Check file existence -0041 inputFile=checkFileExistence(inputFile); -0042 -0043 %Get string containing an MD5 hash -0044 switch binEnd -0045 case '.mac' -0046 [~, md5HashMessage]=system(['md5 "' inputFile '"']); -0047 case '' -0048 [~, md5HashMessage]=system(['md5sum "' inputFile '"']); -0049 case '.exe' -0050 [~, md5HashMessage]=system(['certutil -hashfile "' inputFile '" MD5"']); -0051 end -0052 -0053 %Extract MD5 hash from a string -0054 md5Hash = char(regexp(md5HashMessage,'[a-f0-9]{32}','match')); -0055 end +0032 else +0033 binEnd=char(binEnd); +0034 end +0035 +0036 %Check if binEnd is valid +0037 if ~any(strcmp(binEnd,{'.mac','','.exe'})) +0038 error('Unknown OS, exiting.') +0039 end +0040 +0041 %Check file existence +0042 inputFile=checkFileExistence(inputFile); +0043 +0044 %Get string containing an MD5 hash +0045 switch binEnd +0046 case '.mac' +0047 [~, md5HashMessage]=system(['md5 "' inputFile '"']); +0048 case '' +0049 [~, md5HashMessage]=system(['md5sum "' inputFile '"']); +0050 case '.exe' +0051 [~, md5HashMessage]=system(['certutil -hashfile "' inputFile '" MD5"']); +0052 end +0053 +0054 %Extract MD5 hash from a string +0055 md5Hash = char(regexp(md5HashMessage,'[a-f0-9]{32}','match')); +0056 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/getToolboxVersion.html b/doc/io/getToolboxVersion.html index 64d98f58..eae1e2e7 100644 --- a/doc/io/getToolboxVersion.html +++ b/doc/io/getToolboxVersion.html @@ -34,7 +34,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^
 </ul>
 This function is called by:
 <ul style= -
  • exportForGit exportForGit
  • +
  • exportForGit exportForGit
  • SUBFUNCTIONS ^

    @@ -65,78 +65,80 @@

    SOURCE CODE ^% toolbox string with the toolbox name (e.g. "RAVEN") 0007 % fileID string with the name of a file that is only found in 0008 % the corresponding toolbox (e.g. "ravenCobraWrapper.m"). -0009 % mainBranchFlag logical, if true, function will error if the toolbox is +0009 % mainBranchFlag logical, if true, function will error if the toolbox is 0010 % not on the main branch (opt, default false). 0011 % 0012 % version string containing either the toolbox version or latest 0013 % commit hash (7 characters). 0014 % 0015 % Usage: version = getToolboxVersion(toolbox,fileID,mainBranchFlag) -0016 -0017 if nargin<3 -0018 mainBranchFlag = false; -0019 end -0020 -0021 currentPath = pwd; -0022 version = ''; -0023 -0024 %Try to find root of toolbox: -0025 try -0026 toolboxPath = which(fileID); %full file path -0027 slashPos = getSlashPos(toolboxPath); -0028 toolboxPath = toolboxPath(1:slashPos(end)); %folder path -0029 %Go up until the root is found: -0030 D = dir(toolboxPath); -0031 while ~ismember({'.git'},{D.name}) -0032 slashPos = getSlashPos(toolboxPath); -0033 toolboxPath = toolboxPath(1:slashPos(end-1)); -0034 D = dir(toolboxPath); -0035 end -0036 cd(toolboxPath); -0037 catch -0038 disp([toolbox ' toolbox cannot be found']) -0039 version = 'unknown'; -0040 end -0041 %Check if in main: -0042 if mainBranchFlag -0043 currentBranch = git('rev-parse --abbrev-ref HEAD'); -0044 if any([strcmp(currentBranch, "main"), strcmp(currentBranch, "master")]) -0045 cd(currentPath); -0046 error(['ERROR: ' toolbox ' not in main (or master) branch. Check-out this branch of ' toolbox ' before submitting model for Git.']) -0047 end -0048 end -0049 %Try to find version file of the toolbox: -0050 if isempty(version) -0051 try -0052 fid = fopen([toolboxPath 'version.txt'],'r'); -0053 version = fscanf(fid,'%s'); -0054 fclose(fid); -0055 catch -0056 %If no file available, look up the tag: -0057 try -0058 version = git('describe --tags'); -0059 commit = git('log -n 1 --format=%H'); -0060 commit = commit(1:7); -0061 %If no tag available or commit is part of tag, get commit instead: -0062 if ~isempty(strfind(version,'fatal')) || ~isempty(strfind(version,commit)) -0063 version = ['commit ' commit]; -0064 else -0065 version = strrep(version,'v',''); -0066 end -0067 catch -0068 version = 'unknown'; -0069 end -0070 end -0071 end -0072 cd(currentPath); +0016 toolbox=char(toolbox); +0017 fileID=char(fileID); +0018 +0019 if nargin<3 +0020 mainBranchFlag = false; +0021 end +0022 +0023 currentPath = pwd; +0024 version = ''; +0025 +0026 %Try to find root of toolbox: +0027 try +0028 toolboxPath = which(fileID); %full file path +0029 slashPos = getSlashPos(toolboxPath); +0030 toolboxPath = toolboxPath(1:slashPos(end)); %folder path +0031 %Go up until the root is found: +0032 D = dir(toolboxPath); +0033 while ~ismember({'.git'},{D.name}) +0034 slashPos = getSlashPos(toolboxPath); +0035 toolboxPath = toolboxPath(1:slashPos(end-1)); +0036 D = dir(toolboxPath); +0037 end +0038 cd(toolboxPath); +0039 catch +0040 disp([toolbox ' toolbox cannot be found']) +0041 version = 'unknown'; +0042 end +0043 %Check if in main: +0044 if mainBranchFlag +0045 currentBranch = git('rev-parse --abbrev-ref HEAD'); +0046 if any([strcmp(currentBranch, "main"), strcmp(currentBranch, "master")]) +0047 cd(currentPath); +0048 error(['ERROR: ' toolbox ' not in main (or master) branch. Check-out this branch of ' toolbox ' before submitting model for Git.']) +0049 end +0050 end +0051 %Try to find version file of the toolbox: +0052 if isempty(version) +0053 try +0054 fid = fopen([toolboxPath 'version.txt'],'r'); +0055 version = fscanf(fid,'%s'); +0056 fclose(fid); +0057 catch +0058 %If no file available, look up the tag: +0059 try +0060 version = git('describe --tags'); +0061 commit = git('log -n 1 --format=%H'); +0062 commit = commit(1:7); +0063 %If no tag available or commit is part of tag, get commit instead: +0064 if ~isempty(strfind(version,'fatal')) || ~isempty(strfind(version,commit)) +0065 version = ['commit ' commit]; +0066 else +0067 version = strrep(version,'v',''); +0068 end +0069 catch +0070 version = 'unknown'; +0071 end +0072 end 0073 end -0074 -0075 function slashPos = getSlashPos(path) -0076 slashPos = strfind(path,'\'); %Windows -0077 if isempty(slashPos) -0078 slashPos = strfind(path,'/'); %MAC/Linux -0079 end -0080 end +0074 cd(currentPath); +0075 end +0076 +0077 function slashPos = getSlashPos(path) +0078 slashPos = strfind(path,'\'); %Windows +0079 if isempty(slashPos) +0080 slashPos = strfind(path,'/'); %MAC/Linux +0081 end +0082 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/importExcelModel.html b/doc/io/importExcelModel.html index eea3e956..0784a1f3 100644 --- a/doc/io/importExcelModel.html +++ b/doc/io/importExcelModel.html @@ -194,857 +194,858 @@

    SOURCE CODE ^% setting ignoreErrors to true. 0075 % 0076 % Usage: model=importExcelModel(fileName,removeExcMets,printWarnings,ignoreErrors) -0077 -0078 if nargin<2 -0079 removeExcMets=true; -0080 end -0081 if nargin<3 -0082 printWarnings=true; -0083 end -0084 if nargin<4 -0085 ignoreErrors=false; -0086 end -0087 -0088 if ~(exist(fileName,'file')==2) -0089 error('Excel file %s cannot be found',string(fileName)); -0090 end -0091 -0092 %This is to match the order of the fields to those you get from importing -0093 %from SBML -0094 model=[]; -0095 model.id=[]; -0096 model.name=[]; -0097 model.annotation=[]; -0098 %Default bounds if not defined -0099 model.annotation.defaultLB=-1000; -0100 model.annotation.defaultUB=1000; -0101 model.rxns={}; -0102 model.mets={}; -0103 model.S=[]; -0104 model.lb=[]; -0105 model.ub=[]; -0106 model.rev=[]; -0107 model.c=[]; -0108 model.b=[]; -0109 model.comps={}; -0110 model.compNames={}; -0111 model.compOutside={}; -0112 model.compMiriams={}; -0113 model.rxnNames={}; -0114 model.rxnComps={}; %Will be double later -0115 model.grRules={}; -0116 model.rxnGeneMat=[]; -0117 model.subSystems={}; -0118 model.eccodes={}; -0119 model.rxnMiriams={}; -0120 model.rxnNotes={}; -0121 model.rxnReferences={}; -0122 model.rxnConfidenceScores={}; %Will be double later -0123 model.genes={}; -0124 model.geneComps={}; %Will be double later -0125 model.geneMiriams={}; -0126 model.geneShortNames={}; -0127 model.metNames={}; -0128 model.metComps=[]; -0129 model.inchis={}; -0130 model.metFormulas={}; -0131 model.metMiriams={}; -0132 model.metCharges={}; %Will be double later -0133 model.unconstrained=[]; -0134 -0135 workbook=loadWorkbook(fileName); -0136 -0137 [raw, flag]=loadSheet(workbook,'MODEL'); -0138 -0139 if flag<0 -0140 if printWarnings==true -0141 EM='Could not load the MODEL sheet'; -0142 dispEM(EM,false); -0143 end -0144 model.id='UNKNOWN'; -0145 model.name='No model details available'; -0146 else -0147 raw=cleanSheet(raw); -0148 -0149 %It is assumed that the first line is labels and that the second one is -0150 %info -0151 raw(1,:)=upper(raw(1,:)); -0152 raw(1,:)=strrep(raw(1,:),'MODELID','ID'); -0153 raw(1,:)=strrep(raw(1,:),'MODELNAME','NAME'); -0154 raw(1,:)=strrep(raw(1,:),'DESCRIPTION','NAME'); -0155 -0156 %Loop through the labels -0157 for i=1:numel(raw(1,:)) -0158 switch raw{1,i} -0159 case 'ID' -0160 if any(raw{2,i}) -0161 model.id=toStr(raw{2,i}); %Should be string already -0162 else -0163 EM='No model ID supplied'; -0164 dispEM(EM); -0165 end -0166 case 'NAME' -0167 if any(raw{2,i}) -0168 model.name=toStr(raw{2,i}); %Should be string already -0169 else -0170 EM='No model name supplied'; -0171 dispEM(EM); -0172 end -0173 case 'DEFAULT LOWER' -0174 if ~isempty(raw{2,i}) -0175 try -0176 model.annotation.defaultLB=toDouble(raw{2,i},NaN); -0177 catch -0178 EM='DEFAULT LOWER must be numeric'; -0179 dispEM(EM); -0180 end -0181 else -0182 if printWarnings==true -0183 fprintf('NOTE: DEFAULT LOWER not supplied. Uses -1000\n'); -0184 end -0185 model.annotation.defaultLB=-1000; -0186 end -0187 case 'DEFAULT UPPER' -0188 if ~isempty(raw{2,i}) -0189 try -0190 model.annotation.defaultUB=toDouble(raw{2,i},NaN); -0191 catch -0192 EM='DEFAULT UPPER must be numeric'; -0193 dispEM(EM); -0194 end -0195 else -0196 if printWarnings==true -0197 fprintf('NOTE: DEFAULT UPPER not supplied. Uses 1000\n'); -0198 end -0199 model.annotation.defaultUB=1000; -0200 end -0201 case 'TAXONOMY' -0202 if any(raw{2,i}) -0203 model.annotation.taxonomy=toStr(raw{2,i}); %Should be string already -0204 end -0205 case 'CONTACT GIVEN NAME' -0206 if any(raw{2,i}) -0207 model.annotation.givenName=toStr(raw{2,i}); %Should be string already -0208 end -0209 case 'CONTACT FAMILY NAME' -0210 if any(raw{2,i}) -0211 model.annotation.familyName=toStr(raw{2,i}); %Should be string already -0212 end -0213 case 'CONTACT EMAIL' -0214 if any(raw{2,i}) -0215 model.annotation.email=toStr(raw{2,i}); %Should be string already -0216 end -0217 case 'ORGANIZATION' -0218 if any(raw{2,i}) -0219 model.annotation.organization=toStr(raw{2,i}); %Should be string already -0220 end -0221 case 'NOTES' -0222 if any(raw{2,i}) -0223 model.annotation.note=toStr(raw{2,i}); %Should be string already -0224 end -0225 end -0226 end -0227 end -0228 -0229 %Get compartment information -0230 [raw, flag]=loadSheet(workbook,'COMPS'); -0231 -0232 if flag<0 -0233 if printWarnings==true -0234 EM='Could not load the COMPS sheet. All elements will be assigned to a compartment "s" for "System"'; -0235 dispEM(EM,false); -0236 end -0237 model.comps={'s'}; -0238 model.compNames={'System'}; -0239 else -0240 raw=cleanSheet(raw); -0241 -0242 %Map to new captions -0243 raw(1,:)=upper(raw(1,:)); -0244 raw(1,:)=strrep(raw(1,:),'COMPABBREV','ABBREVIATION'); -0245 raw(1,:)=strrep(raw(1,:),'COMPNAME','NAME'); -0246 -0247 %Loop through the labels -0248 for i=1:numel(raw(1,:)) -0249 switch raw{1,i} -0250 case 'ABBREVIATION' -0251 model.comps=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0252 case 'NAME' -0253 model.compNames=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0254 case 'INSIDE' -0255 model.compOutside=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0256 case 'MIRIAM' -0257 model.compMiriams=raw(2:end,i); -0258 end -0259 end -0260 -0261 %Check that necessary fields are loaded -0262 if isempty(model.comps) -0263 EM='There must be a column named ABBREVIATION in the COMPS sheet'; -0264 dispEM(EM); -0265 end -0266 if isempty(model.compNames) -0267 model.compNames=model.comps; -0268 if printWarnings==true -0269 EM='There is no column named NAME in the COMPS sheet. ABBREVIATION will be used as name'; -0270 dispEM(EM,false); -0271 end -0272 end -0273 model.compMiriams=parseMiriam(model.compMiriams); -0274 end -0275 -0276 %Get all the genes and info about them -0277 [raw, flag]=loadSheet(workbook,'GENES'); -0278 -0279 if flag<0 -0280 if printWarnings==true -0281 EM='There is no spreadsheet named GENES'; -0282 dispEM(EM,false) -0283 end -0284 else -0285 raw=cleanSheet(raw); -0286 -0287 %Map to new captions -0288 raw(1,:)=upper(raw(1,:)); -0289 raw(1,:)=strrep(raw(1,:),'GENE NAME','NAME'); -0290 -0291 %Loop through the labels -0292 foundGenes=false; -0293 for i=1:numel(raw(1,:)) -0294 switch raw{1,i} -0295 case 'NAME' -0296 model.genes=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0297 foundGenes=true; -0298 case 'MIRIAM' -0299 model.geneMiriams=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0300 case 'SHORT NAME' -0301 model.geneShortNames=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0302 case 'COMPARTMENT' -0303 model.geneComps=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0304 end -0305 end -0306 -0307 if foundGenes==false -0308 EM='There must be a column named NAME in the GENES sheet'; -0309 dispEM(EM); -0310 end -0311 -0312 %Its ok if all of them are empty -0313 if all(cellfun(@isempty,model.geneComps)) -0314 model.geneComps=[]; -0315 end -0316 -0317 %Check that geneName contain only strings and no empty strings -0318 if ~iscellstr(model.genes) -0319 EM='All gene names have to be strings'; -0320 dispEM(EM); -0321 else -0322 if any(strcmp('',model.genes)) -0323 EM='There can be no empty strings in gene names'; -0324 dispEM(EM); -0325 end -0326 end -0327 -0328 %Check that geneComp contains only strings and no empty string -0329 if ~isempty(model.geneComps) -0330 if ~iscellstr(model.geneComps) -0331 EM='All gene compartments have to be strings'; -0332 dispEM(EM); -0333 else -0334 if any(strcmp('',model.geneComps)) -0335 EM='There can be no empty strings in gene compartments'; -0336 dispEM(EM); -0337 end -0338 end -0339 [I, model.geneComps]=ismember(model.geneComps,model.comps); -0340 EM='The following genes have compartment abbreviations which could not be found:'; -0341 dispEM(EM,true,model.genes(~I)); -0342 end -0343 end -0344 -0345 model.geneMiriams=parseMiriam(model.geneMiriams); -0346 -0347 %Loads the reaction data -0348 [raw, flag]=loadSheet(workbook,'RXNS'); -0349 -0350 if flag<0 -0351 EM='Could not load the RXNS sheet'; -0352 dispEM(EM); -0353 end -0354 -0355 raw=cleanSheet(raw); -0356 -0357 %Map to new captions -0358 raw(1,:)=upper(raw(1,:)); -0359 raw(1,:)=strrep(raw(1,:),'RXNID','ID'); -0360 -0361 %Loop through the labels -0362 equations={}; -0363 reactionReplacement={}; -0364 for i=1:numel(raw(1,:)) -0365 switch raw{1,i} -0366 case 'ID' -0367 model.rxns=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0368 case 'NAME' -0369 model.rxnNames=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0370 case 'EQUATION' -0371 equations=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0372 case 'EC-NUMBER' -0373 model.eccodes=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0374 case 'GENE ASSOCIATION' -0375 model.grRules=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0376 case 'LOWER BOUND' -0377 try -0378 model.lb=cellfun(@(x) toDouble(x,NaN),raw(2:end,i)); -0379 catch -0380 EM='The lower bounds must be numerical values'; -0381 dispEM(EM); -0382 end -0383 case 'UPPER BOUND' -0384 try -0385 model.ub=cellfun(@(x) toDouble(x,NaN),raw(2:end,i)); -0386 catch -0387 EM='The upper bounds must be numerical values'; -0388 dispEM(EM); -0389 end -0390 case 'OBJECTIVE' -0391 try -0392 model.c=cellfun(@(x) toDouble(x,0),raw(2:end,i)); -0393 catch -0394 EM='The objective coefficients must be numerical values'; -0395 dispEM(EM); -0396 end -0397 case 'COMPARTMENT' -0398 model.rxnComps=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0399 case 'SUBSYSTEM' -0400 subsystems=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0401 case 'REPLACEMENT ID' -0402 reactionReplacement=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0403 case 'MIRIAM' -0404 model.rxnMiriams=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0405 case 'NOTE' -0406 model.rxnNotes=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0407 case 'REFERENCE' -0408 model.rxnReferences=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0409 case 'CONFIDENCE SCORE' -0410 model.rxnConfidenceScores=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0411 end -0412 end -0413 -0414 if ~isempty(model.rxnConfidenceScores) -0415 model.rxnConfidenceScores=str2double(model.rxnConfidenceScores); -0416 end -0417 for i=1:numel(subsystems) -0418 model.subSystems{i,1}=cellstr(strsplit(subsystems{i,1},';')); -0419 end -0420 -0421 %Check that all necessary reaction info has been loaded -0422 if isempty(equations) -0423 EM='There must be a column named EQUATION in the RXNS sheet'; -0424 dispEM(EM); -0425 end -0426 if isempty(model.rxns) -0427 if printWarnings==true -0428 EM='There is no column named ID in the RXNS sheet. The reactions will be named as "r1", "r2"...'; -0429 dispEM(EM,false); -0430 end -0431 I=num2cell((1:numel(equations))'); -0432 model.rxns=strcat('r',cellfun(@num2str,I,'UniformOutput',false)); -0433 end -0434 -0435 %Check if some other stuff is loaded and populate with default values -0436 %otherwise -0437 if isempty(model.rxnNames) -0438 model.rxnNames=cell(numel(model.rxns),1); -0439 model.rxnNames(:)={''}; -0440 if printWarnings==true -0441 EM='There is no column named NAME in the RXNS sheet. Empty strings will be used as reaction names'; -0442 dispEM(EM,false); -0443 end -0444 end -0445 if isempty(model.lb) -0446 %This is not set here since the reversibility isn't known yet -0447 model.lb=nan(numel(model.rxns),1); -0448 if printWarnings==true -0449 EM='There is no column named LOWER BOUND in the RXNS sheet. Default bounds will be used'; -0450 dispEM(EM,false); -0451 end -0452 end -0453 if isempty(model.ub) -0454 model.ub=nan(numel(model.rxns),1); -0455 if printWarnings==true -0456 EM='There is no column named UPPER BOUND in the RXNS sheet. Default bounds will be used'; -0457 dispEM(EM,false); -0458 end -0459 end -0460 if isempty(model.c) -0461 model.c=zeros(numel(model.rxns),1); -0462 if printWarnings==true -0463 EM='There is no column named OBJECTIVE in the RXNS sheet'; -0464 dispEM(EM,false); -0465 end -0466 end -0467 -0468 %Either all reactions must have a compartment string or none of them. Check -0469 %if it's only empty and if so return it to [] -0470 if ~isempty(model.rxnComps) -0471 if all(cellfun(@isempty,model.rxnComps)) -0472 model.rxnComps=[]; -0473 end -0474 end -0475 -0476 %Construct the rxnMiriams structure -0477 model.rxnMiriams=parseMiriam(model.rxnMiriams); -0478 -0479 %Replace the reaction IDs for those IDs that have a corresponding -0480 %replacement name. -0481 I=cellfun(@any,reactionReplacement); -0482 model.rxns(I)=reactionReplacement(I); -0483 -0484 %Check that there are no empty strings in reactionIDs or equations -0485 if any(strcmp('',model.rxns)) -0486 EM='There are empty reaction IDs'; -0487 dispEM(EM); -0488 end -0489 -0490 if any(strcmp('',equations)) -0491 EM='There are empty equations'; -0492 dispEM(EM); -0493 end -0494 -0495 if ~isempty(model.rxnComps) -0496 if any(strcmp('',model.rxnComps)) -0497 EM='Either all reactions must have an associated compartment string or none of them'; -0498 dispEM(EM); -0499 end -0500 end -0501 -0502 if ~isempty(model.grRules) -0503 tempRules=model.grRules; -0504 for i=1:length(model.rxns) -0505 %Check that all gene associations have a match in the gene list -0506 if ~isempty(model.grRules{i}) -0507 tempRules{i}=regexprep(tempRules{i},' and | or ','>'); %New format: Genes are separated 'and' and 'or' strings with parentheses -0508 tempRules{i}=regexprep(tempRules{i},'(',''); %New format: Genes are separated 'and' and 'or' strings with parentheses -0509 tempRules{i}=regexprep(tempRules{i},')',''); %New format: Genes are separated 'and' and 'or' strings with parentheses -0510 indexesNew=strfind(tempRules{i},'>'); %Old format: Genes are separated by ":" for AND and ";" for OR -0511 indexes=strfind(tempRules{i},':'); %Old format: Genes are separated by ":" for AND and ";" for OR -0512 indexes=unique([indexesNew indexes strfind(tempRules{i},';')]); -0513 if isempty(indexes) -0514 %See if you have a match -0515 I=find(strcmp(tempRules{i},model.genes)); -0516 if isempty(I) -0517 EM=['The gene association in reaction ' model.rxns{i} ' (' tempRules{i} ') is not present in the gene list']; -0518 dispEM(EM); -0519 end -0520 else -0521 temp=[0 indexes numel(tempRules{i})+1]; -0522 for j=1:numel(indexes)+1 -0523 %The reaction has several associated genes -0524 geneName=tempRules{i}(temp(j)+1:temp(j+1)-1); -0525 I=find(strcmp(geneName,model.genes)); -0526 if isempty(I) -0527 EM=['The gene association in reaction ' model.rxns{i} ' (' geneName ') is not present in the gene list']; -0528 dispEM(EM); -0529 end -0530 end -0531 end -0532 %In order to adhere to the COBRA standards it should be like -0533 %this: -If only one gene then no parentheses -If only "and" or -0534 %only "or" there should only be one set of parentheses -If both -0535 %"and" and "or", then split on "or". This is not complete, but -0536 %it's the type of relationship supported by the Excel -0537 %formulation -0538 aSign=strfind(model.grRules{i},':'); -0539 oSign=strfind(model.grRules{i},';'); -0540 if isempty(aSign) && isempty(oSign) -0541 model.grRules{i}=model.grRules{i}; -0542 else -0543 if isempty(aSign) -0544 model.grRules{i}=['(' strrep(model.grRules{i},';',' or ') ')']; -0545 else -0546 if isempty(oSign) -0547 model.grRules{i}=['(' strrep(model.grRules{i},':',' and ') ')']; -0548 else -0549 model.grRules{i}=['((' strrep(model.grRules{i},';',') or (') '))']; -0550 model.grRules{i}=strrep(model.grRules{i},':',' and '); -0551 end -0552 end -0553 end -0554 end -0555 end -0556 end -0557 -0558 %Check that the compartment for each reaction can be found -0559 if ~isempty(model.rxnComps) -0560 [I, model.rxnComps]=ismember(model.rxnComps,model.comps); -0561 EM='The following reactions have compartment abbreviations which could not be found:'; -0562 dispEM(EM,true,model.rxns(~I)); -0563 end -0564 -0565 %Get all the metabolites and info about them -0566 [raw, flag]=loadSheet(workbook,'METS'); -0567 -0568 if flag<0 -0569 if printWarnings==true -0570 EM='There is no spreadsheet named METS. The metabolites will be named "m1", "m2"... and assigned to the first compartment'; -0571 dispEM(EM,false); -0572 end -0573 %Parse the equations to find out how many metabolites there are -0574 metsForParsing=parseRxnEqu(equations); -0575 I=num2cell((1:numel(metsForParsing))'); -0576 model.mets=strcat('m',cellfun(@num2str,I,'UniformOutput',false)); -0577 model.metComps=ones(numel(model.mets),1); -0578 model.unconstrained=zeros(numel(model.mets),1); -0579 model.metNames=metsForParsing; -0580 else -0581 raw=cleanSheet(raw); -0582 -0583 %Map to new captions -0584 raw(1,:)=upper(raw(1,:)); -0585 raw(1,:)=strrep(raw(1,:),'METID','ID'); -0586 raw(1,:)=strrep(raw(1,:),'METNAME','NAME'); -0587 -0588 %Loop through the labels -0589 metReplacement={}; -0590 for i=1:numel(raw(1,:)) -0591 switch raw{1,i} -0592 case 'ID' -0593 model.mets=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0594 case 'NAME' -0595 model.metNames=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0596 case 'UNCONSTRAINED' -0597 model.unconstrained=cellfun(@boolToDouble,raw(2:end,i)); -0598 %NaN is returned if the values couldn't be parsed -0599 EM='The UNCONSTRAINED property for the following metabolites must be "true"/"false", 1/0, TRUE/FALSE or not set:'; -0600 dispEM(EM,true,model.mets(isnan(model.unconstrained))); -0601 case 'MIRIAM' -0602 model.metMiriams=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0603 case 'COMPOSITION' -0604 model.metFormulas=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0605 case 'INCHI' -0606 model.inchis=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0607 case 'COMPARTMENT' -0608 model.metComps=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0609 -0610 %Check that all metabolites have compartments defined -0611 if any(strcmp('',model.metComps)) -0612 EM='All metabolites must have an associated compartment string'; -0613 dispEM(EM); -0614 end -0615 case 'REPLACEMENT ID' -0616 metReplacement=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0617 case 'CHARGE' -0618 model.metCharges=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); -0619 end -0620 end -0621 -0622 %Check that necessary fields are loaded (METID) -0623 if isempty(model.mets) -0624 EM='There must be a column named ID in the METS sheet'; -0625 dispEM(EM); -0626 end -0627 -0628 %Check that some other stuff is loaded and use default values otherwise -0629 if isempty(model.metNames) -0630 model.metNames=cell(numel(model.mets),1); -0631 if printWarnings==true -0632 EM='There is no column named NAME in the METS sheet. ID will be used as name'; -0633 dispEM(EM,false); -0634 end -0635 end -0636 if isempty(model.unconstrained) -0637 model.unconstrained=zeros(numel(model.mets),1); -0638 if printWarnings==true -0639 EM='There is no column named UNCONSTRAINED in the METS sheet. All metabolites will be constrained'; -0640 dispEM(EM,false); -0641 end -0642 end -0643 -0644 if isempty(model.metComps) -0645 model.metComps=cell(numel(model.mets),1); -0646 model.metComps(:)=model.comps(1); -0647 if printWarnings==true -0648 EM='There is no column named COMPARTMENT in the METS sheet. All metabolites will be assigned to the first compartment in COMPS. Note that RAVEN makes extensive use of metabolite names and compartments. Some features will therefore not function correctly if metabolite compartments are not correctly assigned'; -0649 dispEM(EM,false); -0650 end -0651 end -0652 -0653 %The composition should be loaded from InChIs when available -0654 I=find(~cellfun(@isempty,model.inchis)); -0655 for i=1:numel(I) -0656 S=regexp(model.inchis(I(i)),'/','split'); -0657 S=S{1}; -0658 if numel(S)>=2 -0659 %Don't copy if it doesn't look good -0660 model.metFormulas(I(i))=S(2); -0661 end -0662 end -0663 -0664 %Check that the compartment for each metabolite can be found. Also -0665 %convert from id to index -0666 [I, model.metComps]=ismember(model.metComps,model.comps); -0667 EM='The following metabolites have compartment abbreviations which could not be found:'; -0668 dispEM(EM,true,model.mets(~I)); -0669 -0670 %Check that the model.mets vector is unique. The problem is that the -0671 %checkModelStruct cannot check for that since only the metReplacements -0672 %(if used) end up in the model structure -0673 I=false(numel(model.mets),1); -0674 [J, K]=unique(model.mets); -0675 if numel(J)~=numel(model.mets) -0676 L=1:numel(model.mets); -0677 L(K)=[]; -0678 I(L)=true; -0679 end -0680 EM='The following metabolites are duplicates:'; -0681 dispEM(EM,~ignoreErrors,model.mets(I)); -0682 -0683 %Check that there are no metabolite IDs which are numbers. This would -0684 %give errors when parsing the equations -0685 I=cellfun(@str2double,model.mets); -0686 EM='The following metabolites have names which cannot be distinguished from numbers:'; -0687 dispEM(EM,~ignoreErrors,model.mets(~isnan(I))); -0688 I=cellfun(@str2double,metReplacement); -0689 EM='The following metabolites have names which cannot be distinguished from numbers:'; -0690 dispEM(EM,~ignoreErrors,metReplacement(~isnan(I))); -0691 -0692 %Replace the metabolite IDs for those IDs that have a corresponding -0693 %replacement metabolite. This is not used for matching, but will be -0694 %checked for consistency with SBML naming conventions -0695 metsForParsing=model.mets; %This is because the equations are written with this -0696 I=cellfun(@any,metReplacement); -0697 model.mets(I)=metReplacement(I); -0698 -0699 %If the metabolite name isn't set, replace it with the metabolite id -0700 I=~cellfun(@any,model.metNames); -0701 model.metNames(I)=model.mets(I); -0702 -0703 %Construct the metMiriams structure -0704 model.metMiriams=parseMiriam(model.metMiriams); -0705 -0706 %Either all metabolites have charge or none of them. Check if it's only -0707 %empty and if so return it to [] -0708 if ~isempty(model.metCharges) -0709 if all(cellfun(@isempty,model.metCharges)) -0710 model.metCharges=[]; -0711 end -0712 end -0713 if ~isempty(model.metCharges) -0714 model.metCharges=str2double(model.metCharges); -0715 end -0716 end -0717 -0718 %Everything seems fine with the metabolite IDs, compartments, genes, and -0719 %reactions -0720 -0721 %Parse the equations -0722 [model.S, mets, badRxns, model.rev]=constructS(equations,metsForParsing,model.rxns); -0723 model.rev=model.rev*1; %Typecast to double -0724 -0725 %Add default constraints -0726 model.lb(isnan(model.lb))=model.annotation.defaultLB.*model.rev(isnan(model.lb)); -0727 model.ub(isnan(model.ub))=model.annotation.defaultUB; -0728 -0729 %Reorder the S matrix so that it fits with the metabolite list in the -0730 %structure -0731 [~, I]=ismember(mets,metsForParsing); -0732 model.S=model.S(I,:); -0733 -0734 %Print warnings about the reactions which contain the same metabolite as -0735 %both reactants and products -0736 EM='The following reactions have metabolites which are present more than once. Only the net reactions will be exported:'; -0737 dispEM(EM,false,model.rxns(badRxns)); -0738 -0739 model.b=zeros(numel(model.mets),1); -0740 -0741 %Fix grRules and reconstruct rxnGeneMat -0742 [grRules,rxnGeneMat] = standardizeGrRules(model,true); -0743 model.grRules = grRules; -0744 model.rxnGeneMat = rxnGeneMat; -0745 -0746 %Remove unused fields -0747 if all(cellfun(@isempty,model.compOutside)) -0748 model=rmfield(model,'compOutside'); -0749 end -0750 if all(cellfun(@isempty,model.compMiriams)) -0751 model=rmfield(model,'compMiriams'); -0752 end -0753 if all(cellfun(@isempty,model.rxnNames)) -0754 model=rmfield(model,'rxnNames'); -0755 end -0756 if isempty(model.rxnComps) -0757 model=rmfield(model,'rxnComps'); -0758 end -0759 if all(cellfun(@isempty,model.grRules)) -0760 model=rmfield(model,'grRules'); -0761 end -0762 if isfield(model,'rxnGeneMat') && isempty(model.rxnGeneMat) -0763 model=rmfield(model,'rxnGeneMat'); -0764 end -0765 if all(cellfun(@isempty,model.subSystems)) -0766 model=rmfield(model,'subSystems'); -0767 end -0768 if all(cellfun(@isempty,model.eccodes)) -0769 model=rmfield(model,'eccodes'); -0770 end -0771 if all(cellfun(@isempty,model.rxnMiriams)) -0772 model=rmfield(model,'rxnMiriams'); -0773 end -0774 if all(cellfun(@isempty,model.rxnNotes)) -0775 model=rmfield(model,'rxnNotes'); -0776 end -0777 if all(cellfun(@isempty,model.rxnReferences)) -0778 model=rmfield(model,'rxnReferences'); -0779 end -0780 if isempty(model.rxnConfidenceScores) -0781 model=rmfield(model,'rxnConfidenceScores'); -0782 end -0783 if isempty(model.genes) -0784 model=rmfield(model,'genes'); -0785 end -0786 if isempty(model.geneComps) -0787 model=rmfield(model,'geneComps'); -0788 end -0789 if isempty(model.geneMiriams) -0790 model=rmfield(model,'geneMiriams'); -0791 end -0792 if all(cellfun(@isempty,model.geneShortNames)) -0793 model=rmfield(model,'geneShortNames'); -0794 end -0795 if all(cellfun(@isempty,model.inchis)) -0796 model=rmfield(model,'inchis'); -0797 end -0798 if all(cellfun(@isempty,model.metFormulas)) -0799 model=rmfield(model,'metFormulas'); -0800 end -0801 if all(cellfun(@isempty,model.metMiriams)) -0802 model=rmfield(model,'metMiriams'); -0803 end -0804 if isempty(model.metCharges) -0805 model=rmfield(model,'metCharges'); -0806 end -0807 -0808 %The model structure has now been reconstructed but it can still contain -0809 %many types of errors. The checkModelConsistency function is used to make -0810 %sure that naming and mapping of stuff looks good -0811 checkModelStruct(model,~ignoreErrors); -0812 -0813 if removeExcMets==true -0814 model=simplifyModel(model); -0815 end +0077 fileName=char(fileName); +0078 +0079 if nargin<2 +0080 removeExcMets=true; +0081 end +0082 if nargin<3 +0083 printWarnings=true; +0084 end +0085 if nargin<4 +0086 ignoreErrors=false; +0087 end +0088 +0089 if ~(exist(fileName,'file')==2) +0090 error('Excel file %s cannot be found',string(fileName)); +0091 end +0092 +0093 %This is to match the order of the fields to those you get from importing +0094 %from SBML +0095 model=[]; +0096 model.id=[]; +0097 model.name=[]; +0098 model.annotation=[]; +0099 %Default bounds if not defined +0100 model.annotation.defaultLB=-1000; +0101 model.annotation.defaultUB=1000; +0102 model.rxns={}; +0103 model.mets={}; +0104 model.S=[]; +0105 model.lb=[]; +0106 model.ub=[]; +0107 model.rev=[]; +0108 model.c=[]; +0109 model.b=[]; +0110 model.comps={}; +0111 model.compNames={}; +0112 model.compOutside={}; +0113 model.compMiriams={}; +0114 model.rxnNames={}; +0115 model.rxnComps={}; %Will be double later +0116 model.grRules={}; +0117 model.rxnGeneMat=[]; +0118 model.subSystems={}; +0119 model.eccodes={}; +0120 model.rxnMiriams={}; +0121 model.rxnNotes={}; +0122 model.rxnReferences={}; +0123 model.rxnConfidenceScores={}; %Will be double later +0124 model.genes={}; +0125 model.geneComps={}; %Will be double later +0126 model.geneMiriams={}; +0127 model.geneShortNames={}; +0128 model.metNames={}; +0129 model.metComps=[]; +0130 model.inchis={}; +0131 model.metFormulas={}; +0132 model.metMiriams={}; +0133 model.metCharges={}; %Will be double later +0134 model.unconstrained=[]; +0135 +0136 workbook=loadWorkbook(fileName); +0137 +0138 [raw, flag]=loadSheet(workbook,'MODEL'); +0139 +0140 if flag<0 +0141 if printWarnings==true +0142 EM='Could not load the MODEL sheet'; +0143 dispEM(EM,false); +0144 end +0145 model.id='UNKNOWN'; +0146 model.name='No model details available'; +0147 else +0148 raw=cleanSheet(raw); +0149 +0150 %It is assumed that the first line is labels and that the second one is +0151 %info +0152 raw(1,:)=upper(raw(1,:)); +0153 raw(1,:)=strrep(raw(1,:),'MODELID','ID'); +0154 raw(1,:)=strrep(raw(1,:),'MODELNAME','NAME'); +0155 raw(1,:)=strrep(raw(1,:),'DESCRIPTION','NAME'); +0156 +0157 %Loop through the labels +0158 for i=1:numel(raw(1,:)) +0159 switch raw{1,i} +0160 case 'ID' +0161 if any(raw{2,i}) +0162 model.id=toStr(raw{2,i}); %Should be string already +0163 else +0164 EM='No model ID supplied'; +0165 dispEM(EM); +0166 end +0167 case 'NAME' +0168 if any(raw{2,i}) +0169 model.name=toStr(raw{2,i}); %Should be string already +0170 else +0171 EM='No model name supplied'; +0172 dispEM(EM); +0173 end +0174 case 'DEFAULT LOWER' +0175 if ~isempty(raw{2,i}) +0176 try +0177 model.annotation.defaultLB=toDouble(raw{2,i},NaN); +0178 catch +0179 EM='DEFAULT LOWER must be numeric'; +0180 dispEM(EM); +0181 end +0182 else +0183 if printWarnings==true +0184 fprintf('NOTE: DEFAULT LOWER not supplied. Uses -1000\n'); +0185 end +0186 model.annotation.defaultLB=-1000; +0187 end +0188 case 'DEFAULT UPPER' +0189 if ~isempty(raw{2,i}) +0190 try +0191 model.annotation.defaultUB=toDouble(raw{2,i},NaN); +0192 catch +0193 EM='DEFAULT UPPER must be numeric'; +0194 dispEM(EM); +0195 end +0196 else +0197 if printWarnings==true +0198 fprintf('NOTE: DEFAULT UPPER not supplied. Uses 1000\n'); +0199 end +0200 model.annotation.defaultUB=1000; +0201 end +0202 case 'TAXONOMY' +0203 if any(raw{2,i}) +0204 model.annotation.taxonomy=toStr(raw{2,i}); %Should be string already +0205 end +0206 case 'CONTACT GIVEN NAME' +0207 if any(raw{2,i}) +0208 model.annotation.givenName=toStr(raw{2,i}); %Should be string already +0209 end +0210 case 'CONTACT FAMILY NAME' +0211 if any(raw{2,i}) +0212 model.annotation.familyName=toStr(raw{2,i}); %Should be string already +0213 end +0214 case 'CONTACT EMAIL' +0215 if any(raw{2,i}) +0216 model.annotation.email=toStr(raw{2,i}); %Should be string already +0217 end +0218 case 'ORGANIZATION' +0219 if any(raw{2,i}) +0220 model.annotation.organization=toStr(raw{2,i}); %Should be string already +0221 end +0222 case 'NOTES' +0223 if any(raw{2,i}) +0224 model.annotation.note=toStr(raw{2,i}); %Should be string already +0225 end +0226 end +0227 end +0228 end +0229 +0230 %Get compartment information +0231 [raw, flag]=loadSheet(workbook,'COMPS'); +0232 +0233 if flag<0 +0234 if printWarnings==true +0235 EM='Could not load the COMPS sheet. All elements will be assigned to a compartment "s" for "System"'; +0236 dispEM(EM,false); +0237 end +0238 model.comps={'s'}; +0239 model.compNames={'System'}; +0240 else +0241 raw=cleanSheet(raw); +0242 +0243 %Map to new captions +0244 raw(1,:)=upper(raw(1,:)); +0245 raw(1,:)=strrep(raw(1,:),'COMPABBREV','ABBREVIATION'); +0246 raw(1,:)=strrep(raw(1,:),'COMPNAME','NAME'); +0247 +0248 %Loop through the labels +0249 for i=1:numel(raw(1,:)) +0250 switch raw{1,i} +0251 case 'ABBREVIATION' +0252 model.comps=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0253 case 'NAME' +0254 model.compNames=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0255 case 'INSIDE' +0256 model.compOutside=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0257 case 'MIRIAM' +0258 model.compMiriams=raw(2:end,i); +0259 end +0260 end +0261 +0262 %Check that necessary fields are loaded +0263 if isempty(model.comps) +0264 EM='There must be a column named ABBREVIATION in the COMPS sheet'; +0265 dispEM(EM); +0266 end +0267 if isempty(model.compNames) +0268 model.compNames=model.comps; +0269 if printWarnings==true +0270 EM='There is no column named NAME in the COMPS sheet. ABBREVIATION will be used as name'; +0271 dispEM(EM,false); +0272 end +0273 end +0274 model.compMiriams=parseMiriam(model.compMiriams); +0275 end +0276 +0277 %Get all the genes and info about them +0278 [raw, flag]=loadSheet(workbook,'GENES'); +0279 +0280 if flag<0 +0281 if printWarnings==true +0282 EM='There is no spreadsheet named GENES'; +0283 dispEM(EM,false) +0284 end +0285 else +0286 raw=cleanSheet(raw); +0287 +0288 %Map to new captions +0289 raw(1,:)=upper(raw(1,:)); +0290 raw(1,:)=strrep(raw(1,:),'GENE NAME','NAME'); +0291 +0292 %Loop through the labels +0293 foundGenes=false; +0294 for i=1:numel(raw(1,:)) +0295 switch raw{1,i} +0296 case 'NAME' +0297 model.genes=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0298 foundGenes=true; +0299 case 'MIRIAM' +0300 model.geneMiriams=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0301 case 'SHORT NAME' +0302 model.geneShortNames=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0303 case 'COMPARTMENT' +0304 model.geneComps=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0305 end +0306 end +0307 +0308 if foundGenes==false +0309 EM='There must be a column named NAME in the GENES sheet'; +0310 dispEM(EM); +0311 end +0312 +0313 %Its ok if all of them are empty +0314 if all(cellfun(@isempty,model.geneComps)) +0315 model.geneComps=[]; +0316 end +0317 +0318 %Check that geneName contain only strings and no empty strings +0319 if ~iscellstr(model.genes) +0320 EM='All gene names have to be strings'; +0321 dispEM(EM); +0322 else +0323 if any(strcmp('',model.genes)) +0324 EM='There can be no empty strings in gene names'; +0325 dispEM(EM); +0326 end +0327 end +0328 +0329 %Check that geneComp contains only strings and no empty string +0330 if ~isempty(model.geneComps) +0331 if ~iscellstr(model.geneComps) +0332 EM='All gene compartments have to be strings'; +0333 dispEM(EM); +0334 else +0335 if any(strcmp('',model.geneComps)) +0336 EM='There can be no empty strings in gene compartments'; +0337 dispEM(EM); +0338 end +0339 end +0340 [I, model.geneComps]=ismember(model.geneComps,model.comps); +0341 EM='The following genes have compartment abbreviations which could not be found:'; +0342 dispEM(EM,true,model.genes(~I)); +0343 end +0344 end +0345 +0346 model.geneMiriams=parseMiriam(model.geneMiriams); +0347 +0348 %Loads the reaction data +0349 [raw, flag]=loadSheet(workbook,'RXNS'); +0350 +0351 if flag<0 +0352 EM='Could not load the RXNS sheet'; +0353 dispEM(EM); +0354 end +0355 +0356 raw=cleanSheet(raw); +0357 +0358 %Map to new captions +0359 raw(1,:)=upper(raw(1,:)); +0360 raw(1,:)=strrep(raw(1,:),'RXNID','ID'); +0361 +0362 %Loop through the labels +0363 equations={}; +0364 reactionReplacement={}; +0365 for i=1:numel(raw(1,:)) +0366 switch raw{1,i} +0367 case 'ID' +0368 model.rxns=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0369 case 'NAME' +0370 model.rxnNames=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0371 case 'EQUATION' +0372 equations=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0373 case 'EC-NUMBER' +0374 model.eccodes=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0375 case 'GENE ASSOCIATION' +0376 model.grRules=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0377 case 'LOWER BOUND' +0378 try +0379 model.lb=cellfun(@(x) toDouble(x,NaN),raw(2:end,i)); +0380 catch +0381 EM='The lower bounds must be numerical values'; +0382 dispEM(EM); +0383 end +0384 case 'UPPER BOUND' +0385 try +0386 model.ub=cellfun(@(x) toDouble(x,NaN),raw(2:end,i)); +0387 catch +0388 EM='The upper bounds must be numerical values'; +0389 dispEM(EM); +0390 end +0391 case 'OBJECTIVE' +0392 try +0393 model.c=cellfun(@(x) toDouble(x,0),raw(2:end,i)); +0394 catch +0395 EM='The objective coefficients must be numerical values'; +0396 dispEM(EM); +0397 end +0398 case 'COMPARTMENT' +0399 model.rxnComps=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0400 case 'SUBSYSTEM' +0401 subsystems=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0402 case 'REPLACEMENT ID' +0403 reactionReplacement=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0404 case 'MIRIAM' +0405 model.rxnMiriams=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0406 case 'NOTE' +0407 model.rxnNotes=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0408 case 'REFERENCE' +0409 model.rxnReferences=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0410 case 'CONFIDENCE SCORE' +0411 model.rxnConfidenceScores=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0412 end +0413 end +0414 +0415 if ~isempty(model.rxnConfidenceScores) +0416 model.rxnConfidenceScores=str2double(model.rxnConfidenceScores); +0417 end +0418 for i=1:numel(subsystems) +0419 model.subSystems{i,1}=cellstr(strsplit(subsystems{i,1},';')); +0420 end +0421 +0422 %Check that all necessary reaction info has been loaded +0423 if isempty(equations) +0424 EM='There must be a column named EQUATION in the RXNS sheet'; +0425 dispEM(EM); +0426 end +0427 if isempty(model.rxns) +0428 if printWarnings==true +0429 EM='There is no column named ID in the RXNS sheet. The reactions will be named as "r1", "r2"...'; +0430 dispEM(EM,false); +0431 end +0432 I=num2cell((1:numel(equations))'); +0433 model.rxns=strcat('r',cellfun(@num2str,I,'UniformOutput',false)); +0434 end +0435 +0436 %Check if some other stuff is loaded and populate with default values +0437 %otherwise +0438 if isempty(model.rxnNames) +0439 model.rxnNames=cell(numel(model.rxns),1); +0440 model.rxnNames(:)={''}; +0441 if printWarnings==true +0442 EM='There is no column named NAME in the RXNS sheet. Empty strings will be used as reaction names'; +0443 dispEM(EM,false); +0444 end +0445 end +0446 if isempty(model.lb) +0447 %This is not set here since the reversibility isn't known yet +0448 model.lb=nan(numel(model.rxns),1); +0449 if printWarnings==true +0450 EM='There is no column named LOWER BOUND in the RXNS sheet. Default bounds will be used'; +0451 dispEM(EM,false); +0452 end +0453 end +0454 if isempty(model.ub) +0455 model.ub=nan(numel(model.rxns),1); +0456 if printWarnings==true +0457 EM='There is no column named UPPER BOUND in the RXNS sheet. Default bounds will be used'; +0458 dispEM(EM,false); +0459 end +0460 end +0461 if isempty(model.c) +0462 model.c=zeros(numel(model.rxns),1); +0463 if printWarnings==true +0464 EM='There is no column named OBJECTIVE in the RXNS sheet'; +0465 dispEM(EM,false); +0466 end +0467 end +0468 +0469 %Either all reactions must have a compartment string or none of them. Check +0470 %if it's only empty and if so return it to [] +0471 if ~isempty(model.rxnComps) +0472 if all(cellfun(@isempty,model.rxnComps)) +0473 model.rxnComps=[]; +0474 end +0475 end +0476 +0477 %Construct the rxnMiriams structure +0478 model.rxnMiriams=parseMiriam(model.rxnMiriams); +0479 +0480 %Replace the reaction IDs for those IDs that have a corresponding +0481 %replacement name. +0482 I=cellfun(@any,reactionReplacement); +0483 model.rxns(I)=reactionReplacement(I); +0484 +0485 %Check that there are no empty strings in reactionIDs or equations +0486 if any(strcmp('',model.rxns)) +0487 EM='There are empty reaction IDs'; +0488 dispEM(EM); +0489 end +0490 +0491 if any(strcmp('',equations)) +0492 EM='There are empty equations'; +0493 dispEM(EM); +0494 end +0495 +0496 if ~isempty(model.rxnComps) +0497 if any(strcmp('',model.rxnComps)) +0498 EM='Either all reactions must have an associated compartment string or none of them'; +0499 dispEM(EM); +0500 end +0501 end +0502 +0503 if ~isempty(model.grRules) +0504 tempRules=model.grRules; +0505 for i=1:length(model.rxns) +0506 %Check that all gene associations have a match in the gene list +0507 if ~isempty(model.grRules{i}) +0508 tempRules{i}=regexprep(tempRules{i},' and | or ','>'); %New format: Genes are separated 'and' and 'or' strings with parentheses +0509 tempRules{i}=regexprep(tempRules{i},'(',''); %New format: Genes are separated 'and' and 'or' strings with parentheses +0510 tempRules{i}=regexprep(tempRules{i},')',''); %New format: Genes are separated 'and' and 'or' strings with parentheses +0511 indexesNew=strfind(tempRules{i},'>'); %Old format: Genes are separated by ":" for AND and ";" for OR +0512 indexes=strfind(tempRules{i},':'); %Old format: Genes are separated by ":" for AND and ";" for OR +0513 indexes=unique([indexesNew indexes strfind(tempRules{i},';')]); +0514 if isempty(indexes) +0515 %See if you have a match +0516 I=find(strcmp(tempRules{i},model.genes)); +0517 if isempty(I) +0518 EM=['The gene association in reaction ' model.rxns{i} ' (' tempRules{i} ') is not present in the gene list']; +0519 dispEM(EM); +0520 end +0521 else +0522 temp=[0 indexes numel(tempRules{i})+1]; +0523 for j=1:numel(indexes)+1 +0524 %The reaction has several associated genes +0525 geneName=tempRules{i}(temp(j)+1:temp(j+1)-1); +0526 I=find(strcmp(geneName,model.genes)); +0527 if isempty(I) +0528 EM=['The gene association in reaction ' model.rxns{i} ' (' geneName ') is not present in the gene list']; +0529 dispEM(EM); +0530 end +0531 end +0532 end +0533 %In order to adhere to the COBRA standards it should be like +0534 %this: -If only one gene then no parentheses -If only "and" or +0535 %only "or" there should only be one set of parentheses -If both +0536 %"and" and "or", then split on "or". This is not complete, but +0537 %it's the type of relationship supported by the Excel +0538 %formulation +0539 aSign=strfind(model.grRules{i},':'); +0540 oSign=strfind(model.grRules{i},';'); +0541 if isempty(aSign) && isempty(oSign) +0542 model.grRules{i}=model.grRules{i}; +0543 else +0544 if isempty(aSign) +0545 model.grRules{i}=['(' strrep(model.grRules{i},';',' or ') ')']; +0546 else +0547 if isempty(oSign) +0548 model.grRules{i}=['(' strrep(model.grRules{i},':',' and ') ')']; +0549 else +0550 model.grRules{i}=['((' strrep(model.grRules{i},';',') or (') '))']; +0551 model.grRules{i}=strrep(model.grRules{i},':',' and '); +0552 end +0553 end +0554 end +0555 end +0556 end +0557 end +0558 +0559 %Check that the compartment for each reaction can be found +0560 if ~isempty(model.rxnComps) +0561 [I, model.rxnComps]=ismember(model.rxnComps,model.comps); +0562 EM='The following reactions have compartment abbreviations which could not be found:'; +0563 dispEM(EM,true,model.rxns(~I)); +0564 end +0565 +0566 %Get all the metabolites and info about them +0567 [raw, flag]=loadSheet(workbook,'METS'); +0568 +0569 if flag<0 +0570 if printWarnings==true +0571 EM='There is no spreadsheet named METS. The metabolites will be named "m1", "m2"... and assigned to the first compartment'; +0572 dispEM(EM,false); +0573 end +0574 %Parse the equations to find out how many metabolites there are +0575 metsForParsing=parseRxnEqu(equations); +0576 I=num2cell((1:numel(metsForParsing))'); +0577 model.mets=strcat('m',cellfun(@num2str,I,'UniformOutput',false)); +0578 model.metComps=ones(numel(model.mets),1); +0579 model.unconstrained=zeros(numel(model.mets),1); +0580 model.metNames=metsForParsing; +0581 else +0582 raw=cleanSheet(raw); +0583 +0584 %Map to new captions +0585 raw(1,:)=upper(raw(1,:)); +0586 raw(1,:)=strrep(raw(1,:),'METID','ID'); +0587 raw(1,:)=strrep(raw(1,:),'METNAME','NAME'); +0588 +0589 %Loop through the labels +0590 metReplacement={}; +0591 for i=1:numel(raw(1,:)) +0592 switch raw{1,i} +0593 case 'ID' +0594 model.mets=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0595 case 'NAME' +0596 model.metNames=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0597 case 'UNCONSTRAINED' +0598 model.unconstrained=cellfun(@boolToDouble,raw(2:end,i)); +0599 %NaN is returned if the values couldn't be parsed +0600 EM='The UNCONSTRAINED property for the following metabolites must be "true"/"false", 1/0, TRUE/FALSE or not set:'; +0601 dispEM(EM,true,model.mets(isnan(model.unconstrained))); +0602 case 'MIRIAM' +0603 model.metMiriams=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0604 case 'COMPOSITION' +0605 model.metFormulas=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0606 case 'INCHI' +0607 model.inchis=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0608 case 'COMPARTMENT' +0609 model.metComps=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0610 +0611 %Check that all metabolites have compartments defined +0612 if any(strcmp('',model.metComps)) +0613 EM='All metabolites must have an associated compartment string'; +0614 dispEM(EM); +0615 end +0616 case 'REPLACEMENT ID' +0617 metReplacement=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0618 case 'CHARGE' +0619 model.metCharges=cellfun(@toStr,raw(2:end,i),'UniformOutput',false); +0620 end +0621 end +0622 +0623 %Check that necessary fields are loaded (METID) +0624 if isempty(model.mets) +0625 EM='There must be a column named ID in the METS sheet'; +0626 dispEM(EM); +0627 end +0628 +0629 %Check that some other stuff is loaded and use default values otherwise +0630 if isempty(model.metNames) +0631 model.metNames=cell(numel(model.mets),1); +0632 if printWarnings==true +0633 EM='There is no column named NAME in the METS sheet. ID will be used as name'; +0634 dispEM(EM,false); +0635 end +0636 end +0637 if isempty(model.unconstrained) +0638 model.unconstrained=zeros(numel(model.mets),1); +0639 if printWarnings==true +0640 EM='There is no column named UNCONSTRAINED in the METS sheet. All metabolites will be constrained'; +0641 dispEM(EM,false); +0642 end +0643 end +0644 +0645 if isempty(model.metComps) +0646 model.metComps=cell(numel(model.mets),1); +0647 model.metComps(:)=model.comps(1); +0648 if printWarnings==true +0649 EM='There is no column named COMPARTMENT in the METS sheet. All metabolites will be assigned to the first compartment in COMPS. Note that RAVEN makes extensive use of metabolite names and compartments. Some features will therefore not function correctly if metabolite compartments are not correctly assigned'; +0650 dispEM(EM,false); +0651 end +0652 end +0653 +0654 %The composition should be loaded from InChIs when available +0655 I=find(~cellfun(@isempty,model.inchis)); +0656 for i=1:numel(I) +0657 S=regexp(model.inchis(I(i)),'/','split'); +0658 S=S{1}; +0659 if numel(S)>=2 +0660 %Don't copy if it doesn't look good +0661 model.metFormulas(I(i))=S(2); +0662 end +0663 end +0664 +0665 %Check that the compartment for each metabolite can be found. Also +0666 %convert from id to index +0667 [I, model.metComps]=ismember(model.metComps,model.comps); +0668 EM='The following metabolites have compartment abbreviations which could not be found:'; +0669 dispEM(EM,true,model.mets(~I)); +0670 +0671 %Check that the model.mets vector is unique. The problem is that the +0672 %checkModelStruct cannot check for that since only the metReplacements +0673 %(if used) end up in the model structure +0674 I=false(numel(model.mets),1); +0675 [J, K]=unique(model.mets); +0676 if numel(J)~=numel(model.mets) +0677 L=1:numel(model.mets); +0678 L(K)=[]; +0679 I(L)=true; +0680 end +0681 EM='The following metabolites are duplicates:'; +0682 dispEM(EM,~ignoreErrors,model.mets(I)); +0683 +0684 %Check that there are no metabolite IDs which are numbers. This would +0685 %give errors when parsing the equations +0686 I=cellfun(@str2double,model.mets); +0687 EM='The following metabolites have names which cannot be distinguished from numbers:'; +0688 dispEM(EM,~ignoreErrors,model.mets(~isnan(I))); +0689 I=cellfun(@str2double,metReplacement); +0690 EM='The following metabolites have names which cannot be distinguished from numbers:'; +0691 dispEM(EM,~ignoreErrors,metReplacement(~isnan(I))); +0692 +0693 %Replace the metabolite IDs for those IDs that have a corresponding +0694 %replacement metabolite. This is not used for matching, but will be +0695 %checked for consistency with SBML naming conventions +0696 metsForParsing=model.mets; %This is because the equations are written with this +0697 I=cellfun(@any,metReplacement); +0698 model.mets(I)=metReplacement(I); +0699 +0700 %If the metabolite name isn't set, replace it with the metabolite id +0701 I=~cellfun(@any,model.metNames); +0702 model.metNames(I)=model.mets(I); +0703 +0704 %Construct the metMiriams structure +0705 model.metMiriams=parseMiriam(model.metMiriams); +0706 +0707 %Either all metabolites have charge or none of them. Check if it's only +0708 %empty and if so return it to [] +0709 if ~isempty(model.metCharges) +0710 if all(cellfun(@isempty,model.metCharges)) +0711 model.metCharges=[]; +0712 end +0713 end +0714 if ~isempty(model.metCharges) +0715 model.metCharges=str2double(model.metCharges); +0716 end +0717 end +0718 +0719 %Everything seems fine with the metabolite IDs, compartments, genes, and +0720 %reactions +0721 +0722 %Parse the equations +0723 [model.S, mets, badRxns, model.rev]=constructS(equations,metsForParsing,model.rxns); +0724 model.rev=model.rev*1; %Typecast to double +0725 +0726 %Add default constraints +0727 model.lb(isnan(model.lb))=model.annotation.defaultLB.*model.rev(isnan(model.lb)); +0728 model.ub(isnan(model.ub))=model.annotation.defaultUB; +0729 +0730 %Reorder the S matrix so that it fits with the metabolite list in the +0731 %structure +0732 [~, I]=ismember(mets,metsForParsing); +0733 model.S=model.S(I,:); +0734 +0735 %Print warnings about the reactions which contain the same metabolite as +0736 %both reactants and products +0737 EM='The following reactions have metabolites which are present more than once. Only the net reactions will be exported:'; +0738 dispEM(EM,false,model.rxns(badRxns)); +0739 +0740 model.b=zeros(numel(model.mets),1); +0741 +0742 %Fix grRules and reconstruct rxnGeneMat +0743 [grRules,rxnGeneMat] = standardizeGrRules(model,true); +0744 model.grRules = grRules; +0745 model.rxnGeneMat = rxnGeneMat; +0746 +0747 %Remove unused fields +0748 if all(cellfun(@isempty,model.compOutside)) +0749 model=rmfield(model,'compOutside'); +0750 end +0751 if all(cellfun(@isempty,model.compMiriams)) +0752 model=rmfield(model,'compMiriams'); +0753 end +0754 if all(cellfun(@isempty,model.rxnNames)) +0755 model=rmfield(model,'rxnNames'); +0756 end +0757 if isempty(model.rxnComps) +0758 model=rmfield(model,'rxnComps'); +0759 end +0760 if all(cellfun(@isempty,model.grRules)) +0761 model=rmfield(model,'grRules'); +0762 end +0763 if isfield(model,'rxnGeneMat') && isempty(model.rxnGeneMat) +0764 model=rmfield(model,'rxnGeneMat'); +0765 end +0766 if all(cellfun(@isempty,model.subSystems)) +0767 model=rmfield(model,'subSystems'); +0768 end +0769 if all(cellfun(@isempty,model.eccodes)) +0770 model=rmfield(model,'eccodes'); +0771 end +0772 if all(cellfun(@isempty,model.rxnMiriams)) +0773 model=rmfield(model,'rxnMiriams'); +0774 end +0775 if all(cellfun(@isempty,model.rxnNotes)) +0776 model=rmfield(model,'rxnNotes'); +0777 end +0778 if all(cellfun(@isempty,model.rxnReferences)) +0779 model=rmfield(model,'rxnReferences'); +0780 end +0781 if isempty(model.rxnConfidenceScores) +0782 model=rmfield(model,'rxnConfidenceScores'); +0783 end +0784 if isempty(model.genes) +0785 model=rmfield(model,'genes'); +0786 end +0787 if isempty(model.geneComps) +0788 model=rmfield(model,'geneComps'); +0789 end +0790 if isempty(model.geneMiriams) +0791 model=rmfield(model,'geneMiriams'); +0792 end +0793 if all(cellfun(@isempty,model.geneShortNames)) +0794 model=rmfield(model,'geneShortNames'); +0795 end +0796 if all(cellfun(@isempty,model.inchis)) +0797 model=rmfield(model,'inchis'); +0798 end +0799 if all(cellfun(@isempty,model.metFormulas)) +0800 model=rmfield(model,'metFormulas'); +0801 end +0802 if all(cellfun(@isempty,model.metMiriams)) +0803 model=rmfield(model,'metMiriams'); +0804 end +0805 if isempty(model.metCharges) +0806 model=rmfield(model,'metCharges'); +0807 end +0808 +0809 %The model structure has now been reconstructed but it can still contain +0810 %many types of errors. The checkModelConsistency function is used to make +0811 %sure that naming and mapping of stuff looks good +0812 checkModelStruct(model,~ignoreErrors); +0813 +0814 if removeExcMets==true +0815 model=simplifyModel(model); 0816 end -0817 -0818 function miriamStruct=parseMiriam(strings,miriamStruct) -0819 %Gets the names and values of Miriam-string. Nothing fancy at all, just to -0820 %prevent using the same code for metabolites, genes, and reactions. The -0821 %function also allows for supplying a miriamStruct and the info will then -0822 %be added -0823 -0824 if nargin<2 -0825 miriamStruct=cell(numel(strings),1); -0826 end -0827 for i=1:numel(strings) -0828 if any(strings{i}) -0829 %A Miriam string can be several ids separated by ";". Each id is -0830 %"name(..:..)/value"; an old format when value is separated by -0831 %colon is also supported -0832 I=regexp(strings{i},';','split'); -0833 if isfield(miriamStruct{i},'name') -0834 startIndex=numel(miriamStruct{i}.name); -0835 miriamStruct{i}.name=[miriamStruct{i}.name;cell(numel(I),1)]; -0836 miriamStruct{i}.value=[miriamStruct{i}.value;cell(numel(I),1)]; -0837 else -0838 startIndex=0; -0839 miriamStruct{i}.name=cell(numel(I),1); -0840 miriamStruct{i}.value=cell(numel(I),1); -0841 end -0842 -0843 for j=1:numel(I) -0844 if any(strfind(I{j},'/')) -0845 index=max(strfind(I{j},'/')); -0846 elseif any(strfind(I{j},':')) -0847 index=max(strfind(I{j},':')); -0848 end -0849 if any(index) -0850 miriamStruct{i}.name{startIndex+j}=I{j}(1:index-1); -0851 miriamStruct{i}.value{startIndex+j}=I{j}(index+1:end); -0852 else -0853 EM=['"' I{j} '" is not a valid MIRIAM string. The format must be "identifier/value" or identifier:value']; -0854 dispEM(EM); -0855 end -0856 end -0857 end -0858 end +0817 end +0818 +0819 function miriamStruct=parseMiriam(strings,miriamStruct) +0820 %Gets the names and values of Miriam-string. Nothing fancy at all, just to +0821 %prevent using the same code for metabolites, genes, and reactions. The +0822 %function also allows for supplying a miriamStruct and the info will then +0823 %be added +0824 +0825 if nargin<2 +0826 miriamStruct=cell(numel(strings),1); +0827 end +0828 for i=1:numel(strings) +0829 if any(strings{i}) +0830 %A Miriam string can be several ids separated by ";". Each id is +0831 %"name(..:..)/value"; an old format when value is separated by +0832 %colon is also supported +0833 I=regexp(strings{i},';','split'); +0834 if isfield(miriamStruct{i},'name') +0835 startIndex=numel(miriamStruct{i}.name); +0836 miriamStruct{i}.name=[miriamStruct{i}.name;cell(numel(I),1)]; +0837 miriamStruct{i}.value=[miriamStruct{i}.value;cell(numel(I),1)]; +0838 else +0839 startIndex=0; +0840 miriamStruct{i}.name=cell(numel(I),1); +0841 miriamStruct{i}.value=cell(numel(I),1); +0842 end +0843 +0844 for j=1:numel(I) +0845 if any(strfind(I{j},'/')) +0846 index=max(strfind(I{j},'/')); +0847 elseif any(strfind(I{j},':')) +0848 index=max(strfind(I{j},':')); +0849 end +0850 if any(index) +0851 miriamStruct{i}.name{startIndex+j}=I{j}(1:index-1); +0852 miriamStruct{i}.value{startIndex+j}=I{j}(index+1:end); +0853 else +0854 EM=['"' I{j} '" is not a valid MIRIAM string. The format must be "identifier/value" or identifier:value']; +0855 dispEM(EM); +0856 end +0857 end +0858 end 0859 end -0860 -0861 %For converting a value to string. This is used instead of num2str because -0862 %I want to convert empty cells to {''}. -0863 function y=toStr(x) -0864 %x can be empty, numerical, string or boolean. It cannot be NaN. Boolean -0865 %values will be converted to '1'/'0' -0866 if isempty(x) -0867 y=''; -0868 else -0869 y=num2str(x); -0870 end +0860 end +0861 +0862 %For converting a value to string. This is used instead of num2str because +0863 %I want to convert empty cells to {''}. +0864 function y=toStr(x) +0865 %x can be empty, numerical, string or boolean. It cannot be NaN. Boolean +0866 %values will be converted to '1'/'0' +0867 if isempty(x) +0868 y=''; +0869 else +0870 y=num2str(x); 0871 end -0872 -0873 %For converting to numeric. This is used instead of str2num because I want -0874 %to be able to choose what empty values should be mapped to. -0875 % -0876 % default the value to use for empty input -0877 function y=toDouble(x,default) -0878 if isempty(x) %Note that this catches '' as well -0879 y=default; -0880 else -0881 if isnumeric(x) -0882 y=x; -0883 else -0884 y=str2double(x); -0885 -0886 %This happens if the input couldn't be converted. Note that the -0887 %input itself cannot be NaN since it was fixed in clean imported -0888 if isnan(y) -0889 EM=['Cannot convert the string "' x '" to double']; -0890 dispEM(EM); -0891 end -0892 end -0893 end +0872 end +0873 +0874 %For converting to numeric. This is used instead of str2num because I want +0875 %to be able to choose what empty values should be mapped to. +0876 % +0877 % default the value to use for empty input +0878 function y=toDouble(x,default) +0879 if isempty(x) %Note that this catches '' as well +0880 y=default; +0881 else +0882 if isnumeric(x) +0883 y=x; +0884 else +0885 y=str2double(x); +0886 +0887 %This happens if the input couldn't be converted. Note that the +0888 %input itself cannot be NaN since it was fixed in clean imported +0889 if isnan(y) +0890 EM=['Cannot convert the string "' x '" to double']; +0891 dispEM(EM); +0892 end +0893 end 0894 end -0895 -0896 %For converting boolean (the UNCONSTRAINED field) to double (the -0897 %model.unconstrained field) -0898 function y=boolToDouble(x) -0899 if isempty(x) -0900 y=0; -0901 return; -0902 end -0903 if islogical(x) -0904 y=x*1; %Typecast to double -0905 return; -0906 end -0907 if isnumeric(x) -0908 if x~=0 -0909 y=1; -0910 return; -0911 else -0912 y=0; -0913 return; -0914 end -0915 end -0916 if ischar(x) -0917 if strcmpi(x,'TRUE') -0918 y=1; -0919 return; -0920 end -0921 if strcmpi(x,'FALSE') -0922 y=0; -0923 return; -0924 end -0925 end -0926 y=NaN; %This means that the input couldn't be parsed -0927 end +0895 end +0896 +0897 %For converting boolean (the UNCONSTRAINED field) to double (the +0898 %model.unconstrained field) +0899 function y=boolToDouble(x) +0900 if isempty(x) +0901 y=0; +0902 return; +0903 end +0904 if islogical(x) +0905 y=x*1; %Typecast to double +0906 return; +0907 end +0908 if isnumeric(x) +0909 if x~=0 +0910 y=1; +0911 return; +0912 else +0913 y=0; +0914 return; +0915 end +0916 end +0917 if ischar(x) +0918 if strcmpi(x,'TRUE') +0919 y=1; +0920 return; +0921 end +0922 if strcmpi(x,'FALSE') +0923 y=0; +0924 return; +0925 end +0926 end +0927 y=NaN; %This means that the input couldn't be parsed +0928 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/importModel.html b/doc/io/importModel.html index bd66a70f..11369716 100644 --- a/doc/io/importModel.html +++ b/doc/io/importModel.html @@ -105,7 +105,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • checkFileExistence checkFileExistence
  • This function is called by: @@ -190,7 +190,7 @@

    SOURCE CODE ^% consensus network model formulation. 0073 % 0074 % Usage: model=importModel(fileName,removeExcMets,isSBML2COBRA,supressWarnings) -0075 +0075 fileName=char(fileName); 0076 if nargin<2 0077 removeExcMets=true; 0078 end @@ -248,1079 +248,1083 @@

    SOURCE CODE ^%Load the model using libSBML -0133 modelSBML = TranslateSBML(fileName,0,0,[1 1]); -0134 -0135 if isempty(modelSBML) -0136 EM='There is a problem with the SBML file. Try using the SBML Validator at http://sbml.org/Facilities/Validator'; -0137 dispEM(EM); -0138 end -0139 -0140 %Remove the preceding strings for reactions, compartments and -0141 %reactants/products in 'reaction' field. The strings for metabolites, genes -0142 %and complexes are not removed, as we will need them later to identify them -0143 %from 'species' field -0144 for i=1:numel(modelSBML.reaction) -0145 modelSBML.reaction(i).name=regexprep(modelSBML.reaction(i).name,'^R_',''); -0146 modelSBML.reaction(i).id=regexprep(modelSBML.reaction(i).id,'^R_',''); -0147 if isfield(modelSBML.reaction(i),'compartment') -0148 modelSBML.reaction(i).compartment=regexprep(modelSBML.reaction(i).compartment,'^C_',''); -0149 end -0150 for j=1:numel(modelSBML.reaction(i).reactant) -0151 modelSBML.reaction(i).reactant(j).species=regexprep(modelSBML.reaction(i).reactant(j).species,'^M_',''); -0152 end -0153 for j=1:numel(modelSBML.reaction(i).product) -0154 modelSBML.reaction(i).product(j).species=regexprep(modelSBML.reaction(i).product(j).species,'^M_',''); -0155 end -0156 end -0157 -0158 %Retrieve compartment names and IDs -0159 compartmentNames=cell(numel(modelSBML.compartment),1); -0160 compartmentIDs=cell(numel(modelSBML.compartment),1); -0161 compartmentOutside=cell(numel(modelSBML.compartment),1); -0162 compartmentMiriams=cell(numel(modelSBML.compartment),1); -0163 -0164 if isfield(modelSBML.compartment,'sboTerm') && numel(unique([modelSBML.compartment.sboTerm])) == 1 -0165 %If all the SBO terms are identical, don't add them to compMiriams -0166 modelSBML.compartment = rmfield(modelSBML.compartment,'sboTerm'); -0167 end -0168 -0169 for i=1:numel(modelSBML.compartment) -0170 compartmentNames{i}=modelSBML.compartment(i).name; -0171 compartmentIDs{i}=regexprep(modelSBML.compartment(i).id,'^C_',''); -0172 if isfield(modelSBML.compartment(i),'outside') -0173 if ~isempty(modelSBML.compartment(i).outside) -0174 compartmentOutside{i}=regexprep(modelSBML.compartment(i).outside,'^C_',''); -0175 else -0176 compartmentOutside{i}=''; -0177 end -0178 else -0179 compartmentOutside{i}=[]; -0180 end -0181 -0182 if isfield(modelSBML.compartment(i),'annotation') -0183 compartmentMiriams{i}=parseMiriam(modelSBML.compartment(i).annotation); -0184 else -0185 compartmentMiriams{i}=[]; -0186 end -0187 -0188 if isfield(modelSBML.compartment(i),'sboTerm') -0189 compartmentMiriams{i} = addSBOtoMiriam(compartmentMiriams{i},modelSBML.compartment(i).sboTerm); +0133 [ravenDir,prevDir]=findRAVENroot(); +0134 fileName=checkFileExistence(fileName,1); +0135 cd(fullfile(ravenDir,'software','libSBML')); +0136 modelSBML = TranslateSBML(fileName,0,0,[1 1]); +0137 cd(prevDir); +0138 +0139 if isempty(modelSBML) +0140 EM='There is a problem with the SBML file. Try using the SBML Validator at http://sbml.org/Facilities/Validator'; +0141 dispEM(EM); +0142 end +0143 +0144 %Remove the preceding strings for reactions, compartments and +0145 %reactants/products in 'reaction' field. The strings for metabolites, genes +0146 %and complexes are not removed, as we will need them later to identify them +0147 %from 'species' field +0148 for i=1:numel(modelSBML.reaction) +0149 modelSBML.reaction(i).name=regexprep(modelSBML.reaction(i).name,'^R_',''); +0150 modelSBML.reaction(i).id=regexprep(modelSBML.reaction(i).id,'^R_',''); +0151 if isfield(modelSBML.reaction(i),'compartment') +0152 modelSBML.reaction(i).compartment=regexprep(modelSBML.reaction(i).compartment,'^C_',''); +0153 end +0154 for j=1:numel(modelSBML.reaction(i).reactant) +0155 modelSBML.reaction(i).reactant(j).species=regexprep(modelSBML.reaction(i).reactant(j).species,'^M_',''); +0156 end +0157 for j=1:numel(modelSBML.reaction(i).product) +0158 modelSBML.reaction(i).product(j).species=regexprep(modelSBML.reaction(i).product(j).species,'^M_',''); +0159 end +0160 end +0161 +0162 %Retrieve compartment names and IDs +0163 compartmentNames=cell(numel(modelSBML.compartment),1); +0164 compartmentIDs=cell(numel(modelSBML.compartment),1); +0165 compartmentOutside=cell(numel(modelSBML.compartment),1); +0166 compartmentMiriams=cell(numel(modelSBML.compartment),1); +0167 +0168 if isfield(modelSBML.compartment,'sboTerm') && numel(unique([modelSBML.compartment.sboTerm])) == 1 +0169 %If all the SBO terms are identical, don't add them to compMiriams +0170 modelSBML.compartment = rmfield(modelSBML.compartment,'sboTerm'); +0171 end +0172 +0173 for i=1:numel(modelSBML.compartment) +0174 compartmentNames{i}=modelSBML.compartment(i).name; +0175 compartmentIDs{i}=regexprep(modelSBML.compartment(i).id,'^C_',''); +0176 if isfield(modelSBML.compartment(i),'outside') +0177 if ~isempty(modelSBML.compartment(i).outside) +0178 compartmentOutside{i}=regexprep(modelSBML.compartment(i).outside,'^C_',''); +0179 else +0180 compartmentOutside{i}=''; +0181 end +0182 else +0183 compartmentOutside{i}=[]; +0184 end +0185 +0186 if isfield(modelSBML.compartment(i),'annotation') +0187 compartmentMiriams{i}=parseMiriam(modelSBML.compartment(i).annotation); +0188 else +0189 compartmentMiriams{i}=[]; 0190 end -0191 end -0192 -0193 %If there are no compartment names then use compartment id as name -0194 if all(cellfun(@isempty,compartmentNames)) -0195 compartmentNames=compartmentIDs; -0196 end -0197 -0198 %Retrieve info on metabolites, genes, complexes -0199 metaboliteNames={}; -0200 metaboliteIDs={}; -0201 metaboliteCompartments={}; -0202 metaboliteUnconstrained=[]; -0203 metaboliteFormula={}; -0204 metaboliteInChI={}; -0205 metaboliteMiriams={}; -0206 metaboliteCharges=[]; -0207 -0208 geneNames={}; -0209 geneIDs={}; -0210 geneMiriams={}; -0211 geneShortNames={}; -0212 geneCompartments={}; -0213 complexIDs={}; -0214 complexNames={}; -0215 -0216 %If the file is not a COBRA Toolbox model. According to the format -0217 %specified in the yeast consensus model both metabolites and genes are a -0218 %type of 'species'. The metabolites have names starting with 'M_' and genes -0219 %with 'E_' -0220 geneSBOs = []; -0221 metSBOs = []; -0222 %Regex of compartment names, later to be used to remove from metabolite -0223 %names if present as suffix. -0224 regexCompNames = ['\s?\[((' strjoin({modelSBML.compartment.name},')|(') '))\]$']; -0225 for i=1:numel(modelSBML.species) -0226 if ~isSBML2COBRA -0227 if length(modelSBML.species(i).id)>=2 && strcmpi(modelSBML.species(i).id(1:2),'E_') -0228 geneNames{numel(geneNames)+1,1}=modelSBML.species(i).name; -0229 -0230 %The "E_" is included in the ID. This is because it's only used -0231 %internally in this file and it makes the matching a little -0232 %smoother -0233 geneIDs{numel(geneIDs)+1,1}=modelSBML.species(i).id; -0234 geneCompartments{numel(geneCompartments)+1,1}=regexprep(modelSBML.species(i).compartment,'^C_',''); -0235 -0236 %Get Miriam structure -0237 if isfield(modelSBML.species(i),'annotation') -0238 %Get Miriam info -0239 geneMiriam=parseMiriam(modelSBML.species(i).annotation); -0240 geneMiriams{numel(geneMiriams)+1,1}=geneMiriam; -0241 else -0242 geneMiriams{numel(geneMiriams)+1,1}=[]; -0243 end -0244 -0245 %Protein short names (for example ERG10) are saved as SHORT -0246 %NAME: NAME in the notes-section of metabolites for SBML Level -0247 %2 and as PROTEIN_ASSOCIATION for each reaction in SBML Level 2 -0248 %COBRA Toolbox format. For now only the SHORT NAME is loaded -0249 %and no mapping takes place -0250 if isfield(modelSBML.species(i),'notes') -0251 geneShortNames{numel(geneShortNames)+1,1}=parseNote(modelSBML.species(i).notes,'SHORT NAME'); -0252 else -0253 geneShortNames{numel(geneShortNames)+1,1}=''; -0254 end -0255 -0256 %Get SBO term -0257 if isfield(modelSBML.species(i),'sboTerm') -0258 geneSBOs(end+1,1) = modelSBML.species(i).sboTerm; -0259 end -0260 elseif length(modelSBML.species(i).id)>=2 && strcmpi(modelSBML.species(i).id(1:3),'Cx_') -0261 %If it's a complex keep the ID and name -0262 complexIDs=[complexIDs;modelSBML.species(i).id]; -0263 complexNames=[complexNames;modelSBML.species(i).name]; -0264 else -0265 %If it is not gene or complex, then it must be a metabolite -0266 metaboliteNames{numel(metaboliteNames)+1,1}=modelSBML.species(i).name; -0267 metaboliteIDs{numel(metaboliteIDs)+1,1}=regexprep(modelSBML.species(i).id,'^M_',''); -0268 metaboliteCompartments{numel(metaboliteCompartments)+1,1}=regexprep(modelSBML.species(i).compartment,'^C_',''); -0269 metaboliteUnconstrained(numel(metaboliteUnconstrained)+1,1)=modelSBML.species(i).boundaryCondition; -0270 -0271 %For each metabolite retrieve the formula and the InChI code if -0272 %available First add the InChI code and the formula from the -0273 %InChI. This allows for overwriting the formula by setting the -0274 %actual formula field -0275 if ~isempty(modelSBML.species(i).annotation) -0276 %Get the formula if available -0277 startString='>InChI='; -0278 endString='</in:inchi>'; -0279 formStart=strfind(modelSBML.species(i).annotation,startString); -0280 if isempty(formStart) -0281 startString='InChI='; -0282 endString='"/>'; -0283 end -0284 formStart=strfind(modelSBML.species(i).annotation,startString); -0285 if ~isempty(formStart) -0286 formEnd=strfind(modelSBML.species(i).annotation,endString); -0287 formEndIndex=find(formEnd>formStart, 1 ); -0288 formula=modelSBML.species(i).annotation(formStart+numel(startString):formEnd(formEndIndex)-1); -0289 metaboliteInChI{numel(metaboliteInChI)+1,1}=formula; -0290 -0291 %The composition is most often present between the -0292 %first and second "/" in the model. In some simple -0293 %molecules, such as salts, there is no second "/". The -0294 %formula is then assumed to be to the end of the string -0295 compositionIndexes=strfind(formula,'/'); -0296 if numel(compositionIndexes)>1 -0297 metaboliteFormula{numel(metaboliteFormula)+1,1}=... -0298 formula(compositionIndexes(1)+1:compositionIndexes(2)-1); -0299 else -0300 if numel(compositionIndexes)==1 -0301 %Probably a simple molecule which can have only -0302 %one conformation -0303 metaboliteFormula{numel(metaboliteFormula)+1,1}=... -0304 formula(compositionIndexes(1)+1:numel(formula)); -0305 else -0306 metaboliteFormula{numel(metaboliteFormula)+1,1}=''; -0307 end -0308 end -0309 elseif isfield(modelSBML.species(i),'fbc_chemicalFormula') -0310 metaboliteInChI{numel(metaboliteInChI)+1,1}=''; -0311 if ~isempty(modelSBML.species(i).fbc_chemicalFormula) -0312 %Cannot extract InChi from formula, so remains -0313 %empty -0314 metaboliteFormula{numel(metaboliteFormula)+1,1}=modelSBML.species(i).fbc_chemicalFormula; -0315 else -0316 metaboliteFormula{numel(metaboliteFormula)+1,1}=''; -0317 end -0318 else -0319 metaboliteInChI{numel(metaboliteInChI)+1,1}=''; -0320 metaboliteFormula{numel(metaboliteFormula)+1,1}=''; -0321 end -0322 -0323 %Get Miriam info -0324 metMiriam=parseMiriam(modelSBML.species(i).annotation); -0325 metaboliteMiriams{numel(metaboliteMiriams)+1,1}=metMiriam; -0326 else -0327 metaboliteInChI{numel(metaboliteInChI)+1,1}=''; -0328 if isfield(modelSBML.species(i),'notes') -0329 metaboliteFormula{numel(metaboliteFormula)+1,1}=parseNote(modelSBML.species(i).notes,'FORMULA'); -0330 else -0331 metaboliteFormula{numel(metaboliteFormula)+1,1}=''; -0332 end -0333 metaboliteMiriams{numel(metaboliteMiriams)+1,1}=[]; -0334 end -0335 if ~isempty(modelSBML.species(i).notes) -0336 if ~isfield(modelSBML.species(i),'annotation') -0337 metaboliteFormula{numel(metaboliteFormula)+1,1}=parseNote(modelSBML.species(i).notes,'FORMULA'); -0338 end -0339 elseif ~isfield(modelSBML.species(i),'annotation') -0340 metaboliteFormula{numel(metaboliteFormula)+1,1}=''; -0341 end -0342 %Get SBO term -0343 if isfield(modelSBML.species(i),'sboTerm') -0344 metSBOs(end+1,1) = modelSBML.species(i).sboTerm; +0191 +0192 if isfield(modelSBML.compartment(i),'sboTerm') +0193 compartmentMiriams{i} = addSBOtoMiriam(compartmentMiriams{i},modelSBML.compartment(i).sboTerm); +0194 end +0195 end +0196 +0197 %If there are no compartment names then use compartment id as name +0198 if all(cellfun(@isempty,compartmentNames)) +0199 compartmentNames=compartmentIDs; +0200 end +0201 +0202 %Retrieve info on metabolites, genes, complexes +0203 metaboliteNames={}; +0204 metaboliteIDs={}; +0205 metaboliteCompartments={}; +0206 metaboliteUnconstrained=[]; +0207 metaboliteFormula={}; +0208 metaboliteInChI={}; +0209 metaboliteMiriams={}; +0210 metaboliteCharges=[]; +0211 +0212 geneNames={}; +0213 geneIDs={}; +0214 geneMiriams={}; +0215 geneShortNames={}; +0216 geneCompartments={}; +0217 complexIDs={}; +0218 complexNames={}; +0219 +0220 %If the file is not a COBRA Toolbox model. According to the format +0221 %specified in the yeast consensus model both metabolites and genes are a +0222 %type of 'species'. The metabolites have names starting with 'M_' and genes +0223 %with 'E_' +0224 geneSBOs = []; +0225 metSBOs = []; +0226 %Regex of compartment names, later to be used to remove from metabolite +0227 %names if present as suffix. +0228 regexCompNames = ['\s?\[((' strjoin({modelSBML.compartment.name},')|(') '))\]$']; +0229 for i=1:numel(modelSBML.species) +0230 if ~isSBML2COBRA +0231 if length(modelSBML.species(i).id)>=2 && strcmpi(modelSBML.species(i).id(1:2),'E_') +0232 geneNames{numel(geneNames)+1,1}=modelSBML.species(i).name; +0233 +0234 %The "E_" is included in the ID. This is because it's only used +0235 %internally in this file and it makes the matching a little +0236 %smoother +0237 geneIDs{numel(geneIDs)+1,1}=modelSBML.species(i).id; +0238 geneCompartments{numel(geneCompartments)+1,1}=regexprep(modelSBML.species(i).compartment,'^C_',''); +0239 +0240 %Get Miriam structure +0241 if isfield(modelSBML.species(i),'annotation') +0242 %Get Miriam info +0243 geneMiriam=parseMiriam(modelSBML.species(i).annotation); +0244 geneMiriams{numel(geneMiriams)+1,1}=geneMiriam; +0245 else +0246 geneMiriams{numel(geneMiriams)+1,1}=[]; +0247 end +0248 +0249 %Protein short names (for example ERG10) are saved as SHORT +0250 %NAME: NAME in the notes-section of metabolites for SBML Level +0251 %2 and as PROTEIN_ASSOCIATION for each reaction in SBML Level 2 +0252 %COBRA Toolbox format. For now only the SHORT NAME is loaded +0253 %and no mapping takes place +0254 if isfield(modelSBML.species(i),'notes') +0255 geneShortNames{numel(geneShortNames)+1,1}=parseNote(modelSBML.species(i).notes,'SHORT NAME'); +0256 else +0257 geneShortNames{numel(geneShortNames)+1,1}=''; +0258 end +0259 +0260 %Get SBO term +0261 if isfield(modelSBML.species(i),'sboTerm') +0262 geneSBOs(end+1,1) = modelSBML.species(i).sboTerm; +0263 end +0264 elseif length(modelSBML.species(i).id)>=2 && strcmpi(modelSBML.species(i).id(1:3),'Cx_') +0265 %If it's a complex keep the ID and name +0266 complexIDs=[complexIDs;modelSBML.species(i).id]; +0267 complexNames=[complexNames;modelSBML.species(i).name]; +0268 else +0269 %If it is not gene or complex, then it must be a metabolite +0270 metaboliteNames{numel(metaboliteNames)+1,1}=modelSBML.species(i).name; +0271 metaboliteIDs{numel(metaboliteIDs)+1,1}=regexprep(modelSBML.species(i).id,'^M_',''); +0272 metaboliteCompartments{numel(metaboliteCompartments)+1,1}=regexprep(modelSBML.species(i).compartment,'^C_',''); +0273 metaboliteUnconstrained(numel(metaboliteUnconstrained)+1,1)=modelSBML.species(i).boundaryCondition; +0274 +0275 %For each metabolite retrieve the formula and the InChI code if +0276 %available First add the InChI code and the formula from the +0277 %InChI. This allows for overwriting the formula by setting the +0278 %actual formula field +0279 if ~isempty(modelSBML.species(i).annotation) +0280 %Get the formula if available +0281 startString='>InChI='; +0282 endString='</in:inchi>'; +0283 formStart=strfind(modelSBML.species(i).annotation,startString); +0284 if isempty(formStart) +0285 startString='InChI='; +0286 endString='"/>'; +0287 end +0288 formStart=strfind(modelSBML.species(i).annotation,startString); +0289 if ~isempty(formStart) +0290 formEnd=strfind(modelSBML.species(i).annotation,endString); +0291 formEndIndex=find(formEnd>formStart, 1 ); +0292 formula=modelSBML.species(i).annotation(formStart+numel(startString):formEnd(formEndIndex)-1); +0293 metaboliteInChI{numel(metaboliteInChI)+1,1}=formula; +0294 +0295 %The composition is most often present between the +0296 %first and second "/" in the model. In some simple +0297 %molecules, such as salts, there is no second "/". The +0298 %formula is then assumed to be to the end of the string +0299 compositionIndexes=strfind(formula,'/'); +0300 if numel(compositionIndexes)>1 +0301 metaboliteFormula{numel(metaboliteFormula)+1,1}=... +0302 formula(compositionIndexes(1)+1:compositionIndexes(2)-1); +0303 else +0304 if numel(compositionIndexes)==1 +0305 %Probably a simple molecule which can have only +0306 %one conformation +0307 metaboliteFormula{numel(metaboliteFormula)+1,1}=... +0308 formula(compositionIndexes(1)+1:numel(formula)); +0309 else +0310 metaboliteFormula{numel(metaboliteFormula)+1,1}=''; +0311 end +0312 end +0313 elseif isfield(modelSBML.species(i),'fbc_chemicalFormula') +0314 metaboliteInChI{numel(metaboliteInChI)+1,1}=''; +0315 if ~isempty(modelSBML.species(i).fbc_chemicalFormula) +0316 %Cannot extract InChi from formula, so remains +0317 %empty +0318 metaboliteFormula{numel(metaboliteFormula)+1,1}=modelSBML.species(i).fbc_chemicalFormula; +0319 else +0320 metaboliteFormula{numel(metaboliteFormula)+1,1}=''; +0321 end +0322 else +0323 metaboliteInChI{numel(metaboliteInChI)+1,1}=''; +0324 metaboliteFormula{numel(metaboliteFormula)+1,1}=''; +0325 end +0326 +0327 %Get Miriam info +0328 metMiriam=parseMiriam(modelSBML.species(i).annotation); +0329 metaboliteMiriams{numel(metaboliteMiriams)+1,1}=metMiriam; +0330 else +0331 metaboliteInChI{numel(metaboliteInChI)+1,1}=''; +0332 if isfield(modelSBML.species(i),'notes') +0333 metaboliteFormula{numel(metaboliteFormula)+1,1}=parseNote(modelSBML.species(i).notes,'FORMULA'); +0334 else +0335 metaboliteFormula{numel(metaboliteFormula)+1,1}=''; +0336 end +0337 metaboliteMiriams{numel(metaboliteMiriams)+1,1}=[]; +0338 end +0339 if ~isempty(modelSBML.species(i).notes) +0340 if ~isfield(modelSBML.species(i),'annotation') +0341 metaboliteFormula{numel(metaboliteFormula)+1,1}=parseNote(modelSBML.species(i).notes,'FORMULA'); +0342 end +0343 elseif ~isfield(modelSBML.species(i),'annotation') +0344 metaboliteFormula{numel(metaboliteFormula)+1,1}=''; 0345 end -0346 end -0347 -0348 elseif isSBML2COBRA -0349 %The metabolite names are assumed to be M_NAME_COMPOSITION or -0350 %_NAME_COMPOSITION or NAME_COMPOSITION or NAME. Regular expressions -0351 %are used that only NAME_COMPOSITION or NAME would be possible -0352 -0353 modelSBML.species(i).name=regexprep(modelSBML.species(i).name,'^M_',''); -0354 modelSBML.species(i).name=regexprep(modelSBML.species(i).name,'^_',''); -0355 underscoreIndex=strfind(modelSBML.species(i).name,'_'); +0346 %Get SBO term +0347 if isfield(modelSBML.species(i),'sboTerm') +0348 metSBOs(end+1,1) = modelSBML.species(i).sboTerm; +0349 end +0350 end +0351 +0352 elseif isSBML2COBRA +0353 %The metabolite names are assumed to be M_NAME_COMPOSITION or +0354 %_NAME_COMPOSITION or NAME_COMPOSITION or NAME. Regular expressions +0355 %are used that only NAME_COMPOSITION or NAME would be possible 0356 -0357 metaboliteNames{numel(metaboliteNames)+1,1}=modelSBML.species(i).name; -0358 -0359 metaboliteIDs{numel(metaboliteIDs)+1,1}=regexprep(modelSBML.species(i).id,'^M_',''); -0360 metaboliteCompartments{numel(metaboliteCompartments)+1,1}=regexprep(modelSBML.species(i).compartment,'^C_',''); -0361 -0362 %I think that COBRA doesn't set the boundary condition, but rather -0363 %uses name_b. Check for either -0364 metaboliteUnconstrained(numel(metaboliteUnconstrained)+1,1)=modelSBML.species(i).boundaryCondition; -0365 if strcmp(metaboliteIDs{end}(max(end-1,1):end),'_b') -0366 metaboliteUnconstrained(end)=1; -0367 end -0368 -0369 %Get the formula -0370 if max(underscoreIndex)<length(modelSBML.species(i).name) -0371 metaboliteFormula{numel(metaboliteFormula)+1,1}=modelSBML.species(i).name(max(underscoreIndex)+1:length(modelSBML.species(i).name)); -0372 else -0373 metaboliteFormula{numel(metaboliteFormula)+1,1}=''; -0374 end -0375 -0376 %The old COBRA version sometimes has composition information in the -0377 %notes instead -0378 if isfield(modelSBML.species(i),'notes') && ~isempty(parseNote(modelSBML.species(i).notes,'FORMULA')) -0379 metaboliteFormula{numel(metaboliteFormula)+1,1}=parseNote(modelSBML.species(i).notes,'FORMULA'); -0380 end -0381 -0382 %Get Miriam info -0383 if ~isempty(modelSBML.species(i).annotation) -0384 metMiriam=parseMiriam(modelSBML.species(i).annotation); -0385 else -0386 metMiriam=[]; -0387 end -0388 metaboliteMiriams{numel(metaboliteMiriams)+1,1}=metMiriam; -0389 -0390 %Get SBO term -0391 if isfield(modelSBML.species(i),'sboTerm') -0392 metSBOs(end+1,1) = modelSBML.species(i).sboTerm; -0393 end -0394 end -0395 %The following lines are executed regardless isSBML2COBRA setting -0396 if isempty(modelSBML.species(i).id) || ~strcmpi(modelSBML.species(i).id(1:2),'E_') -0397 if isempty(modelSBML.species(i).id) || ~strcmpi(modelSBML.species(i).id(1:3),'Cx_') -0398 %Remove trailing [compartment] from metabolite name if present -0399 metaboliteNames{end,1}=regexprep(metaboliteNames{end,1},regexCompNames,''); -0400 metaboliteNames{end,1}=regexprep(metaboliteNames{end,1},'^M_',''); -0401 if isfield(modelSBML.species(i),'fbc_charge') -0402 if ~isempty(modelSBML.species(i).fbc_charge) && modelSBML.species(i).isSetfbc_charge -0403 metaboliteCharges(numel(metaboliteCharges)+1,1)=double(modelSBML.species(i).fbc_charge); -0404 else -0405 if isfield(modelSBML.species(i),'notes') -0406 if strfind(modelSBML.species(i).notes,'CHARGE') -0407 metaboliteCharges(numel(metaboliteCharges)+1,1)=str2double(parseNote(modelSBML.species(i).notes,'CHARGE')); -0408 else -0409 metaboliteCharges(numel(metaboliteCharges)+1,1)=NaN; -0410 end -0411 else -0412 metaboliteCharges(numel(metaboliteCharges)+1,1)=NaN; -0413 end -0414 end -0415 elseif isfield(modelSBML.species(i),'notes') -0416 if strfind(modelSBML.species(i).notes,'CHARGE') -0417 metaboliteCharges(numel(metaboliteCharges)+1,1)=str2double(parseNote(modelSBML.species(i).notes,'CHARGE')); -0418 else -0419 metaboliteCharges(numel(metaboliteCharges)+1,1)=NaN; -0420 end -0421 else -0422 metaboliteCharges(numel(metaboliteCharges)+1,1)=NaN; -0423 end -0424 %Additional information from FBC format Chemical formula -0425 if isfield(modelSBML.species(i),'fbc_chemicalFormula') -0426 if ~isempty(modelSBML.species(i).fbc_chemicalFormula) -0427 metaboliteFormula{numel(metaboliteFormula),1}=modelSBML.species(i).fbc_chemicalFormula; -0428 end -0429 end -0430 end -0431 end -0432 end -0433 -0434 %Add SBO terms to gene and metabolite miriam fields -0435 if numel(unique(geneSBOs)) > 1 % don't add if they're all identical -0436 for i = 1:numel(geneNames) -0437 geneMiriams{i} = addSBOtoMiriam(geneMiriams{i},geneSBOs(i)); -0438 end -0439 end -0440 if numel(unique(metSBOs)) > 1 -0441 for i = 1:numel(metaboliteNames) -0442 metaboliteMiriams{i} = addSBOtoMiriam(metaboliteMiriams{i},metSBOs(i)); -0443 end -0444 end -0445 -0446 %Retrieve info on reactions -0447 reactionNames=cell(numel(modelSBML.reaction),1); -0448 reactionIDs=cell(numel(modelSBML.reaction),1); -0449 subsystems=cell(numel(modelSBML.reaction),1); -0450 eccodes=cell(numel(modelSBML.reaction),1); -0451 eccodes(:,:)=cellstr(''); -0452 rxnconfidencescores=NaN(numel(modelSBML.reaction),1); -0453 rxnreferences=cell(numel(modelSBML.reaction),1); -0454 rxnreferences(:,:)=cellstr(''); -0455 rxnnotes=cell(numel(modelSBML.reaction),1); -0456 rxnnotes(:,:)=cellstr(''); -0457 grRules=cell(numel(modelSBML.reaction),1); -0458 grRules(:,:)=cellstr(''); -0459 grRulesFromModifier=grRules; -0460 rxnComps=zeros(numel(modelSBML.reaction),1); -0461 rxnMiriams=cell(numel(modelSBML.reaction),1); -0462 reactionReversibility=zeros(numel(modelSBML.reaction),1); -0463 reactionUB=zeros(numel(modelSBML.reaction),1); -0464 reactionLB=zeros(numel(modelSBML.reaction),1); -0465 reactionObjective=zeros(numel(modelSBML.reaction),1); -0466 -0467 %Construct the stoichiometric matrix while the reaction info is read -0468 S=zeros(numel(metaboliteIDs),numel(modelSBML.reaction)); -0469 -0470 counter=0; -0471 %If FBC, then bounds have parameter ids defined for the whole model -0472 if isfield(modelSBML,'parameter') -0473 parameter.name=cell(numel(modelSBML.parameter),1); -0474 parameter.name={modelSBML.parameter(:).id}'; -0475 parameter.value={modelSBML.parameter(:).value}'; -0476 end -0477 -0478 if isfield(modelSBML.reaction,'sboTerm') && numel(unique([modelSBML.reaction.sboTerm])) == 1 -0479 %If all the SBO terms are identical, don't add them to rxnMiriams -0480 modelSBML.reaction = rmfield(modelSBML.reaction,'sboTerm'); -0481 end -0482 -0483 for i=1:numel(modelSBML.reaction) -0484 -0485 %Check that the reaction doesn't produce a complex and nothing else. If -0486 %so, then jump to the next reaction. This is because I get the genes -0487 %for complexes from the names and not from the reactions that create -0488 %them. This only applies to the non-COBRA format -0489 if numel(modelSBML.reaction(i).product)==1 -0490 if length(modelSBML.reaction(i).product(1).species)>=3 -0491 if strcmp(modelSBML.reaction(i).product(1).species(1:3),'Cx_')==true -0492 continue; -0493 end -0494 end -0495 end -0496 -0497 %It didn't look like a gene complex-forming reaction -0498 counter=counter+1; -0499 -0500 reactionNames{counter}=modelSBML.reaction(i).name; -0501 -0502 reactionIDs{counter}=modelSBML.reaction(i).id; -0503 reactionReversibility(counter)=modelSBML.reaction(i).reversible; -0504 -0505 %If model is FBC, first get parameter of bound and then replace it with -0506 %the correct value. Probably faster with replace(), but this was only -0507 %introduced in Matlab R2016b -0508 if isfield(modelSBML.reaction(i),'fbc_lowerFluxBound') -0509 lb=modelSBML.reaction(i).fbc_lowerFluxBound; -0510 ub=modelSBML.reaction(i).fbc_upperFluxBound; -0511 for n=1:numel(parameter.value) -0512 lb=regexprep(lb,parameter.name(n),num2str(parameter.value{n})); -0513 ub=regexprep(ub,parameter.name(n),num2str(parameter.value{n})); -0514 end -0515 reactionLB(counter)=str2num(lb); -0516 reactionUB(counter)=str2num(ub); -0517 %The order of these parameters should not be hard coded -0518 elseif isfield(modelSBML.reaction(i).kineticLaw,'parameter') -0519 reactionLB(counter)=modelSBML.reaction(i).kineticLaw.parameter(1).value; -0520 reactionUB(counter)=modelSBML.reaction(i).kineticLaw.parameter(2).value; -0521 reactionObjective(counter)=modelSBML.reaction(i).kineticLaw.parameter(3).value; -0522 else -0523 if reactionReversibility(counter)==true -0524 reactionLB(counter)=-inf; -0525 else -0526 reactionLB(counter)=0; -0527 end -0528 reactionUB(counter)=inf; -0529 reactionObjective(counter)=0; -0530 end -0531 -0532 %Find the associated gene if available -0533 %If FBC, get gene association data from corresponding fields -0534 if isfield(modelSBML.reaction(i),'fbc_geneProductAssociation') -0535 if ~isempty(modelSBML.reaction(i).fbc_geneProductAssociation) && ~isempty(modelSBML.reaction(i).fbc_geneProductAssociation.fbc_association) -0536 grRules{counter}=modelSBML.reaction(i).fbc_geneProductAssociation.fbc_association.fbc_association; -0537 end -0538 elseif isfield(modelSBML.reaction(i),'notes') -0539 %This section was previously executed only if isSBML2COBRA is true. Now -0540 %it will be executed, if 'GENE_ASSOCIATION' is found in -0541 %modelSBML.reaction(i).notes -0542 if strfind(modelSBML.reaction(i).notes,'GENE_ASSOCIATION') -0543 geneAssociation=parseNote(modelSBML.reaction(i).notes,'GENE_ASSOCIATION'); -0544 elseif strfind(modelSBML.reaction(i).notes,'GENE ASSOCIATION') -0545 geneAssociation=parseNote(modelSBML.reaction(i).notes,'GENE ASSOCIATION'); -0546 else -0547 geneAssociation=''; -0548 end -0549 if ~isempty(geneAssociation) -0550 %This adds the grRules. The gene list and rxnGeneMat are created -0551 %later -0552 grRules{counter}=geneAssociation; -0553 end -0554 end -0555 if isempty(grRules{counter}) && ~isempty(modelSBML.reaction(i).modifier) -0556 rules=''; -0557 for j=1:numel(modelSBML.reaction(i).modifier) -0558 modifier=modelSBML.reaction(i).modifier(j).species; -0559 if ~isempty(modifier) -0560 if strcmpi(modifier(1:2),'E_') -0561 index=find(strcmp(modifier,geneIDs)); -0562 %This should be unique and in the geneIDs list, -0563 %otherwise something is wrong -0564 if numel(index)~=1 -0565 EM=['Could not get the gene association data from reaction ' reactionIDs{i}]; -0566 dispEM(EM); -0567 end -0568 if ~isempty(rules) -0569 rules=[rules ' or (' geneNames{index} ')']; -0570 else -0571 rules=['(' geneNames{index} ')']; -0572 end -0573 elseif strcmp(modifier(1:2),'s_') -0574 index=find(strcmp(modifier,metaboliteIDs)); -0575 %This should be unique and in the geneIDs list, -0576 %otherwise something is wrong -0577 if numel(index)~=1 -0578 EM=['Could not get the gene association data from reaction ' reactionIDs{i}]; -0579 dispEM(EM); -0580 end -0581 if ~isempty(rules) -0582 rules=[rules ' or (' metaboliteIDs{index} ')']; -0583 else -0584 rules=['(' metaboliteIDs{index} ')']; -0585 end -0586 else -0587 %It seems to be a complex. Add the corresponding -0588 %genes from the name of the complex (not the -0589 %reaction that creates it) -0590 index=find(strcmp(modifier,complexIDs)); -0591 if numel(index)==1 -0592 if ~isempty(rules) -0593 rules=[rules ' or (' strrep(complexNames{index},':',' and ') ')']; -0594 else -0595 rules=['(' strrep(complexNames{index},':',' and ') ')']; -0596 end -0597 else -0598 %Could not find a complex -0599 EM=['Could not get the gene association data from reaction ' reactionIDs{i}]; -0600 dispEM(EM); -0601 end -0602 end -0603 end -0604 end -0605 grRules{counter}=rules; -0606 grRulesFromModifier{counter}=rules;%Backup copy for grRules, useful to parse Yeast 7.6 -0607 end -0608 -0609 %Add reaction compartment -0610 if isfield(modelSBML.reaction(i),'compartment') -0611 if ~isempty(modelSBML.reaction(i).compartment) -0612 rxnComp=modelSBML.reaction(i).compartment; -0613 else -0614 rxnComp=''; -0615 end -0616 elseif isfield(modelSBML.reaction(i),'notes') -0617 rxnComp=parseNote(modelSBML.reaction(i).notes,'COMPARTMENT'); -0618 end -0619 if ~isempty(rxnComp) -0620 %Find it in the compartment list -0621 [~, J]=ismember(rxnComp,compartmentIDs); -0622 rxnComps(counter)=J; -0623 end -0624 -0625 %Get other Miriam fields. This may include for example database indexes -0626 %to organism-specific databases. EC-codes are supported by the COBRA -0627 %Toolbox format and are therefore loaded separately -0628 if isSBML2COBRA==false -0629 miriamStruct=parseMiriam(modelSBML.reaction(i).annotation); -0630 rxnMiriams{counter}=miriamStruct; -0631 if isfield(modelSBML.reaction(i),'notes') -0632 subsystems{counter,1}=cellstr(parseNote(modelSBML.reaction(i).notes,'SUBSYSTEM')); -0633 subsystems{counter,1}(cellfun('isempty',subsystems{counter,1})) = []; -0634 if strfind(modelSBML.reaction(i).notes,'Confidence Level') -0635 rxnconfidencescores(counter)=str2num(parseNote(modelSBML.reaction(i).notes,'Confidence Level')); -0636 end -0637 rxnreferences{counter,1}=parseNote(modelSBML.reaction(i).notes,'AUTHORS'); -0638 rxnnotes{counter,1}=parseNote(modelSBML.reaction(i).notes,'NOTES'); -0639 end -0640 end -0641 -0642 %Get SBO terms -0643 if isfield(modelSBML.reaction(i),'sboTerm') -0644 rxnMiriams{counter} = addSBOtoMiriam(rxnMiriams{counter}, modelSBML.reaction(i).sboTerm); -0645 end -0646 -0647 %Get ec-codes -0648 eccode=''; -0649 if ~isempty(modelSBML.reaction(i).annotation) -0650 if strfind(modelSBML.reaction(i).annotation,'urn:miriam:ec-code') -0651 eccode=parseAnnotation(modelSBML.reaction(i).annotation,'urn:miriam:',':','ec-code'); -0652 elseif strfind(modelSBML.reaction(i).annotation,'http://identifiers.org/ec-code') -0653 eccode=parseAnnotation(modelSBML.reaction(i).annotation,'http://identifiers.org/','/','ec-code'); -0654 elseif strfind(modelSBML.reaction(i).annotation,'https://identifiers.org/ec-code') -0655 eccode=parseAnnotation(modelSBML.reaction(i).annotation,'https://identifiers.org/','/','ec-code'); -0656 end -0657 elseif isfield(modelSBML.reaction(i),'notes') -0658 if strfind(modelSBML.reaction(i).notes,'EC Number') -0659 eccode=[eccode parseNote(modelSBML.reaction(i).notes,'EC Number')]; -0660 elseif strfind(modelSBML.reaction(i).notes,'PROTEIN_CLASS') -0661 eccode=[eccode parseNote(modelSBML.reaction(i).notes,'PROTEIN_CLASS')]; -0662 end -0663 end -0664 eccodes{counter}=eccode; -0665 -0666 %Add all reactants -0667 for j=1:numel(modelSBML.reaction(i).reactant) -0668 %Get the index of the metabolite in metaboliteIDs. External -0669 %metabolites will be removed at a later stage -0670 metIndex=find(strcmp(modelSBML.reaction(i).reactant(j).species,metaboliteIDs),1); -0671 if isempty(metIndex) -0672 EM=['Could not find metabolite ' modelSBML.reaction(i).reactant(j).species ' in reaction ' reactionIDs{counter}]; -0673 dispEM(EM); -0674 end -0675 S(metIndex,counter)=S(metIndex,counter)+modelSBML.reaction(i).reactant(j).stoichiometry*-1; -0676 end -0677 -0678 %Add all products -0679 for j=1:numel(modelSBML.reaction(i).product) -0680 %Get the index of the metabolite in metaboliteIDs. -0681 metIndex=find(strcmp(modelSBML.reaction(i).product(j).species,metaboliteIDs),1); -0682 if isempty(metIndex) -0683 EM=['Could not find metabolite ' modelSBML.reaction(i).reactant(j).species ' in reaction ' reactionIDs{counter}]; -0684 dispEM(EM); -0685 end -0686 S(metIndex,counter)=S(metIndex,counter)+modelSBML.reaction(i).product(j).stoichiometry; -0687 end -0688 end -0689 -0690 %if FBC, objective function is separately defined. Multiple objective -0691 %functions can be defined, one is set as active -0692 if isfield(modelSBML, 'fbc_activeObjective') -0693 obj=modelSBML.fbc_activeObjective; -0694 for i=1:numel(modelSBML.fbc_objective) -0695 if strcmp(obj,modelSBML.fbc_objective(i).fbc_id) -0696 rxn=modelSBML.fbc_objective(i).fbc_fluxObjective.fbc_reaction; -0697 rxn=regexprep(rxn,'^R_',''); -0698 idx=find(ismember(reactionIDs,rxn)); -0699 reactionObjective(idx)=modelSBML.fbc_objective(i).fbc_fluxObjective.fbc_coefficient; -0700 end -0701 end -0702 end -0703 -0704 %subSystems can be stored as groups instead of in annotations -0705 if isfield(modelSBML,'groups_group') -0706 for i=1:numel(modelSBML.groups_group) -0707 groupreactions={modelSBML.groups_group(i).groups_member(:).groups_idRef}; -0708 groupreactions=regexprep(groupreactions,'^R_',''); -0709 [~, idx] = ismember(groupreactions, reactionIDs); -0710 if any(idx) -0711 for j=1:numel(idx) -0712 if isempty(subsystems{idx(j)}) % First subsystem -0713 subsystems{idx(j)} = {modelSBML.groups_group(i).groups_name}; -0714 else % Consecutive subsystems: concatenate -0715 subsystems{idx(j)} = horzcat(subsystems{idx(j)}, modelSBML.groups_group(i).groups_name); -0716 end -0717 end -0718 end -0719 end -0720 end -0721 -0722 %Shrink the structures if complex-forming reactions had to be skipped -0723 reactionNames=reactionNames(1:counter); -0724 reactionIDs=reactionIDs(1:counter); -0725 subsystems=subsystems(1:counter); -0726 eccodes=eccodes(1:counter); -0727 rxnconfidencescores=rxnconfidencescores(1:counter); -0728 rxnreferences=rxnreferences(1:counter); -0729 rxnnotes=rxnnotes(1:counter); -0730 grRules=grRules(1:counter); -0731 rxnMiriams=rxnMiriams(1:counter); -0732 reactionReversibility=reactionReversibility(1:counter); -0733 reactionUB=reactionUB(1:counter); -0734 reactionLB=reactionLB(1:counter); -0735 reactionObjective=reactionObjective(1:counter); -0736 S=S(:,1:counter); -0737 -0738 model.name=modelSBML.name; -0739 model.id=regexprep(modelSBML.id,'^M_',''); % COBRA adds M_ prefix -0740 model.rxns=reactionIDs; -0741 model.mets=metaboliteIDs; -0742 model.S=sparse(S); -0743 model.lb=reactionLB; -0744 model.ub=reactionUB; -0745 model.rev=reactionReversibility; -0746 model.c=reactionObjective; -0747 model.b=zeros(numel(metaboliteIDs),1); -0748 model.comps=compartmentIDs; -0749 model.compNames=compartmentNames; -0750 model.rxnConfidenceScores=rxnconfidencescores; -0751 model.rxnReferences=rxnreferences; -0752 model.rxnNotes=rxnnotes; -0753 -0754 %Load annotation if available. If there are several authors, only the first -0755 %author credentials are imported -0756 if isfield(modelSBML,'annotation') -0757 endString='</'; -0758 I=strfind(modelSBML.annotation,endString); -0759 J=strfind(modelSBML.annotation,'<vCard:Family>'); -0760 if any(J) -0761 model.annotation.familyName=modelSBML.annotation(J(1)+14:I(find(I>J(1),1))-1); -0762 end -0763 J=strfind(modelSBML.annotation,'<vCard:Given>'); +0357 modelSBML.species(i).name=regexprep(modelSBML.species(i).name,'^M_',''); +0358 modelSBML.species(i).name=regexprep(modelSBML.species(i).name,'^_',''); +0359 underscoreIndex=strfind(modelSBML.species(i).name,'_'); +0360 +0361 metaboliteNames{numel(metaboliteNames)+1,1}=modelSBML.species(i).name; +0362 +0363 metaboliteIDs{numel(metaboliteIDs)+1,1}=regexprep(modelSBML.species(i).id,'^M_',''); +0364 metaboliteCompartments{numel(metaboliteCompartments)+1,1}=regexprep(modelSBML.species(i).compartment,'^C_',''); +0365 +0366 %I think that COBRA doesn't set the boundary condition, but rather +0367 %uses name_b. Check for either +0368 metaboliteUnconstrained(numel(metaboliteUnconstrained)+1,1)=modelSBML.species(i).boundaryCondition; +0369 if strcmp(metaboliteIDs{end}(max(end-1,1):end),'_b') +0370 metaboliteUnconstrained(end)=1; +0371 end +0372 +0373 %Get the formula +0374 if max(underscoreIndex)<length(modelSBML.species(i).name) +0375 metaboliteFormula{numel(metaboliteFormula)+1,1}=modelSBML.species(i).name(max(underscoreIndex)+1:length(modelSBML.species(i).name)); +0376 else +0377 metaboliteFormula{numel(metaboliteFormula)+1,1}=''; +0378 end +0379 +0380 %The old COBRA version sometimes has composition information in the +0381 %notes instead +0382 if isfield(modelSBML.species(i),'notes') && ~isempty(parseNote(modelSBML.species(i).notes,'FORMULA')) +0383 metaboliteFormula{numel(metaboliteFormula)+1,1}=parseNote(modelSBML.species(i).notes,'FORMULA'); +0384 end +0385 +0386 %Get Miriam info +0387 if ~isempty(modelSBML.species(i).annotation) +0388 metMiriam=parseMiriam(modelSBML.species(i).annotation); +0389 else +0390 metMiriam=[]; +0391 end +0392 metaboliteMiriams{numel(metaboliteMiriams)+1,1}=metMiriam; +0393 +0394 %Get SBO term +0395 if isfield(modelSBML.species(i),'sboTerm') +0396 metSBOs(end+1,1) = modelSBML.species(i).sboTerm; +0397 end +0398 end +0399 %The following lines are executed regardless isSBML2COBRA setting +0400 if isempty(modelSBML.species(i).id) || ~strcmpi(modelSBML.species(i).id(1:2),'E_') +0401 if isempty(modelSBML.species(i).id) || ~strcmpi(modelSBML.species(i).id(1:3),'Cx_') +0402 %Remove trailing [compartment] from metabolite name if present +0403 metaboliteNames{end,1}=regexprep(metaboliteNames{end,1},regexCompNames,''); +0404 metaboliteNames{end,1}=regexprep(metaboliteNames{end,1},'^M_',''); +0405 if isfield(modelSBML.species(i),'fbc_charge') +0406 if ~isempty(modelSBML.species(i).fbc_charge) && modelSBML.species(i).isSetfbc_charge +0407 metaboliteCharges(numel(metaboliteCharges)+1,1)=double(modelSBML.species(i).fbc_charge); +0408 else +0409 if isfield(modelSBML.species(i),'notes') +0410 if strfind(modelSBML.species(i).notes,'CHARGE') +0411 metaboliteCharges(numel(metaboliteCharges)+1,1)=str2double(parseNote(modelSBML.species(i).notes,'CHARGE')); +0412 else +0413 metaboliteCharges(numel(metaboliteCharges)+1,1)=NaN; +0414 end +0415 else +0416 metaboliteCharges(numel(metaboliteCharges)+1,1)=NaN; +0417 end +0418 end +0419 elseif isfield(modelSBML.species(i),'notes') +0420 if strfind(modelSBML.species(i).notes,'CHARGE') +0421 metaboliteCharges(numel(metaboliteCharges)+1,1)=str2double(parseNote(modelSBML.species(i).notes,'CHARGE')); +0422 else +0423 metaboliteCharges(numel(metaboliteCharges)+1,1)=NaN; +0424 end +0425 else +0426 metaboliteCharges(numel(metaboliteCharges)+1,1)=NaN; +0427 end +0428 %Additional information from FBC format Chemical formula +0429 if isfield(modelSBML.species(i),'fbc_chemicalFormula') +0430 if ~isempty(modelSBML.species(i).fbc_chemicalFormula) +0431 metaboliteFormula{numel(metaboliteFormula),1}=modelSBML.species(i).fbc_chemicalFormula; +0432 end +0433 end +0434 end +0435 end +0436 end +0437 +0438 %Add SBO terms to gene and metabolite miriam fields +0439 if numel(unique(geneSBOs)) > 1 % don't add if they're all identical +0440 for i = 1:numel(geneNames) +0441 geneMiriams{i} = addSBOtoMiriam(geneMiriams{i},geneSBOs(i)); +0442 end +0443 end +0444 if numel(unique(metSBOs)) > 1 +0445 for i = 1:numel(metaboliteNames) +0446 metaboliteMiriams{i} = addSBOtoMiriam(metaboliteMiriams{i},metSBOs(i)); +0447 end +0448 end +0449 +0450 %Retrieve info on reactions +0451 reactionNames=cell(numel(modelSBML.reaction),1); +0452 reactionIDs=cell(numel(modelSBML.reaction),1); +0453 subsystems=cell(numel(modelSBML.reaction),1); +0454 eccodes=cell(numel(modelSBML.reaction),1); +0455 eccodes(:,:)=cellstr(''); +0456 rxnconfidencescores=NaN(numel(modelSBML.reaction),1); +0457 rxnreferences=cell(numel(modelSBML.reaction),1); +0458 rxnreferences(:,:)=cellstr(''); +0459 rxnnotes=cell(numel(modelSBML.reaction),1); +0460 rxnnotes(:,:)=cellstr(''); +0461 grRules=cell(numel(modelSBML.reaction),1); +0462 grRules(:,:)=cellstr(''); +0463 grRulesFromModifier=grRules; +0464 rxnComps=zeros(numel(modelSBML.reaction),1); +0465 rxnMiriams=cell(numel(modelSBML.reaction),1); +0466 reactionReversibility=zeros(numel(modelSBML.reaction),1); +0467 reactionUB=zeros(numel(modelSBML.reaction),1); +0468 reactionLB=zeros(numel(modelSBML.reaction),1); +0469 reactionObjective=zeros(numel(modelSBML.reaction),1); +0470 +0471 %Construct the stoichiometric matrix while the reaction info is read +0472 S=zeros(numel(metaboliteIDs),numel(modelSBML.reaction)); +0473 +0474 counter=0; +0475 %If FBC, then bounds have parameter ids defined for the whole model +0476 if isfield(modelSBML,'parameter') +0477 parameter.name=cell(numel(modelSBML.parameter),1); +0478 parameter.name={modelSBML.parameter(:).id}'; +0479 parameter.value={modelSBML.parameter(:).value}'; +0480 end +0481 +0482 if isfield(modelSBML.reaction,'sboTerm') && numel(unique([modelSBML.reaction.sboTerm])) == 1 +0483 %If all the SBO terms are identical, don't add them to rxnMiriams +0484 modelSBML.reaction = rmfield(modelSBML.reaction,'sboTerm'); +0485 end +0486 +0487 for i=1:numel(modelSBML.reaction) +0488 +0489 %Check that the reaction doesn't produce a complex and nothing else. If +0490 %so, then jump to the next reaction. This is because I get the genes +0491 %for complexes from the names and not from the reactions that create +0492 %them. This only applies to the non-COBRA format +0493 if numel(modelSBML.reaction(i).product)==1 +0494 if length(modelSBML.reaction(i).product(1).species)>=3 +0495 if strcmp(modelSBML.reaction(i).product(1).species(1:3),'Cx_')==true +0496 continue; +0497 end +0498 end +0499 end +0500 +0501 %It didn't look like a gene complex-forming reaction +0502 counter=counter+1; +0503 +0504 reactionNames{counter}=modelSBML.reaction(i).name; +0505 +0506 reactionIDs{counter}=modelSBML.reaction(i).id; +0507 reactionReversibility(counter)=modelSBML.reaction(i).reversible; +0508 +0509 %If model is FBC, first get parameter of bound and then replace it with +0510 %the correct value. Probably faster with replace(), but this was only +0511 %introduced in Matlab R2016b +0512 if isfield(modelSBML.reaction(i),'fbc_lowerFluxBound') +0513 lb=modelSBML.reaction(i).fbc_lowerFluxBound; +0514 ub=modelSBML.reaction(i).fbc_upperFluxBound; +0515 for n=1:numel(parameter.value) +0516 lb=regexprep(lb,parameter.name(n),num2str(parameter.value{n})); +0517 ub=regexprep(ub,parameter.name(n),num2str(parameter.value{n})); +0518 end +0519 reactionLB(counter)=str2num(lb); +0520 reactionUB(counter)=str2num(ub); +0521 %The order of these parameters should not be hard coded +0522 elseif isfield(modelSBML.reaction(i).kineticLaw,'parameter') +0523 reactionLB(counter)=modelSBML.reaction(i).kineticLaw.parameter(1).value; +0524 reactionUB(counter)=modelSBML.reaction(i).kineticLaw.parameter(2).value; +0525 reactionObjective(counter)=modelSBML.reaction(i).kineticLaw.parameter(3).value; +0526 else +0527 if reactionReversibility(counter)==true +0528 reactionLB(counter)=-inf; +0529 else +0530 reactionLB(counter)=0; +0531 end +0532 reactionUB(counter)=inf; +0533 reactionObjective(counter)=0; +0534 end +0535 +0536 %Find the associated gene if available +0537 %If FBC, get gene association data from corresponding fields +0538 if isfield(modelSBML.reaction(i),'fbc_geneProductAssociation') +0539 if ~isempty(modelSBML.reaction(i).fbc_geneProductAssociation) && ~isempty(modelSBML.reaction(i).fbc_geneProductAssociation.fbc_association) +0540 grRules{counter}=modelSBML.reaction(i).fbc_geneProductAssociation.fbc_association.fbc_association; +0541 end +0542 elseif isfield(modelSBML.reaction(i),'notes') +0543 %This section was previously executed only if isSBML2COBRA is true. Now +0544 %it will be executed, if 'GENE_ASSOCIATION' is found in +0545 %modelSBML.reaction(i).notes +0546 if strfind(modelSBML.reaction(i).notes,'GENE_ASSOCIATION') +0547 geneAssociation=parseNote(modelSBML.reaction(i).notes,'GENE_ASSOCIATION'); +0548 elseif strfind(modelSBML.reaction(i).notes,'GENE ASSOCIATION') +0549 geneAssociation=parseNote(modelSBML.reaction(i).notes,'GENE ASSOCIATION'); +0550 else +0551 geneAssociation=''; +0552 end +0553 if ~isempty(geneAssociation) +0554 %This adds the grRules. The gene list and rxnGeneMat are created +0555 %later +0556 grRules{counter}=geneAssociation; +0557 end +0558 end +0559 if isempty(grRules{counter}) && ~isempty(modelSBML.reaction(i).modifier) +0560 rules=''; +0561 for j=1:numel(modelSBML.reaction(i).modifier) +0562 modifier=modelSBML.reaction(i).modifier(j).species; +0563 if ~isempty(modifier) +0564 if strcmpi(modifier(1:2),'E_') +0565 index=find(strcmp(modifier,geneIDs)); +0566 %This should be unique and in the geneIDs list, +0567 %otherwise something is wrong +0568 if numel(index)~=1 +0569 EM=['Could not get the gene association data from reaction ' reactionIDs{i}]; +0570 dispEM(EM); +0571 end +0572 if ~isempty(rules) +0573 rules=[rules ' or (' geneNames{index} ')']; +0574 else +0575 rules=['(' geneNames{index} ')']; +0576 end +0577 elseif strcmp(modifier(1:2),'s_') +0578 index=find(strcmp(modifier,metaboliteIDs)); +0579 %This should be unique and in the geneIDs list, +0580 %otherwise something is wrong +0581 if numel(index)~=1 +0582 EM=['Could not get the gene association data from reaction ' reactionIDs{i}]; +0583 dispEM(EM); +0584 end +0585 if ~isempty(rules) +0586 rules=[rules ' or (' metaboliteIDs{index} ')']; +0587 else +0588 rules=['(' metaboliteIDs{index} ')']; +0589 end +0590 else +0591 %It seems to be a complex. Add the corresponding +0592 %genes from the name of the complex (not the +0593 %reaction that creates it) +0594 index=find(strcmp(modifier,complexIDs)); +0595 if numel(index)==1 +0596 if ~isempty(rules) +0597 rules=[rules ' or (' strrep(complexNames{index},':',' and ') ')']; +0598 else +0599 rules=['(' strrep(complexNames{index},':',' and ') ')']; +0600 end +0601 else +0602 %Could not find a complex +0603 EM=['Could not get the gene association data from reaction ' reactionIDs{i}]; +0604 dispEM(EM); +0605 end +0606 end +0607 end +0608 end +0609 grRules{counter}=rules; +0610 grRulesFromModifier{counter}=rules;%Backup copy for grRules, useful to parse Yeast 7.6 +0611 end +0612 +0613 %Add reaction compartment +0614 if isfield(modelSBML.reaction(i),'compartment') +0615 if ~isempty(modelSBML.reaction(i).compartment) +0616 rxnComp=modelSBML.reaction(i).compartment; +0617 else +0618 rxnComp=''; +0619 end +0620 elseif isfield(modelSBML.reaction(i),'notes') +0621 rxnComp=parseNote(modelSBML.reaction(i).notes,'COMPARTMENT'); +0622 end +0623 if ~isempty(rxnComp) +0624 %Find it in the compartment list +0625 [~, J]=ismember(rxnComp,compartmentIDs); +0626 rxnComps(counter)=J; +0627 end +0628 +0629 %Get other Miriam fields. This may include for example database indexes +0630 %to organism-specific databases. EC-codes are supported by the COBRA +0631 %Toolbox format and are therefore loaded separately +0632 if isSBML2COBRA==false +0633 miriamStruct=parseMiriam(modelSBML.reaction(i).annotation); +0634 rxnMiriams{counter}=miriamStruct; +0635 if isfield(modelSBML.reaction(i),'notes') +0636 subsystems{counter,1}=cellstr(parseNote(modelSBML.reaction(i).notes,'SUBSYSTEM')); +0637 subsystems{counter,1}(cellfun('isempty',subsystems{counter,1})) = []; +0638 if strfind(modelSBML.reaction(i).notes,'Confidence Level') +0639 rxnconfidencescores(counter)=str2num(parseNote(modelSBML.reaction(i).notes,'Confidence Level')); +0640 end +0641 rxnreferences{counter,1}=parseNote(modelSBML.reaction(i).notes,'AUTHORS'); +0642 rxnnotes{counter,1}=parseNote(modelSBML.reaction(i).notes,'NOTES'); +0643 end +0644 end +0645 +0646 %Get SBO terms +0647 if isfield(modelSBML.reaction(i),'sboTerm') +0648 rxnMiriams{counter} = addSBOtoMiriam(rxnMiriams{counter}, modelSBML.reaction(i).sboTerm); +0649 end +0650 +0651 %Get ec-codes +0652 eccode=''; +0653 if ~isempty(modelSBML.reaction(i).annotation) +0654 if strfind(modelSBML.reaction(i).annotation,'urn:miriam:ec-code') +0655 eccode=parseAnnotation(modelSBML.reaction(i).annotation,'urn:miriam:',':','ec-code'); +0656 elseif strfind(modelSBML.reaction(i).annotation,'http://identifiers.org/ec-code') +0657 eccode=parseAnnotation(modelSBML.reaction(i).annotation,'http://identifiers.org/','/','ec-code'); +0658 elseif strfind(modelSBML.reaction(i).annotation,'https://identifiers.org/ec-code') +0659 eccode=parseAnnotation(modelSBML.reaction(i).annotation,'https://identifiers.org/','/','ec-code'); +0660 end +0661 elseif isfield(modelSBML.reaction(i),'notes') +0662 if strfind(modelSBML.reaction(i).notes,'EC Number') +0663 eccode=[eccode parseNote(modelSBML.reaction(i).notes,'EC Number')]; +0664 elseif strfind(modelSBML.reaction(i).notes,'PROTEIN_CLASS') +0665 eccode=[eccode parseNote(modelSBML.reaction(i).notes,'PROTEIN_CLASS')]; +0666 end +0667 end +0668 eccodes{counter}=eccode; +0669 +0670 %Add all reactants +0671 for j=1:numel(modelSBML.reaction(i).reactant) +0672 %Get the index of the metabolite in metaboliteIDs. External +0673 %metabolites will be removed at a later stage +0674 metIndex=find(strcmp(modelSBML.reaction(i).reactant(j).species,metaboliteIDs),1); +0675 if isempty(metIndex) +0676 EM=['Could not find metabolite ' modelSBML.reaction(i).reactant(j).species ' in reaction ' reactionIDs{counter}]; +0677 dispEM(EM); +0678 end +0679 S(metIndex,counter)=S(metIndex,counter)+modelSBML.reaction(i).reactant(j).stoichiometry*-1; +0680 end +0681 +0682 %Add all products +0683 for j=1:numel(modelSBML.reaction(i).product) +0684 %Get the index of the metabolite in metaboliteIDs. +0685 metIndex=find(strcmp(modelSBML.reaction(i).product(j).species,metaboliteIDs),1); +0686 if isempty(metIndex) +0687 EM=['Could not find metabolite ' modelSBML.reaction(i).reactant(j).species ' in reaction ' reactionIDs{counter}]; +0688 dispEM(EM); +0689 end +0690 S(metIndex,counter)=S(metIndex,counter)+modelSBML.reaction(i).product(j).stoichiometry; +0691 end +0692 end +0693 +0694 %if FBC, objective function is separately defined. Multiple objective +0695 %functions can be defined, one is set as active +0696 if isfield(modelSBML, 'fbc_activeObjective') +0697 obj=modelSBML.fbc_activeObjective; +0698 for i=1:numel(modelSBML.fbc_objective) +0699 if strcmp(obj,modelSBML.fbc_objective(i).fbc_id) +0700 rxn=modelSBML.fbc_objective(i).fbc_fluxObjective.fbc_reaction; +0701 rxn=regexprep(rxn,'^R_',''); +0702 idx=find(ismember(reactionIDs,rxn)); +0703 reactionObjective(idx)=modelSBML.fbc_objective(i).fbc_fluxObjective.fbc_coefficient; +0704 end +0705 end +0706 end +0707 +0708 %subSystems can be stored as groups instead of in annotations +0709 if isfield(modelSBML,'groups_group') +0710 for i=1:numel(modelSBML.groups_group) +0711 groupreactions={modelSBML.groups_group(i).groups_member(:).groups_idRef}; +0712 groupreactions=regexprep(groupreactions,'^R_',''); +0713 [~, idx] = ismember(groupreactions, reactionIDs); +0714 if any(idx) +0715 for j=1:numel(idx) +0716 if isempty(subsystems{idx(j)}) % First subsystem +0717 subsystems{idx(j)} = {modelSBML.groups_group(i).groups_name}; +0718 else % Consecutive subsystems: concatenate +0719 subsystems{idx(j)} = horzcat(subsystems{idx(j)}, modelSBML.groups_group(i).groups_name); +0720 end +0721 end +0722 end +0723 end +0724 end +0725 +0726 %Shrink the structures if complex-forming reactions had to be skipped +0727 reactionNames=reactionNames(1:counter); +0728 reactionIDs=reactionIDs(1:counter); +0729 subsystems=subsystems(1:counter); +0730 eccodes=eccodes(1:counter); +0731 rxnconfidencescores=rxnconfidencescores(1:counter); +0732 rxnreferences=rxnreferences(1:counter); +0733 rxnnotes=rxnnotes(1:counter); +0734 grRules=grRules(1:counter); +0735 rxnMiriams=rxnMiriams(1:counter); +0736 reactionReversibility=reactionReversibility(1:counter); +0737 reactionUB=reactionUB(1:counter); +0738 reactionLB=reactionLB(1:counter); +0739 reactionObjective=reactionObjective(1:counter); +0740 S=S(:,1:counter); +0741 +0742 model.name=modelSBML.name; +0743 model.id=regexprep(modelSBML.id,'^M_',''); % COBRA adds M_ prefix +0744 model.rxns=reactionIDs; +0745 model.mets=metaboliteIDs; +0746 model.S=sparse(S); +0747 model.lb=reactionLB; +0748 model.ub=reactionUB; +0749 model.rev=reactionReversibility; +0750 model.c=reactionObjective; +0751 model.b=zeros(numel(metaboliteIDs),1); +0752 model.comps=compartmentIDs; +0753 model.compNames=compartmentNames; +0754 model.rxnConfidenceScores=rxnconfidencescores; +0755 model.rxnReferences=rxnreferences; +0756 model.rxnNotes=rxnnotes; +0757 +0758 %Load annotation if available. If there are several authors, only the first +0759 %author credentials are imported +0760 if isfield(modelSBML,'annotation') +0761 endString='</'; +0762 I=strfind(modelSBML.annotation,endString); +0763 J=strfind(modelSBML.annotation,'<vCard:Family>'); 0764 if any(J) -0765 model.annotation.givenName=modelSBML.annotation(J(1)+13:I(find(I>J(1),1))-1); +0765 model.annotation.familyName=modelSBML.annotation(J(1)+14:I(find(I>J(1),1))-1); 0766 end -0767 J=strfind(modelSBML.annotation,'<vCard:EMAIL>'); +0767 J=strfind(modelSBML.annotation,'<vCard:Given>'); 0768 if any(J) -0769 model.annotation.email=modelSBML.annotation(J(1)+13:I(find(I>J(1),1))-1); +0769 model.annotation.givenName=modelSBML.annotation(J(1)+13:I(find(I>J(1),1))-1); 0770 end -0771 J=strfind(modelSBML.annotation,'<vCard:Orgname>'); +0771 J=strfind(modelSBML.annotation,'<vCard:EMAIL>'); 0772 if any(J) -0773 model.annotation.organization=modelSBML.annotation(J(1)+15:I(find(I>J(1),1))-1); +0773 model.annotation.email=modelSBML.annotation(J(1)+13:I(find(I>J(1),1))-1); 0774 end -0775 endString='"/>'; -0776 I=strfind(modelSBML.annotation,endString); -0777 if strfind(modelSBML.annotation,'"urn:miriam:') -0778 J=strfind(modelSBML.annotation,'"urn:miriam:'); -0779 if any(J) -0780 model.annotation.taxonomy=modelSBML.annotation(J+12:I(find(I>J,1))-1); -0781 end -0782 else -0783 J=strfind(modelSBML.annotation,'"http://identifiers.org/'); -0784 if any(J) -0785 model.annotation.taxonomy=modelSBML.annotation(J+24:I(find(I>J,1))-1); -0786 else -0787 J=strfind(modelSBML.annotation,'"https://identifiers.org/'); -0788 if any(J) -0789 model.annotation.taxonomy=modelSBML.annotation(J+25:I(find(I>J,1))-1); -0790 end -0791 end -0792 end -0793 end -0794 if isfield(modelSBML,'notes') -0795 startString=strfind(modelSBML.notes,'xhtml">'); -0796 endString=strfind(modelSBML.notes,'</body>'); -0797 if any(startString) && any(endString) -0798 model.annotation.note=modelSBML.notes(startString+7:endString-1); -0799 model.annotation.note=regexprep(model.annotation.note,'<p>|</p>',''); -0800 model.annotation.note=strtrim(model.annotation.note); -0801 end -0802 end -0803 -0804 if any(~cellfun(@isempty,compartmentOutside)) -0805 model.compOutside=compartmentOutside; +0775 J=strfind(modelSBML.annotation,'<vCard:Orgname>'); +0776 if any(J) +0777 model.annotation.organization=modelSBML.annotation(J(1)+15:I(find(I>J(1),1))-1); +0778 end +0779 endString='"/>'; +0780 I=strfind(modelSBML.annotation,endString); +0781 if strfind(modelSBML.annotation,'"urn:miriam:') +0782 J=strfind(modelSBML.annotation,'"urn:miriam:'); +0783 if any(J) +0784 model.annotation.taxonomy=modelSBML.annotation(J+12:I(find(I>J,1))-1); +0785 end +0786 else +0787 J=strfind(modelSBML.annotation,'"http://identifiers.org/'); +0788 if any(J) +0789 model.annotation.taxonomy=modelSBML.annotation(J+24:I(find(I>J,1))-1); +0790 else +0791 J=strfind(modelSBML.annotation,'"https://identifiers.org/'); +0792 if any(J) +0793 model.annotation.taxonomy=modelSBML.annotation(J+25:I(find(I>J,1))-1); +0794 end +0795 end +0796 end +0797 end +0798 if isfield(modelSBML,'notes') +0799 startString=strfind(modelSBML.notes,'xhtml">'); +0800 endString=strfind(modelSBML.notes,'</body>'); +0801 if any(startString) && any(endString) +0802 model.annotation.note=modelSBML.notes(startString+7:endString-1); +0803 model.annotation.note=regexprep(model.annotation.note,'<p>|</p>',''); +0804 model.annotation.note=strtrim(model.annotation.note); +0805 end 0806 end 0807 -0808 model.rxnNames=reactionNames; -0809 model.metNames=metaboliteNames; -0810 -0811 %Match the compartments for metabolites -0812 [~, J]=ismember(metaboliteCompartments,model.comps); -0813 model.metComps=J; +0808 if any(~cellfun(@isempty,compartmentOutside)) +0809 model.compOutside=compartmentOutside; +0810 end +0811 +0812 model.rxnNames=reactionNames; +0813 model.metNames=metaboliteNames; 0814 -0815 %If any genes have been loaded (only for the new format) -0816 if ~isempty(geneNames) -0817 %In some rare cases geneNames may not necessarily be used in grRules. -0818 %That is true for Yeast 7.6. It's therefore important to change gene -0819 %systematic names to geneIDs in sophisticated way. Gene systematic -0820 %names are not unique, since exactly the same name may be in different -0821 %compartments -0822 if all(cellfun(@isempty,strfind(grRules,geneNames{1}))) -0823 geneShortNames=geneNames; -0824 %geneShortNames contain compartments as well, so these are removed -0825 geneShortNames=regexprep(geneShortNames,' \[.+$',''); -0826 %grRules obtained from modifier fields contain geneNames. These are -0827 %changed into geneIDs. grRulesFromModifier is a good way to have -0828 %geneIDs and rxns association when it's important to resolve -0829 %systematic name ambiguities -0830 grRulesFromModifier=regexprep(regexprep(grRulesFromModifier,'\[|\]','_'),regexprep(geneNames,'\[|\]','_'),geneIDs); -0831 grRules=regexprep(regexprep(grRules,'\[|\]','_'),regexprep(geneNames,'\[|\]','_'),geneIDs); -0832 -0833 %Yeast 7.6 contains several metabolites, which were used in gene -0834 %associations. For that reason, the list of species ID is created -0835 %and we then check whether any of them have kegg.genes annotation -0836 %thereby obtaining systematic gene names -0837 geneShortNames=vertcat(geneShortNames,metaboliteNames); -0838 geneIDs=vertcat(geneIDs,metaboliteIDs); -0839 geneSystNames=extractMiriam(vertcat(geneMiriams,metaboliteMiriams),'kegg.genes'); -0840 geneCompartments=vertcat(geneCompartments,metaboliteCompartments); -0841 geneMiriams=vertcat(geneMiriams,metaboliteMiriams); -0842 -0843 %Now we retain information for only these entries, which have -0844 %kegg.genes annotation -0845 geneShortNames=geneShortNames(~cellfun('isempty',geneSystNames)); -0846 geneIDs=geneIDs(~cellfun('isempty',geneSystNames)); -0847 geneSystNames=geneSystNames(~cellfun('isempty',geneSystNames)); -0848 geneCompartments=geneCompartments(~cellfun('isempty',geneSystNames)); -0849 geneMiriams=geneMiriams(~cellfun('isempty',geneSystNames)); -0850 %Now we reorder geneIDs and geneSystNames by geneSystNames string -0851 %length -0852 geneNames=geneIDs;%Backuping geneIDs, since we need unsorted order for later -0853 [~, Indx] = sort(cellfun('size', geneSystNames, 2), 'descend'); -0854 geneIDs = geneIDs(Indx); -0855 geneSystNames = geneSystNames(Indx); -0856 for i=1:numel(geneSystNames) -0857 for j=1:numel(grRules) -0858 if strfind(grRules{j},geneSystNames{i}) -0859 if ~isempty(grRules{j}) -0860 if sum(ismember(geneSystNames,geneSystNames{i}))==1 -0861 grRules{j}=regexprep(grRules{j},geneSystNames{i},geneIDs{i}); -0862 elseif sum(ismember(geneSystNames,geneSystNames{i}))>1 -0863 counter=0; -0864 ovrlpIDs=geneIDs(ismember(geneSystNames,geneSystNames{i})); -0865 for k=1:numel(ovrlpIDs) -0866 if strfind(grRulesFromModifier{j},ovrlpIDs{k}) -0867 counter=counter+1; -0868 grRules{j}=regexprep(grRules{j},geneSystNames{i},ovrlpIDs{k}); -0869 end -0870 if counter>1 -0871 EM=['Gene association is ambiguous for reaction ' modelSBML.reaction(j).id]; -0872 dispEM(EM); +0815 %Match the compartments for metabolites +0816 [~, J]=ismember(metaboliteCompartments,model.comps); +0817 model.metComps=J; +0818 +0819 %If any genes have been loaded (only for the new format) +0820 if ~isempty(geneNames) +0821 %In some rare cases geneNames may not necessarily be used in grRules. +0822 %That is true for Yeast 7.6. It's therefore important to change gene +0823 %systematic names to geneIDs in sophisticated way. Gene systematic +0824 %names are not unique, since exactly the same name may be in different +0825 %compartments +0826 if all(cellfun(@isempty,strfind(grRules,geneNames{1}))) +0827 geneShortNames=geneNames; +0828 %geneShortNames contain compartments as well, so these are removed +0829 geneShortNames=regexprep(geneShortNames,' \[.+$',''); +0830 %grRules obtained from modifier fields contain geneNames. These are +0831 %changed into geneIDs. grRulesFromModifier is a good way to have +0832 %geneIDs and rxns association when it's important to resolve +0833 %systematic name ambiguities +0834 grRulesFromModifier=regexprep(regexprep(grRulesFromModifier,'\[|\]','_'),regexprep(geneNames,'\[|\]','_'),geneIDs); +0835 grRules=regexprep(regexprep(grRules,'\[|\]','_'),regexprep(geneNames,'\[|\]','_'),geneIDs); +0836 +0837 %Yeast 7.6 contains several metabolites, which were used in gene +0838 %associations. For that reason, the list of species ID is created +0839 %and we then check whether any of them have kegg.genes annotation +0840 %thereby obtaining systematic gene names +0841 geneShortNames=vertcat(geneShortNames,metaboliteNames); +0842 geneIDs=vertcat(geneIDs,metaboliteIDs); +0843 geneSystNames=extractMiriam(vertcat(geneMiriams,metaboliteMiriams),'kegg.genes'); +0844 geneCompartments=vertcat(geneCompartments,metaboliteCompartments); +0845 geneMiriams=vertcat(geneMiriams,metaboliteMiriams); +0846 +0847 %Now we retain information for only these entries, which have +0848 %kegg.genes annotation +0849 geneShortNames=geneShortNames(~cellfun('isempty',geneSystNames)); +0850 geneIDs=geneIDs(~cellfun('isempty',geneSystNames)); +0851 geneSystNames=geneSystNames(~cellfun('isempty',geneSystNames)); +0852 geneCompartments=geneCompartments(~cellfun('isempty',geneSystNames)); +0853 geneMiriams=geneMiriams(~cellfun('isempty',geneSystNames)); +0854 %Now we reorder geneIDs and geneSystNames by geneSystNames string +0855 %length +0856 geneNames=geneIDs;%Backuping geneIDs, since we need unsorted order for later +0857 [~, Indx] = sort(cellfun('size', geneSystNames, 2), 'descend'); +0858 geneIDs = geneIDs(Indx); +0859 geneSystNames = geneSystNames(Indx); +0860 for i=1:numel(geneSystNames) +0861 for j=1:numel(grRules) +0862 if strfind(grRules{j},geneSystNames{i}) +0863 if ~isempty(grRules{j}) +0864 if sum(ismember(geneSystNames,geneSystNames{i}))==1 +0865 grRules{j}=regexprep(grRules{j},geneSystNames{i},geneIDs{i}); +0866 elseif sum(ismember(geneSystNames,geneSystNames{i}))>1 +0867 counter=0; +0868 ovrlpIDs=geneIDs(ismember(geneSystNames,geneSystNames{i})); +0869 for k=1:numel(ovrlpIDs) +0870 if strfind(grRulesFromModifier{j},ovrlpIDs{k}) +0871 counter=counter+1; +0872 grRules{j}=regexprep(grRules{j},geneSystNames{i},ovrlpIDs{k}); 0873 end -0874 end -0875 end -0876 end -0877 end -0878 end -0879 end -0880 end -0881 model.genes=geneNames; -0882 model.grRules=grRules; -0883 [grRules,rxnGeneMat] = standardizeGrRules(model,true); -0884 model.grRules = grRules; -0885 model.rxnGeneMat = rxnGeneMat; -0886 -0887 %Match the compartments for genes -0888 [~, J]=ismember(geneCompartments,model.comps); -0889 model.geneComps=J; -0890 else -0891 if ~all(cellfun(@isempty,grRules)) -0892 %If fbc_geneProduct exists, follow the specified gene order, such -0893 %that matching geneShortNames in function below will work -0894 if isfield(modelSBML,'fbc_geneProduct') -0895 genes={modelSBML.fbc_geneProduct.fbc_id}; -0896 -0897 %Get gene Miriams if they were not retrieved above (this occurs -0898 %when genes are stored as fbc_geneProduct instead of species) -0899 if isempty(geneMiriams) -0900 geneMiriams = cell(numel(genes),1); -0901 if isfield(modelSBML.fbc_geneProduct,'sboTerm') && numel(unique([modelSBML.fbc_geneProduct.sboTerm])) == 1 -0902 %If all the SBO terms are identical, don't add them to geneMiriams -0903 modelSBML.fbc_geneProduct = rmfield(modelSBML.fbc_geneProduct,'sboTerm'); -0904 end -0905 for i = 1:numel(genes) -0906 geneMiriams{i}=parseMiriam(modelSBML.fbc_geneProduct(i).annotation); -0907 if isfield(modelSBML.fbc_geneProduct(i),'sboTerm') -0908 geneMiriams{i} = addSBOtoMiriam(geneMiriams{i},modelSBML.fbc_geneProduct(i).sboTerm); -0909 end -0910 end -0911 end -0912 else -0913 genes=getGeneList(grRules); -0914 end -0915 if strcmpi(genes{1}(1:2),'G_') -0916 genes=regexprep(genes,'^G_',''); -0917 grRules=regexprep(grRules,'^G_',''); -0918 grRules=regexprep(grRules,'\(G_','('); -0919 grRules=regexprep(grRules,' G_',' '); -0920 end -0921 model.genes=genes; -0922 model.grRules=grRules; -0923 [grRules,rxnGeneMat] = standardizeGrRules(model,true); -0924 model.grRules = grRules; -0925 model.rxnGeneMat = rxnGeneMat; -0926 end -0927 end -0928 -0929 if all(cellfun(@isempty,geneShortNames)) -0930 if isfield(modelSBML,'fbc_geneProduct') -0931 for i=1:numel(genes) -0932 if ~isempty(modelSBML.fbc_geneProduct(i).fbc_label) -0933 geneShortNames{i,1}=modelSBML.fbc_geneProduct(i).fbc_label; -0934 elseif ~isempty(modelSBML.fbc_geneProduct(i).fbc_name) -0935 geneShortNames{i,1}=modelSBML.fbc_geneProduct(i).fbc_name; -0936 else -0937 geneShortNames{i,1}=''; -0938 end -0939 end -0940 end -0941 end -0942 -0943 %If any InChIs have been loaded -0944 if any(~cellfun(@isempty,metaboliteInChI)) -0945 model.inchis=metaboliteInChI; -0946 end -0947 -0948 %If any formulas have been loaded -0949 if any(~cellfun(@isempty,metaboliteFormula)) -0950 model.metFormulas=metaboliteFormula; -0951 end -0952 -0953 %If any charges have been loaded -0954 if ~isempty(metaboliteCharges) -0955 model.metCharges=metaboliteCharges; -0956 end -0957 -0958 %If any gene short names have been loaded -0959 if any(~cellfun(@isempty,geneShortNames)) -0960 model.geneShortNames=geneShortNames; -0961 end -0962 -0963 %If any Miriam strings for compartments have been loaded -0964 if any(~cellfun(@isempty,compartmentMiriams)) -0965 model.compMiriams=compartmentMiriams; -0966 end -0967 -0968 %If any Miriam strings for metabolites have been loaded -0969 if any(~cellfun(@isempty,metaboliteMiriams)) -0970 model.metMiriams=metaboliteMiriams; -0971 end -0972 -0973 %If any subsystems have been loaded -0974 if any(~cellfun(@isempty,subsystems)) -0975 model.subSystems=subsystems; -0976 end -0977 if any(rxnComps) -0978 if all(rxnComps) -0979 model.rxnComps=rxnComps; -0980 else -0981 if supressWarnings==false -0982 EM='The compartments for the following reactions could not be matched. Ignoring reaction compartment information'; -0983 dispEM(EM,false,model.rxns(rxnComps==0)); -0984 end -0985 end -0986 end -0987 -0988 %If any ec-codes have been loaded -0989 if any(~cellfun(@isempty,eccodes)) -0990 model.eccodes=eccodes; -0991 end -0992 -0993 %If any Miriam strings for reactions have been loaded -0994 if any(~cellfun(@isempty,rxnMiriams)) -0995 model.rxnMiriams=rxnMiriams; -0996 end -0997 -0998 %If any Miriam strings for genes have been loaded -0999 if any(~cellfun(@isempty,geneMiriams)) -1000 model.geneMiriams=geneMiriams; -1001 end -1002 -1003 model.unconstrained=metaboliteUnconstrained; -1004 -1005 %Convert SBML IDs back into their original strings. Here we are using part -1006 %from convertSBMLID, originating from the COBRA Toolbox -1007 model.rxns=regexprep(model.rxns,'__([0-9]+)__','${char(str2num($1))}'); -1008 model.mets=regexprep(model.mets,'__([0-9]+)__','${char(str2num($1))}'); -1009 model.comps=regexprep(model.comps,'__([0-9]+)__','${char(str2num($1))}'); -1010 model.grRules=regexprep(model.grRules,'__([0-9]+)__','${char(str2num($1))}'); -1011 model.genes=regexprep(model.genes,'__([0-9]+)__','${char(str2num($1))}'); -1012 model.id=regexprep(model.id,'__([0-9]+)__','${char(str2num($1))}'); -1013 -1014 %Remove unused fields -1015 if isempty(model.annotation) -1016 model=rmfield(model,'annotation'); -1017 end -1018 if isempty(model.compOutside) -1019 model=rmfield(model,'compOutside'); -1020 end -1021 if isempty(model.compMiriams) -1022 model=rmfield(model,'compMiriams'); -1023 end -1024 if isempty(model.rxnComps) -1025 model=rmfield(model,'rxnComps'); -1026 end -1027 if isempty(model.grRules) -1028 model=rmfield(model,'grRules'); -1029 end -1030 if isempty(model.rxnGeneMat) -1031 model=rmfield(model,'rxnGeneMat'); -1032 end -1033 if isempty(model.subSystems) -1034 model=rmfield(model,'subSystems'); -1035 end -1036 if isempty(model.eccodes) -1037 model=rmfield(model,'eccodes'); -1038 end -1039 if isempty(model.rxnMiriams) -1040 model=rmfield(model,'rxnMiriams'); -1041 end -1042 if cellfun(@isempty,model.rxnNotes) -1043 model=rmfield(model,'rxnNotes'); -1044 end -1045 if cellfun(@isempty,model.rxnReferences) -1046 model=rmfield(model,'rxnReferences'); -1047 end -1048 if isempty(model.rxnConfidenceScores) || all(isnan(model.rxnConfidenceScores)) -1049 model=rmfield(model,'rxnConfidenceScores'); -1050 end -1051 if isempty(model.genes) -1052 model=rmfield(model,'genes'); -1053 elseif isrow(model.genes) -1054 model.genes=transpose(model.genes); -1055 end -1056 if isempty(model.geneComps) -1057 model=rmfield(model,'geneComps'); -1058 end -1059 if isempty(model.geneMiriams) -1060 model=rmfield(model,'geneMiriams'); -1061 end -1062 if isempty(model.geneShortNames) -1063 model=rmfield(model,'geneShortNames'); -1064 end -1065 if isempty(model.inchis) -1066 model=rmfield(model,'inchis'); -1067 end -1068 if isempty(model.metFormulas) -1069 model=rmfield(model,'metFormulas'); -1070 end -1071 if isempty(model.metMiriams) -1072 model=rmfield(model,'metMiriams'); -1073 end -1074 if ~any(model.metCharges) -1075 model=rmfield(model,'metCharges'); -1076 end -1077 -1078 %This just removes the grRules if no genes have been loaded -1079 if ~isfield(model,'genes') && isfield(model,'grRules') -1080 model=rmfield(model,'grRules'); -1081 end -1082 -1083 %Print warnings about bad structure -1084 if supressWarnings==false -1085 checkModelStruct(model,false); -1086 end -1087 -1088 if removeExcMets==true -1089 model=simplifyModel(model); +0874 if counter>1 +0875 EM=['Gene association is ambiguous for reaction ' modelSBML.reaction(j).id]; +0876 dispEM(EM); +0877 end +0878 end +0879 end +0880 end +0881 end +0882 end +0883 end +0884 end +0885 model.genes=geneNames; +0886 model.grRules=grRules; +0887 [grRules,rxnGeneMat] = standardizeGrRules(model,true); +0888 model.grRules = grRules; +0889 model.rxnGeneMat = rxnGeneMat; +0890 +0891 %Match the compartments for genes +0892 [~, J]=ismember(geneCompartments,model.comps); +0893 model.geneComps=J; +0894 else +0895 if ~all(cellfun(@isempty,grRules)) +0896 %If fbc_geneProduct exists, follow the specified gene order, such +0897 %that matching geneShortNames in function below will work +0898 if isfield(modelSBML,'fbc_geneProduct') +0899 genes={modelSBML.fbc_geneProduct.fbc_id}; +0900 +0901 %Get gene Miriams if they were not retrieved above (this occurs +0902 %when genes are stored as fbc_geneProduct instead of species) +0903 if isempty(geneMiriams) +0904 geneMiriams = cell(numel(genes),1); +0905 if isfield(modelSBML.fbc_geneProduct,'sboTerm') && numel(unique([modelSBML.fbc_geneProduct.sboTerm])) == 1 +0906 %If all the SBO terms are identical, don't add them to geneMiriams +0907 modelSBML.fbc_geneProduct = rmfield(modelSBML.fbc_geneProduct,'sboTerm'); +0908 end +0909 for i = 1:numel(genes) +0910 geneMiriams{i}=parseMiriam(modelSBML.fbc_geneProduct(i).annotation); +0911 if isfield(modelSBML.fbc_geneProduct(i),'sboTerm') +0912 geneMiriams{i} = addSBOtoMiriam(geneMiriams{i},modelSBML.fbc_geneProduct(i).sboTerm); +0913 end +0914 end +0915 end +0916 else +0917 genes=getGeneList(grRules); +0918 end +0919 if strcmpi(genes{1}(1:2),'G_') +0920 genes=regexprep(genes,'^G_',''); +0921 grRules=regexprep(grRules,'^G_',''); +0922 grRules=regexprep(grRules,'\(G_','('); +0923 grRules=regexprep(grRules,' G_',' '); +0924 end +0925 model.genes=genes; +0926 model.grRules=grRules; +0927 [grRules,rxnGeneMat] = standardizeGrRules(model,true); +0928 model.grRules = grRules; +0929 model.rxnGeneMat = rxnGeneMat; +0930 end +0931 end +0932 +0933 if all(cellfun(@isempty,geneShortNames)) +0934 if isfield(modelSBML,'fbc_geneProduct') +0935 for i=1:numel(genes) +0936 if ~isempty(modelSBML.fbc_geneProduct(i).fbc_label) +0937 geneShortNames{i,1}=modelSBML.fbc_geneProduct(i).fbc_label; +0938 elseif ~isempty(modelSBML.fbc_geneProduct(i).fbc_name) +0939 geneShortNames{i,1}=modelSBML.fbc_geneProduct(i).fbc_name; +0940 else +0941 geneShortNames{i,1}=''; +0942 end +0943 end +0944 end +0945 end +0946 +0947 %If any InChIs have been loaded +0948 if any(~cellfun(@isempty,metaboliteInChI)) +0949 model.inchis=metaboliteInChI; +0950 end +0951 +0952 %If any formulas have been loaded +0953 if any(~cellfun(@isempty,metaboliteFormula)) +0954 model.metFormulas=metaboliteFormula; +0955 end +0956 +0957 %If any charges have been loaded +0958 if ~isempty(metaboliteCharges) +0959 model.metCharges=metaboliteCharges; +0960 end +0961 +0962 %If any gene short names have been loaded +0963 if any(~cellfun(@isempty,geneShortNames)) +0964 model.geneShortNames=geneShortNames; +0965 end +0966 +0967 %If any Miriam strings for compartments have been loaded +0968 if any(~cellfun(@isempty,compartmentMiriams)) +0969 model.compMiriams=compartmentMiriams; +0970 end +0971 +0972 %If any Miriam strings for metabolites have been loaded +0973 if any(~cellfun(@isempty,metaboliteMiriams)) +0974 model.metMiriams=metaboliteMiriams; +0975 end +0976 +0977 %If any subsystems have been loaded +0978 if any(~cellfun(@isempty,subsystems)) +0979 model.subSystems=subsystems; +0980 end +0981 if any(rxnComps) +0982 if all(rxnComps) +0983 model.rxnComps=rxnComps; +0984 else +0985 if supressWarnings==false +0986 EM='The compartments for the following reactions could not be matched. Ignoring reaction compartment information'; +0987 dispEM(EM,false,model.rxns(rxnComps==0)); +0988 end +0989 end +0990 end +0991 +0992 %If any ec-codes have been loaded +0993 if any(~cellfun(@isempty,eccodes)) +0994 model.eccodes=eccodes; +0995 end +0996 +0997 %If any Miriam strings for reactions have been loaded +0998 if any(~cellfun(@isempty,rxnMiriams)) +0999 model.rxnMiriams=rxnMiriams; +1000 end +1001 +1002 %If any Miriam strings for genes have been loaded +1003 if any(~cellfun(@isempty,geneMiriams)) +1004 model.geneMiriams=geneMiriams; +1005 end +1006 +1007 model.unconstrained=metaboliteUnconstrained; +1008 +1009 %Convert SBML IDs back into their original strings. Here we are using part +1010 %from convertSBMLID, originating from the COBRA Toolbox +1011 model.rxns=regexprep(model.rxns,'__([0-9]+)__','${char(str2num($1))}'); +1012 model.mets=regexprep(model.mets,'__([0-9]+)__','${char(str2num($1))}'); +1013 model.comps=regexprep(model.comps,'__([0-9]+)__','${char(str2num($1))}'); +1014 model.grRules=regexprep(model.grRules,'__([0-9]+)__','${char(str2num($1))}'); +1015 model.genes=regexprep(model.genes,'__([0-9]+)__','${char(str2num($1))}'); +1016 model.id=regexprep(model.id,'__([0-9]+)__','${char(str2num($1))}'); +1017 +1018 %Remove unused fields +1019 if isempty(model.annotation) +1020 model=rmfield(model,'annotation'); +1021 end +1022 if isempty(model.compOutside) +1023 model=rmfield(model,'compOutside'); +1024 end +1025 if isempty(model.compMiriams) +1026 model=rmfield(model,'compMiriams'); +1027 end +1028 if isempty(model.rxnComps) +1029 model=rmfield(model,'rxnComps'); +1030 end +1031 if isempty(model.grRules) +1032 model=rmfield(model,'grRules'); +1033 end +1034 if isempty(model.rxnGeneMat) +1035 model=rmfield(model,'rxnGeneMat'); +1036 end +1037 if isempty(model.subSystems) +1038 model=rmfield(model,'subSystems'); +1039 end +1040 if isempty(model.eccodes) +1041 model=rmfield(model,'eccodes'); +1042 end +1043 if isempty(model.rxnMiriams) +1044 model=rmfield(model,'rxnMiriams'); +1045 end +1046 if cellfun(@isempty,model.rxnNotes) +1047 model=rmfield(model,'rxnNotes'); +1048 end +1049 if cellfun(@isempty,model.rxnReferences) +1050 model=rmfield(model,'rxnReferences'); +1051 end +1052 if isempty(model.rxnConfidenceScores) || all(isnan(model.rxnConfidenceScores)) +1053 model=rmfield(model,'rxnConfidenceScores'); +1054 end +1055 if isempty(model.genes) +1056 model=rmfield(model,'genes'); +1057 elseif isrow(model.genes) +1058 model.genes=transpose(model.genes); +1059 end +1060 if isempty(model.geneComps) +1061 model=rmfield(model,'geneComps'); +1062 end +1063 if isempty(model.geneMiriams) +1064 model=rmfield(model,'geneMiriams'); +1065 end +1066 if isempty(model.geneShortNames) +1067 model=rmfield(model,'geneShortNames'); +1068 end +1069 if isempty(model.inchis) +1070 model=rmfield(model,'inchis'); +1071 end +1072 if isempty(model.metFormulas) +1073 model=rmfield(model,'metFormulas'); +1074 end +1075 if isempty(model.metMiriams) +1076 model=rmfield(model,'metMiriams'); +1077 end +1078 if ~any(model.metCharges) +1079 model=rmfield(model,'metCharges'); +1080 end +1081 +1082 %This just removes the grRules if no genes have been loaded +1083 if ~isfield(model,'genes') && isfield(model,'grRules') +1084 model=rmfield(model,'grRules'); +1085 end +1086 +1087 %Print warnings about bad structure +1088 if supressWarnings==false +1089 checkModelStruct(model,false); 1090 end -1091 end -1092 -1093 function matchGenes=getGeneList(grRules) -1094 %Constructs the list of unique genes from grRules -1095 -1096 %Assumes that everything that isn't a paranthesis, " AND " or " or " is a -1097 %gene name -1098 genes=strrep(grRules,'(',''); -1099 genes=strrep(genes,')',''); -1100 genes=strrep(genes,' or ',' '); -1101 genes=strrep(genes,' and ',' '); -1102 genes=strrep(genes,' OR ',' '); -1103 genes=strrep(genes,' AND ',' '); -1104 genes=regexp(genes,' ','split'); -1105 -1106 allNames={}; -1107 for i=1:numel(genes) -1108 allNames=[allNames genes{i}]; -1109 end -1110 matchGenes=unique(allNames)'; -1111 -1112 %Remove the empty element if present -1113 if isempty(matchGenes{1}) -1114 matchGenes(1)=[]; -1115 end -1116 end -1117 -1118 function fieldContent=parseNote(searchString,fieldName) -1119 %The function obtains the particular information from 'notes' field, using -1120 %fieldName as the dummy string +1091 +1092 if removeExcMets==true +1093 model=simplifyModel(model); +1094 end +1095 end +1096 +1097 function matchGenes=getGeneList(grRules) +1098 %Constructs the list of unique genes from grRules +1099 +1100 %Assumes that everything that isn't a paranthesis, " AND " or " or " is a +1101 %gene name +1102 genes=strrep(grRules,'(',''); +1103 genes=strrep(genes,')',''); +1104 genes=strrep(genes,' or ',' '); +1105 genes=strrep(genes,' and ',' '); +1106 genes=strrep(genes,' OR ',' '); +1107 genes=strrep(genes,' AND ',' '); +1108 genes=regexp(genes,' ','split'); +1109 +1110 allNames={}; +1111 for i=1:numel(genes) +1112 allNames=[allNames genes{i}]; +1113 end +1114 matchGenes=unique(allNames)'; +1115 +1116 %Remove the empty element if present +1117 if isempty(matchGenes{1}) +1118 matchGenes(1)=[]; +1119 end +1120 end 1121 -1122 fieldContent=''; -1123 -1124 if strfind(searchString,fieldName) -1125 [~,targetString] = regexp(searchString,['<p>' fieldName '.*?</p>'],'tokens','match'); -1126 targetString=regexprep(targetString,'<p>|</p>',''); -1127 targetString=regexprep(targetString,[fieldName, ':'],''); -1128 for i=1:numel(targetString) -1129 fieldContent=[fieldContent ';' strtrim(targetString{1,i})]; -1130 end -1131 fieldContent=regexprep(fieldContent,'^;|;$',''); -1132 else -1133 fieldContent=''; -1134 end -1135 end -1136 -1137 function fieldContent=parseAnnotation(searchString,startString,midString,fieldName) -1138 -1139 fieldContent=''; +1122 function fieldContent=parseNote(searchString,fieldName) +1123 %The function obtains the particular information from 'notes' field, using +1124 %fieldName as the dummy string +1125 +1126 fieldContent=''; +1127 +1128 if strfind(searchString,fieldName) +1129 [~,targetString] = regexp(searchString,['<p>' fieldName '.*?</p>'],'tokens','match'); +1130 targetString=regexprep(targetString,'<p>|</p>',''); +1131 targetString=regexprep(targetString,[fieldName, ':'],''); +1132 for i=1:numel(targetString) +1133 fieldContent=[fieldContent ';' strtrim(targetString{1,i})]; +1134 end +1135 fieldContent=regexprep(fieldContent,'^;|;$',''); +1136 else +1137 fieldContent=''; +1138 end +1139 end 1140 -1141 %Removing whitespace characters from the ending strings, which may occur in -1142 %several cases -1143 searchString=regexprep(searchString,'" />','"/>'); -1144 [~,targetString] = regexp(searchString,['<rdf:li rdf:resource="' startString fieldName midString '.*?"/>'],'tokens','match'); -1145 targetString=regexprep(targetString,'<rdf:li rdf:resource="|"/>',''); -1146 targetString=regexprep(targetString,startString,''); -1147 targetString=regexprep(targetString,[fieldName midString],''); -1148 -1149 for i=1:numel(targetString) -1150 fieldContent=[fieldContent ';' strtrim(targetString{1,i})]; -1151 end +1141 function fieldContent=parseAnnotation(searchString,startString,midString,fieldName) +1142 +1143 fieldContent=''; +1144 +1145 %Removing whitespace characters from the ending strings, which may occur in +1146 %several cases +1147 searchString=regexprep(searchString,'" />','"/>'); +1148 [~,targetString] = regexp(searchString,['<rdf:li rdf:resource="' startString fieldName midString '.*?"/>'],'tokens','match'); +1149 targetString=regexprep(targetString,'<rdf:li rdf:resource="|"/>',''); +1150 targetString=regexprep(targetString,startString,''); +1151 targetString=regexprep(targetString,[fieldName midString],''); 1152 -1153 fieldContent=regexprep(fieldContent,'^;|;$',''); -1154 end -1155 -1156 function miriamStruct=parseMiriam(searchString) -1157 %Generates miriam structure from annotation field -1158 -1159 %Finding whether miriams are written in the old or the new way -1160 if strfind(searchString,'urn:miriam:') -1161 startString='urn:miriam:'; -1162 midString=':'; -1163 elseif strfind(searchString,'http://identifiers.org/') -1164 startString='http://identifiers.org/'; -1165 midString='/'; -1166 elseif strfind(searchString,'https://identifiers.org/') -1167 startString='https://identifiers.org/'; -1168 midString='/'; -1169 else -1170 miriamStruct=[]; -1171 return; -1172 end -1173 -1174 miriamStruct=[]; -1175 -1176 searchString=regexprep(searchString,'" />','"/>'); -1177 [~,targetString] = regexp(searchString,'<rdf:li rdf:resource=".*?"/>','tokens','match'); -1178 targetString=regexprep(targetString,'<rdf:li rdf:resource="|"/>',''); -1179 targetString=regexprep(targetString,startString,''); -1180 targetString=regexprep(targetString,midString,'/','once'); -1181 -1182 counter=0; -1183 for i=1:numel(targetString) -1184 if isempty(regexp(targetString{1,i},'inchi|ec-code|sbo', 'once')) -1185 counter=counter+1; -1186 miriamStruct.name{counter,1} = regexprep(targetString{1,i},'/.+','','once'); -1187 miriamStruct.value{counter,1} = regexprep(targetString{1,i},[miriamStruct.name{counter,1} '/'],'','once'); -1188 miriamStruct.name{counter,1} = regexprep(miriamStruct.name{counter,1},'^obo\.',''); -1189 end -1190 end -1191 end -1192 -1193 function miriam = addSBOtoMiriam(miriam,sboTerm) -1194 %Appends SBO term to miriam structure -1195 -1196 sboTerm = {['SBO:' sprintf('%07u',sboTerm)]}; % convert to proper format -1197 if isempty(miriam) -1198 miriam.name = {'sbo'}; -1199 miriam.value = sboTerm; -1200 else -1201 miriam.name(end+1) = {'sbo'}; -1202 miriam.value(end+1) = sboTerm; -1203 end -1204 -1205 end +1153 for i=1:numel(targetString) +1154 fieldContent=[fieldContent ';' strtrim(targetString{1,i})]; +1155 end +1156 +1157 fieldContent=regexprep(fieldContent,'^;|;$',''); +1158 end +1159 +1160 function miriamStruct=parseMiriam(searchString) +1161 %Generates miriam structure from annotation field +1162 +1163 %Finding whether miriams are written in the old or the new way +1164 if strfind(searchString,'urn:miriam:') +1165 startString='urn:miriam:'; +1166 midString=':'; +1167 elseif strfind(searchString,'http://identifiers.org/') +1168 startString='http://identifiers.org/'; +1169 midString='/'; +1170 elseif strfind(searchString,'https://identifiers.org/') +1171 startString='https://identifiers.org/'; +1172 midString='/'; +1173 else +1174 miriamStruct=[]; +1175 return; +1176 end +1177 +1178 miriamStruct=[]; +1179 +1180 searchString=regexprep(searchString,'" />','"/>'); +1181 [~,targetString] = regexp(searchString,'<rdf:li rdf:resource=".*?"/>','tokens','match'); +1182 targetString=regexprep(targetString,'<rdf:li rdf:resource="|"/>',''); +1183 targetString=regexprep(targetString,startString,''); +1184 targetString=regexprep(targetString,midString,'/','once'); +1185 +1186 counter=0; +1187 for i=1:numel(targetString) +1188 if isempty(regexp(targetString{1,i},'inchi|ec-code|sbo', 'once')) +1189 counter=counter+1; +1190 miriamStruct.name{counter,1} = regexprep(targetString{1,i},'/.+','','once'); +1191 miriamStruct.value{counter,1} = regexprep(targetString{1,i},[miriamStruct.name{counter,1} '/'],'','once'); +1192 miriamStruct.name{counter,1} = regexprep(miriamStruct.name{counter,1},'^obo\.',''); +1193 end +1194 end +1195 end +1196 +1197 function miriam = addSBOtoMiriam(miriam,sboTerm) +1198 %Appends SBO term to miriam structure +1199 +1200 sboTerm = {['SBO:' sprintf('%07u',sboTerm)]}; % convert to proper format +1201 if isempty(miriam) +1202 miriam.name = {'sbo'}; +1203 miriam.value = sboTerm; +1204 else +1205 miriam.name(end+1) = {'sbo'}; +1206 miriam.value(end+1) = sboTerm; +1207 end +1208 +1209 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/loadWorkbook.html b/doc/io/loadWorkbook.html index ebca57da..bdd1b7cf 100644 --- a/doc/io/loadWorkbook.html +++ b/doc/io/loadWorkbook.html @@ -69,44 +69,51 @@

    SOURCE CODE ^end 0017 -0018 -0019 %Adds the required classes to the static Java path if not already added -0020 addJavaPaths(); -0021 -0022 %Import required classes from Apache POI -0023 import org.apache.poi.ss.usermodel.*; -0024 import org.apache.poi.ss.util.*; -0025 import java.io.FileInputStream; -0026 import org.apache.poi.hssf.usermodel.*; -0027 import org.apache.poi.xssf.usermodel.*; +0018 %Check if the user has MATLAB Text Analytics Toolbox installed, as it comes +0019 %with its own conflicting version of the required Apache POI files +0020 if exist('vaderSentimentScores.m')== 2 +0021 error(['MATLAB Text Analytics Toolbox found. This should be uninstalled ' ... +0022 'if you want to read/write Excel files. See RAVEN GitHub Issues '... +0023 'page for instructions.']) +0024 end +0025 +0026 %Adds the required classes to the static Java path if not already added +0027 addJavaPaths(); 0028 -0029 %Check if the file exists -0030 if ~(exist(fileName,'file')==2) -0031 if createEmpty==false -0032 EM='The Excel file could not be found'; -0033 dispEM(EM); -0034 else -0035 %Create an empty workbook -0036 [~,~,I]=fileparts(fileName); -0037 if strcmpi(I,'.xls') -0038 workbook=HSSFWorkbook(); -0039 else -0040 if strcmpi(I,'.xlsx') -0041 workbook=XSSFWorkbook(); -0042 else -0043 EM='The file name must end in .xls or .xlsx'; -0044 dispEM(EM); -0045 end -0046 end -0047 end -0048 else -0049 %Opens the workbook. The input stream is needed since it will otherwise -0050 %keep the file open -0051 is=FileInputStream(getFullPath(fileName)); -0052 workbook=WorkbookFactory.create(is); -0053 is.close(); -0054 end -0055 end +0029 %Import required classes from Apache POI +0030 import org.apache.poi.ss.usermodel.*; +0031 import org.apache.poi.ss.util.*; +0032 import java.io.FileInputStream; +0033 import org.apache.poi.hssf.usermodel.*; +0034 import org.apache.poi.xssf.usermodel.*; +0035 +0036 %Check if the file exists +0037 if ~(exist(fileName,'file')==2) +0038 if createEmpty==false +0039 EM='The Excel file could not be found'; +0040 dispEM(EM); +0041 else +0042 %Create an empty workbook +0043 [~,~,I]=fileparts(fileName); +0044 if strcmpi(I,'.xls') +0045 workbook=HSSFWorkbook(); +0046 else +0047 if strcmpi(I,'.xlsx') +0048 workbook=XSSFWorkbook(); +0049 else +0050 EM='The file name must end in .xls or .xlsx'; +0051 dispEM(EM); +0052 end +0053 end +0054 end +0055 else +0056 %Opens the workbook. The input stream is needed since it will otherwise +0057 %keep the file open +0058 is=FileInputStream(getFullPath(fileName)); +0059 workbook=WorkbookFactory.create(is); +0060 is.close(); +0061 end +0062 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/sortIdentifiers.html b/doc/io/sortIdentifiers.html index a65291c6..4d0081ee 100644 --- a/doc/io/sortIdentifiers.html +++ b/doc/io/sortIdentifiers.html @@ -47,7 +47,7 @@

    CROSS-REFERENCE INFORMATION ^
 </ul>
 This function is called by:
 <ul style= -
  • exportForGit exportForGit
  • exportModel exportModel
  • exportToExcelFormat exportToExcelFormat
  • exportToTabDelimited exportToTabDelimited
  • writeYaml writeYaml
  • +
  • exportForGit exportForGit
  • exportModel exportModel
  • exportToExcelFormat exportToExcelFormat
  • exportToTabDelimited exportToTabDelimited
  • writeYaml writeYaml
  • diff --git a/doc/io/writeYaml.html b/doc/io/writeYaml.html index f4a96175..ec7d475e 100644 --- a/doc/io/writeYaml.html +++ b/doc/io/writeYaml.html @@ -48,7 +48,7 @@

    CROSS-REFERENCE INFORMATION ^
 <li><a href=sortIdentifiers exportModel This function is called by: +
  • exportForGit exportForGit
  • SUBFUNCTIONS ^

    @@ -70,285 +70,286 @@

    SOURCE CODE ^% (logical, default=false) 0013 % 0014 % Usage: writeYaml(model,name,preserveQuotes,sortIds) -0015 -0016 if nargin < 3 -0017 preserveQuotes = true; -0018 end -0019 if nargin < 4 -0020 sortIds = false; -0021 end -0022 if ~endsWith(name,{'.yml','.yaml'}) -0023 name = strcat(name,'.yml'); -0024 end -0025 -0026 %Check that model is in RAVEN format: -0027 if isfield(model,'rules') -0028 model = ravenCobraWrapper(model); -0029 end -0030 -0031 %Sort identifiers alphabetically -0032 if sortIds == true -0033 model = sortIdentifiers(model); -0034 end -0035 -0036 %Simplify Miriam fields: -0037 if isfield(model,'metMiriams') -0038 [model.newMetMiriams,model.newMetMiriamNames] = extractMiriam(model.metMiriams); -0039 end -0040 if isfield(model,'rxnMiriams') -0041 [model.newRxnMiriams,model.newRxnMiriamNames] = extractMiriam(model.rxnMiriams); -0042 end -0043 if isfield(model,'geneMiriams') -0044 [model.newGeneMiriams,model.newGeneMiriamNames] = extractMiriam(model.geneMiriams); -0045 end -0046 if isfield(model,'compMiriams') -0047 [model.newCompMiriams,model.newCompMiriamNames] = extractMiriam(model.compMiriams); -0048 end -0049 -0050 %Open file: -0051 fid = fopen(name,'wt'); -0052 fprintf(fid,'---\n!!omap\n'); -0053 -0054 %Insert file header (metadata) -0055 writeMetadata(model,fid); -0056 -0057 %Metabolites: -0058 fprintf(fid,'- metabolites:\n'); -0059 for i = 1:length(model.mets) -0060 fprintf(fid,' - !!omap\n'); -0061 writeField(model, fid, 'mets', 'txt', i, ' - id', preserveQuotes) -0062 writeField(model, fid, 'metNames', 'txt', i, ' - name', preserveQuotes) -0063 writeField(model, fid, 'metComps', 'txt', i, ' - compartment', preserveQuotes) -0064 writeField(model, fid, 'metFormulas', 'txt', i, ' - formula', preserveQuotes) -0065 writeField(model, fid, 'metCharges', 'num', i, ' - charge', preserveQuotes) -0066 writeField(model, fid, 'inchis', 'txt', i, ' - inchis', preserveQuotes) -0067 writeField(model, fid, 'metMiriams', 'txt', i, ' - annotation', preserveQuotes) -0068 writeField(model, fid, 'metFrom', 'txt', i, ' - metFrom', preserveQuotes) -0069 end -0070 -0071 %Reactions: -0072 fprintf(fid,'- reactions:\n'); -0073 for i = 1:length(model.rxns) -0074 fprintf(fid,' - !!omap\n'); -0075 writeField(model, fid, 'rxns', 'txt', i, ' - id', preserveQuotes) -0076 writeField(model, fid, 'rxnNames', 'txt', i, ' - name', preserveQuotes) -0077 writeField(model, fid, 'S', 'txt', i, ' - metabolites', preserveQuotes) -0078 writeField(model, fid, 'lb', 'num', i, ' - lower_bound', preserveQuotes) -0079 writeField(model, fid, 'ub', 'num', i, ' - upper_bound', preserveQuotes) -0080 writeField(model, fid, 'grRules', 'txt', i, ' - gene_reaction_rule', preserveQuotes) -0081 writeField(model, fid, 'rxnFrom', 'txt', i, ' - rxnFrom', preserveQuotes) -0082 if model.c(i)~=0 -0083 writeField(model, fid, 'c', 'num', i, ' - objective_coefficient', preserveQuotes) -0084 end -0085 writeField(model, fid, 'eccodes', 'txt', i, ' - eccodes', preserveQuotes) -0086 writeField(model, fid, 'rxnReferences', 'txt', i, ' - references', preserveQuotes) -0087 writeField(model, fid, 'subSystems', 'txt', i, ' - subsystem', preserveQuotes) -0088 writeField(model, fid, 'rxnMiriams', 'txt', i, ' - annotation', preserveQuotes) -0089 writeField(model, fid, 'rxnConfidenceScores', 'num', i, ' - confidence_score', preserveQuotes) -0090 end -0091 -0092 %Genes: -0093 fprintf(fid,'- genes:\n'); -0094 for i = 1:length(model.genes) -0095 fprintf(fid,' - !!omap\n'); -0096 writeField(model, fid, 'genes', 'txt', i, ' - id', preserveQuotes) -0097 writeField(model, fid, 'geneShortNames', 'txt', i, ' - name', preserveQuotes) -0098 writeField(model, fid, 'geneMiriams', 'txt', i, ' - annotation', preserveQuotes) -0099 end -0100 -0101 %Compartments: -0102 fprintf(fid,'- compartments: !!omap\n'); -0103 for i = 1:length(model.comps) -0104 writeField(model, fid, 'compNames', 'txt', i, ['- ' model.comps{i}], preserveQuotes) -0105 writeField(model, fid, 'compMiriams', 'txt', i, '- annotation', preserveQuotes) -0106 end -0107 -0108 %Close file: -0109 fclose(fid); -0110 -0111 end -0112 -0113 function writeField(model,fid,fieldName,type,pos,name,preserveQuotes) -0114 %Writes a new line in the yaml file if the field exists and the field is -0115 %not empty at the correspoinding position. It's recursive for some fields -0116 %(metMiriams, rxnMiriams, and S) -0117 -0118 if isfield(model,fieldName) -0119 if strcmp(fieldName,'metComps') -0120 %metComps: write full name -0121 fieldName = 'comps'; -0122 pos = model.metComps(pos); -0123 end -0124 -0125 field = eval(['model.' fieldName]); -0126 -0127 if strcmp(fieldName,'metMiriams') -0128 if ~isempty(model.metMiriams{pos}) -0129 fprintf(fid,[' ' name ': !!omap\n']); -0130 for i=1:size(model.newMetMiriams,2) -0131 %'i' represents the different miriam names, e.g. -0132 %kegg.compound or chebi -0133 if ~isempty(model.newMetMiriams{pos,i}) -0134 %As during the following writeField call the value of -0135 %'i' would be lost, it is temporarily concatenated to -0136 %'name' parameter, which will be edited later -0137 writeField(model, fid, 'newMetMiriams', 'txt', pos, [' - ' model.newMetMiriamNames{i} '_' num2str(i)], preserveQuotes) -0138 end -0139 end -0140 end -0141 -0142 elseif strcmp(fieldName,'rxnMiriams') -0143 if ~isempty(model.rxnMiriams{pos}) -0144 fprintf(fid,[' ' name ': !!omap\n']); -0145 for i=1:size(model.newRxnMiriams,2) -0146 if ~isempty(model.newRxnMiriams{pos,i}) -0147 writeField(model, fid, 'newRxnMiriams', 'txt', pos, [' - ' model.newRxnMiriamNames{i} '_' num2str(i)], preserveQuotes) -0148 end -0149 end -0150 end -0151 -0152 elseif strcmp(fieldName,'geneMiriams') -0153 if ~isempty(model.geneMiriams{pos}) -0154 fprintf(fid,[' ' name ': !!omap\n']); -0155 for i=1:size(model.newGeneMiriams,2) -0156 if ~isempty(model.newGeneMiriams{pos,i}) -0157 writeField(model, fid, 'newGeneMiriams', 'txt', pos, [' - ' model.newGeneMiriamNames{i} '_' num2str(i)], preserveQuotes) -0158 end -0159 end -0160 end -0161 -0162 elseif strcmp(fieldName,'compMiriams') -0163 if ~isempty(model.compMiriams{pos}) -0164 fprintf(fid,[' ' name ': !!omap\n']); -0165 for i=1:size(model.newCompMiriams,2) -0166 if ~isempty(model.newCompMiriams{pos,i}) -0167 writeField(model, fid, 'newCompMiriams', 'txt', pos, [' - ' model.newCompMiriamNames{i} '_' num2str(i)], preserveQuotes) -0168 end -0169 end -0170 end -0171 -0172 elseif strcmp(fieldName,'S') -0173 %S: create header & write each metabolite in a new line -0174 fprintf(fid,[' ' name ': !!omap\n']); -0175 if sum(field(:,pos) ~= 0) > 0 -0176 model.mets = model.mets(field(:,pos) ~= 0); -0177 model.coeffs = field(field(:,pos) ~= 0,pos); -0178 %Sort metabolites: -0179 [model.mets,order] = sort(model.mets); -0180 model.coeffs = model.coeffs(order); -0181 for i = 1:length(model.mets) -0182 writeField(model, fid, 'coeffs', 'num', i, [' - ' model.mets{i}], preserveQuotes) -0183 end -0184 end -0185 -0186 elseif sum(strcmp({'subSystems','newMetMiriams','newRxnMiriams','newGeneMiriams','newCompMiriams','eccodes'},fieldName)) > 0 -0187 %eccodes/rxnNotes: if 1 write in 1 line, if more create header and list -0188 if strcmp(fieldName,'subSystems') -0189 list = field{pos}; %subSystems already comes in a cell array -0190 elseif strcmp(fieldName,'newMetMiriams') -0191 index = str2double(regexprep(name,'^.+_','')); -0192 name = regexprep(name,'_\d+$',''); -0193 list = strsplit(model.newMetMiriams{pos,index},'; '); -0194 elseif strcmp(fieldName,'newRxnMiriams') -0195 index = str2double(regexprep(name,'^.+_','')); -0196 name = regexprep(name,'_\d+$',''); -0197 list = strsplit(model.newRxnMiriams{pos,index},'; '); -0198 elseif strcmp(fieldName,'newGeneMiriams') -0199 index = str2double(regexprep(name,'^.+_','')); -0200 name = regexprep(name,'_\d+$',''); -0201 list = strsplit(model.newGeneMiriams{pos,index},'; '); -0202 elseif strcmp(fieldName,'newCompMiriams') -0203 index = str2double(regexprep(name,'^.+_','')); -0204 name = regexprep(name,'_\d+$',''); -0205 list = strsplit(model.newCompMiriams{pos,index},'; '); -0206 else -0207 list = strrep(field{pos},' ',''); %Exception for eccodes -0208 list = strsplit(list,';'); -0209 end -0210 -0211 if length(list) == 1 && ~strcmp(list{1},'') && ~strcmp(fieldName,'subSystems') -0212 if preserveQuotes -0213 list = strcat('"',list,'"'); -0214 end -0215 fprintf(fid,[' ' name ': ' list{1} '\n']); -0216 elseif length(list) > 1 || strcmp(fieldName,'subSystems') -0217 if preserveQuotes -0218 list = strcat('"',list,'"'); -0219 end -0220 fprintf(fid,[' ' name ':\n']); -0221 for i = 1:length(list) -0222 fprintf(fid,[regexprep(name,'(^\s*).*','$1') ' - ' list{i} '\n']); -0223 end -0224 end -0225 -0226 elseif sum(pos) > 0 -0227 %All other fields: -0228 if strcmp(type,'txt') -0229 value = field{pos}; -0230 if preserveQuotes && ~isempty(value) -0231 value = strcat('"',value,'"'); -0232 end -0233 elseif strcmp(type,'num') -0234 if isnan(field(pos)) -0235 value = []; -0236 else -0237 value = num2str(field(pos),12); -0238 end -0239 end -0240 if ~isempty(value) -0241 fprintf(fid,[' ' name ': ' value '\n']); -0242 end -0243 end -0244 end -0245 +0015 name=char(name); +0016 +0017 if nargin < 3 +0018 preserveQuotes = true; +0019 end +0020 if nargin < 4 +0021 sortIds = false; +0022 end +0023 if ~endsWith(name,{'.yml','.yaml'}) +0024 name = strcat(name,'.yml'); +0025 end +0026 +0027 %Check that model is in RAVEN format: +0028 if isfield(model,'rules') +0029 model = ravenCobraWrapper(model); +0030 end +0031 +0032 %Sort identifiers alphabetically +0033 if sortIds == true +0034 model = sortIdentifiers(model); +0035 end +0036 +0037 %Simplify Miriam fields: +0038 if isfield(model,'metMiriams') +0039 [model.newMetMiriams,model.newMetMiriamNames] = extractMiriam(model.metMiriams); +0040 end +0041 if isfield(model,'rxnMiriams') +0042 [model.newRxnMiriams,model.newRxnMiriamNames] = extractMiriam(model.rxnMiriams); +0043 end +0044 if isfield(model,'geneMiriams') +0045 [model.newGeneMiriams,model.newGeneMiriamNames] = extractMiriam(model.geneMiriams); +0046 end +0047 if isfield(model,'compMiriams') +0048 [model.newCompMiriams,model.newCompMiriamNames] = extractMiriam(model.compMiriams); +0049 end +0050 +0051 %Open file: +0052 fid = fopen(name,'wt'); +0053 fprintf(fid,'---\n!!omap\n'); +0054 +0055 %Insert file header (metadata) +0056 writeMetadata(model,fid); +0057 +0058 %Metabolites: +0059 fprintf(fid,'- metabolites:\n'); +0060 for i = 1:length(model.mets) +0061 fprintf(fid,' - !!omap\n'); +0062 writeField(model, fid, 'mets', 'txt', i, ' - id', preserveQuotes) +0063 writeField(model, fid, 'metNames', 'txt', i, ' - name', preserveQuotes) +0064 writeField(model, fid, 'metComps', 'txt', i, ' - compartment', preserveQuotes) +0065 writeField(model, fid, 'metFormulas', 'txt', i, ' - formula', preserveQuotes) +0066 writeField(model, fid, 'metCharges', 'num', i, ' - charge', preserveQuotes) +0067 writeField(model, fid, 'inchis', 'txt', i, ' - inchis', preserveQuotes) +0068 writeField(model, fid, 'metMiriams', 'txt', i, ' - annotation', preserveQuotes) +0069 writeField(model, fid, 'metFrom', 'txt', i, ' - metFrom', preserveQuotes) +0070 end +0071 +0072 %Reactions: +0073 fprintf(fid,'- reactions:\n'); +0074 for i = 1:length(model.rxns) +0075 fprintf(fid,' - !!omap\n'); +0076 writeField(model, fid, 'rxns', 'txt', i, ' - id', preserveQuotes) +0077 writeField(model, fid, 'rxnNames', 'txt', i, ' - name', preserveQuotes) +0078 writeField(model, fid, 'S', 'txt', i, ' - metabolites', preserveQuotes) +0079 writeField(model, fid, 'lb', 'num', i, ' - lower_bound', preserveQuotes) +0080 writeField(model, fid, 'ub', 'num', i, ' - upper_bound', preserveQuotes) +0081 writeField(model, fid, 'grRules', 'txt', i, ' - gene_reaction_rule', preserveQuotes) +0082 writeField(model, fid, 'rxnFrom', 'txt', i, ' - rxnFrom', preserveQuotes) +0083 if model.c(i)~=0 +0084 writeField(model, fid, 'c', 'num', i, ' - objective_coefficient', preserveQuotes) +0085 end +0086 writeField(model, fid, 'eccodes', 'txt', i, ' - eccodes', preserveQuotes) +0087 writeField(model, fid, 'rxnReferences', 'txt', i, ' - references', preserveQuotes) +0088 writeField(model, fid, 'subSystems', 'txt', i, ' - subsystem', preserveQuotes) +0089 writeField(model, fid, 'rxnMiriams', 'txt', i, ' - annotation', preserveQuotes) +0090 writeField(model, fid, 'rxnConfidenceScores', 'num', i, ' - confidence_score', preserveQuotes) +0091 end +0092 +0093 %Genes: +0094 fprintf(fid,'- genes:\n'); +0095 for i = 1:length(model.genes) +0096 fprintf(fid,' - !!omap\n'); +0097 writeField(model, fid, 'genes', 'txt', i, ' - id', preserveQuotes) +0098 writeField(model, fid, 'geneShortNames', 'txt', i, ' - name', preserveQuotes) +0099 writeField(model, fid, 'geneMiriams', 'txt', i, ' - annotation', preserveQuotes) +0100 end +0101 +0102 %Compartments: +0103 fprintf(fid,'- compartments: !!omap\n'); +0104 for i = 1:length(model.comps) +0105 writeField(model, fid, 'compNames', 'txt', i, ['- ' model.comps{i}], preserveQuotes) +0106 writeField(model, fid, 'compMiriams', 'txt', i, '- annotation', preserveQuotes) +0107 end +0108 +0109 %Close file: +0110 fclose(fid); +0111 +0112 end +0113 +0114 function writeField(model,fid,fieldName,type,pos,name,preserveQuotes) +0115 %Writes a new line in the yaml file if the field exists and the field is +0116 %not empty at the correspoinding position. It's recursive for some fields +0117 %(metMiriams, rxnMiriams, and S) +0118 +0119 if isfield(model,fieldName) +0120 if strcmp(fieldName,'metComps') +0121 %metComps: write full name +0122 fieldName = 'comps'; +0123 pos = model.metComps(pos); +0124 end +0125 +0126 field = eval(['model.' fieldName]); +0127 +0128 if strcmp(fieldName,'metMiriams') +0129 if ~isempty(model.metMiriams{pos}) +0130 fprintf(fid,[' ' name ': !!omap\n']); +0131 for i=1:size(model.newMetMiriams,2) +0132 %'i' represents the different miriam names, e.g. +0133 %kegg.compound or chebi +0134 if ~isempty(model.newMetMiriams{pos,i}) +0135 %As during the following writeField call the value of +0136 %'i' would be lost, it is temporarily concatenated to +0137 %'name' parameter, which will be edited later +0138 writeField(model, fid, 'newMetMiriams', 'txt', pos, [' - ' model.newMetMiriamNames{i} '_' num2str(i)], preserveQuotes) +0139 end +0140 end +0141 end +0142 +0143 elseif strcmp(fieldName,'rxnMiriams') +0144 if ~isempty(model.rxnMiriams{pos}) +0145 fprintf(fid,[' ' name ': !!omap\n']); +0146 for i=1:size(model.newRxnMiriams,2) +0147 if ~isempty(model.newRxnMiriams{pos,i}) +0148 writeField(model, fid, 'newRxnMiriams', 'txt', pos, [' - ' model.newRxnMiriamNames{i} '_' num2str(i)], preserveQuotes) +0149 end +0150 end +0151 end +0152 +0153 elseif strcmp(fieldName,'geneMiriams') +0154 if ~isempty(model.geneMiriams{pos}) +0155 fprintf(fid,[' ' name ': !!omap\n']); +0156 for i=1:size(model.newGeneMiriams,2) +0157 if ~isempty(model.newGeneMiriams{pos,i}) +0158 writeField(model, fid, 'newGeneMiriams', 'txt', pos, [' - ' model.newGeneMiriamNames{i} '_' num2str(i)], preserveQuotes) +0159 end +0160 end +0161 end +0162 +0163 elseif strcmp(fieldName,'compMiriams') +0164 if ~isempty(model.compMiriams{pos}) +0165 fprintf(fid,[' ' name ': !!omap\n']); +0166 for i=1:size(model.newCompMiriams,2) +0167 if ~isempty(model.newCompMiriams{pos,i}) +0168 writeField(model, fid, 'newCompMiriams', 'txt', pos, [' - ' model.newCompMiriamNames{i} '_' num2str(i)], preserveQuotes) +0169 end +0170 end +0171 end +0172 +0173 elseif strcmp(fieldName,'S') +0174 %S: create header & write each metabolite in a new line +0175 fprintf(fid,[' ' name ': !!omap\n']); +0176 if sum(field(:,pos) ~= 0) > 0 +0177 model.mets = model.mets(field(:,pos) ~= 0); +0178 model.coeffs = field(field(:,pos) ~= 0,pos); +0179 %Sort metabolites: +0180 [model.mets,order] = sort(model.mets); +0181 model.coeffs = model.coeffs(order); +0182 for i = 1:length(model.mets) +0183 writeField(model, fid, 'coeffs', 'num', i, [' - ' model.mets{i}], preserveQuotes) +0184 end +0185 end +0186 +0187 elseif sum(strcmp({'subSystems','newMetMiriams','newRxnMiriams','newGeneMiriams','newCompMiriams','eccodes'},fieldName)) > 0 +0188 %eccodes/rxnNotes: if 1 write in 1 line, if more create header and list +0189 if strcmp(fieldName,'subSystems') +0190 list = field{pos}; %subSystems already comes in a cell array +0191 elseif strcmp(fieldName,'newMetMiriams') +0192 index = str2double(regexprep(name,'^.+_','')); +0193 name = regexprep(name,'_\d+$',''); +0194 list = strsplit(model.newMetMiriams{pos,index},'; '); +0195 elseif strcmp(fieldName,'newRxnMiriams') +0196 index = str2double(regexprep(name,'^.+_','')); +0197 name = regexprep(name,'_\d+$',''); +0198 list = strsplit(model.newRxnMiriams{pos,index},'; '); +0199 elseif strcmp(fieldName,'newGeneMiriams') +0200 index = str2double(regexprep(name,'^.+_','')); +0201 name = regexprep(name,'_\d+$',''); +0202 list = strsplit(model.newGeneMiriams{pos,index},'; '); +0203 elseif strcmp(fieldName,'newCompMiriams') +0204 index = str2double(regexprep(name,'^.+_','')); +0205 name = regexprep(name,'_\d+$',''); +0206 list = strsplit(model.newCompMiriams{pos,index},'; '); +0207 else +0208 list = strrep(field{pos},' ',''); %Exception for eccodes +0209 list = strsplit(list,';'); +0210 end +0211 +0212 if length(list) == 1 && ~strcmp(list{1},'') && ~strcmp(fieldName,'subSystems') +0213 if preserveQuotes +0214 list = strcat('"',list,'"'); +0215 end +0216 fprintf(fid,[' ' name ': ' list{1} '\n']); +0217 elseif length(list) > 1 || strcmp(fieldName,'subSystems') +0218 if preserveQuotes +0219 list = strcat('"',list,'"'); +0220 end +0221 fprintf(fid,[' ' name ':\n']); +0222 for i = 1:length(list) +0223 fprintf(fid,[regexprep(name,'(^\s*).*','$1') ' - ' list{i} '\n']); +0224 end +0225 end +0226 +0227 elseif sum(pos) > 0 +0228 %All other fields: +0229 if strcmp(type,'txt') +0230 value = field{pos}; +0231 if preserveQuotes && ~isempty(value) +0232 value = strcat('"',value,'"'); +0233 end +0234 elseif strcmp(type,'num') +0235 if isnan(field(pos)) +0236 value = []; +0237 else +0238 value = num2str(field(pos),12); +0239 end +0240 end +0241 if ~isempty(value) +0242 fprintf(fid,[' ' name ': ' value '\n']); +0243 end +0244 end +0245 end 0246 -0247 end -0248 -0249 function writeMetadata(model,fid) -0250 % Writes model metadata to the yaml file. This information will eventually -0251 % be extracted entirely from the model, but for now, many of the entries -0252 % are hard-coded defaults for HumanGEM. -0253 -0254 fprintf(fid, '- metaData:\n'); -0255 fprintf(fid, [' id: "', model.id, '"\n']); -0256 fprintf(fid, [' name: "', model.name, '"\n']); -0257 if isfield(model,'version') -0258 fprintf(fid, [' version: "', model.version, '"\n']); -0259 end -0260 fprintf(fid, [' date: "', datestr(now,29), '"\n']); % 29=YYYY-MM-DD -0261 if isfield(model,'annotation') -0262 if isfield(model.annotation,'defaultLB') -0263 fprintf(fid, [' defaultLB: "', num2str(model.annotation.defaultLB), '"\n']); -0264 end -0265 if isfield(model.annotation,'defaultUB') -0266 fprintf(fid, [' defaultUB: "', num2str(model.annotation.defaultUB), '"\n']); -0267 end -0268 if isfield(model.annotation,'givenName') -0269 fprintf(fid, [' givenName: "', model.annotation.givenName, '"\n']); -0270 end -0271 if isfield(model.annotation,'familyName') -0272 fprintf(fid, [' familyName: "', model.annotation.familyName, '"\n']); -0273 end -0274 if isfield(model.annotation,'authors') -0275 fprintf(fid, [' authors: "', model.annotation.authors, '"\n']); -0276 end -0277 if isfield(model.annotation,'email') -0278 fprintf(fid, [' email: "', model.annotation.email, '"\n']); -0279 end -0280 if isfield(model.annotation,'organization') -0281 fprintf(fid, [' organization: "', model.annotation.organization, '"\n']); -0282 end -0283 if isfield(model.annotation,'taxonomy') -0284 fprintf(fid, [' taxonomy: "', model.annotation.taxonomy, '"\n']); -0285 end -0286 if isfield(model.annotation,'note') -0287 fprintf(fid, [' note: "', model.annotation.note, '"\n']); -0288 end -0289 if isfield(model.annotation,'sourceUrl') -0290 fprintf(fid, [' sourceUrl: "', model.annotation.sourceUrl, '"\n']); -0291 end -0292 end -0293 end +0247 +0248 end +0249 +0250 function writeMetadata(model,fid) +0251 % Writes model metadata to the yaml file. This information will eventually +0252 % be extracted entirely from the model, but for now, many of the entries +0253 % are hard-coded defaults for HumanGEM. +0254 +0255 fprintf(fid, '- metaData:\n'); +0256 fprintf(fid, [' id: "', model.id, '"\n']); +0257 fprintf(fid, [' name: "', model.name, '"\n']); +0258 if isfield(model,'version') +0259 fprintf(fid, [' version: "', model.version, '"\n']); +0260 end +0261 fprintf(fid, [' date: "', datestr(now,29), '"\n']); % 29=YYYY-MM-DD +0262 if isfield(model,'annotation') +0263 if isfield(model.annotation,'defaultLB') +0264 fprintf(fid, [' defaultLB: "', num2str(model.annotation.defaultLB), '"\n']); +0265 end +0266 if isfield(model.annotation,'defaultUB') +0267 fprintf(fid, [' defaultUB: "', num2str(model.annotation.defaultUB), '"\n']); +0268 end +0269 if isfield(model.annotation,'givenName') +0270 fprintf(fid, [' givenName: "', model.annotation.givenName, '"\n']); +0271 end +0272 if isfield(model.annotation,'familyName') +0273 fprintf(fid, [' familyName: "', model.annotation.familyName, '"\n']); +0274 end +0275 if isfield(model.annotation,'authors') +0276 fprintf(fid, [' authors: "', model.annotation.authors, '"\n']); +0277 end +0278 if isfield(model.annotation,'email') +0279 fprintf(fid, [' email: "', model.annotation.email, '"\n']); +0280 end +0281 if isfield(model.annotation,'organization') +0282 fprintf(fid, [' organization: "', model.annotation.organization, '"\n']); +0283 end +0284 if isfield(model.annotation,'taxonomy') +0285 fprintf(fid, [' taxonomy: "', model.annotation.taxonomy, '"\n']); +0286 end +0287 if isfield(model.annotation,'note') +0288 fprintf(fid, [' note: "', model.annotation.note, '"\n']); +0289 end +0290 if isfield(model.annotation,'sourceUrl') +0291 fprintf(fid, [' sourceUrl: "', model.annotation.sourceUrl, '"\n']); +0292 end +0293 end +0294 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/changeGeneAssoc.html b/doc/legacy/core/changeGeneAssoc.html similarity index 74% rename from doc/core/changeGeneAssoc.html rename to doc/legacy/core/changeGeneAssoc.html index 7c1cb4ae..be9aeb41 100644 --- a/doc/core/changeGeneAssoc.html +++ b/doc/legacy/core/changeGeneAssoc.html @@ -8,25 +8,25 @@ - + -
    Home > core > changeGeneAssoc.m
    +
    Home > legacy > core > changeGeneAssoc.m
    - +

    changeGeneAssoc

    -

    PURPOSE ^

    +

    PURPOSE ^

    changeGeneAssoc
    -

    SYNOPSIS ^

    +

    SYNOPSIS ^

    function model = changeGeneAssoc(model,rxnID,geneAssoc,replace)
    -

    DESCRIPTION ^

    +

    DESCRIPTION ^

     changeGeneAssoc
        Changes gene association for a defined reaction
     
    @@ -45,18 +45,18 @@ 

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    +

    CROSS-REFERENCE INFORMATION ^

    This function calls: - + This function is called by: -
    +0303 +0304 function [x,y]=getBindingPos(pathway,speciesAlias,bindingSite) +0305 % getBindingPos +0306 % Calculates the position of a given binding site for a specified species +0307 % +0308 % pathway the pathway structure which should be modified +0309 % speciesAlias the alias of the species bindingSite The binding +0310 % site in Celldesigner is a string of up to +0311 % three letters that defines which of the 16 bindings +0312 % sites on each species to use. They are written as N +0313 % (north), NNW (north north west) and so on +0314 % +0315 % [x, y] The position of the binding site for the species +0316 % +0317 % Usage: [x,y]=getBindingPos(pathway,speciesAlias,bindingSite) +0318 +0319 %Find the species +0320 for i=1:length(pathway.listOfSpecies) +0321 if strcmpi(pathway.listOfSpecies(i).alias,speciesAlias) +0322 xpos=pathway.listOfSpecies(i).x; +0323 ypos=pathway.listOfSpecies(i).y; +0324 h=pathway.listOfSpecies(i).h; +0325 w=pathway.listOfSpecies(i).w; +0326 +0327 %Species marked as "PROTEIN" should be drawn as rectangles. There +0328 %is one binding site in each corner and three in between on each +0329 %side. +0330 if strcmpi(pathway.listOfSpecies(i).type,'PROTEIN') +0331 %The binding sites clockwise from the top position +0332 if strcmpi(bindingSite,'N') +0333 x=xpos+0.5*w; +0334 y=ypos; +0335 break; +0336 end +0337 if strcmpi(bindingSite,'NNE') +0338 x=xpos+0.75*w; +0339 y=ypos; +0340 break; +0341 end +0342 if strcmpi(bindingSite,'NE') +0343 x=xpos+w; +0344 y=ypos; +0345 break; +0346 end +0347 if strcmpi(bindingSite,'ENE') +0348 x=xpos+w; +0349 y=ypos+0.25*h; +0350 break; +0351 end +0352 if strcmpi(bindingSite,'E') +0353 x=xpos+w; +0354 y=ypos+0.5*h; +0355 break; +0356 end +0357 if strcmpi(bindingSite,'ESE') +0358 x=xpos+w; +0359 y=ypos+0.75*h; +0360 break; +0361 end +0362 if strcmpi(bindingSite,'SE') +0363 x=xpos+w; +0364 y=ypos+h; +0365 break; +0366 end +0367 if strcmpi(bindingSite,'SSE') +0368 x=xpos+0.75*w; +0369 y=ypos+h; +0370 break; +0371 end +0372 if strcmpi(bindingSite,'S') +0373 x=xpos+0.5*w; +0374 y=ypos+h; +0375 break; +0376 end +0377 if strcmpi(bindingSite,'SSW') +0378 x=xpos+0.25*w; +0379 y=ypos+h; +0380 break; +0381 end +0382 if strcmpi(bindingSite,'SW') +0383 x=xpos; +0384 y=ypos+h; +0385 break; +0386 end +0387 if strcmpi(bindingSite,'WSW') +0388 x=xpos; +0389 y=ypos+0.75*h; +0390 break; +0391 end +0392 if strcmpi(bindingSite,'W') +0393 x=xpos; +0394 y=ypos+0.5*h; +0395 break; +0396 end +0397 if strcmpi(bindingSite,'WNW') +0398 x=xpos; +0399 y=ypos+0.25*h; +0400 break; +0401 end +0402 if strcmpi(bindingSite,'NW') +0403 x=xpos; +0404 y=ypos; +0405 break; +0406 end +0407 if strcmpi(bindingSite,'NNW') +0408 x=xpos+0.25*w; +0409 y=ypos; +0410 break; +0411 end +0412 end +0413 +0414 %Species marked as "SIMPLE_MOLECULE" should be drawn as ellipses. +0415 %There is one binding site in each extreme point and three in +0416 %between on each side +0417 if strcmpi(pathway.listOfSpecies(i).type,'SIMPLE_MOLECULE') +0418 %Find the center of the ellipse +0419 centerX=xpos+0.5*w; +0420 centerY=ypos+0.5*h; +0421 +0422 %The binding sites clockwise from the top position +0423 if strcmpi(bindingSite,'N') +0424 angle=(4/8)*pi; +0425 end +0426 if strcmpi(bindingSite,'NNE') +0427 angle=(5/8)*pi; +0428 end +0429 if strcmpi(bindingSite,'NE') +0430 angle=(6/8)*pi; +0431 end +0432 if strcmpi(bindingSite,'ENE') +0433 angle=(7/8)*pi; +0434 end +0435 if strcmpi(bindingSite,'E') +0436 angle=(8/8)*pi; +0437 end +0438 if strcmpi(bindingSite,'ESE') +0439 angle=(9/8)*pi; +0440 end +0441 if strcmpi(bindingSite,'SE') +0442 angle=(10/8)*pi; +0443 end +0444 if strcmpi(bindingSite,'SSE') +0445 angle=(11/8)*pi; +0446 end +0447 if strcmpi(bindingSite,'S') +0448 angle=(12/8)*pi; +0449 end +0450 if strcmpi(bindingSite,'SSW') +0451 angle=(13/8)*pi; +0452 end +0453 if strcmpi(bindingSite,'SW') +0454 angle=(14/8)*pi; +0455 end +0456 if strcmpi(bindingSite,'WSW') +0457 angle=(15/8)*pi; +0458 end +0459 if strcmpi(bindingSite,'W') +0460 angle=(16/8)*pi; +0461 end +0462 if strcmpi(bindingSite,'WNW') +0463 angle=(1/8)*pi; +0464 end +0465 if strcmpi(bindingSite,'NW') +0466 angle=(2/8)*pi; +0467 end +0468 if strcmpi(bindingSite,'NNW') +0469 angle=(3/8)*pi; +0470 end +0471 x=centerX-(0.5*w)*cos(angle); +0472 y=centerY-(0.5*h)*sin(angle); +0473 break; +0474 end +0475 end +0476 end +0477 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/plotting/drawMap.html b/doc/plotting/drawMap.html index 0abf0b54..71c27a31 100644 --- a/doc/plotting/drawMap.html +++ b/doc/plotting/drawMap.html @@ -59,7 +59,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • drawPathway drawPathway
  • getObjectiveString getObjectiveString
  • plotAdditionalInfo plotAdditionalInfo
  • plotLabels plotLabels
  • setTitle plotLabels
  • This function is called by: @@ -170,7 +170,7 @@

    SOURCE CODE ^'Objective function'}]; 0102 -0103 additionalText=[additionalText;{getObjectiveString(true, objectiveNames, objectiveValues)}]; +0103 additionalText=[additionalText;{getObjectiveString(true, objectiveNames, objectiveValues)}]; 0104 additionalText=[additionalText;{''}]; 0105 additionalText=[additionalText;{'Constraints (condition A)'}]; 0106 diff --git a/doc/core/getObjectiveString.html b/doc/plotting/getObjectiveString.html similarity index 94% rename from doc/core/getObjectiveString.html rename to doc/plotting/getObjectiveString.html index 785e70c7..9f7b19ea 100644 --- a/doc/core/getObjectiveString.html +++ b/doc/plotting/getObjectiveString.html @@ -12,10 +12,10 @@ -
    Home > core > getObjectiveString.m
    +
    Home > plotting > getObjectiveString.m
    +Index for plotting >-->

    getObjectiveString

    @@ -47,7 +47,7 @@

    CROSS-REFERENCE INFORMATION ^
 </ul>
 This function is called by:
 <ul style= - +
  • drawMap drawMap
  • diff --git a/doc/plotting/index.html b/doc/plotting/index.html index c7668bc5..60a564fa 100644 --- a/doc/plotting/index.html +++ b/doc/plotting/index.html @@ -19,7 +19,7 @@

    Index for plotting

    Matlab files in this directory:

    -
     colorSubsystemModified from colorSubsystemCD as distributed through COBRA Toolbox
     drawMapdrawMap
     drawPathwaydrawPathway
     getColorCodesgetColorCodes
     plotAdditionalInfoplotAdditionalInfo
     plotLabelsplotLabels
     setColorToMapRxnsUSAGE:
     setOmicDataToRxnsUSAGE:
     setTitleplotLabels
    + colorSubsystemModified from colorSubsystemCD as distributed through COBRA Toolbox  drawMapdrawMap  drawPathwaydrawPathway  getColorCodesgetColorCodes  getObjectiveStringgetObjectiveString  plotAdditionalInfoplotAdditionalInfo  plotLabelsplotLabels  setColorToMapRxnsUSAGE:  setOmicDataToRxnsUSAGE:  setTitleplotLabels diff --git a/doc/solver/getMILPParams.html b/doc/solver/getMILPParams.html deleted file mode 100644 index 13728baa..00000000 --- a/doc/solver/getMILPParams.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - Description of getMILPParams - - - - - - - - - -
    Home > solver > getMILPParams.m
    - - - -

    getMILPParams -

    - -

    PURPOSE ^

    -
    getMILPParams
    - -

    SYNOPSIS ^

    -
    function mosekParams=getMILPParams(params)
    - -

    DESCRIPTION ^

    -
     getMILPParams
    -   Returns a MOSEK parameter structure used when solving mixed-integer
    -   linear programming problems
    -
    -    params          structure with one or more of the following fields
    -       maxTime     maximal running time in minutes (opt, default 600)
    -       relGap      maximal relative gap between integer and relaxed
    -                   solution in order to be considered optimal (0.0-1.0)
    -                   (opt, default 0.2)
    -       printReport true if the results of the optimization should be
    -                   displayed on the screen (opt, default false)
    -
    -   mosekParams     a parameter structure to be used with MOSEK
    -
    -   Usage: mosekParams=getMILPParams(params)
    - - -

    CROSS-REFERENCE INFORMATION ^

    -This function calls: - -This function is called by: - - - - - -

    SOURCE CODE ^

    -
    0001 function mosekParams=getMILPParams(params)
    -0002 % getMILPParams
    -0003 %   Returns a MOSEK parameter structure used when solving mixed-integer
    -0004 %   linear programming problems
    -0005 %
    -0006 %    params          structure with one or more of the following fields
    -0007 %       maxTime     maximal running time in minutes (opt, default 600)
    -0008 %       relGap      maximal relative gap between integer and relaxed
    -0009 %                   solution in order to be considered optimal (0.0-1.0)
    -0010 %                   (opt, default 0.2)
    -0011 %       printReport true if the results of the optimization should be
    -0012 %                   displayed on the screen (opt, default false)
    -0013 %
    -0014 %   mosekParams     a parameter structure to be used with MOSEK
    -0015 %
    -0016 %   Usage: mosekParams=getMILPParams(params)
    -0017 
    -0018 if nargin<1
    -0019     params=[];
    -0020 end
    -0021 
    -0022 mosekParams=params;
    -0023 mosekParams.MSK_DPAR_MIO_TOL_ABS_RELAX_INT=10^-12;
    -0024 mosekParams.MSK_DPAR_MIO_TOL_REL_GAP=0.05;
    -0025 
    -0026 %NOTE: These options were removed or renamed in Mosek 8. Should be
    -0027 %investigated. mosekParams.MSK_DPAR_MIO_TOL_REL_RELAX_INT=10^-9;
    -0028 %mosekParams.MSK_DPAR_MIO_TOL_X=10^-9;
    -0029 mosekParams.MSK_DPAR_MIO_TOL_FEAS=10^-12;
    -0030 mosekParams.MSK_DPAR_BASIS_TOL_S=10^-12;
    -0031 mosekParams.MSK_DPAR_BASIS_TOL_X=10^-12;
    -0032 mosekParams.MSK_DPAR_PRESOLVE_TOL_ABS_LINDEP=10^-12;
    -0033 
    -0034 %Get the mosek version. This is a bit problematic since the Mosek function
    -0035 %for getting the version came in version 7.
    -0036 if isfield(params,'presolve')
    -0037     mosekParams.MSK_DPAR_OPTIMIZER_MAX_TIME=params.presolve;
    -0038     mosekParams=rmfield(mosekParams,'presolve');
    -0039 else
    -0040     if any(strfind(evalc('mosekopt info'),'MOSEK Version 7'))
    -0041         mosekParams.MSK_IPAR_PRESOLVE_USE=1;
    -0042     else
    -0043         % NOTE: This options were removed or renamed in Mosek 8. Should be
    -0044         % investigated. mosekParams.MSK_DPAR_PRESOLVE_TOL_LIN_DEP=10^-9;
    -0045         
    -0046         %Turn off the presolve. This is because Mosek sometimes returns
    -0047         %non-feasible solutions because of problems with the presolver.
    -0048         %Should check if version is <6.0.0.147
    -0049         mosekParams.MSK_IPAR_PRESOLVE_USE=0;
    -0050     end
    -0051 end
    -0052 
    -0053 %Use a starting integer solution if supplied. This has no effect if no such
    -0054 %solution is supplied mosekParams.MSK_IPAR_MIO_CONSTRUCT_SOL=1;
    -0055 
    -0056 %10 hours as default upper time limit
    -0057 mosekParams.MSK_DPAR_OPTIMIZER_MAX_TIME=10*60*60;
    -0058 
    -0059 if isfield(params,'maxTime')
    -0060     mosekParams.MSK_DPAR_OPTIMIZER_MAX_TIME=params.maxTime*60;
    -0061     mosekParams=rmfield(mosekParams,'maxTime');
    -0062 end
    -0063 if isfield(params,'relGap')
    -0064     mosekParams.MSK_DPAR_MIO_TOL_REL_GAP=params.relGap;
    -0065     mosekParams=rmfield(mosekParams,'relGap');
    -0066 end
    -0067 if isfield(params,'printReport')
    -0068     mosekParams=rmfield(mosekParams,'printReport');
    -0069 end
    -0070 end
    -
    Generated by m2html © 2005
    - - \ No newline at end of file diff --git a/doc/solver/index.html b/doc/solver/index.html index dc27b09b..e42468a9 100644 --- a/doc/solver/index.html +++ b/doc/solver/index.html @@ -19,7 +19,7 @@

    Index for solver

    Matlab files in this directory:

    -
     checkSolutionChecks if a solution from Mosek is feasible and optimal
     getMILPParamsgetMILPParams
     optimizeProboptimizeProb
     qMOMAqMOMA
     setRavenSolversetRavenSolver
     solveLPsolveLP
     solveQPsolveQP
    + checkSolutionChecks if a solution from Mosek is feasible and optimal  optimizeProboptimizeProb  qMOMAqMOMA  setRavenSolversetRavenSolver  solveLPsolveLP  solveQPsolveQP diff --git a/doc/solver/optimizeProb.html b/doc/solver/optimizeProb.html index 39a056b6..946c06ff 100644 --- a/doc/solver/optimizeProb.html +++ b/doc/solver/optimizeProb.html @@ -48,7 +48,7 @@

    CROSS-REFERENCE INFORMATION ^
 
 <h2><a name=SUBFUNCTIONS ^

    +
  • function s_merged=structUpdate(s_old,s_new)
  • function paramlist = renameparams(paramlist,old,new)
  • SOURCE CODE ^

    0001 function res = optimizeProb(prob,params)
    @@ -64,49 +64,154 @@ 

    SOURCE CODE ^if nargin<2 || isempty(params) 0012 params=struct(); 0013 end -0014 -0015 if(~ispref('RAVEN','solver')) -0016 dispEM('RAVEN solver not defined or unknown. Try using setRavenSolver(''solver'').'); -0017 end -0018 -0019 milp=false; -0020 if isfield(prob,'vartype') && ~all(lower(prob.vartype) == 'c') -0021 disp('MILP detected.'); -0022 milp=true; -0023 end -0024 -0025 solver=getpref('RAVEN','solver'); -0026 if strcmp(solver,'gurobi') -0027 if isfield(params,'relGap'), params=rmfield(params,'relGap'); end -0028 gparams=struct('Presolve',2,'TimeLimit',1000,'OutputFlag',1,'MIPGap',1e-12,'Seed',0,'FeasibilityTol',1e-9,'OptimalityTol',1e-9); -0029 gparams=structUpdate(gparams,params); -0030 if (~milp), gparams.OutputFlag=0; end -0031 res = gurobi(cobraToGurobiProb(prob),gparams); -0032 res = gurobiToCobraRes(res, milp); -0033 elseif strcmp(solver,'cobra') -0034 if (milp) -0035 cparams=struct('timeLimit',1e9,'printLevel',0,'intTol',1e-6,'relMipGapTol',1e-9); -0036 cparams=structUpdate(cparams,params); -0037 res=solveCobraMILP(prob,cparams); -0038 else -0039 res=solveCobraLP(prob); -0040 end -0041 else -0042 dispEM('RAVEN solver not defined or unknown. Try using setRavenSolver(''solver'').'); -0043 end -0044 if res.stat>0 -0045 res.full=res.full(1:size(prob.a,2)); -0046 end -0047 end -0048 -0049 function s_merged=structUpdate(s_old,s_new) -0050 %Remove overlapping fields from first struct; -0051 %Obtain all unique names of remaining fields; -0052 %Merge both structs -0053 s_merged = rmfield(s_old, intersect(fieldnames(s_old), fieldnames(s_new))); -0054 names = [fieldnames(s_merged); fieldnames(s_new)]; -0055 s_merged = cell2struct([struct2cell(s_merged); struct2cell(s_new)], names, 1); -0056 end

    +0014 if(~ispref('RAVEN','solver')) +0015 dispEM('RAVEN solver not defined or unknown. Try using setRavenSolver(''solver'').'); +0016 end +0017 if ~all(lower(prob.vartype) == 'c') +0018 disp('MILP detected.'); +0019 milp=true; +0020 else +0021 milp=false; +0022 end +0023 +0024 %% Define default parameters, which will then be used to make solver- +0025 % specific solverparams structures +0026 defaultparams.feasTol = 1e-9; +0027 defaultparams.optTol = 1e-9; +0028 defaultparams.objTol = 1e-9; +0029 defaultparams.timeLimit = 1000; +0030 %defaultparams.iterationLimit = 1000; +0031 defaultparams.intTol = 1e-12; +0032 defaultparams.relMipGapTol = 1e-12; +0033 defaultparams.absMipGapTol = 1e-12; +0034 +0035 solver=getpref('RAVEN','solver'); +0036 +0037 switch solver +0038 %% Use whatever solver is set by COBRA Toolbox changeCobraSolver +0039 case 'cobra' +0040 if milp +0041 cparams=struct('timeLimit',1e9,'printLevel',0,'intTol',1e-6,'relMipGapTol',1e-9); +0042 cparams=structUpdate(cparams,params); +0043 res=solveCobraMILP(prob,cparams); +0044 else +0045 res=solveCobraLP(prob); +0046 end +0047 +0048 %% Use Gurobi in a MATLAB environment +0049 case 'gurobi' +0050 if milp +0051 solverparams.OutputFlag = 1; +0052 else +0053 solverparams.OutputFlag = 0; +0054 end +0055 solverparams.DisplayInterval= 1; % Level of verbosity +0056 solverparams.TimeLimit = defaultparams.timeLimit; +0057 solverparams.FeasibilityTol = defaultparams.feasTol; +0058 solverparams.OptimalityTol = defaultparams.optTol; +0059 solverparams.Presolve = 2; +0060 solverparams = structUpdate(solverparams,params); +0061 +0062 % Restructering problem according to gurobi format +0063 prob.csense = renameparams(prob.csense, {'L','G','E'}, {'<','>','='}); +0064 prob.osense = renameparams(num2str(prob.osense), {'1','-1'}, {'min','max'}); +0065 +0066 [prob.obj, prob.rhs, prob.sense, prob.modelsense] = deal(prob.c, prob.b, prob.csense, prob.osense); +0067 prob = rmfield(prob, {'c','b','csense','osense'}); +0068 +0069 resG = gurobi(prob,solverparams); +0070 +0071 try +0072 [res.full, res.obj, res.origStat] = deal(resG.x, resG.objval, resG.status); +0073 if milp && strcmp(resG.status, 'TIME_LIMIT') +0074 % If res has the objval field, it succeeded, regardless of +0075 % time_limit status +0076 resG.status = 'OPTIMAL'; +0077 end +0078 switch resG.status +0079 case 'OPTIMAL' +0080 res.stat = 1; +0081 case 'UNBOUNDED' +0082 res.stat = 2; +0083 otherwise +0084 res.stat = 0; +0085 end +0086 if ~milp +0087 [res.vbasis, res.cbasis] = deal(resG.vbasis, resG.cbasis); +0088 end +0089 catch +0090 res.stat = 0; +0091 res.origStat = resG.status; % useful information to have +0092 end +0093 %% Use GLPK using RAVEN-provided binary +0094 case 'glpk' +0095 solverparams.scale = 128; % Auto scaling +0096 solverparams.tmlim = defaultparams.timeLimit; +0097 solverparams.tolbnd = defaultparams.feasTol; +0098 solverparams.toldj = defaultparams.optTol; +0099 solverparams.tolint = defaultparams.intTol; +0100 solverparams.tolobj = defaultparams.objTol; +0101 solverparams.msglev = 0; % Level of verbosity +0102 solverparams = structUpdate(solverparams,params); +0103 +0104 prob.csense = renameparams(prob.csense, {'L','G','E'}, {'U','L','S'}); +0105 +0106 if milp +0107 solverparams.tmlim = solverparams.tmlim*10; +0108 solverparams.msglev = 1; % Level of verbosity +0109 disp('Issues have been observed when using GLPK for MILP solving. Be advised to carefully observe the results, or us another solver.') +0110 end +0111 solverparams.scale = 1; % Auto scaling +0112 +0113 % Ensure that RAVEN glpk binary is used, return to original +0114 % directory afterwards +0115 [ravenDir,currDir]=findRAVENroot(); +0116 cd(fullfile(ravenDir,'software','GLPKmex')) +0117 [xopt, fmin, errnum, extra] = glpk(prob.c, prob.A, prob.b, prob.lb, prob.ub, prob.csense, prob.vartype, prob.osense, solverparams); +0118 cd(currDir) +0119 +0120 switch errnum % 1 = undefined; 2 = feasible; 3 = infeasible; 4 = no feasible solution; 5 = optimal; 6 = no unbounded solution +0121 case 5 +0122 res.stat = 1; % Optimal +0123 case 2 +0124 res.stat = 2; % Feasible, but not optimal +0125 otherwise +0126 res.stat = 0; +0127 end +0128 res.origStat = errnum; +0129 res.full = xopt; +0130 res.obj = fmin; +0131 otherwise +0132 error('RAVEN solver not defined or unknown. Try using setRavenSolver(''solver'').'); +0133 end +0134 if res.stat>0 +0135 res.full=res.full(1:size(prob.a,2)); +0136 end +0137 end +0138 +0139 function s_merged=structUpdate(s_old,s_new) +0140 %Remove overlapping fields from first struct; +0141 %Obtain all unique names of remaining fields; +0142 %Merge both structs +0143 s_merged = rmfield(s_old, intersect(fieldnames(s_old), fieldnames(s_new))); +0144 names = [fieldnames(s_merged); fieldnames(s_new)]; +0145 s_merged = cell2struct([struct2cell(s_merged); struct2cell(s_new)], names, 1); +0146 end +0147 +0148 function paramlist = renameparams(paramlist,old,new) +0149 if ~iscell(paramlist) +0150 wasNoCell = true; +0151 paramlist={paramlist}; +0152 else +0153 wasNoCell = false; +0154 end +0155 for i=1:numel(old) +0156 paramlist = regexprep(paramlist,old{i},new{i}); +0157 end +0158 if wasNoCell +0159 paramlist=paramlist{1}; +0160 end +0161 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/solver/setRavenSolver.html b/doc/solver/setRavenSolver.html index abdaf0a1..62dc4257 100644 --- a/doc/solver/setRavenSolver.html +++ b/doc/solver/setRavenSolver.html @@ -31,11 +31,12 @@

    DESCRIPTION ^SOURCE CODE ^% Sets the solver for RAVEN and optionally saves a default value 0004 % to MATLAB startup. 0005 % -0006 % solver the name of the solver. The following options are available: -0007 % -gurobi (all versions) -0008 % -cobra. If this option is set, then RAVEN uses the current -0009 % COBRA solver. Make sure that the one is set using -0010 % changeCobraSolver -0011 % -0012 % Usage: setRavenSolver(solver) -0013 -0014 if (~ischar(solver)) dispEM('Input should be a string.'); end -0015 -0016 if strcmpi(solver,'gurobi') || strcmpi(solver,'cobra') || strcmpi(solver,'none') -0017 setpref('RAVEN','solver',solver) -0018 elseif strcmpi(solver,'mosek') -0019 error('MOSEK is no longer supported from RAVEN 2.3.0. Choose ''gurobi'' or ''cobra''.') -0020 else -0021 EM='Such solver is not compatible with RAVEN. Available options are ''gurobi'' and ''cobra'''; -0022 dispEM(EM); -0023 end +0006 % solver string with solver name. The following options are available: +0007 % glpk uses RAVEN-provided binaries +0008 % gurobi requires a working Gurobi installation +0009 % cobra requires a working COBRA Toolbox installation. RAVEN +0010 % parses the problem to COBRA and uses the solver that is +0011 % set by changeCobraSolver. +0012 % +0013 % Usage: setRavenSolver(solver) +0014 solver=char(solver); +0015 switch solver +0016 case 'cobra' +0017 global CBT_LP_SOLVER; +0018 if isempty(CBT_LP_SOLVER) +0019 error('COBRA toolbox is not initialized, run ''initCobraToolbox()''') +0020 else +0021 setpref('RAVEN','solver','cobra'); +0022 end +0023 case 'mosek' +0024 error('MOSEK support has been discontinued since RAVEN 2.3.0.') +0025 case {'glpk','gurobi'} +0026 setpref('RAVEN','solver',solver) +0027 otherwise +0028 error('Invalid solver defined') +0029 end +0030 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/solver/solveLP.html b/doc/solver/solveLP.html index c5e67af8..f3aee940 100644 --- a/doc/solver/solveLP.html +++ b/doc/solver/solveLP.html @@ -136,15 +136,15 @@

    SOURCE CODE ^end 0059 end 0060 -0061 % Setup the problem to feed to COBRA. -0062 prob=[]; -0063 prob.c=[model.c*-1;zeros(size(model.S,1),1)]; -0064 prob.b = zeros(size(model.S,1), 1); -0065 prob.lb = [model.lb; model.b(:,1)]; -0066 prob.ub = [model.ub; model.b(:,min(size(model.b,2),2))]; -0067 prob.osense = 1; -0068 prob.csense = char(zeros(size(model.S,1),1)); -0069 prob.csense(:) = 'E'; +0061 % Setup the linear problem for glpk +0062 prob = []; +0063 prob.c = [model.c*-1;zeros(size(model.S,1),1)]; +0064 prob.b = zeros(size(model.S,1), 1); +0065 prob.lb = [model.lb; model.b(:,1)]; +0066 prob.ub = [model.ub; model.b(:,min(size(model.b,2),2))]; +0067 prob.csense = repmat('E', 1, length(prob.b)); % Equality constraints +0068 prob.osense = 1; +0069 prob.vartype = repmat('C', 1, length(prob.c)); % Fluxes are continuous values 0070 prob.A = [model.S -speye(size(model.S,1))]; 0071 prob.a = model.S; 0072 @@ -253,42 +253,24 @@

    SOURCE CODE ^end -0178 %The square of fluxes should be minimized. This only works when -0179 %there is no interval on the mass balance constraints (model.b is a -0180 %vector) -0181 case 2 -0182 % if size(model.b,2)==1 -0183 % qsol=solveQP(model,model.rxns,zeros(numel(model.lb),1)); -0184 % %There is a problem that the solver seldom converges totally in this -0185 % %kind of minimization. Print a warning but use the fluxes -0186 % if any(qsol.x) -0187 % solution.x=qsol.x; -0188 % if qsol.stat==-1 -0189 % fprintf('WARNING: The quadratic fitting did not converge\n'); -0190 % end -0191 % else -0192 % fprintf('WARNING: Could not solve the problem of minimizing the square of fluxes. Uses output from linear program\n'); -0193 % end -0194 % else -0195 % fprintf('WARNING: Cannot minimize square of fluxes when size(model.b,2)==2. Uses output from linear program\n'); -0196 % end -0197 EM='Quadratic solver currently not working. Uses output from original problem'; -0198 dispEM(EM,false); -0199 solution.stat=-2; -0200 %The number of fluxes should be minimized -0201 case 3 -0202 [qx,I]=getMinNrFluxes(model,model.rxns,params); -0203 qx(~I)=0; -0204 if any(I) -0205 solution.x=qx; -0206 else -0207 EM='Could not solve the problem of minimizing the number of fluxes. Uses output from linear program'; -0208 dispEM(EM,false); -0209 solution.stat=-2; -0210 end -0211 end -0212 end -0213 end +0178 +0179 case 2 +0180 error('%Minimization of square of fluxes is deprecated') +0181 +0182 %The number of fluxes should be minimized +0183 case 3 +0184 [qx,I]=getMinNrFluxes(model,model.rxns,params); +0185 qx(~I)=0; +0186 if any(I) +0187 solution.x=qx; +0188 else +0189 EM='Could not solve the problem of minimizing the number of fluxes. Uses output from linear program'; +0190 dispEM(EM,false); +0191 solution.stat=-2; +0192 end +0193 end +0194 end +0195 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/solver/solveQP.html b/doc/solver/solveQP.html index 229ad8a3..96428873 100644 --- a/doc/solver/solveQP.html +++ b/doc/solver/solveQP.html @@ -78,49 +78,50 @@

    SOURCE CODE ^% stat Exit flag 0018 % 0019 % Usage: solution=solveQP(model,rxns,values,maxIter, restartIter) -0020 -0021 if nargin<4 -0022 maxIter=1000; -0023 end -0024 -0025 if nargin<5 -0026 restartIter=1; -0027 end -0028 -0029 %Check that it's feasible -0030 solution=solveLP(model); -0031 if isempty(solution.x) -0032 return; -0033 end -0034 -0035 %Get the indexes of the fluxes to fit -0036 allIndexes=getIndexes(model,rxns,'rxns'); -0037 -0038 f=zeros(numel(model.rxns),1); -0039 H=zeros(numel(model.rxns)); -0040 -0041 %Get the fitIndexes for the experiment -0042 for j=1:numel(allIndexes) %Not that neat -0043 H(allIndexes(j),allIndexes(j))=2; -0044 end -0045 -0046 f(allIndexes)=values.*-2; -0047 -0048 %For a badly formulated problem it can occur that the solver stalls. This -0049 %can sometimes be fixed by trying to solve the problem again -0050 options=optimset('MaxIter',maxIter); -0051 for j=1:restartIter -0052 [x,fval,flag] = ... -0053 quadprog(H,f,[],[],model.S,model.b,model.lb,model.ub,[],options); -0054 if flag>0 -0055 break; -0056 end -0057 end -0058 -0059 solution.f=fval; -0060 solution.x=x; -0061 solution.stat=flag; -0062 end +0020 rxns=char(rxns); +0021 +0022 if nargin<4 +0023 maxIter=1000; +0024 end +0025 +0026 if nargin<5 +0027 restartIter=1; +0028 end +0029 +0030 %Check that it's feasible +0031 solution=solveLP(model); +0032 if isempty(solution.x) +0033 return; +0034 end +0035 +0036 %Get the indexes of the fluxes to fit +0037 allIndexes=getIndexes(model,rxns,'rxns'); +0038 +0039 f=zeros(numel(model.rxns),1); +0040 H=zeros(numel(model.rxns)); +0041 +0042 %Get the fitIndexes for the experiment +0043 for j=1:numel(allIndexes) %Not that neat +0044 H(allIndexes(j),allIndexes(j))=2; +0045 end +0046 +0047 f(allIndexes)=values.*-2; +0048 +0049 %For a badly formulated problem it can occur that the solver stalls. This +0050 %can sometimes be fixed by trying to solve the problem again +0051 options=optimset('MaxIter',maxIter); +0052 for j=1:restartIter +0053 [x,fval,flag] = ... +0054 quadprog(H,f,[],[],model.S,model.b,model.lb,model.ub,[],options); +0055 if flag>0 +0056 break; +0057 end +0058 end +0059 +0060 solution.f=fval; +0061 solution.x=x; +0062 solution.stat=flag; +0063 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/struct_conversion/cobraToGurobiProb.html b/doc/struct_conversion/cobraToGurobiProb.html deleted file mode 100644 index 75d4cba4..00000000 --- a/doc/struct_conversion/cobraToGurobiProb.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - Description of cobraToGurobiProb - - - - - - - - - -
    Home > struct_conversion > cobraToGurobiProb.m
    - - - -

    cobraToGurobiProb -

    - -

    PURPOSE ^

    -
    - -

    SYNOPSIS ^

    -
    function gprob = cobraToGurobiProb(prob)
    - -

    DESCRIPTION ^

    -
    - - -

    CROSS-REFERENCE INFORMATION ^

    -This function calls: - -This function is called by: - - - - - -

    SOURCE CODE ^

    -
    0001 function gprob = cobraToGurobiProb(prob)
    -0002 
    -0003 gprob.obj = prob.c;
    -0004 gprob.rhs = prob.b;
    -0005 gprob.lb = prob.lb;
    -0006 gprob.ub = prob.ub;
    -0007 gprob.A = prob.A;
    -0008 gprob.sense = '=';
    -0009 gprob.modelsense = 'min';
    -0010 
    -0011 % the binary type variables must be defined for milp
    -0012 % use this more complicated approach to ignore "vartype" capitalization
    -0013 f = fieldnames(prob);
    -0014 [~,vartype_index] = ismember('vartype', lower(f));
    -0015 if vartype_index > 0
    -0016     gprob.vtype = prob.(f{vartype_index});
    -0017 else
    -0018     gprob.vtype = repmat('C', 1, size(prob.A, 2));
    -0019 end
    -0020 
    -0021 if isfield(prob,'basis') && ~isempty(prob.basis)
    -0022     gprob.cbasis=prob.basis.cbasis;
    -0023     gprob.vbasis=prob.basis.vbasis;
    -0024 end
    -0025 end
    -
    Generated by m2html © 2005
    - - \ No newline at end of file diff --git a/doc/struct_conversion/cobraToMosekRes.html b/doc/struct_conversion/cobraToMosekRes.html deleted file mode 100644 index 7d6e231b..00000000 --- a/doc/struct_conversion/cobraToMosekRes.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - Description of cobraToMosekRes - - - - - - - - - -
    Home > struct_conversion > cobraToMosekRes.m
    - - - -

    cobraToMosekRes -

    - -

    PURPOSE ^

    -
    build solution
    - -

    SYNOPSIS ^

    -
    function res = cobraToMosekRes(res,keep,milp)
    - -

    DESCRIPTION ^

    -
     build solution
    - - -

    CROSS-REFERENCE INFORMATION ^

    -This function calls: - -This function is called by: - - - - - -

    SOURCE CODE ^

    -
    0001 function res = cobraToMosekRes(res,keep,milp)
    -0002 
    -0003 % build solution
    -0004 if(res.time>=1e9)
    -0005     res.rcode='MSK_RES_TRM_MAX_TIME';
    -0006 else
    -0007     res.rcode='crap';
    -0008 end
    -0009 
    -0010 if(milp)
    -0011     res.sol.int.solsta=res.stat;
    -0012     res.sol.int.prosta=res.stat;
    -0013     if(res.stat~=0)
    -0014         res.sol.int.xx=res.full(1:keep);
    -0015         %res.sol.int.xx=res.int;
    -0016         res.sol.int.pobjval=res.obj;
    -0017         res.sol.pobjval=res.obj;
    -0018     end
    -0019 else
    -0020     res.sol.bas.solsta='FEASIBLE';
    -0021     res.sol.bas.prosta='OPTIMAL';
    -0022     if res.stat==0
    -0023         res.sol.bas.solsta='INFEASIBLE';
    -0024         res.sol.bas.prosta='INFEASIBLE';
    -0025     elseif res.stat==2
    -0026         res.sol.bas.prosta='UNBOUND';
    -0027     end
    -0028     if(res.stat~=0)
    -0029         res.sol.bas.xx=res.full(1:keep);
    -0030         res.sol.bas.pobjval=res.obj;
    -0031         res.sol.pobjval=res.obj;
    -0032         res.x=res.full(1:keep);
    -0033     end
    -0034 end
    -0035 end
    -
    Generated by m2html © 2005
    - - \ No newline at end of file diff --git a/doc/struct_conversion/editMiriam.html b/doc/struct_conversion/editMiriam.html index 257ddc31..d4d88a55 100644 --- a/doc/struct_conversion/editMiriam.html +++ b/doc/struct_conversion/editMiriam.html @@ -114,90 +114,87 @@

    SOURCE CODE ^% model model structure with updated MIRIAM annotation field 0036 % 0037 % Usage: model=editMiriam(model,type,object,miriamName,miriams,keep) -0038 -0039 %Check 'keep' input -0040 if ~any(strcmp(keep,{'replace','fill','add'})) -0041 error('Invalid ''keep'', should be ''replace'',''fill'',''add''.') -0042 end -0043 %Check 'type' input -0044 if ~any(strcmp(type,{'met','gene','rxn','comp'})) -0045 error('Invalid ''type'', should be ''met'', ''gene'', ''rxn'' or ''comp''.') -0046 end -0047 %Check 'object' input -0048 if islogical(object) -0049 idxInModel=find(object); -0050 elseif isnumeric(object) -0051 idxInModel=object; -0052 elseif ischar(object) -0053 if strcmp(object,'all') -0054 idxInModel=1:numel(model.([type,'s'])); -0055 else -0056 idxInModel=getIndexes(model,object,[type,'s']); -0057 if ~all(idxInModel) -0058 dispEM('The following objects cannot be found in the model: ',true,object(~idxInModel)) -0059 end -0060 end -0061 else -0062 [~,idxInModel]=ismember(object,model.([type,'s'])); -0063 if ~all(idxInModel) -0064 dispEM('The following objects cannot be found in the model: ',true,object(~idxInModel)) +0038 miriamName=char(miriamName); +0039 miriams=convertCharArray(miriams); +0040 +0041 %Check 'keep' input +0042 keep=char(keep); +0043 if ~any(strcmp(keep,{'replace','fill','add'})) +0044 error('Invalid ''keep'', should be ''replace'',''fill'',''add''.') +0045 end +0046 %Check 'type' input +0047 type=char(type); +0048 if ~any(strcmp(type,{'met','gene','rxn','comp'})) +0049 error('Invalid ''type'', should be ''met'', ''gene'', ''rxn'' or ''comp''.') +0050 end +0051 %Check 'object' input +0052 if islogical(object) +0053 idxInModel=find(object); +0054 elseif isnumeric(object) +0055 idxInModel=object; +0056 else +0057 object=convertCharArray(object); +0058 if numel(object)==1 && strcmp(object{1},'all') +0059 idxInModel=1:numel(model.([type,'s'])); +0060 else +0061 idxInModel=getIndexes(model,object,[type,'s']); +0062 if ~all(idxInModel) +0063 dispEM('The following objects cannot be found in the model: ',true,object(~idxInModel)) +0064 end 0065 end 0066 end 0067 %Check 'miriams' input -0068 if ischar(miriams) -0069 miriams={miriams}; -0070 end -0071 if numel(miriams)==1 && numel(idxInModel)~=1 -0072 miriams=repmat(miriams,numel(idxInModel),1); -0073 elseif numel(miriams)~=numel(idxInModel) -0074 error('The number of annotations does not match the number of objects.') -0075 end -0076 -0077 miriamFieldName=[type,'Miriams']; -0078 -0079 if isfield(model,miriamFieldName) -0080 [extractedMiriams,extractedMiriamNames]=extractMiriam(model.(miriamFieldName)(idxInModel),'all'); -0081 else -0082 extractedMiriams=cell(numel(idxInModel),1); -0083 extractedMiriamNames={miriamName}; -0084 end -0085 -0086 [~, midx]=ismember(miriamName,extractedMiriamNames); -0087 if midx==0 -0088 midx=numel(extractedMiriamNames)+1; -0089 extractedMiriamNames(end+1)={miriamName}; -0090 extractedMiriams(:,end+1)=miriams; -0091 elseif strcmp(keep,'replace') -0092 extractedMiriams(:,midx)=miriams; -0093 else -0094 noMiriam=cellfun(@isempty,extractedMiriams(:,midx)); -0095 extractedMiriams(noMiriam,midx)=miriams(noMiriam); -0096 if strcmp(keep,'add') % Skipped when only filling empty entries -0097 existingMiriams=[split(extractedMiriams(~noMiriam,midx),'; '), miriams(~noMiriam)]; -0098 uniqueMiriams=cell(size(existingMiriams,1),1); -0099 for i=1:size(existingMiriams,1) -0100 uniqueMiriams{i,1}=strjoin(unique(existingMiriams(i,:)), {'; '}); -0101 end -0102 extractedMiriams(~noMiriam,midx)=uniqueMiriams; -0103 end -0104 end -0105 -0106 % Make Miriam field again -0107 for i=1:numel(idxInModel) -0108 miriam.name=cell(1,1); -0109 miriam.value=cell(1,1); -0110 for j=1:numel(extractedMiriamNames) -0111 if ~isempty(extractedMiriams{i,j}) -0112 values=strsplit(extractedMiriams{i,j},'; '); -0113 miriam.name(end+1:end+numel(values),1)=extractedMiriamNames(j); -0114 miriam.value(end+1:end+numel(values),1)=values; -0115 end -0116 end -0117 miriam.name(1)=[]; -0118 miriam.value(1)=[]; -0119 model.(miriamFieldName){idxInModel(i),1}=miriam; -0120 end -0121 end +0068 if numel(miriams)==1 && numel(idxInModel)~=1 +0069 miriams=repmat(miriams,numel(idxInModel),1); +0070 elseif numel(miriams)~=numel(idxInModel) +0071 error('The number of annotations does not match the number of objects.') +0072 end +0073 +0074 miriamFieldName=[type,'Miriams']; +0075 +0076 if isfield(model,miriamFieldName) +0077 [extractedMiriams,extractedMiriamNames]=extractMiriam(model.(miriamFieldName)(idxInModel),'all'); +0078 else +0079 extractedMiriams=cell(numel(idxInModel),1); +0080 extractedMiriamNames={miriamName}; +0081 end +0082 +0083 [~, midx]=ismember(miriamName,extractedMiriamNames); +0084 if midx==0 +0085 midx=numel(extractedMiriamNames)+1; +0086 extractedMiriamNames(end+1)={miriamName}; +0087 extractedMiriams(:,end+1)=miriams; +0088 elseif strcmp(keep,'replace') +0089 extractedMiriams(:,midx)=miriams; +0090 else +0091 noMiriam=cellfun(@isempty,extractedMiriams(:,midx)); +0092 extractedMiriams(noMiriam,midx)=miriams(noMiriam); +0093 if strcmp(keep,'add') % Skipped when only filling empty entries +0094 existingMiriams=[split(extractedMiriams(~noMiriam,midx),'; '), miriams(~noMiriam)]; +0095 uniqueMiriams=cell(size(existingMiriams,1),1); +0096 for i=1:size(existingMiriams,1) +0097 uniqueMiriams{i,1}=strjoin(unique(existingMiriams(i,:)), {'; '}); +0098 end +0099 extractedMiriams(~noMiriam,midx)=uniqueMiriams; +0100 end +0101 end +0102 +0103 % Make Miriam field again +0104 for i=1:numel(idxInModel) +0105 miriam.name=cell(1,1); +0106 miriam.value=cell(1,1); +0107 for j=1:numel(extractedMiriamNames) +0108 if ~isempty(extractedMiriams{i,j}) +0109 values=strsplit(extractedMiriams{i,j},'; '); +0110 miriam.name(end+1:end+numel(values),1)=extractedMiriamNames(j); +0111 miriam.value(end+1:end+numel(values),1)=values; +0112 end +0113 end +0114 miriam.name(1)=[]; +0115 miriam.value(1)=[]; +0116 model.(miriamFieldName){idxInModel(i),1}=miriam; +0117 end +0118 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/struct_conversion/extractMiriam.html b/doc/struct_conversion/extractMiriam.html index dba14a6c..925afcc0 100644 --- a/doc/struct_conversion/extractMiriam.html +++ b/doc/struct_conversion/extractMiriam.html @@ -52,7 +52,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    @@ -95,66 +95,62 @@

    SOURCE CODE ^% unique miriam names per entity 0025 % extractedMiriamNames cell array with extracted miriam names 0026 % -0027 % Usage: miriam=extractMiriam(modelMiriams,miriamName,addNull) +0027 % Usage: miriam=extractMiriam(modelMiriams,miriamName) 0028 0029 if nargin<2 || strcmp(miriamNames,'all') 0030 extractAllTypes=true; 0031 else 0032 extractAllTypes=false; -0033 end -0034 -0035 %The annotation for all miriam names should be extracted -0036 if extractAllTypes -0037 miriamNames=''; -0038 for i=1:numel(modelMiriams) -0039 if ~isempty(modelMiriams{i,1}) -0040 for j=1:numel(modelMiriams{i,1}.name) -0041 miriamNames{numel(miriamNames)+1,1}=modelMiriams{i,1}.name{j}; -0042 end -0043 end -0044 end -0045 miriamNames=sort(unique(miriamNames)); -0046 end -0047 -0048 %Ensure that the list of miriam names is in appropriate structure -0049 if ischar(miriamNames) -0050 miriamNames={miriamNames}; -0051 end -0052 -0053 %Aggregate the final cell array table with extracted miriam information -0054 miriams=''; -0055 for i=1:numel(miriamNames) -0056 miriams=[miriams, extractMiriamType(modelMiriams,miriamNames{i})]; -0057 end -0058 extractedMiriamNames=miriamNames; -0059 -0060 end -0061 -0062 function miriams=extractMiriamType(modelMiriams,miriamName) -0063 %Create an empty cell array for ids vector -0064 tempMiriams = cell([size(modelMiriams,1) 1]); -0065 %Firstly obtain the list of relevant miriam ids. Several entries may have -0066 %several miriam ids, such ids are kept in additional columns -0067 for i=1:numel(modelMiriams) -0068 if (~isempty(modelMiriams{i,1})) && any(strcmp(modelMiriams{i,1}.name,miriamName)) -0069 for j=1:numel(modelMiriams{i,1}.name) -0070 if strcmp(modelMiriams{i,1}.name(j),miriamName) -0071 tempMiriams(i,j) = modelMiriams{i,1}.value(j); -0072 end -0073 end -0074 else -0075 modelMiriams{i,1} = ''; -0076 end -0077 end -0078 -0079 %Concatenate multiple ids per miriam name in one column with semicolon as -0080 %separator -0081 miriams = cell([size(tempMiriams,1) 1]); -0082 notEmpty=~cellfun(@isempty,tempMiriams); -0083 for i=1:size(miriams) -0084 miriams{i}=strjoin(tempMiriams(i,notEmpty(i,:)),{'; '}); -0085 end -0086 end +0033 miriamNames=convertCharArray(miriamNames); +0034 end +0035 +0036 %The annotation for all miriam names should be extracted +0037 if extractAllTypes +0038 miriamNames={''}; +0039 for i=1:numel(modelMiriams) +0040 if ~isempty(modelMiriams{i,1}) +0041 for j=1:numel(modelMiriams{i,1}.name) +0042 miriamNames{numel(miriamNames)+1,1}=modelMiriams{i,1}.name{j}; +0043 end +0044 end +0045 end +0046 miriamNames=sort(unique(miriamNames)); +0047 end +0048 +0049 %Aggregate the final cell array table with extracted miriam information +0050 miriams=cell(numel(modelMiriams),0); +0051 for i=1:numel(miriamNames) +0052 miriams=[miriams, extractMiriamType(modelMiriams,miriamNames{i})]; +0053 end +0054 extractedMiriamNames=miriamNames; +0055 +0056 end +0057 +0058 function miriams=extractMiriamType(modelMiriams,miriamName) +0059 %Create an empty cell array for ids vector +0060 tempMiriams = cell([size(modelMiriams,1) 1]); +0061 %Firstly obtain the list of relevant miriam ids. Several entries may have +0062 %several miriam ids, such ids are kept in additional columns +0063 for i=1:numel(modelMiriams) +0064 if (~isempty(modelMiriams{i,1})) && any(strcmp(modelMiriams{i,1}.name,miriamName)) +0065 for j=1:numel(modelMiriams{i,1}.name) +0066 if strcmp(modelMiriams{i,1}.name(j),miriamName) +0067 tempMiriams(i,j) = modelMiriams{i,1}.value(j); +0068 end +0069 end +0070 else +0071 modelMiriams{i,1} = ''; +0072 end +0073 end +0074 +0075 %Concatenate multiple ids per miriam name in one column with semicolon as +0076 %separator +0077 miriams = cell([size(tempMiriams,1) 1]); +0078 notEmpty=~cellfun(@isempty,tempMiriams); +0079 for i=1:size(miriams) +0080 miriams{i}=strjoin(tempMiriams(i,notEmpty(i,:)),{'; '}); +0081 end +0082 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/struct_conversion/gurobiToCobraRes.html b/doc/struct_conversion/gurobiToCobraRes.html deleted file mode 100644 index d93c4cdb..00000000 --- a/doc/struct_conversion/gurobiToCobraRes.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - Description of gurobiToCobraRes - - - - - - - - - -
    Home > struct_conversion > gurobiToCobraRes.m
    - - - -

    gurobiToCobraRes -

    - -

    PURPOSE ^

    -
    - -

    SYNOPSIS ^

    -
    function res = gurobiToCobraRes(res, milp)
    - -

    DESCRIPTION ^

    -
    - - -

    CROSS-REFERENCE INFORMATION ^

    -This function calls: - -This function is called by: - - - - - -

    SOURCE CODE ^

    -
    0001 function res = gurobiToCobraRes(res, milp)
    -0002 
    -0003 if nargin < 2
    -0004     milp = false;
    -0005 end
    -0006 
    -0007 try
    -0008     resCb.full = res.x;
    -0009     resCb.obj  = res.objval;
    -0010     resCb.time = res.runtime;
    -0011     resCb.origStat = res.status;
    -0012     if milp && strcmp(res.status, 'TIME_LIMIT')
    -0013         % if the milp res structure has the "objval" field, it succeeded
    -0014         res.status = 'OPTIMAL';
    -0015     end 
    -0016     switch res.status
    -0017         case 'OPTIMAL'
    -0018             resCb.stat = 1;
    -0019         case 'INFEASIBLE'
    -0020             resCb.stat = 0;
    -0021         case 'UNBOUNDED'
    -0022             resCb.stat = 2;
    -0023         case 'INF_OR_UNBD'
    -0024             resCb.stat = 0;
    -0025         otherwise
    -0026             resCb.stat = -1; % Solution not optimal or solver problem
    -0027     end
    -0028     if ~milp
    -0029         resCb.basis.vbasis=res.vbasis;
    -0030         resCb.basis.cbasis=res.cbasis;
    -0031     end
    -0032 catch
    -0033     resCb.stat = 0;
    -0034     if isfield(res, 'status')
    -0035         resCb.origStat = res.status;  % useful information to have
    -0036     end
    -0037 end
    -0038 res=resCb;
    -0039 end
    -
    Generated by m2html © 2005
    - - \ No newline at end of file diff --git a/doc/struct_conversion/index.html b/doc/struct_conversion/index.html index a825ad65..e8c1ba9c 100644 --- a/doc/struct_conversion/index.html +++ b/doc/struct_conversion/index.html @@ -19,7 +19,7 @@

    Index for struct_conversion

    Matlab files in this directory:

    -
     cobraToGurobiProb
     cobraToMosekResbuild solution
     editMiriameditMiriam
     extractMiriamextractMiriam
     gurobiToCobraRes
     ravenCobraWrapperravenCobraWrapper
     standardizeModelFieldOrderstandardizeModelFieldOrder
    + editMiriameditMiriam  extractMiriamextractMiriam  ravenCobraWrapperravenCobraWrapper  standardizeModelFieldOrderstandardizeModelFieldOrder diff --git a/doc/struct_conversion/ravenCobraWrapper.html b/doc/struct_conversion/ravenCobraWrapper.html index a2a9feac..6d40c642 100644 --- a/doc/struct_conversion/ravenCobraWrapper.html +++ b/doc/struct_conversion/ravenCobraWrapper.html @@ -107,404 +107,403 @@

    SOURCE CODE ^end 0036 -0037 [ST, I]=dbstack('-completenames'); -0038 ravenPath=fileparts(fileparts(ST(I).file)); -0039 -0040 % Load COBRA field information -0041 fid = fopen([ravenPath filesep 'struct_conversion' filesep 'COBRA_structure_fields.csv']); % Taken from https://github.com/opencobra/cobratoolbox/blob/develop/src/base/io/definitions/COBRA_structure_fields.csv -0042 fieldFile = textscan(fid,repmat('%s',1,15),'Delimiter','\t','HeaderLines',1); -0043 dbFields = ~cellfun(@isempty,fieldFile{5}); % Only keep fields with database annotations that should be translated to xxxMiriams -0044 dbFields = dbFields & ~contains(fieldFile{1},{'metInChIString','metKEGGID','metPubChemID','rxnECNumbers'}); -0045 COBRAnamespace = fieldFile{5}(dbFields); -0046 COBRAnamespace = regexprep(COBRAnamespace,';.*',''); % Only keep first suggested namespace -0047 COBRAfields = fieldFile{1}(dbFields); -0048 fclose(fid); -0049 -0050 % Load conversion between additional COBRA fields and namespaces: -0051 fid = fopen([ravenPath filesep 'struct_conversion' filesep 'cobraNamespaces.csv']); -0052 fieldFile = textscan(fid,'%s %s','Delimiter',',','HeaderLines',0); -0053 COBRAfields = [COBRAfields; fieldFile{1}]; -0054 COBRAnamespace = [COBRAnamespace; fieldFile{2}]; -0055 rxnCOBRAfields = COBRAfields(startsWith(COBRAfields,'rxn')); -0056 rxnNamespaces = COBRAnamespace(startsWith(COBRAfields,'rxn')); -0057 metCOBRAfields = COBRAfields(startsWith(COBRAfields,'met')); -0058 metNamespaces = COBRAnamespace(startsWith(COBRAfields,'met')); -0059 geneCOBRAfields = COBRAfields(startsWith(COBRAfields,'gene')); -0060 geneNamespaces = COBRAnamespace(startsWith(COBRAfields,'gene')); -0061 fclose(fid); -0062 -0063 if isRaven -0064 %Firstly remove boundary metabolites -0065 model=simplifyModel(model); -0066 end -0067 -0068 % Keep fields that have identical names and content -0069 newModel.S=model.S; -0070 newModel.lb=model.lb; -0071 newModel.ub=model.ub; -0072 newModel.c=model.c; -0073 newModel.rxns=model.rxns; -0074 optFields = {'rxnNames','subSystems','rxnNotes',... -0075 'metFormulas','comps','compNames','metCharges','genes',... -0076 'rxnConfidenceScores','rxnGeneMat','metNotes','rev'}; -0077 for i=1:length(optFields) -0078 if isfield(model,optFields{i}) -0079 newModel.(optFields{i})=model.(optFields{i}); -0080 end -0081 end -0082 -0083 % Convert unique fields -0084 if isRaven -0085 fprintf('Converting RAVEN structure to COBRA..\n'); -0086 %Convert from RAVEN to COBRA structure -0087 -0088 %Mandatory COBRA fields -0089 newModel.rxns=model.rxns; -0090 if all(~cellfun(@isempty,regexp(model.mets,'\[[^\]]+\]$'))) -0091 newModel.mets=model.mets; -0092 else -0093 %Check if model has compartment info as "met_c" suffix in all metabolites: -0094 BiGGformat = false(size(model.mets)); -0095 for i=1:numel(model.comps) -0096 compPos=model.metComps==i; -0097 BiGGformat(compPos)=~cellfun(@isempty,regexp(model.mets(compPos),['_' model.comps{i} '$'])); -0098 end -0099 if all(BiGGformat) -0100 newModel.mets=model.mets; -0101 for i=1:numel(model.comps) -0102 newModel.mets=regexprep(newModel.mets,['_' model.comps{i} '$'],['[' model.comps{i} ']']); -0103 end -0104 else -0105 newModel.mets=strcat(model.mets,'[',model.comps(model.metComps),']'); -0106 end -0107 end -0108 -0109 %b, csense, osenseStr, genes, rules are also mandatory, but defined -0110 %later to match the order of fields -0111 -0112 %Optional COBRA fields -0113 if isfield(model,'id') -0114 newModel.modelID=model.id; -0115 end -0116 if isfield(model,'name') -0117 newModel.modelName=model.name; -0118 end -0119 if isfield(model,'eccodes') -0120 newModel.rxnECNumbers=model.eccodes; -0121 end -0122 if isfield(model,'rxnMiriams') -0123 [miriams,extractedMiriamNames]=extractMiriam(model.rxnMiriams); -0124 for i = 1:length(rxnCOBRAfields) -0125 j=ismember(extractedMiriamNames,rxnNamespaces{i}); -0126 if any(j) -0127 eval(['newModel.' rxnCOBRAfields{i} ' = miriams(:,j);']) -0128 end -0129 end -0130 end -0131 if isfield(model,'rxnReferences') % Concatenate model.rxnReferences to those extracted from model.rxnMiriams -0132 if isfield(newModel,'rxnReferences') -0133 newModel.rxnReferences = strcat(newModel.rxnReferences,{'; '},model.rxnReferences); -0134 newModel.rxnReferences = regexprep(newModel.rxnReferences,'^; $',''); -0135 else -0136 newModel.rxnReferences = model.rxnReferences; -0137 end -0138 end -0139 if isfield(model,'metNames') -0140 newModel.metNames=strcat(model.metNames,' [',model.compNames(model.metComps),']'); -0141 end -0142 if isfield(model,'metMiriams') -0143 [miriams,extractedMiriamNames]=extractMiriam(model.metMiriams); -0144 %Shorten miriam names for KEGG and PubChem. These shorter names -0145 %will be used later to concatenate KEGG COMPOUND/GLYCAN and PubChem -0146 %Compound/Substance, into corresponding COBRA model fields -0147 extractedMiriamNames=regexprep(extractedMiriamNames,'^kegg\..+','kegg'); -0148 extractedMiriamNames=regexprep(extractedMiriamNames,'^pubchem\..+','pubchem'); -0149 i=ismember(extractedMiriamNames,'kegg'); -0150 if any(i) % Combine KEGG compounds and glycans -0151 for j=1:length(i) -0152 if i(j) && isfield(newModel,'metKEGGID')~=1 -0153 newModel.metKEGGID=miriams(:,j); -0154 elseif i(j) -0155 newModel.metKEGGID=strcat(newModel.metKEGGID,';',miriams(:,j)); -0156 end -0157 end -0158 newModel.metKEGGID=regexprep(newModel.metKEGGID,'^;|;$',''); -0159 end -0160 i=ismember(extractedMiriamNames,'pubchem'); -0161 if any(i) % Combine Pubchem compounds and substances -0162 for j=1:length(i) -0163 if i(j) && isfield(newModel,'metPubChemID')~=1 -0164 newModel.metPubChemID=miriams(:,j); -0165 elseif i(j) -0166 newModel.metPubChemID=strcat(newModel.metPubChemID,';',miriams(:,j)); -0167 end -0168 end -0169 newModel.metPubChemID=regexprep(newModel.metPubChemID,'^;|;$',''); -0170 end -0171 %All other Miriams can be directly parsed with no modifications: -0172 for i = 1:length(metCOBRAfields) -0173 j=ismember(extractedMiriamNames,metNamespaces{i}); -0174 if any(j) -0175 eval(['newModel.' metCOBRAfields{i} ' = miriams(:,j);']) -0176 end -0177 end -0178 end -0179 if isfield(model,'inchis') -0180 newModel.metInChIString=regexprep(strcat('InChI=', model.inchis),'^InChI=$',''); -0181 end -0182 newModel.b=zeros(numel(model.mets),1); -0183 newModel.csense=repmat('E',size(model.mets)); -0184 if isfield(model,'geneMiriams') -0185 [miriams,extractedMiriamNames]=extractMiriam(model.geneMiriams); -0186 for i = 1:length(geneCOBRAfields) -0187 j=ismember(extractedMiriamNames,geneNamespaces{i}); -0188 if any(j) -0189 eval(['newModel.' geneCOBRAfields{i} ' = miriams(:,j);']) -0190 end -0191 end -0192 end -0193 if isfield(model,'geneShortNames') -0194 newModel.geneNames=model.geneShortNames; -0195 end -0196 if isfield(model,'genes') -0197 newModel.rules=grrulesToRules(model); -0198 else -0199 fprintf('WARNING: no genes detected. The model therefore may not be exportable to SBML file with writeCbModel\n'); -0200 end -0201 newModel.osenseStr='max'; -0202 else -0203 fprintf('Converting COBRA structure to RAVEN..\n'); -0204 %Convert from COBRA to RAVEN structure -0205 -0206 %Mandatory RAVEN fields -0207 newModel.mets=model.mets; -0208 if ~isfield(model,'comps') -0209 model.comps = unique(regexprep(model.mets,'.*\[([^\]]+)\]$','$1')); -0210 end -0211 for i=1:numel(model.comps) -0212 newModel.mets=regexprep(newModel.mets,['\[', model.comps{i}, '\]$'],''); -0213 newModel.mets=regexprep(newModel.mets,['\[', model.compNames{i}, '\]$'],''); -0214 end -0215 -0216 %In some cases (e.g. any model that uses BiGG ids as main ids), there -0217 %may be overlapping mets due to removal of compartment info. To avoid -0218 %this, we change compartments from e.g. [c] into _c -0219 if numel(unique(newModel.mets))~=numel(model.mets) -0220 newModel.mets=model.mets; -0221 for i=1:numel(model.comps) -0222 newModel.mets=regexprep(newModel.mets,['\[' model.comps{i} '\]$'],['_' model.comps{i}]); -0223 end -0224 end -0225 %Since COBRA no longer contains rev field it is assumed that rxn is -0226 %reversible if its lower bound is set below zero -0227 if ~isfield(model,'rev') -0228 for i=1:numel(model.rxns) -0229 if model.lb(i)<0 -0230 newModel.rev(i,1)=1; -0231 else -0232 newModel.rev(i,1)=0; -0233 end -0234 end -0235 end -0236 newModel.b=zeros(numel(model.mets),1); -0237 if ~isfield(model,'comps') -0238 %Since 'comps' field is not mandatory in COBRA, it may be required -0239 %to obtain the non-redundant list of comps from metabolite ids, if -0240 %'comps' field is not available -0241 newModel.comps=regexprep(model.mets,'^.+\[',''); -0242 newModel.comps=regexprep(newModel.comps,'\]$',''); -0243 newModel.comps=unique(newModel.comps); -0244 end -0245 -0246 %metComps is also mandatory, but defined later to match the order of -0247 %fields -0248 -0249 %Fields 'name' and 'id' are also considered as mandatory, but -0250 %these are added to the model during exportModel/exportToExcelFormat -0251 %anyway, so there is no point to add this information here -0252 -0253 %Optional RAVEN fields -0254 if isfield(model,'modelID') -0255 newModel.id=model.modelID; -0256 end -0257 if isfield(model,'modelName') -0258 newModel.name=model.modelName; -0259 end -0260 if isfield(model,'rules') -0261 model.grRules = rulesTogrrules(model); -0262 [grRules,rxnGeneMat] = standardizeGrRules(model,true); -0263 newModel.grRules = grRules; -0264 newModel.rxnGeneMat = rxnGeneMat; -0265 end -0266 if isfield(model,'rxnECNumbers') -0267 newModel.eccodes=regexprep(model.rxnECNumbers,'EC|EC:',''); -0268 end -0269 if any(isfield(model,rxnCOBRAfields)) -0270 for i=1:numel(model.rxns) -0271 counter=1; -0272 newModel.rxnMiriams{i,1}=[]; -0273 if isfield(model,'rxnReferences') -0274 if ~isempty(model.rxnReferences{i}) -0275 pmids = model.rxnReferences{i}; -0276 pmids = strsplit(pmids,'; '); -0277 nonPmids = cellfun(@isempty,regexp(pmids,'^\d+$','match','once')); -0278 if any(nonPmids) %Not a pubmed id, keep in rxnReferences instead -0279 newModel.rxnReferences{i,1} = strjoin(pmids(nonPmids),', '); -0280 pmids(nonPmids)=[]; -0281 end -0282 for j = 1:length(pmids) -0283 newModel.rxnMiriams{i,1}.name{counter,1} = 'pubmed'; -0284 newModel.rxnMiriams{i,1}.value{counter,1} = pmids{j}; -0285 counter=counter+1; -0286 end -0287 end -0288 end -0289 for j = 2:length(rxnCOBRAfields) %Start from 2, as 1 is rxnReferences -0290 if isfield(model,rxnCOBRAfields{j}) -0291 rxnAnnotation = eval(['model.' rxnCOBRAfields{j} '{i}']); -0292 if ~isempty(rxnAnnotation) -0293 rxnAnnotation = strtrim(strsplit(rxnAnnotation,';')); -0294 for a=1:length(rxnAnnotation) -0295 newModel.rxnMiriams{i,1}.name{counter,1} = rxnNamespaces{j}; -0296 newModel.rxnMiriams{i,1}.value{counter,1} = rxnAnnotation{a}; -0297 counter=counter+1; -0298 end -0299 end -0300 end -0301 end -0302 end -0303 end -0304 if isfield(newModel,'rxnReferences') -0305 emptyEntry = cellfun(@isempty,newModel.rxnReferences); -0306 newModel.rxnReferences(emptyEntry)={''}; -0307 end -0308 if any(isfield(model,geneCOBRAfields)) -0309 for i=1:numel(model.genes) -0310 counter=1; -0311 newModel.geneMiriams{i,1}=[]; -0312 for j = 1:length(geneCOBRAfields) -0313 if isfield(model,geneCOBRAfields{j}) -0314 geneAnnotation = eval(['model.' geneCOBRAfields{j} '{i}']); -0315 if ~isempty(geneAnnotation) -0316 geneAnnotation = strtrim(strsplit(geneAnnotation,';')); -0317 for a=1:length(geneAnnotation) -0318 newModel.geneMiriams{i,1}.name{counter,1} = geneNamespaces{j}; -0319 newModel.geneMiriams{i,1}.value{counter,1} = geneAnnotation{a}; -0320 counter=counter+1; -0321 end -0322 end -0323 end -0324 end -0325 end -0326 end -0327 if isfield(model,'geneNames') -0328 newModel.geneShortNames=model.geneNames; -0329 end -0330 newModel.metNames=model.metNames; -0331 for i=1:numel(model.comps) -0332 newModel.metNames=regexprep(newModel.metNames,['\[', model.comps{i}, '\]$'],''); -0333 newModel.metNames=regexprep(newModel.metNames,['\[', model.compNames{i}, '\]$'],''); -0334 end -0335 newModel.metNames=deblank(newModel.metNames); -0336 newModel.metComps=regexprep(model.mets,'^.+\[',''); -0337 newModel.metComps=regexprep(newModel.metComps,'\]$',''); -0338 [~, newModel.metComps]=ismember(newModel.metComps,newModel.comps); -0339 if isfield(model,'metInChIString') -0340 newModel.inchis=regexprep(model.metInChIString,'^InChI=',''); -0341 end -0342 printWarning=false; -0343 if any(isfield(model,[metCOBRAfields;'metKEGGID';'metPubChemID'])) -0344 for i=1:numel(model.mets) -0345 counter=1; -0346 newModel.metMiriams{i,1}=[]; -0347 if isfield(model,'metKEGGID') -0348 if ~isempty(model.metKEGGID{i}) -0349 if strcmp(model.metKEGGID{i}(1),'C') -0350 newModel.metMiriams{i,1}.name{counter,1} = 'kegg.compound'; -0351 newModel.metMiriams{i,1}.value{counter,1} = model.metKEGGID{i}; -0352 counter=counter+1; -0353 elseif strcmp(model.metKEGGID{i}(1),'G') -0354 newModel.metMiriams{i,1}.name{counter,1} = 'kegg.glycan'; -0355 newModel.metMiriams{i,1}.value{counter,1} = model.metKEGGID{i}; -0356 counter=counter+1; -0357 end -0358 end -0359 end -0360 if isfield(model,'metPubChemID') -0361 if ~isempty(model.metPubChemID{i}) -0362 if length(model.metPubChemID{i})>3 && strcmp(model.metPubChemID{i}(1:4),'CID:') -0363 newModel.metMiriams{i,1}.name{counter,1} = 'pubchem.compound'; -0364 newModel.metMiriams{i,1}.value{counter,1} = model.metPubChemID{i}; -0365 counter=counter+1; -0366 elseif length(model.metPubChemID{i})>3 && strcmp(model.metPubChemID{i}(1:4),'SID:') -0367 newModel.metMiriams{i,1}.name{counter,1} = 'pubchem.substance'; -0368 newModel.metMiriams{i,1}.value{counter,1} = model.metPubChemID{i}; -0369 counter=counter+1; -0370 else -0371 newModel.metMiriams{i,1}.name{counter,1} = 'pubchem.compound'; -0372 newModel.metMiriams{i,1}.value{counter,1} = model.metPubChemID{i}; -0373 counter=counter+1; -0374 printWarning=true; -0375 end -0376 end -0377 end -0378 for j = 1:length(metCOBRAfields) -0379 if isfield(model,metCOBRAfields{j}) -0380 metAnnotation = eval(['model.' metCOBRAfields{j} '{i}']); -0381 if ~isempty(metAnnotation) -0382 metAnnotation = strtrim(strsplit(metAnnotation,';')); -0383 for a=1:length(metAnnotation) -0384 newModel.metMiriams{i,1}.name{counter,1} = metNamespaces{j}; -0385 newModel.metMiriams{i,1}.value{counter,1} = metAnnotation{a}; -0386 counter=counter+1; -0387 end -0388 end -0389 end -0390 end -0391 end -0392 end -0393 if printWarning -0394 fprintf('Could not determine whether PubChemIDs are compounds (CID)\n or substances (SID). All annotated PubChemIDs will therefore \n be assigned as compounds (CID).\n'); -0395 end -0396 end -0397 -0398 % Order fields -0399 modelNew=standardizeModelFieldOrder(newModel); % Corrects for both RAVEN and COBRA models -0400 end -0401 -0402 function rules=grrulesToRules(model) -0403 %This function just takes grRules, changes all gene names to -0404 %'x(geneNumber)' and also changes 'or' and 'and' relations to corresponding -0405 %symbols -0406 replacingGenes=cell([size(model.genes,1) 1]); -0407 for i=1:numel(replacingGenes) -0408 replacingGenes{i}=strcat('x(',num2str(i),')'); -0409 end -0410 rules = strcat({' '},model.grRules,{' '}); -0411 for i=1:length(model.genes) -0412 rules=regexprep(rules,[' ' model.genes{i} ' '],[' ' replacingGenes{i} ' ']); -0413 rules=regexprep(rules,['(' model.genes{i} ' '],['(' replacingGenes{i} ' ']); -0414 rules=regexprep(rules,[' ' model.genes{i} ')'],[' ' replacingGenes{i} ')']); -0415 end -0416 rules=regexprep(rules,' and ',' & '); -0417 rules=regexprep(rules,' or ',' | '); -0418 rules=strtrim(rules); -0419 end -0420 -0421 function grRules=rulesTogrrules(model) -0422 %This function takes rules, replaces &/| for and/or, replaces the x(i) -0423 %format with the actual gene ID, and takes out extra whitespace and -0424 %redundant parenthesis introduced by COBRA, to create grRules. -0425 grRules = strrep(model.rules,'&','and'); -0426 grRules = strrep(grRules,'|','or'); -0427 for i = 1:length(model.genes) -0428 grRules = strrep(grRules,['x(' num2str(i) ')'],model.genes{i}); -0429 end -0430 grRules = strrep(grRules,'( ','('); -0431 grRules = strrep(grRules,' )',')'); -0432 grRules = regexprep(grRules,'^(',''); %rules that start with a "(" -0433 grRules = regexprep(grRules,')$',''); %rules that end with a ")" -0434 end +0037 ravenPath=findRAVENroot(); +0038 +0039 % Load COBRA field information +0040 fid = fopen(fullfile(ravenPath,'struct_conversion','COBRA_structure_fields.csv')); % Taken from https://github.com/opencobra/cobratoolbox/blob/develop/src/base/io/definitions/COBRA_structure_fields.csv +0041 fieldFile = textscan(fid,repmat('%s',1,15),'Delimiter','\t','HeaderLines',1); +0042 dbFields = ~cellfun(@isempty,fieldFile{5}); % Only keep fields with database annotations that should be translated to xxxMiriams +0043 dbFields = dbFields & ~contains(fieldFile{1},{'metInChIString','metKEGGID','metPubChemID','rxnECNumbers'}); +0044 COBRAnamespace = fieldFile{5}(dbFields); +0045 COBRAnamespace = regexprep(COBRAnamespace,';.*',''); % Only keep first suggested namespace +0046 COBRAfields = fieldFile{1}(dbFields); +0047 fclose(fid); +0048 +0049 % Load conversion between additional COBRA fields and namespaces: +0050 fid = fopen(fullfile(ravenPath,'struct_conversion','cobraNamespaces.csv')); +0051 fieldFile = textscan(fid,'%s %s','Delimiter',',','HeaderLines',0); +0052 COBRAfields = [COBRAfields; fieldFile{1}]; +0053 COBRAnamespace = [COBRAnamespace; fieldFile{2}]; +0054 rxnCOBRAfields = COBRAfields(startsWith(COBRAfields,'rxn')); +0055 rxnNamespaces = COBRAnamespace(startsWith(COBRAfields,'rxn')); +0056 metCOBRAfields = COBRAfields(startsWith(COBRAfields,'met')); +0057 metNamespaces = COBRAnamespace(startsWith(COBRAfields,'met')); +0058 geneCOBRAfields = COBRAfields(startsWith(COBRAfields,'gene')); +0059 geneNamespaces = COBRAnamespace(startsWith(COBRAfields,'gene')); +0060 fclose(fid); +0061 +0062 if isRaven +0063 %Firstly remove boundary metabolites +0064 model=simplifyModel(model); +0065 end +0066 +0067 % Keep fields that have identical names and content +0068 newModel.S=model.S; +0069 newModel.lb=model.lb; +0070 newModel.ub=model.ub; +0071 newModel.c=model.c; +0072 newModel.rxns=model.rxns; +0073 optFields = {'rxnNames','subSystems','rxnNotes',... +0074 'metFormulas','comps','compNames','metCharges','genes',... +0075 'rxnConfidenceScores','rxnGeneMat','metNotes','rev'}; +0076 for i=1:length(optFields) +0077 if isfield(model,optFields{i}) +0078 newModel.(optFields{i})=model.(optFields{i}); +0079 end +0080 end +0081 +0082 % Convert unique fields +0083 if isRaven +0084 fprintf('Converting RAVEN structure to COBRA..\n'); +0085 %Convert from RAVEN to COBRA structure +0086 +0087 %Mandatory COBRA fields +0088 newModel.rxns=model.rxns; +0089 if all(~cellfun(@isempty,regexp(model.mets,'\[[^\]]+\]$'))) +0090 newModel.mets=model.mets; +0091 else +0092 %Check if model has compartment info as "met_c" suffix in all metabolites: +0093 BiGGformat = false(size(model.mets)); +0094 for i=1:numel(model.comps) +0095 compPos=model.metComps==i; +0096 BiGGformat(compPos)=~cellfun(@isempty,regexp(model.mets(compPos),['_' model.comps{i} '$'])); +0097 end +0098 if all(BiGGformat) +0099 newModel.mets=model.mets; +0100 for i=1:numel(model.comps) +0101 newModel.mets=regexprep(newModel.mets,['_' model.comps{i} '$'],['[' model.comps{i} ']']); +0102 end +0103 else +0104 newModel.mets=strcat(model.mets,'[',model.comps(model.metComps),']'); +0105 end +0106 end +0107 +0108 %b, csense, osenseStr, genes, rules are also mandatory, but defined +0109 %later to match the order of fields +0110 +0111 %Optional COBRA fields +0112 if isfield(model,'id') +0113 newModel.modelID=model.id; +0114 end +0115 if isfield(model,'name') +0116 newModel.modelName=model.name; +0117 end +0118 if isfield(model,'eccodes') +0119 newModel.rxnECNumbers=model.eccodes; +0120 end +0121 if isfield(model,'rxnMiriams') +0122 [miriams,extractedMiriamNames]=extractMiriam(model.rxnMiriams); +0123 for i = 1:length(rxnCOBRAfields) +0124 j=ismember(extractedMiriamNames,rxnNamespaces{i}); +0125 if any(j) +0126 eval(['newModel.' rxnCOBRAfields{i} ' = miriams(:,j);']) +0127 end +0128 end +0129 end +0130 if isfield(model,'rxnReferences') % Concatenate model.rxnReferences to those extracted from model.rxnMiriams +0131 if isfield(newModel,'rxnReferences') +0132 newModel.rxnReferences = strcat(newModel.rxnReferences,{'; '},model.rxnReferences); +0133 newModel.rxnReferences = regexprep(newModel.rxnReferences,'^; $',''); +0134 else +0135 newModel.rxnReferences = model.rxnReferences; +0136 end +0137 end +0138 if isfield(model,'metNames') +0139 newModel.metNames=strcat(model.metNames,' [',model.compNames(model.metComps),']'); +0140 end +0141 if isfield(model,'metMiriams') +0142 [miriams,extractedMiriamNames]=extractMiriam(model.metMiriams); +0143 %Shorten miriam names for KEGG and PubChem. These shorter names +0144 %will be used later to concatenate KEGG COMPOUND/GLYCAN and PubChem +0145 %Compound/Substance, into corresponding COBRA model fields +0146 extractedMiriamNames=regexprep(extractedMiriamNames,'^kegg\..+','kegg'); +0147 extractedMiriamNames=regexprep(extractedMiriamNames,'^pubchem\..+','pubchem'); +0148 i=ismember(extractedMiriamNames,'kegg'); +0149 if any(i) % Combine KEGG compounds and glycans +0150 for j=1:length(i) +0151 if i(j) && isfield(newModel,'metKEGGID')~=1 +0152 newModel.metKEGGID=miriams(:,j); +0153 elseif i(j) +0154 newModel.metKEGGID=strcat(newModel.metKEGGID,';',miriams(:,j)); +0155 end +0156 end +0157 newModel.metKEGGID=regexprep(newModel.metKEGGID,'^;|;$',''); +0158 end +0159 i=ismember(extractedMiriamNames,'pubchem'); +0160 if any(i) % Combine Pubchem compounds and substances +0161 for j=1:length(i) +0162 if i(j) && isfield(newModel,'metPubChemID')~=1 +0163 newModel.metPubChemID=miriams(:,j); +0164 elseif i(j) +0165 newModel.metPubChemID=strcat(newModel.metPubChemID,';',miriams(:,j)); +0166 end +0167 end +0168 newModel.metPubChemID=regexprep(newModel.metPubChemID,'^;|;$',''); +0169 end +0170 %All other Miriams can be directly parsed with no modifications: +0171 for i = 1:length(metCOBRAfields) +0172 j=ismember(extractedMiriamNames,metNamespaces{i}); +0173 if any(j) +0174 eval(['newModel.' metCOBRAfields{i} ' = miriams(:,j);']) +0175 end +0176 end +0177 end +0178 if isfield(model,'inchis') +0179 newModel.metInChIString=regexprep(strcat('InChI=', model.inchis),'^InChI=$',''); +0180 end +0181 newModel.b=zeros(numel(model.mets),1); +0182 newModel.csense=repmat('E',size(model.mets)); +0183 if isfield(model,'geneMiriams') +0184 [miriams,extractedMiriamNames]=extractMiriam(model.geneMiriams); +0185 for i = 1:length(geneCOBRAfields) +0186 j=ismember(extractedMiriamNames,geneNamespaces{i}); +0187 if any(j) +0188 eval(['newModel.' geneCOBRAfields{i} ' = miriams(:,j);']) +0189 end +0190 end +0191 end +0192 if isfield(model,'geneShortNames') +0193 newModel.geneNames=model.geneShortNames; +0194 end +0195 if isfield(model,'genes') +0196 newModel.rules=grrulesToRules(model); +0197 else +0198 fprintf('WARNING: no genes detected. The model therefore may not be exportable to SBML file with writeCbModel\n'); +0199 end +0200 newModel.osenseStr='max'; +0201 else +0202 fprintf('Converting COBRA structure to RAVEN..\n'); +0203 %Convert from COBRA to RAVEN structure +0204 +0205 %Mandatory RAVEN fields +0206 newModel.mets=model.mets; +0207 if ~isfield(model,'comps') +0208 model.comps = unique(regexprep(model.mets,'.*\[([^\]]+)\]$','$1')); +0209 end +0210 for i=1:numel(model.comps) +0211 newModel.mets=regexprep(newModel.mets,['\[', model.comps{i}, '\]$'],''); +0212 newModel.mets=regexprep(newModel.mets,['\[', model.compNames{i}, '\]$'],''); +0213 end +0214 +0215 %In some cases (e.g. any model that uses BiGG ids as main ids), there +0216 %may be overlapping mets due to removal of compartment info. To avoid +0217 %this, we change compartments from e.g. [c] into _c +0218 if numel(unique(newModel.mets))~=numel(model.mets) +0219 newModel.mets=model.mets; +0220 for i=1:numel(model.comps) +0221 newModel.mets=regexprep(newModel.mets,['\[' model.comps{i} '\]$'],['_' model.comps{i}]); +0222 end +0223 end +0224 %Since COBRA no longer contains rev field it is assumed that rxn is +0225 %reversible if its lower bound is set below zero +0226 if ~isfield(model,'rev') +0227 for i=1:numel(model.rxns) +0228 if model.lb(i)<0 +0229 newModel.rev(i,1)=1; +0230 else +0231 newModel.rev(i,1)=0; +0232 end +0233 end +0234 end +0235 newModel.b=zeros(numel(model.mets),1); +0236 if ~isfield(model,'comps') +0237 %Since 'comps' field is not mandatory in COBRA, it may be required +0238 %to obtain the non-redundant list of comps from metabolite ids, if +0239 %'comps' field is not available +0240 newModel.comps=regexprep(model.mets,'^.+\[',''); +0241 newModel.comps=regexprep(newModel.comps,'\]$',''); +0242 newModel.comps=unique(newModel.comps); +0243 end +0244 +0245 %metComps is also mandatory, but defined later to match the order of +0246 %fields +0247 +0248 %Fields 'name' and 'id' are also considered as mandatory, but +0249 %these are added to the model during exportModel/exportToExcelFormat +0250 %anyway, so there is no point to add this information here +0251 +0252 %Optional RAVEN fields +0253 if isfield(model,'modelID') +0254 newModel.id=model.modelID; +0255 end +0256 if isfield(model,'modelName') +0257 newModel.name=model.modelName; +0258 end +0259 if isfield(model,'rules') +0260 model.grRules = rulesTogrrules(model); +0261 [grRules,rxnGeneMat] = standardizeGrRules(model,true); +0262 newModel.grRules = grRules; +0263 newModel.rxnGeneMat = rxnGeneMat; +0264 end +0265 if isfield(model,'rxnECNumbers') +0266 newModel.eccodes=regexprep(model.rxnECNumbers,'EC|EC:',''); +0267 end +0268 if any(isfield(model,rxnCOBRAfields)) +0269 for i=1:numel(model.rxns) +0270 counter=1; +0271 newModel.rxnMiriams{i,1}=[]; +0272 if isfield(model,'rxnReferences') +0273 if ~isempty(model.rxnReferences{i}) +0274 pmids = model.rxnReferences{i}; +0275 pmids = strsplit(pmids,'; '); +0276 nonPmids = cellfun(@isempty,regexp(pmids,'^\d+$','match','once')); +0277 if any(nonPmids) %Not a pubmed id, keep in rxnReferences instead +0278 newModel.rxnReferences{i,1} = strjoin(pmids(nonPmids),', '); +0279 pmids(nonPmids)=[]; +0280 end +0281 for j = 1:length(pmids) +0282 newModel.rxnMiriams{i,1}.name{counter,1} = 'pubmed'; +0283 newModel.rxnMiriams{i,1}.value{counter,1} = pmids{j}; +0284 counter=counter+1; +0285 end +0286 end +0287 end +0288 for j = 2:length(rxnCOBRAfields) %Start from 2, as 1 is rxnReferences +0289 if isfield(model,rxnCOBRAfields{j}) +0290 rxnAnnotation = eval(['model.' rxnCOBRAfields{j} '{i}']); +0291 if ~isempty(rxnAnnotation) +0292 rxnAnnotation = strtrim(strsplit(rxnAnnotation,';')); +0293 for a=1:length(rxnAnnotation) +0294 newModel.rxnMiriams{i,1}.name{counter,1} = rxnNamespaces{j}; +0295 newModel.rxnMiriams{i,1}.value{counter,1} = rxnAnnotation{a}; +0296 counter=counter+1; +0297 end +0298 end +0299 end +0300 end +0301 end +0302 end +0303 if isfield(newModel,'rxnReferences') +0304 emptyEntry = cellfun(@isempty,newModel.rxnReferences); +0305 newModel.rxnReferences(emptyEntry)={''}; +0306 end +0307 if any(isfield(model,geneCOBRAfields)) +0308 for i=1:numel(model.genes) +0309 counter=1; +0310 newModel.geneMiriams{i,1}=[]; +0311 for j = 1:length(geneCOBRAfields) +0312 if isfield(model,geneCOBRAfields{j}) +0313 geneAnnotation = eval(['model.' geneCOBRAfields{j} '{i}']); +0314 if ~isempty(geneAnnotation) +0315 geneAnnotation = strtrim(strsplit(geneAnnotation,';')); +0316 for a=1:length(geneAnnotation) +0317 newModel.geneMiriams{i,1}.name{counter,1} = geneNamespaces{j}; +0318 newModel.geneMiriams{i,1}.value{counter,1} = geneAnnotation{a}; +0319 counter=counter+1; +0320 end +0321 end +0322 end +0323 end +0324 end +0325 end +0326 if isfield(model,'geneNames') +0327 newModel.geneShortNames=model.geneNames; +0328 end +0329 newModel.metNames=model.metNames; +0330 for i=1:numel(model.comps) +0331 newModel.metNames=regexprep(newModel.metNames,['\[', model.comps{i}, '\]$'],''); +0332 newModel.metNames=regexprep(newModel.metNames,['\[', model.compNames{i}, '\]$'],''); +0333 end +0334 newModel.metNames=deblank(newModel.metNames); +0335 newModel.metComps=regexprep(model.mets,'^.+\[',''); +0336 newModel.metComps=regexprep(newModel.metComps,'\]$',''); +0337 [~, newModel.metComps]=ismember(newModel.metComps,newModel.comps); +0338 if isfield(model,'metInChIString') +0339 newModel.inchis=regexprep(model.metInChIString,'^InChI=',''); +0340 end +0341 printWarning=false; +0342 if any(isfield(model,[metCOBRAfields;'metKEGGID';'metPubChemID'])) +0343 for i=1:numel(model.mets) +0344 counter=1; +0345 newModel.metMiriams{i,1}=[]; +0346 if isfield(model,'metKEGGID') +0347 if ~isempty(model.metKEGGID{i}) +0348 if strcmp(model.metKEGGID{i}(1),'C') +0349 newModel.metMiriams{i,1}.name{counter,1} = 'kegg.compound'; +0350 newModel.metMiriams{i,1}.value{counter,1} = model.metKEGGID{i}; +0351 counter=counter+1; +0352 elseif strcmp(model.metKEGGID{i}(1),'G') +0353 newModel.metMiriams{i,1}.name{counter,1} = 'kegg.glycan'; +0354 newModel.metMiriams{i,1}.value{counter,1} = model.metKEGGID{i}; +0355 counter=counter+1; +0356 end +0357 end +0358 end +0359 if isfield(model,'metPubChemID') +0360 if ~isempty(model.metPubChemID{i}) +0361 if length(model.metPubChemID{i})>3 && strcmp(model.metPubChemID{i}(1:4),'CID:') +0362 newModel.metMiriams{i,1}.name{counter,1} = 'pubchem.compound'; +0363 newModel.metMiriams{i,1}.value{counter,1} = model.metPubChemID{i}; +0364 counter=counter+1; +0365 elseif length(model.metPubChemID{i})>3 && strcmp(model.metPubChemID{i}(1:4),'SID:') +0366 newModel.metMiriams{i,1}.name{counter,1} = 'pubchem.substance'; +0367 newModel.metMiriams{i,1}.value{counter,1} = model.metPubChemID{i}; +0368 counter=counter+1; +0369 else +0370 newModel.metMiriams{i,1}.name{counter,1} = 'pubchem.compound'; +0371 newModel.metMiriams{i,1}.value{counter,1} = model.metPubChemID{i}; +0372 counter=counter+1; +0373 printWarning=true; +0374 end +0375 end +0376 end +0377 for j = 1:length(metCOBRAfields) +0378 if isfield(model,metCOBRAfields{j}) +0379 metAnnotation = eval(['model.' metCOBRAfields{j} '{i}']); +0380 if ~isempty(metAnnotation) +0381 metAnnotation = strtrim(strsplit(metAnnotation,';')); +0382 for a=1:length(metAnnotation) +0383 newModel.metMiriams{i,1}.name{counter,1} = metNamespaces{j}; +0384 newModel.metMiriams{i,1}.value{counter,1} = metAnnotation{a}; +0385 counter=counter+1; +0386 end +0387 end +0388 end +0389 end +0390 end +0391 end +0392 if printWarning +0393 fprintf('Could not determine whether PubChemIDs are compounds (CID)\n or substances (SID). All annotated PubChemIDs will therefore \n be assigned as compounds (CID).\n'); +0394 end +0395 end +0396 +0397 % Order fields +0398 modelNew=standardizeModelFieldOrder(newModel); % Corrects for both RAVEN and COBRA models +0399 end +0400 +0401 function rules=grrulesToRules(model) +0402 %This function just takes grRules, changes all gene names to +0403 %'x(geneNumber)' and also changes 'or' and 'and' relations to corresponding +0404 %symbols +0405 replacingGenes=cell([size(model.genes,1) 1]); +0406 for i=1:numel(replacingGenes) +0407 replacingGenes{i}=strcat('x(',num2str(i),')'); +0408 end +0409 rules = strcat({' '},model.grRules,{' '}); +0410 for i=1:length(model.genes) +0411 rules=regexprep(rules,[' ' model.genes{i} ' '],[' ' replacingGenes{i} ' ']); +0412 rules=regexprep(rules,['(' model.genes{i} ' '],['(' replacingGenes{i} ' ']); +0413 rules=regexprep(rules,[' ' model.genes{i} ')'],[' ' replacingGenes{i} ')']); +0414 end +0415 rules=regexprep(rules,' and ',' & '); +0416 rules=regexprep(rules,' or ',' | '); +0417 rules=strtrim(rules); +0418 end +0419 +0420 function grRules=rulesTogrrules(model) +0421 %This function takes rules, replaces &/| for and/or, replaces the x(i) +0422 %format with the actual gene ID, and takes out extra whitespace and +0423 %redundant parenthesis introduced by COBRA, to create grRules. +0424 grRules = strrep(model.rules,'&','and'); +0425 grRules = strrep(grRules,'|','or'); +0426 for i = 1:length(model.genes) +0427 grRules = strrep(grRules,['x(' num2str(i) ')'],model.genes{i}); +0428 end +0429 grRules = strrep(grRules,'( ','('); +0430 grRules = strrep(grRules,' )',')'); +0431 grRules = regexprep(grRules,'^(',''); %rules that start with a "(" +0432 grRules = regexprep(grRules,')$',''); %rules that end with a ")" +0433 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/struct_conversion/standardizeModelFieldOrder.html b/doc/struct_conversion/standardizeModelFieldOrder.html index 86aff153..833e395b 100644 --- a/doc/struct_conversion/standardizeModelFieldOrder.html +++ b/doc/struct_conversion/standardizeModelFieldOrder.html @@ -69,27 +69,26 @@

    SOURCE CODE ^% 0014 % Usage: orderedModel=standardizeModelFieldOrder(model) 0015 -0016 [ST, I]=dbstack('-completenames'); -0017 ravenPath=fileparts(fileparts(ST(I).file)); -0018 -0019 if ~isfield(model,'rules') % Check if model is RAVEN -0020 fid = fopen([ravenPath filesep 'struct_conversion' filesep 'orderRavenFields.csv']); -0021 fields = textscan(fid,'%s','Delimiter',',','HeaderLines',0); -0022 fields = fields{1}; -0023 fclose(fid); -0024 else % If model is COBRA -0025 fid = fopen([ravenPath filesep 'struct_conversion' filesep 'COBRA_structure_fields.csv']); % Taken from https://github.com/opencobra/cobratoolbox/blob/develop/src/base/io/definitions/COBRA_structure_fields.csv -0026 fields = textscan(fid,repmat('%s',1,15),'Delimiter','\t','HeaderLines',1); -0027 fields = fields{1}; -0028 fclose(fid); -0029 end -0030 -0031 modelfields = fieldnames(model); -0032 order = fields(ismember(fields(:,1),modelfields)); -0033 remainingOrder = sort(setdiff(modelfields,order)); -0034 overallOrder = [columnVector(order);columnVector(remainingOrder)]; -0035 orderedModel = orderfields(model,overallOrder); -0036 end +0016 ravenPath=findRAVENroot(); +0017 +0018 if ~isfield(model,'rules') % Check if model is RAVEN +0019 fid = fopen(fullfile(ravenPath,'struct_conversion','orderRavenFields.csv')); +0020 fields = textscan(fid,'%s','Delimiter',',','HeaderLines',0); +0021 fields = fields{1}; +0022 fclose(fid); +0023 else % If model is COBRA +0024 fid = fopen(fullfile(ravenPath,'struct_conversion','COBRA_structure_fields.csv')); % Taken from https://github.com/opencobra/cobratoolbox/blob/develop/src/base/io/definitions/COBRA_structure_fields.csv +0025 fields = textscan(fid,repmat('%s',1,15),'Delimiter','\t','HeaderLines',1); +0026 fields = fields{1}; +0027 fclose(fid); +0028 end +0029 +0030 modelfields = fieldnames(model); +0031 order = fields(ismember(fields(:,1),modelfields)); +0032 remainingOrder = sort(setdiff(modelfields,order)); +0033 overallOrder = [columnVector(order);columnVector(remainingOrder)]; +0034 orderedModel = orderfields(model,overallOrder); +0035 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/testing/unit_tests/cdhitTests.html b/doc/testing/unit_tests/cdhitTests.html index c2a87baa..31c2880e 100644 --- a/doc/testing/unit_tests/cdhitTests.html +++ b/doc/testing/unit_tests/cdhitTests.html @@ -94,37 +94,36 @@

    SOURCE CODE ^'test_data','yeast_galactosidases.fa'),tmpDIR); 0049 -0050 % Define WSL paths -0051 wslPath.fastaFile=getWSLpath([tmpDIR filesep 'yeast_galactosidases.fa']); -0052 wslPath.outFile=getWSLpath(outFile); -0053 wslPath.cdhit=getWSLpath(fullfile(ravenPath,'software','cd-hit','cd-hit')); -0054 -0055 %% -0056 %Run protein clustering with CD-HIT -0057 if ispc -0058 [~, ~]=system(['wsl "' wslPath.cdhit '" -T "' num2str(cores) '" -i "' wslPath.fastaFile '" -o "' wslPath.outFile '" -c 1.0 -n 5 -M 2000']); -0059 else -0060 [~, ~]=system(['"' fullfile(ravenPath,'software','cd-hit',['cd-hit' binEnd]) '" -T "' num2str(cores) '" -i "' fullfile(tmpDIR, 'yeast_galactosidases.fa') '" -o "' outFile '" -c 1.0 -n 5 -M 2000']); -0061 end -0062 -0063 %% -0064 %Open actual MAFFT results file -0065 actCdhitOutput=importdata(fullfile(outFile)); -0066 -0067 %Remove the old tempfiles -0068 delete([outFile '*']); -0069 -0070 %Remove temporary folder, since testing is finished -0071 [~, ~]=system(['rm "' tmpDIR '" -r']); -0072 -0073 %% -0074 %Check 1a: Check if files for CD-HIT results are the same -0075 verifyEqual(testCase,actCdhitOutput,expCdhitMafftOutput); -0076 -0077 %Check 1b: Change actual CD-HIT results file and check if test fails -0078 actCdhitOutput='abc'; -0079 verifyNotEqual(testCase,actCdhitOutput,expCdhitMafftOutput); -0080 end +0050 %% +0051 %Run protein clustering with CD-HIT +0052 if ispc +0053 % Define WSL paths +0054 wslPath.fastaFile=getWSLpath([tmpDIR filesep 'yeast_galactosidases.fa']); +0055 wslPath.outFile=getWSLpath(outFile); +0056 wslPath.cdhit=getWSLpath(fullfile(ravenPath,'software','cd-hit','cd-hit')); +0057 [~, ~]=system(['wsl "' wslPath.cdhit '" -T "' num2str(cores) '" -i "' wslPath.fastaFile '" -o "' wslPath.outFile '" -c 1.0 -n 5 -M 2000']); +0058 else +0059 [~, ~]=system(['"' fullfile(ravenPath,'software','cd-hit',['cd-hit' binEnd]) '" -T "' num2str(cores) '" -i "' fullfile(tmpDIR, 'yeast_galactosidases.fa') '" -o "' outFile '" -c 1.0 -n 5 -M 2000']); +0060 end +0061 +0062 %% +0063 %Open actual cdhit results file +0064 actCdhitOutput=importdata(fullfile(outFile)); +0065 +0066 %Remove the old tempfiles +0067 delete([outFile '*']); +0068 +0069 %Remove temporary folder, since testing is finished +0070 [~, ~]=system(['rm "' tmpDIR '" -r']); +0071 +0072 %% +0073 %Check 1a: Check if files for CD-HIT results are the same +0074 verifyEqual(testCase,actCdhitOutput,expCdhitMafftOutput); +0075 +0076 %Check 1b: Change actual CD-HIT results file and check if test fails +0077 actCdhitOutput='abc'; +0078 verifyNotEqual(testCase,actCdhitOutput,expCdhitMafftOutput); +0079 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/testing/unit_tests/fillGapsLargeTests.html b/doc/testing/unit_tests/fillGapsLargeTests.html new file mode 100644 index 00000000..ab7c3e0a --- /dev/null +++ b/doc/testing/unit_tests/fillGapsLargeTests.html @@ -0,0 +1,165 @@ + + + + Description of fillGapsLargeTests + + + + + + + + + +
    Home > testing > unit_tests > fillGapsLargeTests.m
    + + + +

    fillGapsLargeTests +

    + +

    PURPOSE ^

    +
    run this test case with the command
    + +

    SYNOPSIS ^

    +
    function tests = fillGapsLargeTests
    + +

    DESCRIPTION ^

    +
    run this test case with the command
    +results = runtests('fillGapsLargeTests.m')
    + + +

    CROSS-REFERENCE INFORMATION ^

    +This function calls: + +This function is called by: + + + +

    SUBFUNCTIONS ^

    + + +

    SOURCE CODE ^

    +
    0001 %run this test case with the command
    +0002 %results = runtests('fillGapsLargeTests.m')
    +0003 function tests = fillGapsLargeTests
    +0004 tests = functiontests(localfunctions);
    +0005 end
    +0006 
    +0007 %% Skip testLargeGlpk, fails with larger models, known issue with glpk
    +0008 % function testLargeGurobi(testCase)
    +0009 % sourceDir = fileparts(fileparts(fileparts(which(mfilename))));
    +0010 % evalc('model=importModel(fullfile(sourceDir,''tutorial'',''iAL1006 v1.00.xml''))');
    +0011 % model.c(1484)=1;
    +0012 % modelDB=model; % Keep as database with reactions
    +0013 % try
    +0014 %     oldSolver=getpref('RAVEN','solver');
    +0015 % catch
    +0016 % end
    +0017 % setRavenSolver('glpk');
    +0018 %
    +0019 % %Remove first 10 reactions
    +0020 % model=removeReactions(modelDB,(1:10));
    +0021 % modelDB.id='DB';
    +0022 % try
    +0023 %     evalc('[newConnected,cannotConnect,addedRxns,model,exitFlag]=fillGaps(model,modelDB)');
    +0024 % catch
    +0025 %     try
    +0026 %         setRavenSolver(oldSolver);
    +0027 %     catch
    +0028 %         rmpref('RAVEN','solver');
    +0029 %     end
    +0030 %     error('Solver not working')
    +0031 % end
    +0032 % sol=solveLP(model);
    +0033 % try
    +0034 %     setRavenSolver(oldSolver);
    +0035 % catch
    +0036 %     rmpref('RAVEN','solver');
    +0037 % end
    +0038 % %Expect at least 5% of the original growth
    +0039 % verifyTrue(testCase,-sol.f>0);
    +0040 % end
    +0041 %%
    +0042 function testLargeGurobi(testCase)
    +0043 if exist('gurobi','file')~=3
    +0044     error('Gurobi not installed or cannot be found in MATLAB path, test skipped')
    +0045 end
    +0046 sourceDir = fileparts(fileparts(fileparts(which(mfilename))));
    +0047 evalc('model=importModel(fullfile(sourceDir,''tutorial'',''iAL1006 v1.00.xml''))');
    +0048 model.c(1484)=1;
    +0049 modelDB=model; % Keep as database with reactions
    +0050 try
    +0051     oldSolver=getpref('RAVEN','solver');
    +0052 catch
    +0053 end
    +0054 setRavenSolver('gurobi');
    +0055 
    +0056 %Remove first 10 reactions
    +0057 model=removeReactions(modelDB,(1:10));
    +0058 modelDB.id='DB';
    +0059 try
    +0060     evalc('[newConnected,cannotConnect,addedRxns,model,exitFlag]=fillGaps(model,modelDB)');
    +0061 catch
    +0062     try
    +0063         setRavenSolver(oldSolver);
    +0064     catch
    +0065         rmpref('RAVEN','solver');
    +0066     end
    +0067     error('Solver not working')
    +0068 end
    +0069 sol=solveLP(model);
    +0070 try
    +0071     setRavenSolver(oldSolver);
    +0072 catch
    +0073     rmpref('RAVEN','solver');
    +0074 end
    +0075 %Expect at least 5% of the original growth
    +0076 verifyTrue(testCase,-sol.f>0);
    +0077 end
    +0078 
    +0079 function testLargeCobra(testCase)
    +0080 if exist('initCobraToolbox.m','file')~=2
    +0081     error('COBRA Toolbox not installed or cannot be found in MATLAB path, test skipped')
    +0082 end
    +0083 sourceDir = fileparts(fileparts(fileparts(which(mfilename))));
    +0084 evalc('model=importModel(fullfile(sourceDir,''tutorial'',''iAL1006 v1.00.xml''))');
    +0085 model.c(1484)=1;
    +0086 modelDB=model; % Keep as database with reactions
    +0087 try
    +0088     oldSolver=getpref('RAVEN','solver');
    +0089 catch
    +0090 end
    +0091 setRavenSolver('cobra');
    +0092 
    +0093 %Remove first 10 reactions
    +0094 model=removeReactions(modelDB,(1:10));
    +0095 modelDB.id='DB';
    +0096 try
    +0097     evalc('[newConnected,cannotConnect,addedRxns,model,exitFlag]=fillGaps(model,modelDB)');
    +0098 catch
    +0099     try
    +0100         setRavenSolver(oldSolver);
    +0101     catch
    +0102         rmpref('RAVEN','solver');
    +0103     end
    +0104     error('Solver not working')
    +0105 end
    +0106 sol=solveLP(model);
    +0107 try
    +0108     setRavenSolver(oldSolver);
    +0109 catch
    +0110     rmpref('RAVEN','solver');
    +0111 end
    +0112 
    +0113 %Expect at least 5% of the original growth
    +0114 verifyTrue(testCase,-sol.f>0);
    +0115 end
    +
    Generated by m2html © 2005
    + + \ No newline at end of file diff --git a/doc/testing/unit_tests/fillGapsSmallTests.html b/doc/testing/unit_tests/fillGapsSmallTests.html new file mode 100644 index 00000000..5d76c5e0 --- /dev/null +++ b/doc/testing/unit_tests/fillGapsSmallTests.html @@ -0,0 +1,164 @@ + + + + Description of fillGapsSmallTests + + + + + + + + + +
    Home > testing > unit_tests > fillGapsSmallTests.m
    + + + +

    fillGapsSmallTests +

    + +

    PURPOSE ^

    +
    run this test case with the command
    + +

    SYNOPSIS ^

    +
    function tests = fillGapsSmallTests
    + +

    DESCRIPTION ^

    +
    run this test case with the command
    +results = runtests('fillGapsSmallTests.m')
    + + +

    CROSS-REFERENCE INFORMATION ^

    +This function calls: + +This function is called by: + + + +

    SUBFUNCTIONS ^

    + + +

    SOURCE CODE ^

    +
    0001 %run this test case with the command
    +0002 %results = runtests('fillGapsSmallTests.m')
    +0003 function tests = fillGapsSmallTests
    +0004 tests = functiontests(localfunctions);
    +0005 end
    +0006 
    +0007 function testSmallGlpk(testCase)
    +0008 %Test using small model
    +0009 sourceDir = fileparts(which(mfilename));
    +0010 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0011 modelDB=model; % Keep as database with reactions
    +0012 try
    +0013     oldSolver=getpref('RAVEN','solver');
    +0014 catch
    +0015 end
    +0016 setRavenSolver('glpk');
    +0017 
    +0018 %Remove first 10 reactions
    +0019 model=removeReactions(modelDB,(1:10));
    +0020 modelDB.id='DB';
    +0021 try
    +0022     evalc('[newConnected,cannotConnect,addedRxns,model,exitFlag]=fillGaps(model,modelDB)');
    +0023 catch
    +0024     try
    +0025         setRavenSolver(oldSolver);
    +0026     catch
    +0027         rmpref('RAVEN','solver');
    +0028     end
    +0029     error('Solver not working')
    +0030 end
    +0031 sol=solveLP(model);
    +0032 try
    +0033     setRavenSolver(oldSolver);
    +0034 catch
    +0035     rmpref('RAVEN','solver');
    +0036 end
    +0037 %Should give non-zero flux
    +0038 verifyTrue(testCase,-sol.f>0);
    +0039 end
    +0040 
    +0041 function testSmallGurobi(testCase)
    +0042 if exist('gurobi','file')~=3
    +0043     error('Gurobi not installed or cannot be found in MATLAB path, test skipped')
    +0044 end
    +0045 %Test using small model
    +0046 sourceDir = fileparts(which(mfilename));
    +0047 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0048 modelDB=model; % Keep as database with reactions
    +0049 try
    +0050     oldSolver=getpref('RAVEN','solver');
    +0051 catch
    +0052 end
    +0053 setRavenSolver('gurobi');
    +0054 
    +0055 %Remove first 10 reactions
    +0056 model=removeReactions(modelDB,(1:10));
    +0057 
    +0058 modelDB.id='DB';
    +0059 try
    +0060     evalc('[newConnected,cannotConnect,addedRxns,model,exitFlag]=fillGaps(model,modelDB)');
    +0061 catch
    +0062     try
    +0063         setRavenSolver(oldSolver);
    +0064     catch
    +0065         rmpref('RAVEN','solver');
    +0066     end
    +0067     error('Solver not working')
    +0068 end
    +0069 sol=solveLP(model);
    +0070 try
    +0071     setRavenSolver(oldSolver);
    +0072 catch
    +0073     rmpref('RAVEN','solver');
    +0074 end
    +0075 %Expect at least 5% of the original growth
    +0076 verifyTrue(testCase,-sol.f>0);
    +0077 end
    +0078 
    +0079 function testSmallCobra(testCase)
    +0080 if exist('initCobraToolbox.m','file')~=2
    +0081     error('COBRA Toolbox not installed or cannot be found in MATLAB path, test skipped')
    +0082 end
    +0083 %Test using small model
    +0084 sourceDir = fileparts(which(mfilename));
    +0085 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0086 modelDB=model; % Keep as database with reactions
    +0087 try
    +0088     oldSolver=getpref('RAVEN','solver');
    +0089 catch
    +0090 end
    +0091 setRavenSolver('cobra');
    +0092 
    +0093 %Remove first 10 reactions
    +0094 model=removeReactions(modelDB,(1:10));
    +0095 modelDB.id='DB';
    +0096 try
    +0097     evalc('[newConnected,cannotConnect,addedRxns,model,exitFlag]=fillGaps(model,modelDB)');
    +0098 catch
    +0099     try
    +0100         setRavenSolver(oldSolver);
    +0101     catch
    +0102         rmpref('RAVEN','solver');
    +0103     end
    +0104     error('Solver not working')
    +0105 end
    +0106 sol=solveLP(model);
    +0107 try
    +0108     setRavenSolver(oldSolver);
    +0109 catch
    +0110     rmpref('RAVEN','solver');
    +0111 end
    +0112 %Expect at least 5% of the original growth
    +0113 verifyTrue(testCase,-sol.f>0);
    +0114 end
    +
    Generated by m2html © 2005
    + + \ No newline at end of file diff --git a/doc/testing/unit_tests/importExportTests.html b/doc/testing/unit_tests/importExportTests.html new file mode 100644 index 00000000..ed2c527e --- /dev/null +++ b/doc/testing/unit_tests/importExportTests.html @@ -0,0 +1,102 @@ + + + + Description of importExportTests + + + + + + + + + +
    Home > testing > unit_tests > importExportTests.m
    + + + +

    importExportTests +

    + +

    PURPOSE ^

    +
    run this test case with the command
    + +

    SYNOPSIS ^

    +
    function tests = importExportTests
    + +

    DESCRIPTION ^

    +
    run this test case with the command
    +results = runtests('importExportTests.m')
    + + +

    CROSS-REFERENCE INFORMATION ^

    +This function calls: + +This function is called by: + + + +

    SUBFUNCTIONS ^

    + + +

    SOURCE CODE ^

    +
    0001 %run this test case with the command
    +0002 %results = runtests('importExportTests.m')
    +0003 function tests = importExportTests
    +0004 tests = functiontests(localfunctions);
    +0005 end
    +0006 
    +0007 function testExcelImport(testCase)
    +0008 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0009 excelFile=fullfile(sourceDir,'tutorial','empty.xlsx');
    +0010 %%Prepare test results, uncomment and run when new reference is needed
    +0011 % modelExcel=importExcelModel(excelFile);
    +0012 % sbmlFile=fullfile(sourceDir,'tutorial','empty.xml');
    +0013 % modelSBML=importModel(sbmlFile);
    +0014 % save(fullfile(sourceDir,'testing','unit_tests','test_data','importExportResults.mat'),'modelExcel','modelSBML');
    +0015 evalc('model=importExcelModel(excelFile)'); % Repress warnings
    +0016 load(fullfile(sourceDir,'testing','unit_tests','test_data','importExportResults.mat'), 'modelExcel');
    +0017 verifyEqual(testCase,model,modelExcel)
    +0018 end
    +0019 
    +0020 function testSBMLImport(testCase)
    +0021 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0022 sbmlFile=fullfile(sourceDir,'tutorial','empty.xml');
    +0023 evalc('model=importModel(sbmlFile)'); % Repress warnings
    +0024 load(fullfile(sourceDir,'testing','unit_tests','test_data','importExportResults.mat'), 'modelSBML');
    +0025 verifyEqual(testCase,model,modelSBML)
    +0026 end
    +0027 
    +0028 function testExcelExport(testCase)
    +0029 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0030 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0031 exportToExcelFormat(model,fullfile(sourceDir,'testing','unit_tests','test_data','_test.xlsx'));
    +0032 %File will not be exactly equal as it contains the current date and time,
    +0033 %so md5 or similar would not work. Just check whether file is reasonably
    +0034 %sized.
    +0035 s = dir(fullfile(sourceDir,'testing','unit_tests','test_data','_test.xlsx'));         
    +0036 filesize = s.bytes;
    +0037 verifyTrue(testCase,filesize>17000);
    +0038 delete(fullfile(sourceDir,'testing','unit_tests','test_data','_test.xlsx'));
    +0039 end
    +0040 
    +0041 function testSBMLExport(testCase)
    +0042 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0043 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0044 evalc('exportModel(model,fullfile(sourceDir,''testing'',''unit_tests'',''test_data'',''_test.xml''))');
    +0045 %File will not be exactly equal as it contains the current date and time,
    +0046 %so md5 or similar would not work. Just check whether file is reasonably
    +0047 %sized.
    +0048 s = dir(fullfile(sourceDir,'testing','unit_tests','test_data','_test.xml'));         
    +0049 filesize = s.bytes;
    +0050 verifyTrue(testCase,filesize>18500);
    +0051 delete(fullfile(sourceDir,'testing','unit_tests','test_data','_test.xml'));
    +0052 end
    +
    Generated by m2html © 2005
    + + \ No newline at end of file diff --git a/doc/testing/unit_tests/index.html b/doc/testing/unit_tests/index.html index 94b8d941..5d8d8c43 100644 --- a/doc/testing/unit_tests/index.html +++ b/doc/testing/unit_tests/index.html @@ -19,7 +19,7 @@

    Index for testing\unit_tests

    Matlab files in this directory:

    -
     blastPlusTestsrun this test case with the command
     cdhitTestsrun this test case with the command
     diamondTestsrun this test case with the command
     hmmerTestsrun this test case with the command
     mafftTestsrun this test case with the command
     miriamTestsrun this test case with the command
     sortIdentifiers_and_permuteModelTestsrun this test case with the command
     tinitTestsrun this test case with the command
    + blastPlusTestsrun this test case with the command  cdhitTestsrun this test case with the command  diamondTestsrun this test case with the command  fillGapsLargeTestsrun this test case with the command  fillGapsSmallTestsrun this test case with the command  hmmerTestsrun this test case with the command  importExportTestsrun this test case with the command  mafftTestsrun this test case with the command  miriamTestsrun this test case with the command  modelAbilitiesTestsrun this test case with the command  modelConversionTestsrun this test case with the command  modelCurationTestsrun this test case with the command  solverTestsrun this test case with the command  sortIdentifiers_and_permuteModelTestsrun this test case with the command  tinitTestsrun this test case with the command

    Subsequent directories:

    diff --git a/doc/testing/unit_tests/miriamTests.html b/doc/testing/unit_tests/miriamTests.html index 0c8d29c0..b84499d0 100644 --- a/doc/testing/unit_tests/miriamTests.html +++ b/doc/testing/unit_tests/miriamTests.html @@ -28,7 +28,7 @@

    SYNOPSIS ^DESCRIPTION ^

    run this test case with the command
    -results = runtests('sortIdentifiers_and_permuteModelTests.m')
    +results = runtests('miriamTests.m')

    CROSS-REFERENCE INFORMATION ^

    @@ -46,7 +46,7 @@

    SUBFUNCTIONS ^SOURCE CODE ^

    0001 %run this test case with the command
    -0002 %results = runtests('sortIdentifiers_and_permuteModelTests.m')
    +0002 %results = runtests('miriamTests.m')
     0003 function tests = miriamTests
     0004 tests = functiontests(localfunctions);
     0005 end
    diff --git a/doc/testing/unit_tests/modelAbilitiesTests.html b/doc/testing/unit_tests/modelAbilitiesTests.html
    new file mode 100644
    index 00000000..c8628528
    --- /dev/null
    +++ b/doc/testing/unit_tests/modelAbilitiesTests.html
    @@ -0,0 +1,173 @@
    +
    +
    +
    +  Description of modelAbilitiesTests
    +  
    +  
    +  
    +  
    +  
    +  
    +
    +
    +
    +
    Home > testing > unit_tests > modelAbilitiesTests.m
    + + + +

    modelAbilitiesTests +

    + +

    PURPOSE ^

    +
    run this test case with the command
    + +

    SYNOPSIS ^

    +
    function tests = modelAbilitiesTests
    + +

    DESCRIPTION ^

    +
    run this test case with the command
    +results = runtests('modelAbilitiesTests.m')
    + + +

    CROSS-REFERENCE INFORMATION ^

    +This function calls: + +This function is called by: + + + +

    SUBFUNCTIONS ^

    + + +

    SOURCE CODE ^

    +
    0001 %run this test case with the command
    +0002 %results = runtests('modelAbilitiesTests.m')
    +0003 function tests = modelAbilitiesTests
    +0004 tests = functiontests(localfunctions);
    +0005 end
    +0006 
    +0007 function canConsumeTest(testCase)
    +0008 %Load the model in RAVEN format
    +0009 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0010 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0011 
    +0012 testOut=canConsume(model,{'r5p_c';'ru5p_DASH_D_c';'s7p_c';'succ_c';'succ_e';'succoa_c';'xu5p_DASH_D_c'});
    +0013 
    +0014 testCheck=[true;true;true;true;true;false;true];
    +0015 
    +0016 verifyEqual(testCase,testOut,testCheck)
    +0017 end
    +0018 
    +0019 function canProduceTest(testCase)
    +0020 %Load the model in RAVEN format
    +0021 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0022 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0023 
    +0024 testOut=canProduce(model,{'r5p_c';'ru5p_DASH_D_c';'s7p_c';'succ_c';'succ_e';'succoa_c';'xu5p_DASH_D_c'});
    +0025 
    +0026 testCheck=[true;true;true;true;true;false;true];
    +0027 
    +0028 verifyEqual(testCase,testOut,testCheck)
    +0029 end
    +0030 
    +0031 function checkProductionTest(testCase)
    +0032 %Load the model in RAVEN format
    +0033 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0034 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0035 
    +0036 [testOut.np, testOut.npn, testOut.nfpm,testOut.mtc,~]=checkProduction(model,true,model.comps,false);
    +0037 
    +0038 testCheck.np=[10;13;16;17;21;30;32;37;49;50;51;52;53;64;65;71];
    +0039 testCheck.npn={'Acetyl-CoA[c]';'ADP[c]';'AMP[c]';'ATP[c]';'Coenzyme A[c]';'D-Fructose[e]';'Fumarate[e]';'L-Glutamine[e]';'L-Malate[e]';'NAD[c]';'NADH[c]';'NADP[c]';'NADPH[c]';'Ubiquinone-8[c]';'Ubiquinol-8[c]';'Succinyl-CoA[c]'};
    +0040 testCheck.nfpm=[true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true;false,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false;false,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false;false,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false;true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true;false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false;false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false;false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false;false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false;false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false;false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false;false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false;false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false;false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false;false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false;true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true];
    +0041 testCheck.mtc={'Acetyl-CoA[c] (connects 3 metabolites)';'ADP[c] (connects 3 metabolites)';'NAD[c] (connects 2 metabolites)';'NADP[c] (connects 2 metabolites)';'Ubiquinone-8[c] (connects 2 metabolites)';'D-Fructose[e] (connects 1 metabolites)';'Fumarate[e] (connects 1 metabolites)';'L-Glutamine[e] (connects 1 metabolites)';'L-Malate[e] (connects 1 metabolites)'};
    +0042 
    +0043 verifyEqual(testCase,testOut,testCheck)
    +0044 end
    +0045 
    +0046 function consumeSomethingTest(testCase)
    +0047 %Load the model in RAVEN format
    +0048 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0049 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0050 
    +0051 [testOut.s, testOut.m]=consumeSomething(model,{'r5p_c';'ru5p_DASH_D_c';'s7p_c';'succ_c';'succ_e';'succoa_c';'xu5p_DASH_D_c'});
    +0052 % Simplify output for later check, no need for high precision
    +0053 % testOut.s(abs(testOut.s)<1e-10)=0;
    +0054 % testOut.s=round(testOut.s,4)
    +0055 testCheck.s=[0;0;-1.45910;0;0;-1.45910;0;0;0;0;8.39000;4.01260;0;-1.45910;0;2.91830;0;1.45910;0;1.45910;0;0;1.45910;0;0;0;0;0;0;0;1.45910;0;0;0;0;-1.45910;1.45910;0;0;0;0;0;0;0;0;0;0;0;1.45910;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;2.91830;0;0;1.45910;1.45910;0;0;0;-1.45910;0;-1.45910;-1.45910;0;0;0;1.45910;1.45910;0;0;0;0;0;0;0;0;0;0;0;0];
    +0056 testCheck.m=[33];
    +0057 
    +0058 verifyEqual(testCase,testOut,testCheck,'AbsTol',1e-4)
    +0059 end
    +0060 
    +0061 function makeSomethingTest(testCase)
    +0062 %Load the model in RAVEN format
    +0063 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0064 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0065 
    +0066 [testOut.s, testOut.m]=makeSomething(model,{'r5p_c';'ru5p_DASH_D_c';'s7p_c';'succ_c';'succ_e';'succoa_c';'xu5p_DASH_D_c'});
    +0067 % Simplify output for later check, no need for high precision
    +0068 % testOut.s(abs(testOut.s)<1e-10)=0;
    +0069 % testOut.s=round(testOut.s,4);
    +0070 
    +0071 testCheck.s=[0;0;-1.86440;0;0;0;0;0;0;0;8.39000;4.66110;0;0;0;3.72890;0;1.86440;0;0;0;0;0;0;0;0;0;-0.932200;0;0;0;0;0;0;0;-1.86440;0;0;0;0.932200;0;0;0;0;0;0;0;0;1.86440;0.932200;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;3.72890;0;0;1.86440;1.86440;0.932200;0;0.932200;-1.86440;0;-1.86440;0;0;0;0;1.86440;0.932200;0;0;0;0;0;0;0;0;0;0;0;0.932200];
    +0072 testCheck.m=[6];
    +0073 
    +0074 verifyEqual(testCase,testOut,testCheck,'AbsTol',1e-4)
    +0075 end
    +0076 
    +0077 function getElementalBalanceTest(testCase)
    +0078 %Load the model in RAVEN format
    +0079 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0080 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0081 
    +0082 testOut=getElementalBalance(model,1);
    +0083 
    +0084 testCheck.balanceStatus=1;
    +0085 testCheck.elements.abbrevs={'C';'N';'O';'S';'P';'H'};
    +0086 testCheck.elements.names={'carbon';'nitrogen';'oxygen';'sulfur';'phosphorus';'hydrogen'};
    +0087 testCheck.leftComp=[44,14,31,1,5,62];
    +0088 testCheck.rightComp=[44,14,31,1,5,62];
    +0089 
    +0090 verifyEqual(testCase,testOut,testCheck)
    +0091 end
    +0092 
    +0093 function getAllowedBoundsTest(testCase)
    +0094 %Load the model in RAVEN format
    +0095 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0096 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0097 
    +0098 
    +0099 [testOut.min, testOut.max, testOut.flag]=getAllowedBounds(model,[1:10]);
    +0100 % Simplify output for later check, no need for high precision
    +0101 % testOut.min(abs(testOut.min)<1e-10)=0;
    +0102 % testOut.min=single(testOut.min);
    +0103 % testOut.max(abs(testOut.max)<1e-10)=0;
    +0104 % testOut.max=single(testOut.max);
    +0105 
    +0106 testCheck.min=[-20;-20;-20;0;0;-20;0;0;-10;-20];
    +0107 testCheck.max=[0;0;0;20;20;0;166.61000;20;0;0];
    +0108 testCheck.flag=[1,1;1,1;1,1;1,1;1,1;1,1;1,1;1,1;1,1;1,1];
    +0109 
    +0110 verifyEqual(testCase,testOut,testCheck,'AbsTol',1e-4)
    +0111 end
    +0112 
    +0113 function getEssentialRxnsTest(testCase)
    +0114 %Load the model in RAVEN format
    +0115 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0116 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0117 
    +0118 [testOut.r, testOut.i]=getEssentialRxns(model);
    +0119 
    +0120 testCheck.r={'EX_glc';'GLCpts'};
    +0121 testCheck.i=[28;50];
    +0122 verifyEqual(testCase,testOut,testCheck)
    +0123 end
    +
    Generated by m2html © 2005
    + + \ No newline at end of file diff --git a/doc/testing/unit_tests/modelConversionTests.html b/doc/testing/unit_tests/modelConversionTests.html new file mode 100644 index 00000000..269e71e1 --- /dev/null +++ b/doc/testing/unit_tests/modelConversionTests.html @@ -0,0 +1,75 @@ + + + + Description of modelConversionTests + + + + + + + + + +
    Home > testing > unit_tests > modelConversionTests.m
    + + + +

    modelConversionTests +

    + +

    PURPOSE ^

    +
    run this test case with the command
    + +

    SYNOPSIS ^

    +
    function tests = modelConversionTests
    + +

    DESCRIPTION ^

    +
    run this test case with the command
    +results = runtests('modelConversionTests.m')
    + + +

    CROSS-REFERENCE INFORMATION ^

    +This function calls: + +This function is called by: + + + +

    SUBFUNCTIONS ^

    + + +

    SOURCE CODE ^

    +
    0001 %run this test case with the command
    +0002 %results = runtests('modelConversionTests.m')
    +0003 function tests = modelConversionTests
    +0004 tests = functiontests(localfunctions);
    +0005 end
    +0006 
    +0007 function ravenCobraWrapperTest(testCase)
    +0008 %This function tests the ravenCobraWrapper function by going through a full
    +0009 %cycle RAVEN -> COBRA -> RAVEN, and the model should be (near) identical
    +0010 %(only annotation field should be lost).
    +0011 
    +0012 %Load the model in RAVEN format
    +0013 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0014 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0015 
    +0016 %Prevent writing of messages to command window
    +0017 evalc('modelCobra=ravenCobraWrapper(model);');
    +0018 evalc('modelRaven=ravenCobraWrapper(modelCobra);');
    +0019 
    +0020 %We know that the annotation field is lost
    +0021 modelNoAnnot=rmfield(model,'annotation');
    +0022 
    +0023 %Check that the actual model is the same as the expected model
    +0024 verifyEqual(testCase,modelRaven,modelNoAnnot)
    +0025 end
    +
    Generated by m2html © 2005
    + + \ No newline at end of file diff --git a/doc/testing/unit_tests/modelCurationTests.html b/doc/testing/unit_tests/modelCurationTests.html new file mode 100644 index 00000000..3f4b0b7e --- /dev/null +++ b/doc/testing/unit_tests/modelCurationTests.html @@ -0,0 +1,505 @@ + + + + Description of modelCurationTests + + + + + + + + + +
    Home > testing > unit_tests > modelCurationTests.m
    + + + +

    modelCurationTests +

    + +

    PURPOSE ^

    +
    run this test case with the command
    + +

    SYNOPSIS ^

    +
    function tests = modelCurationTests
    + +

    DESCRIPTION ^

    +
    run this test case with the command
    +results = runtests('modelCurationTests.m')
    + + +

    CROSS-REFERENCE INFORMATION ^

    +This function calls: + +This function is called by: + + + +

    SUBFUNCTIONS ^

    + + +

    SOURCE CODE ^

    +
    0001 %run this test case with the command
    +0002 %results = runtests('modelCurationTests.m')
    +0003 function tests = modelCurationTests
    +0004 tests = functiontests(localfunctions);
    +0005 end
    +0006 
    +0007 function addExchangeRxnsTest(testCase)
    +0008 sourceDir = fileparts(which(mfilename));
    +0009 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0010 
    +0011 modelNew=addExchangeRxns(model,'both','6pgl_c');
    +0012 
    +0013 %Perform the curation manually for comparison
    +0014 modelManual=model;
    +0015 modelManual.rxns(end+1)={'EXC_BOTH_6pgl_c'};
    +0016 modelManual.lb(end+1)=-1000;
    +0017 modelManual.ub(end+1)=1000;
    +0018 modelManual.c(end+1)=0;
    +0019 modelManual.rev(end+1)=1;
    +0020 modelManual.rxnNames(end+1)={'6-phospho-D-glucono-1,5-lactone exchange (BOTH)'};
    +0021 modelManual.grRules(end+1)={''};
    +0022 modelManual.eccodes(end+1)={''};
    +0023 modelManual.rxnGeneMat(end+1,:)=sparse(zeros(1,numel(modelManual.genes)));
    +0024 modelManual.S(:,end+1)=sparse(zeros(numel(modelManual.mets),1));
    +0025 modelManual.S(5,end)=-1;
    +0026 
    +0027 verifyEqual(testCase,modelNew,modelManual)
    +0028 end
    +0029 
    +0030 function addTransportTest(testCase)
    +0031 sourceDir = fileparts(which(mfilename));
    +0032 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0033 
    +0034 evalc('modelNew=addTransport(model,''c'',''e'',{''6-phospho-D-glucono-1,5-lactone''},false,false,''test_'');');
    +0035 
    +0036 %Perform the curation manually for comparison
    +0037 modelManual=model;
    +0038 modelManual.rxns(end+1)={'test_0001'};
    +0039 modelManual.lb(end+1)=0;
    +0040 modelManual.ub(end+1)=Inf;
    +0041 modelManual.c(end+1)=0;
    +0042 modelManual.rev(end+1)=0;
    +0043 modelManual.rxnNames(end+1)={'6-phospho-D-glucono-1,5-lactone transport, Cytoplasm-Extraorganism'};
    +0044 modelManual.grRules(end+1)={''};
    +0045 modelManual.eccodes(end+1)={''};
    +0046 modelManual.rxnGeneMat(end+1,:)=sparse(zeros(1,numel(modelManual.genes)));
    +0047 
    +0048 modelManual.S(:,end+1)=sparse(zeros(numel(modelManual.mets),1));
    +0049 modelManual.S(end+1,:)=sparse(zeros(1,numel(modelManual.rxns)));
    +0050 modelManual.S([5,73],end)=[-1,1];
    +0051 
    +0052 modelManual.mets(end+1)={'m_0001'};
    +0053 modelManual.metNames(end+1)={'6-phospho-D-glucono-1,5-lactone'};
    +0054 modelManual.metMiriams(end+1)=modelManual.metMiriams(5);
    +0055 modelManual.b(end+1)=[0];
    +0056 modelManual.metFormulas(end+1)={'C6H9O9P'};
    +0057 modelManual.metComps(end+1)=[2];
    +0058 
    +0059 verifyEqual(testCase,modelNew,modelManual)
    +0060 end
    +0061 
    +0062 function addGenesRavenTest(testCase)
    +0063 sourceDir = fileparts(which(mfilename));
    +0064 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0065 
    +0066 genesToAdd.genes={'testgene1','testgene2'};
    +0067 genesToAdd.geneShortNames={'short1','short2'};
    +0068 genesToAdd.geneMiriams{1}=struct('name',{{'testDB1';'testDB2'}},'value',...
    +0069     {{'testValue1';'testValue2'}});
    +0070 genesToAdd.geneMiriams{2}=struct('name',{{'testDB2';'testDB1'}},'value',...
    +0071     {{'testValue2';'testValue1'}});
    +0072 
    +0073 modelNew=addGenesRaven(model,genesToAdd);
    +0074 
    +0075 %Perform the curation manually for comparison
    +0076 modelManual=model;
    +0077 modelManual.geneMiriams(1:numel(modelManual.genes),1)={[]};
    +0078 modelManual.genes(end+1:end+2)=genesToAdd.genes;
    +0079 modelManual.geneShortNames(end+1:end+2)=genesToAdd.geneShortNames;
    +0080 modelManual.rxnGeneMat(:,end+1:end+2)=sparse(zeros(numel(modelManual.rxns),2));
    +0081 modelManual.geneMiriams(end+1:end+2)=genesToAdd.geneMiriams;
    +0082 verifyEqual(testCase,modelNew,modelManual)
    +0083 end
    +0084 
    +0085 function removeGenesTest(testCase)
    +0086 sourceDir = fileparts(which(mfilename));
    +0087 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0088 
    +0089 modelNew=removeGenes(model,'b1817',true,true,false);
    +0090 
    +0091 %Perform the curation manually for comparison
    +0092 modelManual=model;
    +0093 modelManual.genes(54)=[];
    +0094 modelManual.geneShortNames(54)=[];
    +0095 modelManual.rxnGeneMat(:,54)=[];
    +0096 modelManual.rxnGeneMat(45,:)=[];
    +0097 modelManual.grRules(50)={'(b2415 and b1621 and b2417 and b2416) or (b2415 and b2417 and b2416 and b1101)'};
    +0098 modelManual.grRules(45)=[];
    +0099 modelManual.rxns(45)=[];
    +0100 modelManual.rxnNames(45)=[];
    +0101 modelManual.lb(45)=[];
    +0102 modelManual.ub(45)=[];
    +0103 modelManual.c(45)=[];
    +0104 modelManual.rev(45)=[];
    +0105 modelManual.S(:,45)=[];
    +0106 modelManual.eccodes(45)=[];
    +0107 verifyEqual(testCase,modelNew,modelManual)
    +0108 end
    +0109 
    +0110 function addMetsTest(testCase)
    +0111 sourceDir = fileparts(which(mfilename));
    +0112 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0113 
    +0114 metsToAdd.metNames={'metaboliteName','3-Phospho-D-glycerate'};
    +0115 metsToAdd.compartments={'c','e'};
    +0116 metsToAdd.metCharges=[2,0];
    +0117 metsToAdd.metNotes={'this is just a test','another one'};
    +0118 metsToAdd.metMiriams{1}=struct('name',{{'testDB1';'testDB2'}},'value',...
    +0119     {{'testValue1';'testValue2'}});
    +0120 metsToAdd.metMiriams{2}=struct('name',{{'testDB1'}},'value',...
    +0121     {{'testValue1'}});
    +0122 
    +0123 evalc('modelNew=addMets(model,metsToAdd,true);');
    +0124 
    +0125 %Perform the curation manually for comparison
    +0126 modelManual=model;
    +0127 modelManual.metNotes(1:numel(modelManual.mets),1)={''};
    +0128 modelManual.metCharges(1:numel(modelManual.mets),1)=NaN(numel(modelManual.mets),1);
    +0129 modelManual.mets(end+1:end+2)={'m_0001','m_0002'};
    +0130 modelManual.metNames(end+1:end+2)=metsToAdd.metNames;
    +0131 modelManual.metNotes(end+1:end+2)=metsToAdd.metNotes;
    +0132 modelManual.metMiriams(end+1:end+2)=metsToAdd.metMiriams;
    +0133 modelManual.metCharges(end+1:end+2)=[2,NaN];
    +0134 modelManual.b(end+1:end+2)=[0,0];
    +0135 modelManual.metFormulas(end+1:end+2)={'','C3H4O7P'};
    +0136 modelManual.metComps(end+1:end+2)=[1,2];
    +0137 modelManual.S(end+1:end+2,:)=sparse(zeros(2,numel(modelManual.rxns)));
    +0138 
    +0139 verifyEqual(testCase,modelManual,modelNew)
    +0140 end
    +0141 
    +0142 function removeMetsTest(testCase)
    +0143 sourceDir = fileparts(which(mfilename));
    +0144 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0145 
    +0146 modelNew=removeMets(model,'Acetate',true,true,true,true);
    +0147 
    +0148 %Perform the curation manually for comparison
    +0149 modelManual=model;
    +0150 modelManual.mets(6:7)=[];
    +0151 modelManual.metNames(6:7)=[];
    +0152 modelManual.metMiriams(6:7)=[];
    +0153 modelManual.b(6:7)=[];
    +0154 modelManual.metFormulas(6:7)=[];
    +0155 modelManual.metComps(6:7)=[];
    +0156 modelManual.S(6:7,:)=[];
    +0157 
    +0158 modelManual.rxnGeneMat(20,:)=[];
    +0159 modelManual.grRules(20)=[];
    +0160 modelManual.rxns(20)=[];
    +0161 modelManual.rxnNames(20)=[];
    +0162 modelManual.lb(20)=[];
    +0163 modelManual.ub(20)=[];
    +0164 modelManual.c(20)=[];
    +0165 modelManual.rev(20)=[];
    +0166 modelManual.S(:,20)=[];
    +0167 modelManual.eccodes(20)=[];
    +0168 verifyEqual(testCase,modelNew,modelManual)
    +0169 end
    +0170 
    +0171 function addRxnsTest(testCase)
    +0172 sourceDir = fileparts(which(mfilename));
    +0173 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0174 rxnsToAdd.rxns='test1';
    +0175 rxnsToAdd.equations='2-Oxoglutarate => TEST';
    +0176 rxnsToAdd.rxnNames={'testRxn1'}; % test cell array
    +0177 rxnsToAdd.rxnMiriams{1}=struct('name',{{'testDB1';'testDB2'}},'value',...
    +0178     {{'testValue1';'testValue2'}});
    +0179 rxnsToAdd.grRules="b0008"; % test string
    +0180 evalc('modelNew=addRxns(model,rxnsToAdd,2,''c'',true);');
    +0181 
    +0182 rxnsToAdd.rxns='test2';
    +0183 rxnsToAdd=rmfield(rxnsToAdd,'equations');
    +0184 rxnsToAdd.mets={{'6pgl_c','atp_c'}};
    +0185 rxnsToAdd.stoichCoeffs=[[-1,2]];
    +0186 rxnsToAdd.lb=-1000;
    +0187 rxnsToAdd.grRules='test';
    +0188 evalc('modelNew=addRxns(modelNew,rxnsToAdd,1,''c'',true,true);');
    +0189 
    +0190 %Perform the curation manually for comparison
    +0191 modelManual=model;
    +0192 
    +0193 modelManual.rxnMiriams=cell(numel(modelManual.rxns),1);
    +0194 modelManual.rxns(end+1:end+2)={'test1';'test2'};
    +0195 modelManual.mets(end+1)={'m_0001'};
    +0196 modelManual.S(end+1,:)=zeros(1,numel(modelManual.rxns)-2);
    +0197 modelManual.S(:,end+1:end+2)=zeros(numel(modelManual.mets),2);
    +0198 modelManual.S(end,96)=1;
    +0199 modelManual.S([14,73],end-1)=[-1,1];
    +0200 modelManual.S([5,17],end)=[-1,2];
    +0201 modelManual.lb(end+1:end+2)=[0;-1000];
    +0202 modelManual.ub(end+1:end+2)=[Inf;Inf];
    +0203 modelManual.rev(end+1:end+2)=[0;1];
    +0204 modelManual.c(end+1:end+2)=[0;0];
    +0205 modelManual.b(end+1)=[0];
    +0206 modelManual.rxnNames(end+1:end+2)={'testRxn1';'testRxn1'};
    +0207 modelManual.grRules(end+1:end+2)={'b0008';'test'};
    +0208 
    +0209 modelManual.rxnGeneMat(end+1:end+2,:)=zeros(2,numel(modelManual.genes));
    +0210 modelManual.rxnGeneMat(:,end+1)=zeros(numel(modelManual.rxns),1);
    +0211 modelManual.rxnGeneMat(97,end)=1;
    +0212 modelManual.rxnGeneMat(end-1,1)=1;
    +0213 modelManual.rxnGeneMat(end,138)=1;
    +0214 
    +0215 modelManual.eccodes(end+1:end+2)={'';''};
    +0216 modelManual.genes(end+1)={'test'};
    +0217 modelManual.geneShortNames(end+1)={''};
    +0218 modelManual.metNames(end+1)={'TEST'};
    +0219 modelManual.metComps(end+1)=[1];
    +0220 modelManual.metFormulas(end+1)={''};
    +0221 modelManual.metMiriams(end+1)={[]};
    +0222 modelManual.rxnMiriams(end+1:end+2)={struct('name',{{'testDB1';'testDB2'}},'value',...
    +0223     {{'testValue1';'testValue2'}})};
    +0224 
    +0225 verifyEqual(testCase,modelManual,modelNew)
    +0226 end
    +0227 
    +0228 function removeReactionsTest(testCase)
    +0229 sourceDir = fileparts(which(mfilename));
    +0230 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0231 
    +0232 modelNew=removeMets(model,'Acetate',true,true,true,true);
    +0233 
    +0234 %Perform the curation manually for comparison
    +0235 modelManual=model;
    +0236 modelManual.mets(6:7)=[];
    +0237 modelManual.metNames(6:7)=[];
    +0238 modelManual.metMiriams(6:7)=[];
    +0239 modelManual.b(6:7)=[];
    +0240 modelManual.metFormulas(6:7)=[];
    +0241 modelManual.metComps(6:7)=[];
    +0242 modelManual.S(6:7,:)=[];
    +0243 
    +0244 modelManual.rxnGeneMat(20,:)=[];
    +0245 modelManual.grRules(20)=[];
    +0246 modelManual.rxns(20)=[];
    +0247 modelManual.rxnNames(20)=[];
    +0248 modelManual.lb(20)=[];
    +0249 modelManual.ub(20)=[];
    +0250 modelManual.c(20)=[];
    +0251 modelManual.rev(20)=[];
    +0252 modelManual.S(:,20)=[];
    +0253 modelManual.eccodes(20)=[];
    +0254 verifyEqual(testCase,modelNew,modelManual)
    +0255 end
    +0256 
    +0257 function getMetsInCompTest(testCase)
    +0258 %Load the model in RAVEN format
    +0259 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0260 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0261 
    +0262 evalc('[testOut.I, testOut.metNames]=getMetsInComp(model,''e'');');
    +0263 
    +0264 testCheck.I=[false;false;false;false;false;false;true;false;true;false;false;false;false;false;true;false;false;false;false;true;false;false;false;false;true;false;false;false;true;true;false;true;false;false;true;false;true;false;true;false;false;true;false;true;false;false;true;false;true;false;false;false;false;false;true;false;true;false;false;false;true;false;true;false;false;false;false;false;false;true;false;false];
    +0265 testCheck.metNames={'Acetate';'Acetaldehyde';'2-Oxoglutarate';'CO2';'Ethanol';'Formate';'D-Fructose';'Fumarate';'D-Glucose';'L-Glutamine';'L-Glutamate';'H2O';'H+';'D-Lactate';'L-Malate';'Ammonium';'O2';'Phosphate';'Pyruvate';'Succinate'};
    +0266 verifyEqual(testCase,testOut,testCheck)
    +0267 end
    +0268 
    +0269 function getRxnsInCompTest(testCase)
    +0270 %Load the model in RAVEN format
    +0271 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0272 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0273 
    +0274 evalc('[testOut.I, testOut.rxnNames]=getRxnsInComp(model,''e'');');
    +0275 
    +0276 testCheck.I=[20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39];
    +0277 testCheck.rxnNames={'Acetate exchange';'Acetaldehyde exchange';'2-Oxoglutarate exchange';'CO2 exchange';'Ethanol exchange';'Formate exchange';'D-Fructose exchange';'Fumarate exchange';'D-Glucose exchange';'L-Glutamine exchange';'L-Glutamate exchange';'H+ exchange';'H2O exchange';'D-lactate exchange';'L-Malate exchange';'Ammonia exchange';'O2 exchange';'Phosphate exchange';'Pyruvate exchange';'Succinate exchange'};
    +0278 verifyEqual(testCase,testOut,testCheck)
    +0279 end
    +0280 
    +0281 function getAllRxnsFromGenesTest(testCase)
    +0282 %Load the model in RAVEN format
    +0283 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0284 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0285 evalc('testOut=getAllRxnsFromGenes(model,''ACONTa'');');
    +0286 
    +0287 testCheck={'ACONTa';'ACONTb'};
    +0288 verifyEqual(testCase,testOut,testCheck)
    +0289 end
    +0290 
    +0291 function changeRxnsTest(testCase)
    +0292 %Load the model in RAVEN format
    +0293 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0294 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0295 
    +0296 evalc('modelNew=changeRxns(model,''ACKr'',''2-Oxoglutarate => TEST'',2,''c'',true);');
    +0297 
    +0298 %Perform the curation manually for comparison
    +0299 modelManual=model;
    +0300 
    +0301 modelManual.mets(end+1)={'m_0001'};
    +0302 modelManual.S(end+1,:)=zeros(1,numel(modelManual.rxns));
    +0303 modelManual.S(:,3)=0;
    +0304 modelManual.S([14,73],3)=[-1,1];
    +0305 
    +0306 modelManual.metNames(end+1)={'TEST'};
    +0307 modelManual.metComps(end+1)=[1];
    +0308 modelManual.metFormulas(end+1)={''};
    +0309 modelManual.metMiriams(end+1)={[]};
    +0310 modelManual.b(end+1)=[0];
    +0311 modelManual.rev(3)=[0];
    +0312 
    +0313 verifyEqual(testCase,modelNew,modelManual)
    +0314 end
    +0315 
    +0316 function removeBadRxnsTest(testCase)
    +0317 %Load the model in RAVEN format
    +0318 sourceDir=fileparts(fileparts(fileparts(which(mfilename))));
    +0319 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model');
    +0320 
    +0321 [~,exchRxns]=getExchangeRxns(model);
    +0322 modelNew=model;
    +0323 
    +0324 modelNew.lb(exchRxns)=[0];
    +0325 modelNew.ub(exchRxns)=[0];
    +0326 modelNew.lb(modelNew.lb>0)=0;
    +0327 modelNew.S(17,:)=1;
    +0328 [~, testOut]=removeBadRxns(modelNew);
    +0329 evalc('[~, testOut]=removeBadRxns(modelNew,3,modelNew.metComps==2);');
    +0330 
    +0331 import matlab.unittest.constraints.AnyCellOf;
    +0332 import matlab.unittest.constraints.ContainsSubstring;
    +0333 verifyThat(testCase,AnyCellOf({'SUCDi','FRD7'}),ContainsSubstring(testOut{:}),'test')
    +0334 %Either SUCDi or FRD7 should be given as output
    +0335 end
    +0336 
    +0337 function changeGrRulesTest(testCase)
    +0338 sourceDir = fileparts(which(mfilename));
    +0339 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0340 
    +0341 modelNew=changeGrRules(model,{'ACKr','ACONTa'},{'b2296 and b1849';'b1849'},true);
    +0342 modelNew=changeGrRules(modelNew,'ACONTa','b1849',false);
    +0343 
    +0344 %Perform the curation manually for comparison
    +0345 modelManual=model;
    +0346 modelManual.grRules(3:4)={'b2296 and b1849';'b1849 or b1849'};
    +0347 modelManual.rxnGeneMat(3:4,:)=0;
    +0348 modelManual.rxnGeneMat(3,[57,76])=1;
    +0349 modelManual.rxnGeneMat(4,57)=1;
    +0350 
    +0351 verifyEqual(testCase,modelNew,modelManual)
    +0352 end
    +0353 
    +0354 function copyToCompsTest(testCase)
    +0355 sourceDir = fileparts(which(mfilename));
    +0356 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0357 
    +0358 modelNew=copyToComps(model,{'p','e'},'ACKr');
    +0359 
    +0360 %Perform the curation manually for comparison
    +0361 modelManual=model;
    +0362 
    +0363 modelManual.rxns(end+1:end+2)={'ACKr_p';'ACKr_e'};
    +0364 modelManual.mets(end+1:end+7)={'ac_c_p';'actp_c_p';'adp_c_p';'atp_c_p';'actp_c_e';'adp_c_e';'atp_c_e'};
    +0365 modelManual.S(end+1:end+7,:)=zeros(7,numel(modelManual.rxns)-2);
    +0366 modelManual.S(:,end+1:end+2)=zeros(numel(modelManual.mets),2);
    +0367 
    +0368 modelManual.S([73,74,75,76],end-1)=[-1,1,1,-1];
    +0369 modelManual.S([7,77,78,79],end)=[-1,1,1,-1];
    +0370 
    +0371 modelManual.lb(end+1:end+2)=[-1000;-1000];
    +0372 modelManual.ub(end+1:end+2)=[1000;1000];
    +0373 modelManual.rev(end+1:end+2)=[1;1];
    +0374 modelManual.c(end+1:end+2)=[0;0];
    +0375 modelManual.rxnNames(end+1:end+2)={'acetate kinase';'acetate kinase'};
    +0376 modelManual.grRules(end+1:end+2)={'b2296 or b1849 or b3115';'b2296 or b1849 or b3115'};
    +0377 modelManual.eccodes(end+1:end+2)={'2.7.2.1';'2.7.2.1'};
    +0378 
    +0379 modelManual.rxnGeneMat(end+1:end+2,:)=zeros(2,numel(modelManual.genes));
    +0380 modelManual.rxnGeneMat(end-1:end,[57,76,97])=1;
    +0381 
    +0382 modelManual.metNames(end+1:end+7)={'Acetate';'Acetyl phosphate';'ADP';'ATP';'Acetyl phosphate';'ADP';'ATP'};
    +0383 modelManual.metComps(end+1:end+7)=[3;3;3;3;2;2;2];
    +0384 modelManual.metFormulas(end+1:end+7)={'C2H3O2';'C2H3O5P';'C10H12N5O10P2';'C10H12N5O13P3';'C2H3O5P';'C10H12N5O10P2';'C10H12N5O13P3'};
    +0385 modelManual.metMiriams(end+1:end+7)=modelManual.metMiriams([6,12,13,17,12,13,17]);
    +0386 modelManual.b(end+1:end+7)=[0];
    +0387 
    +0388 modelManual.comps(end+1)={'p'};
    +0389 modelManual.compNames(end+1)={'p'};
    +0390 
    +0391 verifyEqual(testCase,modelNew,modelManual)
    +0392 end
    +0393 
    +0394 function setExchangeBoundsTest(testCase)
    +0395 sourceDir = fileparts(which(mfilename));
    +0396 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0397 
    +0398 modelNew=setExchangeBounds(model,{'ac_e';'akg_e'},-500,500);
    +0399 
    +0400 %Perform the curation manually for comparison
    +0401 modelManual=model;
    +0402 
    +0403 exchRxns=[21;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39];
    +0404 modelManual.lb(exchRxns)=0;
    +0405 modelManual.lb([20,22])=-500;
    +0406 modelManual.ub([20,22])=500;
    +0407 
    +0408 verifyEqual(testCase,modelNew,modelManual)
    +0409 end
    +0410 
    +0411 function addRxnsGenesMetsTest(testCase)
    +0412 sourceDir = fileparts(which(mfilename));
    +0413 load(fullfile(sourceDir,'test_data','ecoli_textbook.mat'), 'model');
    +0414 
    +0415 sbmlFile=fullfile(sourceDir,'..','..','tutorial','empty.xml');
    +0416 evalc('modelEmpty=importModel(sbmlFile)'); % Repress warnings
    +0417 
    +0418 evalc('modelNew=addRxnsGenesMets(model,modelEmpty,''r1'',true);');
    +0419 
    +0420 %Perform the curation manually for comparison
    +0421 modelManual=model;
    +0422 
    +0423 modelManual.rxns(end+1)={'r1'};
    +0424 modelManual.mets(end+1:end+3)={'m1';'m2';'m3'};
    +0425 modelManual.S(end+1:end+3,:)=zeros(3,numel(modelManual.rxns)-1);
    +0426 modelManual.S(:,end+1)=zeros(numel(modelManual.mets),1);
    +0427 modelManual.S([42,73,74,75],end)=[-1,-1,1,1];
    +0428 
    +0429 modelManual.lb(end+1)=[0];
    +0430 modelManual.ub(end+1)=[1000];
    +0431 modelManual.rev(end+1)=[0];
    +0432 modelManual.c(end+1)=[0];
    +0433 modelManual.rxnNames(end+1)={'Breakdown of sucrose (invertase)'};
    +0434 modelManual.grRules(end+1)={'g1'};
    +0435 modelManual.eccodes(end+1)={''};
    +0436 modelManual.rxnNotes(1:numel(modelManual.rxns),1)={''};
    +0437 modelManual.rxnNotes(end)={'Added via addRxnsGenesMets()'};
    +0438 modelManual.rxnConfidenceScores(1:numel(modelManual.rxns),1)=NaN;
    +0439 modelManual.rxnConfidenceScores(end)=[0];
    +0440 
    +0441 modelManual.genes(end+1)={'g1'};
    +0442 modelManual.geneShortNames(end+1)={''};
    +0443 
    +0444 modelManual.rxnGeneMat(end+1,:)=zeros(1,numel(modelManual.genes)-1);
    +0445 modelManual.rxnGeneMat(:,end+1)=zeros(numel(modelManual.rxns),1);
    +0446 modelManual.rxnGeneMat(end,end)=1;
    +0447 
    +0448 modelManual.metNames(end+1:end+3)={'sucrose';'glucose';'fructose'};
    +0449 modelManual.metComps(end+1:end+3)=[2;2;2];
    +0450 modelManual.metFormulas(end+1:end+3)={'C12H22O11';'C6H12O6';'C6H12O6'};
    +0451 modelManual.metMiriams(end+1:end+3)={[];[];[]};
    +0452 modelManual.b(end+1:end+3)=[0];
    +0453 
    +0454 verifyEqual(testCase,modelNew,modelManual)
    +0455 end
    +
    Generated by m2html © 2005
    + + \ No newline at end of file diff --git a/doc/testing/unit_tests/solverTests.html b/doc/testing/unit_tests/solverTests.html new file mode 100644 index 00000000..43722631 --- /dev/null +++ b/doc/testing/unit_tests/solverTests.html @@ -0,0 +1,164 @@ + + + + Description of solverTests + + + + + + + + + +
    Home > testing > unit_tests > solverTests.m
    + + + +

    solverTests +

    + +

    PURPOSE ^

    +
    run this test case with the command
    + +

    SYNOPSIS ^

    +
    function tests = solverTests
    + +

    DESCRIPTION ^

    +
    run this test case with the command
    +results = runtests('solverTests.m')
    + + +

    CROSS-REFERENCE INFORMATION ^

    +This function calls: + +This function is called by: + + + +

    SUBFUNCTIONS ^

    + + +

    SOURCE CODE ^

    +
    0001 %run this test case with the command
    +0002 %results = runtests('solverTests.m')
    +0003 function tests = solverTests
    +0004 tests = functiontests(localfunctions);
    +0005 end
    +0006 
    +0007 function testGlpk(testCase)
    +0008 sourceDir = fileparts(which(mfilename));
    +0009 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0010 try
    +0011     oldSolver=getpref('RAVEN','solver');
    +0012 catch
    +0013 end
    +0014 setRavenSolver('glpk');
    +0015 
    +0016 try
    +0017     % Try all three types of flux minimization
    +0018     evalc('sol=solveLP(model,3);');    
    +0019     evalc('sol=solveLP(model,1);');
    +0020     evalc('sol=solveLP(model,0);');
    +0021 catch
    +0022     try
    +0023         setRavenSolver(oldSolver);
    +0024     catch
    +0025         rmpref('RAVEN','solver');
    +0026     end
    +0027     error('Solver not working')
    +0028 end
    +0029 try
    +0030     setRavenSolver(oldSolver);
    +0031 catch
    +0032     rmpref('RAVEN','solver');
    +0033 end
    +0034 
    +0035 load([sourceDir,'/test_data/solverTestOutput.mat'], 'solGlpk');
    +0036 %Check that the actual model is the same as the expected model
    +0037 verifyEqual(testCase,sol,solGlpk,'AbsTol',1e-5)
    +0038 end
    +0039 
    +0040 function testGurobi(testCase)
    +0041 if exist('gurobi','file')~=3
    +0042     error('Gurobi not installed or cannot be found in MATLAB path, test skipped')
    +0043 end
    +0044 sourceDir = fileparts(which(mfilename));
    +0045 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0046 try
    +0047     oldSolver=getpref('RAVEN','solver');
    +0048 catch
    +0049 end
    +0050 setRavenSolver('gurobi');
    +0051 
    +0052 try
    +0053     % Try all three types of flux minimization
    +0054     evalc('sol=solveLP(model,3);');    
    +0055     evalc('sol=solveLP(model,1);');
    +0056     evalc('sol=solveLP(model,0);');
    +0057 catch
    +0058     try
    +0059         setRavenSolver(oldSolver);
    +0060     catch
    +0061         rmpref('RAVEN','solver');
    +0062     end
    +0063     error('Solver not working')
    +0064 end
    +0065 try
    +0066     setRavenSolver(oldSolver);
    +0067 catch
    +0068     rmpref('RAVEN','solver');
    +0069 end
    +0070 
    +0071 load([sourceDir,'/test_data/solverTestOutput.mat'], 'solGurobi');
    +0072 %Check that the actual model is the same as the expected model
    +0073 verifyEqual(testCase,sol,solGurobi,'AbsTol',1e-5)
    +0074 end
    +0075 
    +0076 function testCobra(testCase)
    +0077 if exist('initCobraToolbox.m','file')~=2
    +0078     error('COBRA Toolbox not installed or cannot be found in MATLAB path, test skipped')
    +0079 end
    +0080 sourceDir = fileparts(which(mfilename));
    +0081 load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model');
    +0082 try
    +0083     oldSolver=getpref('RAVEN','solver');
    +0084 catch
    +0085 end
    +0086 global CBT_LP_SOLVER
    +0087 global CBT_MILP_SOLVER
    +0088 CBT_LP_SOLVER = 'glpk';
    +0089 CBT_MILP_SOLVER = 'glpk';
    +0090 setRavenSolver('cobra');
    +0091 
    +0092 try
    +0093     % Try all three types of flux minimization
    +0094     evalc('sol=solveLP(model,3);');    
    +0095     evalc('sol=solveLP(model,1);');
    +0096     evalc('sol=solveLP(model,0);');
    +0097 catch
    +0098     try
    +0099         setRavenSolver(oldSolver);
    +0100     catch
    +0101         rmpref('RAVEN','solver');
    +0102     end
    +0103     error('Solver not working')
    +0104 end
    +0105 try
    +0106     setRavenSolver(oldSolver);
    +0107 catch
    +0108     rmpref('RAVEN','solver');
    +0109 end
    +0110 
    +0111 load([sourceDir,'/test_data/solverTestOutput.mat'], 'solCobra');
    +0112 %Check that the actual model is the same as the expected model
    +0113 verifyEqual(testCase,sol,solCobra,'AbsTol',1e-5)
    +0114 end
    +
    Generated by m2html © 2005
    + + \ No newline at end of file diff --git a/external/getBlast.m b/external/getBlast.m index f9567527..1517846d 100755 --- a/external/getBlast.m +++ b/external/getBlast.m @@ -44,10 +44,10 @@ end %Everything should be cell arrays -organismID=cellstr(organismID); -fastaFile=cellstr(fastaFile); -modelIDs=cellstr(modelIDs); -refFastaFiles=cellstr(refFastaFiles); +organismID=convertCharArray(organismID); +fastaFile=convertCharArray(fastaFile); +modelIDs=convertCharArray(modelIDs); +refFastaFiles=convertCharArray(refFastaFiles); %Create blank structures for results blastStructure=[]; @@ -57,10 +57,8 @@ blastReport.dbHashes.pto={}; blastReport.blastTxtOutput={}; -%Get the directory for RAVEN Toolbox. This may not be the easiest or best -%way to do this -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(ST(I).file)); +%Get the directory for RAVEN Toolbox +ravenPath=findRAVENroot(); %Generate temporary names for BLAST databases and output files tmpDB=tempname; diff --git a/external/getBlastFromExcel.m b/external/getBlastFromExcel.m index 8e158515..2b023cdb 100755 --- a/external/getBlastFromExcel.m +++ b/external/getBlastFromExcel.m @@ -28,6 +28,7 @@ if ~(exist(blastFile,'file')==2) error('BLAST result file %s cannot be found',string(blastFile)); end +organismId=char(organismId); blastStructure=[]; diff --git a/external/getDiamond.m b/external/getDiamond.m index 92018543..c8ccdac9 100755 --- a/external/getDiamond.m +++ b/external/getDiamond.m @@ -45,20 +45,18 @@ end %Everything should be cell arrays -organismID=cellstr(organismID); -fastaFile=cellstr(fastaFile); -modelIDs=cellstr(modelIDs); -refFastaFiles=cellstr(refFastaFiles); +organismID=convertCharArray(organismID); +fastaFile=convertCharArray(fastaFile); +modelIDs=convertCharArray(modelIDs); +refFastaFiles=convertCharArray(refFastaFiles); %Create blank structures for results blastStructure=[]; diamondReport.dbHashes={}; diamondReport.diamondTxtOutput={}; -%Get the directory for RAVEN Toolbox. This may not be the easiest or best -%way to do this -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(ST(I).file)); +%Get the directory for RAVEN Toolbox. +ravenPath=findRAVENroot(); %Generate temporary names for DIAMOND databases and output files tmpDB=tempname; diff --git a/external/getWoLFScores.m b/external/getWoLFScores.m index ae19e940..d0a84f17 100755 --- a/external/getWoLFScores.m +++ b/external/getWoLFScores.m @@ -20,7 +20,8 @@ error('FASTA file %s cannot be found',string(inputFile)); end -if ~strcmp(kingdom,'animal') && ~strcmp(kingdom,'fungi') && ~strcmp(kingdom,'plant') +kingdom=char(kingdom); +if ~any(strcmp(kingdom,{'animal','fungi','plant'})) EM='Allowed kingdoms are "animal", "fungi", and "plant"'; dispEM(EM); end @@ -30,10 +31,8 @@ dispEM(EM); end -%Get the directory for RAVEN Toolbox. This may not be the easiest or best -%way to do this -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(ST(I).file)); +%Get the directory for RAVEN Toolbox +ravenPath=findRAVENroot(); %Temporary output name outFile=tempname; diff --git a/external/kegg/constructMultiFasta.m b/external/kegg/constructMultiFasta.m index daaec2aa..1e924698 100755 --- a/external/kegg/constructMultiFasta.m +++ b/external/kegg/constructMultiFasta.m @@ -14,6 +14,8 @@ function constructMultiFasta(model,sourceFile,outputDir) % % Usage: constructMultiFasta(model,sourceFile,outputDir) +sourceFile=char(sourceFile); +outputDir=char(outputDir); if ~(exist(sourceFile,'file')==2) error('FASTA file %s cannot be found',string(sourceFile)); end diff --git a/external/kegg/getGenesFromKEGG.m b/external/kegg/getGenesFromKEGG.m index 801a43e0..43ef0905 100755 --- a/external/kegg/getGenesFromKEGG.m +++ b/external/kegg/getGenesFromKEGG.m @@ -65,10 +65,11 @@ if nargin<1 keggPath='RAVEN/external/kegg'; +else + keggPath=char(keggPath); end -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(fileparts(ST(I).file))); +ravenPath=findRAVENroot(); genesFile=fullfile(ravenPath,'external','kegg','keggGenes.mat'); if exist(genesFile, 'file') fprintf(['Importing KEGG genes from ' strrep(genesFile,'\','/') '... ']); @@ -273,8 +274,7 @@ allKOs={}; %First check if the reactions have already been parsed -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(fileparts(ST(I).file))); +ravenPath=findRAVENroot; rxnsFile=fullfile(ravenPath,'external','kegg','keggRxns.mat'); if exist(rxnsFile, 'file') fprintf(['NOTE: Importing KEGG ORTHOLOGY list from ' strrep(rxnsFile,'\','/') '.\n']); diff --git a/external/kegg/getKEGGModelForOrganism.m b/external/kegg/getKEGGModelForOrganism.m index efdaed86..28fbf9d4 100755 --- a/external/kegg/getKEGGModelForOrganism.m +++ b/external/kegg/getKEGGModelForOrganism.m @@ -249,21 +249,22 @@ % keepGeneral,cutOff,minScoreRatioKO,minScoreRatioG,maxPhylDist,... % nSequences,seqIdentity) -if nargin<2 +if nargin<2 || isempty(fastaFile) fastaFile=[]; +else + fastaFile=char(fastaFile); end if nargin<3 dataDir=[]; +else + dataDir=char(dataDir); end -if nargin<4 - outDir=[]; -end -if isempty(outDir) +if nargin<4 || isempty(outDir) outDir=tempdir; %Delete all *.out files if any exist delete(fullfile(outDir,'*.out')); -elseif ~isstr(outDir) - error('outDir should be provided as string'); +else + outDir=char(outDir); end if nargin<5 keepSpontaneous=true; @@ -313,10 +314,8 @@ cores = regexp(cores{2},'^\d*','match'); cores = cores{1}; -%Get the directory for RAVEN Toolbox. This is to get the path to the third -%party software used -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(fileparts(ST(I).file))); +%Get the directory for RAVEN Toolbox. +ravenPath=findRAVENroot(); %Checking if dataDir is consistent. It must point to pre-trained HMMs set, %compatible with the the current RAVEN version. The user may have the diff --git a/external/kegg/getMetsFromKEGG.m b/external/kegg/getMetsFromKEGG.m index c480eeba..aeead0cd 100755 --- a/external/kegg/getMetsFromKEGG.m +++ b/external/kegg/getMetsFromKEGG.m @@ -64,10 +64,11 @@ if nargin<1 keggPath='RAVEN/external/kegg'; +else + keggPath=char(keggPath); end -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(fileparts(ST(I).file))); +ravenPath=findRAVENroot(); metsFile=fullfile(ravenPath,'external','kegg','keggMets.mat'); if exist(metsFile, 'file') fprintf(['Importing KEGG metabolites from ' strrep(metsFile,'\','/') '... ']); diff --git a/external/kegg/getModelFromKEGG.m b/external/kegg/getModelFromKEGG.m index 4e49e1c9..9233e259 100755 --- a/external/kegg/getModelFromKEGG.m +++ b/external/kegg/getModelFromKEGG.m @@ -46,6 +46,8 @@ if nargin<1 keggPath='RAVEN/external/kegg'; +else + keggPath=char(keggPath); end if nargin<2 keepSpontaneous=true; @@ -60,8 +62,7 @@ keepGeneral=false; end -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(fileparts(ST(I).file))); +ravenPath=findRAVENroot(); modelFile=fullfile(ravenPath,'external','kegg','keggModel.mat'); if exist(modelFile, 'file') && isNewestFile(ravenPath) fprintf(['Importing the global KEGG model from ' strrep(modelFile,'\','/') '... ']); diff --git a/external/kegg/getPhylDist.m b/external/kegg/getPhylDist.m index 8b208efe..7b83afbd 100755 --- a/external/kegg/getPhylDist.m +++ b/external/kegg/getPhylDist.m @@ -22,6 +22,8 @@ if nargin<1 keggPath='RAVEN/external/kegg'; +else + keggPath=char(keggPath); end if nargin<2 onlyInKingdom=false; @@ -29,8 +31,7 @@ %Check if the reactions have been parsed before and saved. If so, load the %model -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(fileparts(ST(I).file))); +ravenPath=findRAVENroot(); distFile=fullfile(ravenPath,'external','kegg','keggPhylDist.mat'); if exist(distFile, 'file') fprintf(['Importing the KEGG phylogenetic distance matrix from ' strrep(distFile,'\','/') '... ']); diff --git a/external/kegg/getRxnsFromKEGG.m b/external/kegg/getRxnsFromKEGG.m index db5d777a..01b52013 100755 --- a/external/kegg/getRxnsFromKEGG.m +++ b/external/kegg/getRxnsFromKEGG.m @@ -70,12 +70,13 @@ if nargin<1 keggPath='RAVEN/external/kegg'; +else + keggPath=char(keggPath); end %Check if the reactions have been parsed before and saved. If so, load the %model -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(fileparts(ST(I).file))); +ravenPath=findRAVENroot(); rxnsFile=fullfile(ravenPath,'external','kegg','keggRxns.mat'); if exist(rxnsFile, 'file') fprintf(['Importing KEGG reactions from ' strrep(rxnsFile,'\','/') '... ']); diff --git a/external/kegg/getWSLpath.m b/external/kegg/getWSLpath.m index b989caa4..d9a929b9 100644 --- a/external/kegg/getWSLpath.m +++ b/external/kegg/getWSLpath.m @@ -14,6 +14,9 @@ % Uses the WSL function 'wslpath' to translate the path. % % Usage: path=getWSLpath(path) -[~,path]=system(['wsl wslpath ''' path '''']); +[status,path]=system(['wsl wslpath ''' path '''']); +if status==-1 + error('Cannot get access to Windows Subsystem for Linux, check your WSL installation') +end path=path(1:end-1);% Remove final character (line-break) end diff --git a/external/makeFakeBlastStructure.m b/external/makeFakeBlastStructure.m index 66022cf0..43e25231 100755 --- a/external/makeFakeBlastStructure.m +++ b/external/makeFakeBlastStructure.m @@ -25,13 +25,15 @@ % running getModelFromHomology if nargin<3 - throw(MException('','All three parameters should be set')); + error('All three parameters should be set'); end +sourceModelID=char(sourceModelID); +getModelFor=char(getModelFor); % Check whether orthologList is a cell array, with two columns, and more % than 10 rows if (~iscell(orthologList) || ~(size(orthologList,2)==2) || ~(size(orthologList,1)>=10)) - throw(MException('','orthologList should be a cell array with two columns')); + error('orthologList should be a cell array with two columns'); end blastStructure(1).fromId=sourceModelID; diff --git a/external/metacyc/addSpontaneousRxns.m b/external/metacyc/addSpontaneousRxns.m index 0845fad7..f27e22c1 100755 --- a/external/metacyc/addSpontaneousRxns.m +++ b/external/metacyc/addSpontaneousRxns.m @@ -5,7 +5,6 @@ % % Input: % rxnList query list of reactions in cell array -% % metList query list of metabolites in cell array % % spontaneousRxnList reterieved spontaneous reactions associated to @@ -16,11 +15,8 @@ % % Usage: spontaneousRxnList=addSpontaneousRxns(rxnList, metList) -if nargin<2 - disp('Missing input arguments'); - return; -end - +metList=convertCharArray(metList); +rxnList=convertCharArray(rxnList); rxnList=unique(rxnList); % Create the matrix of MetaCyc pathways and spontaneous reactions diff --git a/external/metacyc/getEnzymesFromMetaCyc.m b/external/metacyc/getEnzymesFromMetaCyc.m index f31f58ca..48967b00 100755 --- a/external/metacyc/getEnzymesFromMetaCyc.m +++ b/external/metacyc/getEnzymesFromMetaCyc.m @@ -58,19 +58,24 @@ % A line that contains only '//' separates each object. +if nargin<1 + ravenPath=findRAVENroot(); + metacycPath=fullfile(ravenPath,'external','metacyc'); +else + metacycPath=char(metacycPath); +end + %Check if the enzymatic proteins have been parsed before and saved. If so, %load the model. -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(fileparts(ST(I).file))); -enzymesFile=fullfile(ravenPath,'external','metacyc','metaCycEnzymes.mat'); +enzymesFile=fullfile(metacycPath,'metaCycEnzymes.mat'); metaCycProteinFile='proteins.dat'; metaCycEnzrxnsFile='enzrxns.dat'; -if exist(enzymesFile, 'file') - fprintf(['Importing MetaCyc enzymes and reaction-enzyme association from ' strrep(enzymesFile,'\','/') '... ']); +try + (['Importing MetaCyc enzymes and reaction-enzyme association from ' strrep(enzymesFile,'\','/') '... ']); load(enzymesFile); fprintf('done\n'); -else +catch fprintf(['Cannot locate ' strrep(enzymesFile,'\','/') '\nNow try to generate it from local MetaCyc data files...\n']); if ~exist(fullfile(metacycPath,metaCycProteinFile),'file') || ~exist(fullfile(metacycPath,metaCycEnzrxnsFile),'file') EM=fprintf(['The files of enzymes or proteins cannot be located, and should be downloaded from MetaCyc.\n']); diff --git a/external/metacyc/getMetaCycModelForOrganism.m b/external/metacyc/getMetaCycModelForOrganism.m index 87be4cf0..c69bb097 100755 --- a/external/metacyc/getMetaCycModelForOrganism.m +++ b/external/metacyc/getMetaCycModelForOrganism.m @@ -30,9 +30,12 @@ % Usage: model=getMetaCycModelForOrganism(organismID,fastaFile,... % keepTransportRxns,keepUnbalanced,keepUndetermined,minScore,minPositives,useDiamond) +organismID=char(organismID); if nargin<2 EM='No query protein fasta file is specified'; dispEM(EM); +else + fastaFile=char(fastaFile); end if nargin<3 keepTransportRxns=false; @@ -81,15 +84,14 @@ model.c=metaCycModel.c; model.equations=metaCycModel.equations; -%Get the 'external' directory for RAVEN Toolbox. -[ST I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(ST(I).file)); +%Get the root directory for RAVEN Toolbox. +ravenPath=findRAVENroot(); %Generate blast strcture by either DIAMOND or BLASTP if useDiamond - blastStruc=getDiamond(organismID,fastaFile,{'MetaCyc'},fullfile(ravenPath,'metacyc','protseq.fsa')); + blastStruc=getDiamond(organismID,fastaFile,{'MetaCyc'},fullfile(ravenPath,'external','metacyc','protseq.fsa')); else - blastStruc=getBlast(organismID,fastaFile,{'MetaCyc'},fullfile(ravenPath,'metacyc','protseq.fsa')); + blastStruc=getBlast(organismID,fastaFile,{'MetaCyc'},fullfile(ravenPath,'external','metacyc','protseq.fsa')); end %Only look the query diff --git a/external/metacyc/getMetsFromMetaCyc.m b/external/metacyc/getMetsFromMetaCyc.m index 45b7e5ba..93fe6f52 100755 --- a/external/metacyc/getMetsFromMetaCyc.m +++ b/external/metacyc/getMetsFromMetaCyc.m @@ -57,9 +57,14 @@ % Check if the metabolites have been parsed before and saved. If so, load % the model. -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(fileparts(ST(I).file))); -metsFile=fullfile(ravenPath,'external','metacyc','metaCycMets.mat'); +if nargin<1 + ravenPath=findRAVENroot(); + metacycPath=fullfile(ravenPath,'external','metacyc'); +else + metacycPath=char(metacycPath); +end + +metsFile=fullfile(metacycPath,'metaCycMets.mat'); metaCycMetFile='compounds.dat'; if exist(metsFile, 'file') diff --git a/external/metacyc/getModelFromMetaCyc.m b/external/metacyc/getModelFromMetaCyc.m index 6dccc95a..c1e935c4 100755 --- a/external/metacyc/getModelFromMetaCyc.m +++ b/external/metacyc/getModelFromMetaCyc.m @@ -34,7 +34,10 @@ % Usage: getModelFromMetaCyc(metacycPath,keepTransportRxns,keepUnbalanced,keepUndetermined) if nargin<1 - metacycPath=''; + ravenPath=findRAVENroot(); + metacycPath=fullfile(ravenPath,'external','metacyc'); +else + metacycPath=char(metacycPath); end if nargin<2 keepTransportRxns=false; diff --git a/external/metacyc/getRxnsFromMetaCyc.m b/external/metacyc/getRxnsFromMetaCyc.m index 54b50a44..36e4a28e 100755 --- a/external/metacyc/getRxnsFromMetaCyc.m +++ b/external/metacyc/getRxnsFromMetaCyc.m @@ -68,7 +68,12 @@ % // % A line that contains only '//' separates each object. - +if nargin<1 + ravenPath=findRAVENroot(); + metacycPath=fullfile(ravenPath,'external','metacyc'); +else + metacycPath=char(metacycPath); +end if nargin<2 keepTransportRxns=false; end @@ -81,9 +86,7 @@ %Check if the reactions have been parsed before and saved. Directly load %the model if so. -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(fileparts(ST(I).file))); -rxnsFile=fullfile(ravenPath,'external','metacyc','metaCycRxns.mat'); +rxnsFile=fullfile(metacycPath,'metaCycRxns.mat'); metaCycRxnFile='reactions.dat'; metaCycPwyFile='pathway-links.dat'; diff --git a/external/metacyc/linkMetaCycKEGGRxns.m b/external/metacyc/linkMetaCycKEGGRxns.m index 11dc2165..ea70b4aa 100755 --- a/external/metacyc/linkMetaCycKEGGRxns.m +++ b/external/metacyc/linkMetaCycKEGGRxns.m @@ -98,9 +98,8 @@ rxnLinks=rmfield(rxnLinks,'check'); %Get the MetaCyc path and update the metaCycRxns.mat -[ST, I]=dbstack('-completenames'); -metaCycPath=fileparts(ST(I).file); -rxnsFile=fullfile(metaCycPath,'metaCycRxns.mat'); +ravenPath=findRAVENroot(); +rxnsFile=fullfile(ravenPath,'external','metacyc','metaCycRxns.mat'); save(rxnsFile,'metaCycRxns','rxnLinks','TRANSPORT','UNBALANCED','UNDETERMINED','isSpontaneous'); fprintf(['Reaction associations between MetaCyc and KEGG have been successfully updated!\n\n']); diff --git a/external/parseScores.m b/external/parseScores.m index 562060eb..9205ce8e 100755 --- a/external/parseScores.m +++ b/external/parseScores.m @@ -17,6 +17,8 @@ if nargin<2 predictor='wolf'; +else + predictor=char(predictor); end fid=fopen(inputFile,'r'); diff --git a/external/updateDocumentation.m b/external/updateDocumentation.m index beef0bf5..306b2a2d 100755 --- a/external/updateDocumentation.m +++ b/external/updateDocumentation.m @@ -6,8 +6,7 @@ function updateDocumentation() % Usage: updateDocumentation() %Get the RAVEN path -[ST, I]=dbstack('-completenames'); -[ravenDir,~,~]=fileparts(fileparts(ST(I).file)); +ravenDir=findRAVENroot(); %Make sure that RAVEN-provided m2html is used path(fullfile(ravenDir,'software','m2html'),path); %Get a non-redundant list of RAVEN subdirectories containing MATLAB diff --git a/hpa/parseHPA.m b/hpa/parseHPA.m index f26209b5..3c181c7d 100755 --- a/hpa/parseHPA.m +++ b/hpa/parseHPA.m @@ -40,6 +40,7 @@ version=19; %Change this and add code for more versions when the current HPA version is increased and the format is changed end +fileName=char(fileName); if ~(exist(fileName,'file')==2) error('HPA file %s cannot be found',string(fileName)); end diff --git a/hpa/parseHPArna.m b/hpa/parseHPArna.m index 147c146b..8051207c 100755 --- a/hpa/parseHPArna.m +++ b/hpa/parseHPArna.m @@ -26,6 +26,7 @@ version=19; end +fileName=char(fileName); if ~(exist(fileName,'file')==2) error('HPA file %s cannot be found', string(fileName)); end diff --git a/hpa/scoreModel.m b/hpa/scoreModel.m index 313e32ca..b397c244 100755 --- a/hpa/scoreModel.m +++ b/hpa/scoreModel.m @@ -61,15 +61,21 @@ end if nargin<5 celltype=[]; +else + celltype=char(celltype); end if nargin<6 noGeneScore=-2; end if nargin<7 multipleGeneScoring='best'; +else + multipleGeneScoring=char(multipleGeneScoring); end if nargin<8 multipleCellScoring='best'; +else + multipleCellScoring=char(multipleCellScoring); end if nargin<9 %The first four are for APE, the other ones for staining diff --git a/installation/addRavenToUserPath.m b/installation/addRavenToUserPath.m index 832f26fc..e409bf05 100755 --- a/installation/addRavenToUserPath.m +++ b/installation/addRavenToUserPath.m @@ -15,8 +15,7 @@ function addRavenToUserPath(overwrite) end % Get current RAVEN directory -[ST, I]=dbstack('-completenames'); -[ravenDir,~,~]=fileparts(fileparts(ST(I).file)); +ravenDir=findRAVENroot(); % Lists all subdirectories subpath=regexp(genpath(ravenDir),pathsep,'split'); diff --git a/installation/checkFunctionUniqueness.m b/installation/checkFunctionUniqueness.m index e13e540c..23855a3d 100755 --- a/installation/checkFunctionUniqueness.m +++ b/installation/checkFunctionUniqueness.m @@ -6,8 +6,7 @@ function checkFunctionUniqueness() % Usage: checkFunctionUniqueness() %Get the RAVEN path -[ST, I]=dbstack('-completenames'); -[ravenDir,~,~]=fileparts(fileparts(ST(I).file)); +ravenDir=findRAVENroot(); %Now getting all RAVEN functions recursively; temp_res1=dir([ravenDir '/*/*.m']); @@ -53,9 +52,10 @@ function checkFunctionUniqueness() end if hasConflicts - fprintf('It is strongly recommended to resolve conflicting functions as this may compromise RAVEN functionality\n'); + fprintf('Fail\n') + fprintf(' It is strongly recommended to resolve conflicting functions as this may compromise RAVEN functionality\n'); else - fprintf('OK\n'); + fprintf('Pass\n'); end end diff --git a/installation/checkInstallation.m b/installation/checkInstallation.m index 1f1ea3f2..15ed858b 100755 --- a/installation/checkInstallation.m +++ b/installation/checkInstallation.m @@ -24,138 +24,198 @@ function checkInstallation(develMode) [ST, I]=dbstack('-completenames'); [ravenDir,~,~]=fileparts(fileparts(ST(I).file)); +fprintf('\n*** THE RAVEN TOOLBOX ***\n\n'); %Print the RAVEN version if it is not the development version +fprintf([myStr(' > Checking RAVEN release:',40) '%f']) if exist(fullfile(ravenDir,'version.txt'), 'file') == 2 - fprintf(['\n*** THE RAVEN TOOLBOX v.' fgetl(fopen(fullfile(ravenDir,'version.txt'))) ' ***\n\n']); + fprintf([fgetl(fopen(fullfile(ravenDir,'version.txt'))) '\n']); fclose('all'); else - fprintf('\n*** THE RAVEN TOOLBOX - DEVELOPMENT VERSION ***\n\n'); + fprintf('DEVELOPMENT\n'); end - -fprintf(['MATLAB R' version('-release') ' detected\n\n']); - -fprintf('Checking if RAVEN is on the MATLAB path...\t\t\t\t\t\t\t\t\t'); -if ismember(ravenDir,paths) - fprintf('OK\n'); -else - fprintf('OK (just added)\n'); - subpath=regexp(genpath(ravenDir),pathsep,'split'); %List all subdirectories - pathsToKeep=cellfun(@(x) isempty(strfind(x,'.git')),subpath) & cellfun(@(x) isempty(strfind(x,'doc')),subpath); - addpath(strjoin(subpath(pathsToKeep),pathsep)); - savepath -end - -%Add the required classes to the static Java path if not already added -addJavaPaths(); - -excelFile=fullfile(ravenDir,'tutorial','empty.xlsx'); -xmlFile=fullfile(ravenDir,'tutorial','empty.xml'); -matFile=fullfile(ravenDir,'tutorial','empty.mat'); +fprintf([myStr(' > Checking MATLAB release:',40) '%f']) +fprintf([version('-release') '\n']) +fprintf([myStr(' > Set RAVEN in MATLAB path:',40) '%f']) +subpath=regexp(genpath(ravenDir),pathsep,'split'); %List all subdirectories +pathsToKeep=cellfun(@(x) isempty(strfind(x,'.git')),subpath) & cellfun(@(x) isempty(strfind(x,'doc')),subpath); +addpath(strjoin(subpath(pathsToKeep),pathsep)); +savepath +fprintf('Pass\n'); %Check if it is possible to parse an Excel file -fprintf('Checking if it is possible to parse a model in Microsoft Excel format...\t'); +fprintf('\n=== Model import and export ===\n'); +fprintf([myStr(' > Add Java paths for Excel format:',40) '%f']) try - importExcelModel(excelFile,false,false,true); - fprintf('OK\n'); + %Add the required classes to the static Java path if not already added + addJavaPaths(); + fprintf('Pass\n') catch - fprintf('Not OK\n'); + fprintf('Fail\n') end - -%Check if it is possible to import an SBML model using libSBML -fprintf('Checking if it is possible to import an SBML model using libSBML...\t\t\t'); +fprintf([myStr(' > Check libSBML version:',40) '%f']) try - importModel(xmlFile); + evalc('importModel(fullfile(ravenDir,''tutorial'',''empty.xml''))'); try libSBMLver=OutputSBML; % Only works in libSBML 5.17.0+ - fprintf('OK\n'); + fprintf([libSBMLver.libSBML_version_string '\n']); catch - fprintf(['Not OK\n\n'... - 'An older libSBML version was found, update to version 5.17.0 or higher\n'... - 'for a significant improvement of model import\n\n']); + fprintf('Fail\n') + fprintf(' An older libSBML version was found, update to version 5.17.0 or higher for a significant improvement of model import\n'); end catch - fprintf(['Not OK\nTo import SBML models, download libSBML from\n'... - 'http://sbml.org/Software/libSBML/Downloading_libSBML and add to MATLAB path\n']); + fprintf('Fail\n') + fprintf(' Download libSBML from http://sbml.org/Software/libSBML/Downloading_libSBML and add to MATLAB path\n'); +end +fprintf(' > Checking model import and export:\n') +res=runtests('importExportTests.m','OutputDetail',0); + +fprintf([myStr(' > Import Excel format:',40) '%f']) +if res(1).Passed == 1 + fprintf('Pass\n') +else + fprintf('Fail\n') +end + +fprintf([myStr(' > Export Excel format:',40) '%f']) +if res(3).Passed == 1 + fprintf('Pass\n') +else + fprintf('Fail\n') end -%Define values for keepSolver and workingSolvers, needed for solver -%functionality check -keepSolver=false; -workingSolvers=''; +fprintf([myStr(' > Import SBML format:',40) '%f']) +if res(2).Passed == 1 + fprintf('Pass\n') +else + fprintf('Fail\n') +end + +fprintf([myStr(' > Export SBML format:',40) '%f']) +if res(4).Passed == 1 + fprintf('Pass\n') +else + fprintf('Fail\n') +end + +if res(1).Passed~=1 && res(3).Passed~=1 && exist('vaderSentimentScores.m')==2 + fprintf([' > MATLAB Text Analytics Toolbox found. This should be\n'... + ' uninstalled if you want to read/write Excel files.\n'... + ' See RAVEN GitHub Issues page for instructions.\n']) +end + +%Check if it is possible to import an YAML model +% fprintf(' > Checking import of model in YAML format:\t\t\t'); +% try +% readYaml(ymlFile,true); +% fprintf('Pass\n'); +% catch +% fprintf('Fail\n'); +% end + +fprintf('\n=== Model solvers ===\n'); + %Get current solver. Set it to 'none', if it is not set -if ~ispref('RAVEN','solver') - fprintf('Solver found in preferences... NONE\n'); - setRavenSolver('none'); - curSolv=getpref('RAVEN','solver'); +fprintf(' > Checking for functional LP solvers:\n') +res=runtests('solverTests.m','OutputDetail',0); + +fprintf([myStr(' > glpk:',40) '%f']) +if res(1).Passed == 1 + fprintf('Pass\n') +else + fprintf('Fail\n') +end + +fprintf([myStr(' > gurobi:',40) '%f']) +if res(2).Passed == 1 + fprintf('Pass\n') else - curSolv=getpref('RAVEN','solver'); - fprintf(['Solver found in preferences... ',curSolv,'\n']); + fprintf('Fail\n') end -%Check if it is possible to solve an LP problem using different solvers -solver={'gurobi','cobra'}; +fprintf([myStr(' > cobra:',40) '%f']) +if res(3).Passed == 1 + fprintf('Pass\n') +else + fprintf('Fail\n') +end -for i=1:numel(solver) - fprintf(['Checking if it is possible to solve an LP problem using ',solver{i},'...\t\t\t']); - try - setRavenSolver(solver{i}); - load(matFile); - solveLP(emptyModel); - workingSolvers=strcat(workingSolvers,';',solver{i}); - fprintf('OK\n'); - if strcmp(curSolv,solver{i}) - keepSolver=true; - end - catch - fprintf('Not OK\n'); - end +fprintf(' > Checking for functional MILP solvers:\n') +res=runtests('fillGapsSmallTests.m','OutputDetail',0); + +fprintf([myStr(' > glpk:',40) '%f']) +if res(1).Passed == 1 + fprintf('Pass\n') +else + fprintf('Fail\n') end -if keepSolver - %The solver set in curSolv is functional, so the settings are restored - %to the ones which were set before running checkInstallation - setRavenSolver(curSolv); - fprintf(['Preferred solver... KEPT\nSolver saved as preference... ',curSolv,'\n\n']); -elseif ~isempty(workingSolvers) - %There are working solvers, but the none of them is the solver defined - %by curSolv. The first working solver is therefore set as RAVEN solver - workingSolvers=regexprep(workingSolvers,'^;',''); - workingSolvers=regexprep(workingSolvers,';.+$',''); - %Only one working solver should be left by now in workingSolvers - setRavenSolver(workingSolvers); - fprintf(['Preferred solver... NEW\nSolver saved as preference... ',workingSolvers,'\n\n']); +fprintf([myStr(' > gurobi:',40) '%f']) +if res(2).Passed == 1 + fprintf('Pass\n') else - %No functional solvers were found, so the setting is restored back to - %original - setRavenSolver(curSolv); - fprintf(['WARNING: No working solver was found!\n'... - 'Install the solver, set it using setRavenSolver(''solverName'') and run checkInstallation again\n'... - 'Available solverName options are ''gurobi'' and ''cobra''\n\n']); + fprintf('Fail\n') end -fprintf('Checking essential binary executables:\n'); +fprintf([myStr(' > cobra:',40) '%f']) +if res(3).Passed == 1 + fprintf('Pass\n') +else + fprintf('Fail\n') +end -fprintf('\tBLAST+... '); +fprintf([myStr(' > Set RAVEN solver:',40) '%f']) +try + oldSolver=getpref('RAVEN','solver'); + solverIdx=find(strcmp(oldSolver,{'glpk','gurobi','cobra'})); +catch + solverIdx=0; +end +% Do not change old solver if functional +if solverIdx~=0 && res(solverIdx).Passed == 1 + fprintf([oldSolver '\n']) +% Order of preference: gurobi > glpk > cobra +elseif res(2).Passed == 1 + fprintf('gurobi\n') + setRavenSolver('gurobi'); +elseif res(1).Passed == 1 + fprintf('glpk\n') + setRavenSolver('glpk'); +elseif res(3).Passed == 1 + fprintf('cobra\n') + setRavenSolver('cobra'); +else + fprintf('None, no functional solvers\n') + fprintf(' The glpk should always be working, check your RAVEN installation to make sure all files are present\n') +end + +fprintf('\n=== Essential binary executables ===\n'); +fprintf([myStr(' > Checking BLAST+:',40) '%f']) res=runtests('blastPlusTests.m','OutputDetail',0); interpretResults(res); -fprintf('\tDIAMOND... '); + +fprintf([myStr(' > Checking DIAMOND:',40) '%f']) res=runtests('diamondTests.m','OutputDetail',0); interpretResults(res); -fprintf('\tHMMER... '); + +fprintf([myStr(' > Checking HMMER:',40) '%f']) res=runtests('hmmerTests.m','OutputDetail',0); interpretResults(res); if develMode - fprintf('NOTE: Only fix these binaries if planning to use KEGG FTP dump files in getKEGGModelForOrganism\n'); - fprintf('\tCD-HIT... '); + fprintf('\n=== Development binary executables ===\n'); + fprintf('NOTE: These binaries are only required when using KEGG FTP dump files in getKEGGModelForOrganism\n'); + + fprintf([myStr(' > Checking CD-HIT:',40) '%f']) res=runtests('cdhitTests.m','OutputDetail',0); interpretResults(res); - fprintf('\tMAFFT... '); + + fprintf([myStr(' > Checking MAFFT:',40) '%f']) res=runtests('mafftTests.m','OutputDetail',0); interpretResults(res); end -fprintf('Checking whether RAVEN functions are non-redundant across MATLAB path...\t'); +fprintf('\n=== Compatibility ===\n'); +fprintf([myStr(' > Checking function uniqueness:',40) '%f']) checkFunctionUniqueness(); fprintf('\n*** checkInstallation complete ***\n\n'); @@ -163,8 +223,19 @@ function checkInstallation(develMode) function interpretResults(results) if results.Failed==0 && results.Incomplete==0 - fprintf('OK\n'); + fprintf('Pass\n'); +else + fprintf('Fail\n') + fprintf(' Download/compile the binary and rerun checkInstallation\n'); +end +end + +function str = myStr(InputStr,len) +str=InputStr; +lenDiff = len - length(str); +if lenDiff < 0 + warning('String too long'); else - fprintf('Not OK! Download/compile the binary and rerun checkInstallation\n'); + str = [str blanks(lenDiff)]; end end diff --git a/io/SBMLFromExcel.m b/io/SBMLFromExcel.m index 73111252..175f67ce 100755 --- a/io/SBMLFromExcel.m +++ b/io/SBMLFromExcel.m @@ -16,7 +16,8 @@ function SBMLFromExcel(fileName, outputFileName,toCOBRA,printWarnings) % % NOTE: This is just a wrapper function for importExcelModel, printModelStats % and exportModel. Use those functions directly for greater control. - +fileName=char(fileName); +outputFileName=char(outputFileName); if nargin<3 toCOBRA=false; end diff --git a/io/addJavaPaths.m b/io/addJavaPaths.m index 10bb8250..76b0821c 100755 --- a/io/addJavaPaths.m +++ b/io/addJavaPaths.m @@ -5,8 +5,7 @@ function addJavaPaths() %Get the path to Apache POI -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(ST(I).file)); +ravenPath=findRAVENroot(); poiPATH=fullfile(ravenPath,'software','apache-poi'); toAdd={fullfile(poiPATH,'dom4j-1.6.1.jar'); diff --git a/io/checkFileExistence.m b/io/checkFileExistence.m index 35152388..8596ba2c 100755 --- a/io/checkFileExistence.m +++ b/io/checkFileExistence.m @@ -1,4 +1,4 @@ -function files=checkFileExistence(files,fullOrTemp,allowSpace) +function files=checkFileExistence(files,fullOrTemp,allowSpace,checkExist) % checkFileExistence % Check whether files exist. If no full path is given a file should be % located in the current folder, which by default is appended to the @@ -14,13 +14,17 @@ % (opt, default 0) % allowSpace logical, whether 'space' character is allowed in the % path (opt, default true) +% checkExist logical, whether file existence should really be +% checked, as this function can also be used to return +% the full path to a new file (opt, default true). Can +% only be set to false if fullOrTemp is set to 1. % % Output: % files string or cell array of strings with updated paths if % fullOrTemp was set as 1 or 2, otherwise original paths % are returned % -% Usage: files=checkFileExistence(files,fullOrTemp,allowSpace) +% Usage: files=checkFileExistence(files,fullOrTemp,allowSpace,checkExist) if nargin<2 fullOrTemp = 0; @@ -28,10 +32,12 @@ if nargin<3 allowSpace = true; end - -if isstr(files) +if nargin<4 + checkExist = true; +end +files=convertCharArray(files); +if numel(files)==1 oneFile=true; - files={files}; else oneFile=false; end @@ -46,11 +52,13 @@ files(inCurrDir) = fullfile(cd,files(inCurrDir)); %Check existence -for i=1:numel(files) - if ~exist(files{i},'file') - error('File "%s" cannot be found\n',files{i}); - elseif allowSpace == false & strfind(files{i},' ') - error('File "%s" has an invalid space in the filename or path, please remove this before running this function\n',files{i}); +if checkExist + for i=1:numel(files) + if ~exist(files{i},'file') + error('File "%s" cannot be found\n',files{i}); + elseif allowSpace == false & strfind(files{i},' ') + error('File "%s" has an invalid space in the filename or path, please remove this before running this function\n',files{i}); + end end end diff --git a/io/exportForGit.m b/io/exportForGit.m index c273929d..6da3e10f 100755 --- a/io/exportForGit.m +++ b/io/exportForGit.m @@ -1,4 +1,4 @@ -function out=exportForGit(model,prefix,path,formats,mainBranchFlag,subDirs) +function out=exportForGit(model,prefix,path,formats,mainBranchFlag,subDirs,cobraText) % exportForGit % Generates a directory structure and populates this with model files, ready % to be commited to a Git(Hub) maintained model repository. Writes the model @@ -13,7 +13,7 @@ % formats cell array of strings specifying in what file formats % the model should be exported (opt, default to all % formats as {'mat', 'txt', 'xlsx', 'xml', 'yml'}) -% mainBranchFlag logical, if true, function will error if RAVEN (and +% mainBranchFlag logical, if true, function will error if RAVEN (and % COBRA if detected) is/are not on the main branch. % (opt, default false) % subDirs logical, whether model files for each file format @@ -21,8 +21,15 @@ % 'model' as parent directory, in accordance to the % standard-GEM repository format. If false, all files % are stored in the same folder. (opt, default true) +% cobraText logical, whether the txt file should be in COBRA +% Toolbox format using metabolite IDs, instead of +% metabolite names and compartments. (opt, default +% false) % % Usage: exportForGit(model,prefix,path,formats,mainBranchFlag) +if nargin<7 + cobraText=false; +end if nargin<6 subDirs=true; end @@ -31,9 +38,8 @@ end if nargin<4 || isempty(formats) formats={'mat', 'txt', 'xlsx', 'xml', 'yml'}; -end -if ischar(formats) - formats={formats}; +else + formats=convertCharArray(formats); end if any(~ismember(formats, {'mat', 'txt', 'xlsx', 'xml', 'yml'})) EM='Unknown file format defined. Only mat, txt, xlsx, xml and yml are allowed file formats.'; @@ -41,9 +47,13 @@ end if nargin<3 path='.'; +else + path=char(path); end if nargin<2 prefix='model'; +else + prefix=char(prefix); end %Sort reactions, metabolites and genes alphabetically @@ -54,6 +64,8 @@ COBRAver = getToolboxVersion('COBRA','initCobraToolbox.m',mainBranchFlag); %Retrieve libSBML version: +[ravenDir,prevDir]=findRAVENroot(); +cd(fullfile(ravenDir,'software','libSBML')); try % 5.17.0 and newer libSBMLver=OutputSBML; libSBMLver=libSBMLver.libSBML_version_string; @@ -64,6 +76,7 @@ libSBMLver=libSBMLver.libSBML_version_string; delete('tempModelForLibSBMLversion.xml'); end +cd(prevDir) % Make models folder, no warnings if folder already exists if subDirs @@ -81,12 +94,17 @@ % Write TXT format if ismember('txt', formats) fid=fopen(fullfile(filePath{1},strcat(prefix,'.txt')),'w'); - eqns=constructEquations(model,model.rxns,false,false,false,true); - eqns=strrep(eqns,' => ',' -> '); - eqns=strrep(eqns,' <=> ',' <=> '); - eqns=regexprep(eqns,'> $','>'); - grRules=regexprep(model.grRules,'\((?!\()','( '); - grRules=regexprep(grRules,'(? ',' -> '); + eqns=strrep(eqns,' <=> ',' <=> '); + eqns=regexprep(eqns,'> $','>'); + grRules=regexprep(model.grRules,'\((?!\()','( '); + grRules=regexprep(grRules,'(? + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/software/GLPKmex/glpk.m b/software/GLPKmex/glpk.m new file mode 100755 index 00000000..67f7dfa9 --- /dev/null +++ b/software/GLPKmex/glpk.m @@ -0,0 +1,502 @@ +% Matlab MEX interface for the GLPK library +% +% [xopt, fmin, status, extra] = glpk (c, a, b, lb, ub, ctype, vartype, +% sense, param) +% +% Solve an LP/MILP problem using the GNU GLPK library. Given three +% arguments, glpk solves the following standard LP: +% +% min C'*x subject to A*x <= b +% +% but may also solve problems of the form +% +% [ min | max ] C'*x +% subject to +% A*x [ "=" | "<=" | ">=" ] b +% x >= LB +% x <= UB +% +% Input arguments: +% c = A column array containing the objective function coefficients. +% +% A = A matrix containing the constraints coefficients. +% +% b = A column array containing the right-hand side value for each constraint +% in the constraint matrix. +% +% lb = An array containing the lower bound on each of the variables. If +% lb is not supplied (or an empty array) the default lower bound for the variables is +% minus infinite. +% +% ub = An array containing the upper bound on each of the variables. If +% ub is not supplied (or an empty array) the default upper bound is assumed to be +% infinite. +% +% ctype = An array of characters containing the sense of each constraint in the +% constraint matrix. Each element of the array may be one of the +% following values +% 'F' Free (unbounded) variable (the constraint is ignored). +% 'U' Variable with upper bound ( A(i,:)*x <= b(i)). +% 'S' Fixed Variable (A(i,:)*x = b(i)). +% 'L' Variable with lower bound (A(i,:)*x >= b(i)). +% 'D' Double-bounded variable (A(i,:)*x >= -b(i) and A(i,:)*x <= b(i)). +% +% vartype = A column array containing the types of the variables. +% 'C' Continuous variable. +% 'I' Integer variable +% 'B' Binary variable +% +% sense = If sense is 1, the problem is a minimization. If sense is +% -1, the problem is a maximization. The default value is 1. +% +% param = A structure containing the following parameters used to define the +% behavior of solver. Missing elements in the structure take on default +% values, so you only need to set the elements that you wish to change +% from the default. +% +% Integer parameters: +% msglev (default: 1) +% Level of messages output by solver routines: +% 0 - No output. +% 1 - Error messages only. +% 2 - Normal output. +% 3 - Full output (includes informational messages). +% +% scale (default: 1). Scaling option: +% 0 - No scaling. +% 1 - Equilibration scaling. +% 2 - Geometric mean scaling, then equilibration scaling. +% 3 - Geometric then Equilibrium scaling +% 4 - Round to nearest power of 2 scaling +% +% dual (default: 0). Dual simplex option: +% 0 - Do not use the dual simplex. +% 1 - If initial basic solution is dual feasible, use +% the dual simplex. +% 2- Use two phase dual simplex, or if primal simplex +% if dual fails +% +% price (default: 1). Pricing option (for both primal and dual simplex): +% 0 - Textbook pricing. +% 1 - Steepest edge pricing. +% +% r_test (default: 1). Ratio test Technique: +% 0 - stardard (textbook) +% 1 - Harris's two-pass ratio test +% +% round (default: 0). Solution rounding option: +% +% 0 - Report all primal and dual values "as is". +% 1 - Replace tiny primal and dual values by exact zero. +% +% itlim (default: -1). Simplex iterations limit. +% If this value is positive, it is decreased by one each +% time when one simplex iteration has been performed, and +% reaching zero value signals the solver to stop the search. +% Negative value means no iterations limit. +% +% itcnt (default: 200). Output frequency, in iterations. +% This parameter specifies how frequently the solver sends +% information about the solution to the standard output. +% +% presol (default: 1). If this flag is set, the routine +% lpx_simplex solves the problem using the built-in LP presolver. +% Otherwise the LP presolver is not used. +% +% lpsolver (default: 1) Select which solver to use. +% If the problem is a MIP problem this flag will be ignored. +% 1 - Revised simplex method. +% 2 - Interior point method. +% 3 - Simplex method with exact arithmatic. +% +% branch (default: 2). Branching heuristic option (for MIP only): +% 0 - Branch on the first variable. +% 1 - Branch on the last variable. +% 2 - Branch on the most fractional variable. +% 3 - Branch using a heuristic by Driebeck and Tomlin. +% +% btrack (default: 2). Backtracking heuristic option (for MIP only): +% 0 - Depth first search. +% 1 - Breadth first search. +% 2 - best local bound +% 3 - Backtrack using the best projection heuristic. +% +% pprocess (default: 2) Pre-processing technique option ( for MIP only ): +% 0 - disable preprocessing +% 1 - perform preprocessing for root only +% 2 - perform preprocessing for all levels +% +% usecuts (default: 1). ( for MIP only ): +% glp_intopt generates and adds cutting planes to +% the MIP problem in order to improve its LP relaxation +% before applying the branch&bound method +% 0 -> all cuts off +% 1 -> Gomoy's mixed integer cuts +% 2 -> Mixed integer rounding cuts +% 3 -> Mixed cover cuts +% 4 -> Clique cuts +% 5 -> all cuts +% +% binarize (default: 0 ) Binarizeation option ( for mip only ): +% ( used only if presolver is enabled ) +% 0 -> do not use binarization +% 1 -> replace general integer variables by binary ones +% +% save (default: 0). If this parameter is nonzero save a copy of +% the original problem to file. You can specify the +% file name and format by using the 'savefilename' and +% 'savefiletype' parameters (see in String Parameters Section +% here below). +% If previous parameters are not defined, the original problem +% is saved with CPLEX LP format in the default file "outpb.lp". +% +% mpsinfo (default: 1) If this is set, +% the interface writes to file several comment cards, +% which contains some information about the problem. +% Otherwise the routine writes no comment cards. +% +% mpsobj ( default: 2) This parameter tells the +% routine how to output the objective function row: +% 0 - never output objective function row +% 1 - always output objective function row +% 2 - output objective function row if the problem has +% no free rows +% +% mpsorig (default: 0) If this is set, the +% routine uses the original symbolic names of rows and +% columns. Otherwise the routine generates plain names +% using ordinal numbers of rows and columns. +% +% mpswide (default: 1) If this is set, the +% routine uses all data fields. Otherwise the routine +% keeps fields 5 and 6 empty. +% +% mpsfree (default: 0) If this is set, the routine +% omits column and vector names every time when possible +% (free style). Otherwise the routine never omits these +% names (pedantic style). +% +% +% Real parameters: +% relax (default: 0.07). Relaxation parameter used +% in the ratio test. If it is zero, the textbook ratio test +% is used. If it is non-zero (should be positive), Harris' +% two-pass ratio test is used. In the latter case on the +% first pass of the ratio test basic variables (in the case +% of primal simplex) or reduced costs of non-basic variables +% (in the case of dual simplex) are allowed to slightly violate +% their bounds, but not more than relax*tolbnd or relax*toldj +% (thus, relax is a percentage of tolbnd or toldj). +% +% tolbnd (default: 10e-7). Relative tolerance used +% to check ifthe current basic solution is primal feasible. +% It is not recommended that you change this parameter +% unless you have a detailed understanding of its purpose. +% +% toldj (default: 10e-7). Absolute tolerance used to +% check if the current basic solution is dual feasible. It +% is not recommended that you change this parameter unless +% you have a detailed understanding of its purpose. +% +% tolpiv (default: 10e-9). Relative tolerance used +% to choose eligible pivotal elements of the simplex table. +% It is not recommended that you change this parameter +% unless you have a detailed understanding of its purpose. +% +% objll ( default: -DBL_MAX). Lower limit of the +% objective function. If on the phase II the objective +% function reaches this limit and continues decreasing, the +% solver stops the search. This parameter is used in the +% dual simplex method only. +% +% objul (default: +DBL_MAX). Upper limit of the +% objective function. If on the phase II the objective +% function reaches this limit and continues increasing, +% the solver stops the search. This parameter is used in +% the dual simplex only. +% +% tmlim (default: -1.0). Searching time limit, in +% seconds. If this value is positive, it is decreased each +% time when one simplex iteration has been performed by the +% amount of time spent for the iteration, and reaching zero +% value signals the solver to stop the search. Negative +% value means no time limit. +% +% outdly (default: 0.0). Output delay, in seconds. +% This parameter specifies how long the solver should +% delay sending information about the solution to the standard +% output. Non-positive value means no delay. +% +% tolint (default: 10e-5). Relative tolerance used +% to check if the current basic solution is integer +% feasible. It is not recommended that you change this +% parameter unless you have a detailed understanding of +% its purpose. +% +% tolobj (default: 10e-7). Relative tolerance used +% to check if the value of the objective function is not +% better than in the best known integer feasible solution. +% It is not recommended that you change this parameter +% unless you have a detailed understanding of its purpose. +% +% mipgap (default: 0.0) The relative mip gap tolerance. If the +% relative mip gap for currently known best integer feasible +% solution falls below this tolerance, the solver terminates +% the search. This allows obtaining suboptimal interger +% feasible solutions if solving the problem to optimality +% takes too long. +% +% String Parameters: +% savefilename (default: "outpb"). Specify the name to use to +% save the original problem. MEX interface looks for +% this parameter if 'save' parameter is set to 1. If +% no name is provided "outpb" will be used. +% savefiletype (default: CPLEX format). Specify the format type +% used to save the file. Only the following options +% are allowed: +% 'fixedmps' - fixed MPS format (.mps). +% 'freemps' - free MPS format (.mps). +% 'cplex' - CPLEX LP format (.lp). +% 'plain' - plain text (.txt). +% +% Output values: +% xopt = The optimizer (the value of the decision variables at the optimum). +% +% fopt = The optimum value of the objective function. +% +% status = Status of the optimization. +% 1 solution is undefined +% 2 solution is feasible +% 3 solution is infeasible +% 4 no feasible solution exists +% 5 solution is optimal +% 6 solution is unbounded +% +% If an error occurs, status will contain one of the following +% codes. +% Simplex method: +% 101 invalid basis +% 102 singular matrix +% 103 ill-conditioned matrix +% 104 invalid bounds +% 105 solver failed +% 106 objective lower limit reached +% 107 objective upper limit reached +% 108 iteration limit exceeded +% 109 time limit exceeded +% 110 no primal feasible solution +% 111 no dual feasible solution +% +% Mixed integer problem, interior point method: +% 204 incorrect bounds +% 205 solver failure +% 209 time limit exceeded +% 210 no primal feasible solution +% 212 missing basis +% 214 MIP gap tolerance reached +% 305 problem with no rows/columsn +% 308 iteration limit exceeded +% 316 very slow convergence/divergence +% 317 numerical instability in solving Newtonian system +% +% extra = A data structure containing the following fields: +% lambda - Dual variables. +% redcosts - Reduced Costs. +% time - Time (in seconds) used for solving LP/MIP problem. +% mem - Memory (in Kbytes) used for solving LP/MIP problem. +% +% Example: +% +% c = [10, 6, 4]'; +% a = [ 1, 1, 1; +% 10, 4, 5; +% 2, 2, 6]; +% b = [100, 600, 300]'; +% lb = [0, 0, 0]'; +% ub = []; +% ctype = "UUU"; +% vartype = "CCC"; +% s = -1; +% +% param.msglev = 1; +% param.itlim = 100; +% +% [xmin, fmin, status, extra] = ... +% glpk (c, a, b, lb, ub, ctype, vartype, s, param); +% +% See also: qpng. +% +% Copyright 2005-2007 Nicolo' Giorgetti +% Email: Nicolo' Giorgetti +% updated by Niels Klitgord March 2009 +% Email: Niels Klitgord + +% This file is part of GLPKMEX. +% +% GLPKMEX is free software; you can redistribute it and/or modify it +% under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2, or (at your option) +% any later version. +% +% This part of code is distributed with the FURTHER condition that it +% can be linked to the Matlab libraries and/or use it inside the Matlab +% environment. +% +% GLPKMEX is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +% General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GLPKMEX; see the file COPYING. If not, write to the Free +% Software Foundation, 59 Temple Place - Suite 330, Boston, MA +% 02111-1307, USA. +function [xopt,fmin,status,extra] = glpk (c,a,b,lb,ub,ctype,vartype,sense,param) + +% If there is no input output the version and syntax +if (nargin < 3 || nargin > 9) + disp('GLPK Matlab interface. Version: 2.11'); + disp('(C) 2001-2007, Nicolo'' Giorgetti.'); + disp('Maintained by Niels Klitgord'); + disp('last updated Sept 6, 2011'); + disp(' '); + disp('Syntax: [xopt,fopt,status,extra]=glpk(c,a,b,lb,ub,ctype,vartype,sense,param)'); + disp('try help glpk for more information'); + return; +end + +%% begin with some error checking +if (all(size(c) > 1) || ~isreal(c) || ischar(c)) + error('C must be a real vector'); +end + +% clears glpkcc mex function from memory to deal with param bug +% this is because params not specificly set default to the last used rather +% than internal defaults for some reason.... +clear glpkcc; + +nx = length (c); + +% 1) Force column vector. +c = c(:); + +% 2) Matrix constraint +if (isempty(a)) + error('A cannot be an empty matrix'); +end +[nc, nxa] = size(a); +if (~isreal(a) || nxa ~= nx) + error('A must be a real valued %d by %d matrix', nc, nx); + return; +end + +% 3) RHS +if (isempty(b)) + error('B cannot be an empty vector'); +end +if (~isreal(b) || length(b) ~= nc) + error ('B must be a real valued %d by 1 vector', nc); + return; +end + +% 4) Vector with the lower bound of each variable +if (nargin > 3) + if (isempty(lb)) + lb = repmat(-Inf, nx, 1); + elseif (~isreal(lb) || all(size(lb) > 1) || length(lb) ~= nx) + error ('LB must be a real valued %d by 1 column vector', nx); + return; + end +else + lb = -Inf*ones(nx, 1); +end + +% 5) Vector with the upper bound of each variable +if (nargin > 4) + if (isempty(ub)) + ub = Inf(nx, 1); + elseif (~isreal(ub) || all(size(ub) > 1) || length(ub) ~= nx) + error ('UB must be a real valued %d by 1 column vector', nx); + return; + end +else + ub = Inf(nx, 1); +end + +% 6) Sense of each constraint +if (nargin > 5) + if (isempty (ctype)) + ctype = repmat('U', nc, 1); + elseif (~ischar(ctype) || all(size(ctype) > 1) || length(ctype) ~= nc) + error('CTYPE must be a char valued vector of length %d', nc); + return; + else + for i=1:length(ctype) + switch(ctype(i)) + case {'f','F'}, % do nothing + case {'u','U'}, % do nothing + case {'s','S'}, % do nothing + case {'l','L'}, % do nothing + case {'d','D'}, % do nothing + otherwise + error('CTYPE must contain only F, U, S, L, or D'); + end + end + end +else + ctype= repmat('U', nc, 1); +end + +% 7) Vector with the type of variables +if (nargin > 6) + if isempty(vartype) + vartype = repmat('C', nx, 1); + elseif (~ischar(vartype) || all(size(vartype) > 1) || length (vartype) ~= nx) + error('VARTYPE must be a char valued vector of length %d', nx); + return; + else + for i=1:length(vartype) + switch(vartype(i)) + case {'c','C'}, % do nothing + case {'i','I'}, % do nothing + case {'b','B'}, % do nothing + otherwise + error('VARTYPE must contain only C, I or B'); + end + end + end +else + % As default we consider continuous vars + vartype = repmat('C', nx, 1); +end + +% 8) Sense of optimization +if (nargin >7) + if isempty(sense) + sense=1; + elseif (ischar(sense) || all(size(sense) > 1) || ~isreal(sense)) + error('SENSE must be an integer value'); + elseif sense>=0 + sense=1; + else + sense=-1; + end +else + sense=1; +end + +% 9) Parameters vector +if (nargin > 8) + if (~isstruct(param)) + error('PARAM must be a structure'); + end +else + if str2double(version('-release'))<36 + param =struct; + else + param = struct([]); + end +end + +[xopt, fmin, status, extra] = glpkcc(c, a, b, lb, ub, ctype, vartype, sense, param); + diff --git a/software/GLPKmex/glpkcc.mexa64 b/software/GLPKmex/glpkcc.mexa64 index 9f9351b1..f7a5259e 100755 Binary files a/software/GLPKmex/glpkcc.mexa64 and b/software/GLPKmex/glpkcc.mexa64 differ diff --git a/software/GLPKmex/glpkcc.mexw32 b/software/GLPKmex/glpkcc.mexw32 index c707afee..1bd3daae 100755 Binary files a/software/GLPKmex/glpkcc.mexw32 and b/software/GLPKmex/glpkcc.mexw32 differ diff --git a/software/GLPKmex/glpkcc.mexw64 b/software/GLPKmex/glpkcc.mexw64 index 1a168b63..ee653fb4 100755 Binary files a/software/GLPKmex/glpkcc.mexw64 and b/software/GLPKmex/glpkcc.mexw64 differ diff --git a/software/libSBML/AUTHORS.txt b/software/libSBML/AUTHORS.txt new file mode 100644 index 00000000..9088ddf1 --- /dev/null +++ b/software/libSBML/AUTHORS.txt @@ -0,0 +1,20 @@ + The original code contained here was initially developed by: + + Sarah Keating + Science and Technology Research Centre + University of Hertfordshire + Hatfield, AL10 9AB + United Kingdom + + with contributions from + + Ben Bornstein and Michael Hucka + Control and Dynamical Systems, MC 107-81 + California Institute of Technology + Pasadena, CA, 91125, USA + + For more information about SBML or libSBML, contact: + + The SBML Team + http://sbml.org + mailto:sbml-team@googlegroups.com diff --git a/software/libSBML/CheckAndConvert.m b/software/libSBML/CheckAndConvert.m new file mode 100755 index 00000000..df0a837d --- /dev/null +++ b/software/libSBML/CheckAndConvert.m @@ -0,0 +1,521 @@ +function Formula = CheckAndConvert(Input) +% Formula = CheckAndConvert(Input) +% +% - a script used internally by TranslateSBML to change some mathematical function names +% to those used by MATLAB +% +% Takes +% +% 1. Input - a string representation of the math from an SBML document +% +% Returns +% +% 1. Formula - the original string adjusted to be MATLAB compatible +% + +% Filename : CheckAndConvert.m +% Description : converts from MathML in-fix to MATLAB functions +% Author(s) : SBML Team +% Organization: University of Hertfordshire STRC +% Created : 2004-12-13 +% +% This file is part of libSBML. Please visit http://sbml.org for more +% information about SBML, and the latest version of libSBML. +% +% Copyright (C) 2013-2018 jointly by the following organizations: +% 1. California Institute of Technology, Pasadena, CA, USA +% 2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK +% 3. University of Heidelberg, Heidelberg, Germany +% +% Copyright (C) 2009-2013 jointly by the following organizations: +% 1. California Institute of Technology, Pasadena, CA, USA +% 2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK +% +% Copyright (C) 2006-2008 by the California Institute of Technology, +% Pasadena, CA, USA +% +% Copyright (C) 2002-2005 jointly by the following organizations: +% 1. California Institute of Technology, Pasadena, CA, USA +% 2. Japan Science and Technology Agency, Japan +% +% This library is free software; you can redistribute it and/or modify it +% under the terms of the GNU Lesser General Public License as published by +% the Free Software Foundation. A copy of the license agreement is provided +% in the file named "LICENSE.txt" included with this software distribution +% and also available online as http://sbml.org/software/libsbml/license.html +% +% The original code contained here was initially developed by: +% +% Sarah Keating +% Science and Technology Research Centre +% University of Hertfordshire +% Hatfield, AL10 9AB +% United Kingdom +% +% http://www.sbml.org +% mailto:sbml-team@googlegroups.com +% +% Contributor(s): + +Formula = strrep(Input, 'arccosh', 'acosh'); + +Formula = strrep(Formula, 'arccot', 'acot'); + +Formula = strrep(Formula, 'arccoth', 'acoth'); + +Formula = strrep(Formula, 'arccsc', 'acsc'); + +Formula = strrep(Formula, 'arccsch', 'acsch'); + +Formula = strrep(Formula, 'arcsec', 'asec'); + +Formula = strrep(Formula, 'arcsech', 'asech'); + +Formula = strrep(Formula, 'arcsinh', 'asinh'); + +Formula = strrep(Formula, 'arctanh', 'atanh'); + +Formula = strrep(Formula, 'exponentiale', 'exp(1)'); + +Formula = strrep(Formula, 'geq', 'ge'); + +Formula = strrep(Formula, 'leq', 'le'); + +Formula = strrep(Formula, 'neq', 'ne'); + +Formula = strrep(Formula, 'pow', 'power'); + +% any logical expressions can only have two arguments +Formula = SortLogicals(Formula); + +% log(2,x) must become log2(x) +Formula = strrep(Formula, 'log(2,', 'log2('); + + +% root(n,x) must become nthroot(x,n) +Index = strfind(Formula, 'root('); + +for i = 1:length(Index) + + % create a subformula root(n,x) + SubFormula = ''; + j = 1; + nFunctions=0; %number of functions in expression + closedFunctions=0; %number of closed functions + while(nFunctions==0 || nFunctions~=closedFunctions) + SubFormula(j) = Formula(Index(i)+j-1); + if(strcmp(SubFormula(j),')')) + closedFunctions=closedFunctions+1; + end; + if(strcmp(SubFormula(j),'(')) + nFunctions=nFunctions+1; + end; + j = j+1; + end; + + j = 6; + n = ''; + while(~strcmp(SubFormula(j), ',')) + n = strcat(n, SubFormula(j)); + j = j+1; + end; + + j = j+1; + x = SubFormula(j:length(SubFormula)-1); + + ReplaceFormula = strcat('nthroot(', x, ',', n, ')'); + + Formula = strrep(Formula, SubFormula, ReplaceFormula); + Index = strfind(Formula, 'root('); + + +end; + +% log(n,x) must become (log(x)/log(n)) +% but log(x) must be left alone + +LogTypes = IsItLogBase(Formula); +Index = strfind(Formula, 'log('); + +for i = 1:length(Index) + + if (LogTypes(i) == 1) + % create a subformula log(n,x) + SubFormula = ''; + j = 1; + while(~strcmp(Formula(Index(i)+j-1), ')')) + SubFormula(j) = Formula(Index(i)+j-1); + j = j+1; + end; + SubFormula = strcat(SubFormula, ')'); + + j = 5; + n = ''; + while(~strcmp(SubFormula(j), ',')) + n = strcat(n, SubFormula(j)); + j = j+1; + end; + + j = j+1; + x = ''; + while(~strcmp(SubFormula(j), ')')) + x = strcat(x, SubFormula(j)); + j = j+1; + end; + + ReplaceFormula = sprintf('(log(%s)/log(%s))', x, n); + + Formula = strrep(Formula, SubFormula, ReplaceFormula); + Index = Index + 7; + end; + +end; + + +function y = IsItLogBase(Formula) + +% returns an array of 0/1 indicating whether each occurence of log is +% a log(n,x) or a log(x) +% e.g. Formula = 'log(2,3) + log(6)' +% IsItLogBase returns y = [1,0] + + +y = 0; + +% find log + +LogIndex = strfind(Formula, 'log('); + +if (isempty(LogIndex)) + return; +else + y = zeros(1, length(LogIndex)); + OpenBracket = strfind(Formula, '('); + Comma = strfind(Formula, ','); + CloseBracket = strfind(Formula, ')'); + + for i = 1:length(LogIndex) + if (isempty(Comma)) + % no commas so no logbase formulas + y(i) = 0; + else + + % find the opening bracket + Open = find(ismember(OpenBracket, LogIndex(i)+3) == 1,1); + + % find closing bracket + Close = find(CloseBracket > LogIndex(i)+3, 1); + + % is there a comma between + Greater = find(Comma > OpenBracket(Open),1); + Less = find(Comma < CloseBracket(Close)); + + if (isempty(Greater) || isempty(Less)) + y(i) = 0; + else + Equal = find(Greater == Less, 1); + if (isempty(Equal)) + y(i) = 0; + else + y(i) = 1; + end; + end; + + end; + end; +end; + +function Formula = CorrectFormula(OriginalFormula, LogicalExpression) +% CorrectFormula takes an OriginalFormula (as a char array) +% and a Logical Expression (as a char array with following '(') +% and returns the formula written so that the logical expression only takes 2 arguments +% +% ************************************************************************************* +% +% EXAMPLE: y = CorrectFormula('and(A,B,C)', 'and(') +% +% y = 'and(and(A,B), C)' +% + +% find all opening brackets, closing brackets and commas contained +% within the original formula +OpeningBracketIndex = find((ismember(OriginalFormula, '(')) == 1); + +ClosingBracketIndex = find((ismember(OriginalFormula, ')')) == 1); + +CommaIndex = find((ismember(OriginalFormula, ',')) == 1); + +% check that tha number of brackets matches +if (length(OpeningBracketIndex) ~= length(ClosingBracketIndex)) + error('Bracket mismatch'); +end; + +% find the commas that are between the arguments of the logical expression +% not those that may be part of the argument +% in the OpeningBracketIndex the first element refers to the opening +% bracket of the expression and the last element of ClosingBracketIndex +% refers to the the closing bracket of the expression +% commas between other pairs of brackets do not need to be considered +% e.g. 'and(gt(d,e),lt(2,e),gt(f,d))' +% | | +% relevant commas + +for i = 1:length(CommaIndex) + for j = 2:length(OpeningBracketIndex) + if ((CommaIndex(i) > OpeningBracketIndex(j)) && (CommaIndex(i) < ClosingBracketIndex(j-1))) + CommaIndex(i) = 0; + end; + end; +end; + +NonZeros = find(CommaIndex ~= 0); + +% if there is only one relevant comma +% implies only two arguments +% MATLAB can deal with the OriginalFormula + +if (length(NonZeros) == 1) + Formula = OriginalFormula; + return; +end; + +% get elements that represent the arguments of the logical expression +% as an array of character arrays +% e.g. first element is between opening barcket and first relevant comma +% next elements are between relevant commas +% last element is between last relevant comma and closing bracket + +j = OpeningBracketIndex(1); +ElementNumber = 1; +Elements = cell(1, length(NonZeros)+1); + +for i = 1:length(NonZeros) + element = ''; + j = j+1; + while (j <= CommaIndex(NonZeros(i)) - 1) + element = strcat(element, OriginalFormula(j)); + j = j + 1; + end; + + Elements{ElementNumber} = element; + ElementNumber = ElementNumber + 1; + +end; + + +element = ''; +j = j+1; +while (j < ClosingBracketIndex(length(ClosingBracketIndex)) - 1) + element = strcat(element, OriginalFormula(j)); + j = j + 1; +end; + +Elements{ElementNumber} = element; + +% iteratively replace the first two arguments with the logical expression applied to +% the first two arguments +% e.g. OriginalFormula = 'and(a,b,c,d)' +% becomes 'and(and(a,b),c,d)' +% which becomes 'and(and(and(a,b),c),d)' +Formula = OriginalFormula; + +if (length(Elements) > 2) + for i = 2:length(Elements)-1 + Find = strcat(Elements{i-1}, ',', Elements{i}); + Replace = strcat(LogicalExpression, Find, ')'); + + Formula = strrep(Formula, Find, Replace); + Elements{i} = Replace; + end; +end; + + +function Arguments = CheckLogical(Formula, LogicalExpression) +% CheckLogical takes a Formula (as a character array) +% and a LogicalExpression (as a char array) +% and returns an array of character strings +% representing the application of the logical expression within the formula +% +% NOTE the logical expression is followed by an '(' to prevent confusion +% with other character strings within the formula +% +% ****************************************************************** +% EXAMPLE: y = CheckLogical('piecewise(and(A,B,C), 0.2, 1)' , 'and(') +% +% y = 'and(A,B,C)' +% +% EXAMPLE: y = CheckLogical('or(and(A,B), and(A,B,C))', 'and(') +% +% y = 'and(A,B)' 'and(A,B,C)' + +% find the starting indices of all occurences of the logical expression +Start = strfind(Formula, LogicalExpression); + +if (isempty(Start)) + Arguments = {}; + return; +end; + +possValues = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'; +% remove any functions that may end in the name of a logical eg floor or +% myand +newStart = []; +index = 1; +for j = 1:length(Start) + if Start(j) ~= 1 + prev = Formula(Start(j)-1); + if ~ismember(prev, possValues) + newStart(index) = Start(j); + index = index + 1; + end; + else + newStart(index) = Start(j); + index = index + 1; + end; +end; +Start = newStart; + + + +% if not found; no arguments - return +if (isempty(Start)) + Arguments = {}; + return; +end; + + +Arguments = cell(1, length(Start)); +for j = 1:length(Start) % each occurence of the logical expression + + Stop = 0; + flag = 0; + i = Start(j); + output = ''; + + for i = Start(j):Start(j)+length(LogicalExpression) + output = strcat(output, Formula(i)); + end; + i = i + 1; + % catch case with zero args + if (strcmp(Formula(i-1), ')') && (length(output) == (length(LogicalExpression) + 1))) + Stop = 1; + end; + + while ((Stop == 0) && (i <= length(Formula))) + c = Formula(i); + prev = Formula(i-1); + + if (strcmp(c, '(')) + flag = flag + 1; + output = strcat(output, c); + elseif (strcmp(c, ')')) + if (flag > 0) + output = strcat(output, c); + flag = flag - 1; + else + output = strcat(output, c); + Stop = 1; + end; + + else + output = strcat(output, c); + end; + i = i + 1; + end; + + Arguments{j} = output; + +end; + +function y = SortLogicals(Formula) +% SortLogicals takes a formula as a char array +% and returns the formula with and logical expressions applied to only two arguments + +Formula = LoseWhiteSpace(Formula); + +Find = CheckLogical(Formula, 'and('); + +for i = 1:length(Find) + Replace = CorrectFormula(Find{i}, 'and('); + + Formula = strrep(Formula, Find{i}, Replace); + +end; + +Find = CheckLogical(Formula, 'xor('); + +for i = 1:length(Find) + Replace = CorrectFormula(Find{i}, 'xor('); + + Formula = strrep(Formula, Find{i}, Replace); + +end; + +Find = CheckLogical(Formula, 'or('); + +for i = 1:length(Find) + Replace = CorrectFormula(Find{i}, 'or('); + + Formula = strrep(Formula, Find{i}, Replace); + +end; +y = Formula; + +%********************************************************************** +% LoseWhiteSpace(charArray) takes an array of characters +% and returns the array with any white space removed +% +%********************************************************************** + +function y = LoseWhiteSpace(charArray) +% LoseWhiteSpace(charArray) takes an array of characters +% and returns the array with any white space removed +% +%---------------------------------------------------------------- +% EXAMPLE: +% y = LoseWhiteSpace(' exa mp le') +% y = 'example' +% + +%------------------------------------------------------------ +% check input is an array of characters +if (~ischar(charArray)) + error('LoseWhiteSpace(input)\n%s', 'input must be an array of characters'); +end; + +%------------------------------------------------------------- +% get the length of the array +NoChars = length(charArray); + +%------------------------------------------------------------- +% create an array that indicates whether the elements of charArray are +% spaces +% e.g. WSpace = isspace(' v b') = [1, 1, 0, 1, 0] +% and determine how many + +WSpace = isspace(charArray); +NoSpaces = sum(WSpace); + +%----------------------------------------------------------- +% rewrite the array to leaving out any spaces +% remove any numbers from the array of symbols +if (NoSpaces > 0) + y = ''; + for i = 1:NoChars + if (~isspace(charArray(i))) + y = strcat(y, charArray(i)); + end; + end; +else + y = charArray; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function y = contains( members, individual) + ans = ismember(individual, members); + if sum(ans) >= 1 + y = 1; + else + y = 0; + end; + diff --git a/software/libSBML/Contents.m b/software/libSBML/Contents.m new file mode 100755 index 00000000..1b69c04a --- /dev/null +++ b/software/libSBML/Contents.m @@ -0,0 +1,101 @@ +% +% These are the functions to import and export an SBML model into a +% MATLAB_SBML structure and back to an SBML file. +% +% FUNCTIONS include: +% +% TranslateSBML(varargin) +% +% - translates a sbml file into a matlab structure +% +% OutputSBML(varargin) +% +% - translates a appropriate matlab structure back into sbml and writes +% out the file +% +% addLevelVersion.m +% +% - a script used by TranslateSBML to add a level and version field to all +% parts of a structure +% +% applyUserValidation.m +% +% - a script that can be customized by the user to add additional +% validation to the isSBML_Model function +% +% CheckAndConvert.m +% +% - a script used by TranslateSBML to change some mathematical function names +% to those used by MATLAB +% +% ConvertFormulaToMathML.m +% +% - a script used by OutputSBML to change some mathematical function names +% to those used by MathML +% +% getDefaultValues.m +% +% - a script used to retreive the default values for a given SBMLStructure +% +% getStructureFieldnames.m +% +% - a script used to retreive the fieldnames for a given SBMLStructure +% +% getValueType.m +% +% - a script used to retreive the value types for a given SBMLStructure +% +% isSBML_Model.m +% +% - a script used by OutputSBML to check that a structure is an appropriate +% MATLAB_SBML structure for conversion to SBML +% +% isoctave.m +% +% - a script to determine if octave or matlab is being used +% + +% Description : This is the binding to translate +% sbml models into a MATLAB structure +% Author(s) : SBML Team +% +% This file is part of libSBML. Please visit http://sbml.org for more +% information about SBML, and the latest version of libSBML. +% +% Copyright (C) 2013-2018 jointly by the following organizations: +% 1. California Institute of Technology, Pasadena, CA, USA +% 2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK +% 3. University of Heidelberg, Heidelberg, Germany +% +% Copyright (C) 2009-2013 jointly by the following organizations: +% 1. California Institute of Technology, Pasadena, CA, USA +% 2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK +% +% Copyright (C) 2006-2008 by the California Institute of Technology, +% Pasadena, CA, USA +% +% Copyright (C) 2002-2005 jointly by the following organizations: +% 1. California Institute of Technology, Pasadena, CA, USA +% 2. Japan Science and Technology Agency, Japan +% +% This library is free software; you can redistribute it and/or modify it +% under the terms of the GNU Lesser General Public License as published by +% the Free Software Foundation. A copy of the license agreement is provided +% in the file named "LICENSE.txt" included with this software distribution +% and also available online as http://sbml.org/software/libsbml/license.html +% +% The original code contained here was initially developed by: +% +% Sarah Keating +% Science and Technology Research Centre +% University of Hertfordshire +% Hatfield, AL10 9AB +% United Kingdom +% +% http://www.sbml.org +% mailto:sbml-team@googlegroups.com +% +% Contributor(s): +% +% +% diff --git a/software/libSBML/ConvertFormulaToMathML.m b/software/libSBML/ConvertFormulaToMathML.m new file mode 100755 index 00000000..fbb504f6 --- /dev/null +++ b/software/libSBML/ConvertFormulaToMathML.m @@ -0,0 +1,376 @@ +function Formula = ConvertFormulaToMathML(Input) +% Formula = ConvertFormulaToMathML(Input) +% +% - a script used internally by OutputSBML to change some mathematical function names +% to those recognized by libSBML +% +% Takes +% +% 1. Input - a string representation of the math from MATLAB +% +% Returns +% +% 1. Formula - the original string adjusted to be libSBML compatible +% +% + +% Filename : ConvertFormulaToMathML.m +% +% This file is part of libSBML. Please visit http://sbml.org for more +% information about SBML, and the latest version of libSBML. +% +% Copyright (C) 2013-2018 jointly by the following organizations: +% 1. California Institute of Technology, Pasadena, CA, USA +% 2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK +% 3. University of Heidelberg, Heidelberg, Germany +% +% Copyright (C) 2009-2013 jointly by the following organizations: +% 1. California Institute of Technology, Pasadena, CA, USA +% 2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK +% +% Copyright (C) 2006-2008 by the California Institute of Technology, +% Pasadena, CA, USA +% +% Copyright (C) 2002-2005 jointly by the following organizations: +% 1. California Institute of Technology, Pasadena, CA, USA +% 2. Japan Science and Technology Agency, Japan +% +% This library is free software; you can redistribute it and/or modify it +% under the terms of the GNU Lesser General Public License as published by +% the Free Software Foundation. A copy of the license agreement is provided +% in the file named "LICENSE.txt" included with this software distribution +% and also available online as http://sbml.org/software/libsbml/license.html +% +% The original code contained here was initially developed by: +% +% Sarah Keating +% Science and Technology Research Centre +% University of Hertfordshire +% Hatfield, AL10 9AB +% United Kingdom +% +% http://www.sbml.org +% mailto:sbml-team@googlegroups.com +% +% Contributor(s): + +Input = LoseWhiteSpace(Input); + +Formula = strrep(Input, 'acosh(', 'arccosh('); + +Formula = strrep(Formula, 'acot(', 'arccot('); + +Formula = strrep(Formula, 'acoth(', 'arccoth('); + +Formula = strrep(Formula, 'acsc(', 'arccsc('); + +Formula = strrep(Formula, 'acsch(', 'arccsch('); + +Formula = strrep(Formula, 'asec(', 'arcsec('); + +Formula = strrep(Formula, 'asech(', 'arcsech('); + +Formula = strrep(Formula, 'asinh(', 'arcsinh('); + +Formula = strrep(Formula, 'atanh(', 'arctanh('); + +Formula = strrep(Formula, 'exp(1)', 'exponentiale'); + +Formula = strrep(Formula, 'ge(', 'geq('); + +Formula = strrep(Formula, 'le(', 'leq('); + +Formula = strrep(Formula, 'ne(', 'neq('); + +Formula = strrep(Formula, 'power(', 'pow('); + +% log2(x) must become log(2, x) +Formula = strrep(Formula, 'log2(', 'log(2, '); +% +% +% nthroot(x,n) must become root(n,x) +Index = strfind(Formula, 'nthroot('); + +for i = 1:length(Index) + + % create a subformula nthroot(x,n) + j = 1; + nFunctions=0; %number of functions in expression + closedFunctions=0; %number of closed functions + SubFormula = ''; + while(nFunctions==0 || nFunctions~=closedFunctions) + SubFormula = strcat(SubFormula, Formula(Index(i)+j-1)); + if(strcmp(SubFormula(j),')')) + closedFunctions=closedFunctions+1; + end; + if(strcmp(SubFormula(j),'(')) + nFunctions=nFunctions+1; + end; + j = j+1; + end; + + j = 9; + n = ''; + while(~strcmp(SubFormula(j), ',')) + n = strcat(n, SubFormula(j)); + j = j+1; + end; + + j = j+1; + x = SubFormula(j:length(SubFormula)-1); + + if (exist('OCTAVE_VERSION', 'var')) + ReplaceFormula = myRegexprep(SubFormula, n, x, 'once'); + ReplaceFormula = myRegexprep(ReplaceFormula,regexptranslate('escape',x),n,2); + ReplaceFormula = myRegexprep(ReplaceFormula, 'nthroot', 'root', 'once'); + else + ReplaceFormula = regexprep(SubFormula, n, x, 'once'); + ReplaceFormula = regexprep(ReplaceFormula,regexptranslate('escape',x),n,2); + ReplaceFormula = regexprep(ReplaceFormula, 'nthroot', 'root', 'once'); + end; + + Formula = strrep(Formula, SubFormula, ReplaceFormula); + Index = strfind(Formula, 'nthroot('); + + +end; + +% (log(x)/log(n)) must become log(n,x) +% but log(x) must be left alone +Formula = convertLog(Formula); + +% +function y = convertLog(Formula) +y = Formula; +LogTypes = IsItLogBase(Formula); +num = sum(LogTypes); +Index = strfind(Formula, '(log('); + +if length(Index) > num + error('Problem'); +end; + +subFormula = cell(1, num); +newFormula = cell(1, num); + +subIndex = 1; +for i = 1:length(Index) + if (LogTypes(i) == 1) + % get x and n from (log(x)/log(n)) + % but what if we have pow((log(x)/log(n),y) + pairs = PairBrackets(Formula); + for j=1:length(pairs) + if (pairs(j,1) == Index(i)) + break; + end; + end; + subFormula{subIndex} = Formula(Index(i):pairs(j,2)); + comma = find(subFormula{subIndex} == ',', 1); + if (~isempty(comma)) + doReplace(subIndex) = 0; + else + ff = subFormula{subIndex}; + subPairs = PairBrackets(ff); + x = ff(subPairs(2,1)+1:subPairs(2,2)-1); + n = ff(subPairs(3,1)+1:subPairs(3,2)-1); + newFormula{subIndex} = sprintf('log(%s,%s)', n, x); + doReplace(subIndex) = 1; + end; + subIndex = subIndex+1; + end; + +end; +if (subIndex-1 > num) + error('Problem'); +end; +for i=1:num + if (doReplace(i) == 1) + y = strrep(y, subFormula{i}, newFormula{i}); + end; +end; +function y = IsItLogBase(Formula) + +% returns an array of 0/1 indicating whether each occurence of log is +% a (log(n)/log(x)) or a log(x) +% e.g. Formula = '(log(2)/log(3)) + log(6)' +% IsItLogBase returns y = [1,0] + + +y = 0; +LogIndex = strfind(Formula, '(log('); + +if (isempty(LogIndex)) + return; +else + Divide = strfind(Formula, ')/log('); + pairs = PairBrackets(Formula); + + if (isempty(Divide)) + return; + else + % check that the divide occurs between logs + y = zeros(1, length(LogIndex)); + for i=1:length(LogIndex) + match = 0; + for j=1:length(pairs) + if (pairs(j, 1) == LogIndex(i)) + break; + end; + end; + for k = 1:length(Divide) + if (pairs(j+1,2) == Divide(k)) + match = 1; + break; + end; + end; + + y(i) = match; + end; + end; +end; + +%********************************************************************** +% LoseWhiteSpace(charArray) takes an array of characters +% and returns the array with any white space removed +% +%********************************************************************** + +function y = LoseWhiteSpace(charArray) +% LoseWhiteSpace(charArray) takes an array of characters +% and returns the array with any white space removed +% +%---------------------------------------------------------------- +% EXAMPLE: +% y = LoseWhiteSpace(' exa mp le') +% y = 'example' +% + +%------------------------------------------------------------ +% check input is an array of characters +if (~ischar(charArray)) + error('LoseWhiteSpace(input)\n%s', 'input must be an array of characters'); +end; + +%------------------------------------------------------------- +% get the length of the array +NoChars = length(charArray); + +%------------------------------------------------------------- +% create an array that indicates whether the elements of charArray are +% spaces +% e.g. WSpace = isspace(' v b') = [1, 1, 0, 1, 0] +% and determine how many + +WSpace = isspace(charArray); +NoSpaces = sum(WSpace); + +%----------------------------------------------------------- +% rewrite the array to leaving out any spaces +% remove any numbers from the array of symbols +if (NoSpaces > 0) + y = ''; + for i = 1:NoChars + if (~isspace(charArray(i))) + y = strcat(y, charArray(i)); + end; + end; +else + y = charArray; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function pairs = PairBrackets(formula) +% PairBrackets takes a string +% and returns +% an array of indices of each pair of brackets +% ordered from the opening bracket index +% + +if (~ischar(formula)) + error('%s\n%s', 'PairBrackets(formula)', 'first argument must be a string'); +end; + +OpeningBracketIndex = strfind(formula, '('); +ClosingBracketIndex = strfind(formula, ')'); + +% check that the number of brackets matches +if (length(OpeningBracketIndex) ~= length(ClosingBracketIndex)) + error('Bracket mismatch'); +end; + +if (isempty(OpeningBracketIndex)) + pairs = 0; + return; +end; + +num = length(OpeningBracketIndex); +pairs = zeros(num, 2); +for i = 1:num + j = num; + while(j > 0) + if (OpeningBracketIndex(j) < ClosingBracketIndex(i)) + pairs(i,1) = OpeningBracketIndex(j); + pairs(i,2) = ClosingBracketIndex(i); + OpeningBracketIndex(j) = max(ClosingBracketIndex); + j = 0; + else + j = j - 1; + end; + end; +end; + +% order the pairs so that the opening bracket index is in ascending order + +OriginalPairs = pairs; + +% function 'sort' changes in version 7.0.1 + +v = version; +v_num = str2double(v(1)); + +if (v_num < 7) + TempPairs = sort(pairs, 1); +else + TempPairs = sort(pairs, 1, 'ascend'); +end; + +for i = 1:num + pairs(i, 1) = TempPairs(i, 1); + for j = 1:num + if (OriginalPairs(j, 1) == pairs(i, 1)) + break; + end; + end; + pairs(i, 2) = OriginalPairs(j, 2); +end; + + + +function string = myRegexprep(string, repre, repstr, number) + + %% Parse input arguements + + if isnumeric(number) + n = number; + elseif strcmpi(number, 'once') + n = 1; + else + error('Invalid argument to myRegexprep'); + end; + + [st, en] = regexp(string, repre); + + + if (n > 0) + if (length(st) >= n) + st = st(n); + en = en(n); + else + error('Invalid number of matches in myRegexprep'); + end; + end; + + for i = length(st):-1:1 + string = [string(1:st(i)-1) repstr string(en(i)+1:length(string))]; + end; + diff --git a/software/libSBML/OutputSBML.mexa64 b/software/libSBML/OutputSBML.mexa64 new file mode 100755 index 00000000..e85ddaa1 Binary files /dev/null and b/software/libSBML/OutputSBML.mexa64 differ diff --git a/software/libSBML/OutputSBML.mexglx b/software/libSBML/OutputSBML.mexglx new file mode 100755 index 00000000..ad56bac8 Binary files /dev/null and b/software/libSBML/OutputSBML.mexglx differ diff --git a/software/libSBML/OutputSBML.mexmaci64 b/software/libSBML/OutputSBML.mexmaci64 new file mode 100755 index 00000000..ba0ab2bb Binary files /dev/null and b/software/libSBML/OutputSBML.mexmaci64 differ diff --git a/software/libSBML/OutputSBML.mexw32 b/software/libSBML/OutputSBML.mexw32 new file mode 100755 index 00000000..e4a3a6d8 Binary files /dev/null and b/software/libSBML/OutputSBML.mexw32 differ diff --git a/software/libSBML/OutputSBML.mexw64 b/software/libSBML/OutputSBML.mexw64 new file mode 100755 index 00000000..510fbcd0 Binary files /dev/null and b/software/libSBML/OutputSBML.mexw64 differ diff --git a/software/libSBML/README.txt b/software/libSBML/README.txt new file mode 100644 index 00000000..a0b971d6 --- /dev/null +++ b/software/libSBML/README.txt @@ -0,0 +1,94 @@ + MATLAB application programming interface for libSBML + + Sarah Keating + + The SBML Team + http://www.sbml.org/ + mailto:sbml-team@googlegroups.com + + + +--------------- +1. Quick Start +--------------- + +The libSBML MATLAB binding provides MATLAB functions called +TranslateSBML and OutputSBML. These function can be used to import +and export an SBML model into/out of the MATLAB environment as a +MATLAB data structure. + +The Windows distribution of libSBML includes precompiled copies of +TranslateSBML and OutputSBML. The source distribution of libSBML for +Linux, MacOS X and other Unix-like environments does not come with +precompiled executables and you will need to build TranslateSBML as +described below. + + +------------------------------------------- +2. Configuration and Installation from src +------------------------------------------- + +Windows +------- + +Build libSBML as described in the libsbml instructions. + +Start MATLAB. + +Change to the directory holding the file you +are reading right now, i.e., 'libsbml\src\binding\matlab'. + +Run the buildSBML.m script followed by the installSBML.m script as +appropriate for your MATLAB installation. + + +Linux and MacOS X +----------------- + +The first step is to run the top-level libSBML 'configure' script with +the --with-matlab option. (See the top-level README.txt file in the +libSBML source distribution.) You will probably have to supply the +pathname of the directory tree where MATLAB is installed on your +system. For example, on MacOS X with release R2010b of MATLAB, run +the following shell command in the top-level libsbml directory: + + ./configure --with-matlab=/Applications/MATLAB_R2010b.app + +The libSBML 'configure' script will construct a Makefile in this +directory (i.e., the directory containing the file you are reading +right now), and executing 'make' from the top level will run the +MATLAB compiler to create an object file for use with MATLAB. The +'make install' step will then copy this object file to the library +installation directory chosen by the user. (This directory is +/usr/local/lib by default.) + +The second step is to configure MATLAB to look for the TranslateSBML +and OutputSBML functions in the libSBML library installation +directory. You can do this by using a MATLAB command such as + + addpath('/usr/local/lib'); + +at the MATLAB prompt. You may wish to add this command to your MATLAB +startup script in ${HOME}/matlab/startup.m. + + +------------------------------------------ +3. Licensing, Copyrights and Distribution +------------------------------------------ + +The terms of redistribution for this software are stated in the files +LICENSE.txt and COPYING.txt at the top level of the libSBML +distribution. + + + + + +----------------------------------------------------------------------------- +File author: B. Bornstein, S. Keating, M. Hucka +----------------------------------------------------------------------------- + +# The following is for [X]Emacs users. Please leave in place. +# Local Variables: +# fill-column: 70 +# End: diff --git a/software/libSBML/TranslateSBML.mexa64 b/software/libSBML/TranslateSBML.mexa64 new file mode 100755 index 00000000..6e04323c Binary files /dev/null and b/software/libSBML/TranslateSBML.mexa64 differ diff --git a/software/libSBML/TranslateSBML.mexglx b/software/libSBML/TranslateSBML.mexglx new file mode 100755 index 00000000..290d9ddb Binary files /dev/null and b/software/libSBML/TranslateSBML.mexglx differ diff --git a/software/libSBML/TranslateSBML.mexmaci64 b/software/libSBML/TranslateSBML.mexmaci64 new file mode 100755 index 00000000..10c01475 Binary files /dev/null and b/software/libSBML/TranslateSBML.mexmaci64 differ diff --git a/software/libSBML/TranslateSBML.mexw32 b/software/libSBML/TranslateSBML.mexw32 new file mode 100755 index 00000000..972ba291 Binary files /dev/null and b/software/libSBML/TranslateSBML.mexw32 differ diff --git a/software/libSBML/TranslateSBML.mexw64 b/software/libSBML/TranslateSBML.mexw64 new file mode 100755 index 00000000..56e19908 Binary files /dev/null and b/software/libSBML/TranslateSBML.mexw64 differ diff --git a/software/libSBML/VERSION.txt b/software/libSBML/VERSION.txt new file mode 100644 index 00000000..716cd660 --- /dev/null +++ b/software/libSBML/VERSION.txt @@ -0,0 +1 @@ +5.18.3 diff --git a/software/libSBML/addLevelVersion.m b/software/libSBML/addLevelVersion.m new file mode 100755 index 00000000..4d13ea8b --- /dev/null +++ b/software/libSBML/addLevelVersion.m @@ -0,0 +1,74 @@ +function structure = addLevelVersion(structure, level, version) +% structure = addLevelVersion(structure, level, version) +% +% this function is used internally by TranslateSBML +% +% Takes +% +% 1. structure - any MATLAB_SBML structure +% 2. level - an integer for the value of the level field to be added +% 3. version - an integer for the value of the version field to be added +% +% Returns +% +% 1. structure - the original structure with additional fields 'level' and +% 'version' added to this and every child +% structure +% +% Note: +% The structure must contain a 'typecode' field + +% + +if ~isfield(structure, 'typecode') + return; +end; +if length(structure) ~= 1 ||strcmp(structure.typecode, 'SBML_MODEL') ~= 1 + structure = addData(structure, level, version); +end; +for i = 1:length(structure) + f = fieldnames(structure(i)); + for j = 1:length(f) + if isstruct(structure(i).(f{j})) + substr = structure(i).(f{j}); + structure(i).(f{j}) = addLevelVersion(substr, level, version); + end; + end; +end; + + +function str = addData(str, l, v) +f = fieldnames(str); +if sum(ismember(f, 'level')) > 0 + return; +end; +for i=1:length(str) + str(i).level = l; + str(i).version = v; +end; \ No newline at end of file diff --git a/software/libSBML/applyUserValidation.m b/software/libSBML/applyUserValidation.m new file mode 100755 index 00000000..3af43e13 --- /dev/null +++ b/software/libSBML/applyUserValidation.m @@ -0,0 +1,77 @@ +function [valid, message] = applyUserValidation(SBMLStructure, level, version, packages, pkgVersion) +% [valid, message] = applyUserValidation(SBMLStructure, level, version, packages, pkgVersion) +% +% a script that can be customized by the user to add additional +% validation to the isSBML_Model function +% +% Takes +% +% 1. SBMLstructure - a MATLAB_SBML structure +% 2. level - an integer representing the SBML level +% 3. version - an integer representing the SBML version +% 4. packages - a cell array of the package prefixes used +% e.g. {'fbc'} +% 5. pkgVersion - an array of integers representing the version of each +% package; note indexing should match the +% packages indexing e.g. [1] +% +% Returns +% +% 1. valid = +% - 1, if the structure represents passes the tests imposed +% - 0, otherwise +% 2. a message explaining any failure + +% + +valid = 1; +message = ''; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% example check that all GeneProducts listed have an id value + +% if isempty(packages{1}) +% present = 0; +% else +% [present, index] = ismember('fbc', packages); +% end; +% +% if (present) +% if (pkgVersion(index) == 2) +% gp = SBMLStructure.fbc_geneProduct; +% [a, num] = size(gp); +% for i=1:num +% if (isempty(gp(num).fbc_id)) +% valid = 0; +% message = 'geneProduct is missing the id attribute'; +% end; +% end; +% end; +% end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/software/libSBML/getDefaultValues.m b/software/libSBML/getDefaultValues.m new file mode 100755 index 00000000..8e0ea49f --- /dev/null +++ b/software/libSBML/getDefaultValues.m @@ -0,0 +1,3716 @@ +function [defaultValues] = getDefaultValues(varargin) +% [defaultValues] = getDefaultValues(typecode, level, version, pkgversion(optional)) +% +% Takes +% +% 1. typecode; a string representing the type of object being queried +% 2. level, an integer representing an SBML level +% 3. version, an integer representing an SBML version +% 4. pkgversion, an integer representing the SBML package version +% (defaults to 1) +% +% Returns +% +% 1. an array of default values for an SBML structure of the given typecode, level and version +% +% *NOTE:* The corresponding fields present in an SBML structure can be found using +% the function `getStructureFieldnames` + +% + +typecode = varargin{1}; +level = varargin{2}; +version = varargin{3}; + +pkgCount = 0; + +if (nargin > 3) + if (nargin < 5) + error('not enough arguments'); + end; + pkgCount = length(varargin{4}); + % packages = cell(1, pkgCount); + % pkgVersion = zeros(1, pkgCount); + packages = varargin{4}; + pkgVersion = varargin{5}; +end; + + + defaultValues = []; +done = 1; + + +switch (typecode) + case {'SBML_ALGEBRAIC_RULE', 'AlgebraicRule', 'algebraicRule', 'rule'} + fhandle = str2func('getAlgebraicRuleDefaultValues'); + case {'SBML_ASSIGNMENT_RULE', 'AssignmentRule', 'assignmentRule'} + fhandle = str2func('getAssignmentRuleDefaultValues'); + case {'SBML_COMPARTMENT', 'Compartment', 'compartment'} + fhandle = str2func('getCompartmentDefaultValues'); + case {'SBML_COMPARTMENT_TYPE', 'CompartmentType', 'compartmentType'} + fhandle = str2func('getCompartmentTypeDefaultValues'); + case {'SBML_COMPARTMENT_VOLUME_RULE', 'CompartmentVolumeRule', 'compartmentVolumeRule'} + fhandle = str2func('getCompartmentVolumeRuleDefaultValues'); + case {'SBML_CONSTRAINT', 'Constraint', 'constraint'} + fhandle = str2func('getConstraintDefaultValues'); + case {'SBML_DELAY', 'Delay', 'delay'} + fhandle = str2func('getDelayDefaultValues'); + case {'SBML_EVENT', 'Event', 'event'} + fhandle = str2func('getEventDefaultValues'); + case {'SBML_EVENT_ASSIGNMENT', 'EventAssignment', 'eventAssignment'} + fhandle = str2func('getEventAssignmentDefaultValues'); + case {'SBML_FUNCTION_DEFINITION', 'FunctionDefinition', 'functionDefinition'} + fhandle = str2func('getFunctionDefinitionDefaultValues'); + case {'SBML_INITIAL_ASSIGNMENT', 'InitialAssignment', 'initialAssignment'} + fhandle = str2func('getInitialAssignmentDefaultValues'); + case {'SBML_KINETIC_LAW', 'KineticLaw', 'kineticLaw'} + fhandle = str2func('getKineticLawDefaultValues'); + case {'SBML_LOCAL_PARAMETER', 'LocalParameter', 'localParameter'} + fhandle = str2func('getLocalParameterDefaultValues'); + case {'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getModelDefaultValues'); + case {'SBML_MODIFIER_SPECIES_REFERENCE', 'ModifierSpeciesReference', 'modifierSpeciesReference', 'modifier'} + fhandle = str2func('getModifierSpeciesReferenceDefaultValues'); + case {'SBML_PARAMETER', 'Parameter', 'parameter'} + fhandle = str2func('getParameterDefaultValues'); + case {'SBML_PARAMETER_RULE', 'ParameterRule', 'parameterRule'} + fhandle = str2func('getParameterRuleDefaultValues'); + case {'SBML_PRIORITY', 'Priority', 'priority'} + fhandle = str2func('getPriorityDefaultValues'); + case {'SBML_RATE_RULE', 'RateRule', 'ruleRule'} + fhandle = str2func('getRateRuleDefaultValues'); + case {'SBML_REACTION', 'Reaction', 'reaction'} + fhandle = str2func('getReactionDefaultValues'); + case {'SBML_SPECIES', 'Species', 'species'} + fhandle = str2func('getSpeciesDefaultValues'); + case {'SBML_SPECIES_CONCENTRATION_RULE', 'SpeciesConcentrationRule', 'speciesConcentrationRule'} + fhandle = str2func('getSpeciesConcentrationRuleDefaultValues'); + case {'SBML_SPECIES_REFERENCE', 'SpeciesReference', 'speciesReference', 'reactant', 'Reactant', 'product', 'Product'} + fhandle = str2func('getSpeciesReferenceDefaultValues'); + case {'SBML_SPECIES_TYPE', 'SpeciesType', 'speciesType'} + fhandle = str2func('getSpeciesTypeDefaultValues'); + case {'SBML_STOICHIOMETRY_MATH', 'StoichiometryMath', 'stoichiometryMath'} + fhandle = str2func('getStoichiometryMathDefaultValues'); + case {'SBML_TRIGGER', 'Trigger', 'trigger'} + fhandle = str2func('getTriggerDefaultValues'); + case {'SBML_UNIT', 'Unit', 'unit'} + fhandle = str2func('getUnitDefaultValues'); + case {'SBML_UNIT_DEFINITION', 'UnitDefinition', 'unitDefinition'} + fhandle = str2func('getUnitDefinitionDefaultValues'); + otherwise + done = 0; +end; + +if done == 1 + [defaultValues] = feval(fhandle, level, version); +else + i = 1; + found = 0; + while (i < pkgCount+1) + [found, fhandle] = getFields(typecode, packages{i}, 0); + if (found == 1) + break; + end; + i = i + 1; + end; + if (found == 1) + [defaultValues] = feval(fhandle, level, version, pkgVersion(i)); + done = 1; + end; +end; + +if (done == 1 && pkgCount > 0) + % we may need to extend the fields + i = 1; + while (i < pkgCount+1) + [found, fhandle] = getFields(typecode, packages{i}, 1); + if (found == 1) + copySBML = defaultValues; + [newdefaultValues] = feval(fhandle, level, version, pkgVersion(i)); + defaultValues = [copySBML, newdefaultValues]; + end; + i = i + 1; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [found, fhandle] = getFields(typecode, pkg, extension) + fhandle = str2func('disp'); + found = 0; + if (strcmp(pkg, 'fbc')) + if (extension) + if (isFBCExtension(typecode)) + [found, fhandle] = getFBCDefaultValueFunction(typecode); + end; + else + [found, fhandle] = getFBCDefaultValueFunction(typecode); + end; + elseif strcmp(pkg, 'qual') + if (extension) + if (isQUALExtension(typecode)) + [found, fhandle] = getQUALDefaultValueFunction(typecode); + end; + else + [found, fhandle] = getQUALDefaultValueFunction(typecode); + end; + elseif strcmp(pkg, 'groups') + if (extension) + if (isGROUPSExtension(typecode)) + [found, fhandle] = getGROUPSDefaultValueFunction(typecode); + end; + else + [found, fhandle] = getGROUPSDefaultValueFunction(typecode); + end; + end; +%%%%% REMOVE END +%%%%% ADD ADDITIONAL + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function extend = isFBCExtension(typecode) + extend = 0; + switch (typecode) + case {'SBML_FBC_MODEL', 'FBCModel', 'SBML_MODEL', 'Model', 'model'} + extend = 1; + case {'SBML_FBC_SPECIES', 'FBCSpecies', 'SBML_SPECIES', 'Species', 'species'} + extend = 1; + case {'SBML_FBC_REACTION', 'FBCReaction','SBML_REACTION', 'Reaction', 'reaction'} + extend = 1; + end; + +function extend = isQUALExtension(typecode) + extend = 0; + switch (typecode) + case {'SBML_QUAL_MODEL', 'QUALModel', 'SBML_MODEL', 'Model', 'model'} + extend = 1; + end; + +function extend = isGROUPSExtension(typecode) + extend = 0; + switch (typecode) + case {'SBML_GROUPS_MODEL', 'GROUPSModel', 'SBML_MODEL', 'Model', 'model'} + extend = 1; + end; +%%%% ADD isExtension +%%%% ADD isExtension +%%%% END isExtension + +function [found, fhandle] = getFBCDefaultValueFunction(typecode) + found = 1; + switch (typecode) + case {'SBML_FBC_FLUXBOUND', 'FluxBound', 'fluxBound', 'fbc_fluxBound'} + fhandle = str2func('getFluxBoundDefaultValues'); + case {'SBML_FBC_FLUXOBJECTIVE', 'FluxObjective', 'fluxObjective', 'fbc_fluxObjective'} + fhandle = str2func('getFluxObjectiveDefaultValues'); + case {'SBML_FBC_OBJECTIVE', 'Objective', 'objective', 'fbc_objective'} + fhandle = str2func('getObjectiveDefaultValues'); + case {'SBML_FBC_GENE_PRODUCT', 'GeneProduct', 'geneProduct', 'fbc_geneProduct'} + fhandle = str2func('getGeneProductDefaultValues'); + case {'SBML_FBC_GENE_PRODUCT_ASSOCIATION', 'GeneProductAssociation', 'geneProductAssociation', 'fbc_geneProductAssociation'} + fhandle = str2func('getGeneProductAssociationDefaultValues'); + case {'SBML_FBC_ASSOCIATION', 'Association', 'association', 'fbc_association'} + fhandle = str2func('getAssociationDefaultValues'); + case {'SBML_FBC_MODEL', 'FBCModel', 'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getFBCModelDefaultValues'); + case {'SBML_FBC_SPECIES', 'FBCSpecies', 'SBML_SPECIES', 'Species', 'species'} + fhandle = str2func('getFBCSpeciesDefaultValues'); + case {'SBML_FBC_REACTION', 'FBCReaction','SBML_REACTION', 'Reaction', 'reaction'} + fhandle = str2func('getFBCReactionDefaultValues'); + otherwise + fhandle = str2func('disp'); + found = 0; + end; + +function [found, fhandle] = getQUALDefaultValueFunction(typecode) + found = 1; + switch (typecode) + case {'SBML_QUAL_QUALITATIVE_SPECIES', 'QualitativeSpecies', 'qualitativeSpecies', 'qual_qualitativeSpecies'} + fhandle = str2func('getQualitativeSpeciesDefaultValues'); + case {'SBML_QUAL_TRANSITION', 'Transition', 'transition', 'qual_transition'} + fhandle = str2func('getTransitionDefaultValues'); + case {'SBML_QUAL_INPUT', 'Input', 'input', 'qual_input'} + fhandle = str2func('getInputDefaultValues'); + case {'SBML_QUAL_OUTPUT', 'Output', 'output', 'qual_output'} + fhandle = str2func('getOutputDefaultValues'); + case {'SBML_QUAL_DEFAULT_TERM', 'DefaultTerm', 'defaultTerm', 'qual_defaultTerm'} + fhandle = str2func('getDefaultTermDefaultValues'); + case {'SBML_QUAL_FUNCTION_TERM', 'FunctionTerm', 'functionTerm', 'qual_functionTerm'} + fhandle = str2func('getFunctionTermDefaultValues'); + case {'SBML_QUAL_MODEL', 'QUALModel', 'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getQUALModelDefaultValues'); + otherwise + fhandle = str2func('disp'); + found = 0; + end; + +function [found, fhandle] = getGROUPSDefaultValueFunction(typecode) + found = 1; + switch (typecode) + case {'SBML_GROUPS_GROUP', 'Group', 'group', 'groups_group'} + fhandle = str2func('getGroupDefaultValues'); + case {'SBML_GROUPS_MEMBER', 'Member', 'member', 'groups_member'} + fhandle = str2func('getMemberDefaultValues'); + case {'SBML_GROUPS_MODEL', 'GROUPSModel', 'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getGROUPSModelDefaultValues'); + otherwise + fhandle = str2func('disp'); + found = 0; + end; +%%%% ADD getFieldname +%%%% ADD getFieldname +%%%% END getFieldname +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getAlgebraicRuleDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = { + 'SBML_ALGEBRAIC_RULE', ... + '', ... + '', ... + 'scalar', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_ALGEBRAIC_RULE', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_ALGEBRAIC_RULE', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_ALGEBRAIC_RULE', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_ALGEBRAIC_RULE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_ALGEBRAIC_RULE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_ALGEBRAIC_RULE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getAssignmentRuleDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = []; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_ASSIGNMENT_RULE', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_ASSIGNMENT_RULE', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_ASSIGNMENT_RULE', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_ASSIGNMENT_RULE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_ASSIGNMENT_RULE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_ASSIGNMENT_RULE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getCompartmentDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = { + 'SBML_COMPARTMENT', ... + '', ... + '', ... + '', ... + 1.0, ... + '', ... + '', ... + int32(0), ... + }; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_COMPARTMENT', ... + '', ... + '', ... + '', ... + '', ... + '', ... + int32(3), ... + 0/0, ... + '', ... + '', ... + int32(0), ... + int32(0), ... + int32(0), ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_COMPARTMENT', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + int32(3), ... + 0/0, ... + '', ... + '', ... + int32(0), ... + int32(0), ... + int32(0), ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_COMPARTMENT', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + '', ... + int32(3), ... + 0/0, ... + '', ... + '', ... + int32(0), ... + int32(0), ... + int32(0), ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_COMPARTMENT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + int32(3), ... + 0/0, ... + '', ... + '', ... + int32(0), ... + int32(0), ... + int32(0), ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_COMPARTMENT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + 0/0, ... + 0/0, ... + '', ... + int32(0), ... + int32(0), ... + int32(0), ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_COMPARTMENT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + 0/0, ... + 0/0, ... + '', ... + int32(0), ... + int32(0), ... + int32(0), ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getCompartmentTypeDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = []; +elseif (level == 2) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = { + 'SBML_COMPARTMENT_TYPE', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_COMPARTMENT_TYPE', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_COMPARTMENT_TYPE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = []; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getCompartmentVolumeRuleDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = { + 'SBML_COMPARTMENT_VOLUME_RULE', ... + '', ... + '', ... + 'scalar', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; +elseif (level == 2) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = []; + elseif (version == 3) + defaultValues = []; + elseif (version == 4 || version == 5) + defaultValues = []; + end; +elseif (level == 3) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = []; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getConstraintDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = []; +elseif (level == 2) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = { + 'SBML_CONSTRAINT', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_CONSTRAINT', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_CONSTRAINT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_CONSTRAINT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_CONSTRAINT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getDelayDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = []; +elseif (level == 2) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = []; + elseif (version == 3) + defaultValues = { + 'SBML_DELAY', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_DELAY', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_DELAY', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_DELAY', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getEventAssignmentDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = []; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_EVENT_ASSIGNMENT', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_EVENT_ASSIGNMENT', ... + '', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_EVENT_ASSIGNMENT', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_EVENT_ASSIGNMENT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_EVENT_ASSIGNMENT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_EVENT_ASSIGNMENT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getEventDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = []; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_EVENT', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + [], ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_EVENT', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + int32(-1), ... + [], ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_EVENT', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + [], ... + [], ... + [], ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_EVENT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + int32(0), ... + [], ... + [], ... + [], ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_EVENT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + int32(0), ... + [], ... + [], ... + [], ... + [], ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_EVENT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + int32(0), ... + [], ... + [], ... + [], ... + [], ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getFunctionDefinitionDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = []; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_FUNCTION_DEFINITION', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_FUNCTION_DEFINITION', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + '', ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_FUNCTION_DEFINITION', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + '', ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_FUNCTION_DEFINITION', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_FUNCTION_DEFINITION', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_FUNCTION_DEFINITION', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getInitialAssignmentDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = []; +elseif (level == 2) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = { + 'SBML_INITIAL_ASSIGNMENT', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_INITIAL_ASSIGNMENT', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_INITIAL_ASSIGNMENT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_INITIAL_ASSIGNMENT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_INITIAL_ASSIGNMENT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getKineticLawDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = { + 'SBML_KINETIC_LAW', ... + '', ... + '', ... + '', ... + [], ... + '', ... + '', ... + }; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_KINETIC_LAW', ... + '', ... + '', ... + '', ... + '', ... + '', ... + [], ... + '', ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_KINETIC_LAW', ... + '', ... + '', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_KINETIC_LAW', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + [], ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_KINETIC_LAW', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + [], ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_KINETIC_LAW', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + [], ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_KINETIC_LAW', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + [], ... + '', ... + '', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getLocalParameterDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = []; +elseif (level == 2) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = []; + elseif (version == 3) + defaultValues = []; + elseif (version == 4 || version == 5) + defaultValues = []; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_LOCAL_PARAMETER', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + 0/0, ... + '', ... + int32(0), ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_LOCAL_PARAMETER', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + 0/0, ... + '', ... + int32(0), ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getModelDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = { + 'SBML_MODEL', ... + '', ... + '', ... + level, ... + version, ... + '', ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + }; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_MODEL', ... + '', ... + '', ... + '', ... + level, ... + version, ... + '', ... + '', ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + '', ... + '', ... + [], ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_MODEL', ... + '', ... + '', ... + '', ... + level, ... + version, ... + '', ... + '', ... + int32(-1), ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + '', ... + '', ... + [], ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_MODEL', ... + '', ... + '', ... + '', ... + level, ... + version, ... + '', ... + '', ... + int32(-1), ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + '', ... + '', ... + [], ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_MODEL', ... + '', ... + '', ... + '', ... + [], ... + level, ... + version, ... + '', ... + '', ... + int32(-1), ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + '', ... + '', ... + [], ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_MODEL', ... + '', ... + '', ... + '', ... + [], ... + level, ... + version, ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + int32(-1), ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + '', ... + '', ... + '', ... + [], ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_MODEL', ... + '', ... + '', ... + '', ... + [], ... + level, ... + version, ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + int32(-1), ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + [], ... + '', ... + '', ... + '', ... + '', ... + [], ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getModifierSpeciesReferenceDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = []; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_MODIFIER_SPECIES_REFERENCE', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_MODIFIER_SPECIES_REFERENCE', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + int32(-1), ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_MODIFIER_SPECIES_REFERENCE', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + '', ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_MODIFIER_SPECIES_REFERENCE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_MODIFIER_SPECIES_REFERENCE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_MODIFIER_SPECIES_REFERENCE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getParameterDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = { + 'SBML_PARAMETER', ... + '', ... + '', ... + '', ... + 0/0, ... + '', ... + int32(0), ... + }; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_PARAMETER', ... + '', ... + '', ... + '', ... + '', ... + '', ... + 0/0, ... + '', ... + int32(0), ... + int32(0), ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_PARAMETER', ... + '', ... + '', ... + '', ... + '', ... + '', ... + 0/0, ... + '', ... + int32(0), ... + int32(-1), ... + int32(0), ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_PARAMETER', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + 0/0, ... + '', ... + int32(0), ... + int32(0), ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_PARAMETER', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + 0/0, ... + '', ... + int32(0), ... + int32(0), ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_PARAMETER', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + 0/0, ... + '', ... + int32(0), ... + int32(0), ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_PARAMETER', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + 0/0, ... + '', ... + int32(0), ... + int32(0), ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getParameterRuleDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = { + 'SBML_PARAMETER_RULE', ... + '', ... + '', ... + 'scalar', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; +elseif (level == 2) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = []; + elseif (version == 3) + defaultValues = []; + elseif (version == 4 || version == 5) + defaultValues = []; + end; +elseif (level == 3) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = []; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getPriorityDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = []; +elseif (level == 2) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = []; + elseif (version == 3) + defaultValues = []; + elseif (version == 4 || version == 5) + defaultValues = []; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_PRIORITY', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_PRIORITY', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getRateRuleDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = []; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_RATE_RULE', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_RATE_RULE', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_RATE_RULE', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_RATE_RULE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_RATE_RULE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_RATE_RULE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getReactionDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = { + 'SBML_REACTION', ... + '', ... + '', ... + '', ... + [], ... + [], ... + [], ... + int32(0), ... + int32(0), ... + }; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_REACTION', ... + '', ... + '', ... + '', ... + '', ... + '', ... + [], ... + [], ... + [], ... + [], ... + int32(0), ... + int32(0), ... + int32(0), ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_REACTION', ... + '', ... + '', ... + '', ... + '', ... + '', ... + [], ... + [], ... + [], ... + [], ... + int32(0), ... + int32(0), ... + int32(-1), ... + int32(0), ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_REACTION', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + [], ... + [], ... + [], ... + [], ... + int32(0), ... + int32(0), ... + int32(0), ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_REACTION', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + [], ... + [], ... + [], ... + [], ... + int32(0), ... + int32(0), ... + int32(0), ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_REACTION', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + [], ... + [], ... + [], ... + [], ... + int32(0), ... + int32(0), ... + int32(0), ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_REACTION', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + [], ... + [], ... + [], ... + [], ... + int32(0), ... + '', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getSpeciesConcentrationRuleDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = { + 'SBML_SPECIES_CONCENTRATION_RULE', ... + '', ... + '', ... + 'scalar', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; +elseif (level == 2) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = []; + elseif (version == 3) + defaultValues = []; + elseif (version == 4 || version == 5) + defaultValues = []; + end; +elseif (level == 3) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = []; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getSpeciesDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = { + 'SBML_SPECIES', ... + '', ... + '', ... + '', ... + '', ... + 0/0, ... + '', ... + int32(0), ... + 0, ... + int32(0), ... + int32(0), ... + }; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_SPECIES', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + 0/0, ... + 0/0, ... + '', ... + '', ... + int32(0), ... + int32(0), ... + 0, ... + int32(0), ... + int32(0), ... + int32(0), ... + int32(0), ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_SPECIES', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + 0/0, ... + 0/0, ... + '', ... + '', ... + int32(0), ... + int32(0), ... + 0, ... + int32(0), ... + int32(0), ... + int32(0), ... + int32(0), ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_SPECIES', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + 0/0, ... + 0/0, ... + '', ... + int32(0), ... + int32(0), ... + 0, ... + int32(0), ... + int32(0), ... + int32(0), ... + int32(0), ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_SPECIES', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + 0/0, ... + 0/0, ... + '', ... + int32(0), ... + int32(0), ... + 0, ... + int32(0), ... + int32(0), ... + int32(0), ... + int32(0), ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_SPECIES', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + 0/0, ... + 0/0, ... + '', ... + int32(0), ... + int32(0), ... + int32(0), ... + int32(0), ... + int32(0), ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_SPECIES', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + 0/0, ... + 0/0, ... + '', ... + int32(0), ... + int32(0), ... + int32(0), ... + int32(0), ... + int32(0), ... + '', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getSpeciesReferenceDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = { + 'SBML_SPECIES_REFERENCE', ... + '', ... + '', ... + '', ... + int32(1), ... + int32(1), ... + }; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_SPECIES_REFERENCE', ... + '', ... + '', ... + '', ... + '', ... + 1, ... + int32(1), ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_SPECIES_REFERENCE', ... + '', ... + '', ... + '', ... + '', ... + '', ... + '', ... + int32(-1), ... + 1, ... + '', ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_SPECIES_REFERENCE', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + '', ... + 1, ... + [], ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_SPECIES_REFERENCE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + 1, ... + [], ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_SPECIES_REFERENCE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + 0/0, ... + int32(0), ... + int32(0), ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_SPECIES_REFERENCE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + 0/0, ... + int32(0), ... + int32(0), ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getSpeciesTypeDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = []; +elseif (level == 2) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = { + 'SBML_SPECIES_TYPE', ... + '', ... + '', ... + '', ... + '', ... + '', ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_SPECIES_TYPE', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_SPECIES_TYPE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = []; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getStoichiometryMathDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = []; +elseif (level == 2) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = []; + elseif (version == 3) + defaultValues = { + 'SBML_STOICHIOMETRY_MATH', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_STOICHIOMETRY_MATH', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = []; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getTriggerDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = []; +elseif (level == 2) + if (version == 1) + defaultValues = []; + elseif (version == 2) + defaultValues = []; + elseif (version == 3) + defaultValues = { + 'SBML_TRIGGER', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_TRIGGER', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_TRIGGER', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + int32(0), ... + int32(0), ... + '', ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_TRIGGER', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + int32(0), ... + int32(0), ... + '', ... + '', ... + '', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getUnitDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = { + 'SBML_UNIT', ... + '', ... + '', ... + '', ... + int32(-1), ... + int32(0)', ... + }; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_UNIT', ... + '', ... + '', ... + '', ... + '', ... + int32(1), ... + int32(0), ... + 1.0, ... + 0.0, ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_UNIT', ... + '', ... + '', ... + '', ... + '', ... + int32(1), ... + int32(0), ... + 1.0, ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_UNIT', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + int32(1), ... + int32(0), ... + 1.0, ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_UNIT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + int32(1), ... + int32(0), ... + 1.0, ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_UNIT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + 0/0, ... + 0/0, ... + 0/0, ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_UNIT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + 0/0, ... + 0/0, ... + 0/0, ... + '', ... + '', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [defaultValues] = getUnitDefinitionDefaultValues(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + defaultValues = { + 'SBML_UNIT_DEFINITION', ... + '', ... + '', ... + '', ... + [], ... + }; +elseif (level == 2) + if (version == 1) + defaultValues = { + 'SBML_UNIT_DEFINITION', ... + '', ... + '', ... + '', ... + '', ... + '', ... + [], ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_UNIT_DEFINITION', ... + '', ... + '', ... + '', ... + '', ... + '', ... + [], ... + }; + elseif (version == 3) + defaultValues = { + 'SBML_UNIT_DEFINITION', ... + '', ... + '', ... + '', ... + int32(-1), ... + '', ... + '', ... + [], ... + }; + elseif (version == 4 || version == 5) + defaultValues = { + 'SBML_UNIT_DEFINITION', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + [], ... + }; + end; +elseif (level == 3) + if (version == 1) + defaultValues = { + 'SBML_UNIT_DEFINITION', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + [], ... + }; + elseif (version == 2) + defaultValues = { + 'SBML_UNIT_DEFINITION', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + [], ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFBCModelDefaultValues(level, ... + version, pkgVersion) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { int32(1), ... + [], ... + [], ... + '', ... + }; + nNumberFields = 4; + elseif(pkgVersion ==2) + SBMLfieldnames = { int32(2), ... + [], ... + [], ... + '', ... + 0, ... + }; + nNumberFields = 5; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFBCSpeciesDefaultValues(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion < 3) + SBMLfieldnames = { int32(-1), ... + '', ... + int32(0), ... + 3 ... + int32(version) ... + int32(pkgVersion), ... + }; + nNumberFields = 6; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFluxBoundDefaultValues(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version <3) + if (pkgVersion == 1) + SBMLfieldnames = { 'SBML_FBC_FLUXBOUND', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + 0/0, ... + int32(0), ... + 3 ... + int32(version) ... + 1, ... + }; + nNumberFields = 14; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFluxObjectiveDefaultValues(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion < 3) + SBMLfieldnames = { 'SBML_FBC_FLUXOBJECTIVE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + 0/0, ... + int32(0), ... + 3 ... + int32(version) ... + int32(pkgVersion), ... + }; + nNumberFields = 12; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getObjectiveDefaultValues(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion < 3) + SBMLfieldnames = { 'SBML_FBC_OBJECTIVE', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + [], ... + 3 ... + int32(version) ... + int32(pkgVersion), ... + }; + nNumberFields = 12; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getGeneProductDefaultValues(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + SBMLfieldnames = { 'SBML_FBC_GENE_PRODUCT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + 3 ... + int32(version) ... + int32(pkgVersion), ... + }; + nNumberFields = 13; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFBCReactionDefaultValues(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + SBMLfieldnames = { '', ... + '', ... + [], ... + 3 ... + int32(version) ... + int32(pkgVersion), ... + }; + nNumberFields = 6; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getGeneProductAssociationDefaultValues(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + + SBMLfieldnames = { 'SBML_FBC_GENE_PRODUCT_ASSOCIATION', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + [], ... + 3 ... + int32(version) ... + int32(pkgVersion), ... + }; + nNumberFields = 12; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getAssociationDefaultValues(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + + SBMLfieldnames = { 'SBML_FBC_ASSOCIATION', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + 3 ... + int32(version) ... + int32(pkgVersion), ... + }; + nNumberFields = 10; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getQUALModelDefaultValues(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + int32(pkgVersion), ... + [], ... + [], ... + }; + nNumberFields = 3; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getQualitativeSpeciesDefaultValues(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_QUAL_QUALITATIVE_SPECIES', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + int32(0), ... + int32(0), ... + int32(0), ... + 3, ... + int32(version), ... + int32(pkgVersion), ... + }; + nNumberFields = 15; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getTransitionDefaultValues(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_QUAL_TRANSITION', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + [], ... + [], ... + [], ... + [], ... + 3, ... + int32(version), ... + int32(pkgVersion), ... + }; + nNumberFields = 14; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getInputDefaultValues(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_QUAL_INPUT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + '', ... + int32(0), ... + 3, ... + int32(version), ... + int32(pkgVersion), ... + }; + nNumberFields = 15; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getOutputDefaultValues(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_QUAL_OUTPUT', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + int32(0), ... + 3, ... + int32(version), ... + int32(pkgVersion), ... + }; + nNumberFields = 14; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getDefaultTermDefaultValues(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_QUAL_DEFAULT_TERM', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + int32(0), ... + 3, ... + int32(version), ... + int32(pkgVersion), ... + }; + nNumberFields = 10; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getFunctionTermDefaultValues(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_QUAL_FUNCTION_TERM', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + int32(0), ... + '', ... + 3, ... + int32(version), ... + int32(pkgVersion), ... + }; + nNumberFields = 11; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getGROUPSModelDefaultValues(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + int32(pkgVersion), ... + [], ... + }; + nNumberFields = 2; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getGroupDefaultValues(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_GROUPS_GROUP', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + [], ... + 3, ... + int32(version), ... + int32(pkgVersion), ... + }; + nNumberFields = 13; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getMemberDefaultValues(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_GROUPS_MEMBER', ... + '', ... + '', ... + '', ... + [], ... + int32(-1), ... + '', ... + '', ... + '', ... + '', ... + 3, ... + int32(version), ... + int32(pkgVersion), ... + }; + nNumberFields = 13; + end; + end; + end; + +%%%% ADD functions +%%%% ADD functions + +%%%% END functions + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function valid = isValidLevelVersionCombination(level, version) +valid = 1; + +if ~isIntegralNumber(level) + error('level must be an integer'); +elseif ~isIntegralNumber(version) + error('version must be an integer'); +end; + +if (level < 1 || level > 3) + error('current SBML levels are 1, 2 or 3'); +end; + +if (level == 1) + if (version < 1 || version > 2) + error('SBMLToolbox supports versions 1-2 of SBML Level 1'); + end; + +elseif (level == 2) + if (version < 1 || version > 5) + error('SBMLToolbox supports versions 1-5 of SBML Level 2'); + end; + +elseif (level == 3) + if (version < 1 || version > 2) + error('SBMLToolbox supports version 1-2 of SBML Level 3'); + end; + +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function value = isIntegralNumber(number) +value = 0; + +integerClasses = {'int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64'}; + +% since the function isinteger does not exist in MATLAB Rel 13 +% this is not used +%if (isinteger(number)) +if (ismember(class(number), integerClasses)) + value = 1; +elseif (isnumeric(number)) + % if it is an integer + if (number == fix(number)) + value = 1; + end; +end; + + + diff --git a/software/libSBML/getSBMLDefaultStruct.m b/software/libSBML/getSBMLDefaultStruct.m new file mode 100755 index 00000000..0521b860 --- /dev/null +++ b/software/libSBML/getSBMLDefaultStruct.m @@ -0,0 +1,83 @@ +function sbmlStruct = getSBMLDefaultStruct(varargin) +% structure = getSBMLDefaultStruct(element_name, level, version, +% packages (optional), packageVersion (optional)) +% +% Takes +% +% 1. element_name - the name of the SBML element whose structure is wanted +% 2. level - an integer for the value of the level field to be added +% 3. version - an integer for the value of the version field to be added +% 4. packages, cell array of package names +% 5. packageVersion, an integer array representing the SBML package versions +% +% Returns +% +% 1. structure - the original structure with additional fields 'level' and +% 'version' added to this and every child +% structure +% + +% Thanks to Thomas Pfau for providing this function. + +% + +pkgCount = 0; + +if (nargin < 3) + error('not enough input arguments'); +else + element_name = varargin{1}; + level = varargin{2}; + version = varargin{3}; +end; +packages = {}; +packageVersion = 1; +if (nargin > 3) + if (nargin < 5) + error('not enough input arguments'); + end; + pkgCount = length(varargin{4}); + packages = varargin{4}; + if (length(varargin{5}) ~= pkgCount) + error('need a version number for each package'); + end; + packageVersion = varargin{5}; +end; + +fieldData = [getStructureFieldnames(element_name, level, version, ... +packages, packageVersion) ; getDefaultValues(element_name, level, ... +version, packages, packageVersion)]; + +if ~isempty(fieldData) + fieldData = reshape(fieldData,numel(fieldData),1); + sbmlStruct = struct(fieldData{:}); +else + sbmlStruct = struct(); +end; +end \ No newline at end of file diff --git a/software/libSBML/getStructure.m b/software/libSBML/getStructure.m new file mode 100755 index 00000000..1a046be4 --- /dev/null +++ b/software/libSBML/getStructure.m @@ -0,0 +1,66 @@ +function [fieldnames, defaults, valuetypes, num] = getStructure(varargin) +% [SBMLfieldnames, nNumberFields] = getStructure(typecode, level, version, pkgversion(optional)) +% +% Takes +% +% 1. typecode; a string representing the type of object being queried +% 2. level, an integer representing an SBML level +% 3. version, an integer representing an SBML version +% 4. pkgversion, an integer representing the SBML package version +% (defaults to 1) +% +% Returns +% +% 1. an array of fieldnames for an SBML structure of the given typecode, level and version +% 2. an array of default Values +% 3. an array of value types +% 4. the number of fieldnames +% + +% + +typecode = varargin{1}; +level = varargin{2}; +version = varargin{3}; + +pkgCount = 0; + +if (nargin > 3) + if (nargin < 5) + error('not enough arguments'); + end; + packages = varargin{4}; + pkgVersion = varargin{5}; + [fieldnames, num] = getStructureEnum(typecode, level, version, packages, pkgVersion); + defaults = getDefaultValues(typecode, level, version, packages, pkgVersion); + valuetypes = getValueType(typecode, level, version, packages, pkgVersion); +else + [fieldnames, num] = getStructureEnum(typecode, level, version); + defaults = getDefaultValues(typecode, level, version); + valuetypes = getValueType(typecode, level, version); +end; \ No newline at end of file diff --git a/software/libSBML/getStructureEnum.m b/software/libSBML/getStructureEnum.m new file mode 100755 index 00000000..e7086bd5 --- /dev/null +++ b/software/libSBML/getStructureEnum.m @@ -0,0 +1,3289 @@ +function [SBMLfieldnames, nNumberFields] = getStructureEnum(varargin) +% [SBMLfieldnames, nNumberFields] = getStructureFieldnames(typecode, level, version, pkgversion(optional)) +% +% Takes +% +% 1. typecode; a string representing the type of object being queried +% 2. level, an integer representing an SBML level +% 3. version, an integer representing an SBML version +% 4. pkgversion, an integer representing the SBML package version +% (defaults to 1) +% +% Returns +% +% 1. an array of fieldnames for an SBML structure of the given typecode, level and version +% 2. the number of fieldnames +% + +% + +typecode = varargin{1}; +level = varargin{2}; +version = varargin{3}; + +pkgCount = 0; + +if (nargin > 3) + if (nargin < 5) + error('not enough arguments'); + end; + pkgCount = length(varargin{4}); + % packages = cell(1, pkgCount); + % pkgVersion = zeros(1, pkgCount); + packages = varargin{4}; + pkgVersion = varargin{5}; +end; + + + SBMLfieldnames = []; + nNumberFields = 0; +done = 1; + + +switch (typecode) + case {'SBML_ALGEBRAIC_RULE', 'AlgebraicRule', 'algebraicRule', 'rule'} + fhandle = str2func('getAlgebraicRuleFieldnames'); + case {'SBML_ASSIGNMENT_RULE', 'AssignmentRule', 'assignmentRule'} + fhandle = str2func('getAssignmentRuleFieldnames'); + case {'SBML_COMPARTMENT', 'Compartment', 'compartment'} + fhandle = str2func('getCompartmentFieldnames'); + case {'SBML_COMPARTMENT_TYPE', 'CompartmentType', 'compartmentType'} + fhandle = str2func('getCompartmentTypeFieldnames'); + case {'SBML_COMPARTMENT_VOLUME_RULE', 'CompartmentVolumeRule', 'compartmentVolumeRule'} + fhandle = str2func('getCompartmentVolumeRuleFieldnames'); + case {'SBML_CONSTRAINT', 'Constraint', 'constraint'} + fhandle = str2func('getConstraintFieldnames'); + case {'SBML_DELAY', 'Delay', 'delay'} + fhandle = str2func('getDelayFieldnames'); + case {'SBML_EVENT', 'Event', 'event'} + fhandle = str2func('getEventFieldnames'); + case {'SBML_EVENT_ASSIGNMENT', 'EventAssignment', 'eventAssignment'} + fhandle = str2func('getEventAssignmentFieldnames'); + case {'SBML_FUNCTION_DEFINITION', 'FunctionDefinition', 'functionDefinition'} + fhandle = str2func('getFunctionDefinitionFieldnames'); + case {'SBML_INITIAL_ASSIGNMENT', 'InitialAssignment', 'initialAssignment'} + fhandle = str2func('getInitialAssignmentFieldnames'); + case {'SBML_KINETIC_LAW', 'KineticLaw', 'kineticLaw'} + fhandle = str2func('getKineticLawFieldnames'); + case {'SBML_LOCAL_PARAMETER', 'LocalParameter', 'localParameter'} + fhandle = str2func('getLocalParameterFieldnames'); + case {'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getModelFieldnames'); + case {'SBML_MODIFIER_SPECIES_REFERENCE', 'ModifierSpeciesReference', 'modifierSpeciesReference', 'modifier'} + fhandle = str2func('getModifierSpeciesReferenceFieldnames'); + case {'SBML_PARAMETER', 'Parameter', 'parameter'} + fhandle = str2func('getParameterFieldnames'); + case {'SBML_PARAMETER_RULE', 'ParameterRule', 'parameterRule'} + fhandle = str2func('getParameterRuleFieldnames'); + case {'SBML_PRIORITY', 'Priority', 'priority'} + fhandle = str2func('getPriorityFieldnames'); + case {'SBML_RATE_RULE', 'RateRule', 'ruleRule'} + fhandle = str2func('getRateRuleFieldnames'); + case {'SBML_REACTION', 'Reaction', 'reaction'} + fhandle = str2func('getReactionFieldnames'); + case {'SBML_SPECIES', 'Species', 'species'} + fhandle = str2func('getSpeciesFieldnames'); + case {'SBML_SPECIES_CONCENTRATION_RULE', 'SpeciesConcentrationRule', 'speciesConcentrationRule'} + fhandle = str2func('getSpeciesConcentrationRuleFieldnames'); + case {'SBML_SPECIES_REFERENCE', 'SpeciesReference', 'speciesReference', 'reactant', 'Reactant', 'product', 'Product'} + fhandle = str2func('getSpeciesReferenceFieldnames'); + case {'SBML_SPECIES_TYPE', 'SpeciesType', 'speciesType'} + fhandle = str2func('getSpeciesTypeFieldnames'); + case {'SBML_STOICHIOMETRY_MATH', 'StoichiometryMath', 'stoichiometryMath'} + fhandle = str2func('getStoichiometryMathFieldnames'); + case {'SBML_TRIGGER', 'Trigger', 'trigger'} + fhandle = str2func('getTriggerFieldnames'); + case {'SBML_UNIT', 'Unit', 'unit'} + fhandle = str2func('getUnitFieldnames'); + case {'SBML_UNIT_DEFINITION', 'UnitDefinition', 'unitDefinition'} + fhandle = str2func('getUnitDefinitionFieldnames'); + otherwise + done = 0; +end; + +if done == 1 + [SBMLfieldnames, nNumberFields] = feval(fhandle, level, version); +else + i = 1; + found = 0; + while (i < pkgCount+1) + [found, fhandle] = getFields(typecode, packages{i}, 0); + if (found == 1) + break; + end; + i = i + 1; + end; + if (found == 1) + [SBMLfieldnames, nNumberFields] = feval(fhandle, level, version, pkgVersion(i)); + done = 1; + end; +end; + +if (done == 1 && pkgCount > 0) + % we may need to extend the fields + i = 1; + while (i < pkgCount+1) + [found, fhandle] = getFields(typecode, packages{i}, 1); + if (found == 1) + copySBML = SBMLfieldnames; + [newSBMLfieldnames, newNumberFields] = feval(fhandle, level, version, pkgVersion(i)); + SBMLfieldnames = [copySBML, newSBMLfieldnames]; + nNumberFields = nNumberFields + newNumberFields; + end; + i = i + 1; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [found, fhandle] = getFields(typecode, pkg, extension) + fhandle = str2func('disp'); + found = 0; + if (strcmp(pkg, 'fbc')) + if (extension) + if (isFBCExtension(typecode)) + [found, fhandle] = getFBCFieldnameFunction(typecode); + end; + else + [found, fhandle] = getFBCFieldnameFunction(typecode); + end; + elseif strcmp(pkg, 'qual') + if (extension) + if (isQUALExtension(typecode)) + [found, fhandle] = getQUALFieldnameFunction(typecode); + end; + else + [found, fhandle] = getQUALFieldnameFunction(typecode); + end; + elseif strcmp(pkg, 'groups') + if (extension) + if (isGROUPSExtension(typecode)) + [found, fhandle] = getGROUPSFieldnameFunction(typecode); + end; + else + [found, fhandle] = getGROUPSFieldnameFunction(typecode); + end; + end; +%%%%% REMOVE END +%%%%% ADD ADDITIONAL + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function extend = isFBCExtension(typecode) + extend = 0; + switch (typecode) + case {'SBML_FBC_MODEL', 'FBCModel', 'SBML_MODEL', 'Model', 'model'} + extend = 1; + case {'SBML_FBC_SPECIES', 'FBCSpecies', 'SBML_SPECIES', 'Species', 'species'} + extend = 1; + case {'SBML_FBC_REACTION', 'FBCReaction','SBML_REACTION', 'Reaction', 'reaction'} + extend = 1; + end; + +function extend = isQUALExtension(typecode) + extend = 0; + switch (typecode) + case {'SBML_QUAL_MODEL', 'QUALModel', 'SBML_MODEL', 'Model', 'model'} + extend = 1; + end; + +function extend = isGROUPSExtension(typecode) + extend = 0; + switch (typecode) + case {'SBML_GROUPS_MODEL', 'GROUPSModel', 'SBML_MODEL', 'Model', 'model'} + extend = 1; + end; +%%%% ADD isExtension +%%%% ADD isExtension +%%%% END isExtension + +function [found, fhandle] = getFBCFieldnameFunction(typecode) + found = 1; + switch (typecode) + case {'SBML_FBC_FLUXBOUND', 'FluxBound', 'fluxBound', 'fbc_fluxBound'} + fhandle = str2func('getFluxBoundFieldnames'); + case {'SBML_FBC_FLUXOBJECTIVE', 'FluxObjective', 'fluxObjective', 'fbc_fluxObjective'} + fhandle = str2func('getFluxObjectiveFieldnames'); + case {'SBML_FBC_OBJECTIVE', 'Objective', 'objective', 'fbc_objective'} + fhandle = str2func('getObjectiveFieldnames'); + case {'SBML_FBC_GENE_PRODUCT', 'GeneProduct', 'geneProduct', 'fbc_geneProduct'} + fhandle = str2func('getGeneProductFieldnames'); + case {'SBML_FBC_GENE_PRODUCT_ASSOCIATION', 'GeneProductAssociation', 'geneProductAssociation', 'fbc_geneProductAssociation'} + fhandle = str2func('getGeneProductAssociationFieldnames'); + case {'SBML_FBC_ASSOCIATION', 'Association', 'association', 'fbc_association'} + fhandle = str2func('getAssociationFieldnames'); + case {'SBML_FBC_MODEL', 'FBCModel', 'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getFBCModelFieldnames'); + case {'SBML_FBC_SPECIES', 'FBCSpecies', 'SBML_SPECIES', 'Species', 'species'} + fhandle = str2func('getFBCSpeciesFieldnames'); + case {'SBML_FBC_REACTION', 'FBCReaction','SBML_REACTION', 'Reaction', 'reaction'} + fhandle = str2func('getFBCReactionFieldnames'); + otherwise + fhandle = str2func('disp'); + found = 0; + end; + +function [found, fhandle] = getQUALFieldnameFunction(typecode) + found = 1; + switch (typecode) + case {'SBML_QUAL_QUALITATIVE_SPECIES', 'QualitativeSpecies', 'qualitativeSpecies', 'qual_qualitativeSpecies'} + fhandle = str2func('getQualitativeSpeciesFieldnames'); + case {'SBML_QUAL_TRANSITION', 'Transition', 'transition', 'qual_transition'} + fhandle = str2func('getTransitionFieldnames'); + case {'SBML_QUAL_INPUT', 'Input', 'input', 'qual_input'} + fhandle = str2func('getInputFieldnames'); + case {'SBML_QUAL_OUTPUT', 'Output', 'output', 'qual_output'} + fhandle = str2func('getOutputFieldnames'); + case {'SBML_QUAL_DEFAULT_TERM', 'DefaultTerm', 'defaultTerm', 'qual_defaultTerm'} + fhandle = str2func('getDefaultTermFieldnames'); + case {'SBML_QUAL_FUNCTION_TERM', 'FunctionTerm', 'functionTerm', 'qual_functionTerm'} + fhandle = str2func('getFunctionTermFieldnames'); + case {'SBML_QUAL_MODEL', 'QUALModel', 'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getQUALModelFieldnames'); + otherwise + fhandle = str2func('disp'); + found = 0; + end; + +function [found, fhandle] = getGROUPSFieldnameFunction(typecode) + found = 1; + switch (typecode) + case {'SBML_GROUPS_GROUP', 'Group', 'group', 'groups_group'} + fhandle = str2func('getGroupFieldnames'); + case {'SBML_GROUPS_MEMBER', 'Member', 'member', 'groups_member'} + fhandle = str2func('getMemberFieldnames'); + case {'SBML_GROUPS_MODEL', 'GROUPSModel', 'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getGROUPSModelFieldnames'); + otherwise + fhandle = str2func('disp'); + found = 0; + end; +%%%% ADD getFieldname +%%%% ADD getFieldname +%%%% END getFieldname + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getAlgebraicRuleFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'type','','',0,6}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 10; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 10; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 11; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 11; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 12; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 12; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + }; + nNumberFields = 14; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getAssignmentRuleFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 10; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 11; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 11; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 12; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 12; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + }; + nNumberFields = 14; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getCompartmentFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'volume','volume','',1,20}, ... + {'units','units','',1,20}, ... + {'outside','outside','',1,20}, ... + {'isSetVolume','volume','',0,7}, ... + }; + nNumberFields = 8; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'spatialDimensions','spatialDimensions','',1,20}, ... + {'size','size','',1,20}, ... + {'units','units','',1,20}, ... + {'outside','outside','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetSize','size','',0,7}, ... + {'isSetVolume','volume','',0,7}, ... + }; + nNumberFields = 13; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'compartmentType','compartmentType','',1,20}, ... + {'spatialDimensions','spatialDimensions','',1,20}, ... + {'size','size','',1,20}, ... + {'units','units','',1,20}, ... + {'outside','outside','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetSize','size','',0,7}, ... + {'isSetVolume','volume','',0,7}, ... + }; + nNumberFields = 14; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'compartmentType','compartmentType','',1,20}, ... + {'spatialDimensions','spatialDimensions','',1,20}, ... + {'size','size','',1,20}, ... + {'units','units','',1,20}, ... + {'outside','outside','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetSize','size','',0,7}, ... + {'isSetVolume','volume','',0,7}, ... + }; + nNumberFields = 15; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'compartmentType','compartmentType','',1,20}, ... + {'spatialDimensions','spatialDimensions','',1,20}, ... + {'size','size','',1,20}, ... + {'units','units','',1,20}, ... + {'outside','outside','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetSize','size','',0,7}, ... + {'isSetVolume','volume','',0,7}, ... + }; + nNumberFields = 16; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'spatialDimensions','spatialDimensions','',1,20}, ... + {'size','size','',1,20}, ... + {'units','units','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetSize','size','',0,7}, ... + {'isSetSpatialDimensions','spatialDimensions','',0,7}, ... + }; + nNumberFields = 14; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'spatialDimensions','spatialDimensions','',1,20}, ... + {'size','size','',1,20}, ... + {'units','units','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetSize','size','',0,7}, ... + {'isSetSpatialDimensions','spatialDimensions','',0,7}, ... + }; + nNumberFields = 14; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getCompartmentTypeFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + }; + nNumberFields = 6; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + }; + nNumberFields = 7; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + }; + nNumberFields = 8; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 2; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getCompartmentVolumeRuleFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'type','','',0,6}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 10; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 3) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 4 || version == 5) + SBMLfieldnames = []; + nNumberFields = 0; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 2; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getConstraintFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + {'message','message','',1,8}, ... + }; + nNumberFields = 7; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + {'message','message','',1,8}, ... + }; + nNumberFields = 7; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + {'message','message','',1,8}, ... + }; + nNumberFields = 8; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + {'message','message','',1,8}, ... + }; + nNumberFields = 8; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + {'message','message','',1,8}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + }; + nNumberFields = 10; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getDelayFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 6; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 7; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 7; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + }; + nNumberFields =9; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getEventAssignmentFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'variable','variable','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 6; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'variable','variable','',1,20}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 7; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'variable','variable','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 7; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'variable','variable','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 8; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'variable','variable','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 8; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'variable','variable','',1,20}, ... + {'math','math','',1,5}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + }; + nNumberFields = 10; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getEventFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'trigger','trigger','',1,13}, ... + {'delay','delay','',1,13}, ... + {'timeUnits','timeUnits','',1,20}, ... + {'eventAssignment','eventAssignment','',1,20}, ... + }; + nNumberFields = 10; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'trigger','trigger','',1,13}, ... + {'delay','delay','',1,13}, ... + {'timeUnits','timeUnits','',1,20}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'eventAssignment','eventAssignment','',1,20}, ... + }; + nNumberFields = 11; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'trigger','trigger','',1,20}, ... + {'delay','delay','',1,20}, ... + {'eventAssignment','eventAssignment','',1,20}, ... + }; + nNumberFields = 10; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'useValuesFromTriggerTime','useValuesFromTriggerTime','',1,20}, ... + {'trigger','trigger','',1,20}, ... + {'delay','delay','',1,20}, ... + {'eventAssignment','eventAssignment','',1,20}, ... + }; + nNumberFields = 12; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'useValuesFromTriggerTime','useValuesFromTriggerTime','',1,20}, ... + {'trigger','trigger','',1,20}, ... + {'delay','delay','',1,20}, ... + {'priority','priority','',1,20}, ... + {'eventAssignment','eventAssignment','',1,20}, ... + }; + nNumberFields = 13; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'useValuesFromTriggerTime','useValuesFromTriggerTime','',1,20}, ... + {'trigger','trigger','',1,20}, ... + {'delay','delay','',1,20}, ... + {'priority','priority','',1,20}, ... + {'eventAssignment','eventAssignment','',1,20}, ... + }; + nNumberFields = 13; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getFunctionDefinitionFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 7; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 8; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 8; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 9; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 9; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 9; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getInitialAssignmentFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'symbol','symbol','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 7; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'symbol','symbol','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 7; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'symbol','symbol','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 8; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'symbol','symbol','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 8; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'symbol','symbol','',1,20}, ... + {'math','math','',1,5}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + }; + nNumberFields = 10; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getKineticLawFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'formula','formula','',1,5}, ... + {'parameter','parameter','',1,20}, ... + {'timeUnits','timeUnits','',1,20}, ... + {'substanceUnits','substanceUnits','',1,20}, ... + }; + nNumberFields = 7; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'formula','formula','',1,5}, ... + {'math','math','',1,5}, ... + {'parameter','parameter','',1,20}, ... + {'timeUnits','timeUnits','',1,20}, ... + {'substanceUnits','substanceUnits','',1,20}, ... + }; + nNumberFields = 9; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'formula','formula','',1,5}, ... + {'math','math','',1,5}, ... + {'parameter','parameter','',1,20}, ... + {'sboTerm','sboTerm','',1,20}, ... + }; + nNumberFields = 8; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'math','math','',1,5}, ... + {'parameter','parameter','',1,20}, ... + }; + nNumberFields = 8; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'math','math','',1,5}, ... + {'parameter','parameter','',1,20}, ... + }; + nNumberFields = 9; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + {'localParameter','localParameter','',1,20}, ... + }; + nNumberFields = 8; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + {'localParameter','localParameter','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + }; + nNumberFields = 10; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getLocalParameterFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'value','value','',1,20}, ... + {'units','units','',1,20}, ... + {'isSetValue','value','',0,7}, ... + }; + nNumberFields = 11; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'value','value','',1,20}, ... + {'units','units','',1,20}, ... + {'isSetValue','value','',0,7}, ... + }; + nNumberFields = 11; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getModelFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'SBML_level','','',0,0}, ... + {'SBML_version','','',0,0}, ... + {'name','name','',1,20}, ... + {'unitDefinition','unitDefinition','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'species','species','',1,20}, ... + {'parameter','parameter','',1,20}, ... + {'rule','rule','',1,20}, ... + {'reaction','reaction','',1,20}, ... + {'namespaces','','',0,3}, ... + }; + nNumberFields = 13; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'SBML_level','','',0,0}, ... + {'SBML_version','','',0,0}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'functionDefinition','functionDefinition','',1,20}, ... + {'unitDefinition','unitDefinition','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'species','species','',1,20}, ... + {'parameter','parameter','',1,20}, ... + {'rule','rule','',1,20}, ... + {'reaction','reaction','',1,20}, ... + {'event','event','',1,20}, ... + {'time_symbol','','',0,9}, ... + {'delay_symbol','','',0,10}, ... + {'namespaces','','',0,3}, ... + }; + nNumberFields = 19; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'SBML_level','','',0,0}, ... + {'SBML_version','','',0,0}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'functionDefinition','functionDefinition','',1,20}, ... + {'unitDefinition','unitDefinition','',1,20}, ... + {'compartmentType','compartmentType','',1,20}, ... + {'speciesType','speciesType','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'species','species','',1,20}, ... + {'parameter','parameter','',1,20}, ... + {'initialAssignment','initialAssignment','',1,20}, ... + {'rule','rule','',1,20}, ... + {'constraint','constraint','',1,20}, ... + {'reaction','reaction','',1,20}, ... + {'event','event','',1,20}, ... + {'time_symbol','','',0,9}, ... + {'delay_symbol','','',0,10}, ... + {'namespaces','','',0,3}, ... + }; + nNumberFields = 24; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'SBML_level','','',0,0}, ... + {'SBML_version','','',0,0}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'functionDefinition','functionDefinition','',1,20}, ... + {'unitDefinition','unitDefinition','',1,20}, ... + {'compartmentType','compartmentType','',1,20}, ... + {'speciesType','speciesType','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'species','species','',1,20}, ... + {'parameter','parameter','',1,20}, ... + {'initialAssignment','initialAssignment','',1,20}, ... + {'rule','rule','',1,20}, ... + {'constraint','constraint','',1,20}, ... + {'reaction','reaction','',1,20}, ... + {'event','event','',1,20}, ... + {'time_symbol','','',0,9}, ... + {'delay_symbol','','',0,10}, ... + {'namespaces','','',0,3}, ... + }; + nNumberFields = 24; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'SBML_level','','',0,0}, ... + {'SBML_version','','',0,0}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'functionDefinition','functionDefinition','',1,20}, ... + {'unitDefinition','unitDefinition','',1,20}, ... + {'compartmentType','compartmentType','',1,20}, ... + {'speciesType','speciesType','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'species','species','',1,20}, ... + {'parameter','parameter','',1,20}, ... + {'initialAssignment','initialAssignment','',1,20}, ... + {'rule','rule','',1,20}, ... + {'constraint','constraint','',1,20}, ... + {'reaction','reaction','',1,20}, ... + {'event','event','',1,20}, ... + {'time_symbol','','',0,9}, ... + {'delay_symbol','','',0,10}, ... + {'namespaces','','',0,3}, ... + }; + nNumberFields = 25; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'SBML_level','','',0,0}, ... + {'SBML_version','','',0,0}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'timeUnits','timeUnits','',1,20}, ... + {'substanceUnits','substanceUnits','',1,20}, ... + {'volumeUnits','volumeUnits','',1,20}, ... + {'areaUnits','areaUnits','',1,20}, ... + {'lengthUnits','lengthUnits','',1,20}, ... + {'extentUnits','extentUnits','',1,20}, ... + {'conversionFactor','conversionFactor','',1,20}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'functionDefinition','functionDefinition','',1,20}, ... + {'unitDefinition','unitDefinition','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'species','species','',1,20}, ... + {'parameter','parameter','',1,20}, ... + {'initialAssignment','initialAssignment','',1,20}, ... + {'rule','rule','',1,20}, ... + {'constraint','constraint','',1,20}, ... + {'reaction','reaction','',1,20}, ... + {'event','event','',1,20}, ... + {'time_symbol','','',0,9}, ... + {'delay_symbol','','',0,10}, ... + {'avogadro_symbol','','',0,11}, ... + {'namespaces','','',0,3}, ... + }; + nNumberFields = 31; + elseif (version == 2) + SBMLfieldnames = { + {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'SBML_level','','',0,0}, ... + {'SBML_version','','',0,0}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'timeUnits','timeUnits','',1,20}, ... + {'substanceUnits','substanceUnits','',1,20}, ... + {'volumeUnits','volumeUnits','',1,20}, ... + {'areaUnits','areaUnits','',1,20}, ... + {'lengthUnits','lengthUnits','',1,20}, ... + {'extentUnits','extentUnits','',1,20}, ... + {'conversionFactor','conversionFactor','',1,20}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'functionDefinition','functionDefinition','',1,20}, ... + {'unitDefinition','unitDefinition','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'species','species','',1,20}, ... + {'parameter','parameter','',1,20}, ... + {'initialAssignment','initialAssignment','',1,20}, ... + {'rule','rule','',1,20}, ... + {'constraint','constraint','',1,20}, ... + {'reaction','reaction','',1,20}, ... + {'event','event','',1,20}, ... + {'time_symbol','','',0,9}, ... + {'delay_symbol','','',0,10}, ... + {'avogadro_symbol','','',0,11}, ... + {'rateOf_symbol','','',0,12}, ... + {'namespaces','','',0,3}, ... + }; + nNumberFields = 32; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getModifierSpeciesReferenceFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'species','species','',1,20}, ... + }; + nNumberFields = 5; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'species','species','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + {'sboTerm','sboTerm','',1,20}, ... + }; + nNumberFields = 8; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'species','species','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + }; + nNumberFields = 8; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'species','species','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + }; + nNumberFields = 9; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'species','species','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + }; + nNumberFields = 9; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'species','species','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + }; + nNumberFields = 11; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getParameterFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'value','value','',1,20}, ... + {'units','units','',1,20}, ... + {'isSetValue','value','',0,7}, ... + }; + nNumberFields = 7; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'value','value','',1,20}, ... + {'units','units','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetValue','value','',0,7}, ... + }; + nNumberFields = 10; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'value','value','',1,20}, ... + {'units','units','',1,20}, ... + {'constant','constant','',1,20}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'isSetValue','value','',0,7}, ... + }; + nNumberFields = 11; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'value','value','',1,20}, ... + {'units','units','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetValue','value','',0,7}, ... + }; + nNumberFields = 11; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'value','value','',1,20}, ... + {'units','units','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetValue','value','',0,7}, ... + }; + nNumberFields = 12; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'value','value','',1,20}, ... + {'units','units','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetValue','value','',0,7}, ... + }; + nNumberFields = 12; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'value','value','',1,20}, ... + {'units','units','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetValue','value','',0,7}, ... + }; + nNumberFields = 12; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getParameterRuleFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'type','','',0,6}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 10; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 3) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 4 || version == 5) + SBMLfieldnames = []; + nNumberFields = 0; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 2; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getPriorityFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 7; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + }; + nNumberFields = 9; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getRateRuleFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 10; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 11; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 11; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 12; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 12; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + }; + nNumberFields = 14; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getReactionFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'reactant','reactant','',1,20}, ... + {'product','product','',1,20}, ... + {'kineticLaw','kineticLaw','',1,20}, ... + {'reversible','reversible','',1,20}, ... + {'fast','fast','',1,20}, ... + }; + nNumberFields = 9; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'reactant','reactant','',1,20}, ... + {'product','product','',1,20}, ... + {'modifier','modifier','',1,20}, ... + {'kineticLaw','kineticLaw','',1,20}, ... + {'reversible','reversible','',1,20}, ... + {'fast','fast','',1,20}, ... + {'isSetFast','fast','',0,7}, ... + }; + nNumberFields = 13; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'reactant','reactant','',1,20}, ... + {'product','product','',1,20}, ... + {'modifier','modifier','',1,20}, ... + {'kineticLaw','kineticLaw','',1,20}, ... + {'reversible','reversible','',1,20}, ... + {'fast','fast','',1,20}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'isSetFast','fast','',0,7}, ... + }; + nNumberFields = 14; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'reactant','reactant','',1,20}, ... + {'product','product','',1,20}, ... + {'modifier','modifier','',1,20}, ... + {'kineticLaw','kineticLaw','',1,20}, ... + {'reversible','reversible','',1,20}, ... + {'fast','fast','',1,20}, ... + {'isSetFast','fast','',0,7}, ... + }; + nNumberFields = 14; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'reactant','reactant','',1,20}, ... + {'product','product','',1,20}, ... + {'modifier','modifier','',1,20}, ... + {'kineticLaw','kineticLaw','',1,20}, ... + {'reversible','reversible','',1,20}, ... + {'fast','fast','',1,20}, ... + {'isSetFast','fast','',0,7}, ... + }; + nNumberFields = 15; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'reactant','reactant','',1,20}, ... + {'product','product','',1,20}, ... + {'modifier','modifier','',1,20}, ... + {'kineticLaw','kineticLaw','',1,20}, ... + {'reversible','reversible','',1,20}, ... + {'fast','fast','',1,20}, ... + {'isSetFast','fast','',0,7}, ... + {'compartment','compartment','',1,20}, ... + }; + nNumberFields = 16; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'reactant','reactant','',1,20}, ... + {'product','product','',1,20}, ... + {'modifier','modifier','',1,20}, ... + {'kineticLaw','kineticLaw','',1,20}, ... + {'reversible','reversible','',1,20}, ... + {'compartment','compartment','',1,20}, ... + }; + nNumberFields = 14; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getSpeciesConcentrationRuleFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'type','','',0,6}, ... + {'formula','formula','',1,5}, ... + {'variable','variable','',1,20}, ... + {'species','species','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'name','name','',1,20}, ... + {'units','units','',1,20}, ... + }; + nNumberFields = 10; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 3) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 4 || version == 5) + SBMLfieldnames = []; + nNumberFields = 0; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 2; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getSpeciesFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'initialAmount','initialAmount','',1,20}, ... + {'units','units','',1,20}, ... + {'boundaryCondition','boundaryCondition','',1,20}, ... + {'charge','charge','',1,20}, ... + {'isSetInitialAmount','initialAmount','',0,7}, ... + {'isSetCharge','charge','',0,7}, ... + }; + nNumberFields = 11; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'initialAmount','initialAmount','',1,20}, ... + {'initialConcentration','initialConcentration','',1,20}, ... + {'substanceUnits','substanceUnits','',1,20}, ... + {'spatialSizeUnits','spatialSizeUnits','',1,20}, ... + {'hasOnlySubstanceUnits','hasOnlySubstanceUnits','',1,20}, ... + {'boundaryCondition','boundaryCondition','',1,20}, ... + {'charge','charge','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetInitialAmount','initialAmount','',0,7}, ... + {'isSetInitialConcentration','initialConcentration','',0,7}, ... + {'isSetCharge','charge','',0,7}, ... + }; + nNumberFields = 18; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'speciesType','speciesType','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'initialAmount','initialAmount','',1,20}, ... + {'initialConcentration','initialConcentration','',1,20}, ... + {'substanceUnits','substanceUnits','',1,20}, ... + {'spatialSizeUnits','spatialSizeUnits','',1,20}, ... + {'hasOnlySubstanceUnits','hasOnlySubstanceUnits','',1,20}, ... + {'boundaryCondition','boundaryCondition','',1,20}, ... + {'charge','charge','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetInitialAmount','initialAmount','',0,7}, ... + {'isSetInitialConcentration','initialConcentration','',0,7}, ... + {'isSetCharge','charge','',0,7}, ... + }; + nNumberFields = 19; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'speciesType','speciesType','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'initialAmount','initialAmount','',1,20}, ... + {'initialConcentration','initialConcentration','',1,20}, ... + {'substanceUnits','substanceUnits','',1,20}, ... + {'hasOnlySubstanceUnits','hasOnlySubstanceUnits','',1,20}, ... + {'boundaryCondition','boundaryCondition','',1,20}, ... + {'charge','charge','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetInitialAmount','initialAmount','',0,7}, ... + {'isSetInitialConcentration','initialConcentration','',0,7}, ... + {'isSetCharge','charge','',0,7}, ... + }; + nNumberFields = 19; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'speciesType','speciesType','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'initialAmount','initialAmount','',1,20}, ... + {'initialConcentration','initialConcentration','',1,20}, ... + {'substanceUnits','substanceUnits','',1,20}, ... + {'hasOnlySubstanceUnits','hasOnlySubstanceUnits','',1,20}, ... + {'boundaryCondition','boundaryCondition','',1,20}, ... + {'charge','charge','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetInitialAmount','initialAmount','',0,7}, ... + {'isSetInitialConcentration','initialConcentration','',0,7}, ... + {'isSetCharge','charge','',0,7}, ... + }; + nNumberFields = 20; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'initialAmount','initialAmount','',1,20}, ... + {'initialConcentration','initialConcentration','',1,20}, ... + {'substanceUnits','substanceUnits','',1,20}, ... + {'hasOnlySubstanceUnits','hasOnlySubstanceUnits','',1,20}, ... + {'boundaryCondition','boundaryCondition','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetInitialAmount','initialAmount','',0,7}, ... + {'isSetInitialConcentration','initialConcentration','',0,7}, ... + {'conversionFactor','conversionFactor','',1,20}, ... + }; + nNumberFields = 18; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'compartment','compartment','',1,20}, ... + {'initialAmount','initialAmount','',1,20}, ... + {'initialConcentration','initialConcentration','',1,20}, ... + {'substanceUnits','substanceUnits','',1,20}, ... + {'hasOnlySubstanceUnits','hasOnlySubstanceUnits','',1,20}, ... + {'boundaryCondition','boundaryCondition','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetInitialAmount','initialAmount','',0,7}, ... + {'isSetInitialConcentration','initialConcentration','',0,7}, ... + {'conversionFactor','conversionFactor','',1,20}, ... + }; + nNumberFields = 18; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getSpeciesReferenceFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'species','species','',1,20}, ... + {'stoichiometry','stoichiometry','',1,20}, ... + {'denominator','denominator','',1,20}, ... + }; + nNumberFields = 6; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'species','species','',1,20}, ... + {'stoichiometry','stoichiometry','',1,20}, ... + {'denominator','denominator','',1,20}, ... + {'stoichiometryMath','stoichiometryMath','',1,13}, ... + }; + nNumberFields = 8; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'species','species','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'stoichiometry','stoichiometry','',1,20}, ... + {'stoichiometryMath','stoichiometryMath','',1,13}, ... + }; + nNumberFields = 10; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'species','species','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + {'stoichiometry','stoichiometry','',1,20}, ... + {'stoichiometryMath','stoichiometryMath','',1,20}, ... + }; + nNumberFields = 10; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'species','species','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + {'stoichiometry','stoichiometry','',1,20}, ... + {'stoichiometryMath','stoichiometryMath','',1,20}, ... + }; + nNumberFields = 11; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'species','species','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + {'stoichiometry','stoichiometry','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetStoichiometry','stoichiometry','',0,7}, ... + }; + nNumberFields = 12; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'species','species','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + {'stoichiometry','stoichiometry','',1,20}, ... + {'constant','constant','',1,20}, ... + {'isSetStoichiometry','stoichiometry','',0,7}, ... + }; + nNumberFields = 12; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getSpeciesTypeFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + }; + nNumberFields = 6; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + }; + nNumberFields = 7; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + }; + nNumberFields = 8; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 2; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getStoichiometryMathFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 6; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 7; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 2; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getTriggerFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 6; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 7; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'persistent','persistent','',1,20}, ... + {'initialValue','initialValue','',1,20}, ... + {'math','math','',1,5}, ... + }; + nNumberFields = 9; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'persistent','persistent','',1,20}, ... + {'initialValue','initialValue','',1,20}, ... + {'math','math','',1,5}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + }; + nNumberFields = 11; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getUnitDefinitionFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'unit','unit','',1,20}, ... + }; + nNumberFields = 5; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'unit','unit','',1,20}, ... + }; + nNumberFields = 7; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'unit','unit','',1,20}, ... + }; + nNumberFields = 7; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'unit','unit','',1,20}, ... + }; + nNumberFields = 8; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'unit','unit','',1,20}, ... + }; + nNumberFields = 9; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'unit','unit','',1,20}, ... + }; + nNumberFields = 9; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'name','name','',1,20}, ... + {'id','id','',1,20}, ... + {'unit','unit','',1,20}, ... + }; + nNumberFields = 9; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getUnitFieldnames(level, ... + version) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +if (level == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'kind','kind','',1,20}, ... + {'exponent','exponent','',1,20}, ... + {'scale','scale','',1,20}, ... + }; + nNumberFields = 6; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'kind','kind','',1,20}, ... + {'exponent','exponent','',1,20}, ... + {'scale','scale','',1,20}, ... + {'multiplier','multiplier','',1,20}, ... + {'offset','offset','',1,20}, ... + }; + nNumberFields = 9; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'kind','kind','',1,20}, ... + {'exponent','exponent','',1,20}, ... + {'scale','scale','',1,20}, ... + {'multiplier','multiplier','',1,20}, ... + }; + nNumberFields = 8; + elseif (version == 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'kind','kind','',1,20}, ... + {'exponent','exponent','',1,20}, ... + {'scale','scale','',1,20}, ... + {'multiplier','multiplier','',1,20}, ... + }; + nNumberFields = 9; + elseif (version == 4 || version == 5) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'kind','kind','',1,20}, ... + {'exponent','exponent','',1,20}, ... + {'scale','scale','',1,20}, ... + {'multiplier','multiplier','',1,20}, ... + }; + nNumberFields = 10; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'kind','kind','',1,20}, ... + {'exponent','exponent','',1,20}, ... + {'scale','scale','',1,20}, ... + {'multiplier','multiplier','',1,20}, ... + }; + nNumberFields = 10; + elseif (version == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'kind','kind','',1,20}, ... + {'exponent','exponent','',1,20}, ... + {'scale','scale','',1,20}, ... + {'multiplier','multiplier','',1,20}, ... + {'id','id','',1,20}, ... + {'name','name','',1,20}, ... + }; + nNumberFields = 12; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getFBCModelFieldnames(level, ... + version, pkgVersion) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +% need a check on package version +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { {'fbc_version','version','fbc',1,20}, ... + {'fbc_fluxBound','fluxBound','fbc',1,20}, ... + {'fbc_objective','objective','fbc',1,20}, ... + {'fbc_activeObjective','activeObjective','fbc',1,20}, ... + }; + nNumberFields = 4; + elseif(pkgVersion ==2) + SBMLfieldnames = { {'fbc_version','version','fbc',1,20}, ... + {'fbc_geneProduct','geneProduct','fbc',1,20}, ... + {'fbc_objective','objective','fbc',1,20}, ... + {'fbc_activeObjective','activeObjective','fbc',1,20}, ... + {'fbc_strict','strict','fbc',1,20} + }; + nNumberFields = 5; + end; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getFBCSpeciesFieldnames(level, ... + version, pkgVersion) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +% need a check on package version +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion < 3) + SBMLfieldnames = { {'fbc_charge','charge','fbc',1,20}, ... + {'fbc_chemicalFormula','chemicalFormula','fbc',1,20}, ... + {'isSetfbc_charge','charge','fbc',0,7}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'fbc_version','version','fbc',1,20}, ... + }; + nNumberFields = 6; + end; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getFluxBoundFieldnames(level, ... + version, pkgVersion) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +% need a check on package version +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version <3) + if (pkgVersion == 1) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'fbc_id','id','fbc',1,20}, ... + {'fbc_reaction','reaction','fbc',1,20}, ... + {'fbc_operation','operation','fbc',1,20}, ... + {'fbc_value','value','fbc',1,20}, ... + {'isSetfbc_value','value','fbc',0,7}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'fbc_version','version','fbc',1,20}, ... + }; + nNumberFields = 14; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getFluxObjectiveFieldnames(level, ... + version, pkgVersion) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +% need a check on package version +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion < 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'fbc_reaction','reaction','fbc',1,20}, ... + {'fbc_coefficient','coefficient','fbc',1,20}, ... + {'isSetfbc_coefficient','coefficient','fbc',0,7}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'fbc_version','version','fbc',1,20}, ... + }; + nNumberFields = 12; + end; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getObjectiveFieldnames(level, ... + version, pkgVersion) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +% need a check on package version +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion < 3) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'fbc_id','id','fbc',1,20}, ... + {'fbc_type','type','fbc',1,20}, ... + {'fbc_fluxObjective','fluxObjective','fbc',1,20}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'fbc_version','version','fbc',1,20}, ... + }; + nNumberFields = 12; + end; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getGeneProductFieldnames(level, ... + version, pkgVersion) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +% need a check on package version +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'fbc_id','id','fbc',1,20}, ... + {'fbc_name','name','fbc',1,20}, ... + {'fbc_label','label','fbc',1,20}, ... + {'fbc_associatedSpecies','associatedSpecies','fbc',1,20}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'fbc_version','version','fbc',1,20}, ... + }; + nNumberFields = 13; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getFBCReactionFieldnames(level, ... + version, pkgVersion) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +% need a check on package version +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + SBMLfieldnames = { {'fbc_lowerFluxBound','lowerFluxBound','fbc',1,20}, ... + {'fbc_upperFluxBound','upperFluxBound','fbc',1,20}, ... + {'fbc_geneProductAssociation','geneProductAssociation','fbc',1,20}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'fbc_version','version','fbc',1,20}, ... + }; + nNumberFields = 6; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getGeneProductAssociationFieldnames(level, ... + version, pkgVersion) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +% need a check on package version +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'fbc_id','id','fbc',1,20}, ... + {'fbc_name','name','fbc',1,20}, ... + {'fbc_association','association','fbc',1,20}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'fbc_version','version','fbc',1,20}, ... + }; + nNumberFields = 12; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getAssociationFieldnames(level, ... + version, pkgVersion) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; +% need a check on package version +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + SBMLfieldnames = { {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'fbc_association','association','fbc',1,14}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'fbc_version','version','fbc',1,20}, ... + }; + nNumberFields = 10; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getQUALModelFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + SBMLfieldnames = []; + nNumberFields = 0; + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + {'qual_version','version','qual',1,20}, ... + {'qual_qualitativeSpecies','qualitativeSpecies','qual',1,20}, ... + {'qual_transition','transition','qual',1,20}, ... + }; + nNumberFields = 3; + end; + end; + end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getQualitativeSpeciesFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + SBMLfieldnames = []; + nNumberFields = 0; + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'qual_id','id','qual',1,20}, ... + {'qual_name','name','qual',1,20}, ... + {'qual_compartment','compartment','qual',1,20}, ... + {'qual_constant','constant','qual',1,20}, ... + {'qual_initialLevel','initialLevel','qual',1,20}, ... + {'qual_maxLevel','maxLevel','qual',1,20}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'qual_version','version','qual',1,20}, ... + }; + nNumberFields = 15; + end; + end; + end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getTransitionFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + SBMLfieldnames = []; + nNumberFields = 0; + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'qual_id','id','qual',1,20}, ... + {'qual_name','name','qual',1,20}, ... + {'qual_input','input','qual',1,20}, ... + {'qual_output','output','qual',1,20}, ... + {'qual_functionTerm','functionTerm','qual',1,20}, ... + {'qual_defaultTerm','defaultTerm','qual',1,20}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'qual_version','version','qual',1,20}, ... + }; + nNumberFields = 14; + end; + end; + end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getInputFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + SBMLfieldnames = []; + nNumberFields = 0; + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'qual_id','id','qual',1,20}, ... + {'qual_name','name','qual',1,20}, ... + {'qual_sign','sign','qual',1,20}, ... + {'qual_qualitativeSpecies','qualitativeSpecies','qual',1,20}, ... + {'qual_transitionEffect','transitionEffect','qual',1,20}, ... + {'qual_thresholdLevel','thresholdLevel','qual',1,20}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'qual_version','version','qual',1,20}, ... + }; + nNumberFields = 15; + end; + end; + end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getOutputFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + SBMLfieldnames = []; + nNumberFields = 0; + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'qual_id','id','qual',1,20}, ... + {'qual_qualitativeSpecies','qualitativeSpecies','qual',1,20}, ... + {'qual_transitionEffect','transitionEffect','qual',1,20}, ... + {'qual_name','name','qual',1,20}, ... + {'qual_outputLevel','outputLevel','qual',1,20}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'qual_version','version','qual',1,20}, ... + }; + nNumberFields = 14; + end; + end; + end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getDefaultTermFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + SBMLfieldnames = []; + nNumberFields = 0; + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'qual_resultLevel','resultLevel','qual',1,20}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'qual_version','version','qual',1,20}, ... + }; + nNumberFields = 10; + end; + end; + end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getFunctionTermFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + SBMLfieldnames = []; + nNumberFields = 0; + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'qual_resultLevel','resultLevel','qual',1,20}, ... + {'math','math','',1,5}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'qual_version','version','qual',1,20}, ... + }; + nNumberFields = 11; + end; + end; + end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getGROUPSModelFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + SBMLfieldnames = []; + nNumberFields = 0; + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + {'groups_version','version','groups',1,20}, ... + {'groups_group','group','groups',1,20}, ... + }; + nNumberFields = 2; + end; + end; + end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getGroupFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + SBMLfieldnames = []; + nNumberFields = 0; + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'groups_id','id','groups',1,20}, ... + {'groups_name','name','groups',1,20}, ... + {'groups_kind','kind','groups',1,20}, ... + {'groups_member','member','groups',1,20}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'groups_version','version','groups',1,20}, ... + }; + nNumberFields = 13; + end; + end; + end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getMemberFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + SBMLfieldnames = []; + nNumberFields = 0; + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + {'typecode','','',0,0}, ... + {'metaid','metaid','',1,20}, ... + {'notes','notes','',1,1}, ... + {'annotation','annotation','',1,2}, ... + {'cvterms','','',0,4}, ... + {'sboTerm','sboTerm','',1,20}, ... + {'groups_id','id','groups',1,20}, ... + {'groups_name','name','groups',1,20}, ... + {'groups_idRef','idRef','groups',1,20}, ... + {'groups_metaIdRef','metaIdRef','groups',1,20}, ... + {'level','','', 0, 0}, ... + {'version','','', 0, 0}, ... + {'groups_version','version','groups',1,20}, ... + }; + nNumberFields = 13; + end; + end; + end; +%%%% ADD functions +%%%% ADD functions +%%%% END functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function valid = isValidLevelVersionCombination(level, version) +valid = 1; +if ~isIntegralNumber(level) + error('level must be an integer'); +elseif ~isIntegralNumber(version) + error('version must be an integer'); +end; +if (level < 1 || level > 3) + error('current SBML levels are 1, 2 or 3'); +end; +if (level == 1) + if (version < 1 || version > 2) + error('SBMLToolbox supports versions 1-2 of SBML Level 1'); + end; +elseif (level == 2) + if (version < 1 || version > 5) + error('SBMLToolbox supports versions 1-5 of SBML Level 2'); + end; +elseif (level == 3) + if (version < 1 || version > 2) + error('SBMLToolbox supports version 1-2 of SBML Level 3'); + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function value = isIntegralNumber(number) +value = 0; +integerClasses = {'int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64'}; +% since the function isinteger does not exist in MATLAB Rel 13 +% this is not used +%if (isinteger(number)) +if (ismember(class(number), integerClasses)) + value = 1; +elseif (isnumeric(number)) + % if it is an integer + if (number == fix(number)) + value = 1; + end; +end; diff --git a/software/libSBML/getStructureFieldnames.m b/software/libSBML/getStructureFieldnames.m new file mode 100755 index 00000000..bed838ed --- /dev/null +++ b/software/libSBML/getStructureFieldnames.m @@ -0,0 +1,3753 @@ +function [SBMLfieldnames, nNumberFields] = getStructureFieldnames(varargin) +% [SBMLfieldnames, nNumberFields] = getStructureFieldnames(typecode, level, version, pkgversion(optional)) +% +% Takes +% +% 1. typecode; a string representing the type of object being queried +% 2. level, an integer representing an SBML level +% 3. version, an integer representing an SBML version +% 4. pkgversion, an integer representing the SBML package version +% (defaults to 1) +% +% Returns +% +% 1. an array of fieldnames for an SBML structure of the given typecode, level and version +% 2. the number of fieldnames +% + +% + +typecode = varargin{1}; +level = varargin{2}; +version = varargin{3}; + +pkgCount = 0; + +if (nargin > 3) + if (nargin < 5) + error('not enough arguments'); + end; + pkgCount = length(varargin{4}); + % packages = cell(1, pkgCount); + % pkgVersion = zeros(1, pkgCount); + packages = varargin{4}; + pkgVersion = varargin{5}; +end; + + + SBMLfieldnames = []; + nNumberFields = 0; +done = 1; + + +switch (typecode) + case {'SBML_ALGEBRAIC_RULE', 'AlgebraicRule', 'algebraicRule', 'rule'} + fhandle = str2func('getAlgebraicRuleFieldnames'); + case {'SBML_ASSIGNMENT_RULE', 'AssignmentRule', 'assignmentRule'} + fhandle = str2func('getAssignmentRuleFieldnames'); + case {'SBML_COMPARTMENT', 'Compartment', 'compartment'} + fhandle = str2func('getCompartmentFieldnames'); + case {'SBML_COMPARTMENT_TYPE', 'CompartmentType', 'compartmentType'} + fhandle = str2func('getCompartmentTypeFieldnames'); + case {'SBML_COMPARTMENT_VOLUME_RULE', 'CompartmentVolumeRule', 'compartmentVolumeRule'} + fhandle = str2func('getCompartmentVolumeRuleFieldnames'); + case {'SBML_CONSTRAINT', 'Constraint', 'constraint'} + fhandle = str2func('getConstraintFieldnames'); + case {'SBML_DELAY', 'Delay', 'delay'} + fhandle = str2func('getDelayFieldnames'); + case {'SBML_EVENT', 'Event', 'event'} + fhandle = str2func('getEventFieldnames'); + case {'SBML_EVENT_ASSIGNMENT', 'EventAssignment', 'eventAssignment'} + fhandle = str2func('getEventAssignmentFieldnames'); + case {'SBML_FUNCTION_DEFINITION', 'FunctionDefinition', 'functionDefinition'} + fhandle = str2func('getFunctionDefinitionFieldnames'); + case {'SBML_INITIAL_ASSIGNMENT', 'InitialAssignment', 'initialAssignment'} + fhandle = str2func('getInitialAssignmentFieldnames'); + case {'SBML_KINETIC_LAW', 'KineticLaw', 'kineticLaw'} + fhandle = str2func('getKineticLawFieldnames'); + case {'SBML_LOCAL_PARAMETER', 'LocalParameter', 'localParameter'} + fhandle = str2func('getLocalParameterFieldnames'); + case {'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getModelFieldnames'); + case {'SBML_MODIFIER_SPECIES_REFERENCE', 'ModifierSpeciesReference', 'modifierSpeciesReference', 'modifier'} + fhandle = str2func('getModifierSpeciesReferenceFieldnames'); + case {'SBML_PARAMETER', 'Parameter', 'parameter'} + fhandle = str2func('getParameterFieldnames'); + case {'SBML_PARAMETER_RULE', 'ParameterRule', 'parameterRule'} + fhandle = str2func('getParameterRuleFieldnames'); + case {'SBML_PRIORITY', 'Priority', 'priority'} + fhandle = str2func('getPriorityFieldnames'); + case {'SBML_RATE_RULE', 'RateRule', 'ruleRule'} + fhandle = str2func('getRateRuleFieldnames'); + case {'SBML_REACTION', 'Reaction', 'reaction'} + fhandle = str2func('getReactionFieldnames'); + case {'SBML_SPECIES', 'Species', 'species'} + fhandle = str2func('getSpeciesFieldnames'); + case {'SBML_SPECIES_CONCENTRATION_RULE', 'SpeciesConcentrationRule', 'speciesConcentrationRule'} + fhandle = str2func('getSpeciesConcentrationRuleFieldnames'); + case {'SBML_SPECIES_REFERENCE', 'SpeciesReference', 'speciesReference', 'reactant', 'Reactant', 'product', 'Product'} + fhandle = str2func('getSpeciesReferenceFieldnames'); + case {'SBML_SPECIES_TYPE', 'SpeciesType', 'speciesType'} + fhandle = str2func('getSpeciesTypeFieldnames'); + case {'SBML_STOICHIOMETRY_MATH', 'StoichiometryMath', 'stoichiometryMath'} + fhandle = str2func('getStoichiometryMathFieldnames'); + case {'SBML_TRIGGER', 'Trigger', 'trigger'} + fhandle = str2func('getTriggerFieldnames'); + case {'SBML_UNIT', 'Unit', 'unit'} + fhandle = str2func('getUnitFieldnames'); + case {'SBML_UNIT_DEFINITION', 'UnitDefinition', 'unitDefinition'} + fhandle = str2func('getUnitDefinitionFieldnames'); + otherwise + done = 0; +end; + +if done == 1 + [SBMLfieldnames, nNumberFields] = feval(fhandle, level, version); +else + i = 1; + found = 0; + while (i < pkgCount+1) + [found, fhandle] = getFields(typecode, packages{i}, 0); + if (found == 1) + break; + end; + i = i + 1; + end; + if (found == 1) + [SBMLfieldnames, nNumberFields] = feval(fhandle, level, version, pkgVersion(i)); + done = 1; + end; +end; + +if (done == 1 && pkgCount > 0) + % we may need to extend the fields + i = 1; + while (i < pkgCount+1) + [found, fhandle] = getFields(typecode, packages{i}, 1); + if (found == 1) + copySBML = SBMLfieldnames; + [newSBMLfieldnames, newNumberFields] = feval(fhandle, level, version, pkgVersion(i)); + SBMLfieldnames = [copySBML, newSBMLfieldnames]; + nNumberFields = nNumberFields + newNumberFields; + end; + i = i + 1; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [found, fhandle] = getFields(typecode, pkg, extension) + fhandle = str2func('disp'); + found = 0; + if (strcmp(pkg, 'fbc')) + if (extension) + if (isFBCExtension(typecode)) + [found, fhandle] = getFBCFieldnameFunction(typecode); + end; + else + [found, fhandle] = getFBCFieldnameFunction(typecode); + end; + elseif strcmp(pkg, 'qual') + if (extension) + if (isQUALExtension(typecode)) + [found, fhandle] = getQUALFieldnameFunction(typecode); + end; + else + [found, fhandle] = getQUALFieldnameFunction(typecode); + end; + elseif strcmp(pkg, 'groups') + if (extension) + if (isGROUPSExtension(typecode)) + [found, fhandle] = getGROUPSFieldnameFunction(typecode); + end; + else + [found, fhandle] = getGROUPSFieldnameFunction(typecode); + end; + end; +%%%%% REMOVE END +%%%%% ADD ADDITIONAL + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function extend = isFBCExtension(typecode) + extend = 0; + switch (typecode) + case {'SBML_FBC_MODEL', 'FBCModel', 'SBML_MODEL', 'Model', 'model'} + extend = 1; + case {'SBML_FBC_SPECIES', 'FBCSpecies', 'SBML_SPECIES', 'Species', 'species'} + extend = 1; + case {'SBML_FBC_REACTION', 'FBCReaction','SBML_REACTION', 'Reaction', 'reaction'} + extend = 1; + end; + +function extend = isQUALExtension(typecode) + extend = 0; + switch (typecode) + case {'SBML_QUAL_MODEL', 'QUALModel', 'SBML_MODEL', 'Model', 'model'} + extend = 1; + end; + +function extend = isGROUPSExtension(typecode) + extend = 0; + switch (typecode) + case {'SBML_GROUPS_MODEL', 'GROUPSModel', 'SBML_MODEL', 'Model', 'model'} + extend = 1; + end; +%%%% ADD isExtension +%%%% ADD isExtension +%%%% END isExtension + +function [found, fhandle] = getFBCFieldnameFunction(typecode) + found = 1; + switch (typecode) + case {'SBML_FBC_FLUXBOUND', 'FluxBound', 'fluxBound', 'fbc_fluxBound'} + fhandle = str2func('getFluxBoundFieldnames'); + case {'SBML_FBC_FLUXOBJECTIVE', 'FluxObjective', 'fluxObjective', 'fbc_fluxObjective'} + fhandle = str2func('getFluxObjectiveFieldnames'); + case {'SBML_FBC_OBJECTIVE', 'Objective', 'objective', 'fbc_objective'} + fhandle = str2func('getObjectiveFieldnames'); + case {'SBML_FBC_GENE_PRODUCT', 'GeneProduct', 'geneProduct', 'fbc_geneProduct'} + fhandle = str2func('getGeneProductFieldnames'); + case {'SBML_FBC_GENE_PRODUCT_ASSOCIATION', 'GeneProductAssociation', 'geneProductAssociation', 'fbc_geneProductAssociation'} + fhandle = str2func('getGeneProductAssociationFieldnames'); + case {'SBML_FBC_ASSOCIATION', 'Association', 'association', 'fbc_association'} + fhandle = str2func('getAssociationFieldnames'); + case {'SBML_FBC_MODEL', 'FBCModel', 'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getFBCModelFieldnames'); + case {'SBML_FBC_SPECIES', 'FBCSpecies', 'SBML_SPECIES', 'Species', 'species'} + fhandle = str2func('getFBCSpeciesFieldnames'); + case {'SBML_FBC_REACTION', 'FBCReaction','SBML_REACTION', 'Reaction', 'reaction'} + fhandle = str2func('getFBCReactionFieldnames'); + otherwise + fhandle = str2func('disp'); + found = 0; + end; + +function [found, fhandle] = getQUALFieldnameFunction(typecode) + found = 1; + switch (typecode) + case {'SBML_QUAL_QUALITATIVE_SPECIES', 'QualitativeSpecies', 'qualitativeSpecies', 'qual_qualitativeSpecies'} + fhandle = str2func('getQualitativeSpeciesFieldnames'); + case {'SBML_QUAL_TRANSITION', 'Transition', 'transition', 'qual_transition'} + fhandle = str2func('getTransitionFieldnames'); + case {'SBML_QUAL_INPUT', 'Input', 'input', 'qual_input'} + fhandle = str2func('getInputFieldnames'); + case {'SBML_QUAL_OUTPUT', 'Output', 'output', 'qual_output'} + fhandle = str2func('getOutputFieldnames'); + case {'SBML_QUAL_DEFAULT_TERM', 'DefaultTerm', 'defaultTerm', 'qual_defaultTerm'} + fhandle = str2func('getDefaultTermFieldnames'); + case {'SBML_QUAL_FUNCTION_TERM', 'FunctionTerm', 'functionTerm', 'qual_functionTerm'} + fhandle = str2func('getFunctionTermFieldnames'); + case {'SBML_QUAL_MODEL', 'QUALModel', 'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getQUALModelFieldnames'); + otherwise + fhandle = str2func('disp'); + found = 0; + end; + +function [found, fhandle] = getGROUPSFieldnameFunction(typecode) + found = 1; + switch (typecode) + case {'SBML_GROUPS_GROUP', 'Group', 'group', 'groups_group'} + fhandle = str2func('getGroupFieldnames'); + case {'SBML_GROUPS_MEMBER', 'Member', 'member', 'groups_member'} + fhandle = str2func('getMemberFieldnames'); + case {'SBML_GROUPS_MODEL', 'GROUPSModel', 'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getGROUPSModelFieldnames'); + otherwise + fhandle = str2func('disp'); + found = 0; + end; +%%%% ADD getFieldname +%%%% ADD getFieldname +%%%% END getFieldname + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getAlgebraicRuleFieldnames(level, ... + version) + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = { 'typecode', ... + 'notes', ... + 'annotation', ... + 'type', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 10; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 10; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 11; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 11; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 12; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 12; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + 'id', ... + 'name', ... + }; + nNumberFields = 14; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getAssignmentRuleFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 10; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 11; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 11; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 12; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 12; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + 'id', ... + 'name', ... + }; + nNumberFields = 14; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getCompartmentFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = { 'typecode', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'volume', ... + 'units', ... + 'outside', ... + 'isSetVolume', ... + }; + nNumberFields = 8; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'id', ... + 'spatialDimensions', ... + 'size', ... + 'units', ... + 'outside', ... + 'constant', ... + 'isSetSize', ... + 'isSetVolume', ... + }; + nNumberFields = 13; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'id', ... + 'compartmentType', ... + 'spatialDimensions', ... + 'size', ... + 'units', ... + 'outside', ... + 'constant', ... + 'isSetSize', ... + 'isSetVolume', ... + }; + nNumberFields = 14; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'compartmentType', ... + 'spatialDimensions', ... + 'size', ... + 'units', ... + 'outside', ... + 'constant', ... + 'isSetSize', ... + 'isSetVolume', ... + }; + nNumberFields = 15; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'compartmentType', ... + 'spatialDimensions', ... + 'size', ... + 'units', ... + 'outside', ... + 'constant', ... + 'isSetSize', ... + 'isSetVolume', ... + }; + nNumberFields = 16; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'spatialDimensions', ... + 'size', ... + 'units', ... + 'constant', ... + 'isSetSize', ... + 'isSetSpatialDimensions', ... + }; + nNumberFields = 14; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'spatialDimensions', ... + 'size', ... + 'units', ... + 'constant', ... + 'isSetSize', ... + 'isSetSpatialDimensions', ... + }; + nNumberFields = 14; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getCompartmentTypeFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'id', ... + }; + nNumberFields = 6; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'name', ... + 'id', ... + }; + nNumberFields = 7; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + }; + nNumberFields = 8; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 2; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getCompartmentVolumeRuleFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = { 'typecode', ... + 'notes', ... + 'annotation', ... + 'type', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 10; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 3) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 4 || version == 5) + SBMLfieldnames = []; + nNumberFields = 0; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 2; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getConstraintFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'math', ... + 'message', ... + }; + nNumberFields = 7; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'math', ... + 'message', ... + }; + nNumberFields = 7; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'math', ... + 'message', ... + }; + nNumberFields = 8; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'math', ... + 'message', ... + }; + nNumberFields = 8; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'math', ... + 'message', ... + 'id', ... + 'name', ... + }; + nNumberFields = 10; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getDelayFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'math', ... + }; + nNumberFields = 6; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'math', ... + }; + nNumberFields = 7; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'math', ... + }; + nNumberFields = 7; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'math', ... + 'id', ... + 'name', ... + }; + nNumberFields =9; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getEventAssignmentFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'variable', ... + 'math', ... + }; + nNumberFields = 6; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'variable', ... + 'sboTerm', ... + 'math', ... + }; + nNumberFields = 7; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'variable', ... + 'math', ... + }; + nNumberFields = 7; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'variable', ... + 'math', ... + }; + nNumberFields = 8; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'variable', ... + 'math', ... + }; + nNumberFields = 8; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'variable', ... + 'math', ... + 'id', ... + 'name', ... + }; + nNumberFields = 10; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getEventFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'id', ... + 'trigger', ... + 'delay', ... + 'timeUnits', ... + 'eventAssignment', ... + }; + nNumberFields = 10; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'id', ... + 'trigger', ... + 'delay', ... + 'timeUnits', ... + 'sboTerm', ... + 'eventAssignment', ... + }; + nNumberFields = 11; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'trigger', ... + 'delay', ... + 'eventAssignment', ... + }; + nNumberFields = 10; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'useValuesFromTriggerTime', ... + 'trigger', ... + 'delay', ... + 'eventAssignment', ... + }; + nNumberFields = 12; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'useValuesFromTriggerTime', ... + 'trigger', ... + 'delay', ... + 'priority', ... + 'eventAssignment', ... + }; + nNumberFields = 13; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'useValuesFromTriggerTime', ... + 'trigger', ... + 'delay', ... + 'priority', ... + 'eventAssignment', ... + }; + nNumberFields = 13; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFunctionDefinitionFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'id', ... + 'math', ... + }; + nNumberFields = 7; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'math', ... + }; + nNumberFields = 8; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'math', ... + }; + nNumberFields = 8; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'math', ... + }; + nNumberFields = 9; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'math', ... + }; + nNumberFields = 9; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'math', ... + }; + nNumberFields = 9; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getInitialAssignmentFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'symbol', ... + 'math', ... + }; + nNumberFields = 7; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'symbol', ... + 'math', ... + }; + nNumberFields = 7; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'symbol', ... + 'math', ... + }; + nNumberFields = 8; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'symbol', ... + 'math', ... + }; + nNumberFields = 8; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'symbol', ... + 'math', ... + 'id', ... + 'name', ... + }; + nNumberFields = 10; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getKineticLawFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = { 'typecode', ... + 'notes', ... + 'annotation', ... + 'formula', ... + 'parameter', ... + 'timeUnits', ... + 'substanceUnits', ... + }; + nNumberFields = 7; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'formula', ... + 'math', ... + 'parameter', ... + 'timeUnits', ... + 'substanceUnits', ... + }; + nNumberFields = 9; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'formula', ... + 'math', ... + 'parameter', ... + 'sboTerm', ... + }; + nNumberFields = 8; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'formula', ... + 'math', ... + 'parameter', ... + }; + nNumberFields = 8; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'formula', ... + 'math', ... + 'parameter', ... + }; + nNumberFields = 9; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'math', ... + 'localParameter', ... + }; + nNumberFields = 8; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'math', ... + 'localParameter', ... + 'id', ... + 'name', ... + }; + nNumberFields = 10; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getLocalParameterFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'value', ... + 'units', ... + 'isSetValue', ... + }; + nNumberFields = 11; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'value', ... + 'units', ... + 'isSetValue', ... + }; + nNumberFields = 11; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getModelFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = { 'typecode', ... + 'notes', ... + 'annotation', ... + 'SBML_level', ... + 'SBML_version', ... + 'name', ... + 'unitDefinition', ... + 'compartment', ... + 'species', ... + 'parameter', ... + 'rule', ... + 'reaction', ... + 'namespaces', ... + }; + nNumberFields = 13; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'SBML_level', ... + 'SBML_version', ... + 'name', ... + 'id', ... + 'functionDefinition', ... + 'unitDefinition', ... + 'compartment', ... + 'species', ... + 'parameter', ... + 'rule', ... + 'reaction', ... + 'event', ... + 'time_symbol', ... + 'delay_symbol', ... + 'namespaces', ... + }; + nNumberFields = 19; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'SBML_level', ... + 'SBML_version', ... + 'name', ... + 'id', ... + 'sboTerm', ... + 'functionDefinition', ... + 'unitDefinition', ... + 'compartmentType', ... + 'speciesType', ... + 'compartment', ... + 'species', ... + 'parameter', ... + 'initialAssignment', ... + 'rule', ... + 'constraint', ... + 'reaction', ... + 'event', ... + 'time_symbol', ... + 'delay_symbol', ... + 'namespaces', ... + }; + nNumberFields = 24; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'SBML_level', ... + 'SBML_version', ... + 'name', ... + 'id', ... + 'sboTerm', ... + 'functionDefinition', ... + 'unitDefinition', ... + 'compartmentType', ... + 'speciesType', ... + 'compartment', ... + 'species', ... + 'parameter', ... + 'initialAssignment', ... + 'rule', ... + 'constraint', ... + 'reaction', ... + 'event', ... + 'time_symbol', ... + 'delay_symbol', ... + 'namespaces', ... + }; + nNumberFields = 24; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'SBML_level', ... + 'SBML_version', ... + 'name', ... + 'id', ... + 'sboTerm', ... + 'functionDefinition', ... + 'unitDefinition', ... + 'compartmentType', ... + 'speciesType', ... + 'compartment', ... + 'species', ... + 'parameter', ... + 'initialAssignment', ... + 'rule', ... + 'constraint', ... + 'reaction', ... + 'event', ... + 'time_symbol', ... + 'delay_symbol', ... + 'namespaces', ... + }; + nNumberFields = 25; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'SBML_level', ... + 'SBML_version', ... + 'name', ... + 'id', ... + 'timeUnits', ... + 'substanceUnits', ... + 'volumeUnits', ... + 'areaUnits', ... + 'lengthUnits', ... + 'extentUnits', ... + 'conversionFactor', ... + 'sboTerm', ... + 'functionDefinition', ... + 'unitDefinition', ... + 'compartment', ... + 'species', ... + 'parameter', ... + 'initialAssignment', ... + 'rule', ... + 'constraint', ... + 'reaction', ... + 'event', ... + 'time_symbol', ... + 'delay_symbol', ... + 'avogadro_symbol', ... + 'namespaces', ... + }; + nNumberFields = 31; + elseif (version == 2) + SBMLfieldnames = { + 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'SBML_level', ... + 'SBML_version', ... + 'name', ... + 'id', ... + 'timeUnits', ... + 'substanceUnits', ... + 'volumeUnits', ... + 'areaUnits', ... + 'lengthUnits', ... + 'extentUnits', ... + 'conversionFactor', ... + 'sboTerm', ... + 'functionDefinition', ... + 'unitDefinition', ... + 'compartment', ... + 'species', ... + 'parameter', ... + 'initialAssignment', ... + 'rule', ... + 'constraint', ... + 'reaction', ... + 'event', ... + 'time_symbol', ... + 'delay_symbol', ... + 'avogadro_symbol', ... + 'rateOf_symbol', ... + 'namespaces', ... + }; + nNumberFields = 32; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getModifierSpeciesReferenceFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'species', ... + }; + nNumberFields = 5; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'species', ... + 'id', ... + 'name', ... + 'sboTerm', ... + }; + nNumberFields = 8; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'species', ... + 'id', ... + 'name', ... + }; + nNumberFields = 8; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'species', ... + 'id', ... + 'name', ... + }; + nNumberFields = 9; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'species', ... + 'id', ... + 'name', ... + }; + nNumberFields = 9; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'species', ... + 'id', ... + 'name', ... + 'id', ... + 'name', ... + }; + nNumberFields = 11; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getParameterFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = { 'typecode', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'value', ... + 'units', ... + 'isSetValue', ... + }; + nNumberFields = 7; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'id', ... + 'value', ... + 'units', ... + 'constant', ... + 'isSetValue', ... + }; + nNumberFields = 10; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'id', ... + 'value', ... + 'units', ... + 'constant', ... + 'sboTerm', ... + 'isSetValue', ... + }; + nNumberFields = 11; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'value', ... + 'units', ... + 'constant', ... + 'isSetValue', ... + }; + nNumberFields = 11; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'value', ... + 'units', ... + 'constant', ... + 'isSetValue', ... + }; + nNumberFields = 12; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'value', ... + 'units', ... + 'constant', ... + 'isSetValue', ... + }; + nNumberFields = 12; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'value', ... + 'units', ... + 'constant', ... + 'isSetValue', ... + }; + nNumberFields = 12; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getParameterRuleFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = { 'typecode', ... + 'notes', ... + 'annotation', ... + 'type', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 10; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 3) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 4 || version == 5) + SBMLfieldnames = []; + nNumberFields = 0; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 2; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getPriorityFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'math', ... + }; + nNumberFields = 7; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'math', ... + 'id', ... + 'name', ... + }; + nNumberFields = 9; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getRateRuleFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 10; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 11; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 11; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 12; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 12; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + 'id', ... + 'name', ... + }; + nNumberFields = 14; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getReactionFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = { 'typecode', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'reactant', ... + 'product', ... + 'kineticLaw', ... + 'reversible', ... + 'fast', ... + }; + nNumberFields = 9; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'id', ... + 'reactant', ... + 'product', ... + 'modifier', ... + 'kineticLaw', ... + 'reversible', ... + 'fast', ... + 'isSetFast', ... + }; + nNumberFields = 13; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'id', ... + 'reactant', ... + 'product', ... + 'modifier', ... + 'kineticLaw', ... + 'reversible', ... + 'fast', ... + 'sboTerm', ... + 'isSetFast', ... + }; + nNumberFields = 14; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'reactant', ... + 'product', ... + 'modifier', ... + 'kineticLaw', ... + 'reversible', ... + 'fast', ... + 'isSetFast', ... + }; + nNumberFields = 14; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'reactant', ... + 'product', ... + 'modifier', ... + 'kineticLaw', ... + 'reversible', ... + 'fast', ... + 'isSetFast', ... + }; + nNumberFields = 15; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'reactant', ... + 'product', ... + 'modifier', ... + 'kineticLaw', ... + 'reversible', ... + 'fast', ... + 'isSetFast', ... + 'compartment', ... + }; + nNumberFields = 16; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'reactant', ... + 'product', ... + 'modifier', ... + 'kineticLaw', ... + 'reversible', ... + 'compartment', ... + }; + nNumberFields = 14; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getSpeciesConcentrationRuleFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = { 'typecode', ... + 'notes', ... + 'annotation', ... + 'type', ... + 'formula', ... + 'variable', ... + 'species', ... + 'compartment', ... + 'name', ... + 'units', ... + }; + nNumberFields = 10; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 3) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 4 || version == 5) + SBMLfieldnames = []; + nNumberFields = 0; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 2; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getSpeciesFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = { 'typecode', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'compartment', ... + 'initialAmount', ... + 'units', ... + 'boundaryCondition', ... + 'charge', ... + 'isSetInitialAmount', ... + 'isSetCharge', ... + }; + nNumberFields = 11; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'id', ... + 'compartment', ... + 'initialAmount', ... + 'initialConcentration', ... + 'substanceUnits', ... + 'spatialSizeUnits', ... + 'hasOnlySubstanceUnits', ... + 'boundaryCondition', ... + 'charge', ... + 'constant', ... + 'isSetInitialAmount', ... + 'isSetInitialConcentration', ... + 'isSetCharge', ... + }; + nNumberFields = 18; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'id', ... + 'speciesType', ... + 'compartment', ... + 'initialAmount', ... + 'initialConcentration', ... + 'substanceUnits', ... + 'spatialSizeUnits', ... + 'hasOnlySubstanceUnits', ... + 'boundaryCondition', ... + 'charge', ... + 'constant', ... + 'isSetInitialAmount', ... + 'isSetInitialConcentration', ... + 'isSetCharge', ... + }; + nNumberFields = 19; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'speciesType', ... + 'compartment', ... + 'initialAmount', ... + 'initialConcentration', ... + 'substanceUnits', ... + 'hasOnlySubstanceUnits', ... + 'boundaryCondition', ... + 'charge', ... + 'constant', ... + 'isSetInitialAmount', ... + 'isSetInitialConcentration', ... + 'isSetCharge', ... + }; + nNumberFields = 19; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'speciesType', ... + 'compartment', ... + 'initialAmount', ... + 'initialConcentration', ... + 'substanceUnits', ... + 'hasOnlySubstanceUnits', ... + 'boundaryCondition', ... + 'charge', ... + 'constant', ... + 'isSetInitialAmount', ... + 'isSetInitialConcentration', ... + 'isSetCharge', ... + }; + nNumberFields = 20; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'compartment', ... + 'initialAmount', ... + 'initialConcentration', ... + 'substanceUnits', ... + 'hasOnlySubstanceUnits', ... + 'boundaryCondition', ... + 'constant', ... + 'isSetInitialAmount', ... + 'isSetInitialConcentration', ... + 'conversionFactor', ... + }; + nNumberFields = 18; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'compartment', ... + 'initialAmount', ... + 'initialConcentration', ... + 'substanceUnits', ... + 'hasOnlySubstanceUnits', ... + 'boundaryCondition', ... + 'constant', ... + 'isSetInitialAmount', ... + 'isSetInitialConcentration', ... + 'conversionFactor', ... + }; + nNumberFields = 18; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getSpeciesReferenceFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = { 'typecode', ... + 'notes', ... + 'annotation', ... + 'species', ... + 'stoichiometry', ... + 'denominator', ... + }; + nNumberFields = 6; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'species', ... + 'stoichiometry', ... + 'denominator', ... + 'stoichiometryMath', ... + }; + nNumberFields = 8; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'species', ... + 'id', ... + 'name', ... + 'sboTerm', ... + 'stoichiometry', ... + 'stoichiometryMath', ... + }; + nNumberFields = 10; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'species', ... + 'id', ... + 'name', ... + 'stoichiometry', ... + 'stoichiometryMath', ... + }; + nNumberFields = 10; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'species', ... + 'id', ... + 'name', ... + 'stoichiometry', ... + 'stoichiometryMath', ... + }; + nNumberFields = 11; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'species', ... + 'id', ... + 'name', ... + 'stoichiometry', ... + 'constant', ... + 'isSetStoichiometry', ... + }; + nNumberFields = 12; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'species', ... + 'id', ... + 'name', ... + 'stoichiometry', ... + 'constant', ... + 'isSetStoichiometry', ... + }; + nNumberFields = 12; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getSpeciesTypeFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'id', ... + }; + nNumberFields = 6; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'name', ... + 'id', ... + }; + nNumberFields = 7; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + }; + nNumberFields = 8; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 2; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getStoichiometryMathFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'math', ... + }; + nNumberFields = 6; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'math', ... + }; + nNumberFields = 7; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 2; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getTriggerFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 2) + SBMLfieldnames = []; + nNumberFields = 0; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'math', ... + }; + nNumberFields = 6; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'math', ... + }; + nNumberFields = 7; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'persistent', ... + 'initialValue', ... + 'math', ... + }; + nNumberFields = 9; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'persistent', ... + 'initialValue', ... + 'math', ... + 'id', ... + 'name', ... + }; + nNumberFields = 11; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getUnitDefinitionFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = { 'typecode', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'unit', ... + }; + nNumberFields = 5; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'id', ... + 'unit', ... + }; + nNumberFields = 7; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'name', ... + 'id', ... + 'unit', ... + }; + nNumberFields = 7; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'unit', ... + }; + nNumberFields = 8; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'unit', ... + }; + nNumberFields = 9; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'unit', ... + }; + nNumberFields = 9; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'name', ... + 'id', ... + 'unit', ... + }; + nNumberFields = 9; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getUnitFieldnames(level, ... + version) + + + + + + + + + + + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +if (level == 1) + SBMLfieldnames = { 'typecode', ... + 'notes', ... + 'annotation', ... + 'kind', ... + 'exponent', ... + 'scale', ... + }; + nNumberFields = 6; +elseif (level == 2) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'kind', ... + 'exponent', ... + 'scale', ... + 'multiplier', ... + 'offset', ... + }; + nNumberFields = 9; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'kind', ... + 'exponent', ... + 'scale', ... + 'multiplier', ... + }; + nNumberFields = 8; + elseif (version == 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'sboTerm', ... + 'kind', ... + 'exponent', ... + 'scale', ... + 'multiplier', ... + }; + nNumberFields = 9; + elseif (version == 4 || version == 5) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'kind', ... + 'exponent', ... + 'scale', ... + 'multiplier', ... + }; + nNumberFields = 10; + end; +elseif (level == 3) + if (version == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'kind', ... + 'exponent', ... + 'scale', ... + 'multiplier', ... + }; + nNumberFields = 10; + elseif (version == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'kind', ... + 'exponent', ... + 'scale', ... + 'multiplier', ... + 'id', ... + 'name', ... + }; + nNumberFields = 12; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFBCModelFieldnames(level, ... + version, pkgVersion) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { 'fbc_version', ... + 'fbc_fluxBound', ... + 'fbc_objective', ... + 'fbc_activeObjective', ... + }; + nNumberFields = 4; + elseif(pkgVersion ==2) + SBMLfieldnames = { 'fbc_version', ... + 'fbc_geneProduct', ... + 'fbc_objective', ... + 'fbc_activeObjective', ... + 'fbc_strict' + }; + nNumberFields = 5; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFBCSpeciesFieldnames(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion < 3) + SBMLfieldnames = { 'fbc_charge', ... + 'fbc_chemicalFormula', ... + 'isSetfbc_charge', ... + 'level', ... + 'version', ... + 'fbc_version', ... + }; + nNumberFields = 6; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFluxBoundFieldnames(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version <3) + if (pkgVersion == 1) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'fbc_id', ... + 'fbc_reaction', ... + 'fbc_operation', ... + 'fbc_value', ... + 'isSetfbc_value', ... + 'level', ... + 'version', ... + 'fbc_version', ... + }; + nNumberFields = 14; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFluxObjectiveFieldnames(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion < 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'fbc_reaction', ... + 'fbc_coefficient', ... + 'isSetfbc_coefficient', ... + 'level', ... + 'version', ... + 'fbc_version', ... + }; + nNumberFields = 12; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getObjectiveFieldnames(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion < 3) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'fbc_id', ... + 'fbc_type', ... + 'fbc_fluxObjective', ... + 'level', ... + 'version', ... + 'fbc_version', ... + }; + nNumberFields = 12; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getGeneProductFieldnames(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'fbc_id', ... + 'fbc_name', ... + 'fbc_label', ... + 'fbc_associatedSpecies', ... + 'level', ... + 'version', ... + 'fbc_version', ... + }; + nNumberFields = 13; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFBCReactionFieldnames(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + SBMLfieldnames = { 'fbc_lowerFluxBound', ... + 'fbc_upperFluxBound', ... + 'fbc_geneProductAssociation', ... + 'level', ... + 'version', ... + 'fbc_version', ... + }; + nNumberFields = 6; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getGeneProductAssociationFieldnames(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'fbc_id', ... + 'fbc_name', ... + 'fbc_association', ... + 'level', ... + 'version', ... + 'fbc_version', ... + }; + nNumberFields = 12; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getAssociationFieldnames(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + + SBMLfieldnames = { 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'fbc_association', ... + 'level', ... + 'version', ... + 'fbc_version', ... + }; + nNumberFields = 10; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getQUALModelFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'qual_version', ... + 'qual_qualitativeSpecies', ... + 'qual_transition', ... + }; + nNumberFields = 3; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getQualitativeSpeciesFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'qual_id', ... + 'qual_name', ... + 'qual_compartment', ... + 'qual_constant', ... + 'qual_initialLevel', ... + 'qual_maxLevel', ... + 'level', ... + 'version', ... + 'qual_version', ... + }; + nNumberFields = 15; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getTransitionFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'qual_id', ... + 'qual_name', ... + 'qual_input', ... + 'qual_output', ... + 'qual_functionTerm', ... + 'qual_defaultTerm', ... + 'level', ... + 'version', ... + 'qual_version', ... + }; + nNumberFields = 14; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getInputFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'qual_id', ... + 'qual_name', ... + 'qual_sign', ... + 'qual_qualitativeSpecies', ... + 'qual_transitionEffect', ... + 'qual_thresholdLevel', ... + 'level', ... + 'version', ... + 'qual_version', ... + }; + nNumberFields = 15; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getOutputFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'qual_id', ... + 'qual_qualitativeSpecies', ... + 'qual_transitionEffect', ... + 'qual_name', ... + 'qual_outputLevel', ... + 'level', ... + 'version', ... + 'qual_version', ... + }; + nNumberFields = 14; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getDefaultTermFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'qual_resultLevel', ... + 'level', ... + 'version', ... + 'qual_version', ... + }; + nNumberFields = 10; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getFunctionTermFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'qual_resultLevel', ... + 'math', ... + 'level', ... + 'version', ... + 'qual_version', ... + }; + nNumberFields = 11; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getGROUPSModelFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'groups_version', ... + 'groups_group', ... + }; + nNumberFields = 2; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getGroupFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'groups_id', ... + 'groups_name', ... + 'groups_kind', ... + 'groups_member', ... + 'level', ... + 'version', ... + 'groups_version', ... + }; + nNumberFields = 13; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getMemberFieldnames(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'typecode', ... + 'metaid', ... + 'notes', ... + 'annotation', ... + 'cvterms', ... + 'sboTerm', ... + 'groups_id', ... + 'groups_name', ... + 'groups_idRef', ... + 'groups_metaIdRef', ... + 'level', ... + 'version', ... + 'groups_version', ... + }; + nNumberFields = 13; + end; + end; + end; + +%%%% ADD functions +%%%% ADD functions + +%%%% END functions + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function valid = isValidLevelVersionCombination(level, version) +valid = 1; + +if ~isIntegralNumber(level) + error('level must be an integer'); +elseif ~isIntegralNumber(version) + error('version must be an integer'); +end; + +if (level < 1 || level > 3) + error('current SBML levels are 1, 2 or 3'); +end; + +if (level == 1) + if (version < 1 || version > 2) + error('SBMLToolbox supports versions 1-2 of SBML Level 1'); + end; + +elseif (level == 2) + if (version < 1 || version > 5) + error('SBMLToolbox supports versions 1-5 of SBML Level 2'); + end; + +elseif (level == 3) + if (version < 1 || version > 2) + error('SBMLToolbox supports version 1-2 of SBML Level 3'); + end; + +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function value = isIntegralNumber(number) +value = 0; + +integerClasses = {'int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64'}; + +% since the function isinteger does not exist in MATLAB Rel 13 +% this is not used +%if (isinteger(number)) +if (ismember(class(number), integerClasses)) + value = 1; +elseif (isnumeric(number)) + % if it is an integer + if (number == fix(number)) + value = 1; + end; +end; + + + diff --git a/software/libSBML/getValueType.m b/software/libSBML/getValueType.m new file mode 100755 index 00000000..199bad9f --- /dev/null +++ b/software/libSBML/getValueType.m @@ -0,0 +1,3719 @@ +function [valueType] = getValueType(varargin) +% [valueType] = getValueType(typecode, level, version, pkgversion(optional)) +% +% Takes +% +% 1. typecode; a string representing the type of object being queried +% 2. level, an integer representing an SBML level +% 3. version, an integer representing an SBML version +% 4. pkgversion, an integer representing the SBML package version +% (defaults to 1) +% +% Returns +% +% 1. an array of the value types for an SBML structure of the given typecode, level and version +% +% *NOTE:* The corresponding fields present in an SBML structure can be found using +% the function `getStructureFieldnames` + +% + +typecode = varargin{1}; +level = varargin{2}; +version = varargin{3}; + +pkgCount = 0; + +if (nargin > 3) + if (nargin < 5) + error('not enough arguments'); + end; + pkgCount = length(varargin{4}); + % packages = cell(1, pkgCount); + % pkgVersion = zeros(1, pkgCount); + packages = varargin{4}; + pkgVersion = varargin{5}; +end; + + + valueType = []; + + + + +done = 1; + +switch (typecode) + case {'SBML_ALGEBRAIC_RULE', 'AlgebraicRule', 'algebraicRule', 'rule'} + fhandle = str2func('getAlgebraicRuleValueType'); + case {'SBML_ASSIGNMENT_RULE', 'AssignmentRule', 'assignmentRule'} + fhandle = str2func('getAssignmentRuleValueType'); + case {'SBML_COMPARTMENT', 'Compartment', 'compartment'} + fhandle = str2func('getCompartmentValueType'); + case {'SBML_COMPARTMENT_TYPE', 'CompartmentType', 'compartmentType'} + fhandle = str2func('getCompartmentTypeValueType'); + case {'SBML_COMPARTMENT_VOLUME_RULE', 'CompartmentVolumeRule', 'compartmentVolumeRule'} + fhandle = str2func('getCompartmentVolumeRuleValueType'); + case {'SBML_CONSTRAINT', 'Constraint', 'constraint'} + fhandle = str2func('getConstraintValueType'); + case {'SBML_DELAY', 'Delay', 'delay'} + fhandle = str2func('getDelayValueType'); + case {'SBML_EVENT', 'Event', 'event'} + fhandle = str2func('getEventValueType'); + case {'SBML_EVENT_ASSIGNMENT', 'EventAssignment', 'eventAssignment'} + fhandle = str2func('getEventAssignmentValueType'); + case {'SBML_FUNCTION_DEFINITION', 'FunctionDefinition', 'functionDefinition'} + fhandle = str2func('getFunctionDefinitionValueType'); + case {'SBML_INITIAL_ASSIGNMENT', 'InitialAssignment', 'initialAssignment'} + fhandle = str2func('getInitialAssignmentValueType'); + case {'SBML_KINETIC_LAW', 'KineticLaw', 'kineticLaw'} + fhandle = str2func('getKineticLawValueType'); + case {'SBML_LOCAL_PARAMETER', 'LocalParameter', 'localParameter'} + fhandle = str2func('getLocalParameterValueType'); + case {'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getModelValueType'); + case {'SBML_MODIFIER_SPECIES_REFERENCE', 'ModifierSpeciesReference', 'modifierSpeciesReference', 'modifier'} + fhandle = str2func('getModifierSpeciesReferenceValueType'); + case {'SBML_PARAMETER', 'Parameter', 'parameter'} + fhandle = str2func('getParameterValueType'); + case {'SBML_PARAMETER_RULE', 'ParameterRule', 'parameterRule'} + fhandle = str2func('getParameterRuleValueType'); + case {'SBML_PRIORITY', 'Priority', 'priority'} + fhandle = str2func('getPriorityValueType'); + case {'SBML_RATE_RULE', 'RateRule', 'ruleRule'} + fhandle = str2func('getRateRuleValueType'); + case {'SBML_REACTION', 'Reaction', 'reaction'} + fhandle = str2func('getReactionValueType'); + case {'SBML_SPECIES', 'Species', 'species'} + fhandle = str2func('getSpeciesValueType'); + case {'SBML_SPECIES_CONCENTRATION_RULE', 'SpeciesConcentrationRule', 'speciesConcentrationRule'} + fhandle = str2func('getSpeciesConcentrationRuleValueType'); + case {'SBML_SPECIES_REFERENCE', 'SpeciesReference', 'speciesReference', 'reactant', 'Reactant', 'product', 'Product'} + fhandle = str2func('getSpeciesReferenceValueType'); + case {'SBML_SPECIES_TYPE', 'SpeciesType', 'speciesType'} + fhandle = str2func('getSpeciesTypeValueType'); + case {'SBML_STOICHIOMETRY_MATH', 'StoichiometryMath', 'stoichiometryMath'} + fhandle = str2func('getStoichiometryMathValueType'); + case {'SBML_TRIGGER', 'Trigger', 'trigger'} + fhandle = str2func('getTriggerValueType'); + case {'SBML_UNIT', 'Unit', 'unit'} + fhandle = str2func('getUnitValueType'); + case {'SBML_UNIT_DEFINITION', 'UnitDefinition', 'unitDefinition'} + fhandle = str2func('getUnitDefinitionValueType'); + otherwise + done = 0; +end; + +if done == 1 + [valueType] = feval(fhandle, level, version); +else + i = 1; + found = 0; + while (i < pkgCount+1) + [found, fhandle] = getValues(typecode, packages{i}, 0); + if (found == 1) + break; + end; + i = i + 1; + end; + if (found == 1) + [valueType] = feval(fhandle, level, version, pkgVersion(i)); + done = 1; + end; +end; + +if (done == 1 && pkgCount > 0) + % we may need to extend the fields + i = 1; + while (i < pkgCount+1) + [found, fhandle] = getValues(typecode, packages{i}, 1); + if (found == 1) + copySBML = valueType; + [newValueType] = feval(fhandle, level, version, pkgVersion(i)); + valueType = [copySBML, newValueType]; + end; + i = i + 1; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [found, fhandle] = getValues(typecode, pkg, extension) + fhandle = str2func('disp'); + found = 0; + if (strcmp(pkg, 'fbc')) + if (extension) + if (isFBCExtension(typecode)) + [found, fhandle] = getFBCValueFunction(typecode); + end; + else + [found, fhandle] = getFBCValueFunction(typecode); + end; + elseif strcmp(pkg, 'qual') + if (extension) + if (isQUALExtension(typecode)) + [found, fhandle] = getQUALValueTypeFunction(typecode); + end; + else + [found, fhandle] = getQUALValueTypeFunction(typecode); + end; + elseif strcmp(pkg, 'groups') + if (extension) + if (isGROUPSExtension(typecode)) + [found, fhandle] = getGROUPSValueTypeFunction(typecode); + end; + else + [found, fhandle] = getGROUPSValueTypeFunction(typecode); + end; + end; +%%%%% REMOVE END +%%%%% ADD ADDITIONAL + + +function extend = isFBCExtension(typecode) + extend = 0; + switch (typecode) + case {'SBML_FBC_MODEL', 'FBCModel', 'SBML_MODEL', 'Model', 'model'} + extend = 1; + case {'SBML_FBC_SPECIES', 'FBCSpecies', 'SBML_SPECIES', 'Species', 'species'} + extend = 1; + case {'SBML_FBC_REACTION', 'FBCReaction','SBML_REACTION', 'Reaction', 'reaction'} + extend = 1; + end; + +function extend = isQUALExtension(typecode) + extend = 0; + switch (typecode) + case {'SBML_QUAL_MODEL', 'QUALModel', 'SBML_MODEL', 'Model', 'model'} + extend = 1; + end; + +function extend = isGROUPSExtension(typecode) + extend = 0; + switch (typecode) + case {'SBML_GROUPS_MODEL', 'GROUPSModel', 'SBML_MODEL', 'Model', 'model'} + extend = 1; + end; +%%%% ADD isExtension +%%%% ADD isExtension +%%%% END isExtension + +function [found, fhandle] = getFBCValueFunction(typecode) + found = 1; + switch (typecode) + case {'SBML_FBC_FLUXBOUND', 'FluxBound', 'fluxBound', 'fbc_fluxBound'} + fhandle = str2func('getFluxBoundValueType'); + case {'SBML_FBC_FLUXOBJECTIVE', 'FluxObjective', 'fluxObjective', 'fbc_fluxObjective'} + fhandle = str2func('getFluxObjectiveValueType'); + case {'SBML_FBC_OBJECTIVE', 'Objective', 'objective', 'fbc_objective'} + fhandle = str2func('getObjectiveValueType'); + case {'SBML_FBC_MODEL', 'FBCModel', 'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getFBCModelValueType'); + case {'SBML_FBC_SPECIES', 'FBCSpecies', 'SBML_SPECIES', 'Species', 'species'} + fhandle = str2func('getFBCSpeciesValueType'); + case {'SBML_FBC_GENE_PRODUCT', 'GeneProduct', 'geneProduct', 'fbc_geneProduct'} + fhandle = str2func('getGeneProductValueType'); + case {'SBML_FBC_GENE_PRODUCT_ASSOCIATION', 'GeneProductAssociation', 'geneProductAssociation', 'fbc_geneProductAssociation'} + fhandle = str2func('getGeneProductAssociationValueType'); + case {'SBML_FBC_REACTION', 'FBCReaction','SBML_REACTION', 'Reaction', 'reaction'} + fhandle = str2func('getFBCReactionValueType'); + case {'SBML_FBC_GENE_PRODUCT_REF', 'Association', 'association', 'SBML_FBC_ASSOCIATION', 'fbc_association'} + fhandle = str2func('getAssociationValueType'); + otherwise + fhandle = str2func('disp'); + found = 0; + end; + +function [found, fhandle] = getQUALValueTypeFunction(typecode) + found = 1; + switch (typecode) + case {'SBML_QUAL_QUALITATIVE_SPECIES', 'QualitativeSpecies', 'qualitativeSpecies', 'qual_qualitativeSpecies'} + fhandle = str2func('getQualitativeSpeciesValueType'); + case {'SBML_QUAL_TRANSITION', 'Transition', 'transition', 'qual_transition'} + fhandle = str2func('getTransitionValueType'); + case {'SBML_QUAL_INPUT', 'Input', 'input', 'qual_input'} + fhandle = str2func('getInputValueType'); + case {'SBML_QUAL_OUTPUT', 'Output', 'output', 'qual_output'} + fhandle = str2func('getOutputValueType'); + case {'SBML_QUAL_DEFAULT_TERM', 'DefaultTerm', 'defaultTerm', 'qual_defaultTerm'} + fhandle = str2func('getDefaultTermValueType'); + case {'SBML_QUAL_FUNCTION_TERM', 'FunctionTerm', 'functionTerm', 'qual_functionTerm'} + fhandle = str2func('getFunctionTermValueType'); + case {'SBML_QUAL_MODEL', 'QUALModel', 'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getQUALModelValueType'); + otherwise + fhandle = str2func('disp'); + found = 0; + end; + +function [found, fhandle] = getGROUPSValueTypeFunction(typecode) + found = 1; + switch (typecode) + case {'SBML_GROUPS_GROUP', 'Group', 'group', 'groups_group'} + fhandle = str2func('getGroupValueType'); + case {'SBML_GROUPS_MEMBER', 'Member', 'member', 'groups_member'} + fhandle = str2func('getMemberValueType'); + case {'SBML_GROUPS_MODEL', 'GROUPSModel', 'SBML_MODEL', 'Model', 'model'} + fhandle = str2func('getGROUPSModelValueType'); + otherwise + fhandle = str2func('disp'); + found = 0; + end; +%%%% ADD getFieldname +%%%% ADD getFieldname +%%%% END getFieldname + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getAlgebraicRuleValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = { + 'SBML_ALGEBRAIC_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_ALGEBRAIC_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_ALGEBRAIC_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 3) + valueType = { + 'SBML_ALGEBRAIC_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_ALGEBRAIC_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_ALGEBRAIC_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_ALGEBRAIC_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getAssignmentRuleValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = []; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_ASSIGNMENT_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_ASSIGNMENT_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 3) + valueType = { + 'SBML_ASSIGNMENT_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_ASSIGNMENT_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_ASSIGNMENT_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_ASSIGNMENT_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getCompartmentValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = { + 'SBML_COMPARTMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'char', ... + 'char', ... + 'bool', ... + }; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_COMPARTMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'uint', ... + 'double', ... + 'char', ... + 'char', ... + 'bool', ... + 'bool', ... + 'bool', ... + }; + elseif (version == 2) + valueType = { + 'SBML_COMPARTMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'uint', ... + 'double', ... + 'char', ... + 'char', ... + 'bool', ... + 'bool', ... + 'bool', ... + }; + elseif (version == 3) + valueType = { + 'SBML_COMPARTMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'uint', ... + 'double', ... + 'char', ... + 'char', ... + 'bool', ... + 'bool', ... + 'bool', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_COMPARTMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'uint', ... + 'double', ... + 'char', ... + 'char', ... + 'bool', ... + 'bool', ... + 'bool', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_COMPARTMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'double', ... + 'double', ... + 'char', ... + 'bool', ... + 'bool', ... + 'bool', ... + }; + elseif (version == 2) + valueType = { + 'SBML_COMPARTMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'double', ... + 'double', ... + 'char', ... + 'bool', ... + 'bool', ... + 'bool', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getCompartmentTypeValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = []; +elseif (level == 2) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = { + 'SBML_COMPARTMENT_TYPE', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 3) + valueType = { + 'SBML_COMPARTMENT_TYPE', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_COMPARTMENT_TYPE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = []; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getCompartmentVolumeRuleValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = { + 'SBML_COMPARTMENT_VOLUME_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; +elseif (level == 2) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = []; + elseif (version == 3) + valueType = []; + elseif (version == 4 || version == 5) + valueType = []; + end; +elseif (level == 3) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = []; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getConstraintValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = []; +elseif (level == 2) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = { + 'SBML_CONSTRAINT', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + }; + elseif (version == 3) + valueType = { + 'SBML_CONSTRAINT', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_CONSTRAINT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_CONSTRAINT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_CONSTRAINT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getDelayValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = []; +elseif (level == 2) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = []; + elseif (version == 3) + valueType = { + 'SBML_DELAY', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_DELAY', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_DELAY', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_DELAY', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getEventAssignmentValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = []; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_EVENT_ASSIGNMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_EVENT_ASSIGNMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + }; + elseif (version == 3) + valueType = { + 'SBML_EVENT_ASSIGNMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_EVENT_ASSIGNMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_EVENT_ASSIGNMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_EVENT_ASSIGNMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getEventValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = []; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_EVENT', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + }; + elseif (version == 2) + valueType = { + 'SBML_EVENT', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'structure', ... + }; + elseif (version == 3) + valueType = { + 'SBML_EVENT', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'structure', ... + 'structure', ... + 'structure', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_EVENT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'bool', ... + 'structure', ... + 'structure', ... + 'structure', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_EVENT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'bool', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + }; + elseif (version == 2) + valueType = { + 'SBML_EVENT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'bool', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getFunctionDefinitionValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = []; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_FUNCTION_DEFINITION', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_FUNCTION_DEFINITION', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 3) + valueType = { + 'SBML_FUNCTION_DEFINITION', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_FUNCTION_DEFINITION', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_FUNCTION_DEFINITION', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_FUNCTION_DEFINITION', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getInitialAssignmentValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = []; +elseif (level == 2) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = { + 'SBML_INITIAL_ASSIGNMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + }; + elseif (version == 3) + valueType = { + 'SBML_INITIAL_ASSIGNMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_INITIAL_ASSIGNMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_INITIAL_ASSIGNMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_INITIAL_ASSIGNMENT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getKineticLawValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = { + 'SBML_KINETIC_LAW', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'char', ... + 'char', ... + }; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_KINETIC_LAW', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'char', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_KINETIC_LAW', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + }; + elseif (version == 3) + valueType = { + 'SBML_KINETIC_LAW', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'structure', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_KINETIC_LAW', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'structure', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_KINETIC_LAW', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'structure', ... + }; + elseif (version == 2) + valueType = { + 'SBML_KINETIC_LAW', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'structure', ... + 'char', ... + 'char', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getLocalParameterValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = []; +elseif (level == 2) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = []; + elseif (version == 3) + valueType = []; + elseif (version == 4 || version == 5) + valueType = []; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_LOCAL_PARAMETER', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'double', ... + 'char', ... + 'bool', ... + }; + elseif (version == 2) + valueType = { + 'SBML_LOCAL_PARAMETER', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'double', ... + 'char', ... + 'bool', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getModelValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = { + 'SBML_MODEL', ... + 'char', ... + 'char', ... + 'int', ... + 'int', ... + 'char', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + }; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_MODEL', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'int', ... + 'char', ... + 'char', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'char', ... + 'char', ... + 'structure', ... + }; + elseif (version == 2) + valueType = { + 'SBML_MODEL', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'int', ... + 'char', ... + 'char', ... + 'int', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'char', ... + 'char', ... + 'structure', ... + }; + elseif (version == 3) + valueType = { + 'SBML_MODEL', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'int', ... + 'char', ... + 'char', ... + 'int', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'char', ... + 'char', ... + 'structure', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_MODEL', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'int', ... + 'char', ... + 'char', ... + 'int', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'char', ... + 'char', ... + 'structure', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_MODEL', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + }; + elseif (version == 2) + valueType = { + 'SBML_MODEL', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getModifierSpeciesReferenceValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = []; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_MODIFIER_SPECIES_REFERENCE', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_MODIFIER_SPECIES_REFERENCE', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + }; + elseif (version == 3) + valueType = { + 'SBML_MODIFIER_SPECIES_REFERENCE', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_MODIFIER_SPECIES_REFERENCE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_MODIFIER_SPECIES_REFERENCE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_MODIFIER_SPECIES_REFERENCE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getParameterValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = { + 'SBML_PARAMETER', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'char', ... + 'bool', ... + }; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_PARAMETER', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'char', ... + 'bool', ... + 'bool', ... + }; + elseif (version == 2) + valueType = { + 'SBML_PARAMETER', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'char', ... + 'bool', ... + 'int', ... + 'bool', ... + }; + elseif (version == 3) + valueType = { + 'SBML_PARAMETER', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'double', ... + 'char', ... + 'bool', ... + 'bool', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_PARAMETER', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'double', ... + 'char', ... + 'bool', ... + 'bool', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_PARAMETER', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'double', ... + 'char', ... + 'bool', ... + 'bool', ... + }; + elseif (version == 2) + valueType = { + 'SBML_PARAMETER', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'double', ... + 'char', ... + 'bool', ... + 'bool', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getParameterRuleValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = { + 'SBML_PARAMETER_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; +elseif (level == 2) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = []; + elseif (version == 3) + valueType = []; + elseif (version == 4 || version == 5) + valueType = []; + end; +elseif (level == 3) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = []; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getPriorityValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = []; +elseif (level == 2) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = []; + elseif (version == 3) + valueType = []; + elseif (version == 4 || version == 5) + valueType = []; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_PRIORITY', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_PRIORITY', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getRateRuleValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = []; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_RATE_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_RATE_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 3) + valueType = { + 'SBML_RATE_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_RATE_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_RATE_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_RATE_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getReactionValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = { + 'SBML_REACTION', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'bool', ... + 'bool', ... + }; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_REACTION', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'bool', ... + 'bool', ... + 'bool', ... + }; + elseif (version == 2) + valueType = { + 'SBML_REACTION', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'bool', ... + 'bool', ... + 'int', ... + 'bool', ... + }; + elseif (version == 3) + valueType = { + 'SBML_REACTION', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'bool', ... + 'bool', ... + 'bool', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_REACTION', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'bool', ... + 'bool', ... + 'bool', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_REACTION', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'bool', ... + 'bool', ... + 'bool', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_REACTION', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'bool', ... + 'char', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getSpeciesConcentrationRuleValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = { + 'SBML_SPECIES_CONCENTRATION_RULE', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; +elseif (level == 2) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = []; + elseif (version == 3) + valueType = []; + elseif (version == 4 || version == 5) + valueType = []; + end; +elseif (level == 3) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = []; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getSpeciesValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = { + 'SBML_SPECIES', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'char', ... + 'bool', ... + 'int', ... + 'bool', ... + 'bool', ... + }; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_SPECIES', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'double', ... + 'char', ... + 'char', ... + 'bool', ... + 'bool', ... + 'int', ... + 'bool', ... + 'bool', ... + 'bool', ... + 'bool', ... + }; + elseif (version == 2) + valueType = { + 'SBML_SPECIES', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'double', ... + 'char', ... + 'char', ... + 'bool', ... + 'bool', ... + 'int', ... + 'bool', ... + 'bool', ... + 'bool', ... + 'bool', ... + }; + elseif (version == 3) + valueType = { + 'SBML_SPECIES', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'double', ... + 'char', ... + 'bool', ... + 'bool', ... + 'int', ... + 'bool', ... + 'bool', ... + 'bool', ... + 'bool', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_SPECIES', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'double', ... + 'char', ... + 'bool', ... + 'bool', ... + 'int', ... + 'bool', ... + 'bool', ... + 'bool', ... + 'bool', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_SPECIES', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'double', ... + 'char', ... + 'bool', ... + 'bool', ... + 'bool', ... + 'bool', ... + 'bool', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_SPECIES', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'double', ... + 'char', ... + 'bool', ... + 'bool', ... + 'bool', ... + 'bool', ... + 'bool', ... + 'char', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getSpeciesReferenceValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = { + 'SBML_SPECIES_REFERENCE', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'int', ... + }; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_SPECIES_REFERENCE', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'int', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_SPECIES_REFERENCE', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'double', ... + 'char', ... + }; + elseif (version == 3) + valueType = { + 'SBML_SPECIES_REFERENCE', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'structure', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_SPECIES_REFERENCE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'structure', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_SPECIES_REFERENCE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'bool', ... + 'bool', ... + }; + elseif (version == 2) + valueType = { + 'SBML_SPECIES_REFERENCE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'bool', ... + 'bool', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getSpeciesTypeValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = []; +elseif (level == 2) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = { + 'SBML_SPECIES_TYPE', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + }; + elseif (version == 3) + valueType = { + 'SBML_SPECIES_TYPE', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_SPECIES_TYPE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = []; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getStoichiometryMathValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = []; +elseif (level == 2) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = []; + elseif (version == 3) + valueType = { + 'SBML_STOICHIOMETRY_MATH', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_STOICHIOMETRY_MATH', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = []; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getTriggerValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = []; +elseif (level == 2) + if (version == 1) + valueType = []; + elseif (version == 2) + valueType = []; + elseif (version == 3) + valueType = { + 'SBML_TRIGGER', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_TRIGGER', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_TRIGGER', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'bool', ... + 'bool', ... + 'char', ... + }; + elseif (version == 2) + valueType = { + 'SBML_TRIGGER', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'bool', ... + 'bool', ... + 'char', ... + 'char', ... + 'char', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getUnitValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = { + 'SBML_UNIT', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'int', ... + }; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_UNIT', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'int', ... + 'double', ... + 'double', ... + }; + elseif (version == 2) + valueType = { + 'SBML_UNIT', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'int', ... + 'double', ... + }; + elseif (version == 3) + valueType = { + 'SBML_UNIT', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'int', ... + 'int', ... + 'double', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_UNIT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'int', ... + 'int', ... + 'double', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_UNIT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'double', ... + 'int', ... + 'double', ... + }; + elseif (version == 2) + valueType = { + 'SBML_UNIT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'double', ... + 'int', ... + 'double', ... + 'char', ... + 'char', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [valueType] = getUnitDefinitionValueType(level, version) + + + + + + + + + + + + +if ~isValidLevelVersionCombination(level, version) + error('invalid level/version combination'); +end; + +if (level == 1) + valueType = { + 'SBML_UNIT_DEFINITION', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + }; +elseif (level == 2) + if (version == 1) + valueType = { + 'SBML_UNIT_DEFINITION', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + }; + elseif (version == 2) + valueType = { + 'SBML_UNIT_DEFINITION', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + }; + elseif (version == 3) + valueType = { + 'SBML_UNIT_DEFINITION', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'char', ... + 'char', ... + 'structure', ... + }; + elseif (version == 4 || version == 5) + valueType = { + 'SBML_UNIT_DEFINITION', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'structure', ... + }; + end; +elseif (level == 3) + if (version == 1) + valueType = { + 'SBML_UNIT_DEFINITION', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'structure', ... + }; + elseif (version == 2) + valueType = { + 'SBML_UNIT_DEFINITION', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'structure', ... + }; + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFBCModelValueType(level, ... + version, pkgVersion) +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { 'uint', ... + 'structure', ... + 'structure', ... + 'char', ... + }; + nNumberFields = 4; + elseif(pkgVersion ==2) + SBMLfieldnames = { 'uint', ... + 'structure', ... + 'structure', ... + 'char', ... + 'bool' + }; + nNumberFields = 5; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFBCSpeciesValueType(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion < 3) + SBMLfieldnames = { 'int', ... + 'char', ... + 'bool', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 6; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFluxBoundValueType(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version <3) + if (pkgVersion == 1) + SBMLfieldnames = { 'SBML_FBC_FLUXBOUND', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'double', ... + 'bool', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 14; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFluxObjectiveValueType(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion < 3) + SBMLfieldnames = { 'SBML_FBC_FLUXOBJECTIVE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'double', ... + 'bool', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 12; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getObjectiveValueType(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion < 3) + SBMLfieldnames = { 'SBML_FBC_OBJECTIVE', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'structure', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 12; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getGeneProductValueType(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + SBMLfieldnames = { 'SBML_FBC_GENE_PRODUCT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 13; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getFBCReactionValueType(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + SBMLfieldnames = { 'char', ... + 'char', ... + 'structure', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 6; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getGeneProductAssociationValueType(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + + SBMLfieldnames = { 'SBML_FBC_GENE_PRODUCT_ASSOCIATION', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'structure', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 12; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [SBMLfieldnames, nNumberFields] = getAssociationValueType(level, ... + version, pkgVersion) + +if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); +end; + +% need a check on package version + +if (level == 1) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 2) + SBMLfieldnames = []; + nNumberFields = 0; +elseif (level == 3) + if (version < 3) + if (pkgVersion == 2) + + SBMLfieldnames = { 'SBML_FBC_ASSOCIATION', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 9; + else + SBMLfieldnames = []; + nNumberFields = 0; + end; + end; +end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getQUALModelValueType(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'uint', ... + 'structure', ... + 'structure', ... + }; + nNumberFields = 3; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getQualitativeSpeciesValueType(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_QUAL_QUALITATIVE_SPECIES', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'bool', ... + 'uint', ... + 'uint', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 15; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getTransitionValueType(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_QUAL_TRANSITION', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'structure', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 14; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getInputValueType(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_QUAL_INPUT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'uint', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 15; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getOutputValueType(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_QUAL_OUTPUT', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'int', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 14; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getDefaultTermValueType(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_QUAL_DEFAULT_TERM', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'uint', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 10; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getFunctionTermValueType(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_QUAL_FUNCTION_TERM', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'uint', ... + 'char', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 11; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getGROUPSModelValueType(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'uint', ... + 'structure', ... + }; + nNumberFields = 2; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getGroupValueType(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_GROUPS_GROUP', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 13; + end; + end; + end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [SBMLfieldnames, nNumberFields] = getMemberValueType(level, ... +version, pkgVersion) + if (~isValidLevelVersionCombination(level, version)) + error ('invalid level/version combination'); + end; + + SBMLfieldnames = []; + nNumberFields = 0; + + if (level == 3) + if (version < 3) + if (pkgVersion == 1) + SBMLfieldnames = { + 'SBML_GROUPS_MEMBER', ... + 'char', ... + 'char', ... + 'char', ... + 'structure', ... + 'int', ... + 'char', ... + 'char', ... + 'char', ... + 'char', ... + 'uint', ... + 'uint', ... + 'uint', ... + }; + nNumberFields = 13; + end; + end; + end; + + +%%%% ADD functions +%%%% ADD functions +%%%% END functions + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function valid = isValidLevelVersionCombination(level, version) +valid = 1; + +if ~isIntegralNumber(level) + error('level must be an integer'); +elseif ~isIntegralNumber(version) + error('version must be an integer'); +end; + +if (level < 1 || level > 3) + error('current SBML levels are 1, 2 or 3'); +end; + +if (level == 1) + if (version < 1 || version > 2) + error('SBMLToolbox supports versions 1-2 of SBML Level 1'); + end; + +elseif (level == 2) + if (version < 1 || version > 5) + error('SBMLToolbox supports versions 1-5 of SBML Level 2'); + end; + +elseif (level == 3) + if (version < 1 || version > 2) + error('SBMLToolbox supports version 1-2 of SBML Level 3'); + end; + +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function value = isIntegralNumber(number) +value = 0; + +integerClasses = {'int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64'}; + +% since the function isinteger does not exist in MATLAB Rel 13 +% this is not used +%if (isinteger(number)) +if (ismember(class(number), integerClasses)) + value = 1; +elseif (isnumeric(number)) + % if it is an integer + if (number == fix(number)) + value = 1; + end; +end; + + + diff --git a/software/libSBML/installSBML.m b/software/libSBML/installSBML.m new file mode 100755 index 00000000..83fa922e --- /dev/null +++ b/software/libSBML/installSBML.m @@ -0,0 +1,400 @@ +function installSBML(varargin) +% Installs the MATLAB language interface for libSBML. +% +% This script assumes that the libsbml matlab binding executables files already +% exist in the folder where this install file is located. +% +% It optionally takes an argument indicating whether messages should be +% displayed. This is on by default. + +% Filename : install.m +% Description : install matlab binding +% Author(s) : SBML Team +% Organization: EMBL-EBI +% +% This file is part of libSBML. Please visit http://sbml.org for more +% information about SBML, and the latest version of libSBML. +% +% Copyright (C) 2013-2018 jointly by the following organizations: +% 1. California Institute of Technology, Pasadena, CA, USA +% 2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK +% 3. University of Heidelberg, Heidelberg, Germany +% +% Copyright (C) 2009-2013 jointly by the following organizations: +% 1. California Institute of Technology, Pasadena, CA, USA +% 2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK +% +% Copyright (C) 2006-2008 by the California Institute of Technology, +% Pasadena, CA, USA +% +% Copyright (C) 2002-2005 jointly by the following organizations: +% 1. California Institute of Technology, Pasadena, CA, USA +% 2. Japan Science and Technology Agency, Japan +% +% This library is free software; you can redistribute it and/or modify it +% under the terms of the GNU Lesser General Public License as published by +% the Free Software Foundation. A copy of the license agreement is provided +% in the file named "LICENSE.txt" included with this software distribution +% and also available online as http://sbml.org/software/libsbml/license.html +% + +% ========================================================================= +% Main loop. +% ========================================================================= + +% look at input arguments + + [verbose] = checkInputArguments(varargin); + + myDisp({'Installing the libSBML interface.'}, verbose); + + [matlab_octave] = check_system(verbose); + + [functioning, located] = checkForExecutables(matlab_octave, verbose); + + if (functioning == 0) + if (located == 0) + % we didnt find executables where we first looked + error('%s%s', 'Executables were not found.', ... + 'Please make sure they are in the same directory as the installSBML and other scripts.'); + else + % we found executables but they did not work + error('%s%s%s\n%s%s', ... + 'Executables were located at ', pwd(), ' but failed to execute', ... + 'Please contact the libSBML team libsbml-team@googlegroups.com ', ... + 'for further assistance'); + end; + end; + + if (functioning == 1) + myDisp({'Installation successful'}, verbose); + end; +end + + + +% ========================================================================= +% Helper functions +% ========================================================================= + +% check any input arguments +%-------------------------------------------------------------------------- +function [verbose] = checkInputArguments(input) + + numArgs = length(input); + + if (numArgs > 1) + reportInputArgumentError('Too many arguments to install script'); + end; + + if (numArgs == 1) + verbose = input{1}; + else + verbose = 1; + end; + + if (verbose ~= 0 && verbose ~= 1) + reportInputArgumentError('Incorrect value for verbose flag; it should be either 1 or 0'); + end; +end + +% display error message relating to input arguments +%--------------------------------------------------- +function reportInputArgumentError(message) + + error('%s\n%s\n\t%s%s\n\t%s%s\n\t\t%s', message, ... + 'Arguments are optional but if present:', ... + 'the argument should be a flag (0 or 1) indicating ', ... + 'whether messages should be displayed ', ... + '0 - no messages; 1 - display messages'); +end + + + +% display error messages iff verbose = 1 +%----------------------------------------- +function myDisp(message, verbose) + + outputStr = ''; + + if (verbose == 1) + for i=1:length(message) + outputStr = sprintf('%s\n%s', outputStr, message{i}); + end; + end; + + disp(outputStr); +end + +% +% +% Is this windows +% Mac OS X 10.7 Lion returns true for a call to ispc() +% since we were using that to distinguish between windows and macs we need +% to catch this +% ------------------------------------------------------------------------ +function y = isWindows() + + y = 1; + + if isunix() + y = 0; + return; + end; + + if ismac() + y = 0; + return; + end; + + if ~ispc() + error('\n%s\n%s\n', ... + 'Unable to determine the type of operating system in use.', ... + 'Please contact libsbml-team@googlegroups.com to help resolve this problem.'); + end; +end + +% +% Assess our computing environment. +% ------------------------------------------------------------------------- +function [matlab_octave] = check_system(verbose) + message{1} = '* Doing preliminary checks of runtime environment ...'; + + if (strcmp(isoctave(), '0')) + matlab_octave = 'MATLAB'; + message{2} = ' - This appears to be MATLAB and not Octave.'; + else + matlab_octave = 'Octave'; + message{2} = ' - This appears to be Octave and not MATLAB.'; + end; + + myDisp(message, verbose); +end + +% +% check for executables and that they are right ones +% ------------------------------------------------------------------------- +function [success, located] = checkForExecutables(matlab_octave, verbose) + directory = pwd(); + message{1} = 'Checking for executables in '; + message{2} = sprintf('\t%s', directory); + + transFile = strcat('TranslateSBML.', mexext()); + outFile = strcat('OutputSBML.', mexext()); + + thisDirTFile = fullfile(pwd(), transFile); + thisDirOFile = fullfile(pwd(), outFile); + + success = 0; + located = 0; + + if strcmpi(matlab_octave, 'matlab') + if (~(exist([directory, filesep, transFile], 'file') ~= 0 ... + && exist([directory, filesep, outFile], 'file') ~= 0)) + located = 0; + else + located = 1; + end; + else + % octave is much more picky about whether the files exist + % it wants to find the libraries at the same time + % exist throws an exception if it cannot find them + if (~(myExist(directory, transFile) ~= 0 ... + && myExist(directory, outFile) ~= 0)) + located = 0; + else + located = 1; + end; + end; + + if (located == 1) + % we have found the executables where the user says but + % need to check that there are not other files on the path + t = which(transFile); + o = which(outFile); + + % exclude the current dir + currentT = strcmp(t, thisDirTFile); + currentO = strcmp(t, thisDirOFile); + found = 0; + if (currentT == 1 && currentO == 1) + t_found = 0; + if (isempty(t) == 0 && strcmp(t, [directory, filesep, transFile]) == 0) + found = 1; + t_found = 1; + elseif (isempty(o) == 0 && strcmp(o, [directory, filesep, outFile]) == 0) + found = 1; + end; + end; + if (found == 1) + if (t_found == 1) + pathDir = t; + else + pathDir = o; + end; + error('%s\n%s\n%s', 'Other libsbml executables found on the path at:', ... + pathDir, ... + 'Please uninstall these before attempting to install again'); + end; + end; + + + if (located == 1) + message{3} = 'Executables found'; + else + message{3} = 'Executables not found'; + end; + + + myDisp(message, verbose); + + if (located == 1) + % we have found the executables + % add the directory to the matlab path + added = addDir(directory, verbose); + + % if addDir returns 0 this may be that the user does not have + % permission to add to the path + if (added == 0) + error('%s%s%s%s\n%s%s', ... + 'The directory containing the executables could not ', ... + 'be added to the ', matlab_octave, ' path', ... + 'You may need to run in administrator mode or contact your ', ... + 'network manager if running from a network'); + elseif (added == 1) + % to test the actual files we need to be in the directory + % if we happen to be in the src tree where the .m helps files + % exist these will get picked up first by the function calls + % according to mathworks the only way to avoid this is to cd to the + % right dir + currentDir = pwd(); + cd(directory); + success = doesItRun(matlab_octave, verbose, currentDir); + cd (currentDir); + end; + + % at this point if success = 0 it means there was an error running + % the files - take the directory out of the path + if (success == 0 && added == 1) + removeDir(directory, verbose); + end; + end; +end + +% test the installation +% ------------------------------------------------------------------------- +function success = doesItRun(matlab_octave, verbose, dirForTest) + + success = 1; + + message{1} = 'Attempting to execute functions'; + myDisp(message, verbose); + + testFile = fullfile(dirForTest, 'test.xml'); + + if strcmpi(matlab_octave, 'matlab') + try + M = TranslateSBML(testFile); + message{1} = 'TranslateSBML successful'; + catch ME + success = 0; + message{1} = sprintf('%s\n%s', 'TranslateSBML failed', ME.message); + end; + else + try + M = TranslateSBML(testFile); + message{1} = 'TranslateSBML successful'; + catch + success = 0; + message{1} = 'TranslateSBML failed'; + end; + end; + + if strcmpi(matlab_octave, 'matlab') + outFile = [tempdir, filesep, 'test-out.xml']; + else + if isWindows() + outFile = [tempdir, 'temp', filesep, 'test-out.xml']; + else + outFile = [tempdir, 'test-out.xml']; + end; + end; + + if (success == 1) + if strcmpi(matlab_octave, 'matlab') + try + if (verbose == 1) + OutputSBML(M, outFile); + else + OutputSBML(M, outFile, verbose, verbose); + end; + message{2} = 'OutputSBML successful'; + catch ME + success = 0; + message{2} = sprintf('%s\n%s', 'OutputSBML failed', ME.message); + end; + else + try + if (verbose == 1) + OutputSBML(M, outFile); + else + OutputSBML(M, outFile, verbose, verbose); + end; + message{2} = 'OutputSBML successful'; + catch + success = 0; + message{2} = 'OutputSBML failed'; + end; + end; + end; + + myDisp(message, verbose); +end + +% add directory to the matlab path +% ------------------------------------------------------------------------- +function added = addDir(name, verbose) + + added = 0; + addpath(name); + if (savepath ~= 0) + message{1} = sprintf('Adding %s to path ...\nFailed', name); + else + message{1} = sprintf('Adding %s to path ...\nSuccess', name); + added = 1; + end; + + myDisp(message, verbose); +end + +% remove directory to the matlab path +% ------------------------------------------------------------------------- +function added = removeDir(name, verbose) + + added = 0; + rmpath(name); + if (savepath ~= 0) + message{1} = sprintf('Removing %s from path ...\nFailed', name); + else + message{1} = sprintf('Removing %s from path ...\nSuccess', name); + added = 1; + end; + + myDisp(message, verbose); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function found = myExist(directory, filename) + + +found = 0; +dirnames = dir(directory); +i = 1; +while (found == 0 && i <= length(dirnames)) + if (dirnames(i).isdir == 0) + found = strcmp(dirnames(i).name, filename); + end; + i = i+1; +end; + +end diff --git a/software/libSBML/isEnabled.m b/software/libSBML/isEnabled.m new file mode 100755 index 00000000..7414dad5 --- /dev/null +++ b/software/libSBML/isEnabled.m @@ -0,0 +1,90 @@ +function enabled = isEnabled(package) +% enabled = isEnabled(package) +% +% Takes +% +% 1. package - a string representing an SBML L3 package +% +% Returns +% +% 1. enabled +% - 1, if the package can be used by this instance of libSBML +% - 0, otherwise + +% + +% assume not enabled +enabled = 0; + +supported = {'fbc', 'qual', 'groups'}; +if ~ischar(package) + disp('argument must be a string representing an SBML L3 package'); +elseif ~ismember(supported, package) + return; +end; + +if (isoctave() == '0') + filename = fullfile(tempdir, 'pkg.xml'); +else + filename = fullfile(pwd, 'pkg.xml'); +end; +writeTempFile(filename, package); + +version_field = strcat(package, '_version'); +try + [m, e] = TranslateSBML(filename, 1, 0); + + if (isempty(e) && isfield(m, version_field) == 1 ) + enabled = 1; + end; + + delete(filename); + +catch err + disp(err.identifier) + delete(filename); + + return +end; + + + + +function writeTempFile(filename, package) + +fout = fopen(filename, 'w'); + +fprintf(fout, '\n'); +fprintf(fout, '\n')); +fprintf(fout, ' \n\n'); + +fclose(fout); diff --git a/software/libSBML/isFbcEnabled.m b/software/libSBML/isFbcEnabled.m new file mode 100755 index 00000000..8acf6804 --- /dev/null +++ b/software/libSBML/isFbcEnabled.m @@ -0,0 +1,76 @@ +function fbcEnabled = isFbcEnabled() +% Checks whether the version of libSBML has been built with +% the FBC package extension enabled + +% Filename : isFbcEnabled.m +% Description : check fbc status +% Author(s) : SBML Team +% Organization: EMBL-EBI, Caltech +% Created : 2011-02-08 +% +% This file is part of libSBML. Please visit http://sbml.org for more +% information about SBML, and the latest version of libSBML. +% +% Copyright (C) 2013-2018 jointly by the following organizations: +% 1. California Institute of Technology, Pasadena, CA, USA +% 2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK +% 3. University of Heidelberg, Heidelberg, Germany +% +% Copyright (C) 2009-2011 jointly by the following organizations: +% 1. California Institute of Technology, Pasadena, CA, USA +% 2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK +% +% Copyright (C) 2006-2008 by the California Institute of Technology, +% Pasadena, CA, USA +% +% Copyright (C) 2002-2005 jointly by the following organizations: +% 1. California Institute of Technology, Pasadena, CA, USA +% 2. Japan Science and Technology Agency, Japan +% +% This library is free software; you can redistribute it and/or modify +% it under the terms of the GNU Lesser General Public License as +% published by the Free Software Foundation. A copy of the license +% agreement is provided in the file named "LICENSE.txt" included with +% this software distribution and also available online as +% http://sbml.org/software/libsbml/license.html + +% assume not enabled +fbcEnabled = 0; + +if (isoctave() == '0') + filename = fullfile(tempdir, 'fbc.xml'); +else + filename = fullfile(pwd, 'fbc.xml'); +end; +writeTempFile(filename); + +try + [m, e] = TranslateSBML(filename, 1, 0); + + if (length(e) == 0 && isfield(m, 'fbc_version') == 1 ) + fbcEnabled = 1; + end; + + delete(filename); + +catch + + delete(filename); + + return +end; + + + + +function writeTempFile(filename) + +fout = fopen(filename, 'w'); + +fprintf(fout, '\n'); +fprintf(fout, '\n'); +fprintf(fout, ' \n\n'); + +fclose(fout); diff --git a/software/libSBML/isSBML_Model.m b/software/libSBML/isSBML_Model.m new file mode 100755 index 00000000..9fb7864b --- /dev/null +++ b/software/libSBML/isSBML_Model.m @@ -0,0 +1,343 @@ +function [valid, message] = isSBML_Model(varargin) +% [valid, message] = isSBML_Model(SBMLModel) +% +% Takes +% +% 1. SBMLModel, an SBML Model structure +% 2. extensions_allowed (optional) = +% - 0, structures should contain ONLY required fields +% - 1, structures may contain additional fields (default) +%3. applyUserValidation (optional) = +% - 0, no further validation (default) +% - 1, run the applyUserValidation function as part of validation +% +% Returns +% +% 1. valid = +% - 1, if the structure represents +% a MATLAB_SBML Model structure of the appropriate +% level and version +% - 0, otherwise +% 2. a message explaining any failure +% + +% + +supported = {'fbc'}; + +%check the input arguments are appropriate +if (nargin < 1) + error('isSBML_Model needs at least one argument'); +elseif (nargin == 1) + SBMLStructure = varargin{1}; + extensions_allowed = 1; + userValidation = 0; +elseif (nargin == 2) + SBMLStructure = varargin{1}; + extensions_allowed = varargin{2}; + userValidation = 0; +elseif (nargin == 3) + SBMLStructure = varargin{1}; + extensions_allowed = varargin{2}; + userValidation = varargin{3}; +else + error('too many arguments to isSBML_Model'); +end; + +if ~isempty(SBMLStructure) + if isfield(SBMLStructure, 'SBML_level') && ~isempty(SBMLStructure.SBML_level) + level = SBMLStructure.SBML_level; + else + level = 3; + end; + if isfield(SBMLStructure, 'SBML_version') && ~isempty(SBMLStructure.SBML_version) + version = SBMLStructure.SBML_version; + else + version = 1; + end; +else + level = 3; + version = 1; +end; + +pkgCount = 0; + +num = length(supported); +packages = cell(1, num); +pkgVersion = zeros(1, num); + +valid = 1; +% identify packages +for i=1:length(supported) + vers = strcat(supported{i}, '_version'); + if isfield(SBMLStructure, vers) + if isempty(SBMLStructure.(vers)) + valid = 0; + message = sprintf('Missing %s value', vers); + else + pkgCount = pkgCount + 1; + packages{pkgCount} = supported{i}; + pkgVersion(pkgCount) = SBMLStructure.(vers); + end; + end; +end; + +if (valid == 1) + [valid, message] = isSBML_Struct('model', SBMLStructure, level, version, packages, pkgVersion, extensions_allowed); + + if (valid == 1 && userValidation == 1) + [valid, message] = applyUserValidation(SBMLStructure, level, version, packages, pkgVersion); + end; +end; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [valid, message] = isSBML_Struct(typecode, SBMLStructure, level, version, packages, pkgVersion, extensions_allowed) + +num = length(SBMLStructure); +if (num == 0) + valid = 0; + message = 'Invalid Model structure'; + return; +elseif (num > 1) + valid = 0; + message = 'cannot deal with arrays of structures'; + return; +end; + +isValidLevelVersionCombination(level, version); + +message = ''; + +% check that argument is a structure +valid = isstruct(SBMLStructure); + +% if the level and version fields exist they must match +if (valid == 1 && isfield(SBMLStructure, 'level') && ~isempty(SBMLStructure)) + if ~isequal(level, SBMLStructure.level) + valid = 0; + message = sprintf('%s level mismatch', typecode); + end; +end; +if (valid == 1 && isfield(SBMLStructure, 'version') && ~isempty(SBMLStructure)) + if ~isequal(version, SBMLStructure.version) + valid = 0; + message = sprintf('%s version mismatch', typecode); + end; +end; + +if (strcmp(typecode, 'rule') == 1) + if isfield(SBMLStructure, 'typecode') + typecode = SBMLStructure.typecode; + end; +end; + +% check that structure contains all the necessary fields +if (isempty(typecode)) + valid = 0; + message = sprintf('missing typecode'); +end; +if (valid == 1) + [SBMLfieldnames, numFields] = getStructureFieldnames(typecode, level, version, packages, pkgVersion); + if (numFields ==0) + valid = 0; + message = sprintf('%s invalid level/version', typecode); + end; + + [value_types] = getValueType(typecode, level, version, packages, pkgVersion); + [defaults] = getDefaultValues(typecode, level, version, packages, pkgVersion); +else + SBMLfieldnames = []; + numFields = 0; + [value_types] = []; + [defaults] = []; +end; +% check the typecode +if (valid == 1 && ~isempty(SBMLStructure)) + if isfield(SBMLStructure, 'typecode') + if (strcmp(defaults{1}, SBMLStructure.typecode) ~= 1) + % for a association there may be differences + if (strcmp(defaults{1}, 'SBML_FBC_ASSOCIATION') == 1) + possible = {'SBML_FBC_GENE_PRODUCT_REF', 'SBML_FBC_AND', 'SBML_FBC_OR', 'SBML_FBC_ASSOCIATION'}; + if ~ismember(possible, SBMLStructure.typecode) + valid = 0; + message = sprintf('%s typecode mismatch', typecode); + return; + end; + else + valid = 0; + message = sprintf('%s typecode mismatch', typecode); + return; + end; + end; + else + valid = 0; + message = sprintf('%s missing typecode field', typecode); + return; + end; +end; + +if iscell(value_types) == 0 + typecode + SBMLfieldnames +end; + +index = 1; +while (valid == 1 && index <= numFields) + field = char(SBMLfieldnames(index)); + valid = isfield(SBMLStructure, field); + if (strcmp(char(field), 'cvterms')==1) + % do nothing + valid = 1; + elseif (valid == 0) + message = sprintf('%s field missing', field); + else + mess = ''; + if (index ~= 1) + value = getfield(SBMLStructure, field); + if (strcmp(value_types{index}, 'structure') ~= 1) + correctType = getCorrectType(value_types{index}); + % need to deal with matlab number value_types + valid = isValidType(value, correctType); +% valid = isa(value, correctType); + else + for i=1:length(value) + if (valid == 1) + if (strcmp(char(field), 'namespaces') ~= 1 && strcmp(char(field), 'cvterms')~=1) + [valid, mess] = isSBML_Struct(field, value(i), level, version, packages, pkgVersion, extensions_allowed); + end; + end; + end; + end; + end; + if (valid == 0) + if (isempty(mess)) + message = sprintf('%s %s field incorrect type', typecode, field); + else + message = sprintf('%s structure reports %s', field, mess); + end; + end; + end; + index = index + 1; +end; + +if (extensions_allowed == 0) + % check that the structure contains ONLY the expected fields + if (valid == 1) + % here we hack for structures that dont list level and version + numExpected = length(fieldnames(SBMLStructure)); + if (sum(ismember(SBMLfieldnames, 'level')) == 0 && strcmp('SBML_MODEL', SBMLStructure.typecode) ~= 1) + numExpected = numExpected - 2; + end; + if (numFields ~= numExpected) + valid = 0; + message = sprintf('%s - Unexpected field detected', typecode); + end; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function ctype = getCorrectType(type) + +if (strcmp(type, 'bool') == 1) + ctype = 'int32'; +elseif (strcmp(type, 'int') == 1) + ctype = 'int32'; +elseif (strcmp(type, 'uint') == 1) + ctype = 'int32'; +else + ctype = type; +end; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function valid = isValidLevelVersionCombination(level, version) + +valid = 1; + +if ~isIntegralNumber(level) + error('level must be an integer'); +elseif ~isIntegralNumber(version) + error('version must be an integer'); +end; + +if (level < 1 || level > 3) + error('current SBML levels are 1, 2 or 3'); +end; + +if (level == 1) + if (version < 1 || version > 2) + error('libSBML supports versions 1-2 of SBML Level 1'); + end; + +elseif (level == 2) + if (version < 1 || version > 5) + error('libSBML supports versions 1-5 of SBML Level 2'); + end; + +elseif (level == 3) + if (version > 2) + error('libSBML supports only versions 1 and 2 of SBML Level 3'); + end; + +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function value = isIntegralNumber(number) + + +value = 0; + +integerClasses = {'int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64'}; + +% since the function isinteger does not exist in MATLAB Rel 13 +% this is not used +%if (isinteger(number)) +if (ismember(class(number), integerClasses)) + value = 1; +elseif (isnumeric(number)) + % if it is an integer + if (number == fix(number)) + value = 1; + end; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function valid = isValidType(value, correctType) +if (isempty(value)) + valid = 1; +else + valid = isIntegralNumber(value); + + if (~valid) + valid = isa(value, correctType); + end; +end; + diff --git a/software/libSBML/isoctave.m b/software/libSBML/isoctave.m new file mode 100755 index 00000000..7d4b1690 --- /dev/null +++ b/software/libSBML/isoctave.m @@ -0,0 +1,27 @@ +function t=isoctave() +%ISOCTAVE True if the operating environment is octave. +% Usage: t=isoctave(); +% +% Returns 1 if the operating environment is octave, otherwise +% 0 (Matlab) + +% @file isoctave.m +% @brief Returns true if using octave +% @author Sarah Keating +% +% +% ISOCTAVE.M +% +% COPYRIGHT : (c) NUHAG, Dept.Math., University of Vienna, AUSTRIA +% http://nuhag.eu/ +% Permission is granted to modify and re-distribute this +% code in any manner as long as this notice is preserved. +% All standard disclaimers apply. +% + +if exist('OCTAVE_VERSION') > 0 + % Only Octave has this variable. + t='1'; +else + t='0'; +end; diff --git a/software/libSBML/test.xml b/software/libSBML/test.xml new file mode 100644 index 00000000..732f8430 --- /dev/null +++ b/software/libSBML/test.xml @@ -0,0 +1,89 @@ + + + + + +

    Simple branch system.

    +

    The reaction looks like this:

    +

    reaction-1: X0 -> S1; k1*X0;

    +

    reaction-2: S1 -> X1; k2*S1;

    +

    reaction-3: S1 -> X2; k3*S1;

    + +
    + + + + + + + + + + + + + + + + + + + + + + k1 + X0 + + + + + + + + + + + + + + + + + + + k2 + S1 + + + + + + + + + + + + + + + + + + + k3 + S1 + + + + + + + + +
    +
    diff --git a/solver/getMILPParams.m b/solver/getMILPParams.m deleted file mode 100755 index 2bcd01ac..00000000 --- a/solver/getMILPParams.m +++ /dev/null @@ -1,70 +0,0 @@ -function mosekParams=getMILPParams(params) -% getMILPParams -% Returns a MOSEK parameter structure used when solving mixed-integer -% linear programming problems -% -% params structure with one or more of the following fields -% maxTime maximal running time in minutes (opt, default 600) -% relGap maximal relative gap between integer and relaxed -% solution in order to be considered optimal (0.0-1.0) -% (opt, default 0.2) -% printReport true if the results of the optimization should be -% displayed on the screen (opt, default false) -% -% mosekParams a parameter structure to be used with MOSEK -% -% Usage: mosekParams=getMILPParams(params) - -if nargin<1 - params=[]; -end - -mosekParams=params; -mosekParams.MSK_DPAR_MIO_TOL_ABS_RELAX_INT=10^-12; -mosekParams.MSK_DPAR_MIO_TOL_REL_GAP=0.05; - -%NOTE: These options were removed or renamed in Mosek 8. Should be -%investigated. mosekParams.MSK_DPAR_MIO_TOL_REL_RELAX_INT=10^-9; -%mosekParams.MSK_DPAR_MIO_TOL_X=10^-9; -mosekParams.MSK_DPAR_MIO_TOL_FEAS=10^-12; -mosekParams.MSK_DPAR_BASIS_TOL_S=10^-12; -mosekParams.MSK_DPAR_BASIS_TOL_X=10^-12; -mosekParams.MSK_DPAR_PRESOLVE_TOL_ABS_LINDEP=10^-12; - -%Get the mosek version. This is a bit problematic since the Mosek function -%for getting the version came in version 7. -if isfield(params,'presolve') - mosekParams.MSK_DPAR_OPTIMIZER_MAX_TIME=params.presolve; - mosekParams=rmfield(mosekParams,'presolve'); -else - if any(strfind(evalc('mosekopt info'),'MOSEK Version 7')) - mosekParams.MSK_IPAR_PRESOLVE_USE=1; - else - % NOTE: This options were removed or renamed in Mosek 8. Should be - % investigated. mosekParams.MSK_DPAR_PRESOLVE_TOL_LIN_DEP=10^-9; - - %Turn off the presolve. This is because Mosek sometimes returns - %non-feasible solutions because of problems with the presolver. - %Should check if version is <6.0.0.147 - mosekParams.MSK_IPAR_PRESOLVE_USE=0; - end -end - -%Use a starting integer solution if supplied. This has no effect if no such -%solution is supplied mosekParams.MSK_IPAR_MIO_CONSTRUCT_SOL=1; - -%10 hours as default upper time limit -mosekParams.MSK_DPAR_OPTIMIZER_MAX_TIME=10*60*60; - -if isfield(params,'maxTime') - mosekParams.MSK_DPAR_OPTIMIZER_MAX_TIME=params.maxTime*60; - mosekParams=rmfield(mosekParams,'maxTime'); -end -if isfield(params,'relGap') - mosekParams.MSK_DPAR_MIO_TOL_REL_GAP=params.relGap; - mosekParams=rmfield(mosekParams,'relGap'); -end -if isfield(params,'printReport') - mosekParams=rmfield(mosekParams,'printReport'); -end -end diff --git a/solver/optimizeProb.m b/solver/optimizeProb.m index 5f2a4653..03ce7c1a 100755 --- a/solver/optimizeProb.m +++ b/solver/optimizeProb.m @@ -11,35 +11,125 @@ if nargin<2 || isempty(params) params=struct(); end - if(~ispref('RAVEN','solver')) dispEM('RAVEN solver not defined or unknown. Try using setRavenSolver(''solver'').'); end - -milp=false; -if isfield(prob,'vartype') && ~all(lower(prob.vartype) == 'c') +if ~all(lower(prob.vartype) == 'c') disp('MILP detected.'); milp=true; +else + milp=false; end +%% Define default parameters, which will then be used to make solver- +% specific solverparams structures +defaultparams.feasTol = 1e-9; +defaultparams.optTol = 1e-9; +defaultparams.objTol = 1e-9; +defaultparams.timeLimit = 1000; +%defaultparams.iterationLimit = 1000; +defaultparams.intTol = 1e-12; +defaultparams.relMipGapTol = 1e-12; +defaultparams.absMipGapTol = 1e-12; + solver=getpref('RAVEN','solver'); -if strcmp(solver,'gurobi') - if isfield(params,'relGap'), params=rmfield(params,'relGap'); end - gparams=struct('Presolve',2,'TimeLimit',1000,'OutputFlag',1,'MIPGap',1e-12,'Seed',0,'FeasibilityTol',1e-9,'OptimalityTol',1e-9); - gparams=structUpdate(gparams,params); - if (~milp), gparams.OutputFlag=0; end - res = gurobi(cobraToGurobiProb(prob),gparams); - res = gurobiToCobraRes(res, milp); -elseif strcmp(solver,'cobra') - if (milp) - cparams=struct('timeLimit',1e9,'printLevel',0,'intTol',1e-6,'relMipGapTol',1e-9); - cparams=structUpdate(cparams,params); - res=solveCobraMILP(prob,cparams); + +switch solver + %% Use whatever solver is set by COBRA Toolbox changeCobraSolver + case 'cobra' + if milp + cparams=struct('timeLimit',1e9,'printLevel',0,'intTol',1e-6,'relMipGapTol',1e-9); + cparams=structUpdate(cparams,params); + res=solveCobraMILP(prob,cparams); + else + res=solveCobraLP(prob); + end + + %% Use Gurobi in a MATLAB environment + case 'gurobi' + if milp + solverparams.OutputFlag = 1; else - res=solveCobraLP(prob); + solverparams.OutputFlag = 0; end -else - dispEM('RAVEN solver not defined or unknown. Try using setRavenSolver(''solver'').'); + solverparams.DisplayInterval= 1; % Level of verbosity + solverparams.TimeLimit = defaultparams.timeLimit; + solverparams.FeasibilityTol = defaultparams.feasTol; + solverparams.OptimalityTol = defaultparams.optTol; + solverparams.Presolve = 2; + solverparams = structUpdate(solverparams,params); + + % Restructering problem according to gurobi format + prob.csense = renameparams(prob.csense, {'L','G','E'}, {'<','>','='}); + prob.osense = renameparams(num2str(prob.osense), {'1','-1'}, {'min','max'}); + + [prob.obj, prob.rhs, prob.sense, prob.modelsense] = deal(prob.c, prob.b, prob.csense, prob.osense); + prob = rmfield(prob, {'c','b','csense','osense'}); + + resG = gurobi(prob,solverparams); + + try + [res.full, res.obj, res.origStat] = deal(resG.x, resG.objval, resG.status); + if milp && strcmp(resG.status, 'TIME_LIMIT') + % If res has the objval field, it succeeded, regardless of + % time_limit status + resG.status = 'OPTIMAL'; + end + switch resG.status + case 'OPTIMAL' + res.stat = 1; + case 'UNBOUNDED' + res.stat = 2; + otherwise + res.stat = 0; + end + if ~milp + [res.vbasis, res.cbasis] = deal(resG.vbasis, resG.cbasis); + end + catch + res.stat = 0; + res.origStat = resG.status; % useful information to have + end + %% Use GLPK using RAVEN-provided binary + case 'glpk' + solverparams.scale = 128; % Auto scaling + solverparams.tmlim = defaultparams.timeLimit; + solverparams.tolbnd = defaultparams.feasTol; + solverparams.toldj = defaultparams.optTol; + solverparams.tolint = defaultparams.intTol; + solverparams.tolobj = defaultparams.objTol; + solverparams.msglev = 0; % Level of verbosity + solverparams = structUpdate(solverparams,params); + + prob.csense = renameparams(prob.csense, {'L','G','E'}, {'U','L','S'}); + + if milp + solverparams.tmlim = solverparams.tmlim*10; + solverparams.msglev = 1; % Level of verbosity + disp('Issues have been observed when using GLPK for MILP solving. Be advised to carefully observe the results, or us another solver.') + end + solverparams.scale = 1; % Auto scaling + + % Ensure that RAVEN glpk binary is used, return to original + % directory afterwards + [ravenDir,currDir]=findRAVENroot(); + cd(fullfile(ravenDir,'software','GLPKmex')) + [xopt, fmin, errnum, extra] = glpk(prob.c, prob.A, prob.b, prob.lb, prob.ub, prob.csense, prob.vartype, prob.osense, solverparams); + cd(currDir) + + switch errnum % 1 = undefined; 2 = feasible; 3 = infeasible; 4 = no feasible solution; 5 = optimal; 6 = no unbounded solution + case 5 + res.stat = 1; % Optimal + case 2 + res.stat = 2; % Feasible, but not optimal + otherwise + res.stat = 0; + end + res.origStat = errnum; + res.full = xopt; + res.obj = fmin; + otherwise + error('RAVEN solver not defined or unknown. Try using setRavenSolver(''solver'').'); end if res.stat>0 res.full=res.full(1:size(prob.a,2)); @@ -54,3 +144,18 @@ names = [fieldnames(s_merged); fieldnames(s_new)]; s_merged = cell2struct([struct2cell(s_merged); struct2cell(s_new)], names, 1); end + +function paramlist = renameparams(paramlist,old,new) +if ~iscell(paramlist) + wasNoCell = true; + paramlist={paramlist}; +else + wasNoCell = false; +end +for i=1:numel(old) + paramlist = regexprep(paramlist,old{i},new{i}); +end +if wasNoCell + paramlist=paramlist{1}; +end +end diff --git a/solver/setRavenSolver.m b/solver/setRavenSolver.m index 7b3fcf42..99f6ff0e 100755 --- a/solver/setRavenSolver.m +++ b/solver/setRavenSolver.m @@ -3,21 +3,28 @@ function setRavenSolver(solver) % Sets the solver for RAVEN and optionally saves a default value % to MATLAB startup. % -% solver the name of the solver. The following options are available: -% -gurobi (all versions) -% -cobra. If this option is set, then RAVEN uses the current -% COBRA solver. Make sure that the one is set using -% changeCobraSolver +% solver string with solver name. The following options are available: +% glpk uses RAVEN-provided binaries +% gurobi requires a working Gurobi installation +% cobra requires a working COBRA Toolbox installation. RAVEN +% parses the problem to COBRA and uses the solver that is +% set by changeCobraSolver. % % Usage: setRavenSolver(solver) - -if (~ischar(solver)) dispEM('Input should be a string.'); end - -if strcmpi(solver,'gurobi') || strcmpi(solver,'cobra') || strcmpi(solver,'none') - setpref('RAVEN','solver',solver) -elseif strcmpi(solver,'mosek') - error('MOSEK is no longer supported from RAVEN 2.3.0. Choose ''gurobi'' or ''cobra''.') -else - EM='Such solver is not compatible with RAVEN. Available options are ''gurobi'' and ''cobra'''; - dispEM(EM); +solver=char(solver); +switch solver + case 'cobra' + global CBT_LP_SOLVER; + if isempty(CBT_LP_SOLVER) + error('COBRA toolbox is not initialized, run ''initCobraToolbox()''') + else + setpref('RAVEN','solver','cobra'); + end + case 'mosek' + error('MOSEK support has been discontinued since RAVEN 2.3.0.') + case {'glpk','gurobi'} + setpref('RAVEN','solver',solver) + otherwise + error('Invalid solver defined') +end end diff --git a/solver/solveLP.m b/solver/solveLP.m index 3fdef18e..e3032479 100755 --- a/solver/solveLP.m +++ b/solver/solveLP.m @@ -58,15 +58,15 @@ end end -% Setup the problem to feed to COBRA. -prob=[]; -prob.c=[model.c*-1;zeros(size(model.S,1),1)]; -prob.b = zeros(size(model.S,1), 1); -prob.lb = [model.lb; model.b(:,1)]; -prob.ub = [model.ub; model.b(:,min(size(model.b,2),2))]; -prob.osense = 1; -prob.csense = char(zeros(size(model.S,1),1)); -prob.csense(:) = 'E'; +% Setup the linear problem for glpk +prob = []; +prob.c = [model.c*-1;zeros(size(model.S,1),1)]; +prob.b = zeros(size(model.S,1), 1); +prob.lb = [model.lb; model.b(:,1)]; +prob.ub = [model.ub; model.b(:,min(size(model.b,2),2))]; +prob.csense = repmat('E', 1, length(prob.b)); % Equality constraints +prob.osense = 1; +prob.vartype = repmat('C', 1, length(prob.c)); % Fluxes are continuous values prob.A = [model.S -speye(size(model.S,1))]; prob.a = model.S; @@ -175,28 +175,10 @@ dispEM(EM,false); solution.stat=-2; end - %The square of fluxes should be minimized. This only works when - %there is no interval on the mass balance constraints (model.b is a - %vector) + case 2 - % if size(model.b,2)==1 - % qsol=solveQP(model,model.rxns,zeros(numel(model.lb),1)); - % %There is a problem that the solver seldom converges totally in this - % %kind of minimization. Print a warning but use the fluxes - % if any(qsol.x) - % solution.x=qsol.x; - % if qsol.stat==-1 - % fprintf('WARNING: The quadratic fitting did not converge\n'); - % end - % else - % fprintf('WARNING: Could not solve the problem of minimizing the square of fluxes. Uses output from linear program\n'); - % end - % else - % fprintf('WARNING: Cannot minimize square of fluxes when size(model.b,2)==2. Uses output from linear program\n'); - % end - EM='Quadratic solver currently not working. Uses output from original problem'; - dispEM(EM,false); - solution.stat=-2; + error('%Minimization of square of fluxes is deprecated') + %The number of fluxes should be minimized case 3 [qx,I]=getMinNrFluxes(model,model.rxns,params); diff --git a/solver/solveQP.m b/solver/solveQP.m index 4a4f3c6a..d74085ce 100755 --- a/solver/solveQP.m +++ b/solver/solveQP.m @@ -17,6 +17,7 @@ % stat Exit flag % % Usage: solution=solveQP(model,rxns,values,maxIter, restartIter) +rxns=char(rxns); if nargin<4 maxIter=1000; diff --git a/struct_conversion/cobraToGurobiProb.m b/struct_conversion/cobraToGurobiProb.m deleted file mode 100755 index f86c9f6d..00000000 --- a/struct_conversion/cobraToGurobiProb.m +++ /dev/null @@ -1,25 +0,0 @@ -function gprob = cobraToGurobiProb(prob) - -gprob.obj = prob.c; -gprob.rhs = prob.b; -gprob.lb = prob.lb; -gprob.ub = prob.ub; -gprob.A = prob.A; -gprob.sense = '='; -gprob.modelsense = 'min'; - -% the binary type variables must be defined for milp -% use this more complicated approach to ignore "vartype" capitalization -f = fieldnames(prob); -[~,vartype_index] = ismember('vartype', lower(f)); -if vartype_index > 0 - gprob.vtype = prob.(f{vartype_index}); -else - gprob.vtype = repmat('C', 1, size(prob.A, 2)); -end - -if isfield(prob,'basis') && ~isempty(prob.basis) - gprob.cbasis=prob.basis.cbasis; - gprob.vbasis=prob.basis.vbasis; -end -end \ No newline at end of file diff --git a/struct_conversion/cobraToMosekRes.m b/struct_conversion/cobraToMosekRes.m deleted file mode 100755 index 514c15bc..00000000 --- a/struct_conversion/cobraToMosekRes.m +++ /dev/null @@ -1,35 +0,0 @@ -function res = cobraToMosekRes(res,keep,milp) - -% build solution -if(res.time>=1e9) - res.rcode='MSK_RES_TRM_MAX_TIME'; -else - res.rcode='crap'; -end - -if(milp) - res.sol.int.solsta=res.stat; - res.sol.int.prosta=res.stat; - if(res.stat~=0) - res.sol.int.xx=res.full(1:keep); - %res.sol.int.xx=res.int; - res.sol.int.pobjval=res.obj; - res.sol.pobjval=res.obj; - end -else - res.sol.bas.solsta='FEASIBLE'; - res.sol.bas.prosta='OPTIMAL'; - if res.stat==0 - res.sol.bas.solsta='INFEASIBLE'; - res.sol.bas.prosta='INFEASIBLE'; - elseif res.stat==2 - res.sol.bas.prosta='UNBOUND'; - end - if(res.stat~=0) - res.sol.bas.xx=res.full(1:keep); - res.sol.bas.pobjval=res.obj; - res.sol.pobjval=res.obj; - res.x=res.full(1:keep); - end -end -end diff --git a/struct_conversion/editMiriam.m b/struct_conversion/editMiriam.m index 16c4ac32..9e20109b 100755 --- a/struct_conversion/editMiriam.m +++ b/struct_conversion/editMiriam.m @@ -35,12 +35,16 @@ % model model structure with updated MIRIAM annotation field % % Usage: model=editMiriam(model,type,object,miriamName,miriams,keep) +miriamName=char(miriamName); +miriams=convertCharArray(miriams); %Check 'keep' input +keep=char(keep); if ~any(strcmp(keep,{'replace','fill','add'})) error('Invalid ''keep'', should be ''replace'',''fill'',''add''.') end %Check 'type' input +type=char(type); if ~any(strcmp(type,{'met','gene','rxn','comp'})) error('Invalid ''type'', should be ''met'', ''gene'', ''rxn'' or ''comp''.') end @@ -49,8 +53,9 @@ idxInModel=find(object); elseif isnumeric(object) idxInModel=object; -elseif ischar(object) - if strcmp(object,'all') +else + object=convertCharArray(object); + if numel(object)==1 && strcmp(object{1},'all') idxInModel=1:numel(model.([type,'s'])); else idxInModel=getIndexes(model,object,[type,'s']); @@ -58,16 +63,8 @@ dispEM('The following objects cannot be found in the model: ',true,object(~idxInModel)) end end -else - [~,idxInModel]=ismember(object,model.([type,'s'])); - if ~all(idxInModel) - dispEM('The following objects cannot be found in the model: ',true,object(~idxInModel)) - end end %Check 'miriams' input -if ischar(miriams) - miriams={miriams}; -end if numel(miriams)==1 && numel(idxInModel)~=1 miriams=repmat(miriams,numel(idxInModel),1); elseif numel(miriams)~=numel(idxInModel) diff --git a/struct_conversion/extractMiriam.m b/struct_conversion/extractMiriam.m index 66f89dde..fae3970b 100755 --- a/struct_conversion/extractMiriam.m +++ b/struct_conversion/extractMiriam.m @@ -24,17 +24,18 @@ % unique miriam names per entity % extractedMiriamNames cell array with extracted miriam names % -% Usage: miriam=extractMiriam(modelMiriams,miriamName,addNull) +% Usage: miriam=extractMiriam(modelMiriams,miriamName) if nargin<2 || strcmp(miriamNames,'all') extractAllTypes=true; else extractAllTypes=false; + miriamNames=convertCharArray(miriamNames); end %The annotation for all miriam names should be extracted if extractAllTypes - miriamNames=''; + miriamNames={''}; for i=1:numel(modelMiriams) if ~isempty(modelMiriams{i,1}) for j=1:numel(modelMiriams{i,1}.name) @@ -45,13 +46,8 @@ miriamNames=sort(unique(miriamNames)); end -%Ensure that the list of miriam names is in appropriate structure -if ischar(miriamNames) - miriamNames={miriamNames}; -end - %Aggregate the final cell array table with extracted miriam information -miriams=''; +miriams=cell(numel(modelMiriams),0); for i=1:numel(miriamNames) miriams=[miriams, extractMiriamType(modelMiriams,miriamNames{i})]; end diff --git a/struct_conversion/gurobiToCobraRes.m b/struct_conversion/gurobiToCobraRes.m deleted file mode 100755 index af6f7b9b..00000000 --- a/struct_conversion/gurobiToCobraRes.m +++ /dev/null @@ -1,39 +0,0 @@ -function res = gurobiToCobraRes(res, milp) - -if nargin < 2 - milp = false; -end - -try - resCb.full = res.x; - resCb.obj = res.objval; - resCb.time = res.runtime; - resCb.origStat = res.status; - if milp && strcmp(res.status, 'TIME_LIMIT') - % if the milp res structure has the "objval" field, it succeeded - res.status = 'OPTIMAL'; - end - switch res.status - case 'OPTIMAL' - resCb.stat = 1; - case 'INFEASIBLE' - resCb.stat = 0; - case 'UNBOUNDED' - resCb.stat = 2; - case 'INF_OR_UNBD' - resCb.stat = 0; - otherwise - resCb.stat = -1; % Solution not optimal or solver problem - end - if ~milp - resCb.basis.vbasis=res.vbasis; - resCb.basis.cbasis=res.cbasis; - end -catch - resCb.stat = 0; - if isfield(res, 'status') - resCb.origStat = res.status; % useful information to have - end -end -res=resCb; -end diff --git a/struct_conversion/ravenCobraWrapper.m b/struct_conversion/ravenCobraWrapper.m index 8225bac2..1d321139 100755 --- a/struct_conversion/ravenCobraWrapper.m +++ b/struct_conversion/ravenCobraWrapper.m @@ -34,11 +34,10 @@ isRaven=true; end -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(ST(I).file)); +ravenPath=findRAVENroot(); % Load COBRA field information -fid = fopen([ravenPath filesep 'struct_conversion' filesep 'COBRA_structure_fields.csv']); % Taken from https://github.com/opencobra/cobratoolbox/blob/develop/src/base/io/definitions/COBRA_structure_fields.csv +fid = fopen(fullfile(ravenPath,'struct_conversion','COBRA_structure_fields.csv')); % Taken from https://github.com/opencobra/cobratoolbox/blob/develop/src/base/io/definitions/COBRA_structure_fields.csv fieldFile = textscan(fid,repmat('%s',1,15),'Delimiter','\t','HeaderLines',1); dbFields = ~cellfun(@isempty,fieldFile{5}); % Only keep fields with database annotations that should be translated to xxxMiriams dbFields = dbFields & ~contains(fieldFile{1},{'metInChIString','metKEGGID','metPubChemID','rxnECNumbers'}); @@ -48,7 +47,7 @@ fclose(fid); % Load conversion between additional COBRA fields and namespaces: -fid = fopen([ravenPath filesep 'struct_conversion' filesep 'cobraNamespaces.csv']); +fid = fopen(fullfile(ravenPath,'struct_conversion','cobraNamespaces.csv')); fieldFile = textscan(fid,'%s %s','Delimiter',',','HeaderLines',0); COBRAfields = [COBRAfields; fieldFile{1}]; COBRAnamespace = [COBRAnamespace; fieldFile{2}]; diff --git a/struct_conversion/standardizeModelFieldOrder.m b/struct_conversion/standardizeModelFieldOrder.m index 34f1cab5..ac448f71 100755 --- a/struct_conversion/standardizeModelFieldOrder.m +++ b/struct_conversion/standardizeModelFieldOrder.m @@ -13,16 +13,15 @@ % % Usage: orderedModel=standardizeModelFieldOrder(model) -[ST, I]=dbstack('-completenames'); -ravenPath=fileparts(fileparts(ST(I).file)); +ravenPath=findRAVENroot(); if ~isfield(model,'rules') % Check if model is RAVEN - fid = fopen([ravenPath filesep 'struct_conversion' filesep 'orderRavenFields.csv']); + fid = fopen(fullfile(ravenPath,'struct_conversion','orderRavenFields.csv')); fields = textscan(fid,'%s','Delimiter',',','HeaderLines',0); fields = fields{1}; fclose(fid); else % If model is COBRA - fid = fopen([ravenPath filesep 'struct_conversion' filesep 'COBRA_structure_fields.csv']); % Taken from https://github.com/opencobra/cobratoolbox/blob/develop/src/base/io/definitions/COBRA_structure_fields.csv + fid = fopen(fullfile(ravenPath,'struct_conversion','COBRA_structure_fields.csv')); % Taken from https://github.com/opencobra/cobratoolbox/blob/develop/src/base/io/definitions/COBRA_structure_fields.csv fields = textscan(fid,repmat('%s',1,15),'Delimiter','\t','HeaderLines',1); fields = fields{1}; fclose(fid); @@ -33,4 +32,31 @@ remainingOrder = sort(setdiff(modelfields,order)); overallOrder = [columnVector(order);columnVector(remainingOrder)]; orderedModel = orderfields(model,overallOrder); -end \ No newline at end of file +end + +function vecT = columnVector(vec) +% Converts a vector to a column vector +% +% USAGE: +% +% vecT = columnVector(vec) +% +% INPUT: +% vec: a vector +% +% OUTPUT: +% vecT: a column vector +% +% .. Authors: +% - Original file: Markus Herrgard +% - Minor changes: Laurent Heirendt January 2017 +% - Copied from COBRA Toolbox May 2022 + +[n, m] = size(vec); + +if (m ~= 1 && n < m) || n == 1 + vecT = vec'; +else + vecT = vec; +end +end diff --git a/testing/unit_tests/cdhitTests.m b/testing/unit_tests/cdhitTests.m index d3d3e82b..1427b711 100755 --- a/testing/unit_tests/cdhitTests.m +++ b/testing/unit_tests/cdhitTests.m @@ -47,21 +47,20 @@ function testCdhit(testCase) sourceDir = fileparts(which(mfilename)); copyfile(fullfile(sourceDir,'test_data','yeast_galactosidases.fa'),tmpDIR); -% Define WSL paths -wslPath.fastaFile=getWSLpath([tmpDIR filesep 'yeast_galactosidases.fa']); -wslPath.outFile=getWSLpath(outFile); -wslPath.cdhit=getWSLpath(fullfile(ravenPath,'software','cd-hit','cd-hit')); - %% %Run protein clustering with CD-HIT if ispc + % Define WSL paths + wslPath.fastaFile=getWSLpath([tmpDIR filesep 'yeast_galactosidases.fa']); + wslPath.outFile=getWSLpath(outFile); + wslPath.cdhit=getWSLpath(fullfile(ravenPath,'software','cd-hit','cd-hit')); [~, ~]=system(['wsl "' wslPath.cdhit '" -T "' num2str(cores) '" -i "' wslPath.fastaFile '" -o "' wslPath.outFile '" -c 1.0 -n 5 -M 2000']); else [~, ~]=system(['"' fullfile(ravenPath,'software','cd-hit',['cd-hit' binEnd]) '" -T "' num2str(cores) '" -i "' fullfile(tmpDIR, 'yeast_galactosidases.fa') '" -o "' outFile '" -c 1.0 -n 5 -M 2000']); end %% -%Open actual MAFFT results file +%Open actual cdhit results file actCdhitOutput=importdata(fullfile(outFile)); %Remove the old tempfiles diff --git a/testing/unit_tests/fillGapsLargeTests.m b/testing/unit_tests/fillGapsLargeTests.m new file mode 100644 index 00000000..5df25eab --- /dev/null +++ b/testing/unit_tests/fillGapsLargeTests.m @@ -0,0 +1,115 @@ +%run this test case with the command +%results = runtests('fillGapsLargeTests.m') +function tests = fillGapsLargeTests +tests = functiontests(localfunctions); +end + +%% Skip testLargeGlpk, fails with larger models, known issue with glpk +% function testLargeGurobi(testCase) +% sourceDir = fileparts(fileparts(fileparts(which(mfilename)))); +% evalc('model=importModel(fullfile(sourceDir,''tutorial'',''iAL1006 v1.00.xml''))'); +% model.c(1484)=1; +% modelDB=model; % Keep as database with reactions +% try +% oldSolver=getpref('RAVEN','solver'); +% catch +% end +% setRavenSolver('glpk'); +% +% %Remove first 10 reactions +% model=removeReactions(modelDB,(1:10)); +% modelDB.id='DB'; +% try +% evalc('[newConnected,cannotConnect,addedRxns,model,exitFlag]=fillGaps(model,modelDB)'); +% catch +% try +% setRavenSolver(oldSolver); +% catch +% rmpref('RAVEN','solver'); +% end +% error('Solver not working') +% end +% sol=solveLP(model); +% try +% setRavenSolver(oldSolver); +% catch +% rmpref('RAVEN','solver'); +% end +% %Expect at least 5% of the original growth +% verifyTrue(testCase,-sol.f>0); +% end +%% +function testLargeGurobi(testCase) +if exist('gurobi','file')~=3 + error('Gurobi not installed or cannot be found in MATLAB path, test skipped') +end +sourceDir = fileparts(fileparts(fileparts(which(mfilename)))); +evalc('model=importModel(fullfile(sourceDir,''tutorial'',''iAL1006 v1.00.xml''))'); +model.c(1484)=1; +modelDB=model; % Keep as database with reactions +try + oldSolver=getpref('RAVEN','solver'); +catch +end +setRavenSolver('gurobi'); + +%Remove first 10 reactions +model=removeReactions(modelDB,(1:10)); +modelDB.id='DB'; +try + evalc('[newConnected,cannotConnect,addedRxns,model,exitFlag]=fillGaps(model,modelDB)'); +catch + try + setRavenSolver(oldSolver); + catch + rmpref('RAVEN','solver'); + end + error('Solver not working') +end +sol=solveLP(model); +try + setRavenSolver(oldSolver); +catch + rmpref('RAVEN','solver'); +end +%Expect at least 5% of the original growth +verifyTrue(testCase,-sol.f>0); +end + +function testLargeCobra(testCase) +if exist('initCobraToolbox.m','file')~=2 + error('COBRA Toolbox not installed or cannot be found in MATLAB path, test skipped') +end +sourceDir = fileparts(fileparts(fileparts(which(mfilename)))); +evalc('model=importModel(fullfile(sourceDir,''tutorial'',''iAL1006 v1.00.xml''))'); +model.c(1484)=1; +modelDB=model; % Keep as database with reactions +try + oldSolver=getpref('RAVEN','solver'); +catch +end +setRavenSolver('cobra'); + +%Remove first 10 reactions +model=removeReactions(modelDB,(1:10)); +modelDB.id='DB'; +try + evalc('[newConnected,cannotConnect,addedRxns,model,exitFlag]=fillGaps(model,modelDB)'); +catch + try + setRavenSolver(oldSolver); + catch + rmpref('RAVEN','solver'); + end + error('Solver not working') +end +sol=solveLP(model); +try + setRavenSolver(oldSolver); +catch + rmpref('RAVEN','solver'); +end + +%Expect at least 5% of the original growth +verifyTrue(testCase,-sol.f>0); +end \ No newline at end of file diff --git a/testing/unit_tests/fillGapsSmallTests.m b/testing/unit_tests/fillGapsSmallTests.m new file mode 100644 index 00000000..83487714 --- /dev/null +++ b/testing/unit_tests/fillGapsSmallTests.m @@ -0,0 +1,114 @@ +%run this test case with the command +%results = runtests('fillGapsSmallTests.m') +function tests = fillGapsSmallTests +tests = functiontests(localfunctions); +end + +function testSmallGlpk(testCase) +%Test using small model +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); +modelDB=model; % Keep as database with reactions +try + oldSolver=getpref('RAVEN','solver'); +catch +end +setRavenSolver('glpk'); + +%Remove first 10 reactions +model=removeReactions(modelDB,(1:10)); +modelDB.id='DB'; +try + evalc('[newConnected,cannotConnect,addedRxns,model,exitFlag]=fillGaps(model,modelDB)'); +catch + try + setRavenSolver(oldSolver); + catch + rmpref('RAVEN','solver'); + end + error('Solver not working') +end +sol=solveLP(model); +try + setRavenSolver(oldSolver); +catch + rmpref('RAVEN','solver'); +end +%Should give non-zero flux +verifyTrue(testCase,-sol.f>0); +end + +function testSmallGurobi(testCase) +if exist('gurobi','file')~=3 + error('Gurobi not installed or cannot be found in MATLAB path, test skipped') +end +%Test using small model +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); +modelDB=model; % Keep as database with reactions +try + oldSolver=getpref('RAVEN','solver'); +catch +end +setRavenSolver('gurobi'); + +%Remove first 10 reactions +model=removeReactions(modelDB,(1:10)); + +modelDB.id='DB'; +try + evalc('[newConnected,cannotConnect,addedRxns,model,exitFlag]=fillGaps(model,modelDB)'); +catch + try + setRavenSolver(oldSolver); + catch + rmpref('RAVEN','solver'); + end + error('Solver not working') +end +sol=solveLP(model); +try + setRavenSolver(oldSolver); +catch + rmpref('RAVEN','solver'); +end +%Expect at least 5% of the original growth +verifyTrue(testCase,-sol.f>0); +end + +function testSmallCobra(testCase) +if exist('initCobraToolbox.m','file')~=2 + error('COBRA Toolbox not installed or cannot be found in MATLAB path, test skipped') +end +%Test using small model +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); +modelDB=model; % Keep as database with reactions +try + oldSolver=getpref('RAVEN','solver'); +catch +end +setRavenSolver('cobra'); + +%Remove first 10 reactions +model=removeReactions(modelDB,(1:10)); +modelDB.id='DB'; +try + evalc('[newConnected,cannotConnect,addedRxns,model,exitFlag]=fillGaps(model,modelDB)'); +catch + try + setRavenSolver(oldSolver); + catch + rmpref('RAVEN','solver'); + end + error('Solver not working') +end +sol=solveLP(model); +try + setRavenSolver(oldSolver); +catch + rmpref('RAVEN','solver'); +end +%Expect at least 5% of the original growth +verifyTrue(testCase,-sol.f>0); +end \ No newline at end of file diff --git a/testing/unit_tests/importExportTests.m b/testing/unit_tests/importExportTests.m new file mode 100644 index 00000000..f50cb79b --- /dev/null +++ b/testing/unit_tests/importExportTests.m @@ -0,0 +1,52 @@ +%run this test case with the command +%results = runtests('importExportTests.m') +function tests = importExportTests +tests = functiontests(localfunctions); +end + +function testExcelImport(testCase) +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +excelFile=fullfile(sourceDir,'tutorial','empty.xlsx'); +%%Prepare test results, uncomment and run when new reference is needed +% modelExcel=importExcelModel(excelFile); +% sbmlFile=fullfile(sourceDir,'tutorial','empty.xml'); +% modelSBML=importModel(sbmlFile); +% save(fullfile(sourceDir,'testing','unit_tests','test_data','importExportResults.mat'),'modelExcel','modelSBML'); +evalc('model=importExcelModel(excelFile)'); % Repress warnings +load(fullfile(sourceDir,'testing','unit_tests','test_data','importExportResults.mat'), 'modelExcel'); +verifyEqual(testCase,model,modelExcel) +end + +function testSBMLImport(testCase) +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +sbmlFile=fullfile(sourceDir,'tutorial','empty.xml'); +evalc('model=importModel(sbmlFile)'); % Repress warnings +load(fullfile(sourceDir,'testing','unit_tests','test_data','importExportResults.mat'), 'modelSBML'); +verifyEqual(testCase,model,modelSBML) +end + +function testExcelExport(testCase) +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); +exportToExcelFormat(model,fullfile(sourceDir,'testing','unit_tests','test_data','_test.xlsx')); +%File will not be exactly equal as it contains the current date and time, +%so md5 or similar would not work. Just check whether file is reasonably +%sized. +s = dir(fullfile(sourceDir,'testing','unit_tests','test_data','_test.xlsx')); +filesize = s.bytes; +verifyTrue(testCase,filesize>17000); +delete(fullfile(sourceDir,'testing','unit_tests','test_data','_test.xlsx')); +end + +function testSBMLExport(testCase) +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); +evalc('exportModel(model,fullfile(sourceDir,''testing'',''unit_tests'',''test_data'',''_test.xml''))'); +%File will not be exactly equal as it contains the current date and time, +%so md5 or similar would not work. Just check whether file is reasonably +%sized. +s = dir(fullfile(sourceDir,'testing','unit_tests','test_data','_test.xml')); +filesize = s.bytes; +verifyTrue(testCase,filesize>18500); +delete(fullfile(sourceDir,'testing','unit_tests','test_data','_test.xml')); +end diff --git a/testing/unit_tests/mafftTests.m b/testing/unit_tests/mafftTests.m index b4ffdfd4..9c5b877b 100755 --- a/testing/unit_tests/mafftTests.m +++ b/testing/unit_tests/mafftTests.m @@ -33,11 +33,6 @@ function testMafft(testCase) sourceDir = fileparts(which(mfilename)); copyfile(fullfile(sourceDir,'test_data','yeast_galactosidases.fa'),tmpDIR); -% Define WSL paths -wslPath.fastaFile=getWSLpath([tmpDIR filesep 'yeast_galactosidases.fa']); -wslPath.outFile=getWSLpath(outFile); -wslPath.mafft=getWSLpath(fullfile(ravenPath,'software','mafft','mafft-linux64','mafft.bat')); - %% %Run protein multi-sequence alignment with MAFFT if ismac @@ -45,6 +40,10 @@ function testMafft(testCase) elseif isunix [~, ~]=system(['"' fullfile(ravenPath,'software','mafft','mafft-linux64','mafft.bat') '" --auto --anysymbol --thread "' num2str(cores) '" "' fullfile(tmpDIR, 'yeast_galactosidases.fa') '" > "' outFile '"']); elseif ispc + % Define WSL paths + wslPath.fastaFile=getWSLpath([tmpDIR filesep 'yeast_galactosidases.fa']); + wslPath.outFile=getWSLpath(outFile); + wslPath.mafft=getWSLpath(fullfile(ravenPath,'software','mafft','mafft-linux64','mafft.bat')); [~, ~]=system(['wsl "' wslPath.mafft '" --auto --anysymbol --quiet --thread "' num2str(cores) '" --out "' wslPath.outFile '" "' wslPath.fastaFile '"']); end diff --git a/testing/unit_tests/miriamTests.m b/testing/unit_tests/miriamTests.m index d7cbac09..635f1af7 100644 --- a/testing/unit_tests/miriamTests.m +++ b/testing/unit_tests/miriamTests.m @@ -1,5 +1,5 @@ %run this test case with the command -%results = runtests('sortIdentifiers_and_permuteModelTests.m') +%results = runtests('miriamTests.m') function tests = miriamTests tests = functiontests(localfunctions); end diff --git a/testing/unit_tests/modelAbilitiesTests.m b/testing/unit_tests/modelAbilitiesTests.m new file mode 100644 index 00000000..a9780257 --- /dev/null +++ b/testing/unit_tests/modelAbilitiesTests.m @@ -0,0 +1,123 @@ +%run this test case with the command +%results = runtests('modelAbilitiesTests.m') +function tests = modelAbilitiesTests +tests = functiontests(localfunctions); +end + +function canConsumeTest(testCase) +%Load the model in RAVEN format +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); + +testOut=canConsume(model,{'r5p_c';'ru5p_DASH_D_c';'s7p_c';'succ_c';'succ_e';'succoa_c';'xu5p_DASH_D_c'}); + +testCheck=[true;true;true;true;true;false;true]; + +verifyEqual(testCase,testOut,testCheck) +end + +function canProduceTest(testCase) +%Load the model in RAVEN format +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); + +testOut=canProduce(model,{'r5p_c';'ru5p_DASH_D_c';'s7p_c';'succ_c';'succ_e';'succoa_c';'xu5p_DASH_D_c'}); + +testCheck=[true;true;true;true;true;false;true]; + +verifyEqual(testCase,testOut,testCheck) +end + +function checkProductionTest(testCase) +%Load the model in RAVEN format +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); + +[testOut.np, testOut.npn, testOut.nfpm,testOut.mtc,~]=checkProduction(model,true,model.comps,false); + +testCheck.np=[10;13;16;17;21;30;32;37;49;50;51;52;53;64;65;71]; +testCheck.npn={'Acetyl-CoA[c]';'ADP[c]';'AMP[c]';'ATP[c]';'Coenzyme A[c]';'D-Fructose[e]';'Fumarate[e]';'L-Glutamine[e]';'L-Malate[e]';'NAD[c]';'NADH[c]';'NADP[c]';'NADPH[c]';'Ubiquinone-8[c]';'Ubiquinol-8[c]';'Succinyl-CoA[c]'}; +testCheck.nfpm=[true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true;false,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false;false,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false;false,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false;true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true;false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false;false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false;false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false;false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false;false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false;false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false;false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false;false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false;false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false;false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false;true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true]; +testCheck.mtc={'Acetyl-CoA[c] (connects 3 metabolites)';'ADP[c] (connects 3 metabolites)';'NAD[c] (connects 2 metabolites)';'NADP[c] (connects 2 metabolites)';'Ubiquinone-8[c] (connects 2 metabolites)';'D-Fructose[e] (connects 1 metabolites)';'Fumarate[e] (connects 1 metabolites)';'L-Glutamine[e] (connects 1 metabolites)';'L-Malate[e] (connects 1 metabolites)'}; + +verifyEqual(testCase,testOut,testCheck) +end + +function consumeSomethingTest(testCase) +%Load the model in RAVEN format +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); + +[testOut.s, testOut.m]=consumeSomething(model,{'r5p_c';'ru5p_DASH_D_c';'s7p_c';'succ_c';'succ_e';'succoa_c';'xu5p_DASH_D_c'}); +% Simplify output for later check, no need for high precision +% testOut.s(abs(testOut.s)<1e-10)=0; +% testOut.s=round(testOut.s,4) +testCheck.s=[0;0;-1.45910;0;0;-1.45910;0;0;0;0;8.39000;4.01260;0;-1.45910;0;2.91830;0;1.45910;0;1.45910;0;0;1.45910;0;0;0;0;0;0;0;1.45910;0;0;0;0;-1.45910;1.45910;0;0;0;0;0;0;0;0;0;0;0;1.45910;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;2.91830;0;0;1.45910;1.45910;0;0;0;-1.45910;0;-1.45910;-1.45910;0;0;0;1.45910;1.45910;0;0;0;0;0;0;0;0;0;0;0;0]; +testCheck.m=[33]; + +verifyEqual(testCase,testOut,testCheck,'AbsTol',1e-4) +end + +function makeSomethingTest(testCase) +%Load the model in RAVEN format +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); + +[testOut.s, testOut.m]=makeSomething(model,{'r5p_c';'ru5p_DASH_D_c';'s7p_c';'succ_c';'succ_e';'succoa_c';'xu5p_DASH_D_c'}); +% Simplify output for later check, no need for high precision +% testOut.s(abs(testOut.s)<1e-10)=0; +% testOut.s=round(testOut.s,4); + +testCheck.s=[0;0;-1.86440;0;0;0;0;0;0;0;8.39000;4.66110;0;0;0;3.72890;0;1.86440;0;0;0;0;0;0;0;0;0;-0.932200;0;0;0;0;0;0;0;-1.86440;0;0;0;0.932200;0;0;0;0;0;0;0;0;1.86440;0.932200;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;3.72890;0;0;1.86440;1.86440;0.932200;0;0.932200;-1.86440;0;-1.86440;0;0;0;0;1.86440;0.932200;0;0;0;0;0;0;0;0;0;0;0;0.932200]; +testCheck.m=[6]; + +verifyEqual(testCase,testOut,testCheck,'AbsTol',1e-4) +end + +function getElementalBalanceTest(testCase) +%Load the model in RAVEN format +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); + +testOut=getElementalBalance(model,1); + +testCheck.balanceStatus=1; +testCheck.elements.abbrevs={'C';'N';'O';'S';'P';'H'}; +testCheck.elements.names={'carbon';'nitrogen';'oxygen';'sulfur';'phosphorus';'hydrogen'}; +testCheck.leftComp=[44,14,31,1,5,62]; +testCheck.rightComp=[44,14,31,1,5,62]; + +verifyEqual(testCase,testOut,testCheck) +end + +function getAllowedBoundsTest(testCase) +%Load the model in RAVEN format +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); + + +[testOut.min, testOut.max, testOut.flag]=getAllowedBounds(model,[1:10]); +% Simplify output for later check, no need for high precision +% testOut.min(abs(testOut.min)<1e-10)=0; +% testOut.min=single(testOut.min); +% testOut.max(abs(testOut.max)<1e-10)=0; +% testOut.max=single(testOut.max); + +testCheck.min=[-20;-20;-20;0;0;-20;0;0;-10;-20]; +testCheck.max=[0;0;0;20;20;0;166.61000;20;0;0]; +testCheck.flag=[1,1;1,1;1,1;1,1;1,1;1,1;1,1;1,1;1,1;1,1]; + +verifyEqual(testCase,testOut,testCheck,'AbsTol',1e-4) +end + +function getEssentialRxnsTest(testCase) +%Load the model in RAVEN format +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); + +[testOut.r, testOut.i]=getEssentialRxns(model); + +testCheck.r={'EX_glc';'GLCpts'}; +testCheck.i=[28;50]; +verifyEqual(testCase,testOut,testCheck) +end diff --git a/testing/unit_tests/modelConversionTests.m b/testing/unit_tests/modelConversionTests.m new file mode 100644 index 00000000..6ddba7ca --- /dev/null +++ b/testing/unit_tests/modelConversionTests.m @@ -0,0 +1,25 @@ +%run this test case with the command +%results = runtests('modelConversionTests.m') +function tests = modelConversionTests +tests = functiontests(localfunctions); +end + +function ravenCobraWrapperTest(testCase) +%This function tests the ravenCobraWrapper function by going through a full +%cycle RAVEN -> COBRA -> RAVEN, and the model should be (near) identical +%(only annotation field should be lost). + +%Load the model in RAVEN format +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); + +%Prevent writing of messages to command window +evalc('modelCobra=ravenCobraWrapper(model);'); +evalc('modelRaven=ravenCobraWrapper(modelCobra);'); + +%We know that the annotation field is lost +modelNoAnnot=rmfield(model,'annotation'); + +%Check that the actual model is the same as the expected model +verifyEqual(testCase,modelRaven,modelNoAnnot) +end diff --git a/testing/unit_tests/modelCurationTests.m b/testing/unit_tests/modelCurationTests.m new file mode 100644 index 00000000..afb7a065 --- /dev/null +++ b/testing/unit_tests/modelCurationTests.m @@ -0,0 +1,455 @@ +%run this test case with the command +%results = runtests('modelCurationTests.m') +function tests = modelCurationTests +tests = functiontests(localfunctions); +end + +function addExchangeRxnsTest(testCase) +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); + +modelNew=addExchangeRxns(model,'both','6pgl_c'); + +%Perform the curation manually for comparison +modelManual=model; +modelManual.rxns(end+1)={'EXC_BOTH_6pgl_c'}; +modelManual.lb(end+1)=-1000; +modelManual.ub(end+1)=1000; +modelManual.c(end+1)=0; +modelManual.rev(end+1)=1; +modelManual.rxnNames(end+1)={'6-phospho-D-glucono-1,5-lactone exchange (BOTH)'}; +modelManual.grRules(end+1)={''}; +modelManual.eccodes(end+1)={''}; +modelManual.rxnGeneMat(end+1,:)=sparse(zeros(1,numel(modelManual.genes))); +modelManual.S(:,end+1)=sparse(zeros(numel(modelManual.mets),1)); +modelManual.S(5,end)=-1; + +verifyEqual(testCase,modelNew,modelManual) +end + +function addTransportTest(testCase) +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); + +evalc('modelNew=addTransport(model,''c'',''e'',{''6-phospho-D-glucono-1,5-lactone''},false,false,''test_'');'); + +%Perform the curation manually for comparison +modelManual=model; +modelManual.rxns(end+1)={'test_0001'}; +modelManual.lb(end+1)=0; +modelManual.ub(end+1)=Inf; +modelManual.c(end+1)=0; +modelManual.rev(end+1)=0; +modelManual.rxnNames(end+1)={'6-phospho-D-glucono-1,5-lactone transport, Cytoplasm-Extraorganism'}; +modelManual.grRules(end+1)={''}; +modelManual.eccodes(end+1)={''}; +modelManual.rxnGeneMat(end+1,:)=sparse(zeros(1,numel(modelManual.genes))); + +modelManual.S(:,end+1)=sparse(zeros(numel(modelManual.mets),1)); +modelManual.S(end+1,:)=sparse(zeros(1,numel(modelManual.rxns))); +modelManual.S([5,73],end)=[-1,1]; + +modelManual.mets(end+1)={'m_0001'}; +modelManual.metNames(end+1)={'6-phospho-D-glucono-1,5-lactone'}; +modelManual.metMiriams(end+1)=modelManual.metMiriams(5); +modelManual.b(end+1)=[0]; +modelManual.metFormulas(end+1)={'C6H9O9P'}; +modelManual.metComps(end+1)=[2]; + +verifyEqual(testCase,modelNew,modelManual) +end + +function addGenesRavenTest(testCase) +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); + +genesToAdd.genes={'testgene1','testgene2'}; +genesToAdd.geneShortNames={'short1','short2'}; +genesToAdd.geneMiriams{1}=struct('name',{{'testDB1';'testDB2'}},'value',... + {{'testValue1';'testValue2'}}); +genesToAdd.geneMiriams{2}=struct('name',{{'testDB2';'testDB1'}},'value',... + {{'testValue2';'testValue1'}}); + +modelNew=addGenesRaven(model,genesToAdd); + +%Perform the curation manually for comparison +modelManual=model; +modelManual.geneMiriams(1:numel(modelManual.genes),1)={[]}; +modelManual.genes(end+1:end+2)=genesToAdd.genes; +modelManual.geneShortNames(end+1:end+2)=genesToAdd.geneShortNames; +modelManual.rxnGeneMat(:,end+1:end+2)=sparse(zeros(numel(modelManual.rxns),2)); +modelManual.geneMiriams(end+1:end+2)=genesToAdd.geneMiriams; +verifyEqual(testCase,modelNew,modelManual) +end + +function removeGenesTest(testCase) +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); + +modelNew=removeGenes(model,'b1817',true,true,false); + +%Perform the curation manually for comparison +modelManual=model; +modelManual.genes(54)=[]; +modelManual.geneShortNames(54)=[]; +modelManual.rxnGeneMat(:,54)=[]; +modelManual.rxnGeneMat(45,:)=[]; +modelManual.grRules(50)={'(b2415 and b1621 and b2417 and b2416) or (b2415 and b2417 and b2416 and b1101)'}; +modelManual.grRules(45)=[]; +modelManual.rxns(45)=[]; +modelManual.rxnNames(45)=[]; +modelManual.lb(45)=[]; +modelManual.ub(45)=[]; +modelManual.c(45)=[]; +modelManual.rev(45)=[]; +modelManual.S(:,45)=[]; +modelManual.eccodes(45)=[]; +verifyEqual(testCase,modelNew,modelManual) +end + +function addMetsTest(testCase) +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); + +metsToAdd.metNames={'metaboliteName','3-Phospho-D-glycerate'}; +metsToAdd.compartments={'c','e'}; +metsToAdd.metCharges=[2,0]; +metsToAdd.metNotes={'this is just a test','another one'}; +metsToAdd.metMiriams{1}=struct('name',{{'testDB1';'testDB2'}},'value',... + {{'testValue1';'testValue2'}}); +metsToAdd.metMiriams{2}=struct('name',{{'testDB1'}},'value',... + {{'testValue1'}}); + +evalc('modelNew=addMets(model,metsToAdd,true);'); + +%Perform the curation manually for comparison +modelManual=model; +modelManual.metNotes(1:numel(modelManual.mets),1)={''}; +modelManual.metCharges(1:numel(modelManual.mets),1)=NaN(numel(modelManual.mets),1); +modelManual.mets(end+1:end+2)={'m_0001','m_0002'}; +modelManual.metNames(end+1:end+2)=metsToAdd.metNames; +modelManual.metNotes(end+1:end+2)=metsToAdd.metNotes; +modelManual.metMiriams(end+1:end+2)=metsToAdd.metMiriams; +modelManual.metCharges(end+1:end+2)=[2,NaN]; +modelManual.b(end+1:end+2)=[0,0]; +modelManual.metFormulas(end+1:end+2)={'','C3H4O7P'}; +modelManual.metComps(end+1:end+2)=[1,2]; +modelManual.S(end+1:end+2,:)=sparse(zeros(2,numel(modelManual.rxns))); + +verifyEqual(testCase,modelManual,modelNew) +end + +function removeMetsTest(testCase) +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); + +modelNew=removeMets(model,'Acetate',true,true,true,true); + +%Perform the curation manually for comparison +modelManual=model; +modelManual.mets(6:7)=[]; +modelManual.metNames(6:7)=[]; +modelManual.metMiriams(6:7)=[]; +modelManual.b(6:7)=[]; +modelManual.metFormulas(6:7)=[]; +modelManual.metComps(6:7)=[]; +modelManual.S(6:7,:)=[]; + +modelManual.rxnGeneMat(20,:)=[]; +modelManual.grRules(20)=[]; +modelManual.rxns(20)=[]; +modelManual.rxnNames(20)=[]; +modelManual.lb(20)=[]; +modelManual.ub(20)=[]; +modelManual.c(20)=[]; +modelManual.rev(20)=[]; +modelManual.S(:,20)=[]; +modelManual.eccodes(20)=[]; +verifyEqual(testCase,modelNew,modelManual) +end + +function addRxnsTest(testCase) +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); +rxnsToAdd.rxns='test1'; +rxnsToAdd.equations='2-Oxoglutarate => TEST'; +rxnsToAdd.rxnNames={'testRxn1'}; % test cell array +rxnsToAdd.rxnMiriams{1}=struct('name',{{'testDB1';'testDB2'}},'value',... + {{'testValue1';'testValue2'}}); +rxnsToAdd.grRules="b0008"; % test string +evalc('modelNew=addRxns(model,rxnsToAdd,2,''c'',true);'); + +rxnsToAdd.rxns='test2'; +rxnsToAdd=rmfield(rxnsToAdd,'equations'); +rxnsToAdd.mets={{'6pgl_c','atp_c'}}; +rxnsToAdd.stoichCoeffs=[[-1,2]]; +rxnsToAdd.lb=-1000; +rxnsToAdd.grRules='test'; +evalc('modelNew=addRxns(modelNew,rxnsToAdd,1,''c'',true,true);'); + +%Perform the curation manually for comparison +modelManual=model; + +modelManual.rxnMiriams=cell(numel(modelManual.rxns),1); +modelManual.rxns(end+1:end+2)={'test1';'test2'}; +modelManual.mets(end+1)={'m_0001'}; +modelManual.S(end+1,:)=zeros(1,numel(modelManual.rxns)-2); +modelManual.S(:,end+1:end+2)=zeros(numel(modelManual.mets),2); +modelManual.S(end,96)=1; +modelManual.S([14,73],end-1)=[-1,1]; +modelManual.S([5,17],end)=[-1,2]; +modelManual.lb(end+1:end+2)=[0;-1000]; +modelManual.ub(end+1:end+2)=[Inf;Inf]; +modelManual.rev(end+1:end+2)=[0;1]; +modelManual.c(end+1:end+2)=[0;0]; +modelManual.b(end+1)=[0]; +modelManual.rxnNames(end+1:end+2)={'testRxn1';'testRxn1'}; +modelManual.grRules(end+1:end+2)={'b0008';'test'}; + +modelManual.rxnGeneMat(end+1:end+2,:)=zeros(2,numel(modelManual.genes)); +modelManual.rxnGeneMat(:,end+1)=zeros(numel(modelManual.rxns),1); +modelManual.rxnGeneMat(97,end)=1; +modelManual.rxnGeneMat(end-1,1)=1; +modelManual.rxnGeneMat(end,138)=1; + +modelManual.eccodes(end+1:end+2)={'';''}; +modelManual.genes(end+1)={'test'}; +modelManual.geneShortNames(end+1)={''}; +modelManual.metNames(end+1)={'TEST'}; +modelManual.metComps(end+1)=[1]; +modelManual.metFormulas(end+1)={''}; +modelManual.metMiriams(end+1)={[]}; +modelManual.rxnMiriams(end+1:end+2)={struct('name',{{'testDB1';'testDB2'}},'value',... + {{'testValue1';'testValue2'}})}; + +verifyEqual(testCase,modelManual,modelNew) +end + +function removeReactionsTest(testCase) +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); + +modelNew=removeMets(model,'Acetate',true,true,true,true); + +%Perform the curation manually for comparison +modelManual=model; +modelManual.mets(6:7)=[]; +modelManual.metNames(6:7)=[]; +modelManual.metMiriams(6:7)=[]; +modelManual.b(6:7)=[]; +modelManual.metFormulas(6:7)=[]; +modelManual.metComps(6:7)=[]; +modelManual.S(6:7,:)=[]; + +modelManual.rxnGeneMat(20,:)=[]; +modelManual.grRules(20)=[]; +modelManual.rxns(20)=[]; +modelManual.rxnNames(20)=[]; +modelManual.lb(20)=[]; +modelManual.ub(20)=[]; +modelManual.c(20)=[]; +modelManual.rev(20)=[]; +modelManual.S(:,20)=[]; +modelManual.eccodes(20)=[]; +verifyEqual(testCase,modelNew,modelManual) +end + +function getMetsInCompTest(testCase) +%Load the model in RAVEN format +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); + +evalc('[testOut.I, testOut.metNames]=getMetsInComp(model,''e'');'); + +testCheck.I=[false;false;false;false;false;false;true;false;true;false;false;false;false;false;true;false;false;false;false;true;false;false;false;false;true;false;false;false;true;true;false;true;false;false;true;false;true;false;true;false;false;true;false;true;false;false;true;false;true;false;false;false;false;false;true;false;true;false;false;false;true;false;true;false;false;false;false;false;false;true;false;false]; +testCheck.metNames={'Acetate';'Acetaldehyde';'2-Oxoglutarate';'CO2';'Ethanol';'Formate';'D-Fructose';'Fumarate';'D-Glucose';'L-Glutamine';'L-Glutamate';'H2O';'H+';'D-Lactate';'L-Malate';'Ammonium';'O2';'Phosphate';'Pyruvate';'Succinate'}; +verifyEqual(testCase,testOut,testCheck) +end + +function getRxnsInCompTest(testCase) +%Load the model in RAVEN format +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); + +evalc('[testOut.I, testOut.rxnNames]=getRxnsInComp(model,''e'');'); + +testCheck.I=[20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39]; +testCheck.rxnNames={'Acetate exchange';'Acetaldehyde exchange';'2-Oxoglutarate exchange';'CO2 exchange';'Ethanol exchange';'Formate exchange';'D-Fructose exchange';'Fumarate exchange';'D-Glucose exchange';'L-Glutamine exchange';'L-Glutamate exchange';'H+ exchange';'H2O exchange';'D-lactate exchange';'L-Malate exchange';'Ammonia exchange';'O2 exchange';'Phosphate exchange';'Pyruvate exchange';'Succinate exchange'}; +verifyEqual(testCase,testOut,testCheck) +end + +function getAllRxnsFromGenesTest(testCase) +%Load the model in RAVEN format +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); +evalc('testOut=getAllRxnsFromGenes(model,''ACONTa'');'); + +testCheck={'ACONTa';'ACONTb'}; +verifyEqual(testCase,testOut,testCheck) +end + +function changeRxnsTest(testCase) +%Load the model in RAVEN format +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); + +evalc('modelNew=changeRxns(model,''ACKr'',''2-Oxoglutarate => TEST'',2,''c'',true);'); + +%Perform the curation manually for comparison +modelManual=model; + +modelManual.mets(end+1)={'m_0001'}; +modelManual.S(end+1,:)=zeros(1,numel(modelManual.rxns)); +modelManual.S(:,3)=0; +modelManual.S([14,73],3)=[-1,1]; + +modelManual.metNames(end+1)={'TEST'}; +modelManual.metComps(end+1)=[1]; +modelManual.metFormulas(end+1)={''}; +modelManual.metMiriams(end+1)={[]}; +modelManual.b(end+1)=[0]; +modelManual.rev(3)=[0]; + +verifyEqual(testCase,modelNew,modelManual) +end + +function removeBadRxnsTest(testCase) +%Load the model in RAVEN format +sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); +load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); + +[~,exchRxns]=getExchangeRxns(model); +modelNew=model; + +modelNew.lb(exchRxns)=[0]; +modelNew.ub(exchRxns)=[0]; +modelNew.lb(modelNew.lb>0)=0; +modelNew.S(17,:)=1; +[~, testOut]=removeBadRxns(modelNew); +evalc('[~, testOut]=removeBadRxns(modelNew,3,modelNew.metComps==2);'); + +import matlab.unittest.constraints.AnyCellOf; +import matlab.unittest.constraints.ContainsSubstring; +verifyThat(testCase,AnyCellOf({'SUCDi','FRD7'}),ContainsSubstring(testOut{:}),'test') +%Either SUCDi or FRD7 should be given as output +end + +function changeGrRulesTest(testCase) +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); + +modelNew=changeGrRules(model,{'ACKr','ACONTa'},{'b2296 and b1849';'b1849'},true); +modelNew=changeGrRules(modelNew,'ACONTa','b1849',false); + +%Perform the curation manually for comparison +modelManual=model; +modelManual.grRules(3:4)={'b2296 and b1849';'b1849 or b1849'}; +modelManual.rxnGeneMat(3:4,:)=0; +modelManual.rxnGeneMat(3,[57,76])=1; +modelManual.rxnGeneMat(4,57)=1; + +verifyEqual(testCase,modelNew,modelManual) +end + +function copyToCompsTest(testCase) +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); + +modelNew=copyToComps(model,{'p','e'},'ACKr'); + +%Perform the curation manually for comparison +modelManual=model; + +modelManual.rxns(end+1:end+2)={'ACKr_p';'ACKr_e'}; +modelManual.mets(end+1:end+7)={'ac_c_p';'actp_c_p';'adp_c_p';'atp_c_p';'actp_c_e';'adp_c_e';'atp_c_e'}; +modelManual.S(end+1:end+7,:)=zeros(7,numel(modelManual.rxns)-2); +modelManual.S(:,end+1:end+2)=zeros(numel(modelManual.mets),2); + +modelManual.S([73,74,75,76],end-1)=[-1,1,1,-1]; +modelManual.S([7,77,78,79],end)=[-1,1,1,-1]; + +modelManual.lb(end+1:end+2)=[-1000;-1000]; +modelManual.ub(end+1:end+2)=[1000;1000]; +modelManual.rev(end+1:end+2)=[1;1]; +modelManual.c(end+1:end+2)=[0;0]; +modelManual.rxnNames(end+1:end+2)={'acetate kinase';'acetate kinase'}; +modelManual.grRules(end+1:end+2)={'b2296 or b1849 or b3115';'b2296 or b1849 or b3115'}; +modelManual.eccodes(end+1:end+2)={'2.7.2.1';'2.7.2.1'}; + +modelManual.rxnGeneMat(end+1:end+2,:)=zeros(2,numel(modelManual.genes)); +modelManual.rxnGeneMat(end-1:end,[57,76,97])=1; + +modelManual.metNames(end+1:end+7)={'Acetate';'Acetyl phosphate';'ADP';'ATP';'Acetyl phosphate';'ADP';'ATP'}; +modelManual.metComps(end+1:end+7)=[3;3;3;3;2;2;2]; +modelManual.metFormulas(end+1:end+7)={'C2H3O2';'C2H3O5P';'C10H12N5O10P2';'C10H12N5O13P3';'C2H3O5P';'C10H12N5O10P2';'C10H12N5O13P3'}; +modelManual.metMiriams(end+1:end+7)=modelManual.metMiriams([6,12,13,17,12,13,17]); +modelManual.b(end+1:end+7)=[0]; + +modelManual.comps(end+1)={'p'}; +modelManual.compNames(end+1)={'p'}; + +verifyEqual(testCase,modelNew,modelManual) +end + +function setExchangeBoundsTest(testCase) +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); + +modelNew=setExchangeBounds(model,{'ac_e';'akg_e'},-500,500); + +%Perform the curation manually for comparison +modelManual=model; + +exchRxns=[21;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39]; +modelManual.lb(exchRxns)=0; +modelManual.lb([20,22])=-500; +modelManual.ub([20,22])=500; + +verifyEqual(testCase,modelNew,modelManual) +end + +function addRxnsGenesMetsTest(testCase) +sourceDir = fileparts(which(mfilename)); +load(fullfile(sourceDir,'test_data','ecoli_textbook.mat'), 'model'); + +sbmlFile=fullfile(sourceDir,'..','..','tutorial','empty.xml'); +evalc('modelEmpty=importModel(sbmlFile)'); % Repress warnings + +evalc('modelNew=addRxnsGenesMets(model,modelEmpty,''r1'',true);'); + +%Perform the curation manually for comparison +modelManual=model; + +modelManual.rxns(end+1)={'r1'}; +modelManual.mets(end+1:end+3)={'m1';'m2';'m3'}; +modelManual.S(end+1:end+3,:)=zeros(3,numel(modelManual.rxns)-1); +modelManual.S(:,end+1)=zeros(numel(modelManual.mets),1); +modelManual.S([42,73,74,75],end)=[-1,-1,1,1]; + +modelManual.lb(end+1)=[0]; +modelManual.ub(end+1)=[1000]; +modelManual.rev(end+1)=[0]; +modelManual.c(end+1)=[0]; +modelManual.rxnNames(end+1)={'Breakdown of sucrose (invertase)'}; +modelManual.grRules(end+1)={'g1'}; +modelManual.eccodes(end+1)={''}; +modelManual.rxnNotes(1:numel(modelManual.rxns),1)={''}; +modelManual.rxnNotes(end)={'Added via addRxnsGenesMets()'}; +modelManual.rxnConfidenceScores(1:numel(modelManual.rxns),1)=NaN; +modelManual.rxnConfidenceScores(end)=[0]; + +modelManual.genes(end+1)={'g1'}; +modelManual.geneShortNames(end+1)={''}; + +modelManual.rxnGeneMat(end+1,:)=zeros(1,numel(modelManual.genes)-1); +modelManual.rxnGeneMat(:,end+1)=zeros(numel(modelManual.rxns),1); +modelManual.rxnGeneMat(end,end)=1; + +modelManual.metNames(end+1:end+3)={'sucrose';'glucose';'fructose'}; +modelManual.metComps(end+1:end+3)=[2;2;2]; +modelManual.metFormulas(end+1:end+3)={'C12H22O11';'C6H12O6';'C6H12O6'}; +modelManual.metMiriams(end+1:end+3)={[];[];[]}; +modelManual.b(end+1:end+3)=[0]; + +verifyEqual(testCase,modelNew,modelManual) +end diff --git a/testing/unit_tests/solverTests.m b/testing/unit_tests/solverTests.m new file mode 100644 index 00000000..abea5dfe --- /dev/null +++ b/testing/unit_tests/solverTests.m @@ -0,0 +1,114 @@ +%run this test case with the command +%results = runtests('solverTests.m') +function tests = solverTests +tests = functiontests(localfunctions); +end + +function testGlpk(testCase) +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); +try + oldSolver=getpref('RAVEN','solver'); +catch +end +setRavenSolver('glpk'); + +try + % Try all three types of flux minimization + evalc('sol=solveLP(model,3);'); + evalc('sol=solveLP(model,1);'); + evalc('sol=solveLP(model,0);'); +catch + try + setRavenSolver(oldSolver); + catch + rmpref('RAVEN','solver'); + end + error('Solver not working') +end +try + setRavenSolver(oldSolver); +catch + rmpref('RAVEN','solver'); +end + +load([sourceDir,'/test_data/solverTestOutput.mat'], 'solGlpk'); +%Check that the actual model is the same as the expected model +verifyEqual(testCase,sol,solGlpk,'AbsTol',1e-5) +end + +function testGurobi(testCase) +if exist('gurobi','file')~=3 + error('Gurobi not installed or cannot be found in MATLAB path, test skipped') +end +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); +try + oldSolver=getpref('RAVEN','solver'); +catch +end +setRavenSolver('gurobi'); + +try + % Try all three types of flux minimization + evalc('sol=solveLP(model,3);'); + evalc('sol=solveLP(model,1);'); + evalc('sol=solveLP(model,0);'); +catch + try + setRavenSolver(oldSolver); + catch + rmpref('RAVEN','solver'); + end + error('Solver not working') +end +try + setRavenSolver(oldSolver); +catch + rmpref('RAVEN','solver'); +end + +load([sourceDir,'/test_data/solverTestOutput.mat'], 'solGurobi'); +%Check that the actual model is the same as the expected model +verifyEqual(testCase,sol,solGurobi,'AbsTol',1e-5) +end + +function testCobra(testCase) +if exist('initCobraToolbox.m','file')~=2 + error('COBRA Toolbox not installed or cannot be found in MATLAB path, test skipped') +end +sourceDir = fileparts(which(mfilename)); +load([sourceDir,'/test_data/ecoli_textbook.mat'], 'model'); +try + oldSolver=getpref('RAVEN','solver'); +catch +end +global CBT_LP_SOLVER +global CBT_MILP_SOLVER +CBT_LP_SOLVER = 'glpk'; +CBT_MILP_SOLVER = 'glpk'; +setRavenSolver('cobra'); + +try + % Try all three types of flux minimization + evalc('sol=solveLP(model,3);'); + evalc('sol=solveLP(model,1);'); + evalc('sol=solveLP(model,0);'); +catch + try + setRavenSolver(oldSolver); + catch + rmpref('RAVEN','solver'); + end + error('Solver not working') +end +try + setRavenSolver(oldSolver); +catch + rmpref('RAVEN','solver'); +end + +load([sourceDir,'/test_data/solverTestOutput.mat'], 'solCobra'); +%Check that the actual model is the same as the expected model +verifyEqual(testCase,sol,solCobra,'AbsTol',1e-5) +end diff --git a/testing/unit_tests/test_data/importExportResults.mat b/testing/unit_tests/test_data/importExportResults.mat new file mode 100644 index 00000000..0674972e Binary files /dev/null and b/testing/unit_tests/test_data/importExportResults.mat differ diff --git a/testing/unit_tests/test_data/solverTestOutput.mat b/testing/unit_tests/test_data/solverTestOutput.mat new file mode 100644 index 00000000..f7f5ab6e Binary files /dev/null and b/testing/unit_tests/test_data/solverTestOutput.mat differ