diff --git a/.gitattributes b/.gitattributes index 3e0ca4ab..7f4d5667 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10,3 +10,4 @@ mafft binary .gitattributes export-ignore .gitignore export-ignore .github export-ignore +*.mat filter=lfs diff=lfs merge=lfs -text diff --git a/INIT/runINIT.m b/INIT/runINIT.m index ca064f50..f20fd586 100644 --- a/INIT/runINIT.m +++ b/INIT/runINIT.m @@ -1,4 +1,4 @@ -function [outModel, deletedRxns, metProduction, fValue]=runINIT(model,rxnScores,presentMets,essentialRxns,prodWeight,allowExcretion,noRevLoops) +function [outModel, deletedRxns, metProduction, fValue]=runINIT(model,rxnScores,presentMets,essentialRxns,prodWeight,allowExcretion,noRevLoops,params) % runINIT % Generates a model using the INIT algorithm, based on proteomics and/or % transcriptomics and/or metabolomics and/or metabolic tasks. This is the @@ -38,6 +38,7 @@ % problem significantly more computationally intensive to % solve (two more integer constraints per reversible reaction) % (optional, default false) +% params parameter structure for use by optimizeProb % % outModel the resulting model structure % deletedRxns reactions which were deleted by the algorithm diff --git a/core/FSEOF.m b/core/FSEOF.m index 585abf1f..e60740ce 100755 --- a/core/FSEOF.m +++ b/core/FSEOF.m @@ -119,7 +119,12 @@ A2=char(model.rxns(num)); %enzyme ID A3=char(model.rxnNames(num)); %enzyme Name if isfield(model,'subSystems') && ~isempty(model.subSystems{num}); - A4=char(strjoin(model.subSystems{num,1},';')); %Subsystems + if ~any(cellfun(@(x) iscell(x), model.subSystems)); + subSys = cellfun(@(x) {x}, model.subSystems, 'uni', 0); + else + subSys = model.subSystems; + end + A4=char(strjoin(subSys{num},';')); %Subsystems else A4=''; end diff --git a/core/addExchangeRxns.m b/core/addExchangeRxns.m index 31df9b80..831e888b 100755 --- a/core/addExchangeRxns.m +++ b/core/addExchangeRxns.m @@ -63,8 +63,8 @@ end if isfield(model,'subSystems') fillerSub = filler; - if iscell(model.subSystems(1,1)) - fillerSub = repmat({fillerSub},numel(J),1); + if any(cellfun(@(x) iscell(x), model.subSystems)) + fillerSub(:)={{''}}; end model.subSystems=[model.subSystems;fillerSub]; end diff --git a/core/addRxns.m b/core/addRxns.m index f23222e1..3ce890c6 100755 --- a/core/addRxns.m +++ b/core/addRxns.m @@ -227,10 +227,12 @@ nOldRxns=numel(model.rxns); filler=cell(nRxns,1); filler(:)={''}; -cellfiller=cellfun(@(x) cell(0,0),filler,'UniformOutput',false); +cellfiller=cell(nRxns,1); +cellfiller(:)={{''}}; largeFiller=cell(nOldRxns,1); largeFiller(:)={''}; -celllargefiller=cellfun(@(x) cell(0,0),largeFiller,'UniformOutput',false); +largeCellFiller=cell(nOldRxns,1); +largeCellFiller(:)={{''}}; %***Add everything to the model except for the equations. if numel(rxnsToAdd.equations)~=nRxns @@ -350,24 +352,45 @@ end if isfield(rxnsToAdd,'subSystems') - if numel(rxnsToAdd.subSystems)~=nRxns - EM='rxnsToAdd.subSystems must have the same number of elements as rxnsToAdd.rxns'; - dispEM(EM); + % Has to be cell array + if ischar(rxnsToAdd.subSystems) + rxnsToAdd.subSystems = {rxnsToAdd.subSystems}; + end + % If all nested cells are 1x1, then unnest + if all(cellfun(@(x) iscell(x) && isscalar(x), rxnsToAdd.subSystems)) + rxnsToAdd.subSystems = transpose([rxnsToAdd.subSystems{:}]); end - for i=1:numel(rxnsToAdd.subSystems) - if ischar(rxnsToAdd.subSystems{i}) - rxnsToAdd.subSystems{i}=rxnsToAdd.subSystems(i); + % Cell array should now be as simple as possible. Check if it is nested + subSysRxnsNested = any(cellfun(@(x) iscell(x), rxnsToAdd.subSystems)); + if isfield(newModel,'subSystems') + subSysModelNested = any(cellfun(@(x) iscell(x), newModel.subSystems)); + else + subSysModelNested = subSysRxnsNested; + if subSysRxnsNested + newModel.subSystems=largeCellFiller; + else + newModel.subSystems=largeFiller; end end - %Fill with standard if it doesn't exist - if ~isfield(newModel,'subSystems') - newModel.subSystems=celllargefiller; + if subSysRxnsNested && ~subSysModelNested + % Make all existing subSystems nested + newModel.subSystems = cellfun(@(x) {x}, newModel.subSystems, 'uni', 0); + elseif ~subSysRxnsNested && subSysModelNested + rxnsToAdd.subSystems = cellfun(@(x) {x}, rxnsToAdd.subSystems, 'uni', 0); + end + if numel(rxnsToAdd.subSystems)~=nRxns + EM='rxnsToAdd.subSystems must have the same number of elements as rxnsToAdd.rxns'; + dispEM(EM); end newModel.subSystems=[newModel.subSystems;rxnsToAdd.subSystems(:)]; else - %Fill with standard if it doesn't exist + %Fill with standard if it does not exist if isfield(newModel,'subSystems') - newModel.subSystems=[newModel.subSystems;cellfiller]; + if any(cellfun(@(x) iscell(x), newModel.subSystems)) + newModel.subSystems=[newModel.subSystems;cellfiller]; + else + newModel.subSystems=[newModel.subSystems;filler]; + end end end if isfield(rxnsToAdd,'rxnMiriams') diff --git a/core/addTransport.m b/core/addTransport.m index 160f9fd2..4b88f022 100755 --- a/core/addTransport.m +++ b/core/addTransport.m @@ -134,11 +134,15 @@ model.eccodes=[model.eccodes;filler]; end if isfield(model,'subSystems') - ssFiller=filler; + isNested = any(cellfun(@(x) iscell(x), model.subSystems)); + ssFiller = filler; if isRev==1 - ssFiller(:)={{['Transport between ' fromComp ' and ' toComps{i}]}}; + ssFiller(:) = {['Transport between ' fromComp ' and ' toComps{i}]}; else - ssFiller(:)={{['Transport from ' fromComp ' to ' toComps{i}]}}; + ssFiller(:) = {['Transport from ' fromComp ' to ' toComps{i}]}; + end + if isNested + ssFiller = cellfun(@(x) {x}, ssFiller, 'uni', 0); end model.subSystems=[model.subSystems;ssFiller]; end diff --git a/core/checkModelStruct.m b/core/checkModelStruct.m index 3fb1e15f..eb9f8e6d 100755 --- a/core/checkModelStruct.m +++ b/core/checkModelStruct.m @@ -175,11 +175,11 @@ function checkModelStruct(model,throwErrors,trimWarnings) end end if isfield(model,'subSystems') - for i=1:numel(model.subSystems) - if ~iscell(model.subSystems{i,1}) - EM='The "subSystems" field must be a cell array'; + isNested = any(cellfun(@(x) iscell(x), model.subSystems)); + isCellStr = any(cellfun(@(x) ischar(x), model.subSystems)); + if ~xor(isNested,isCellStr) + EM='The "subSystems" field must be a cell array of chars, *or* a cell array of cell arrays of chars'; dispEM(EM,throwErrors); - end end end if isfield(model,'eccodes') diff --git a/core/compareMultipleModels.m b/core/compareMultipleModels.m index bb34169f..596d0957 100755 --- a/core/compareMultipleModels.m +++ b/core/compareMultipleModels.m @@ -92,16 +92,6 @@ fprintf('*** Done \n\n') -%% Flatten models' subSystems field -% Convert from cell array of cells to cell array of strings -% NOTE: this function currently only recognizes one subSystem per reaction; -% additional subSystems will be ignored! -for i = 1:numel(models) - cells = cellfun(@iscell,models{i}.subSystems); - models{i}.subSystems(cells) = cellfun(@(s) s{1}, models{i}.subSystems(cells), 'UniformOutput', false); -end - - %% Compare models structure & function based on high-dimensional methods % Compare number of reactions in each subsystem in each model using a heatmap field = 'subSystems'; @@ -110,6 +100,16 @@ fprintf('\nWARNING: At least one model does not contain the field "subSystems". \n') fprintf(' Skipping subsystem comparison. \n\n') else + %% Flatten model subSystems field + % Convert from cell array of cells to cell array of strings + % NOTE: this function currently only recognizes one subSystem per reaction; + % additional subSystems will be ignored! + for i = 1:numel(models) + if any(cellfun(@(x) iscell(x), models{i}.subSystems)); + cells = cellfun(@iscell,models{i}.subSystems); + models{i}.subSystems(cells) = cellfun(@(s) s{1}, models{i}.subSystems(cells), 'UniformOutput', false); + end + end [id,compMat] = compareModelField(models,field); compStruct.subsystems.ID = id; compStruct.subsystems.matrix = compMat; diff --git a/core/copyToComps.m b/core/copyToComps.m index a285e650..042b4c0b 100755 --- a/core/copyToComps.m +++ b/core/copyToComps.m @@ -25,24 +25,26 @@ % % Usage: model=copyToComps(model,toComps,rxns,deleteOriginal,compNames,compOutside) -if nargin<3 - rxns=model.rxns; -elseif ~islogical(rxns) && ~isnumeric(rxns) - rxns=convertCharArray(rxns); +arguments + model (1,1) struct + toComps {emptyOrTextOrCellOfText} + rxns = model.rxns + deleteOriginal {emptyOrLogicalScalar} = false + compNames {emptyOrTextOrCellOfText} = toComps + compOutside {emptyOrTextOrCellOfText} = ''; end -if nargin<4 - deleteOriginal=false; + +if nargin >= 3 && ~islogical(rxns) && ~isnumeric(rxns) + rxns = convertCharArray(rxns); end -if nargin<5 - compNames=toComps; -else +if nargin >= 5 compNames=convertCharArray(compNames); end -if nargin<6 - compOutside=cell(numel(toComps),1); - compOutside(:)={''}; -else +if nargin >= 6 compOutside=convertCharArray(compOutside); + if length(compOutside) ~= length(compNames) + error('compOutside and compNames should be of equal size.'); + end end originalID=model.id; @@ -79,15 +81,20 @@ modelToAdd.compMiriams=modelToAdd.compMiriams(J); end modelToAdd.metComps=ones(numel(modelToAdd.mets),1); - + if isfield(modelToAdd,'metFrom') + modelToAdd = rmfield(modelToAdd,'metFrom'); + end + if isfield(modelToAdd,'rxnFrom') + modelToAdd = rmfield(modelToAdd,'rxnFrom'); + end + if isfield(modelToAdd,'geneFrom') + modelToAdd = rmfield(modelToAdd,'geneFrom'); + end + %Merge the models - model=mergeModels({model;modelToAdd},'metNames'); + model=mergeModels({model;modelToAdd},'metNames',[],true); 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/findRAVENroot.m b/core/findRAVENroot.m index 10c28ce4..17e4b878 100755 --- a/core/findRAVENroot.m +++ b/core/findRAVENroot.m @@ -1,23 +1,27 @@ function [ravenPath, prevDir] = findRAVENroot() % findRAVENroot -% Finds the root of the RAVEN directory, by searching for the path to +% Finds the root of the RAVEN directory, first by 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(); -ravenPath = ST(strcmp({ST.name},'findRAVENroot')).file; -rootFound = 0; -while rootFound == 0 - isRoot = isfile(fullfile(ravenPath,'RAVEN2.png')); - if isRoot - 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.') +if ispref('RAVEN','ravenPath') + ravenPath = getpref('RAVEN','ravenPath'); +else + ravenPath = ST(strcmp({ST.name},'findRAVENroot')).file; + rootFound = 0; + while rootFound == 0 + isRoot = isfile(fullfile(ravenPath,'RAVEN2.png')); + if isRoot + 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 end \ No newline at end of file diff --git a/core/fitTasks.m b/core/fitTasks.m index 9963f9e7..f823d459 100755 --- a/core/fitTasks.m +++ b/core/fitTasks.m @@ -34,7 +34,7 @@ % the result. % % Usage: [outModel, addedRxns]=fitTasks(model,refModel,inputFile,printOutput,... -% rxnScores,taskStructure,params) +% rxnScores,taskStructure) if nargin<4 printOutput=true; @@ -48,9 +48,6 @@ if nargin<6 taskStructure=[]; end -if nargin<7 - params=[]; -end if isempty(taskStructure) && ~isfile(inputFile) error('Task file %s cannot be found',string(inputFile)); @@ -266,9 +263,9 @@ %Only do gap-filling if it cannot be solved failed=false; try - [~, ~, newRxns, newModel, exitFlag]=fillGaps(tModel,refModel,false,true,supressWarnings,rxnScores,params); + [~, ~, newRxns, newModel, exitFlag]=fillGaps(tModel,refModel,false,true,supressWarnings,rxnScores); if exitFlag==-2 - EM=['"[' taskStructure(i).id '] ' taskStructure(i).description '" was aborted before reaching optimality. Consider increasing params.maxTime\n']; + EM=['"[' taskStructure(i).id '] ' taskStructure(i).description '" was aborted before reaching optimality.\n']; dispEM(EM,false); end catch diff --git a/core/mergeModels.m b/core/mergeModels.m index 29faff96..d7ef3669 100755 --- a/core/mergeModels.m +++ b/core/mergeModels.m @@ -1,37 +1,76 @@ -function model=mergeModels(models,metParam,supressWarnings) +function model=mergeModels(models,metParam,supressWarnings,copyToComps) % mergeModels % 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. % +% Input: % models a cell array with model structures -% metParam string specifying whether to refer to metabolite name -% (metNames) or ID (mets) for matching (default, metNames) -% supressWarnings true if warnings should be supressed (optional, default -% false) +% metParam string metabolite name ('metNames') or ID ('mets') are +% used for matching (optional, default 'metNames') +% supressWarnings logical whether warnings should be supressed (optional, +% default false) +% copyToComps logical whether mergeModels is run via copyToComps +% (optional, default false) % -% model a model structure with the merged model. Follows the structure -% of normal models but also has 'rxnFrom/metFrom/geneFrom' fields -% to indicate from which model each reaction/metabolite/gene was -% taken +% Output: +% model a model structure with the merged model. Follows the +% structure of normal models but also has 'rxnFrom/ +% metFrom/geneFrom' fields to indicate from which model +% each reaction/metabolite/gene was taken. If the model +% already has 'rxnFrom/metFrom/geneFrom' fields, then +% these fields are not modified. % % Usage: model=mergeModels(models) +arguments + models; + metParam {emptyOrTextScalar} = "metNames" + supressWarnings {emptyOrLogicalScalar} = false + copyToComps {emptyOrLogicalScalar} = false +end + +metParam = char(metParam); + %Just return the model if numel(models)<=1 model=models{1}; return; end -if nargin<2 - metParam='metNames'; -else - metParam=char(metParam); -end +hasMetFrom = cellfun(@(s) isfield(s,'metFrom'), models); +hasGeneFrom = cellfun(@(s) isfield(s,'geneFrom'), models); +hasRxnFrom = cellfun(@(s) isfield(s,'rxnFrom'), models); -if nargin<3 - supressWarnings=false; +for i = 1:numel(models) + if copyToComps + if hasMetFrom(1) + models{2}.metFrom = repmat({''},numel(models{i}.mets),1); + end + elseif ~any(hasMetFrom) + models{i}.metFrom = repmat({models{i}.id},numel(models{i}.mets),1); + elseif ~hasMetFrom(i) + models{i}.metFrom = repmat({''},numel(models{i}.mets),1); + end + if copyToComps + if hasRxnFrom(1) + models{2}.rxnFrom = repmat({''},numel(models{i}.rxns),1); + end + elseif ~any(hasRxnFrom) + models{i}.rxnFrom = repmat({models{i}.id},numel(models{i}.rxns),1); + elseif ~hasRxnFrom(i) + models{i}.rxnFrom = repmat({''},numel(models{i}.rxns),1); + end + if copyToComps + if hasGeneFrom(1) + models{2}.geneFrom = repmat({''},numel(models{i}.genes),1); + end + elseif ~any(hasGeneFrom) && any(cellfun(@(s) isfield(s,'genes'), models)) + models{i}.geneFrom = repmat({models{i}.id},numel(models{i}.genes),1); + elseif ~hasGeneFrom(i) + models{i}.geneFrom = repmat({''},numel(models{i}.genes),1); + end end %Add new functionality in the order specified in models @@ -39,19 +78,15 @@ model.id='MERGED'; model.name=''; -model.rxnFrom=cell(numel(models{1}.rxns),1); -model.rxnFrom(:)={models{1}.id}; -model.metFrom=cell(numel(models{1}.mets),1); -model.metFrom(:)={models{1}.id}; -if isfield(models{1},'genes') - model.geneFrom=cell(numel(models{1}.genes),1); - model.geneFrom(:)={models{1}.id}; -end - if isfield(model,'equations') model=rmfield(model,'equations'); end +for i=1:numel(models) + if isfield(models{i},'subSystems') + models{i}.subSystems = cellfun(@(x) {x}, models{i}.subSystems, 'uni', 0); + end +end for i=2:numel(models) %Add the model id to the rxn id id it already exists in the model (id %have to be unique) This is because it makes a '[]' string if no new @@ -78,15 +113,15 @@ end %Add all static stuff - rxnFrom=cell(numel(models{i}.rxns),1); - rxnFrom(:)={models{i}.id}; - model.rxnFrom=[model.rxnFrom;rxnFrom]; - model.rxns=[model.rxns;models{i}.rxns]; - model.rxnNames=[model.rxnNames;models{i}.rxnNames]; - model.lb=[model.lb;models{i}.lb]; - model.ub=[model.ub;models{i}.ub]; - model.c=[model.c;models{i}.c]; - model.rev=[model.rev;models{i}.rev]; + if any(hasRxnFrom) || (~copyToComps && ~any(hasRxnFrom)) + model.rxnFrom = [model.rxnFrom; models{i}.rxnFrom]; + end + model.rxns = [model.rxns; models{i}.rxns]; + model.rxnNames = [model.rxnNames; models{i}.rxnNames]; + model.lb = [model.lb; models{i}.lb]; + model.ub = [model.ub; models{i}.ub]; + model.c = [model.c; models{i}.c]; + model.rev = [model.rev; models{i}.rev]; if isfield(models{i},'subSystems') if isfield(model,'subSystems') @@ -253,7 +288,6 @@ if strcmpi(metParam,'mets') %Get the new metabolites from matching the models. Metabolites are matched by metabolite ID (model.mets). - oldMetComps=model.comps(model.metComps); oldMets=model.mets; if ~isempty(models{i}.mets) @@ -287,12 +321,12 @@ end %Add static info on the metabolites - metFrom=cell(numel(metsToAdd),1); - metFrom(:)={models{i}.id}; - model.metFrom=[model.metFrom;metFrom]; - model.mets=[model.mets;models{i}.mets(metsToAdd)]; - model.metNames=[model.metNames;models{i}.metNames(metsToAdd)]; - model.b=[model.b;zeros(numel(metsToAdd),size(model.b,2))]; + if any(hasMetFrom) + model.metFrom = [model.metFrom; models{i}.metFrom(metsToAdd)]; + end + model.mets = [model.mets; models{i}.mets(metsToAdd)]; + model.metNames = [model.metNames; models{i}.metNames(metsToAdd)]; + model.b = [model.b; zeros(numel(metsToAdd),size(model.b,2))]; if isfield(model,'unconstrained') if isfield(models{i},'unconstrained') @@ -481,13 +515,13 @@ if isfield(models{i},'genes') if ~isfield(model,'genes') %If there was no gene info before - model.genes=models{i}.genes; - model.rxnGeneMat=[sparse(numel(model.rxns),numel(models{i}.genes));models{i}.rxnGeneMat]; - emptyGene=cell(numel(model.rxns),1); - emptyGene(:)={''}; - model.grRules=[emptyGene;models{i}.grRules]; - model.geneFrom=cell(numel(models{i}.genes),1); - model.geneFrom(:)={models{i}.id}; + model.genes = models{i}.genes; + model.rxnGeneMat = [sparse(numel(model.rxns),numel(models{i}.genes));models{i}.rxnGeneMat]; + emptyGene = repmat({''},numel(model.rxns),1); + model.grRules = [emptyGene;models{i}.grRules]; + if any(hasGeneFrom) + model.geneFrom = models{i}.geneFrom; + end if isfield(models{i},'geneShortNames') model.geneShortNames=models{i}.geneShortNames; @@ -513,11 +547,9 @@ %Only add extra gene info on new genes. This might not be %correct and should be changed later... if ~isempty(genesToAdd) - model.genes=[model.genes;models{i}.genes(genesToAdd)]; - emptyGene=cell(numel(genesToAdd),1); - emptyGene(:)={models{i}.id}; - model.geneFrom=[model.geneFrom;emptyGene]; - model.rxnGeneMat=[model.rxnGeneMat sparse(size(model.rxnGeneMat,1),numel(genesToAdd))]; + model.genes = [model.genes; models{i}.genes(genesToAdd)]; + model.geneFrom = [model.geneFrom; models{i}.geneFrom(genesToAdd)]; + model.rxnGeneMat = [model.rxnGeneMat sparse(size(model.rxnGeneMat,1),numel(genesToAdd))]; if isfield(models{i},'geneShortNames') if isfield(model,'geneShortNames') @@ -585,9 +617,9 @@ end %Remap the genes from the new model. The same thing as with - %mets; this is a wasteful way to do it but I don't care right + %mets; this is a wasteful way to do it but I do not care right %now - [a, b]=ismember(models{i}.genes,model.genes); + a = ismember(models{i}.genes,model.genes); %Just a check if ~all(a) @@ -609,4 +641,10 @@ [grRules,rxnGeneMat] = standardizeGrRules(model,true); model.grRules = grRules; model.rxnGeneMat = rxnGeneMat; +%Flatten subSystems if possible +if isfield(model,'subSystems') + if all(cellfun(@(x) iscell(x) && isscalar(x), model.subSystems)) + model.subSystems = transpose([model.subSystems{:}]); + end +end end diff --git a/core/parseTaskList.m b/core/parseTaskList.m index 614710c5..e6cafca0 100755 --- a/core/parseTaskList.m +++ b/core/parseTaskList.m @@ -2,10 +2,11 @@ % parseTaskList % Parses a task list file. % -% inputFile a task list in Excel format. The file must contain a -% sheet named TASKS, which in turn may contain the -% following column headers (note, all rows starting with -% a non-empty cell are removed. The first row after that +% inputFile a task list in either Excel (*.xlsx, with a sheet named +% TASKS with all relevant content) or tab-delimited +% (*.txt) format. The file may contain the following +% column headers (note, all rows starting with a +% non-empty cell are removed. The first row after that % is considered the headers): % ID % the only required header. Each task must have a diff --git a/core/predictLocalization.m b/core/predictLocalization.m index 2bfff833..1908caa6 100755 --- a/core/predictLocalization.m +++ b/core/predictLocalization.m @@ -621,7 +621,7 @@ outModel.compNames(2)=GSS.compartments(1); end end -outModel.compNames=[outModel.compNames;GSS.compartments(2:end)']; +outModel.compNames=[outModel.compNames;GSS.compartments(2:end)]; %Ugly little loop for i=1:numel(GSS.compartments)-1 @@ -726,7 +726,11 @@ outModel.rxnMiriams=[outModel.rxnMiriams;{[]}]; end if isfield(outModel,'subSystems') - outModel.subSystems=[outModel.subSystems;{{'Inferred transport reactions'}}]; + if any(cellfun(@(x) iscell(x), outModel.subSystems)) + outModel.subSystems=[outModel.subSystems;{{'Inferred transport reactions'}}]; + else + outModel.subSystems=[outModel.subSystems;{'Inferred transport reactions'}]; + end end if isfield(outModel,'eccodes') outModel.eccodes=[outModel.eccodes;{''}]; diff --git a/core/setParam.m b/core/setParam.m index 734853b7..70705f3f 100755 --- a/core/setParam.m +++ b/core/setParam.m @@ -68,7 +68,7 @@ params(~Lia)=[]; indexes(~Lia)=[]; paramType(~Lia)=[]; - dispEM('Reactions not present in model, will be ignored:',false,rxnLise(~Lia)); + dispEM('Reactions not present in model, will be ignored:',false,rxnList(~Lia)); end %Change the parameters diff --git a/core/sortModel.m b/core/sortModel.m index 8d329fbc..7dc00d7e 100755 --- a/core/sortModel.m +++ b/core/sortModel.m @@ -65,6 +65,9 @@ subsystemsUnique=''; subsystemsConcatenated=''; for i=1:numel(model.subSystems) + if ~iscell(model.subSystems{i}) + model.subSystems{i} = {model.subSystems{i}}; + end subsystemsConcatenated{i,1}=strjoin(model.subSystems{i,1},';'); if ~isempty(model.subSystems{i,1}) for j=1:numel(model.subSystems{i,1}) diff --git a/doc/INIT/getINITModel.html b/doc/INIT/getINITModel.html index 739882c2..d0913510 100644 --- a/doc/INIT/getINITModel.html +++ b/doc/INIT/getINITModel.html @@ -133,7 +133,7 @@

DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

This function calls: +
  • runINIT runINIT
  • This function is called by: @@ -446,7 +446,7 @@

    SOURCE CODE ^%carry flux in one direction. Runs without the constraints on reversibility 0301 %and with all output allowed. This is to reduce the complexity of the 0302 %problem. -0303 [~, deletedRxnsInINIT, metProduction]=runINIT(simplifyModel(cModel),rxnScores,metabolomicsData,essentialRxnsForTasks,0,true,false,params); +0303 [~, deletedRxnsInINIT, metProduction]=runINIT(simplifyModel(cModel),rxnScores,metabolomicsData,essentialRxnsForTasks,0,true,false,params); 0304 initModel=removeReactions(cModel,deletedRxnsInINIT,true,true); 0305 if printReport==true 0306 printScores(initModel,'INIT model statistics',hpaData,arrayData,tissue,celltype); diff --git a/doc/INIT/runINIT.html b/doc/INIT/runINIT.html index e4003c24..15cbb20d 100644 --- a/doc/INIT/runINIT.html +++ b/doc/INIT/runINIT.html @@ -24,7 +24,7 @@

    PURPOSE ^runINIT

    SYNOPSIS ^

    -
    function [outModel, deletedRxns, metProduction, fValue]=runINIT(model,rxnScores,presentMets,essentialRxns,prodWeight,allowExcretion,noRevLoops)
    +
    function [outModel, deletedRxns, metProduction, fValue]=runINIT(model,rxnScores,presentMets,essentialRxns,prodWeight,allowExcretion,noRevLoops,params)

    DESCRIPTION ^

     runINIT
    @@ -66,6 +66,7 @@ 

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

    -
    0001 function [outModel, deletedRxns, metProduction, fValue]=runINIT(model,rxnScores,presentMets,essentialRxns,prodWeight,allowExcretion,noRevLoops)
    +
    0001 function [outModel, deletedRxns, metProduction, fValue]=runINIT(model,rxnScores,presentMets,essentialRxns,prodWeight,allowExcretion,noRevLoops,params)
     0002 % runINIT
     0003 %    Generates a model using the INIT algorithm, based on proteomics and/or
     0004 %   transcriptomics and/or metabolomics and/or metabolic tasks. This is the
    @@ -141,303 +142,304 @@ 

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

    +0041 % params parameter structure for use by optimizeProb +0042 % +0043 % outModel the resulting model structure +0044 % deletedRxns reactions which were deleted by the algorithm +0045 % metProduction array that indicates which of the +0046 % metabolites in presentMets that could be +0047 % produced +0048 % -2: metabolite name not found in model +0049 % -1: metabolite found, but it could not be produced +0050 % 1: metabolite could be produced +0051 % fValue objective value (sum of (the negative of) +0052 % reaction scores for the included reactions and +0053 % prodWeight*number of produced metabolites) +0054 % +0055 % This function is the actual implementation of the algorithm. See +0056 % getINITModel for a higher-level function for model reconstruction. See +0057 % PLoS Comput Biol. 2012;8(5):e1002518 for details regarding the +0058 % implementation. +0059 % +0060 % Usage: [outModel deletedRxns metProduction fValue]=runINIT(model,... +0061 % rxnScores,presentMets,essentialRxns,prodWeight,allowExcretion,... +0062 % noRevLoops,params) +0063 +0064 if nargin<2 +0065 rxnScores=zeros(numel(model.rxns),1); +0066 end +0067 if isempty(rxnScores) +0068 rxnScores=zeros(numel(model.rxns),1); +0069 end +0070 if nargin<3 || isempty(presentMets) +0071 presentMets={}; +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 nargin<5 || isempty(prodWeight) +0081 prodWeight=0.5; +0082 end +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 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(1,size(prob.a,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 940f3278..af3e7a45 100644 --- a/doc/core/FSEOF.html +++ b/doc/core/FSEOF.html @@ -191,29 +191,34 @@

    SOURCE CODE ^%enzyme ID 0120 A3=char(model.rxnNames(num)); %enzyme Name 0121 if isfield(model,'subSystems') && ~isempty(model.subSystems{num}); -0122 A4=char(strjoin(model.subSystems{num,1},';')); %Subsystems -0123 else -0124 A4=''; -0125 end -0126 A5=num2str(model.rev(num)*rxnDirection(num,1)); %reaction Dirction -0127 A6=char(model.grRules(num)); %Gr Rule -0128 if output == 1 %Output to a file -0129 fprintf(fid,formatSpec,A0,A1,A2,A3,A4,A5,A6); -0130 else %Output screen -0131 fprintf(formatSpec,A0,A1,A2,A3,A4,A5,A6); -0132 end -0133 end -0134 end -0135 -0136 if output == 1 %Output to a file -0137 fclose(fid); -0138 end -0139 -0140 if nargout == 1 -0141 targets.logical=logical(fseof.target); -0142 targets.slope=abs(fseof.results(:,iterations)-fseof.results(:,1))/abs(targetMax-targetMax/iterations); %Slope calculation +0122 if ~any(cellfun(@(x) iscell(x), model.subSystems)); +0123 subSys = cellfun(@(x) {x}, model.subSystems, 'uni', 0); +0124 else +0125 subSys = model.subSystems; +0126 end +0127 A4=char(strjoin(subSys{num},';')); %Subsystems +0128 else +0129 A4=''; +0130 end +0131 A5=num2str(model.rev(num)*rxnDirection(num,1)); %reaction Dirction +0132 A6=char(model.grRules(num)); %Gr Rule +0133 if output == 1 %Output to a file +0134 fprintf(fid,formatSpec,A0,A1,A2,A3,A4,A5,A6); +0135 else %Output screen +0136 fprintf(formatSpec,A0,A1,A2,A3,A4,A5,A6); +0137 end +0138 end +0139 end +0140 +0141 if output == 1 %Output to a file +0142 fclose(fid); 0143 end -0144 end

    +0144 +0145 if nargout == 1 +0146 targets.logical=logical(fseof.target); +0147 targets.slope=abs(fseof.results(:,iterations)-fseof.results(:,1))/abs(targetMax-targetMax/iterations); %Slope calculation +0148 end +0149 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/addExchangeRxns.html b/doc/core/addExchangeRxns.html index 77045cdd..c1bdf99f 100644 --- a/doc/core/addExchangeRxns.html +++ b/doc/core/addExchangeRxns.html @@ -127,8 +127,8 @@

    SOURCE CODE ^end 0064 if isfield(model,'subSystems') 0065 fillerSub = filler; -0066 if iscell(model.subSystems(1,1)) -0067 fillerSub = repmat({fillerSub},numel(J),1); +0066 if any(cellfun(@(x) iscell(x), model.subSystems)) +0067 fillerSub(:)={{''}}; 0068 end 0069 model.subSystems=[model.subSystems;fillerSub]; 0070 end diff --git a/doc/core/addRxns.html b/doc/core/addRxns.html index ffdcf6e6..5a26576f 100644 --- a/doc/core/addRxns.html +++ b/doc/core/addRxns.html @@ -371,453 +371,476 @@

    SOURCE CODE ^''}; -0230 cellfiller=cellfun(@(x) cell(0,0),filler,'UniformOutput',false); -0231 largeFiller=cell(nOldRxns,1); -0232 largeFiller(:)={''}; -0233 celllargefiller=cellfun(@(x) cell(0,0),largeFiller,'UniformOutput',false); -0234 -0235 %***Add everything to the model except for the equations. -0236 if numel(rxnsToAdd.equations)~=nRxns -0237 EM='rxnsToAdd.equations must have the same number of elements as rxnsToAdd.rxns'; -0238 dispEM(EM); -0239 end -0240 -0241 %Parse the equations. This is done at this early stage since I need the -0242 %reversibility info -0243 [S, mets, badRxns, reversible]=constructS(rxnsToAdd.equations); -0244 EM='The following equations have one or more metabolites both as substrate and product. Only the net equations will be added:'; -0245 dispEM(EM,false,rxnsToAdd.rxns(badRxns)); -0246 -0247 newModel.rev=[newModel.rev;reversible]; -0248 newModel.rxns=[newModel.rxns;rxnsToAdd.rxns(:)]; -0249 -0250 if isfield(rxnsToAdd,'rxnNames') -0251 rxnsToAdd.rxnNames=convertCharArray(rxnsToAdd.rxnNames); -0252 if numel(rxnsToAdd.rxnNames)~=nRxns -0253 EM='rxnsToAdd.rxnNames must have the same number of elements as rxnsToAdd.rxns'; -0254 dispEM(EM); -0255 end -0256 %Fill with standard if it doesn't exist -0257 if ~isfield(newModel,'rxnNames') -0258 newModel.rxnNames=largeFiller; -0259 end -0260 newModel.rxnNames=[newModel.rxnNames;rxnsToAdd.rxnNames(:)]; -0261 else -0262 %Fill with standard if it doesn't exist -0263 if isfield(newModel,'rxnNames') -0264 newModel.rxnNames=[newModel.rxnNames;filler]; -0265 end -0266 end -0267 -0268 if isfield(newModel,'annotation') & isfield(newModel.annotation,'defaultLB') -0269 newLb=newModel.annotation.defaultLB; -0270 else -0271 newLb=-inf; -0272 end -0273 -0274 if isfield(rxnsToAdd,'lb') -0275 if numel(rxnsToAdd.lb)~=nRxns -0276 EM='rxnsToAdd.lb must have the same number of elements as rxnsToAdd.rxns'; -0277 dispEM(EM); -0278 end -0279 %Fill with standard if it doesn't exist -0280 if ~isfield(newModel,'lb') -0281 newModel.lb=zeros(nOldRxns,1); -0282 newModel.lb(newModel.rev~=0)=newLb; -0283 end -0284 newModel.lb=[newModel.lb;rxnsToAdd.lb(:)]; -0285 else -0286 %Fill with standard if it doesn't exist -0287 if isfield(newModel,'lb') -0288 I=zeros(nRxns,1); -0289 I(reversible~=0)=newLb; -0290 newModel.lb=[newModel.lb;I]; -0291 end -0292 end -0293 -0294 if isfield(newModel,'annotation') & isfield(newModel.annotation,'defaultUB') -0295 newUb=newModel.annotation.defaultUB; -0296 else -0297 newUb=inf; -0298 end -0299 -0300 if isfield(rxnsToAdd,'ub') -0301 if numel(rxnsToAdd.ub)~=nRxns -0302 EM='rxnsToAdd.ub must have the same number of elements as rxnsToAdd.rxns'; -0303 dispEM(EM); -0304 end -0305 %Fill with standard if it doesn't exist -0306 if ~isfield(newModel,'ub') -0307 newModel.ub=repmat(newUb,nOldRxns,1); -0308 end -0309 newModel.ub=[newModel.ub;rxnsToAdd.ub(:)]; -0310 else -0311 %Fill with standard if it doesn't exist -0312 if isfield(newModel,'ub') -0313 newModel.ub=[newModel.ub;repmat(newUb,nRxns,1)]; -0314 end -0315 end -0316 -0317 if isfield(rxnsToAdd,'c') -0318 if numel(rxnsToAdd.c)~=nRxns -0319 EM='rxnsToAdd.c must have the same number of elements as rxnsToAdd.rxns'; -0320 dispEM(EM); -0321 end -0322 %Fill with standard if it doesn't exist -0323 if ~isfield(newModel,'c') -0324 newModel.c=zeros(nOldRxns,1); -0325 end -0326 newModel.c=[newModel.c;rxnsToAdd.c(:)]; -0327 else -0328 %Fill with standard if it doesn't exist -0329 if isfield(newModel,'c') -0330 newModel.c=[newModel.c;zeros(nRxns,1)]; -0331 end -0332 end -0333 -0334 if isfield(rxnsToAdd,'eccodes') -0335 rxnsToAdd.eccodes=convertCharArray(rxnsToAdd.eccodes); -0336 if numel(rxnsToAdd.eccodes)~=nRxns -0337 EM='rxnsToAdd.eccodes must have the same number of elements as rxnsToAdd.rxns'; -0338 dispEM(EM); -0339 end -0340 %Fill with standard if it doesn't exist -0341 if ~isfield(newModel,'eccodes') -0342 newModel.eccodes=largeFiller; -0343 end -0344 newModel.eccodes=[newModel.eccodes;rxnsToAdd.eccodes(:)]; -0345 else -0346 %Fill with standard if it doesn't exist -0347 if isfield(newModel,'eccodes') -0348 newModel.eccodes=[newModel.eccodes;filler]; -0349 end -0350 end -0351 -0352 if isfield(rxnsToAdd,'subSystems') -0353 if numel(rxnsToAdd.subSystems)~=nRxns -0354 EM='rxnsToAdd.subSystems must have the same number of elements as rxnsToAdd.rxns'; -0355 dispEM(EM); -0356 end -0357 for i=1:numel(rxnsToAdd.subSystems) -0358 if ischar(rxnsToAdd.subSystems{i}) -0359 rxnsToAdd.subSystems{i}=rxnsToAdd.subSystems(i); -0360 end -0361 end -0362 %Fill with standard if it doesn't exist -0363 if ~isfield(newModel,'subSystems') -0364 newModel.subSystems=celllargefiller; -0365 end -0366 newModel.subSystems=[newModel.subSystems;rxnsToAdd.subSystems(:)]; -0367 else -0368 %Fill with standard if it doesn't exist -0369 if isfield(newModel,'subSystems') -0370 newModel.subSystems=[newModel.subSystems;cellfiller]; -0371 end -0372 end -0373 if isfield(rxnsToAdd,'rxnMiriams') -0374 if numel(rxnsToAdd.rxnMiriams)~=nRxns -0375 EM='rxnsToAdd.rxnMiriams must have the same number of elements as rxnsToAdd.rxns'; -0376 dispEM(EM); -0377 end -0378 %Fill with standard if it doesn't exist -0379 if ~isfield(newModel,'rxnMiriams') -0380 newModel.rxnMiriams=cell(nOldRxns,1); -0381 end -0382 newModel.rxnMiriams=[newModel.rxnMiriams;rxnsToAdd.rxnMiriams(:)]; -0383 else -0384 %Fill with standard if it doesn't exist -0385 if isfield(newModel,'rxnMiriams') -0386 newModel.rxnMiriams=[newModel.rxnMiriams;cell(nRxns,1)]; -0387 end -0388 end -0389 if isfield(rxnsToAdd,'rxnComps') -0390 if numel(rxnsToAdd.rxnComps)~=nRxns -0391 EM='rxnsToAdd.rxnComps must have the same number of elements as rxnsToAdd.rxns'; -0392 dispEM(EM); -0393 end -0394 %Fill with standard if it doesn't exist -0395 if ~isfield(newModel,'rxnComps') -0396 newModel.rxnComps=ones(nOldRxns,1); -0397 EM='Adding reactions with compartment information to a model without such information. All existing reactions will be assigned to the first compartment'; -0398 dispEM(EM,false); -0399 end -0400 newModel.rxnComps=[newModel.rxnComps;rxnsToAdd.rxnComps(:)]; -0401 else -0402 %Fill with standard if it doesn't exist -0403 if isfield(newModel,'rxnComps') -0404 newModel.rxnComps=[newModel.rxnComps;ones(nRxns,1)]; -0405 %fprintf('NOTE: The added reactions will be assigned to the first -0406 %compartment\n'); -0407 end -0408 end -0409 if isfield(rxnsToAdd,'grRules') -0410 rxnsToAdd.grRules=convertCharArray(rxnsToAdd.grRules); -0411 if numel(rxnsToAdd.grRules)~=nRxns -0412 EM='rxnsToAdd.grRules must have the same number of elements as rxnsToAdd.rxns'; -0413 dispEM(EM); -0414 end -0415 %Fill with standard if it doesn't exist -0416 if ~isfield(newModel,'grRules') -0417 newModel.grRules=largeFiller; -0418 end -0419 newModel.grRules=[newModel.grRules;rxnsToAdd.grRules(:)]; -0420 else -0421 %Fill with standard if it doesn't exist -0422 if isfield(newModel,'grRules') -0423 newModel.grRules=[newModel.grRules;filler]; -0424 end -0425 end -0426 -0427 if isfield(rxnsToAdd,'rxnFrom') -0428 rxnsToAdd.rxnFrom=convertCharArray(rxnsToAdd.rxnFrom); -0429 if numel(rxnsToAdd.rxnFrom)~=nRxns -0430 EM='rxnsToAdd.rxnFrom must have the same number of elements as rxnsToAdd.rxns'; -0431 dispEM(EM); -0432 end -0433 %Fill with standard if it doesn't exist -0434 if ~isfield(newModel,'rxnFrom') -0435 newModel.rxnFrom=largeFiller; -0436 end -0437 newModel.rxnFrom=[newModel.rxnFrom;rxnsToAdd.rxnFrom(:)]; -0438 else -0439 %Fill with standard if it doesn't exist -0440 if isfield(newModel,'rxnFrom') -0441 newModel.rxnFrom=[newModel.rxnFrom;filler]; -0442 end -0443 end -0444 -0445 if isfield(rxnsToAdd,'rxnNotes') -0446 rxnsToAdd.rxnNotes=convertCharArray(rxnsToAdd.rxnNotes); -0447 if numel(rxnsToAdd.rxnNotes)~=nRxns -0448 EM='rxnsToAdd.rxnNotes must have the same number of elements as rxnsToAdd.rxns'; -0449 dispEM(EM); -0450 end -0451 %Fill with standard if it doesn't exist -0452 if ~isfield(newModel,'rxnNotes') -0453 newModel.rxnNotes=largeFiller; -0454 end -0455 newModel.rxnNotes=[newModel.rxnNotes;rxnsToAdd.rxnNotes(:)]; -0456 else -0457 %Fill with standard if it doesn't exist -0458 if isfield(newModel,'rxnNotes') -0459 newModel.rxnNotes=[newModel.rxnNotes;filler]; -0460 end -0461 end -0462 -0463 if isfield(rxnsToAdd,'rxnReferences') -0464 rxnsToAdd.rxnReferences=convertCharArray(rxnsToAdd.rxnReferences); -0465 if numel(rxnsToAdd.rxnReferences)~=nRxns -0466 EM='rxnsToAdd.rxnReferences must have the same number of elements as rxnsToAdd.rxns'; -0467 dispEM(EM); -0468 end -0469 %Fill with standard if it doesn't exist -0470 if ~isfield(newModel,'rxnReferences') -0471 newModel.rxnReferences=largeFiller; -0472 end -0473 newModel.rxnReferences=[newModel.rxnReferences;rxnsToAdd.rxnReferences(:)]; -0474 else -0475 %Fill with standard if it doesn't exist -0476 if isfield(newModel,'rxnReferences') -0477 newModel.rxnReferences=[newModel.rxnReferences;filler]; -0478 end -0479 end -0480 -0481 if isfield(rxnsToAdd,'pwys') -0482 rxnsToAdd.pwys=convertCharArray(rxnsToAdd.pwys); -0483 if numel(rxnsToAdd.pwys)~=nRxns -0484 EM='rxnsToAdd.pwys must have the same number of elements as rxnsToAdd.rxns'; -0485 dispEM(EM); -0486 end -0487 %Fill with standard if it doesn't exist -0488 if ~isfield(newModel,'pwys') -0489 newModel.pwys=largeFiller; -0490 end -0491 newModel.pwys=[newModel.pwys;rxnsToAdd.pwys(:)]; -0492 else -0493 %Fill with standard if it doesn't exist -0494 if isfield(newModel,'pwys') -0495 newModel.pwys=[newModel.pwys;filler]; -0496 end -0497 end -0498 -0499 if isfield(rxnsToAdd,'rxnConfidenceScores') -0500 if numel(rxnsToAdd.rxnConfidenceScores)~=nRxns -0501 EM='rxnsToAdd.rxnConfidenceScores must have the same number of elements as rxnsToAdd.rxns'; -0502 dispEM(EM); -0503 end -0504 %Fill with standard if it doesn't exist -0505 if ~isfield(newModel,'rxnConfidenceScores') -0506 newModel.rxnConfidenceScores=NaN(nOldRxns,1); -0507 end -0508 newModel.rxnConfidenceScores=[newModel.rxnConfidenceScores;rxnsToAdd.rxnConfidenceScores(:)]; -0509 else +0230 cellfiller=cell(nRxns,1); +0231 cellfiller(:)={{''}}; +0232 largeFiller=cell(nOldRxns,1); +0233 largeFiller(:)={''}; +0234 largeCellFiller=cell(nOldRxns,1); +0235 largeCellFiller(:)={{''}}; +0236 +0237 %***Add everything to the model except for the equations. +0238 if numel(rxnsToAdd.equations)~=nRxns +0239 EM='rxnsToAdd.equations must have the same number of elements as rxnsToAdd.rxns'; +0240 dispEM(EM); +0241 end +0242 +0243 %Parse the equations. This is done at this early stage since I need the +0244 %reversibility info +0245 [S, mets, badRxns, reversible]=constructS(rxnsToAdd.equations); +0246 EM='The following equations have one or more metabolites both as substrate and product. Only the net equations will be added:'; +0247 dispEM(EM,false,rxnsToAdd.rxns(badRxns)); +0248 +0249 newModel.rev=[newModel.rev;reversible]; +0250 newModel.rxns=[newModel.rxns;rxnsToAdd.rxns(:)]; +0251 +0252 if isfield(rxnsToAdd,'rxnNames') +0253 rxnsToAdd.rxnNames=convertCharArray(rxnsToAdd.rxnNames); +0254 if numel(rxnsToAdd.rxnNames)~=nRxns +0255 EM='rxnsToAdd.rxnNames must have the same number of elements as rxnsToAdd.rxns'; +0256 dispEM(EM); +0257 end +0258 %Fill with standard if it doesn't exist +0259 if ~isfield(newModel,'rxnNames') +0260 newModel.rxnNames=largeFiller; +0261 end +0262 newModel.rxnNames=[newModel.rxnNames;rxnsToAdd.rxnNames(:)]; +0263 else +0264 %Fill with standard if it doesn't exist +0265 if isfield(newModel,'rxnNames') +0266 newModel.rxnNames=[newModel.rxnNames;filler]; +0267 end +0268 end +0269 +0270 if isfield(newModel,'annotation') & isfield(newModel.annotation,'defaultLB') +0271 newLb=newModel.annotation.defaultLB; +0272 else +0273 newLb=-inf; +0274 end +0275 +0276 if isfield(rxnsToAdd,'lb') +0277 if numel(rxnsToAdd.lb)~=nRxns +0278 EM='rxnsToAdd.lb must have the same number of elements as rxnsToAdd.rxns'; +0279 dispEM(EM); +0280 end +0281 %Fill with standard if it doesn't exist +0282 if ~isfield(newModel,'lb') +0283 newModel.lb=zeros(nOldRxns,1); +0284 newModel.lb(newModel.rev~=0)=newLb; +0285 end +0286 newModel.lb=[newModel.lb;rxnsToAdd.lb(:)]; +0287 else +0288 %Fill with standard if it doesn't exist +0289 if isfield(newModel,'lb') +0290 I=zeros(nRxns,1); +0291 I(reversible~=0)=newLb; +0292 newModel.lb=[newModel.lb;I]; +0293 end +0294 end +0295 +0296 if isfield(newModel,'annotation') & isfield(newModel.annotation,'defaultUB') +0297 newUb=newModel.annotation.defaultUB; +0298 else +0299 newUb=inf; +0300 end +0301 +0302 if isfield(rxnsToAdd,'ub') +0303 if numel(rxnsToAdd.ub)~=nRxns +0304 EM='rxnsToAdd.ub must have the same number of elements as rxnsToAdd.rxns'; +0305 dispEM(EM); +0306 end +0307 %Fill with standard if it doesn't exist +0308 if ~isfield(newModel,'ub') +0309 newModel.ub=repmat(newUb,nOldRxns,1); +0310 end +0311 newModel.ub=[newModel.ub;rxnsToAdd.ub(:)]; +0312 else +0313 %Fill with standard if it doesn't exist +0314 if isfield(newModel,'ub') +0315 newModel.ub=[newModel.ub;repmat(newUb,nRxns,1)]; +0316 end +0317 end +0318 +0319 if isfield(rxnsToAdd,'c') +0320 if numel(rxnsToAdd.c)~=nRxns +0321 EM='rxnsToAdd.c must have the same number of elements as rxnsToAdd.rxns'; +0322 dispEM(EM); +0323 end +0324 %Fill with standard if it doesn't exist +0325 if ~isfield(newModel,'c') +0326 newModel.c=zeros(nOldRxns,1); +0327 end +0328 newModel.c=[newModel.c;rxnsToAdd.c(:)]; +0329 else +0330 %Fill with standard if it doesn't exist +0331 if isfield(newModel,'c') +0332 newModel.c=[newModel.c;zeros(nRxns,1)]; +0333 end +0334 end +0335 +0336 if isfield(rxnsToAdd,'eccodes') +0337 rxnsToAdd.eccodes=convertCharArray(rxnsToAdd.eccodes); +0338 if numel(rxnsToAdd.eccodes)~=nRxns +0339 EM='rxnsToAdd.eccodes must have the same number of elements as rxnsToAdd.rxns'; +0340 dispEM(EM); +0341 end +0342 %Fill with standard if it doesn't exist +0343 if ~isfield(newModel,'eccodes') +0344 newModel.eccodes=largeFiller; +0345 end +0346 newModel.eccodes=[newModel.eccodes;rxnsToAdd.eccodes(:)]; +0347 else +0348 %Fill with standard if it doesn't exist +0349 if isfield(newModel,'eccodes') +0350 newModel.eccodes=[newModel.eccodes;filler]; +0351 end +0352 end +0353 +0354 if isfield(rxnsToAdd,'subSystems') +0355 % Has to be cell array +0356 if ischar(rxnsToAdd.subSystems) +0357 rxnsToAdd.subSystems = {rxnsToAdd.subSystems}; +0358 end +0359 % If all nested cells are 1x1, then unnest +0360 if all(cellfun(@(x) iscell(x) && isscalar(x), rxnsToAdd.subSystems)) +0361 rxnsToAdd.subSystems = transpose([rxnsToAdd.subSystems{:}]); +0362 end +0363 % Cell array should now be as simple as possible. Check if it is nested +0364 subSysRxnsNested = any(cellfun(@(x) iscell(x), rxnsToAdd.subSystems)); +0365 if isfield(newModel,'subSystems') +0366 subSysModelNested = any(cellfun(@(x) iscell(x), newModel.subSystems)); +0367 else +0368 subSysModelNested = subSysRxnsNested; +0369 if subSysRxnsNested +0370 newModel.subSystems=largeCellFiller; +0371 else +0372 newModel.subSystems=largeFiller; +0373 end +0374 end +0375 if subSysRxnsNested && ~subSysModelNested +0376 % Make all existing subSystems nested +0377 newModel.subSystems = cellfun(@(x) {x}, newModel.subSystems, 'uni', 0); +0378 elseif ~subSysRxnsNested && subSysModelNested +0379 rxnsToAdd.subSystems = cellfun(@(x) {x}, rxnsToAdd.subSystems, 'uni', 0); +0380 end +0381 if numel(rxnsToAdd.subSystems)~=nRxns +0382 EM='rxnsToAdd.subSystems must have the same number of elements as rxnsToAdd.rxns'; +0383 dispEM(EM); +0384 end +0385 newModel.subSystems=[newModel.subSystems;rxnsToAdd.subSystems(:)]; +0386 else +0387 %Fill with standard if it does not exist +0388 if isfield(newModel,'subSystems') +0389 if any(cellfun(@(x) iscell(x), newModel.subSystems)) +0390 newModel.subSystems=[newModel.subSystems;cellfiller]; +0391 else +0392 newModel.subSystems=[newModel.subSystems;filler]; +0393 end +0394 end +0395 end +0396 if isfield(rxnsToAdd,'rxnMiriams') +0397 if numel(rxnsToAdd.rxnMiriams)~=nRxns +0398 EM='rxnsToAdd.rxnMiriams 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,'rxnMiriams') +0403 newModel.rxnMiriams=cell(nOldRxns,1); +0404 end +0405 newModel.rxnMiriams=[newModel.rxnMiriams;rxnsToAdd.rxnMiriams(:)]; +0406 else +0407 %Fill with standard if it doesn't exist +0408 if isfield(newModel,'rxnMiriams') +0409 newModel.rxnMiriams=[newModel.rxnMiriams;cell(nRxns,1)]; +0410 end +0411 end +0412 if isfield(rxnsToAdd,'rxnComps') +0413 if numel(rxnsToAdd.rxnComps)~=nRxns +0414 EM='rxnsToAdd.rxnComps must have the same number of elements as rxnsToAdd.rxns'; +0415 dispEM(EM); +0416 end +0417 %Fill with standard if it doesn't exist +0418 if ~isfield(newModel,'rxnComps') +0419 newModel.rxnComps=ones(nOldRxns,1); +0420 EM='Adding reactions with compartment information to a model without such information. All existing reactions will be assigned to the first compartment'; +0421 dispEM(EM,false); +0422 end +0423 newModel.rxnComps=[newModel.rxnComps;rxnsToAdd.rxnComps(:)]; +0424 else +0425 %Fill with standard if it doesn't exist +0426 if isfield(newModel,'rxnComps') +0427 newModel.rxnComps=[newModel.rxnComps;ones(nRxns,1)]; +0428 %fprintf('NOTE: The added reactions will be assigned to the first +0429 %compartment\n'); +0430 end +0431 end +0432 if isfield(rxnsToAdd,'grRules') +0433 rxnsToAdd.grRules=convertCharArray(rxnsToAdd.grRules); +0434 if numel(rxnsToAdd.grRules)~=nRxns +0435 EM='rxnsToAdd.grRules 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,'grRules') +0440 newModel.grRules=largeFiller; +0441 end +0442 newModel.grRules=[newModel.grRules;rxnsToAdd.grRules(:)]; +0443 else +0444 %Fill with standard if it doesn't exist +0445 if isfield(newModel,'grRules') +0446 newModel.grRules=[newModel.grRules;filler]; +0447 end +0448 end +0449 +0450 if isfield(rxnsToAdd,'rxnFrom') +0451 rxnsToAdd.rxnFrom=convertCharArray(rxnsToAdd.rxnFrom); +0452 if numel(rxnsToAdd.rxnFrom)~=nRxns +0453 EM='rxnsToAdd.rxnFrom must have the same number of elements as rxnsToAdd.rxns'; +0454 dispEM(EM); +0455 end +0456 %Fill with standard if it doesn't exist +0457 if ~isfield(newModel,'rxnFrom') +0458 newModel.rxnFrom=largeFiller; +0459 end +0460 newModel.rxnFrom=[newModel.rxnFrom;rxnsToAdd.rxnFrom(:)]; +0461 else +0462 %Fill with standard if it doesn't exist +0463 if isfield(newModel,'rxnFrom') +0464 newModel.rxnFrom=[newModel.rxnFrom;filler]; +0465 end +0466 end +0467 +0468 if isfield(rxnsToAdd,'rxnNotes') +0469 rxnsToAdd.rxnNotes=convertCharArray(rxnsToAdd.rxnNotes); +0470 if numel(rxnsToAdd.rxnNotes)~=nRxns +0471 EM='rxnsToAdd.rxnNotes must have the same number of elements as rxnsToAdd.rxns'; +0472 dispEM(EM); +0473 end +0474 %Fill with standard if it doesn't exist +0475 if ~isfield(newModel,'rxnNotes') +0476 newModel.rxnNotes=largeFiller; +0477 end +0478 newModel.rxnNotes=[newModel.rxnNotes;rxnsToAdd.rxnNotes(:)]; +0479 else +0480 %Fill with standard if it doesn't exist +0481 if isfield(newModel,'rxnNotes') +0482 newModel.rxnNotes=[newModel.rxnNotes;filler]; +0483 end +0484 end +0485 +0486 if isfield(rxnsToAdd,'rxnReferences') +0487 rxnsToAdd.rxnReferences=convertCharArray(rxnsToAdd.rxnReferences); +0488 if numel(rxnsToAdd.rxnReferences)~=nRxns +0489 EM='rxnsToAdd.rxnReferences must have the same number of elements as rxnsToAdd.rxns'; +0490 dispEM(EM); +0491 end +0492 %Fill with standard if it doesn't exist +0493 if ~isfield(newModel,'rxnReferences') +0494 newModel.rxnReferences=largeFiller; +0495 end +0496 newModel.rxnReferences=[newModel.rxnReferences;rxnsToAdd.rxnReferences(:)]; +0497 else +0498 %Fill with standard if it doesn't exist +0499 if isfield(newModel,'rxnReferences') +0500 newModel.rxnReferences=[newModel.rxnReferences;filler]; +0501 end +0502 end +0503 +0504 if isfield(rxnsToAdd,'pwys') +0505 rxnsToAdd.pwys=convertCharArray(rxnsToAdd.pwys); +0506 if numel(rxnsToAdd.pwys)~=nRxns +0507 EM='rxnsToAdd.pwys must have the same number of elements as rxnsToAdd.rxns'; +0508 dispEM(EM); +0509 end 0510 %Fill with standard if it doesn't exist -0511 if isfield(newModel,'rxnConfidenceScores') -0512 newModel.rxnConfidenceScores=[newModel.rxnConfidenceScores;NaN(nRxns,1)]; +0511 if ~isfield(newModel,'pwys') +0512 newModel.pwys=largeFiller; 0513 end -0514 end -0515 -0516 if isfield(rxnsToAdd,'rxnDeltaG') -0517 if numel(rxnsToAdd.rxnDeltaG)~=nRxns -0518 EM='rxnsToAdd.rxnDeltaG must have the same number of elements as rxnsToAdd.rxns'; -0519 dispEM(EM); -0520 end -0521 %Fill with standard if it doesn't exist -0522 if ~isfield(newModel,'rxnDeltaG') -0523 newModel.rxnDeltaG=NaN(nOldRxns,1); -0524 end -0525 newModel.rxnDeltaG=[newModel.rxnDeltaG;rxnsToAdd.rxnDeltaG(:)]; -0526 else +0514 newModel.pwys=[newModel.pwys;rxnsToAdd.pwys(:)]; +0515 else +0516 %Fill with standard if it doesn't exist +0517 if isfield(newModel,'pwys') +0518 newModel.pwys=[newModel.pwys;filler]; +0519 end +0520 end +0521 +0522 if isfield(rxnsToAdd,'rxnConfidenceScores') +0523 if numel(rxnsToAdd.rxnConfidenceScores)~=nRxns +0524 EM='rxnsToAdd.rxnConfidenceScores must have the same number of elements as rxnsToAdd.rxns'; +0525 dispEM(EM); +0526 end 0527 %Fill with standard if it doesn't exist -0528 if isfield(newModel,'rxnDeltaG') -0529 newModel.rxnDeltaG=[newModel.rxnDeltaG;NaN(nRxns,1)]; +0528 if ~isfield(newModel,'rxnConfidenceScores') +0529 newModel.rxnConfidenceScores=NaN(nOldRxns,1); 0530 end -0531 end -0532 -0533 -0534 %***Start parsing the equations and adding the info to the S matrix The -0535 %mets are matched to model.mets -0536 if eqnType==1 -0537 [I, J]=ismember(mets,model.mets); -0538 if ~all(I) -0539 if allowNewMets==true || ischar(allowNewMets) -0540 %Add the new mets -0541 metsToAdd.mets=mets(~I); -0542 metsToAdd.metNames=metsToAdd.mets; -0543 metsToAdd.compartments=compartment; -0544 if ischar(allowNewMets) -0545 newModel=addMets(newModel,metsToAdd,true,allowNewMets); -0546 else -0547 newModel=addMets(newModel,metsToAdd,true); -0548 end -0549 else -0550 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. Are you sure that eqnType=1?'; -0551 dispEM(EM); -0552 end +0531 newModel.rxnConfidenceScores=[newModel.rxnConfidenceScores;rxnsToAdd.rxnConfidenceScores(:)]; +0532 else +0533 %Fill with standard if it doesn't exist +0534 if isfield(newModel,'rxnConfidenceScores') +0535 newModel.rxnConfidenceScores=[newModel.rxnConfidenceScores;NaN(nRxns,1)]; +0536 end +0537 end +0538 +0539 if isfield(rxnsToAdd,'rxnDeltaG') +0540 if numel(rxnsToAdd.rxnDeltaG)~=nRxns +0541 EM='rxnsToAdd.rxnDeltaG must have the same number of elements as rxnsToAdd.rxns'; +0542 dispEM(EM); +0543 end +0544 %Fill with standard if it doesn't exist +0545 if ~isfield(newModel,'rxnDeltaG') +0546 newModel.rxnDeltaG=NaN(nOldRxns,1); +0547 end +0548 newModel.rxnDeltaG=[newModel.rxnDeltaG;rxnsToAdd.rxnDeltaG(:)]; +0549 else +0550 %Fill with standard if it doesn't exist +0551 if isfield(newModel,'rxnDeltaG') +0552 newModel.rxnDeltaG=[newModel.rxnDeltaG;NaN(nRxns,1)]; 0553 end -0554 %Calculate the indexes of the metabolites and add the info -0555 metIndexes=J; -0556 metIndexes(~I)=numel(newModel.mets)-sum(~I)+1:numel(newModel.mets); -0557 end -0558 -0559 %Do some stuff that is the same for eqnType=2 and eqnType=3 -0560 if eqnType==2 || eqnType==3 -0561 %For later.. -0562 t2=strcat(model.metNames,'***',model.comps(model.metComps)); -0563 end -0564 -0565 %The mets are matched to model.metNames and assigned to "compartment" -0566 if eqnType==2 -0567 %%Check that the metabolite names aren't present in the same -0568 %%compartment. -0569 %Not the neatest way maybe.. -0570 t1=strcat(mets,'***',compartment); -0571 [I, J]=ismember(t1,t2); -0572 -0573 if ~all(I) -0574 if allowNewMets==true || ischar(allowNewMets) -0575 %Add the new mets -0576 metsToAdd.metNames=mets(~I); -0577 metsToAdd.compartments=compartment; -0578 if ischar(allowNewMets) -0579 newModel=addMets(newModel,metsToAdd,true,allowNewMets); -0580 else -0581 newModel=addMets(newModel,metsToAdd,true); -0582 end -0583 else -0584 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'; -0585 dispEM(EM); -0586 end -0587 end -0588 -0589 %Calculate the indexes of the metabolites -0590 metIndexes=J; -0591 metIndexes(~I)=numel(newModel.mets)-sum(~I)+1:numel(newModel.mets); -0592 end -0593 -0594 %The equations are on the form metNames[compName] -0595 if eqnType==3 -0596 %Parse the metabolite names -0597 metNames=cell(numel(mets),1); -0598 compartments=metNames; -0599 for i=1:numel(mets) -0600 starts=max(strfind(mets{i},'[')); -0601 ends=max(strfind(mets{i},']')); -0602 -0603 %Check that the formatting is correct -0604 if isempty(starts) || isempty(ends) || ends<numel(mets{i}) -0605 EM=['The metabolite ' mets{i} ' is not correctly formatted for eqnType=3']; -0606 dispEM(EM); -0607 end -0608 -0609 %Check that the compartment is correct -0610 compartments{i}=mets{i}(starts+1:ends-1); -0611 I=ismember(compartments(i),newModel.comps); -0612 if ~I -0613 EM=['The metabolite ' mets{i} ' has a compartment that is not in model.comps']; -0614 dispEM(EM); -0615 end -0616 metNames{i}=mets{i}(1:starts-1); -0617 end -0618 -0619 %Check if the metabolite exists already -0620 t1=strcat(metNames,'***',compartments); -0621 [I, J]=ismember(t1,t2); -0622 -0623 if ~all(I) -0624 if allowNewMets==true | ischar(allowNewMets) -0625 %Add the new mets -0626 metsToAdd.metNames=metNames(~I); -0627 metsToAdd.compartments=compartments(~I); -0628 if ischar(allowNewMets) -0629 newModel=addMets(newModel,metsToAdd,true,allowNewMets); -0630 else -0631 newModel=addMets(newModel,metsToAdd,true); -0632 end -0633 else -0634 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'; -0635 dispEM(EM); -0636 end -0637 end -0638 -0639 %Calculate the indexes of the metabolites -0640 metIndexes=J; -0641 metIndexes(~I)=numel(newModel.mets)-sum(~I)+1:numel(newModel.mets); -0642 end -0643 -0644 %Add the info to the stoichiometric matrix -0645 newModel.S=[newModel.S sparse(size(newModel.S,1),nRxns)]; -0646 -0647 for i=1:nRxns -0648 newModel.S(metIndexes,nOldRxns+i)=S(:,i); -0649 %Parse the grRules and check whether all genes in grRules appear in -0650 %genes -0651 if isfield(newModel,'grRules') -0652 rule=newModel.grRules{nOldRxns+i}; -0653 rule=strrep(rule,'(',''); -0654 rule=strrep(rule,')',''); -0655 rule=strrep(rule,' or ',' '); -0656 rule=strrep(rule,' and ',' '); -0657 genes=regexp(rule,' ','split'); -0658 [I, J]=ismember(genes,newModel.genes); -0659 if ~all(I) && any(rule) -0660 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']; -0661 dispEM(EM); -0662 end -0663 end -0664 end -0665 -0666 %Make temporary minimal model structure with only new rxns, to parse to -0667 %standardizeGrRules -0668 newRxnsModel.genes=newModel.genes; -0669 newRxnsModel.grRules=newModel.grRules(length(model.rxns)+1:end); -0670 newRxnsModel.rxns=newModel.rxns(length(model.rxns)+1:end); -0671 -0672 %Fix grRules and reconstruct rxnGeneMat -0673 [grRules,rxnGeneMat] = standardizeGrRules(newRxnsModel,true); -0674 newModel.rxnGeneMat = [newModel.rxnGeneMat; rxnGeneMat]; -0675 newModel.grRules = [newModel.grRules(1:nOldRxns); grRules]; -0676 end +0554 end +0555 +0556 +0557 %***Start parsing the equations and adding the info to the S matrix The +0558 %mets are matched to model.mets +0559 if eqnType==1 +0560 [I, J]=ismember(mets,model.mets); +0561 if ~all(I) +0562 if allowNewMets==true || ischar(allowNewMets) +0563 %Add the new mets +0564 metsToAdd.mets=mets(~I); +0565 metsToAdd.metNames=metsToAdd.mets; +0566 metsToAdd.compartments=compartment; +0567 if ischar(allowNewMets) +0568 newModel=addMets(newModel,metsToAdd,true,allowNewMets); +0569 else +0570 newModel=addMets(newModel,metsToAdd,true); +0571 end +0572 else +0573 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. Are you sure that eqnType=1?'; +0574 dispEM(EM); +0575 end +0576 end +0577 %Calculate the indexes of the metabolites and add the info +0578 metIndexes=J; +0579 metIndexes(~I)=numel(newModel.mets)-sum(~I)+1:numel(newModel.mets); +0580 end +0581 +0582 %Do some stuff that is the same for eqnType=2 and eqnType=3 +0583 if eqnType==2 || eqnType==3 +0584 %For later.. +0585 t2=strcat(model.metNames,'***',model.comps(model.metComps)); +0586 end +0587 +0588 %The mets are matched to model.metNames and assigned to "compartment" +0589 if eqnType==2 +0590 %%Check that the metabolite names aren't present in the same +0591 %%compartment. +0592 %Not the neatest way maybe.. +0593 t1=strcat(mets,'***',compartment); +0594 [I, J]=ismember(t1,t2); +0595 +0596 if ~all(I) +0597 if allowNewMets==true || ischar(allowNewMets) +0598 %Add the new mets +0599 metsToAdd.metNames=mets(~I); +0600 metsToAdd.compartments=compartment; +0601 if ischar(allowNewMets) +0602 newModel=addMets(newModel,metsToAdd,true,allowNewMets); +0603 else +0604 newModel=addMets(newModel,metsToAdd,true); +0605 end +0606 else +0607 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'; +0608 dispEM(EM); +0609 end +0610 end +0611 +0612 %Calculate the indexes of the metabolites +0613 metIndexes=J; +0614 metIndexes(~I)=numel(newModel.mets)-sum(~I)+1:numel(newModel.mets); +0615 end +0616 +0617 %The equations are on the form metNames[compName] +0618 if eqnType==3 +0619 %Parse the metabolite names +0620 metNames=cell(numel(mets),1); +0621 compartments=metNames; +0622 for i=1:numel(mets) +0623 starts=max(strfind(mets{i},'[')); +0624 ends=max(strfind(mets{i},']')); +0625 +0626 %Check that the formatting is correct +0627 if isempty(starts) || isempty(ends) || ends<numel(mets{i}) +0628 EM=['The metabolite ' mets{i} ' is not correctly formatted for eqnType=3']; +0629 dispEM(EM); +0630 end +0631 +0632 %Check that the compartment is correct +0633 compartments{i}=mets{i}(starts+1:ends-1); +0634 I=ismember(compartments(i),newModel.comps); +0635 if ~I +0636 EM=['The metabolite ' mets{i} ' has a compartment that is not in model.comps']; +0637 dispEM(EM); +0638 end +0639 metNames{i}=mets{i}(1:starts-1); +0640 end +0641 +0642 %Check if the metabolite exists already +0643 t1=strcat(metNames,'***',compartments); +0644 [I, J]=ismember(t1,t2); +0645 +0646 if ~all(I) +0647 if allowNewMets==true | ischar(allowNewMets) +0648 %Add the new mets +0649 metsToAdd.metNames=metNames(~I); +0650 metsToAdd.compartments=compartments(~I); +0651 if ischar(allowNewMets) +0652 newModel=addMets(newModel,metsToAdd,true,allowNewMets); +0653 else +0654 newModel=addMets(newModel,metsToAdd,true); +0655 end +0656 else +0657 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'; +0658 dispEM(EM); +0659 end +0660 end +0661 +0662 %Calculate the indexes of the metabolites +0663 metIndexes=J; +0664 metIndexes(~I)=numel(newModel.mets)-sum(~I)+1:numel(newModel.mets); +0665 end +0666 +0667 %Add the info to the stoichiometric matrix +0668 newModel.S=[newModel.S sparse(size(newModel.S,1),nRxns)]; +0669 +0670 for i=1:nRxns +0671 newModel.S(metIndexes,nOldRxns+i)=S(:,i); +0672 %Parse the grRules and check whether all genes in grRules appear in +0673 %genes +0674 if isfield(newModel,'grRules') +0675 rule=newModel.grRules{nOldRxns+i}; +0676 rule=strrep(rule,'(',''); +0677 rule=strrep(rule,')',''); +0678 rule=strrep(rule,' or ',' '); +0679 rule=strrep(rule,' and ',' '); +0680 genes=regexp(rule,' ','split'); +0681 [I, J]=ismember(genes,newModel.genes); +0682 if ~all(I) && any(rule) +0683 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']; +0684 dispEM(EM); +0685 end +0686 end +0687 end +0688 +0689 %Make temporary minimal model structure with only new rxns, to parse to +0690 %standardizeGrRules +0691 newRxnsModel.genes=newModel.genes; +0692 newRxnsModel.grRules=newModel.grRules(length(model.rxns)+1:end); +0693 newRxnsModel.rxns=newModel.rxns(length(model.rxns)+1:end); +0694 +0695 %Fix grRules and reconstruct rxnGeneMat +0696 [grRules,rxnGeneMat] = standardizeGrRules(newRxnsModel,true); +0697 newModel.rxnGeneMat = [newModel.rxnGeneMat; rxnGeneMat]; +0698 newModel.grRules = [newModel.grRules(1:nOldRxns); grRules]; +0699 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/addTransport.html b/doc/core/addTransport.html index 98b65338..21b58cbe 100644 --- a/doc/core/addTransport.html +++ b/doc/core/addTransport.html @@ -202,45 +202,49 @@

    SOURCE CODE ^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,'rxnMiriams') -0152 model.rxnMiriams=[model.rxnMiriams;cell(nRxns,1)]; -0153 end -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'); +0137 isNested = any(cellfun(@(x) iscell(x), model.subSystems)); +0138 ssFiller = filler; +0139 if isRev==1 +0140 ssFiller(:) = {['Transport between ' fromComp ' and ' toComps{i}]}; +0141 else +0142 ssFiller(:) = {['Transport from ' fromComp ' to ' toComps{i}]}; +0143 end +0144 if isNested +0145 ssFiller = cellfun(@(x) {x}, ssFiller, 'uni', 0); +0146 end +0147 model.subSystems=[model.subSystems;ssFiller]; +0148 end +0149 if isfield(model,'grRules') +0150 model.grRules=[model.grRules;filler]; +0151 end +0152 if isfield(model,'rxnFrom') +0153 model.rxnFrom=[model.rxnFrom;filler]; +0154 end +0155 if isfield(model,'rxnMiriams') +0156 model.rxnMiriams=[model.rxnMiriams;cell(nRxns,1)]; 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,'rxnReferences') -0165 model.rxnReferences=[model.rxnReferences;filler]; -0166 end -0167 if isfield(model,'rxnConfidenceScores') -0168 model.rxnConfidenceScores=[model.rxnConfidenceScores;ones(nRxns,1)]; -0169 end -0170 if isfield(model,'rxnDeltaG') -0171 model.rxnDeltaG=[model.rxnDeltaG;zeros(nRxns,1)]; -0172 end -0173 addedRxns = [addedRxns; addedRxnsID]; -0174 end -0175 end +0158 if isfield(model,'rxnComps') +0159 model.rxnComps=[model.rxnComps;ones(nRxns,1)]; +0160 fprintf('NOTE: The added transport reactions will be added to the first compartment\n'); +0161 end +0162 if isfield(model,'rxnGeneMat') +0163 model.rxnGeneMat=[model.rxnGeneMat;sparse(nRxns,numel(model.genes))]; +0164 end +0165 if isfield(model,'rxnNotes') +0166 model.rxnNotes=[model.rxnNotes;filler]; +0167 end +0168 if isfield(model,'rxnReferences') +0169 model.rxnReferences=[model.rxnReferences;filler]; +0170 end +0171 if isfield(model,'rxnConfidenceScores') +0172 model.rxnConfidenceScores=[model.rxnConfidenceScores;ones(nRxns,1)]; +0173 end +0174 if isfield(model,'rxnDeltaG') +0175 model.rxnDeltaG=[model.rxnDeltaG;zeros(nRxns,1)]; +0176 end +0177 addedRxns = [addedRxns; addedRxnsID]; +0178 end +0179 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/checkModelStruct.html b/doc/core/checkModelStruct.html index 920a7c8b..a25d6ed4 100644 --- a/doc/core/checkModelStruct.html +++ b/doc/core/checkModelStruct.html @@ -234,11 +234,11 @@

    SOURCE CODE ^end 0176 end 0177 if isfield(model,'subSystems') -0178 for i=1:numel(model.subSystems) -0179 if ~iscell(model.subSystems{i,1}) -0180 EM='The "subSystems" field must be a cell array'; -0181 dispEM(EM,throwErrors); -0182 end +0178 isNested = any(cellfun(@(x) iscell(x), model.subSystems)); +0179 isCellStr = any(cellfun(@(x) ischar(x), model.subSystems)); +0180 if ~xor(isNested,isCellStr) +0181 EM='The "subSystems" field must be a cell array of chars, *or* a cell array of cell arrays of chars'; +0182 dispEM(EM,throwErrors); 0183 end 0184 end 0185 if isfield(model,'eccodes') diff --git a/doc/core/compareMultipleModels.html b/doc/core/compareMultipleModels.html index d4b35e1c..9a36fa00 100644 --- a/doc/core/compareMultipleModels.html +++ b/doc/core/compareMultipleModels.html @@ -178,24 +178,24 @@

    SOURCE CODE ^'*** 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 +0095 %% Compare models structure & function based on high-dimensional methods +0096 % Compare number of reactions in each subsystem in each model using a heatmap +0097 field = 'subSystems'; +0098 fprintf('\n Comparing subsystem utilization \n') +0099 if any(~cellfun(@(m) isfield(m,field),models)) +0100 fprintf('\nWARNING: At least one model does not contain the field "subSystems". \n') +0101 fprintf(' Skipping subsystem comparison. \n\n') +0102 else +0103 %% Flatten model subSystems field +0104 % Convert from cell array of cells to cell array of strings +0105 % NOTE: this function currently only recognizes one subSystem per reaction; +0106 % additional subSystems will be ignored! +0107 for i = 1:numel(models) +0108 if any(cellfun(@(x) iscell(x), models{i}.subSystems)); +0109 cells = cellfun(@iscell,models{i}.subSystems); +0110 models{i}.subSystems(cells) = cellfun(@(s) s{1}, models{i}.subSystems(cells), 'UniformOutput', false); +0111 end +0112 end 0113 [id,compMat] = compareModelField(models,field); 0114 compStruct.subsystems.ID = id; 0115 compStruct.subsystems.matrix = compMat; diff --git a/doc/core/copyToComps.html b/doc/core/copyToComps.html index 4e85433e..33b17a6e 100644 --- a/doc/core/copyToComps.html +++ b/doc/core/copyToComps.html @@ -57,10 +57,10 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • convertCharArray convertCharArray
  • getIndexes getIndexes
  • mergeModels mergeModels
  • removeReactions removeReactions
  • This function is called by: +
  • mergeModels mergeModels
  • @@ -93,76 +93,83 @@

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

    CROSS-REFERENCE INFORMATION ^
 <li><a href=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
  • 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
  • diff --git a/doc/core/fillGaps.html b/doc/core/fillGaps.html index 5ff4d82e..ba68613a 100644 --- a/doc/core/fillGaps.html +++ b/doc/core/fillGaps.html @@ -94,7 +94,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • dispEM dispEM
  • getExchangeRxns getExchangeRxns
  • getMinNrFluxes getMinNrFluxes
  • haveFlux haveFlux
  • mergeModels mergeModels
  • removeReactions removeReactions
  • simplifyModel simplifyModel
  • This function is called by: @@ -235,7 +235,7 @@

    SOURCE CODE ^%First merge all models into one big one -0133 allModels=mergeModels([{model};models],'metNames',true); +0133 allModels=mergeModels([{model};models],'metNames',true); 0134 0135 %Add that net production is ok 0136 if allowNetProduction==true @@ -316,7 +316,7 @@

    SOURCE CODE ^removeReactions(allModels,I,true,true,true); 0213 -0214 newModel=mergeModels({model;addedModel},'metNames',true); +0214 newModel=mergeModels({model;addedModel},'metNames',true); 0215 addedRxns=setdiff(newModel.rxns,model.rxns); 0216 newModel=rmfield(newModel,'rxnScores'); 0217 end diff --git a/doc/core/findRAVENroot.html b/doc/core/findRAVENroot.html index a3a1cf38..df783a87 100644 --- a/doc/core/findRAVENroot.html +++ b/doc/core/findRAVENroot.html @@ -28,7 +28,7 @@

    SYNOPSIS ^DESCRIPTION ^

     findRAVENroot
    -   Finds the root of the RAVEN directory, by searching for the path to
    +   Finds the root of the RAVEN directory, first by  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.
    @@ -48,27 +48,31 @@

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

    0001 function [ravenPath, prevDir] = findRAVENroot()
     0002 % findRAVENroot
    -0003 %   Finds the root of the RAVEN directory, by searching for the path to
    +0003 %   Finds the root of the RAVEN directory, first by  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 ravenPath = ST(strcmp({ST.name},'findRAVENroot')).file;
    -0011 rootFound = 0;
    -0012 while rootFound == 0
    -0013     isRoot = isfile(fullfile(ravenPath,'RAVEN2.png'));
    -0014     if isRoot
    -0015         rootFound = 1;
    -0016     else
    -0017         ravenPathOld = ravenPath;
    -0018         ravenPath = fileparts(ravenPath);
    -0019         if strcmp(ravenPathOld,ravenPath)
    -0020             error('Cannot find the RAVEN root directory. Make sure you have not removed the RAVEN2.png file from your RAVEN installation.')
    -0021         end
    -0022     end
    -0023 end
    +0010 if ispref('RAVEN','ravenPath') +0011 ravenPath = getpref('RAVEN','ravenPath'); +0012 else +0013 ravenPath = ST(strcmp({ST.name},'findRAVENroot')).file; +0014 rootFound = 0; +0015 while rootFound == 0 +0016 isRoot = isfile(fullfile(ravenPath,'RAVEN2.png')); +0017 if isRoot +0018 rootFound = 1; +0019 else +0020 ravenPathOld = ravenPath; +0021 ravenPath = fileparts(ravenPath); +0022 if strcmp(ravenPathOld,ravenPath) +0023 error('Cannot find the RAVEN root directory. Make sure you have not removed the RAVEN2.png file from your RAVEN installation.') +0024 end +0025 end +0026 end +0027 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/fitTasks.html b/doc/core/fitTasks.html index fa6bdbcb..03cc8895 100644 --- a/doc/core/fitTasks.html +++ b/doc/core/fitTasks.html @@ -62,13 +62,13 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • addMets addMets
  • addRxns addRxns
  • dispEM dispEM
  • fillGaps fillGaps
  • mergeModels mergeModels
  • parseTaskList parseTaskList
  • printFluxes printFluxes
  • removeReactions removeReactions
  • setParam setParam
  • This function is called by: @@ -113,7 +113,7 @@

    SOURCE CODE ^% the result. 0035 % 0036 % Usage: [outModel, addedRxns]=fitTasks(model,refModel,inputFile,printOutput,... -0037 % rxnScores,taskStructure,params) +0037 % rxnScores,taskStructure) 0038 0039 if nargin<4 0040 printOutput=true; @@ -127,286 +127,283 @@

    SOURCE CODE ^if nargin<6 0049 taskStructure=[]; 0050 end -0051 if nargin<7 -0052 params=[]; -0053 end -0054 -0055 if isempty(taskStructure) && ~isfile(inputFile) -0056 error('Task file %s cannot be found',string(inputFile)); -0057 end -0058 -0059 if strcmpi(model.id,refModel.id) -0060 fprintf('NOTE: The model and reference model have the same IDs. The ID for the reference model was set to "refModel" in order to keep track of the origin of reactions.\n'); -0061 refModel.id='refModel'; -0062 end -0063 -0064 if any(rxnScores>=0) -0065 EM='Only negative values are allowed in rxnScores'; -0066 dispEM(EM); -0067 end -0068 -0069 %Prepare the input models a little -0070 model.b=zeros(numel(model.mets),2); -0071 modelMets=upper(strcat(model.metNames,'[',model.comps(model.metComps),']')); -0072 %This is the mets in the reference model. Used if the tasks involve -0073 %metabolites that doesn't exist in the model -0074 largeModelMets=upper(strcat(refModel.metNames,'[',refModel.comps(refModel.metComps),']')); -0075 -0076 if ~isfield(model,'unconstrained') -0077 EM='Exchange metabolites should normally not be removed from the model when using checkTasks. Inputs and outputs are defined in the task file instead. Use importModel(file,false) to import a model with exchange metabolites remaining'; -0078 dispEM(EM,false); -0079 end -0080 -0081 if isempty(taskStructure) -0082 taskStructure=parseTaskList(inputFile); -0083 end -0084 -0085 tModel=model; -0086 addedRxns=false(numel(refModel.rxns),numel(taskStructure)); -0087 supressWarnings=false; -0088 nAdded=0; -0089 for i=1:numel(taskStructure) -0090 if ~taskStructure(i).shouldFail -0091 %Set the inputs -0092 if ~isempty(taskStructure(i).inputs) -0093 [I, J]=ismember(upper(taskStructure(i).inputs),modelMets); -0094 K=ismember(upper(taskStructure(i).inputs),'ALLMETS'); -0095 L=~cellfun('isempty',strfind(upper(taskStructure(i).inputs),'ALLMETSIN')); -0096 %Check that all metabolites are either real metabolites or -0097 %ALLMETS/ALLMETSIN -0098 goodMets=I|K|L; -0099 if ~all(goodMets) -0100 %Not all of the inputs could be found in the small model. -0101 %Check if they exist in the large model -0102 [found, metMatch]=ismember(upper(taskStructure(i).inputs(~goodMets)),largeModelMets); -0103 if ~all(found) -0104 EM=['Could not find all inputs in "[' taskStructure(i).id '] ' taskStructure(i).description '" in either model']; -0105 disp(EM); -0106 else -0107 %Otherwise add them to the model -0108 met.metNames=refModel.metNames(metMatch); -0109 met.compartments=refModel.comps(refModel.metComps(metMatch)); -0110 -0111 %Add the metabolite both to the base model and the -0112 %model used in the current task -0113 model=addMets(model,met); -0114 tModel=addMets(tModel,met); -0115 modelMets=[modelMets;upper(taskStructure(i).inputs(~goodMets))]; -0116 end -0117 -0118 %By now the indexes might be getting a bit confusing, but -0119 %this is to update the indexes of the "real" metabolites to -0120 %point to the newly added ones -0121 I(~goodMets)=true; %All the bad ones are fixed at this stage -0122 J(~goodMets)=numel(modelMets)-numel(metMatch)+1:numel(modelMets); -0123 end -0124 if numel(J(I))~=numel(unique(J(I))) -0125 EM=['The constraints on some input(s) in "[' taskStructure(i).id '] ' taskStructure(i).description '" are defined more than one time']; -0126 dispEM(EM); -0127 end -0128 %If all metabolites should be added -0129 if any(K) -0130 %Check if ALLMETS is the first metabolite. Otherwise print -0131 %a warning since it will write over any other constraints -0132 %that are set -0133 if K(1)==0 -0134 EM=['ALLMETS is used as an input in "[' taskStructure(i).id '] ' taskStructure(i).description '" but it it not the first metabolite in the list. Constraints defined for the metabolites before it will be over-written']; -0135 dispEM(EM,false); -0136 end -0137 %Use the first match of ALLMETS. There should only be one, -0138 %but still.. -0139 tModel.b(:,1)=taskStructure(i).UBin(find(K,1))*-1; -0140 end -0141 %If metabolites in a specific compartment should be used -0142 if any(L) -0143 L=find(L); -0144 for j=1:numel(L) -0145 %The compartment defined -0146 compartment=upper(taskStructure(i).inputs{L(j)}(11:end-1)); -0147 %Check if it exists in the model -0148 C=find(ismember(upper(model.comps),compartment)); -0149 if any(C) -0150 %Match to metabolites -0151 tModel.b(model.metComps==C,1)=taskStructure(i).UBin(L(j))*-1; -0152 else -0153 EM=['The compartment defined for ALLMETSIN in "[' taskStructure(i).id '] ' taskStructure(i).description '" does not exist']; -0154 dispEM(EM); -0155 end -0156 end -0157 end -0158 %Then add the normal constraints -0159 if any(J(I)) -0160 tModel.b(J(I),1)=taskStructure(i).UBin(I)*-1; -0161 tModel.b(J(I),2)=taskStructure(i).LBin(I)*-1; -0162 end -0163 end -0164 %Set the outputs -0165 if ~isempty(taskStructure(i).outputs) -0166 [I, J]=ismember(upper(taskStructure(i).outputs),modelMets); -0167 K=ismember(upper(taskStructure(i).outputs),'ALLMETS'); -0168 L=~cellfun('isempty',strfind(upper(taskStructure(i).outputs),'ALLMETSIN')); -0169 %Check that all metabolites are either real metabolites or -0170 %ALLMETS/ALLMETSIN -0171 goodMets=I|K|L; -0172 if ~all(goodMets) -0173 %Not all of the outputs could be found in the small model. -0174 %Check if they exist in the large model -0175 [found, metMatch]=ismember(upper(taskStructure(i).outputs(~goodMets)),largeModelMets); -0176 if ~all(found) -0177 EM=['Could not find all outputs in "[' taskStructure(i).id '] ' taskStructure(i).description '" in either model']; -0178 dispEM(EM); -0179 else -0180 %Otherwise add them to the model -0181 met.metNames=refModel.metNames(metMatch); -0182 met.compartments=refModel.comps(refModel.metComps(metMatch)); -0183 -0184 %Add the metabolite both to the base model and the -0185 %model used in the current task -0186 model=addMets(model,met); -0187 tModel=addMets(tModel,met); -0188 modelMets=[modelMets;upper(taskStructure(i).outputs(~goodMets))]; -0189 end -0190 -0191 %By now the indexes might be getting a bit confusing, but -0192 %this is to update the indexes of the "real" metabolites to -0193 %point to the newly added ones -0194 I(~goodMets)=true; %All the bad ones are fixed at this stage -0195 J(~goodMets)=numel(modelMets)-numel(metMatch)+1:numel(modelMets); -0196 end -0197 if numel(J(I))~=numel(unique(J(I))) -0198 EM=['The constraints on some output(s) in "[' taskStructure(i).id '] ' taskStructure(i).description '" are defined more than one time']; -0199 dispEM(EM); -0200 end -0201 %If all metabolites should be added -0202 if any(K) -0203 %Check if ALLMETS is the first metabolite. Otherwise print -0204 %a warning since it will write over any other constraints -0205 %that are set -0206 if K(1)==0 -0207 EM=['ALLMETS is used as an output in "[' taskStructure(i).id '] ' taskStructure(i).description '" but it it not the first metabolite in the list. Constraints defined for the metabolites before it will be over-written']; -0208 dispEM(EM,false); -0209 end -0210 %Use the first match of ALLMETS. There should only be one, -0211 %but still.. -0212 tModel.b(:,2)=taskStructure(i).UBout(find(K,1)); -0213 end -0214 %If metabolites in a specific compartment should be used -0215 if any(L) -0216 L=find(L); -0217 for j=1:numel(L) -0218 %The compartment defined -0219 compartment=upper(taskStructure(i).outputs{L(j)}(11:end-1)); -0220 %Check if it exists in the model -0221 C=find(ismember(upper(model.comps),compartment)); -0222 if any(C) -0223 %Match to metabolites -0224 tModel.b(model.metComps==C,2)=taskStructure(i).UBout(L(j)); -0225 else -0226 EM=['The compartment defined for ALLMETSIN in "[' taskStructure(i).id '] ' taskStructure(i).description '" does not exist']; -0227 dispEM(EM); -0228 end -0229 end -0230 end -0231 %Then add the normal constraints -0232 if any(J(I)) -0233 %Verify that IN and OUT bounds are consistent. Cannot require -0234 %that a metabolite is simultaneously input AND output at some -0235 %nonzero flux. -0236 J = J(I); -0237 I = find(I); % otherwise indexing becomes confusing -0238 nonzero_LBin = tModel.b(J,2) < 0; -0239 nonzero_LBout = taskStructure(i).LBout(I) > 0; -0240 if any(nonzero_LBin & nonzero_LBout) -0241 EM=['The IN LB and OUT LB in "[' taskStructure(i).id '] ' taskStructure(i).description '" cannot be nonzero for the same metabolite']; -0242 dispEM(EM); -0243 end -0244 tModel.b(J(nonzero_LBout),1)=taskStructure(i).LBout(I(nonzero_LBout)); -0245 tModel.b(J,2)=taskStructure(i).UBout(I); -0246 end -0247 end -0248 -0249 %Add new rxns -0250 if ~isempty(taskStructure(i).equations) -0251 rxn.equations=taskStructure(i).equations; -0252 rxn.lb=taskStructure(i).LBequ; -0253 rxn.ub=taskStructure(i).UBequ; -0254 rxn.rxns=strcat({'TEMPORARY_'},num2str((1:numel(taskStructure(i).equations))')); -0255 tModel=addRxns(tModel,rxn,3); -0256 end -0257 %Add changed bounds -0258 if ~isempty(taskStructure(i).changed) -0259 tModel=setParam(tModel,'lb',taskStructure(i).changed,taskStructure(i).LBrxn); -0260 tModel=setParam(tModel,'ub',taskStructure(i).changed,taskStructure(i).UBrxn); -0261 end -0262 -0263 %Solve and print. Display a warning if the problem is not solveable -0264 sol=solveLP(tModel); -0265 if isempty(sol.x) -0266 %Only do gap-filling if it cannot be solved -0267 failed=false; -0268 try -0269 [~, ~, newRxns, newModel, exitFlag]=fillGaps(tModel,refModel,false,true,supressWarnings,rxnScores,params); -0270 if exitFlag==-2 -0271 EM=['"[' taskStructure(i).id '] ' taskStructure(i).description '" was aborted before reaching optimality. Consider increasing params.maxTime\n']; -0272 dispEM(EM,false); -0273 end -0274 catch -0275 EM=['"[' taskStructure(i).id '] ' taskStructure(i).description '" could not be performed for any set of reactions\n']; -0276 dispEM(EM,false); -0277 failed=true; -0278 end -0279 if failed==false -0280 if ~isempty(newRxns) -0281 nAdded=nAdded+numel(newRxns); -0282 -0283 %Add the reactions to the base model. It is not correct -0284 %to use newModel directly, as it may contain -0285 %reactions/constraints that are specific to this task -0286 model=mergeModels({model,removeReactions(newModel,setdiff(newModel.rxns,newRxns),true,true)},'metNames',true); -0287 -0288 %Keep track of the added reactions -0289 addedRxns(ismember(refModel.rxns,newRxns),i)=true; +0051 +0052 if isempty(taskStructure) && ~isfile(inputFile) +0053 error('Task file %s cannot be found',string(inputFile)); +0054 end +0055 +0056 if strcmpi(model.id,refModel.id) +0057 fprintf('NOTE: The model and reference model have the same IDs. The ID for the reference model was set to "refModel" in order to keep track of the origin of reactions.\n'); +0058 refModel.id='refModel'; +0059 end +0060 +0061 if any(rxnScores>=0) +0062 EM='Only negative values are allowed in rxnScores'; +0063 dispEM(EM); +0064 end +0065 +0066 %Prepare the input models a little +0067 model.b=zeros(numel(model.mets),2); +0068 modelMets=upper(strcat(model.metNames,'[',model.comps(model.metComps),']')); +0069 %This is the mets in the reference model. Used if the tasks involve +0070 %metabolites that doesn't exist in the model +0071 largeModelMets=upper(strcat(refModel.metNames,'[',refModel.comps(refModel.metComps),']')); +0072 +0073 if ~isfield(model,'unconstrained') +0074 EM='Exchange metabolites should normally not be removed from the model when using checkTasks. Inputs and outputs are defined in the task file instead. Use importModel(file,false) to import a model with exchange metabolites remaining'; +0075 dispEM(EM,false); +0076 end +0077 +0078 if isempty(taskStructure) +0079 taskStructure=parseTaskList(inputFile); +0080 end +0081 +0082 tModel=model; +0083 addedRxns=false(numel(refModel.rxns),numel(taskStructure)); +0084 supressWarnings=false; +0085 nAdded=0; +0086 for i=1:numel(taskStructure) +0087 if ~taskStructure(i).shouldFail +0088 %Set the inputs +0089 if ~isempty(taskStructure(i).inputs) +0090 [I, J]=ismember(upper(taskStructure(i).inputs),modelMets); +0091 K=ismember(upper(taskStructure(i).inputs),'ALLMETS'); +0092 L=~cellfun('isempty',strfind(upper(taskStructure(i).inputs),'ALLMETSIN')); +0093 %Check that all metabolites are either real metabolites or +0094 %ALLMETS/ALLMETSIN +0095 goodMets=I|K|L; +0096 if ~all(goodMets) +0097 %Not all of the inputs could be found in the small model. +0098 %Check if they exist in the large model +0099 [found, metMatch]=ismember(upper(taskStructure(i).inputs(~goodMets)),largeModelMets); +0100 if ~all(found) +0101 EM=['Could not find all inputs in "[' taskStructure(i).id '] ' taskStructure(i).description '" in either model']; +0102 disp(EM); +0103 else +0104 %Otherwise add them to the model +0105 met.metNames=refModel.metNames(metMatch); +0106 met.compartments=refModel.comps(refModel.metComps(metMatch)); +0107 +0108 %Add the metabolite both to the base model and the +0109 %model used in the current task +0110 model=addMets(model,met); +0111 tModel=addMets(tModel,met); +0112 modelMets=[modelMets;upper(taskStructure(i).inputs(~goodMets))]; +0113 end +0114 +0115 %By now the indexes might be getting a bit confusing, but +0116 %this is to update the indexes of the "real" metabolites to +0117 %point to the newly added ones +0118 I(~goodMets)=true; %All the bad ones are fixed at this stage +0119 J(~goodMets)=numel(modelMets)-numel(metMatch)+1:numel(modelMets); +0120 end +0121 if numel(J(I))~=numel(unique(J(I))) +0122 EM=['The constraints on some input(s) in "[' taskStructure(i).id '] ' taskStructure(i).description '" are defined more than one time']; +0123 dispEM(EM); +0124 end +0125 %If all metabolites should be added +0126 if any(K) +0127 %Check if ALLMETS is the first metabolite. Otherwise print +0128 %a warning since it will write over any other constraints +0129 %that are set +0130 if K(1)==0 +0131 EM=['ALLMETS is used as an input in "[' taskStructure(i).id '] ' taskStructure(i).description '" but it it not the first metabolite in the list. Constraints defined for the metabolites before it will be over-written']; +0132 dispEM(EM,false); +0133 end +0134 %Use the first match of ALLMETS. There should only be one, +0135 %but still.. +0136 tModel.b(:,1)=taskStructure(i).UBin(find(K,1))*-1; +0137 end +0138 %If metabolites in a specific compartment should be used +0139 if any(L) +0140 L=find(L); +0141 for j=1:numel(L) +0142 %The compartment defined +0143 compartment=upper(taskStructure(i).inputs{L(j)}(11:end-1)); +0144 %Check if it exists in the model +0145 C=find(ismember(upper(model.comps),compartment)); +0146 if any(C) +0147 %Match to metabolites +0148 tModel.b(model.metComps==C,1)=taskStructure(i).UBin(L(j))*-1; +0149 else +0150 EM=['The compartment defined for ALLMETSIN in "[' taskStructure(i).id '] ' taskStructure(i).description '" does not exist']; +0151 dispEM(EM); +0152 end +0153 end +0154 end +0155 %Then add the normal constraints +0156 if any(J(I)) +0157 tModel.b(J(I),1)=taskStructure(i).UBin(I)*-1; +0158 tModel.b(J(I),2)=taskStructure(i).LBin(I)*-1; +0159 end +0160 end +0161 %Set the outputs +0162 if ~isempty(taskStructure(i).outputs) +0163 [I, J]=ismember(upper(taskStructure(i).outputs),modelMets); +0164 K=ismember(upper(taskStructure(i).outputs),'ALLMETS'); +0165 L=~cellfun('isempty',strfind(upper(taskStructure(i).outputs),'ALLMETSIN')); +0166 %Check that all metabolites are either real metabolites or +0167 %ALLMETS/ALLMETSIN +0168 goodMets=I|K|L; +0169 if ~all(goodMets) +0170 %Not all of the outputs could be found in the small model. +0171 %Check if they exist in the large model +0172 [found, metMatch]=ismember(upper(taskStructure(i).outputs(~goodMets)),largeModelMets); +0173 if ~all(found) +0174 EM=['Could not find all outputs in "[' taskStructure(i).id '] ' taskStructure(i).description '" in either model']; +0175 dispEM(EM); +0176 else +0177 %Otherwise add them to the model +0178 met.metNames=refModel.metNames(metMatch); +0179 met.compartments=refModel.comps(refModel.metComps(metMatch)); +0180 +0181 %Add the metabolite both to the base model and the +0182 %model used in the current task +0183 model=addMets(model,met); +0184 tModel=addMets(tModel,met); +0185 modelMets=[modelMets;upper(taskStructure(i).outputs(~goodMets))]; +0186 end +0187 +0188 %By now the indexes might be getting a bit confusing, but +0189 %this is to update the indexes of the "real" metabolites to +0190 %point to the newly added ones +0191 I(~goodMets)=true; %All the bad ones are fixed at this stage +0192 J(~goodMets)=numel(modelMets)-numel(metMatch)+1:numel(modelMets); +0193 end +0194 if numel(J(I))~=numel(unique(J(I))) +0195 EM=['The constraints on some output(s) in "[' taskStructure(i).id '] ' taskStructure(i).description '" are defined more than one time']; +0196 dispEM(EM); +0197 end +0198 %If all metabolites should be added +0199 if any(K) +0200 %Check if ALLMETS is the first metabolite. Otherwise print +0201 %a warning since it will write over any other constraints +0202 %that are set +0203 if K(1)==0 +0204 EM=['ALLMETS is used as an output in "[' taskStructure(i).id '] ' taskStructure(i).description '" but it it not the first metabolite in the list. Constraints defined for the metabolites before it will be over-written']; +0205 dispEM(EM,false); +0206 end +0207 %Use the first match of ALLMETS. There should only be one, +0208 %but still.. +0209 tModel.b(:,2)=taskStructure(i).UBout(find(K,1)); +0210 end +0211 %If metabolites in a specific compartment should be used +0212 if any(L) +0213 L=find(L); +0214 for j=1:numel(L) +0215 %The compartment defined +0216 compartment=upper(taskStructure(i).outputs{L(j)}(11:end-1)); +0217 %Check if it exists in the model +0218 C=find(ismember(upper(model.comps),compartment)); +0219 if any(C) +0220 %Match to metabolites +0221 tModel.b(model.metComps==C,2)=taskStructure(i).UBout(L(j)); +0222 else +0223 EM=['The compartment defined for ALLMETSIN in "[' taskStructure(i).id '] ' taskStructure(i).description '" does not exist']; +0224 dispEM(EM); +0225 end +0226 end +0227 end +0228 %Then add the normal constraints +0229 if any(J(I)) +0230 %Verify that IN and OUT bounds are consistent. Cannot require +0231 %that a metabolite is simultaneously input AND output at some +0232 %nonzero flux. +0233 J = J(I); +0234 I = find(I); % otherwise indexing becomes confusing +0235 nonzero_LBin = tModel.b(J,2) < 0; +0236 nonzero_LBout = taskStructure(i).LBout(I) > 0; +0237 if any(nonzero_LBin & nonzero_LBout) +0238 EM=['The IN LB and OUT LB in "[' taskStructure(i).id '] ' taskStructure(i).description '" cannot be nonzero for the same metabolite']; +0239 dispEM(EM); +0240 end +0241 tModel.b(J(nonzero_LBout),1)=taskStructure(i).LBout(I(nonzero_LBout)); +0242 tModel.b(J,2)=taskStructure(i).UBout(I); +0243 end +0244 end +0245 +0246 %Add new rxns +0247 if ~isempty(taskStructure(i).equations) +0248 rxn.equations=taskStructure(i).equations; +0249 rxn.lb=taskStructure(i).LBequ; +0250 rxn.ub=taskStructure(i).UBequ; +0251 rxn.rxns=strcat({'TEMPORARY_'},num2str((1:numel(taskStructure(i).equations))')); +0252 tModel=addRxns(tModel,rxn,3); +0253 end +0254 %Add changed bounds +0255 if ~isempty(taskStructure(i).changed) +0256 tModel=setParam(tModel,'lb',taskStructure(i).changed,taskStructure(i).LBrxn); +0257 tModel=setParam(tModel,'ub',taskStructure(i).changed,taskStructure(i).UBrxn); +0258 end +0259 +0260 %Solve and print. Display a warning if the problem is not solveable +0261 sol=solveLP(tModel); +0262 if isempty(sol.x) +0263 %Only do gap-filling if it cannot be solved +0264 failed=false; +0265 try +0266 [~, ~, newRxns, newModel, exitFlag]=fillGaps(tModel,refModel,false,true,supressWarnings,rxnScores); +0267 if exitFlag==-2 +0268 EM=['"[' taskStructure(i).id '] ' taskStructure(i).description '" was aborted before reaching optimality.\n']; +0269 dispEM(EM,false); +0270 end +0271 catch +0272 EM=['"[' taskStructure(i).id '] ' taskStructure(i).description '" could not be performed for any set of reactions\n']; +0273 dispEM(EM,false); +0274 failed=true; +0275 end +0276 if failed==false +0277 if ~isempty(newRxns) +0278 nAdded=nAdded+numel(newRxns); +0279 +0280 %Add the reactions to the base model. It is not correct +0281 %to use newModel directly, as it may contain +0282 %reactions/constraints that are specific to this task +0283 model=mergeModels({model,removeReactions(newModel,setdiff(newModel.rxns,newRxns),true,true)},'metNames',true); +0284 +0285 %Keep track of the added reactions +0286 addedRxns(ismember(refModel.rxns,newRxns),i)=true; +0287 end +0288 if printOutput==true +0289 fprintf(['[' taskStructure(i).id '] ' taskStructure(i).description ': Added ' num2str(numel(newRxns)) ' reaction(s), ' num2str(nAdded) ' reactions added in total\n']); 0290 end -0291 if printOutput==true -0292 fprintf(['[' taskStructure(i).id '] ' taskStructure(i).description ': Added ' num2str(numel(newRxns)) ' reaction(s), ' num2str(nAdded) ' reactions added in total\n']); -0293 end -0294 end -0295 else -0296 if printOutput==true -0297 fprintf(['[' taskStructure(i).id '] ' taskStructure(i).description ': Added 0 reaction(s), ' num2str(nAdded) ' reactions added in total\n']); -0298 end -0299 end -0300 supressWarnings=true; -0301 -0302 %Print the output if chosen -0303 if taskStructure(i).printFluxes && printOutput -0304 if ~isempty(sol.x) -0305 sol=solveLP(tModel,1); -0306 printFluxes(tModel,sol.x,false,10^-5,[],'%rxnID (%eqn):%flux\n'); -0307 fprintf('\n'); -0308 else -0309 %If the problem wasn't solveable then the gap-filled model -0310 %should be used -0311 if failed==false -0312 sol=solveLP(newModel,1); -0313 printFluxes(newModel,sol.x,false,10^-5,[],'%rxnID (%eqn):%flux\n'); -0314 fprintf('\n'); -0315 end -0316 end -0317 end -0318 -0319 tModel=model; -0320 %Since new mets are added by merging the new reactions and not only -0321 %from the task sheet -0322 modelMets=upper(strcat(model.metNames,'[',model.comps(model.metComps),']')); -0323 else -0324 EM=['"[' taskStructure(i).id '] ' taskStructure(i).description '" is set as SHOULD FAIL. Such tasks cannot be modelled using this approach and the task is therefore ignored\n']; -0325 dispEM(EM,false); -0326 end -0327 end -0328 model.b(:,2) = []; % resume field b -0329 outModel=model; -0330 end +0291 end +0292 else +0293 if printOutput==true +0294 fprintf(['[' taskStructure(i).id '] ' taskStructure(i).description ': Added 0 reaction(s), ' num2str(nAdded) ' reactions added in total\n']); +0295 end +0296 end +0297 supressWarnings=true; +0298 +0299 %Print the output if chosen +0300 if taskStructure(i).printFluxes && printOutput +0301 if ~isempty(sol.x) +0302 sol=solveLP(tModel,1); +0303 printFluxes(tModel,sol.x,false,10^-5,[],'%rxnID (%eqn):%flux\n'); +0304 fprintf('\n'); +0305 else +0306 %If the problem wasn't solveable then the gap-filled model +0307 %should be used +0308 if failed==false +0309 sol=solveLP(newModel,1); +0310 printFluxes(newModel,sol.x,false,10^-5,[],'%rxnID (%eqn):%flux\n'); +0311 fprintf('\n'); +0312 end +0313 end +0314 end +0315 +0316 tModel=model; +0317 %Since new mets are added by merging the new reactions and not only +0318 %from the task sheet +0319 modelMets=upper(strcat(model.metNames,'[',model.comps(model.metComps),']')); +0320 else +0321 EM=['"[' taskStructure(i).id '] ' taskStructure(i).description '" is set as SHOULD FAIL. Such tasks cannot be modelled using this approach and the task is therefore ignored\n']; +0322 dispEM(EM,false); +0323 end +0324 end +0325 model.b(:,2) = []; % resume field b +0326 outModel=model; +0327 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/getModelFromHomology.html b/doc/core/getModelFromHomology.html index e8f6d374..5291424f 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: @@ -631,7 +631,7 @@

    SOURCE CODE ^%Now merge the models. All information should be correct except for 'or' 0526 %complexes -0527 draftModel=mergeModels(models,'metNames'); +0527 draftModel=mergeModels(models,'metNames'); 0528 0529 %Remove unnecessary OLD_ genes, that were added with OR relationships 0530 regexStr=['OLD_(', strjoin(modelNames(:),'|'),')_(\S^\))+']; diff --git a/doc/core/mergeModels.html b/doc/core/mergeModels.html index b6d69f7c..b4315eb6 100644 --- a/doc/core/mergeModels.html +++ b/doc/core/mergeModels.html @@ -24,7 +24,7 @@

    PURPOSE ^mergeModels

    SYNOPSIS ^

    -
    function model=mergeModels(models,metParam,supressWarnings)
    +
    function model=mergeModels(models,metParam,supressWarnings,copyToComps)

    DESCRIPTION ^

     mergeModels
    @@ -33,16 +33,22 @@ 

    DESCRIPTION ^DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • copyToComps copyToComps
  • dispEM dispEM
  • standardizeGrRules standardizeGrRules
  • This function is called by: @@ -59,618 +65,656 @@

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

    -
    0001 function model=mergeModels(models,metParam,supressWarnings)
    +
    0001 function model=mergeModels(models,metParam,supressWarnings,copyToComps)
     0002 % mergeModels
     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 (optional, 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
    +0008 % Input:
    +0009 %   models          a cell array with model structures
    +0010 %   metParam        string metabolite name ('metNames') or ID ('mets') are
    +0011 %                   used for matching (optional, default 'metNames')
    +0012 %   supressWarnings logical whether warnings should be supressed (optional,
    +0013 %                   default false)
    +0014 %   copyToComps     logical whether mergeModels is run via copyToComps
    +0015 %                   (optional, default false)
    +0016 %
    +0017 % Output:
    +0018 %   model           a model structure with the merged model. Follows the
    +0019 %                   structure of normal models but also has 'rxnFrom/
    +0020 %                   metFrom/geneFrom' fields to indicate from which model
    +0021 %                   each reaction/metabolite/gene was taken. If the model
    +0022 %                   already has 'rxnFrom/metFrom/geneFrom' fields, then
    +0023 %                   these fields are not modified.
    +0024 %
    +0025 % Usage: model=mergeModels(models)
     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 %Add new functionality in the order specified in models
    -0038 model=models{1};
    -0039 model.id='MERGED';
    -0040 model.name='';
    +0027 arguments
    +0028     models;
    +0029     metParam {emptyOrTextScalar} = "metNames"
    +0030     supressWarnings {emptyOrLogicalScalar} = false
    +0031     copyToComps {emptyOrLogicalScalar} = false
    +0032 end
    +0033 
    +0034 metParam = char(metParam);
    +0035 
    +0036 %Just return the model
    +0037 if numel(models)<=1
    +0038     model=models{1};
    +0039     return;
    +0040 end
     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     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     
    -0109     if isfield(models{i},'eccodes')
    -0110         if isfield(model,'eccodes')
    -0111             model.eccodes=[model.eccodes;models{i}.eccodes];
    -0112         else
    -0113             emptyEC=cell(numel(model.rxns)-numel(models{i}.rxns),1);
    -0114             emptyEC(:)={''};
    -0115             model.eccodes=[emptyEC;models{i}.eccodes];
    -0116         end
    -0117     else
    -0118         if isfield(model,'eccodes')
    -0119             emptyEC=cell(numel(models{i}.rxns),1);
    -0120             emptyEC(:)={''};
    -0121             model.eccodes=[model.eccodes;emptyEC];
    -0122         end
    -0123     end
    -0124     
    -0125     if isfield(models{i},'rxnMiriams')
    -0126         if isfield(model,'rxnMiriams')
    -0127             model.rxnMiriams=[model.rxnMiriams;models{i}.rxnMiriams];
    -0128         else
    -0129             model.rxnMiriams=[cell(numel(model.rxns)-numel(models{i}.rxns),1);models{i}.rxnMiriams];
    -0130         end
    -0131     else
    -0132         if isfield(model,'rxnMiriams')
    -0133             model.rxnMiriams=[model.rxnMiriams;cell(numel(models{i}.rxns),1)];
    +0042 hasMetFrom  = cellfun(@(s) isfield(s,'metFrom'), models);
    +0043 hasGeneFrom = cellfun(@(s) isfield(s,'geneFrom'), models);
    +0044 hasRxnFrom  = cellfun(@(s) isfield(s,'rxnFrom'), models);
    +0045 
    +0046 for i = 1:numel(models)
    +0047     if copyToComps
    +0048         if hasMetFrom(1)
    +0049             models{2}.metFrom = repmat({''},numel(models{i}.mets),1);
    +0050         end
    +0051     elseif ~any(hasMetFrom)
    +0052         models{i}.metFrom = repmat({models{i}.id},numel(models{i}.mets),1);
    +0053     elseif ~hasMetFrom(i)
    +0054         models{i}.metFrom = repmat({''},numel(models{i}.mets),1);
    +0055     end
    +0056     if copyToComps
    +0057         if hasRxnFrom(1)
    +0058             models{2}.rxnFrom = repmat({''},numel(models{i}.rxns),1);
    +0059         end
    +0060     elseif ~any(hasRxnFrom)
    +0061         models{i}.rxnFrom = repmat({models{i}.id},numel(models{i}.rxns),1);
    +0062     elseif ~hasRxnFrom(i)
    +0063         models{i}.rxnFrom = repmat({''},numel(models{i}.rxns),1);
    +0064     end
    +0065     if copyToComps
    +0066         if hasGeneFrom(1)
    +0067             models{2}.geneFrom = repmat({''},numel(models{i}.genes),1);
    +0068         end
    +0069     elseif ~any(hasGeneFrom) && any(cellfun(@(s) isfield(s,'genes'), models))
    +0070         models{i}.geneFrom = repmat({models{i}.id},numel(models{i}.genes),1);
    +0071     elseif ~hasGeneFrom(i)
    +0072         models{i}.geneFrom = repmat({''},numel(models{i}.genes),1);
    +0073     end
    +0074 end
    +0075 
    +0076 %Add new functionality in the order specified in models
    +0077 model=models{1};
    +0078 model.id='MERGED';
    +0079 model.name='';
    +0080 
    +0081 if isfield(model,'equations')
    +0082     model=rmfield(model,'equations');
    +0083 end
    +0084 
    +0085 for i=1:numel(models)
    +0086     if isfield(models{i},'subSystems')
    +0087         models{i}.subSystems = cellfun(@(x) {x}, models{i}.subSystems, 'uni', 0);
    +0088     end
    +0089 end
    +0090 for i=2:numel(models)
    +0091     %Add the model id to the rxn id id it already exists in the model (id
    +0092     %have to be unique) This is because it makes a '[]' string if no new
    +0093     %reactions
    +0094     if ~isempty(models{i}.rxns)
    +0095         I=ismember(models{i}.rxns,model.rxns);
    +0096         models{i}.rxns(I)=strcat(models{i}.rxns(I),['_' models{i}.id]);
    +0097     end
    +0098     
    +0099     %Make sure that there are no conflicting reaction ids
    +0100     [~, ~, conflicting]=intersect(model.rxns,models{i}.rxns);
    +0101     
    +0102     if ~isempty(conflicting)
    +0103         printString=cell(numel(conflicting),1);
    +0104         for j=1:numel(conflicting)
    +0105             printString{j}=['Old: ' models{i}.rxns{conflicting(j)} ' New: ' models{i}.rxns{conflicting(j)} '_' models{i}.id];
    +0106             models{i}.rxns{conflicting(j)}=[models{i}.rxns{conflicting(j)} '_' models{i}.id];
    +0107         end
    +0108         if supressWarnings==false
    +0109             EM=['The following reaction IDs in ' models{i}.id ' are already present in the model and were renamed:'];
    +0110             dispEM(EM,false,printString);
    +0111             fprintf('\n');
    +0112         end
    +0113     end
    +0114     
    +0115     %Add all static stuff
    +0116     if any(hasRxnFrom) || (~copyToComps && ~any(hasRxnFrom))
    +0117         model.rxnFrom  = [model.rxnFrom;  models{i}.rxnFrom];
    +0118     end
    +0119     model.rxns     = [model.rxns;     models{i}.rxns];
    +0120     model.rxnNames = [model.rxnNames; models{i}.rxnNames];
    +0121     model.lb       = [model.lb;       models{i}.lb];
    +0122     model.ub       = [model.ub;       models{i}.ub];
    +0123     model.c        = [model.c;        models{i}.c];
    +0124     model.rev      = [model.rev;      models{i}.rev];
    +0125     
    +0126     if isfield(models{i},'subSystems')
    +0127         if isfield(model,'subSystems')
    +0128             model.subSystems=[model.subSystems;models{i}.subSystems];
    +0129         else
    +0130             emptySubSystem=cell(numel(model.rxns)-numel(models{i}.rxns),1);
    +0131             emptySubSystem(:)={''};
    +0132             emptySubSystem=cellfun(@(x) cell(0,0),emptySubSystem,'UniformOutput',false);
    +0133             model.subSystems=[emptySubSystem;models{i}.subSystems];
     0134         end
    -0135     end
    -0136     
    -0137     if isfield(models{i},'rxnNotes')
    -0138         if isfield(model,'rxnNotes')
    -0139             model.rxnNotes=[model.rxnNotes;models{i}.rxnNotes];
    -0140         else
    -0141             emptyNotes=cell(numel(model.rxns)-numel(models{i}.rxns),1);
    -0142             emptyNotes(:)={''};
    -0143             model.rxnNotes=[emptyNotes;models{i}.rxnNotes];
    -0144         end
    -0145     else
    -0146         if isfield(model,'rxnNotes')
    -0147             emptyNotes=cell(numel(models{i}.rxns),1);
    -0148             emptyNotes(:)={''};
    -0149             model.rxnNotes=[model.rxnNotes;emptyNotes];
    -0150         end
    -0151     end
    -0152     
    -0153     if isfield(models{i},'rxnReferences')
    -0154         if isfield(model,'rxnReferences')
    -0155             model.rxnReferences=[model.rxnReferences;models{i}.rxnReferences];
    -0156         else
    -0157             emptyReferences=cell(numel(model.rxns)-numel(models{i}.rxns),1);
    -0158             emptyReferences(:)={''};
    -0159             model.rxnReferences=[emptyReferences;models{i}.rxnReferences];
    -0160         end
    -0161     else
    -0162         if isfield(model,'rxnReferences')
    -0163             emptyReferences=cell(numel(models{i}.rxns),1);
    -0164             emptyReferences(:)={''};
    -0165             model.rxnReferences=[model.rxnReferences;emptyReferences];
    -0166         end
    -0167     end
    -0168     
    -0169     if isfield(models{i},'rxnConfidenceScores')
    -0170         if isfield(model,'rxnConfidenceScores')
    -0171             model.rxnConfidenceScores=[model.rxnConfidenceScores;models{i}.rxnConfidenceScores];
    -0172         else
    -0173             model.rxnConfidenceScores=[NaN(numel(model.rxns)-numel(models{i}.rxns),1);models{i}.rxnConfidenceScores];
    -0174         end
    -0175     else
    -0176         if isfield(model,'rxnConfidenceScores')
    -0177             model.rxnConfidenceScores=[model.rxnConfidenceScores;NaN(numel(models{i}.rxns),1)];
    -0178         end
    -0179     end
    -0180 
    -0181     if isfield(models{i},'rxnDeltaG')
    -0182         if isfield(model,'rxnDeltaG')
    -0183             model.rxnDeltaG=[model.rxnDeltaG;models{i}.rxnDeltaG];
    -0184         else
    -0185             model.rxnDeltaG=[NaN(numel(model.rxns)-numel(models{i}.rxns),1);models{i}.rxnDeltaG];
    -0186         end
    -0187     else
    -0188         if isfield(model,'rxnDeltaG')
    -0189             model.rxnDeltaG=[model.rxnDeltaG;NaN(numel(models{i}.rxns),1)];
    -0190         end
    -0191     end
    -0192     
    -0193     if isfield(models{i},'rxnComps')
    -0194         if isfield(model,'rxnComps')
    -0195             model.rxnComps=[model.rxnComps;models{i}.rxnComps];
    -0196         else
    -0197             model.rxnComps=[ones(numel(model.rxns)-numel(models{i}.rxns),1);models{i}.rxnComps];
    -0198             fprintf('NOTE: One of the models does not contain compartment information for its reactions. All reactions in that model has been assigned to the first compartment\n');
    -0199         end
    -0200     else
    -0201         if isfield(model,'rxnComps')
    -0202             model.rxnComps=[model.rxnComps;ones(numel(models{i}.rxns),1)];
    -0203             fprintf('NOTE: One of the models does not contain compartment information for its reactions. All reactions in that model has been assigned to the first compartment\n');
    -0204         end
    -0205     end
    -0206     
    -0207     if isfield(models{i},'rxnScores')
    -0208         if isfield(model,'rxnScores')
    -0209             model.rxnScores=[model.rxnScores;models{i}.rxnScores];
    -0210         else
    -0211             emptyRS=zeros(numel(model.rxns)-numel(models{i}.rxns),1);
    -0212             model.rxnScores=[emptyRS;models{i}.rxnScores];
    +0135     else
    +0136         if isfield(model,'subSystems')
    +0137             emptySubSystem=cell(numel(models{i}.rxns),1);
    +0138             emptySubSystem(:)={''};
    +0139             emptySubSystem=cellfun(@(x) cell(0,0),emptySubSystem,'UniformOutput',false);
    +0140             model.subSystems=[model.subSystems;emptySubSystem];
    +0141         end
    +0142     end
    +0143     
    +0144     if isfield(models{i},'eccodes')
    +0145         if isfield(model,'eccodes')
    +0146             model.eccodes=[model.eccodes;models{i}.eccodes];
    +0147         else
    +0148             emptyEC=cell(numel(model.rxns)-numel(models{i}.rxns),1);
    +0149             emptyEC(:)={''};
    +0150             model.eccodes=[emptyEC;models{i}.eccodes];
    +0151         end
    +0152     else
    +0153         if isfield(model,'eccodes')
    +0154             emptyEC=cell(numel(models{i}.rxns),1);
    +0155             emptyEC(:)={''};
    +0156             model.eccodes=[model.eccodes;emptyEC];
    +0157         end
    +0158     end
    +0159     
    +0160     if isfield(models{i},'rxnMiriams')
    +0161         if isfield(model,'rxnMiriams')
    +0162             model.rxnMiriams=[model.rxnMiriams;models{i}.rxnMiriams];
    +0163         else
    +0164             model.rxnMiriams=[cell(numel(model.rxns)-numel(models{i}.rxns),1);models{i}.rxnMiriams];
    +0165         end
    +0166     else
    +0167         if isfield(model,'rxnMiriams')
    +0168             model.rxnMiriams=[model.rxnMiriams;cell(numel(models{i}.rxns),1)];
    +0169         end
    +0170     end
    +0171     
    +0172     if isfield(models{i},'rxnNotes')
    +0173         if isfield(model,'rxnNotes')
    +0174             model.rxnNotes=[model.rxnNotes;models{i}.rxnNotes];
    +0175         else
    +0176             emptyNotes=cell(numel(model.rxns)-numel(models{i}.rxns),1);
    +0177             emptyNotes(:)={''};
    +0178             model.rxnNotes=[emptyNotes;models{i}.rxnNotes];
    +0179         end
    +0180     else
    +0181         if isfield(model,'rxnNotes')
    +0182             emptyNotes=cell(numel(models{i}.rxns),1);
    +0183             emptyNotes(:)={''};
    +0184             model.rxnNotes=[model.rxnNotes;emptyNotes];
    +0185         end
    +0186     end
    +0187     
    +0188     if isfield(models{i},'rxnReferences')
    +0189         if isfield(model,'rxnReferences')
    +0190             model.rxnReferences=[model.rxnReferences;models{i}.rxnReferences];
    +0191         else
    +0192             emptyReferences=cell(numel(model.rxns)-numel(models{i}.rxns),1);
    +0193             emptyReferences(:)={''};
    +0194             model.rxnReferences=[emptyReferences;models{i}.rxnReferences];
    +0195         end
    +0196     else
    +0197         if isfield(model,'rxnReferences')
    +0198             emptyReferences=cell(numel(models{i}.rxns),1);
    +0199             emptyReferences(:)={''};
    +0200             model.rxnReferences=[model.rxnReferences;emptyReferences];
    +0201         end
    +0202     end
    +0203     
    +0204     if isfield(models{i},'rxnConfidenceScores')
    +0205         if isfield(model,'rxnConfidenceScores')
    +0206             model.rxnConfidenceScores=[model.rxnConfidenceScores;models{i}.rxnConfidenceScores];
    +0207         else
    +0208             model.rxnConfidenceScores=[NaN(numel(model.rxns)-numel(models{i}.rxns),1);models{i}.rxnConfidenceScores];
    +0209         end
    +0210     else
    +0211         if isfield(model,'rxnConfidenceScores')
    +0212             model.rxnConfidenceScores=[model.rxnConfidenceScores;NaN(numel(models{i}.rxns),1)];
     0213         end
    -0214     else
    -0215         if isfield(model,'rxnScores')
    -0216             emptyRS=zeros(numel(models{i}.rxns),1);
    -0217             model.rxnScores=[model.rxnScores;emptyRS];
    -0218         end
    -0219     end
    -0220     
    -0221     if isfield(models{i},'pwys')
    -0222         if isfield(model,'pwys')
    -0223             model.pwys=[model.pwys;models{i}.pwys];
    -0224         else
    -0225             model.pwys=[cell(numel(model.rxns)-numel(models{i}.rxns),1);models{i}.pwys];
    -0226         end
    -0227     else
    -0228         if isfield(model,'pwys')
    -0229             model.pwys=[model.pwys;cell(numel(models{i}.rxns),1)];
    -0230         end
    -0231     end
    -0232 
    -0233     if strcmpi(metParam,'metNames')
    -0234     %Get the new metabolites from matching the models. Metabolites are said
    -0235     %to be the same if they share name and compartment id. This means that
    -0236     %metabolite IDs are not taken into account.
    -0237         
    -0238         oldMetComps=model.comps(model.metComps);
    -0239         oldMets=strcat(model.metNames,'[',oldMetComps,']');
    -0240         %This is because it makes a '[]' string if no new metabolites
    -0241         if ~isempty(models{i}.metNames)
    -0242             newMetComps=models{i}.comps(models{i}.metComps);
    -0243             newMets=strcat(models{i}.metNames,'[',newMetComps,']');
    -0244         else
    -0245             newMets={};
    -0246             newMetComps={};
    -0247         end
    -0248         tf=ismember(newMets,oldMets);
    -0249         metsToAdd=find(~tf);
    -0250 
    -0251     end
    -0252 
    -0253     if strcmpi(metParam,'mets')
    -0254     %Get the new metabolites from matching the models. Metabolites are matched by metabolite ID (model.mets).
    -0255 
    -0256         oldMetComps=model.comps(model.metComps);
    -0257         oldMets=model.mets;
    -0258     
    -0259         if ~isempty(models{i}.mets)
    -0260             newMetComps=models{i}.comps(models{i}.metComps);
    -0261             newMets=models{i}.mets;
    -0262         else
    -0263             newMets={};
    -0264             newMetComps={};
    +0214     end
    +0215 
    +0216     if isfield(models{i},'rxnDeltaG')
    +0217         if isfield(model,'rxnDeltaG')
    +0218             model.rxnDeltaG=[model.rxnDeltaG;models{i}.rxnDeltaG];
    +0219         else
    +0220             model.rxnDeltaG=[NaN(numel(model.rxns)-numel(models{i}.rxns),1);models{i}.rxnDeltaG];
    +0221         end
    +0222     else
    +0223         if isfield(model,'rxnDeltaG')
    +0224             model.rxnDeltaG=[model.rxnDeltaG;NaN(numel(models{i}.rxns),1)];
    +0225         end
    +0226     end
    +0227     
    +0228     if isfield(models{i},'rxnComps')
    +0229         if isfield(model,'rxnComps')
    +0230             model.rxnComps=[model.rxnComps;models{i}.rxnComps];
    +0231         else
    +0232             model.rxnComps=[ones(numel(model.rxns)-numel(models{i}.rxns),1);models{i}.rxnComps];
    +0233             fprintf('NOTE: One of the models does not contain compartment information for its reactions. All reactions in that model has been assigned to the first compartment\n');
    +0234         end
    +0235     else
    +0236         if isfield(model,'rxnComps')
    +0237             model.rxnComps=[model.rxnComps;ones(numel(models{i}.rxns),1)];
    +0238             fprintf('NOTE: One of the models does not contain compartment information for its reactions. All reactions in that model has been assigned to the first compartment\n');
    +0239         end
    +0240     end
    +0241     
    +0242     if isfield(models{i},'rxnScores')
    +0243         if isfield(model,'rxnScores')
    +0244             model.rxnScores=[model.rxnScores;models{i}.rxnScores];
    +0245         else
    +0246             emptyRS=zeros(numel(model.rxns)-numel(models{i}.rxns),1);
    +0247             model.rxnScores=[emptyRS;models{i}.rxnScores];
    +0248         end
    +0249     else
    +0250         if isfield(model,'rxnScores')
    +0251             emptyRS=zeros(numel(models{i}.rxns),1);
    +0252             model.rxnScores=[model.rxnScores;emptyRS];
    +0253         end
    +0254     end
    +0255     
    +0256     if isfield(models{i},'pwys')
    +0257         if isfield(model,'pwys')
    +0258             model.pwys=[model.pwys;models{i}.pwys];
    +0259         else
    +0260             model.pwys=[cell(numel(model.rxns)-numel(models{i}.rxns),1);models{i}.pwys];
    +0261         end
    +0262     else
    +0263         if isfield(model,'pwys')
    +0264             model.pwys=[model.pwys;cell(numel(models{i}.rxns),1)];
     0265         end
    -0266         tf=ismember(newMets,oldMets);
    -0267         metsToAdd=find(~tf);
    -0268 
    -0269     end
    -0270     
    -0271     %First add the new metabolites Make sure that there are no conflicting
    -0272     %metabolite ids
    -0273     conflicting=ismember(models{i}.mets(metsToAdd),model.mets);
    -0274     
    -0275     conflicting=find(conflicting);
    -0276     
    -0277     if ~isempty(conflicting)
    -0278         printString=cell(numel(conflicting),1);
    -0279         for j=1:numel(conflicting)
    -0280             printString{j}=['Old: ' models{i}.mets{metsToAdd(conflicting(j))} ' New: ' models{i}.mets{metsToAdd(conflicting(j))} '_' models{i}.id];
    -0281             models{i}.mets{metsToAdd(conflicting(j))}=[models{i}.mets{metsToAdd(conflicting(j))} '_' models{i}.id];
    +0266     end
    +0267 
    +0268     if strcmpi(metParam,'metNames')
    +0269     %Get the new metabolites from matching the models. Metabolites are said
    +0270     %to be the same if they share name and compartment id. This means that
    +0271     %metabolite IDs are not taken into account.
    +0272         
    +0273         oldMetComps=model.comps(model.metComps);
    +0274         oldMets=strcat(model.metNames,'[',oldMetComps,']');
    +0275         %This is because it makes a '[]' string if no new metabolites
    +0276         if ~isempty(models{i}.metNames)
    +0277             newMetComps=models{i}.comps(models{i}.metComps);
    +0278             newMets=strcat(models{i}.metNames,'[',newMetComps,']');
    +0279         else
    +0280             newMets={};
    +0281             newMetComps={};
     0282         end
    -0283         if supressWarnings==false
    -0284             EM=['The following metabolite IDs in ' models{i}.id ' are already present in the model and were renamed:'];
    -0285             dispEM(EM,false,printString);
    -0286         end
    -0287     end
    -0288     
    -0289     %Add static info on the metabolites
    -0290     metFrom=cell(numel(metsToAdd),1);
    -0291     metFrom(:)={models{i}.id};
    -0292     model.metFrom=[model.metFrom;metFrom];
    -0293     model.mets=[model.mets;models{i}.mets(metsToAdd)];
    -0294     model.metNames=[model.metNames;models{i}.metNames(metsToAdd)];
    -0295     model.b=[model.b;zeros(numel(metsToAdd),size(model.b,2))];
    -0296     
    -0297     if isfield(model,'unconstrained')
    -0298         if isfield(models{i},'unconstrained')
    -0299             model.unconstrained=[model.unconstrained;models{i}.unconstrained(metsToAdd)];
    -0300         else
    -0301             model.unconstrained=[model.unconstrained;zeros(numel(metsToAdd),1)];
    -0302         end
    -0303     else
    -0304         if isfield(models{i},'unconstrained')
    -0305             model.unconstrained=[zeros(numel(model.mets),1);models{i}.unconstrained(metsToAdd)];
    -0306         end
    -0307     end
    +0283         tf=ismember(newMets,oldMets);
    +0284         metsToAdd=find(~tf);
    +0285 
    +0286     end
    +0287 
    +0288     if strcmpi(metParam,'mets')
    +0289     %Get the new metabolites from matching the models. Metabolites are matched by metabolite ID (model.mets).
    +0290 
    +0291         oldMets=model.mets;
    +0292     
    +0293         if ~isempty(models{i}.mets)
    +0294             newMetComps=models{i}.comps(models{i}.metComps);
    +0295             newMets=models{i}.mets;
    +0296         else
    +0297             newMets={};
    +0298             newMetComps={};
    +0299         end
    +0300         tf=ismember(newMets,oldMets);
    +0301         metsToAdd=find(~tf);
    +0302 
    +0303     end
    +0304     
    +0305     %First add the new metabolites Make sure that there are no conflicting
    +0306     %metabolite ids
    +0307     conflicting=ismember(models{i}.mets(metsToAdd),model.mets);
     0308     
    -0309     %Only add extra info on new metabolites since it's a little tricky to
    -0310     %chose what to keep otherwise. Should change in the future
    -0311 
    -0312     if ~isempty(metsToAdd)
    -0313         if isfield(models{i},'inchis')
    -0314             if isfield(model,'inchis')
    -0315                 model.inchis=[model.inchis;models{i}.inchis(metsToAdd)];
    -0316             else
    -0317                 emptyInchi=cell(numel(model.mets)-numel(metsToAdd),1);
    -0318                 emptyInchi(:)={''};
    -0319                 model.inchis=[emptyInchi;models{i}.inchis(metsToAdd)];
    -0320             end
    -0321         else
    -0322             if isfield(model,'inchis')
    -0323                 emptyInchi=cell(numel(metsToAdd),1);
    -0324                 emptyInchi(:)={''};
    -0325                 model.inchis=[model.inchis;emptyInchi];
    -0326             end
    -0327         end
    -0328 
    -0329         if isfield(models{i},'metSmiles')
    -0330             if isfield(model,'metSmiles')
    -0331                 model.metSmiles=[model.metSmiles;models{i}.metSmiles(metsToAdd)];
    -0332             else
    -0333                 emptyInchi=cell(numel(model.mets)-numel(metsToAdd),1);
    -0334                 emptyInchi(:)={''};
    -0335                 model.metSmiles=[emptyInchi;models{i}.metSmiles(metsToAdd)];
    -0336             end
    -0337         else
    -0338             if isfield(model,'metSmiles')
    -0339                 emptyInchi=cell(numel(metsToAdd),1);
    -0340                 emptyInchi(:)={''};
    -0341                 model.metSmiles=[model.metSmiles;emptyInchi];
    -0342             end
    -0343         end
    -0344         
    -0345         if isfield(models{i},'metFormulas')
    -0346             if isfield(model,'metFormulas')
    -0347                 model.metFormulas=[model.metFormulas;models{i}.metFormulas(metsToAdd)];
    -0348             else
    -0349                 emptyMetFormulas=cell(numel(model.mets)-numel(metsToAdd),1);
    -0350                 emptyMetFormulas(:)={''};
    -0351                 model.metFormulas=[emptyMetFormulas;models{i}.metFormulas(metsToAdd)];
    -0352             end
    -0353         else
    -0354             if isfield(model,'metFormulas')
    -0355                 emptyMetFormulas=cell(numel(metsToAdd),1);
    -0356                 emptyMetFormulas(:)={''};
    -0357                 model.metFormulas=[model.metFormulas;emptyMetFormulas];
    -0358             end
    -0359         end
    -0360         
    -0361         if isfield(models{i},'metCharges')
    -0362             if isfield(model,'metCharges')
    -0363                 model.metCharges=[model.metCharges;models{i}.metCharges(metsToAdd)];
    -0364             else
    -0365                 emptyMetCharge=nan(numel(model.mets)-numel(metsToAdd),1);
    -0366                 model.metCharges=[emptyMetCharge;models{i}.metCharges(metsToAdd)];
    -0367             end
    -0368         else
    -0369             if isfield(model,'metCharges')
    -0370                 emptyMetCharge=nan(numel(metsToAdd),1);
    -0371                 model.metCharges=[model.metCharges;emptyMetCharge];
    -0372             end
    -0373         end
    -0374 
    -0375         if isfield(models{i},'metDeltaG')
    -0376             if isfield(model,'metDeltaG')
    -0377                 model.metDeltaG=[model.metDeltaG;models{i}.metDeltaG(metsToAdd)];
    -0378             else
    -0379                 emptyMetCharge=nan(numel(model.mets)-numel(metsToAdd),1);
    -0380                 model.metDeltaG=[emptyMetCharge;models{i}.metDeltaG(metsToAdd)];
    -0381             end
    -0382         else
    -0383             if isfield(model,'metDeltaG')
    -0384                 emptyMetCharge=nan(numel(metsToAdd),1);
    -0385                 model.metDeltaG=[model.metDeltaG;emptyMetCharge];
    +0309     conflicting=find(conflicting);
    +0310     
    +0311     if ~isempty(conflicting)
    +0312         printString=cell(numel(conflicting),1);
    +0313         for j=1:numel(conflicting)
    +0314             printString{j}=['Old: ' models{i}.mets{metsToAdd(conflicting(j))} ' New: ' models{i}.mets{metsToAdd(conflicting(j))} '_' models{i}.id];
    +0315             models{i}.mets{metsToAdd(conflicting(j))}=[models{i}.mets{metsToAdd(conflicting(j))} '_' models{i}.id];
    +0316         end
    +0317         if supressWarnings==false
    +0318             EM=['The following metabolite IDs in ' models{i}.id ' are already present in the model and were renamed:'];
    +0319             dispEM(EM,false,printString);
    +0320         end
    +0321     end
    +0322     
    +0323     %Add static info on the metabolites
    +0324     if any(hasMetFrom)
    +0325         model.metFrom  = [model.metFrom;  models{i}.metFrom(metsToAdd)];
    +0326     end
    +0327     model.mets     = [model.mets;     models{i}.mets(metsToAdd)];
    +0328     model.metNames = [model.metNames; models{i}.metNames(metsToAdd)];
    +0329     model.b        = [model.b;        zeros(numel(metsToAdd),size(model.b,2))];
    +0330     
    +0331     if isfield(model,'unconstrained')
    +0332         if isfield(models{i},'unconstrained')
    +0333             model.unconstrained=[model.unconstrained;models{i}.unconstrained(metsToAdd)];
    +0334         else
    +0335             model.unconstrained=[model.unconstrained;zeros(numel(metsToAdd),1)];
    +0336         end
    +0337     else
    +0338         if isfield(models{i},'unconstrained')
    +0339             model.unconstrained=[zeros(numel(model.mets),1);models{i}.unconstrained(metsToAdd)];
    +0340         end
    +0341     end
    +0342     
    +0343     %Only add extra info on new metabolites since it's a little tricky to
    +0344     %chose what to keep otherwise. Should change in the future
    +0345 
    +0346     if ~isempty(metsToAdd)
    +0347         if isfield(models{i},'inchis')
    +0348             if isfield(model,'inchis')
    +0349                 model.inchis=[model.inchis;models{i}.inchis(metsToAdd)];
    +0350             else
    +0351                 emptyInchi=cell(numel(model.mets)-numel(metsToAdd),1);
    +0352                 emptyInchi(:)={''};
    +0353                 model.inchis=[emptyInchi;models{i}.inchis(metsToAdd)];
    +0354             end
    +0355         else
    +0356             if isfield(model,'inchis')
    +0357                 emptyInchi=cell(numel(metsToAdd),1);
    +0358                 emptyInchi(:)={''};
    +0359                 model.inchis=[model.inchis;emptyInchi];
    +0360             end
    +0361         end
    +0362 
    +0363         if isfield(models{i},'metSmiles')
    +0364             if isfield(model,'metSmiles')
    +0365                 model.metSmiles=[model.metSmiles;models{i}.metSmiles(metsToAdd)];
    +0366             else
    +0367                 emptyInchi=cell(numel(model.mets)-numel(metsToAdd),1);
    +0368                 emptyInchi(:)={''};
    +0369                 model.metSmiles=[emptyInchi;models{i}.metSmiles(metsToAdd)];
    +0370             end
    +0371         else
    +0372             if isfield(model,'metSmiles')
    +0373                 emptyInchi=cell(numel(metsToAdd),1);
    +0374                 emptyInchi(:)={''};
    +0375                 model.metSmiles=[model.metSmiles;emptyInchi];
    +0376             end
    +0377         end
    +0378         
    +0379         if isfield(models{i},'metFormulas')
    +0380             if isfield(model,'metFormulas')
    +0381                 model.metFormulas=[model.metFormulas;models{i}.metFormulas(metsToAdd)];
    +0382             else
    +0383                 emptyMetFormulas=cell(numel(model.mets)-numel(metsToAdd),1);
    +0384                 emptyMetFormulas(:)={''};
    +0385                 model.metFormulas=[emptyMetFormulas;models{i}.metFormulas(metsToAdd)];
     0386             end
    -0387         end
    -0388         
    -0389         if isfield(models{i},'metMiriams')
    -0390             if isfield(model,'metMiriams')
    -0391                 model.metMiriams=[model.metMiriams;models{i}.metMiriams(metsToAdd)];
    -0392             else
    -0393                 emptyMetMiriam=cell(numel(model.mets)-numel(metsToAdd),1);
    -0394                 model.metMiriams=[emptyMetMiriam;models{i}.metMiriams(metsToAdd)];
    -0395             end
    -0396         else
    -0397             if isfield(model,'metMiriams')
    -0398                 emptyMetMiriam=cell(numel(metsToAdd),1);
    -0399                 model.metMiriams=[model.metMiriams;emptyMetMiriam];
    -0400             end
    -0401         end
    -0402     end
    -0403     
    -0404     %Add if there are any new compartments and add those. This can change
    -0405     %the order of compartments and the corresponding indexes in
    -0406     %model.metComps.
    -0407     
    -0408     %Find overlapping and new compartments
    -0409     [overlap, oldIDs]=ismember(models{i}.comps,model.comps);
    -0410     overlap=find(overlap);
    -0411     
    -0412     %Add the new compartments if any
    -0413     if numel(overlap)~=numel(models{i}.compNames)
    -0414         compIndexes=oldIDs==0;
    -0415         
    -0416         %Make sure that there are no conflicting compartment ids
    -0417         [~, conflicting]=ismember(models{i}.compNames(compIndexes),model.compNames);
    -0418         if any(conflicting)
    -0419             EM=['The following compartment IDs in ' models{i}.id ' are already present in the model but with another name. They have to be renamed'];
    -0420             dispEM(EM,true,model.comps(conflicting));
    +0387         else
    +0388             if isfield(model,'metFormulas')
    +0389                 emptyMetFormulas=cell(numel(metsToAdd),1);
    +0390                 emptyMetFormulas(:)={''};
    +0391                 model.metFormulas=[model.metFormulas;emptyMetFormulas];
    +0392             end
    +0393         end
    +0394         
    +0395         if isfield(models{i},'metCharges')
    +0396             if isfield(model,'metCharges')
    +0397                 model.metCharges=[model.metCharges;models{i}.metCharges(metsToAdd)];
    +0398             else
    +0399                 emptyMetCharge=nan(numel(model.mets)-numel(metsToAdd),1);
    +0400                 model.metCharges=[emptyMetCharge;models{i}.metCharges(metsToAdd)];
    +0401             end
    +0402         else
    +0403             if isfield(model,'metCharges')
    +0404                 emptyMetCharge=nan(numel(metsToAdd),1);
    +0405                 model.metCharges=[model.metCharges;emptyMetCharge];
    +0406             end
    +0407         end
    +0408 
    +0409         if isfield(models{i},'metDeltaG')
    +0410             if isfield(model,'metDeltaG')
    +0411                 model.metDeltaG=[model.metDeltaG;models{i}.metDeltaG(metsToAdd)];
    +0412             else
    +0413                 emptyMetCharge=nan(numel(model.mets)-numel(metsToAdd),1);
    +0414                 model.metDeltaG=[emptyMetCharge;models{i}.metDeltaG(metsToAdd)];
    +0415             end
    +0416         else
    +0417             if isfield(model,'metDeltaG')
    +0418                 emptyMetCharge=nan(numel(metsToAdd),1);
    +0419                 model.metDeltaG=[model.metDeltaG;emptyMetCharge];
    +0420             end
     0421         end
     0422         
    -0423         %It's ok to add duplicate name, but not duplicate IDs
    -0424         model.compNames=[model.compNames; models{i}.compNames(compIndexes)];
    -0425         model.comps=[model.comps; models{i}.comps(compIndexes)];
    -0426         if isfield(model,'compOutside')
    -0427             if isfield(models{i},'compOutside')
    -0428                 model.compOutside=[model.compOutside; models{i}.compOutside(compIndexes)];
    -0429             else
    -0430                 %This is if not all models have the field
    -0431                 padding=cell(sum(compIndexes),1);
    -0432                 padding(:)={''};
    -0433                 model.compOutside=[model.compOutside;padding];
    +0423         if isfield(models{i},'metMiriams')
    +0424             if isfield(model,'metMiriams')
    +0425                 model.metMiriams=[model.metMiriams;models{i}.metMiriams(metsToAdd)];
    +0426             else
    +0427                 emptyMetMiriam=cell(numel(model.mets)-numel(metsToAdd),1);
    +0428                 model.metMiriams=[emptyMetMiriam;models{i}.metMiriams(metsToAdd)];
    +0429             end
    +0430         else
    +0431             if isfield(model,'metMiriams')
    +0432                 emptyMetMiriam=cell(numel(metsToAdd),1);
    +0433                 model.metMiriams=[model.metMiriams;emptyMetMiriam];
     0434             end
     0435         end
    -0436         if isfield(model,'compMiriams')
    -0437             if isfield(models{i},'compMiriams')
    -0438                 model.compMiriams=[model.compMiriams; models{i}.compMiriams(compIndexes)];
    -0439             else
    -0440                 %This is if not all models have the field
    -0441                 model.compMiriams=[model.compMiriams;cell(sum(compIndexes),1)];
    -0442             end
    -0443         end
    -0444     end
    +0436     end
    +0437     
    +0438     %Add if there are any new compartments and add those. This can change
    +0439     %the order of compartments and the corresponding indexes in
    +0440     %model.metComps.
    +0441     
    +0442     %Find overlapping and new compartments
    +0443     [overlap, oldIDs]=ismember(models{i}.comps,model.comps);
    +0444     overlap=find(overlap);
     0445     
    -0446     %Only add new comp info on the un-matched metabolites since the old
    -0447     %ones will be mapped to the existing list anyways
    -0448     [I, J]=ismember(newMetComps(metsToAdd),model.comps);
    -0449     %Just a check
    -0450     if ~all(I)
    -0451         EM='There was an unexpected error in matching compartments';
    -0452         dispEM(EM);
    -0453     end
    -0454     model.metComps=[model.metComps;J];
    -0455      
    -0456     %Create the new stoichiometric matrix
    -0457     model.S=[model.S;sparse(numel(metsToAdd),size(model.S,2))];
    -0458     
    -0459 
    -0460     if strcmpi(metParam,'metNames')
    -0461         %Rematch metabolite names. Not the most clever way to do it maybe
    -0462         allMets=strcat(model.metNames,'[',model.comps(model.metComps),']');
    -0463         [~, J]=ismember(newMets,allMets);
    -0464     end
    -0465 
    -0466     if strcmpi(metParam,'mets')
    -0467         %Rematch metabolite by IDs and add unique new metabolites
    -0468         allMets=model.mets;
    -0469         uniqueNewMets = setdiff(newMets,oldMets);
    -0470         allMets(end+1:end+numel(uniqueNewMets)) = uniqueNewMets;
    -0471         [~, J]=ismember(newMets,allMets);
    -0472     end
    -0473 
    -0474     %Update the stoichiometric matrix for the model to add
    -0475     newS=sparse(numel(model.mets),numel(models{i}.rxns));
    -0476     newS(J,:)=models{i}.S;
    -0477     model.S=[model.S newS];
    -0478 
    +0446     %Add the new compartments if any
    +0447     if numel(overlap)~=numel(models{i}.compNames)
    +0448         compIndexes=oldIDs==0;
    +0449         
    +0450         %Make sure that there are no conflicting compartment ids
    +0451         [~, conflicting]=ismember(models{i}.compNames(compIndexes),model.compNames);
    +0452         if any(conflicting)
    +0453             EM=['The following compartment IDs in ' models{i}.id ' are already present in the model but with another name. They have to be renamed'];
    +0454             dispEM(EM,true,model.comps(conflicting));
    +0455         end
    +0456         
    +0457         %It's ok to add duplicate name, but not duplicate IDs
    +0458         model.compNames=[model.compNames; models{i}.compNames(compIndexes)];
    +0459         model.comps=[model.comps; models{i}.comps(compIndexes)];
    +0460         if isfield(model,'compOutside')
    +0461             if isfield(models{i},'compOutside')
    +0462                 model.compOutside=[model.compOutside; models{i}.compOutside(compIndexes)];
    +0463             else
    +0464                 %This is if not all models have the field
    +0465                 padding=cell(sum(compIndexes),1);
    +0466                 padding(:)={''};
    +0467                 model.compOutside=[model.compOutside;padding];
    +0468             end
    +0469         end
    +0470         if isfield(model,'compMiriams')
    +0471             if isfield(models{i},'compMiriams')
    +0472                 model.compMiriams=[model.compMiriams; models{i}.compMiriams(compIndexes)];
    +0473             else
    +0474                 %This is if not all models have the field
    +0475                 model.compMiriams=[model.compMiriams;cell(sum(compIndexes),1)];
    +0476             end
    +0477         end
    +0478     end
     0479     
    -0480     %Now add new genes
    -0481     if isfield(models{i},'genes')
    -0482         if ~isfield(model,'genes')
    -0483             %If there was no gene info before
    -0484             model.genes=models{i}.genes;
    -0485             model.rxnGeneMat=[sparse(numel(model.rxns),numel(models{i}.genes));models{i}.rxnGeneMat];
    -0486             emptyGene=cell(numel(model.rxns),1);
    -0487             emptyGene(:)={''};
    -0488             model.grRules=[emptyGene;models{i}.grRules];
    -0489             model.geneFrom=cell(numel(models{i}.genes),1);
    -0490             model.geneFrom(:)={models{i}.id};
    -0491             
    -0492             if isfield(models{i},'geneShortNames')
    -0493                 model.geneShortNames=models{i}.geneShortNames;
    -0494             end
    -0495 
    -0496             if isfield(models{i},'proteins')
    -0497                 model.proteins=models{i}.proteins;
    -0498             end
    +0480     %Only add new comp info on the un-matched metabolites since the old
    +0481     %ones will be mapped to the existing list anyways
    +0482     [I, J]=ismember(newMetComps(metsToAdd),model.comps);
    +0483     %Just a check
    +0484     if ~all(I)
    +0485         EM='There was an unexpected error in matching compartments';
    +0486         dispEM(EM);
    +0487     end
    +0488     model.metComps=[model.metComps;J];
    +0489      
    +0490     %Create the new stoichiometric matrix
    +0491     model.S=[model.S;sparse(numel(metsToAdd),size(model.S,2))];
    +0492     
    +0493 
    +0494     if strcmpi(metParam,'metNames')
    +0495         %Rematch metabolite names. Not the most clever way to do it maybe
    +0496         allMets=strcat(model.metNames,'[',model.comps(model.metComps),']');
    +0497         [~, J]=ismember(newMets,allMets);
    +0498     end
     0499 
    -0500             if isfield(models{i},'geneMiriams')
    -0501                 model.geneMiriams=models{i}.geneMiriams;
    -0502             end
    -0503             
    -0504             if isfield(models{i},'geneComps')
    -0505                 model.geneComps=models{i}.geneComps;
    -0506             end
    -0507         else
    -0508             %If gene info should be merged
    -0509             a=ismember(models{i}.genes,model.genes);
    -0510             
    -0511             genesToAdd=find(~a);
    -0512             
    -0513             %Only add extra gene info on new genes. This might not be
    -0514             %correct and should be changed later...
    -0515             if ~isempty(genesToAdd)
    -0516                 model.genes=[model.genes;models{i}.genes(genesToAdd)];
    -0517                 emptyGene=cell(numel(genesToAdd),1);
    -0518                 emptyGene(:)={models{i}.id};
    -0519                 model.geneFrom=[model.geneFrom;emptyGene];
    -0520                 model.rxnGeneMat=[model.rxnGeneMat sparse(size(model.rxnGeneMat,1),numel(genesToAdd))];
    -0521                 
    -0522                 if isfield(models{i},'geneShortNames')
    -0523                     if isfield(model,'geneShortNames')
    -0524                         model.geneShortNames=[model.geneShortNames;models{i}.geneShortNames(genesToAdd)];
    -0525                     else
    -0526                         emptyGeneSN=cell(numel(model.genes)-numel(genesToAdd),1);
    -0527                         emptyGeneSN(:)={''};
    -0528                         model.geneShortNames=[emptyGeneSN;models{i}.geneShortNames(genesToAdd)];
    -0529                     end
    -0530                 else
    -0531                     if isfield(model,'geneShortNames')
    -0532                         emptyGeneSN=cell(numel(genesToAdd),1);
    -0533                         emptyGeneSN(:)={''};
    -0534                         model.geneShortNames=[model.geneShortNames;emptyGeneSN];
    -0535                     end
    -0536                 end
    -0537 
    -0538                 if isfield(models{i},'proteins')
    -0539                     if isfield(model,'proteins')
    -0540                         model.proteins=[model.proteins;models{i}.proteins(genesToAdd)];
    -0541                     else
    -0542                         emptyGeneSN=cell(numel(model.genes)-numel(genesToAdd),1);
    -0543                         emptyGeneSN(:)={''};
    -0544                         model.proteins=[emptyGeneSN;models{i}.proteins(genesToAdd)];
    -0545                     end
    -0546                 else
    -0547                     if isfield(model,'proteins')
    -0548                         emptyGeneSN=cell(numel(genesToAdd),1);
    -0549                         emptyGeneSN(:)={''};
    -0550                         model.proteins=[model.proteins;emptyGeneSN];
    -0551                     end
    -0552                 end
    -0553 
    -0554                 if isfield(models{i},'geneMiriams')
    -0555                     if isfield(model,'geneMiriams')
    -0556                         model.geneMiriams=[model.geneMiriams;models{i}.geneMiriams(genesToAdd)];
    +0500     if strcmpi(metParam,'mets')
    +0501         %Rematch metabolite by IDs and add unique new metabolites
    +0502         allMets=model.mets;
    +0503         uniqueNewMets = setdiff(newMets,oldMets);
    +0504         allMets(end+1:end+numel(uniqueNewMets)) = uniqueNewMets;
    +0505         [~, J]=ismember(newMets,allMets);
    +0506     end
    +0507 
    +0508     %Update the stoichiometric matrix for the model to add
    +0509     newS=sparse(numel(model.mets),numel(models{i}.rxns));
    +0510     newS(J,:)=models{i}.S;
    +0511     model.S=[model.S newS];
    +0512 
    +0513     
    +0514     %Now add new genes
    +0515     if isfield(models{i},'genes')
    +0516         if ~isfield(model,'genes')
    +0517             %If there was no gene info before
    +0518             model.genes      = models{i}.genes;
    +0519             model.rxnGeneMat = [sparse(numel(model.rxns),numel(models{i}.genes));models{i}.rxnGeneMat];
    +0520             emptyGene        = repmat({''},numel(model.rxns),1);
    +0521             model.grRules    = [emptyGene;models{i}.grRules];
    +0522             if any(hasGeneFrom)
    +0523                 model.geneFrom   = models{i}.geneFrom;
    +0524             end
    +0525             
    +0526             if isfield(models{i},'geneShortNames')
    +0527                 model.geneShortNames=models{i}.geneShortNames;
    +0528             end
    +0529 
    +0530             if isfield(models{i},'proteins')
    +0531                 model.proteins=models{i}.proteins;
    +0532             end
    +0533 
    +0534             if isfield(models{i},'geneMiriams')
    +0535                 model.geneMiriams=models{i}.geneMiriams;
    +0536             end
    +0537             
    +0538             if isfield(models{i},'geneComps')
    +0539                 model.geneComps=models{i}.geneComps;
    +0540             end
    +0541         else
    +0542             %If gene info should be merged
    +0543             a=ismember(models{i}.genes,model.genes);
    +0544             
    +0545             genesToAdd=find(~a);
    +0546             
    +0547             %Only add extra gene info on new genes. This might not be
    +0548             %correct and should be changed later...
    +0549             if ~isempty(genesToAdd)
    +0550                 model.genes      = [model.genes;        models{i}.genes(genesToAdd)];
    +0551                 model.geneFrom   = [model.geneFrom;     models{i}.geneFrom(genesToAdd)];
    +0552                 model.rxnGeneMat = [model.rxnGeneMat    sparse(size(model.rxnGeneMat,1),numel(genesToAdd))];
    +0553                 
    +0554                 if isfield(models{i},'geneShortNames')
    +0555                     if isfield(model,'geneShortNames')
    +0556                         model.geneShortNames=[model.geneShortNames;models{i}.geneShortNames(genesToAdd)];
     0557                     else
    -0558                         emptyGeneMir=cell(numel(model.genes)-numel(genesToAdd),1);
    -0559                         model.geneMiriams=[emptyGeneMir;models{i}.geneMiriams(genesToAdd)];
    -0560                     end
    -0561                 else
    -0562                     if isfield(model,'geneMiriams')
    -0563                         emptyGeneMir=cell(numel(genesToAdd),1);
    -0564                         model.geneMiriams=[model.geneMiriams;emptyGeneMir];
    -0565                     end
    -0566                 end
    -0567                 
    -0568                 if isfield(models{i},'geneComps')
    -0569                     if isfield(model,'geneComps')
    -0570                         model.geneComps=[model.geneComps;models{i}.geneComps(genesToAdd)];
    -0571                     else
    -0572                         emptyGeneMir=ones(numel(model.genes)-numel(genesToAdd),1);
    -0573                         model.geneComps=[emptyGeneMir;models{i}.geneComps(genesToAdd)];
    -0574                         EM='Adding genes with compartment information to a model without such information. All existing genes will be assigned to the first compartment';
    -0575                         dispEM(EM,false);
    -0576                     end
    -0577                 else
    -0578                     if isfield(model,'geneComps')
    -0579                         emptyGeneMir=ones(numel(genesToAdd),1);
    -0580                         model.geneComps=[model.geneComps;emptyGeneMir];
    -0581                         EM='Adding genes with compartment information to a model without such information. All existing genes will be assigned to the first compartment';
    -0582                         dispEM(EM,false);
    +0558                         emptyGeneSN=cell(numel(model.genes)-numel(genesToAdd),1);
    +0559                         emptyGeneSN(:)={''};
    +0560                         model.geneShortNames=[emptyGeneSN;models{i}.geneShortNames(genesToAdd)];
    +0561                     end
    +0562                 else
    +0563                     if isfield(model,'geneShortNames')
    +0564                         emptyGeneSN=cell(numel(genesToAdd),1);
    +0565                         emptyGeneSN(:)={''};
    +0566                         model.geneShortNames=[model.geneShortNames;emptyGeneSN];
    +0567                     end
    +0568                 end
    +0569 
    +0570                 if isfield(models{i},'proteins')
    +0571                     if isfield(model,'proteins')
    +0572                         model.proteins=[model.proteins;models{i}.proteins(genesToAdd)];
    +0573                     else
    +0574                         emptyGeneSN=cell(numel(model.genes)-numel(genesToAdd),1);
    +0575                         emptyGeneSN(:)={''};
    +0576                         model.proteins=[emptyGeneSN;models{i}.proteins(genesToAdd)];
    +0577                     end
    +0578                 else
    +0579                     if isfield(model,'proteins')
    +0580                         emptyGeneSN=cell(numel(genesToAdd),1);
    +0581                         emptyGeneSN(:)={''};
    +0582                         model.proteins=[model.proteins;emptyGeneSN];
     0583                     end
     0584                 end
    -0585             end
    -0586             
    -0587             %Remap the genes from the new model. The same thing as with
    -0588             %mets; this is a wasteful way to do it but I don't care right
    -0589             %now
    -0590             [a, b]=ismember(models{i}.genes,model.genes);
    -0591             
    -0592             %Just a check
    -0593             if ~all(a)
    -0594                 EM='There was an unexpected error in matching genes';
    -0595                 dispEM(EM);
    -0596             end
    -0597             model.grRules=[model.grRules;models{i}.grRules];
    -0598         end
    -0599     else
    -0600         %Add empty gene associations
    -0601         if isfield(model,'genes')
    -0602             emptyGene=cell(numel(models{i}.rxns),1);
    -0603             emptyGene(:)={''};
    -0604             model.grRules=[model.grRules;emptyGene];
    -0605         end
    -0606     end
    -0607 end
    -0608 %Fix grRules and reconstruct rxnGeneMat
    -0609 [grRules,rxnGeneMat] = standardizeGrRules(model,true);
    -0610 model.grRules = grRules;
    -0611 model.rxnGeneMat = rxnGeneMat;
    -0612 end
    +0585 +0586 if isfield(models{i},'geneMiriams') +0587 if isfield(model,'geneMiriams') +0588 model.geneMiriams=[model.geneMiriams;models{i}.geneMiriams(genesToAdd)]; +0589 else +0590 emptyGeneMir=cell(numel(model.genes)-numel(genesToAdd),1); +0591 model.geneMiriams=[emptyGeneMir;models{i}.geneMiriams(genesToAdd)]; +0592 end +0593 else +0594 if isfield(model,'geneMiriams') +0595 emptyGeneMir=cell(numel(genesToAdd),1); +0596 model.geneMiriams=[model.geneMiriams;emptyGeneMir]; +0597 end +0598 end +0599 +0600 if isfield(models{i},'geneComps') +0601 if isfield(model,'geneComps') +0602 model.geneComps=[model.geneComps;models{i}.geneComps(genesToAdd)]; +0603 else +0604 emptyGeneMir=ones(numel(model.genes)-numel(genesToAdd),1); +0605 model.geneComps=[emptyGeneMir;models{i}.geneComps(genesToAdd)]; +0606 EM='Adding genes with compartment information to a model without such information. All existing genes will be assigned to the first compartment'; +0607 dispEM(EM,false); +0608 end +0609 else +0610 if isfield(model,'geneComps') +0611 emptyGeneMir=ones(numel(genesToAdd),1); +0612 model.geneComps=[model.geneComps;emptyGeneMir]; +0613 EM='Adding genes with compartment information to a model without such information. All existing genes will be assigned to the first compartment'; +0614 dispEM(EM,false); +0615 end +0616 end +0617 end +0618 +0619 %Remap the genes from the new model. The same thing as with +0620 %mets; this is a wasteful way to do it but I do not care right +0621 %now +0622 a = ismember(models{i}.genes,model.genes); +0623 +0624 %Just a check +0625 if ~all(a) +0626 EM='There was an unexpected error in matching genes'; +0627 dispEM(EM); +0628 end +0629 model.grRules=[model.grRules;models{i}.grRules]; +0630 end +0631 else +0632 %Add empty gene associations +0633 if isfield(model,'genes') +0634 emptyGene=cell(numel(models{i}.rxns),1); +0635 emptyGene(:)={''}; +0636 model.grRules=[model.grRules;emptyGene]; +0637 end +0638 end +0639 end +0640 %Fix grRules and reconstruct rxnGeneMat +0641 [grRules,rxnGeneMat] = standardizeGrRules(model,true); +0642 model.grRules = grRules; +0643 model.rxnGeneMat = rxnGeneMat; +0644 %Flatten subSystems if possible +0645 if isfield(model,'subSystems') +0646 if all(cellfun(@(x) iscell(x) && isscalar(x), model.subSystems)) +0647 model.subSystems = transpose([model.subSystems{:}]); +0648 end +0649 end +0650 end

    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/parseTaskList.html b/doc/core/parseTaskList.html index 091bf07f..51aa28e2 100644 --- a/doc/core/parseTaskList.html +++ b/doc/core/parseTaskList.html @@ -30,10 +30,11 @@

    DESCRIPTION ^
     parseTaskList
        Parses a task list file.
     
    -   inputFile       a task list in Excel format. The file must contain a
    -                   sheet named TASKS, which in turn may contain the
    -                   following column headers (note, all rows starting with
    -                   a non-empty cell are removed. The first row after that
    +   inputFile       a task list in either Excel (*.xlsx, with a sheet named
    +                   TASKS with all relevant content) or tab-delimited
    +                   (*.txt) format. The file may contain the following
    +                   column headers (note, all rows starting with a
    +                   non-empty cell are removed. The first row after that
                        is considered the headers):
                        ID
                            the only required header. Each task must have a
    @@ -154,286 +155,287 @@ 

    SOURCE CODE ^% parseTaskList 0003 % Parses a task list file. 0004 % -0005 % inputFile a task list in Excel format. The file must contain a -0006 % sheet named TASKS, which in turn may contain the -0007 % following column headers (note, all rows starting with -0008 % a non-empty cell are removed. The first row after that -0009 % is considered the headers): -0010 % ID -0011 % the only required header. Each task must have a -0012 % unique id (string or numeric). Tasks can span multiple -0013 % rows, only the first row in each task should have -0014 % an id -0015 % DESCRIPTION -0016 % description of the task -0017 % IN -0018 % allowed input(s) for the task. Metabolite names -0019 % should be on the form -0020 % "model.metName[model.comps]". Several inputs -0021 % can be delimited by ";". If so, then the same -0022 % bounds are used for all inputs. If that is not -0023 % wanted, then use several rows for the task -0024 % IN LB -0025 % lower bound for the uptake of the metabolites in -0026 % the row (optional, default 0 which corresponds to a -0027 % minimal uptake of 0 units) -0028 % IN UB -0029 % upper bound for the uptake of the metabolites in -0030 % the row (optional, default 1000 which corresponds to a -0031 % maximal uptake of 1000 units) -0032 % OUT -0033 % allowed output(s) for the task (see IN) -0034 % OUT LB -0035 % lower bound for the production of the metabolites in -0036 % the row (optional, default 0 which corresponds to a -0037 % minimal production of 0 units) -0038 % OUT UB -0039 % upper bound for the production of the metabolites in -0040 % the row (optional, default 1000 which corresponds to a -0041 % maximal production of 1000 units) -0042 % EQU -0043 % equation to add. The equation should be on the form -0044 % "0.4 A + 2 B <=> (or =>) C" and the metabolites -0045 % should be on the form -0046 % "model.metName[model.comps]" (optional) -0047 % EQU LB -0048 % lower bound for the equation (optional, default -1000 -0049 % for reversible and 0 for irreversible) -0050 % EQU UB -0051 % upper bound for the equation (optional, default 1000) -0052 % CHANGED RXN -0053 % reaction ID for which to change the bounds for. -0054 % Several IDs can be delimited by ";". If so, -0055 % then the same bounds are used for all reactions. If -0056 % that is not wanted, then use several rows for the task -0057 % CHANGED LB -0058 % lower bound for the reaction -0059 % CHANGED UB -0060 % upper bound for the reaction -0061 % SHOULD FAIL -0062 % true if the correct behavior of the model is to -0063 % not have a feasible solution given the constraints -0064 % (optional, default false) -0065 % PRINT FLUX -0066 % true if the function should print the corresponding -0067 % flux distribution for a task. Can be useful for -0068 % testing (optional, default false) -0069 % -0070 % taskStruct array of structures with the following fields -0071 % id the id of the task -0072 % description the description of the task -0073 % shouldFail true if the task should fail -0074 % printFluxes true if the fluxes should be printed -0075 % comments string with comments -0076 % inputs cell array with input metabolites (in the form metName[comps]) -0077 % LBin array with lower bounds on inputs (default, 0) -0078 % UBin array with upper bounds on inputs (default, 1000) -0079 % outputs cell array with output metabolites (in the form metName[comps]) -0080 % LBout array with lower bounds on outputs (default, 0) -0081 % UBout array with upper bounds on outputs (default, 1000) -0082 % equations cell array with equations (with mets in the form metName[comps]) -0083 % LBequ array with lower bounds on equations (default, -1000 for -0084 % reversible and 0 for irreversible) -0085 % UBequ array with upper bounds on equations (default, 1000) -0086 % changed cell array with reactions to change bounds for -0087 % LBrxn array with lower bounds on changed reactions -0088 % UBrxn array with upper bounds on changed reactions -0089 % -0090 % This function is used for defining a set of tasks for a model to -0091 % perform. The tasks are defined by defining constraints on the model, -0092 % and if the problem is feasible, then the task is considered successful. -0093 % In general, each row can contain one constraint on uptakes, one -0094 % constraint on outputs, one new equation, and one change of reaction -0095 % bounds. If more bounds are needed to define the task, then several rows -0096 % can be used for each task. To perform the task use checkTasks or -0097 % fitTasks. -0098 % -0099 % NOTE: The general metabolites "ALLMETS" and "ALLMETSIN[comps]" -0100 % can be used as inputs or outputs in the similar manner to normal -0101 % metabolites. This is a convenient way to, for example, allow excretion of -0102 % all metabolites to check whether it's the synthesis of some metabolite -0103 % that is limiting or whether it's the degradation of some byproduct. One -0104 % important difference is that only the upper bounds are used for these general -0105 % metabolites. That is, you can only say that uptake or excretion is -0106 % allowed, not that it is required. This is to avoid conflicts where the -0107 % constraints for the general metabolites overwrite those of the real -0108 % ones. -0109 % -0110 % Usage: taskStruct=parseTaskList(inputFile) -0111 -0112 if ~isfile(inputFile) -0113 error('Task list %s cannot be found',string(inputFile)); -0114 end -0115 -0116 %Load the tasks file -0117 convNumeric = false; -0118 if strcmp(extractAfter(inputFile,strlength(inputFile) - 4), '.txt') -0119 %load from tab delimited text file -0120 fid = fopen(inputFile); -0121 %Need to read numeric columns as strings, this is converted further -0122 %down. If not, the titles would be lost. -0123 convNumeric = true; -0124 C = textscan(fid,'%q%q%q%q%q%q%q%q%q%q%q%q%q%q%q%q%q%q%q%q%*[^\n]', 'Delimiter', '\t'); -0125 fclose(fid); -0126 raw = [C{:}];%unnest the cell array of cell arrays into a 2-dim cell array -0127 else -0128 [raw,flag]=loadSheet(loadWorkbook(inputFile), 'TASKS'); -0129 if flag~=0 -0130 EM=['Could not load sheet "TASKS" from ' inputFile]; -0131 dispEM(EM); -0132 end -0133 end -0134 -0135 %Remove all lines starting with "#" (or actually any character) and all -0136 %empty columns -0137 raw=cleanSheet(raw); -0138 -0139 %Captions -0140 columns={'ID';'DESCRIPTION';'IN';'IN LB';'IN UB';'OUT';'OUT LB';'OUT UB';'EQU';'EQU LB';'EQU UB';'CHANGED RXN';'CHANGED LB';'CHANGED UB';'SHOULD FAIL';'PRINT FLUX';'COMMENTS'}; -0141 %Match the columns -0142 [I, colI]=ismember(columns,raw(1,:)); -0143 -0144 %If read from a text file, the numbers will be strings - fix that -0145 if convNumeric % in theory, this if should not be needed, the code should do nothing if all are already numeric. But it is kept as a safeguard. -0146 numericColumns = [0 0 0 1 1 0 1 1 0 1 1 0 1 1 0 0 0] == 1; -0147 cols = colI(numericColumns); -0148 numeric = cellfun(@isnumeric,raw(:,cols)); -0149 %trick to avoid messing up the title row: -0150 numeric(1,:) = 1; -0151 for colind = 1:numel(cols) -0152 col = cols(colind); -0153 raw(~numeric(:,colind),col) = cellfun(@str2num, raw(~numeric(:,colind),col), 'UniformOutput', false); -0154 end -0155 end -0156 -0157 %Check that the ID field is present -0158 if I(1)==0 -0159 EM='The TASKS sheet must have a column named ID'; -0160 dispEM(EM); -0161 end -0162 -0163 %make sure numerical fields are converted from strings -0164 -0165 %Add default bounds where needed -0166 for i=[4 5 7 8] -0167 I=cellfun(@isempty,raw(:,colI(i))); -0168 if i==5 || i==8 -0169 raw(I,colI(i))={1000}; -0170 else -0171 raw(I,colI(i))={0}; -0172 end -0173 end -0174 -0175 %Create an empty task structure -0176 eTask.id=''; -0177 eTask.description=''; -0178 eTask.shouldFail=false; -0179 eTask.printFluxes=false; -0180 eTask.comments=''; -0181 eTask.inputs={}; -0182 eTask.LBin=[]; -0183 eTask.UBin=[]; -0184 eTask.outputs={}; -0185 eTask.LBout=[]; -0186 eTask.UBout=[]; -0187 eTask.equations={}; -0188 eTask.LBequ=[]; -0189 eTask.UBequ=[]; -0190 eTask.changed={}; -0191 eTask.LBrxn=[]; -0192 eTask.UBrxn=[]; -0193 -0194 %Main loop -0195 taskStruct=[]; -0196 task=eTask; -0197 if isnumeric(raw{2,colI(1)}) -0198 task.id=num2str(raw{2,colI(1)}); -0199 else -0200 task.id=raw{2,colI(1)}; -0201 end -0202 task.description=raw{2,colI(2)}; -0203 if ~isempty(raw{2,colI(15)}) -0204 task.shouldFail=true; -0205 end -0206 if ~isempty(raw{2,colI(16)}) -0207 task.printFluxes=true; -0208 end -0209 if ~isempty(raw{2,colI(17)}) -0210 task.comments=raw{2,colI(17)}; -0211 end -0212 -0213 for i=2:size(raw,1) -0214 %Set the inputs -0215 if ischar(raw{i,colI(3)}) -0216 inputs=regexp(raw{i,colI(3)},';','split'); -0217 task.inputs=[task.inputs;inputs(:)]; -0218 task.LBin=[task.LBin;ones(numel(inputs),1)*raw{i,colI(4)}]; -0219 task.UBin=[task.UBin;ones(numel(inputs),1)*raw{i,colI(5)}]; -0220 end -0221 %Set the outputs -0222 if ischar(raw{i,colI(6)}) -0223 outputs=regexp(raw{i,colI(6)},';','split'); -0224 task.outputs=[task.outputs;outputs(:)]; -0225 task.LBout=[task.LBout;ones(numel(outputs),1)*raw{i,colI(7)}]; -0226 task.UBout=[task.UBout;ones(numel(outputs),1)*raw{i,colI(8)}]; -0227 end -0228 %Add new rxns -0229 if ischar(raw{i,colI(9)}) -0230 task.equations=[task.equations;raw{i,colI(9)}]; -0231 if ~isempty(raw{i,colI(10)}) -0232 task.LBequ=[task.LBequ;raw{i,colI(10)}]; -0233 else -0234 if any(strfind(raw{i,colI(9)},'<=>')) -0235 task.LBequ=[task.LBequ;-1000]; -0236 else -0237 task.LBequ=[task.LBequ;0]; -0238 end -0239 end -0240 if ~isempty(raw{i,colI(11)}) -0241 task.UBequ=[task.UBequ;raw{i,colI(11)}]; -0242 else -0243 task.UBequ=[task.UBequ;1000]; -0244 end -0245 end -0246 %Add changed bounds -0247 if ischar(raw{i,colI(12)}) -0248 changed=regexp(raw{i,colI(12)},';','split'); -0249 task.changed=[task.changed;changed(:)]; -0250 task.LBrxn=[task.LBrxn;ones(numel(changed),1)*raw{i,colI(13)}]; -0251 task.UBrxn=[task.UBrxn;ones(numel(changed),1)*raw{i,colI(14)}]; -0252 end -0253 -0254 %Check if it should add more constraints -0255 if i<size(raw,1) -0256 if isempty(raw{i+1,colI(1)}) -0257 continue; -0258 end -0259 end -0260 -0261 taskStruct=[taskStruct;task]; -0262 task=eTask; -0263 if i<size(raw,1) -0264 if isnumeric(raw{i+1,colI(1)}) -0265 task.id=num2str(raw{i+1,colI(1)}); -0266 else -0267 task.id=raw{i+1,colI(1)}; -0268 end -0269 task.description=raw{i+1,colI(2)}; -0270 if ~isempty(raw{i+1,colI(15)}) -0271 task.shouldFail=true; -0272 end -0273 if ~isempty(raw{i+1,colI(16)}) -0274 task.printFluxes=true; -0275 end -0276 if ~isempty(raw{i+1,colI(17)}) -0277 task.comments=raw{i+1,colI(17)}; -0278 end -0279 end -0280 end -0281 -0282 %Should add more checks, such as unique IDs and missing headers -0283 -0284 end

    +0005 % inputFile a task list in either Excel (*.xlsx, with a sheet named +0006 % TASKS with all relevant content) or tab-delimited +0007 % (*.txt) format. The file may contain the following +0008 % column headers (note, all rows starting with a +0009 % non-empty cell are removed. The first row after that +0010 % is considered the headers): +0011 % ID +0012 % the only required header. Each task must have a +0013 % unique id (string or numeric). Tasks can span multiple +0014 % rows, only the first row in each task should have +0015 % an id +0016 % DESCRIPTION +0017 % description of the task +0018 % IN +0019 % allowed input(s) for the task. Metabolite names +0020 % should be on the form +0021 % "model.metName[model.comps]". Several inputs +0022 % can be delimited by ";". If so, then the same +0023 % bounds are used for all inputs. If that is not +0024 % wanted, then use several rows for the task +0025 % IN LB +0026 % lower bound for the uptake of the metabolites in +0027 % the row (optional, default 0 which corresponds to a +0028 % minimal uptake of 0 units) +0029 % IN UB +0030 % upper bound for the uptake of the metabolites in +0031 % the row (optional, default 1000 which corresponds to a +0032 % maximal uptake of 1000 units) +0033 % OUT +0034 % allowed output(s) for the task (see IN) +0035 % OUT LB +0036 % lower bound for the production of the metabolites in +0037 % the row (optional, default 0 which corresponds to a +0038 % minimal production of 0 units) +0039 % OUT UB +0040 % upper bound for the production of the metabolites in +0041 % the row (optional, default 1000 which corresponds to a +0042 % maximal production of 1000 units) +0043 % EQU +0044 % equation to add. The equation should be on the form +0045 % "0.4 A + 2 B <=> (or =>) C" and the metabolites +0046 % should be on the form +0047 % "model.metName[model.comps]" (optional) +0048 % EQU LB +0049 % lower bound for the equation (optional, default -1000 +0050 % for reversible and 0 for irreversible) +0051 % EQU UB +0052 % upper bound for the equation (optional, default 1000) +0053 % CHANGED RXN +0054 % reaction ID for which to change the bounds for. +0055 % Several IDs can be delimited by ";". If so, +0056 % then the same bounds are used for all reactions. If +0057 % that is not wanted, then use several rows for the task +0058 % CHANGED LB +0059 % lower bound for the reaction +0060 % CHANGED UB +0061 % upper bound for the reaction +0062 % SHOULD FAIL +0063 % true if the correct behavior of the model is to +0064 % not have a feasible solution given the constraints +0065 % (optional, default false) +0066 % PRINT FLUX +0067 % true if the function should print the corresponding +0068 % flux distribution for a task. Can be useful for +0069 % testing (optional, default false) +0070 % +0071 % taskStruct array of structures with the following fields +0072 % id the id of the task +0073 % description the description of the task +0074 % shouldFail true if the task should fail +0075 % printFluxes true if the fluxes should be printed +0076 % comments string with comments +0077 % inputs cell array with input metabolites (in the form metName[comps]) +0078 % LBin array with lower bounds on inputs (default, 0) +0079 % UBin array with upper bounds on inputs (default, 1000) +0080 % outputs cell array with output metabolites (in the form metName[comps]) +0081 % LBout array with lower bounds on outputs (default, 0) +0082 % UBout array with upper bounds on outputs (default, 1000) +0083 % equations cell array with equations (with mets in the form metName[comps]) +0084 % LBequ array with lower bounds on equations (default, -1000 for +0085 % reversible and 0 for irreversible) +0086 % UBequ array with upper bounds on equations (default, 1000) +0087 % changed cell array with reactions to change bounds for +0088 % LBrxn array with lower bounds on changed reactions +0089 % UBrxn array with upper bounds on changed reactions +0090 % +0091 % This function is used for defining a set of tasks for a model to +0092 % perform. The tasks are defined by defining constraints on the model, +0093 % and if the problem is feasible, then the task is considered successful. +0094 % In general, each row can contain one constraint on uptakes, one +0095 % constraint on outputs, one new equation, and one change of reaction +0096 % bounds. If more bounds are needed to define the task, then several rows +0097 % can be used for each task. To perform the task use checkTasks or +0098 % fitTasks. +0099 % +0100 % NOTE: The general metabolites "ALLMETS" and "ALLMETSIN[comps]" +0101 % can be used as inputs or outputs in the similar manner to normal +0102 % metabolites. This is a convenient way to, for example, allow excretion of +0103 % all metabolites to check whether it's the synthesis of some metabolite +0104 % that is limiting or whether it's the degradation of some byproduct. One +0105 % important difference is that only the upper bounds are used for these general +0106 % metabolites. That is, you can only say that uptake or excretion is +0107 % allowed, not that it is required. This is to avoid conflicts where the +0108 % constraints for the general metabolites overwrite those of the real +0109 % ones. +0110 % +0111 % Usage: taskStruct=parseTaskList(inputFile) +0112 +0113 if ~isfile(inputFile) +0114 error('Task list %s cannot be found',string(inputFile)); +0115 end +0116 +0117 %Load the tasks file +0118 convNumeric = false; +0119 if strcmp(extractAfter(inputFile,strlength(inputFile) - 4), '.txt') +0120 %load from tab delimited text file +0121 fid = fopen(inputFile); +0122 %Need to read numeric columns as strings, this is converted further +0123 %down. If not, the titles would be lost. +0124 convNumeric = true; +0125 C = textscan(fid,'%q%q%q%q%q%q%q%q%q%q%q%q%q%q%q%q%q%q%q%q%*[^\n]', 'Delimiter', '\t'); +0126 fclose(fid); +0127 raw = [C{:}];%unnest the cell array of cell arrays into a 2-dim cell array +0128 else +0129 [raw,flag]=loadSheet(loadWorkbook(inputFile), 'TASKS'); +0130 if flag~=0 +0131 EM=['Could not load sheet "TASKS" from ' inputFile]; +0132 dispEM(EM); +0133 end +0134 end +0135 +0136 %Remove all lines starting with "#" (or actually any character) and all +0137 %empty columns +0138 raw=cleanSheet(raw); +0139 +0140 %Captions +0141 columns={'ID';'DESCRIPTION';'IN';'IN LB';'IN UB';'OUT';'OUT LB';'OUT UB';'EQU';'EQU LB';'EQU UB';'CHANGED RXN';'CHANGED LB';'CHANGED UB';'SHOULD FAIL';'PRINT FLUX';'COMMENTS'}; +0142 %Match the columns +0143 [I, colI]=ismember(columns,raw(1,:)); +0144 +0145 %If read from a text file, the numbers will be strings - fix that +0146 if convNumeric % in theory, this if should not be needed, the code should do nothing if all are already numeric. But it is kept as a safeguard. +0147 numericColumns = [0 0 0 1 1 0 1 1 0 1 1 0 1 1 0 0 0] == 1; +0148 cols = colI(numericColumns); +0149 numeric = cellfun(@isnumeric,raw(:,cols)); +0150 %trick to avoid messing up the title row: +0151 numeric(1,:) = 1; +0152 for colind = 1:numel(cols) +0153 col = cols(colind); +0154 raw(~numeric(:,colind),col) = cellfun(@str2num, raw(~numeric(:,colind),col), 'UniformOutput', false); +0155 end +0156 end +0157 +0158 %Check that the ID field is present +0159 if I(1)==0 +0160 EM='The TASKS sheet must have a column named ID'; +0161 dispEM(EM); +0162 end +0163 +0164 %make sure numerical fields are converted from strings +0165 +0166 %Add default bounds where needed +0167 for i=[4 5 7 8] +0168 I=cellfun(@isempty,raw(:,colI(i))); +0169 if i==5 || i==8 +0170 raw(I,colI(i))={1000}; +0171 else +0172 raw(I,colI(i))={0}; +0173 end +0174 end +0175 +0176 %Create an empty task structure +0177 eTask.id=''; +0178 eTask.description=''; +0179 eTask.shouldFail=false; +0180 eTask.printFluxes=false; +0181 eTask.comments=''; +0182 eTask.inputs={}; +0183 eTask.LBin=[]; +0184 eTask.UBin=[]; +0185 eTask.outputs={}; +0186 eTask.LBout=[]; +0187 eTask.UBout=[]; +0188 eTask.equations={}; +0189 eTask.LBequ=[]; +0190 eTask.UBequ=[]; +0191 eTask.changed={}; +0192 eTask.LBrxn=[]; +0193 eTask.UBrxn=[]; +0194 +0195 %Main loop +0196 taskStruct=[]; +0197 task=eTask; +0198 if isnumeric(raw{2,colI(1)}) +0199 task.id=num2str(raw{2,colI(1)}); +0200 else +0201 task.id=raw{2,colI(1)}; +0202 end +0203 task.description=raw{2,colI(2)}; +0204 if ~isempty(raw{2,colI(15)}) +0205 task.shouldFail=true; +0206 end +0207 if ~isempty(raw{2,colI(16)}) +0208 task.printFluxes=true; +0209 end +0210 if ~isempty(raw{2,colI(17)}) +0211 task.comments=raw{2,colI(17)}; +0212 end +0213 +0214 for i=2:size(raw,1) +0215 %Set the inputs +0216 if ischar(raw{i,colI(3)}) +0217 inputs=regexp(raw{i,colI(3)},';','split'); +0218 task.inputs=[task.inputs;inputs(:)]; +0219 task.LBin=[task.LBin;ones(numel(inputs),1)*raw{i,colI(4)}]; +0220 task.UBin=[task.UBin;ones(numel(inputs),1)*raw{i,colI(5)}]; +0221 end +0222 %Set the outputs +0223 if ischar(raw{i,colI(6)}) +0224 outputs=regexp(raw{i,colI(6)},';','split'); +0225 task.outputs=[task.outputs;outputs(:)]; +0226 task.LBout=[task.LBout;ones(numel(outputs),1)*raw{i,colI(7)}]; +0227 task.UBout=[task.UBout;ones(numel(outputs),1)*raw{i,colI(8)}]; +0228 end +0229 %Add new rxns +0230 if ischar(raw{i,colI(9)}) +0231 task.equations=[task.equations;raw{i,colI(9)}]; +0232 if ~isempty(raw{i,colI(10)}) +0233 task.LBequ=[task.LBequ;raw{i,colI(10)}]; +0234 else +0235 if any(strfind(raw{i,colI(9)},'<=>')) +0236 task.LBequ=[task.LBequ;-1000]; +0237 else +0238 task.LBequ=[task.LBequ;0]; +0239 end +0240 end +0241 if ~isempty(raw{i,colI(11)}) +0242 task.UBequ=[task.UBequ;raw{i,colI(11)}]; +0243 else +0244 task.UBequ=[task.UBequ;1000]; +0245 end +0246 end +0247 %Add changed bounds +0248 if ischar(raw{i,colI(12)}) +0249 changed=regexp(raw{i,colI(12)},';','split'); +0250 task.changed=[task.changed;changed(:)]; +0251 task.LBrxn=[task.LBrxn;ones(numel(changed),1)*raw{i,colI(13)}]; +0252 task.UBrxn=[task.UBrxn;ones(numel(changed),1)*raw{i,colI(14)}]; +0253 end +0254 +0255 %Check if it should add more constraints +0256 if i<size(raw,1) +0257 if isempty(raw{i+1,colI(1)}) +0258 continue; +0259 end +0260 end +0261 +0262 taskStruct=[taskStruct;task]; +0263 task=eTask; +0264 if i<size(raw,1) +0265 if isnumeric(raw{i+1,colI(1)}) +0266 task.id=num2str(raw{i+1,colI(1)}); +0267 else +0268 task.id=raw{i+1,colI(1)}; +0269 end +0270 task.description=raw{i+1,colI(2)}; +0271 if ~isempty(raw{i+1,colI(15)}) +0272 task.shouldFail=true; +0273 end +0274 if ~isempty(raw{i+1,colI(16)}) +0275 task.printFluxes=true; +0276 end +0277 if ~isempty(raw{i+1,colI(17)}) +0278 task.comments=raw{i+1,colI(17)}; +0279 end +0280 end +0281 end +0282 +0283 %Should add more checks, such as unique IDs and missing headers +0284 +0285 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/predictLocalization.html b/doc/core/predictLocalization.html index 2622161e..8b7b0ddf 100644 --- a/doc/core/predictLocalization.html +++ b/doc/core/predictLocalization.html @@ -726,7 +726,7 @@

    SOURCE CODE ^end 0623 end -0624 outModel.compNames=[outModel.compNames;GSS.compartments(2:end)']; +0624 outModel.compNames=[outModel.compNames;GSS.compartments(2:end)]; 0625 0626 %Ugly little loop 0627 for i=1:numel(GSS.compartments)-1 @@ -831,413 +831,417 @@

    SOURCE CODE ^end 0728 if isfield(outModel,'subSystems') -0729 outModel.subSystems=[outModel.subSystems;{{'Inferred transport reactions'}}]; -0730 end -0731 if isfield(outModel,'eccodes') -0732 outModel.eccodes=[outModel.eccodes;{''}]; -0733 end -0734 if isfield(outModel,'rxnFrom') -0735 outModel.rxnFrom=[outModel.rxnFrom;{''}]; -0736 end -0737 if isfield(outModel,'rxnNotes') -0738 outModel.rxnNotes=[outModel.rxnNotes;{''}]; -0739 end -0740 if isfield(outModel,'rxnReferences') -0741 outModel.rxnReferences=[outModel.rxnReferences;{''}]; -0742 end -0743 if isfield(outModel,'rxnConfidenceScores') -0744 outModel.rxnConfidenceScores=[outModel.rxnConfidenceScores;NaN]; -0745 end -0746 if isfield(outModel,'rxnDeltaG') -0747 outModel.rxnDeltaG=[outModel.rxnDeltaG;NaN]; -0748 end -0749 end -0750 -0751 %Then remove all reactions and metabolites that aren't used in the final -0752 %solution from the optimization -0753 [~, J]=find(bestS(:,1:nER+nComps*nRxns)); -0754 K=true(numel(outModel.rxns),1); -0755 K(J)=false; -0756 K(end-nTransRxns+1:end)=false; -0757 outModel=removeReactions(outModel,K,true); -0758 -0759 %Remove all fake genes -0760 I=strncmp('&&FAKE&&',outModel.genes,8); -0761 outModel.genes(I)=[]; -0762 if isfield(outModel,'geneMiriams') -0763 outModel.geneMiriams(I)=[]; -0764 end -0765 if isfield(outModel,'geneShortNames') -0766 outModel.geneShortNames(I)=[]; -0767 end -0768 if isfield(outModel,'proteins') -0769 outModel.proteins(I)=[]; -0770 end -0771 outModel.rxnGeneMat(:,I)=[]; -0772 -0773 %Fix grRules and reconstruct rxnGeneMat -0774 [grRules,rxnGeneMat] = standardizeGrRules(outModel,true); -0775 outModel.grRules = grRules; -0776 outModel.rxnGeneMat = rxnGeneMat; -0777 end -0778 -0779 %Moves a gene and all associated reactions from one compartment to another -0780 function [S, g2c]=moveGene(S,model,g2c,geneToMove,toComp,nRxns,nMets) -0781 %Find the current compartment and update to the new one -0782 currentComp=find(g2c(geneToMove,:)); -0783 g2c(geneToMove,:)=false; -0784 g2c(geneToMove,toComp)=true; -0785 -0786 %Find the reactions in the original model that the gene controls -0787 [I, ~]=find(model.rxnGeneMat(:,geneToMove)); -0788 -0789 %Calculate their current positions in the S matrix -0790 oldRxns=I+(currentComp-1)*nRxns; -0791 -0792 %And their new positions -0793 newRxns=I+(toComp-1)*nRxns; -0794 -0795 %The metabolite ids also have to be changed in order to match the new -0796 %compartment -0797 metChange=nMets*(toComp-currentComp); +0729 if any(cellfun(@(x) iscell(x), outModel.subSystems)) +0730 outModel.subSystems=[outModel.subSystems;{{'Inferred transport reactions'}}]; +0731 else +0732 outModel.subSystems=[outModel.subSystems;{'Inferred transport reactions'}]; +0733 end +0734 end +0735 if isfield(outModel,'eccodes') +0736 outModel.eccodes=[outModel.eccodes;{''}]; +0737 end +0738 if isfield(outModel,'rxnFrom') +0739 outModel.rxnFrom=[outModel.rxnFrom;{''}]; +0740 end +0741 if isfield(outModel,'rxnNotes') +0742 outModel.rxnNotes=[outModel.rxnNotes;{''}]; +0743 end +0744 if isfield(outModel,'rxnReferences') +0745 outModel.rxnReferences=[outModel.rxnReferences;{''}]; +0746 end +0747 if isfield(outModel,'rxnConfidenceScores') +0748 outModel.rxnConfidenceScores=[outModel.rxnConfidenceScores;NaN]; +0749 end +0750 if isfield(outModel,'rxnDeltaG') +0751 outModel.rxnDeltaG=[outModel.rxnDeltaG;NaN]; +0752 end +0753 end +0754 +0755 %Then remove all reactions and metabolites that aren't used in the final +0756 %solution from the optimization +0757 [~, J]=find(bestS(:,1:nER+nComps*nRxns)); +0758 K=true(numel(outModel.rxns),1); +0759 K(J)=false; +0760 K(end-nTransRxns+1:end)=false; +0761 outModel=removeReactions(outModel,K,true); +0762 +0763 %Remove all fake genes +0764 I=strncmp('&&FAKE&&',outModel.genes,8); +0765 outModel.genes(I)=[]; +0766 if isfield(outModel,'geneMiriams') +0767 outModel.geneMiriams(I)=[]; +0768 end +0769 if isfield(outModel,'geneShortNames') +0770 outModel.geneShortNames(I)=[]; +0771 end +0772 if isfield(outModel,'proteins') +0773 outModel.proteins(I)=[]; +0774 end +0775 outModel.rxnGeneMat(:,I)=[]; +0776 +0777 %Fix grRules and reconstruct rxnGeneMat +0778 [grRules,rxnGeneMat] = standardizeGrRules(outModel,true); +0779 outModel.grRules = grRules; +0780 outModel.rxnGeneMat = rxnGeneMat; +0781 end +0782 +0783 %Moves a gene and all associated reactions from one compartment to another +0784 function [S, g2c]=moveGene(S,model,g2c,geneToMove,toComp,nRxns,nMets) +0785 %Find the current compartment and update to the new one +0786 currentComp=find(g2c(geneToMove,:)); +0787 g2c(geneToMove,:)=false; +0788 g2c(geneToMove,toComp)=true; +0789 +0790 %Find the reactions in the original model that the gene controls +0791 [I, ~]=find(model.rxnGeneMat(:,geneToMove)); +0792 +0793 %Calculate their current positions in the S matrix +0794 oldRxns=I+(currentComp-1)*nRxns; +0795 +0796 %And their new positions +0797 newRxns=I+(toComp-1)*nRxns; 0798 -0799 %Update the reactions -0800 [I, J, K]=find(S(:,oldRxns)); -0801 I=I+metChange; +0799 %The metabolite ids also have to be changed in order to match the new +0800 %compartment +0801 metChange=nMets*(toComp-currentComp); 0802 -0803 %Move the reactions -0804 S(:,oldRxns)=0; -0805 S(sub2ind(size(S),I,newRxns(J)))=K; -0806 end -0807 -0808 %Finds which metabolites are unconnected, in the sense that they are never -0809 %a product or only a product in a reversible reaction where one reactant is -0810 %only a product in the opposite direction of that reaction. This function -0811 %ignores exchange metabolites. Returns a vector of metabolite indexes. -0812 %metsToCheck is an array of metabolite indexes to check for connectivity. -0813 %If not supplied then all metabolites are checked -0814 function unconnected=findUnconnected(S,nEM,metsToCheck) -0815 if nargin>2 -0816 %Do this by deleting everything from the network that is not in -0817 %metsToCheck and that is not exchange metabolites -0818 I=false(size(S,1),1); -0819 I(1:nEM)=true; -0820 I(metsToCheck)=true; -0821 S=S(I,:); -0822 end -0823 -0824 em=false(size(S,1),1); -0825 em(1:nEM)=true; -0826 -0827 %Construct a matrix in which the reversible reactions are inverted -0828 I=sum(S>2,1) | sum(S>2,1); -0829 revS=S; -0830 revS(:,I)=revS(:,I)*-1; -0831 -0832 %First calculate the ones that are ok -0833 %Produced in 2 rxns, is exchange, is not used at all, is produced in -0834 %non-reversible, involved in more than 1 reversible reactions -0835 connected=sum(S>0,2)>1 | em | sum(S~=0,2)==0 | sum(S(:,~I)>0,2)>0 | sum(S(:,I)~=0,2)>1; -0836 -0837 %Then get the ones that are unconnected because they are never produced -0838 unconnected=sum(S>0 | revS>0,2)==0 & connected==false; -0839 -0840 %Then get the ones that are potentially unconnected -0841 maybeUnconnected=~connected & ~unconnected; -0842 %maybeUnconnected=find(maybeUnconnectedS); +0803 %Update the reactions +0804 [I, J, K]=find(S(:,oldRxns)); +0805 I=I+metChange; +0806 +0807 %Move the reactions +0808 S(:,oldRxns)=0; +0809 S(sub2ind(size(S),I,newRxns(J)))=K; +0810 end +0811 +0812 %Finds which metabolites are unconnected, in the sense that they are never +0813 %a product or only a product in a reversible reaction where one reactant is +0814 %only a product in the opposite direction of that reaction. This function +0815 %ignores exchange metabolites. Returns a vector of metabolite indexes. +0816 %metsToCheck is an array of metabolite indexes to check for connectivity. +0817 %If not supplied then all metabolites are checked +0818 function unconnected=findUnconnected(S,nEM,metsToCheck) +0819 if nargin>2 +0820 %Do this by deleting everything from the network that is not in +0821 %metsToCheck and that is not exchange metabolites +0822 I=false(size(S,1),1); +0823 I(1:nEM)=true; +0824 I(metsToCheck)=true; +0825 S=S(I,:); +0826 end +0827 +0828 em=false(size(S,1),1); +0829 em(1:nEM)=true; +0830 +0831 %Construct a matrix in which the reversible reactions are inverted +0832 I=sum(S>2,1) | sum(S>2,1); +0833 revS=S; +0834 revS(:,I)=revS(:,I)*-1; +0835 +0836 %First calculate the ones that are ok +0837 %Produced in 2 rxns, is exchange, is not used at all, is produced in +0838 %non-reversible, involved in more than 1 reversible reactions +0839 connected=sum(S>0,2)>1 | em | sum(S~=0,2)==0 | sum(S(:,~I)>0,2)>0 | sum(S(:,I)~=0,2)>1; +0840 +0841 %Then get the ones that are unconnected because they are never produced +0842 unconnected=sum(S>0 | revS>0,2)==0 & connected==false; 0843 -0844 %The metabolites in maybeUnconnected are involved in one reversible -0845 %reaction and not produced in any other reaction. This means that the -0846 %reactions which have at least one met in maybeUnconnected as reactant and -0847 %one as product are unconnected. The metabolites in maybeUnconnected that -0848 %are present in those reactions are then dead ends -0849 deadRxns=any(S(maybeUnconnected,:)>0) & any(S(maybeUnconnected,:)<0); -0850 -0851 %Get the mets involved in any of those reactions -0852 problematic=any(S(:,deadRxns)~=0,2); -0853 -0854 %If any of these are in the maybeUnconnected list then the metabolite is -0855 %unconnected -0856 unconnected(problematic & maybeUnconnected)=true; +0844 %Then get the ones that are potentially unconnected +0845 maybeUnconnected=~connected & ~unconnected; +0846 %maybeUnconnected=find(maybeUnconnectedS); +0847 +0848 %The metabolites in maybeUnconnected are involved in one reversible +0849 %reaction and not produced in any other reaction. This means that the +0850 %reactions which have at least one met in maybeUnconnected as reactant and +0851 %one as product are unconnected. The metabolites in maybeUnconnected that +0852 %are present in those reactions are then dead ends +0853 deadRxns=any(S(maybeUnconnected,:)>0) & any(S(maybeUnconnected,:)<0); +0854 +0855 %Get the mets involved in any of those reactions +0856 problematic=any(S(:,deadRxns)~=0,2); 0857 -0858 %Map back to metsToCheck -0859 if nargin>2 -0860 unconnected=metsToCheck(unconnected(nEM+1:end)); -0861 else -0862 unconnected=find(unconnected); -0863 end -0864 end -0865 -0866 %Given a set of unconnected metabolites, this function tries to move each -0867 %gene that could connect any of them, calculates the number of newly -0868 %connected metabolites minus the number of newly disconnected metabolites. -0869 %As some metabolites are very connected, only 25 genes are checked. Genes -0870 %that have a low score in their current compartment are more likely to be -0871 %moved -0872 function [geneIndex, moveTo, deltaConnected, deltaScore]=selectGenes(S,nEM,nMets,nER,nRxns,model,unconnected,g2c,GSS) -0873 %If moveTo is 0 then the gene cannot connect any of the metabolites -0874 moveTo=zeros(numel(model.genes),1); -0875 deltaConnected=zeros(numel(model.genes),1); -0876 -0877 %First get where the metabolites are now -0878 nComps=size(g2c,2); -0879 comps=ceil((unconnected-nEM)/((size(S,1)-nEM)/nComps)); +0858 %If any of these are in the maybeUnconnected list then the metabolite is +0859 %unconnected +0860 unconnected(problematic & maybeUnconnected)=true; +0861 +0862 %Map back to metsToCheck +0863 if nargin>2 +0864 unconnected=metsToCheck(unconnected(nEM+1:end)); +0865 else +0866 unconnected=find(unconnected); +0867 end +0868 end +0869 +0870 %Given a set of unconnected metabolites, this function tries to move each +0871 %gene that could connect any of them, calculates the number of newly +0872 %connected metabolites minus the number of newly disconnected metabolites. +0873 %As some metabolites are very connected, only 25 genes are checked. Genes +0874 %that have a low score in their current compartment are more likely to be +0875 %moved +0876 function [geneIndex, moveTo, deltaConnected, deltaScore]=selectGenes(S,nEM,nMets,nER,nRxns,model,unconnected,g2c,GSS) +0877 %If moveTo is 0 then the gene cannot connect any of the metabolites +0878 moveTo=zeros(numel(model.genes),1); +0879 deltaConnected=zeros(numel(model.genes),1); 0880 -0881 %Find the corresponding metabolite indexes if they all were in the default -0882 %compartment -0883 dcIndexes=unique(unconnected-(comps-1)*nMets); +0881 %First get where the metabolites are now +0882 nComps=size(g2c,2); +0883 comps=ceil((unconnected-nEM)/((size(S,1)-nEM)/nComps)); 0884 -0885 %Then find them if they were in any other compartment -0886 allIndexes=dcIndexes; -0887 for i=1:nComps-1 -0888 allIndexes=[allIndexes;dcIndexes+nMets*i]; -0889 end -0890 -0891 %Also check which reversible reactions that could be used -0892 I=sum(S>2,1) | sum(S>2,1); -0893 revS=S; -0894 revS(:,I)=revS(:,I)*-1; -0895 -0896 %Find all reactions that could make any of the unconnected metabolites in -0897 %some other compartment -0898 newMets=setdiff(allIndexes,unconnected); -0899 [~, potential]=find(S(newMets,:)>0 | revS(newMets,:)>0); -0900 potential(potential<=nER | potential>nER+nRxns*nComps)=[]; %No exchange rxns or transport rxns -0901 -0902 %Map J to the real metabolic reactions in model -0903 rxnComps=ceil((potential-nER)/(nRxns)); -0904 -0905 %Find the corresponding reaction indexes if they all were in the default -0906 %compartment -0907 dcRxnIndexes=potential-(rxnComps-1)*nRxns; +0885 %Find the corresponding metabolite indexes if they all were in the default +0886 %compartment +0887 dcIndexes=unique(unconnected-(comps-1)*nMets); +0888 +0889 %Then find them if they were in any other compartment +0890 allIndexes=dcIndexes; +0891 for i=1:nComps-1 +0892 allIndexes=[allIndexes;dcIndexes+nMets*i]; +0893 end +0894 +0895 %Also check which reversible reactions that could be used +0896 I=sum(S>2,1) | sum(S>2,1); +0897 revS=S; +0898 revS(:,I)=revS(:,I)*-1; +0899 +0900 %Find all reactions that could make any of the unconnected metabolites in +0901 %some other compartment +0902 newMets=setdiff(allIndexes,unconnected); +0903 [~, potential]=find(S(newMets,:)>0 | revS(newMets,:)>0); +0904 potential(potential<=nER | potential>nER+nRxns*nComps)=[]; %No exchange rxns or transport rxns +0905 +0906 %Map J to the real metabolic reactions in model +0907 rxnComps=ceil((potential-nER)/(nRxns)); 0908 -0909 %Get the genes for those reactions -0910 genes=find(sum(model.rxnGeneMat(dcRxnIndexes,:)>0,1)); -0911 -0912 %For some cases there can be very many reactions to connect something. This -0913 %is in particular true in the beginning of the optimization if, say, ATP is -0914 %unconnected. Therefore limit the number of genes to be checked to 25. -0915 %Weigh so that genes with bad scores in their current compartment are more -0916 %likely to be moved. -0917 -0918 %Get scores for these genes -0919 [~, J]=find(g2c(genes,:)); -0920 -0921 %Add a small weight so that genes in their best compartment could be moved -0922 %as well -0923 geneScores=GSS.scores(sub2ind(size(g2c),genes(:),J)); -0924 modGeneScores=1.1-geneScores; -0925 if numel(genes)>25 -0926 rGenes=genes(randsample(numel(genes),min(numel(genes),25),true,modGeneScores)); -0927 -0928 %The sampling with weights could give duplicates -0929 rGenes=unique(rGenes); -0930 -0931 %Reorder the geneScores to match -0932 [~, I]=ismember(rGenes,genes); -0933 geneScores=geneScores(I); -0934 genes=rGenes; -0935 end -0936 for i=1:numel(genes) -0937 %Since one gene is moved at a time, only metabolites involved in any of -0938 %the reactions for that gene can become unconnected. This helps to -0939 %speed up the algorithm. First get all involved reactions in the -0940 %default compartment -0941 rxns=find(model.rxnGeneMat(:,genes(i))); -0942 -0943 %Then get their mets -0944 mets=find(sum(model.S(:,rxns)~=0,2)>0); -0945 -0946 %Then get their indexes in all compartments -0947 allIndexes=mets; -0948 for j=1:nComps-1 -0949 allIndexes=[allIndexes;mets+nMets*j]; -0950 end -0951 -0952 %Check which of the unconnected metabolites that these reactions -0953 %correspond to. This could have been done earlier, but it is fast. The -0954 %reversibility check is skipped because it is unlikely to be an issue -0955 %here. Worst case is that the gene is tested once to much -0956 [I, ~]=find(model.S(:,rxns)); -0957 moveToComps=unique(comps(ismember(dcIndexes,I))); -0958 -0959 %Try to move the gene to each of the compartments -0960 bestMove=-inf; -0961 bestComp=[]; -0962 for j=1:numel(moveToComps) -0963 newS=moveGene(S,model,g2c,genes(i),moveToComps(j),nRxns,nMets); -0964 -0965 %Check how many metabolites that are unconnected after moving the -0966 %gene -0967 dConnected=numel(unconnected)-numel(findUnconnected(newS,nEM,[allIndexes;unconnected])); -0968 if dConnected>bestMove -0969 bestMove=dConnected; -0970 bestComp=moveToComps(j); -0971 end -0972 end -0973 -0974 %Add the difference in connectivity and where the genes should be moved -0975 moveTo(genes(i))=bestComp; -0976 deltaConnected(genes(i))=bestMove; -0977 end -0978 -0979 %Finish up -0980 geneIndex=genes(:); -0981 moveTo=moveTo(geneIndex); -0982 deltaConnected=deltaConnected(geneIndex); -0983 deltaScore=GSS.scores(sub2ind(size(g2c),geneIndex(:),moveTo))-geneScores; -0984 end -0985 -0986 %Small function to add a transport reactions between two metabolites. -0987 %Transport reactions are written as having a coefficient 2.0 for both -0988 %reactant and product. This is not a "real" reaction, but since all normal -0989 %reactions have coefficient -1/1 or -10/10 it is a compact way of writing -0990 %it -0991 function S=addTransport(S,nRxns,nER,nMets,nEM,nComps,metA,metB) -0992 mets=[metA;metB]; -0993 %Find the current compartments for the metabolites -0994 comps=ceil((mets-nEM)/((size(S,1)-nEM)/nComps)); -0995 -0996 if sum(comps==1)~=1 -0997 EM='Tried to create a transport reaction from a non-default compartment'; -0998 dispEM(EM); -0999 end -1000 -1001 %Calculate the reaction index -1002 rIndex=(nER+nRxns*nComps)+mets(comps~=1)-nEM-nMets; -1003 -1004 S(mets,rIndex)=2; -1005 end -1006 -1007 %Scores a network based on the localization of the genes and the number of -1008 %transporter reactions used -1009 function [score, geneScore, transportCost]=scoreModel(S,g2c,GSS,transportCost) -1010 [I, J]=find(g2c); -1011 geneScore=sum(GSS.scores(sub2ind(size(g2c),I,J))); -1012 [I, ~]=find(S==2); -1013 I=unique(I); -1014 transportCost=sum(transportCost(I)); -1015 score=geneScore-transportCost; -1016 end -1017 -1018 % To avoid dependency on stats toolbox, use this alternative implementation -1019 % of randsample, source: -1020 % https://github.com/gpeyre/numerical-tours/blob/dacee30081c04ef5f67b26b387ead85f2b193af9/matlab/toolbox_signal/randsample.m -1021 function y = randsample(n, k, replace, w) -1022 %RANDSAMPLE Random sample, with or without replacement. -1023 % Y = RANDSAMPLE(N,K) returns Y as a vector of K values sampled uniformly -1024 % at random, without replacement, from the integers 1:N. -1025 % -1026 % Y = RANDSAMPLE(POPULATION,K) returns K values sampled uniformly at -1027 % random, without replacement, from the values in the vector POPULATION. -1028 % -1029 % Y = RANDSAMPLE(...,REPLACE) returns a sample taken with replacement if -1030 % REPLACE is true, or without replacement if REPLACE is false (the default). -1031 % -1032 % Y = RANDSAMPLE(...,true,W) returns a weighted sample, using positive -1033 % weights W, taken with replacement. W is often a vector of probabilities. -1034 % This function does not support weighted sampling without replacement. +0909 %Find the corresponding reaction indexes if they all were in the default +0910 %compartment +0911 dcRxnIndexes=potential-(rxnComps-1)*nRxns; +0912 +0913 %Get the genes for those reactions +0914 genes=find(sum(model.rxnGeneMat(dcRxnIndexes,:)>0,1)); +0915 +0916 %For some cases there can be very many reactions to connect something. This +0917 %is in particular true in the beginning of the optimization if, say, ATP is +0918 %unconnected. Therefore limit the number of genes to be checked to 25. +0919 %Weigh so that genes with bad scores in their current compartment are more +0920 %likely to be moved. +0921 +0922 %Get scores for these genes +0923 [~, J]=find(g2c(genes,:)); +0924 +0925 %Add a small weight so that genes in their best compartment could be moved +0926 %as well +0927 geneScores=GSS.scores(sub2ind(size(g2c),genes(:),J)); +0928 modGeneScores=1.1-geneScores; +0929 if numel(genes)>25 +0930 rGenes=genes(randsample(numel(genes),min(numel(genes),25),true,modGeneScores)); +0931 +0932 %The sampling with weights could give duplicates +0933 rGenes=unique(rGenes); +0934 +0935 %Reorder the geneScores to match +0936 [~, I]=ismember(rGenes,genes); +0937 geneScores=geneScores(I); +0938 genes=rGenes; +0939 end +0940 for i=1:numel(genes) +0941 %Since one gene is moved at a time, only metabolites involved in any of +0942 %the reactions for that gene can become unconnected. This helps to +0943 %speed up the algorithm. First get all involved reactions in the +0944 %default compartment +0945 rxns=find(model.rxnGeneMat(:,genes(i))); +0946 +0947 %Then get their mets +0948 mets=find(sum(model.S(:,rxns)~=0,2)>0); +0949 +0950 %Then get their indexes in all compartments +0951 allIndexes=mets; +0952 for j=1:nComps-1 +0953 allIndexes=[allIndexes;mets+nMets*j]; +0954 end +0955 +0956 %Check which of the unconnected metabolites that these reactions +0957 %correspond to. This could have been done earlier, but it is fast. The +0958 %reversibility check is skipped because it is unlikely to be an issue +0959 %here. Worst case is that the gene is tested once to much +0960 [I, ~]=find(model.S(:,rxns)); +0961 moveToComps=unique(comps(ismember(dcIndexes,I))); +0962 +0963 %Try to move the gene to each of the compartments +0964 bestMove=-inf; +0965 bestComp=[]; +0966 for j=1:numel(moveToComps) +0967 newS=moveGene(S,model,g2c,genes(i),moveToComps(j),nRxns,nMets); +0968 +0969 %Check how many metabolites that are unconnected after moving the +0970 %gene +0971 dConnected=numel(unconnected)-numel(findUnconnected(newS,nEM,[allIndexes;unconnected])); +0972 if dConnected>bestMove +0973 bestMove=dConnected; +0974 bestComp=moveToComps(j); +0975 end +0976 end +0977 +0978 %Add the difference in connectivity and where the genes should be moved +0979 moveTo(genes(i))=bestComp; +0980 deltaConnected(genes(i))=bestMove; +0981 end +0982 +0983 %Finish up +0984 geneIndex=genes(:); +0985 moveTo=moveTo(geneIndex); +0986 deltaConnected=deltaConnected(geneIndex); +0987 deltaScore=GSS.scores(sub2ind(size(g2c),geneIndex(:),moveTo))-geneScores; +0988 end +0989 +0990 %Small function to add a transport reactions between two metabolites. +0991 %Transport reactions are written as having a coefficient 2.0 for both +0992 %reactant and product. This is not a "real" reaction, but since all normal +0993 %reactions have coefficient -1/1 or -10/10 it is a compact way of writing +0994 %it +0995 function S=addTransport(S,nRxns,nER,nMets,nEM,nComps,metA,metB) +0996 mets=[metA;metB]; +0997 %Find the current compartments for the metabolites +0998 comps=ceil((mets-nEM)/((size(S,1)-nEM)/nComps)); +0999 +1000 if sum(comps==1)~=1 +1001 EM='Tried to create a transport reaction from a non-default compartment'; +1002 dispEM(EM); +1003 end +1004 +1005 %Calculate the reaction index +1006 rIndex=(nER+nRxns*nComps)+mets(comps~=1)-nEM-nMets; +1007 +1008 S(mets,rIndex)=2; +1009 end +1010 +1011 %Scores a network based on the localization of the genes and the number of +1012 %transporter reactions used +1013 function [score, geneScore, transportCost]=scoreModel(S,g2c,GSS,transportCost) +1014 [I, J]=find(g2c); +1015 geneScore=sum(GSS.scores(sub2ind(size(g2c),I,J))); +1016 [I, ~]=find(S==2); +1017 I=unique(I); +1018 transportCost=sum(transportCost(I)); +1019 score=geneScore-transportCost; +1020 end +1021 +1022 % To avoid dependency on stats toolbox, use this alternative implementation +1023 % of randsample, source: +1024 % https://github.com/gpeyre/numerical-tours/blob/dacee30081c04ef5f67b26b387ead85f2b193af9/matlab/toolbox_signal/randsample.m +1025 function y = randsample(n, k, replace, w) +1026 %RANDSAMPLE Random sample, with or without replacement. +1027 % Y = RANDSAMPLE(N,K) returns Y as a vector of K values sampled uniformly +1028 % at random, without replacement, from the integers 1:N. +1029 % +1030 % Y = RANDSAMPLE(POPULATION,K) returns K values sampled uniformly at +1031 % random, without replacement, from the values in the vector POPULATION. +1032 % +1033 % Y = RANDSAMPLE(...,REPLACE) returns a sample taken with replacement if +1034 % REPLACE is true, or without replacement if REPLACE is false (the default). 1035 % -1036 % Example: Generate a random sequence of the characters ACGT, with -1037 % replacement, according to specified probabilities. -1038 % -1039 % R = randsample('ACGT',48,true,[0.15 0.35 0.35 0.15]) -1040 % -1041 % See also RAND, RANDPERM. -1042 -1043 % Copyright 1993-2008 The MathWorks, Inc. -1044 % $Revision: 1.1.4.3 $ $Date: 2008/12/01 08:09:34 $ -1045 -1046 if nargin < 2 -1047 error('stats:randsample:TooFewInputs','Requires two input arguments.'); -1048 elseif numel(n) == 1 -1049 population = []; -1050 else -1051 population = n; -1052 n = numel(population); -1053 if length(population)~=n -1054 error('stats:randsample:BadPopulation','POPULATION must be a vector.'); -1055 end -1056 end -1057 -1058 if nargin < 3 -1059 replace = false; +1036 % Y = RANDSAMPLE(...,true,W) returns a weighted sample, using positive +1037 % weights W, taken with replacement. W is often a vector of probabilities. +1038 % This function does not support weighted sampling without replacement. +1039 % +1040 % Example: Generate a random sequence of the characters ACGT, with +1041 % replacement, according to specified probabilities. +1042 % +1043 % R = randsample('ACGT',48,true,[0.15 0.35 0.35 0.15]) +1044 % +1045 % See also RAND, RANDPERM. +1046 +1047 % Copyright 1993-2008 The MathWorks, Inc. +1048 % $Revision: 1.1.4.3 $ $Date: 2008/12/01 08:09:34 $ +1049 +1050 if nargin < 2 +1051 error('stats:randsample:TooFewInputs','Requires two input arguments.'); +1052 elseif numel(n) == 1 +1053 population = []; +1054 else +1055 population = n; +1056 n = numel(population); +1057 if length(population)~=n +1058 error('stats:randsample:BadPopulation','POPULATION must be a vector.'); +1059 end 1060 end 1061 -1062 if nargin < 4 -1063 w = []; -1064 elseif ~isempty(w) -1065 if length(w) ~= n -1066 if isempty(population) -1067 error('stats:randsample:InputSizeMismatch',... -1068 'W must have length equal to N.'); -1069 else -1070 error('stats:randsample:InputSizeMismatch',... -1071 'W must have the same length as the population.'); -1072 end -1073 else -1074 p = w(:)' / sum(w); -1075 end -1076 end -1077 -1078 switch replace -1079 -1080 % Sample with replacement -1081 case {true, 'true', 1} -1082 if isempty(w) -1083 y = ceil(n .* rand(k,1)); -1084 else -1085 [dum, y] = histc(rand(k,1),[0 cumsum(p)]); -1086 end -1087 -1088 % Sample without replacement -1089 case {false, 'false', 0} -1090 if k > n -1091 if isempty(population) -1092 error('stats:randsample:SampleTooLarge',... -1093 'K must be less than or equal to N for sampling without replacement.'); -1094 else -1095 error('stats:randsample:SampleTooLarge',... -1096 'K must be less than or equal to the population size.'); -1097 end -1098 end -1099 -1100 if isempty(w) -1101 % If the sample is a sizeable fraction of the population, -1102 % just randomize the whole population (which involves a full -1103 % sort of n random values), and take the first k. -1104 if 4*k > n -1105 rp = randperm(n); -1106 y = rp(1:k); -1107 -1108 % If the sample is a small fraction of the population, a full sort -1109 % is wasteful. Repeatedly sample with replacement until there are -1110 % k unique values. -1111 else -1112 x = zeros(1,n); % flags -1113 sumx = 0; -1114 while sumx < k -1115 x(ceil(n * rand(1,k-sumx))) = 1; % sample w/replacement -1116 sumx = sum(x); % count how many unique elements so far -1117 end -1118 y = find(x > 0); -1119 y = y(randperm(k)); -1120 end -1121 else -1122 error('stats:randsample:NoWeighting',... -1123 'Weighted sampling without replacement is not supported.'); -1124 end -1125 otherwise -1126 error('stats:randsample:BadReplaceValue',... -1127 'REPLACE must be either true or false.'); -1128 end -1129 -1130 if ~isempty(population) -1131 y = population(y); -1132 else -1133 y = y(:); -1134 end -1135 end +1062 if nargin < 3 +1063 replace = false; +1064 end +1065 +1066 if nargin < 4 +1067 w = []; +1068 elseif ~isempty(w) +1069 if length(w) ~= n +1070 if isempty(population) +1071 error('stats:randsample:InputSizeMismatch',... +1072 'W must have length equal to N.'); +1073 else +1074 error('stats:randsample:InputSizeMismatch',... +1075 'W must have the same length as the population.'); +1076 end +1077 else +1078 p = w(:)' / sum(w); +1079 end +1080 end +1081 +1082 switch replace +1083 +1084 % Sample with replacement +1085 case {true, 'true', 1} +1086 if isempty(w) +1087 y = ceil(n .* rand(k,1)); +1088 else +1089 [dum, y] = histc(rand(k,1),[0 cumsum(p)]); +1090 end +1091 +1092 % Sample without replacement +1093 case {false, 'false', 0} +1094 if k > n +1095 if isempty(population) +1096 error('stats:randsample:SampleTooLarge',... +1097 'K must be less than or equal to N for sampling without replacement.'); +1098 else +1099 error('stats:randsample:SampleTooLarge',... +1100 'K must be less than or equal to the population size.'); +1101 end +1102 end +1103 +1104 if isempty(w) +1105 % If the sample is a sizeable fraction of the population, +1106 % just randomize the whole population (which involves a full +1107 % sort of n random values), and take the first k. +1108 if 4*k > n +1109 rp = randperm(n); +1110 y = rp(1:k); +1111 +1112 % If the sample is a small fraction of the population, a full sort +1113 % is wasteful. Repeatedly sample with replacement until there are +1114 % k unique values. +1115 else +1116 x = zeros(1,n); % flags +1117 sumx = 0; +1118 while sumx < k +1119 x(ceil(n * rand(1,k-sumx))) = 1; % sample w/replacement +1120 sumx = sum(x); % count how many unique elements so far +1121 end +1122 y = find(x > 0); +1123 y = y(randperm(k)); +1124 end +1125 else +1126 error('stats:randsample:NoWeighting',... +1127 'Weighted sampling without replacement is not supported.'); +1128 end +1129 otherwise +1130 error('stats:randsample:BadReplaceValue',... +1131 'REPLACE must be either true or false.'); +1132 end +1133 +1134 if ~isempty(population) +1135 y = population(y); +1136 else +1137 y = y(:); +1138 end +1139 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/setParam.html b/doc/core/setParam.html index 96f0a107..31319787 100644 --- a/doc/core/setParam.html +++ b/doc/core/setParam.html @@ -140,7 +140,7 @@

    SOURCE CODE ^dispEM('Reactions not present in model, will be ignored:',false,rxnLise(~Lia)); +0071 dispEM('Reactions not present in model, will be ignored:',false,rxnList(~Lia)); 0072 end 0073 0074 %Change the parameters diff --git a/doc/core/sortModel.html b/doc/core/sortModel.html index 9033f9dc..b14269df 100644 --- a/doc/core/sortModel.html +++ b/doc/core/sortModel.html @@ -127,120 +127,123 @@

    SOURCE CODE ^''; 0066 subsystemsConcatenated=''; 0067 for i=1:numel(model.subSystems) -0068 subsystemsConcatenated{i,1}=strjoin(model.subSystems{i,1},';'); -0069 if ~isempty(model.subSystems{i,1}) -0070 for j=1:numel(model.subSystems{i,1}) -0071 subsystemsUnique{numel(subsystemsUnique)+1,1}=model.subSystems{i,1}{1,j}; -0072 end -0073 end -0074 end -0075 subsystemsUnique=unique(subsystemsUnique); -0076 for i=1:numel(subsystemsUnique) -0077 %Get all reactions for that subsystem -0078 rxns=find(~cellfun(@isempty,regexp(subsystemsConcatenated,subsystemsUnique(i)))); -0079 -0080 %Temporarily ignore large subsystems because of inefficient -0081 %implementation -0082 if numel(rxns)<2 || numel(rxns)>250 -0083 continue; -0084 end -0085 -0086 nRxns=numel(rxns); -0087 revRxns=rxns(model.rev(rxns)~=0); +0068 if ~iscell(model.subSystems{i}) +0069 model.subSystems{i} = {model.subSystems{i}}; +0070 end +0071 subsystemsConcatenated{i,1}=strjoin(model.subSystems{i,1},';'); +0072 if ~isempty(model.subSystems{i,1}) +0073 for j=1:numel(model.subSystems{i,1}) +0074 subsystemsUnique{numel(subsystemsUnique)+1,1}=model.subSystems{i,1}{1,j}; +0075 end +0076 end +0077 end +0078 subsystemsUnique=unique(subsystemsUnique); +0079 for i=1:numel(subsystemsUnique) +0080 %Get all reactions for that subsystem +0081 rxns=find(~cellfun(@isempty,regexp(subsystemsConcatenated,subsystemsUnique(i)))); +0082 +0083 %Temporarily ignore large subsystems because of inefficient +0084 %implementation +0085 if numel(rxns)<2 || numel(rxns)>250 +0086 continue; +0087 end 0088 -0089 %This variable will hold the current reversibility directions of -0090 %the reversible reactions. 1 means the same direction as in the -0091 %original model and -1 means the opposite direction. -0092 oldRev=ones(numel(revRxns),1); -0093 -0094 %The problem could probably be solved analytically but a simple -0095 %random method is implemented here instead. Two reactions are -0096 %chosen randomly and their positions are switched. A score is -0097 %calculated based on the number of metabolites that are produced -0098 %before they are consumed. If the perturbed model has a better or -0099 %equal score than the original the reaction order is switched. If -0100 %no increase in score has been seen after 1000*rxnsInSubsystem then -0101 %the optimization is terminated -0102 -0103 rxnOrder=1:nRxns; -0104 oldScore=-inf; -0105 counter=0; -0106 firstIter=true; -0107 while 1==1 -0108 counter=counter+1; -0109 if counter==100*nRxns -0110 break; -0111 end -0112 -0113 newRxnOrder=rxnOrder; -0114 rev=oldRev; +0089 nRxns=numel(rxns); +0090 revRxns=rxns(model.rev(rxns)~=0); +0091 +0092 %This variable will hold the current reversibility directions of +0093 %the reversible reactions. 1 means the same direction as in the +0094 %original model and -1 means the opposite direction. +0095 oldRev=ones(numel(revRxns),1); +0096 +0097 %The problem could probably be solved analytically but a simple +0098 %random method is implemented here instead. Two reactions are +0099 %chosen randomly and their positions are switched. A score is +0100 %calculated based on the number of metabolites that are produced +0101 %before they are consumed. If the perturbed model has a better or +0102 %equal score than the original the reaction order is switched. If +0103 %no increase in score has been seen after 1000*rxnsInSubsystem then +0104 %the optimization is terminated +0105 +0106 rxnOrder=1:nRxns; +0107 oldScore=-inf; +0108 counter=0; +0109 firstIter=true; +0110 while 1==1 +0111 counter=counter+1; +0112 if counter==100*nRxns +0113 break; +0114 end 0115 -0116 if firstIter==false -0117 y=randperm(nRxns,2); -0118 -0119 %Switch the order -0120 newRxnOrder(y(1))=rxnOrder(y(2)); -0121 newRxnOrder(y(2))=rxnOrder(y(1)); -0122 -0123 %With a 50% chance, also switch the reversibility of one of -0124 %the reactions -0125 if rand()>0.5 && numel(rev)>1 -0126 n=randperm(numel(rev),1); -0127 rev(n)=rev(n)*-1; -0128 end -0129 end -0130 firstIter=false; -0131 -0132 tempS=model.S; -0133 -0134 %Switch the directionalities -0135 for j=1:numel(rev) -0136 if rev(j)==-1 -0137 tempS(:,revRxns(j))=tempS(:,revRxns(j)).*-1; -0138 end -0139 end -0140 -0141 %Get the metabolites that are involved and when they are -0142 %produced/consumed -0143 s=tempS(:,newRxnOrder); -0144 -0145 %Remove mets that aren't used in both directions -0146 s=s(any(s,2),:); +0116 newRxnOrder=rxnOrder; +0117 rev=oldRev; +0118 +0119 if firstIter==false +0120 y=randperm(nRxns,2); +0121 +0122 %Switch the order +0123 newRxnOrder(y(1))=rxnOrder(y(2)); +0124 newRxnOrder(y(2))=rxnOrder(y(1)); +0125 +0126 %With a 50% chance, also switch the reversibility of one of +0127 %the reactions +0128 if rand()>0.5 && numel(rev)>1 +0129 n=randperm(numel(rev),1); +0130 rev(n)=rev(n)*-1; +0131 end +0132 end +0133 firstIter=false; +0134 +0135 tempS=model.S; +0136 +0137 %Switch the directionalities +0138 for j=1:numel(rev) +0139 if rev(j)==-1 +0140 tempS(:,revRxns(j))=tempS(:,revRxns(j)).*-1; +0141 end +0142 end +0143 +0144 %Get the metabolites that are involved and when they are +0145 %produced/consumed +0146 s=tempS(:,newRxnOrder); 0147 -0148 %Add so that all mets are produced and consumed in the end -0149 s=[s ones(size(s,1),1) ones(size(s,1),1)*-1]; +0148 %Remove mets that aren't used in both directions +0149 s=s(any(s,2),:); 0150 -0151 %For each metabolite, find the reaction where it's first -0152 %produced and the reaction where it's first consumed -0153 s1=s>0; -0154 r1=arrayfun(@(x) find(s1(x,:),1,'first'),1:size(s1,1)); -0155 s2=s<0; -0156 r2=arrayfun(@(x) find(s2(x,:),1,'first'),1:size(s2,1)); -0157 -0158 score=sum(r1<r2); -0159 -0160 if score>=oldScore -0161 if score>oldScore -0162 counter=0; -0163 end -0164 oldScore=score; -0165 oldRev=rev; -0166 rxnOrder=newRxnOrder; -0167 end -0168 end -0169 -0170 %Update the model for this subsystem -0171 for j=1:numel(oldRev) -0172 if oldRev(j)==-1 -0173 model.S(:,revRxns(j))=model.S(:,revRxns(j)).*-1; -0174 end -0175 end -0176 order=1:numel(model.rxns); -0177 order(rxns)=rxns(rxnOrder); -0178 model=permuteModel(model, order, 'rxns'); -0179 end -0180 end -0181 end +0151 %Add so that all mets are produced and consumed in the end +0152 s=[s ones(size(s,1),1) ones(size(s,1),1)*-1]; +0153 +0154 %For each metabolite, find the reaction where it's first +0155 %produced and the reaction where it's first consumed +0156 s1=s>0; +0157 r1=arrayfun(@(x) find(s1(x,:),1,'first'),1:size(s1,1)); +0158 s2=s<0; +0159 r2=arrayfun(@(x) find(s2(x,:),1,'first'),1:size(s2,1)); +0160 +0161 score=sum(r1<r2); +0162 +0163 if score>=oldScore +0164 if score>oldScore +0165 counter=0; +0166 end +0167 oldScore=score; +0168 oldRev=rev; +0169 rxnOrder=newRxnOrder; +0170 end +0171 end +0172 +0173 %Update the model for this subsystem +0174 for j=1:numel(oldRev) +0175 if oldRev(j)==-1 +0176 model.S(:,revRxns(j))=model.S(:,revRxns(j)).*-1; +0177 end +0178 end +0179 order=1:numel(model.rxns); +0180 order(rxns)=rxns(rxnOrder); +0181 model=permuteModel(model, order, 'rxns'); +0182 end +0183 end +0184 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/core/standardizeGrRules.html b/doc/core/standardizeGrRules.html index b9cb023f..b58d66bd 100644 --- a/doc/core/standardizeGrRules.html +++ b/doc/core/standardizeGrRules.html @@ -56,7 +56,7 @@

    CROSS-REFERENCE INFORMATION ^
 </ul>
 This function is called by:
 <ul style= -
  • addRxns addRxns
  • changeGrRules changeGrRules
  • contractModel contractModel
  • expandModel expandModel
  • getModelFromHomology getModelFromHomology
  • mergeModels mergeModels
  • predictLocalization predictLocalization
  • removeGenes removeGenes
  • +
  • addRxns addRxns
  • changeGrRules changeGrRules
  • contractModel contractModel
  • expandModel expandModel
  • getModelFromHomology getModelFromHomology
  • mergeModels mergeModels
  • predictLocalization predictLocalization
  • removeGenes removeGenes
  • SUBFUNCTIONS ^

    diff --git a/doc/external/kegg/getKEGGModelForOrganism.html b/doc/external/kegg/getKEGGModelForOrganism.html index e5ec6a91..843e4b45 100644 --- a/doc/external/kegg/getKEGGModelForOrganism.html +++ b/doc/external/kegg/getKEGGModelForOrganism.html @@ -63,7 +63,7 @@

    DESCRIPTION ^DESCRIPTION ^SOURCE CODE ^% The hidden Markov models as generated in 2b or 0039 % downloaded from BioMet Toolbox (see below) 0040 % The final directory in dataDir should be styled as -0041 % prok90_kegg105 or euk90_kegg105, indicating whether +0041 % prok90_kegg116 or euk90_kegg116, indicating whether 0042 % the HMMs were trained on pro- or eukaryotic 0043 % sequences; using which sequence similarity treshold 0044 % (first set of digits); using which KEGG version @@ -543,36 +543,36 @@

    SOURCE CODE ^else 0260 outDir=char(outDir); 0261 end -0262 if nargin<5 +0262 if nargin<5 || isempty(keepSpontaneous) 0263 keepSpontaneous=true; 0264 end -0265 if nargin<6 +0265 if nargin<6 || isempty(keepUndefinedStoich) 0266 keepUndefinedStoich=true; 0267 end -0268 if nargin<7 +0268 if nargin<7 || isempty(keepIncomplete) 0269 keepIncomplete=true; 0270 end -0271 if nargin<8 +0271 if nargin<8 || isempty(keepGeneral) 0272 keepGeneral=false; 0273 end -0274 if nargin<9 +0274 if nargin<9 || isempty(cutOff) 0275 cutOff=10^-50; 0276 end -0277 if nargin<10 +0277 if nargin<10 || isempty(minScoreRatioKO) 0278 minScoreRatioKO=0.3; 0279 end -0280 if nargin<11 +0280 if nargin<11 || isempty(minScoreRatioG) 0281 minScoreRatioG=0.8; 0282 end -0283 if nargin<12 +0283 if nargin<12 || isempty(maxPhylDist) 0284 maxPhylDist=inf; 0285 %Include all sequences for each reaction 0286 end -0287 if nargin<13 +0287 if nargin<13 || isempty(nSequences) 0288 nSequences=inf; 0289 %Include all sequences for each reaction 0290 end -0291 if nargin<14 +0291 if nargin<14 || isempty(seqIdentity) 0292 seqIdentity=0.9; 0293 end 0294 @@ -599,9 +599,9 @@

    SOURCE CODE ^%required zip file already in working directory or have it extracted. If 0316 %the zip file and directory is not here, it is downloaded from the cloud 0317 if ~isempty(dataDir) -0318 hmmOptions={'euk90_kegg105','prok90_kegg105'}; +0318 hmmOptions={'euk90_kegg116','prok90_kegg116'}; 0319 if ~endsWith(dataDir,hmmOptions) %Check if dataDir ends with any of the hmmOptions. -0320 %If not, then check whether the required folders exist anyway. +0320 %If not, then check whether the required folders exist anyway. 0321 if ~isfile(fullfile(dataDir,'keggdb','genes.pep')) && ... 0322 ~isfolder(fullfile(dataDir,'fasta')) && ... 0323 ~isfolder(fullfile(dataDir,'aligned')) && ... @@ -618,19 +618,19 @@

    SOURCE CODE ^else 0335 hmmIndex=strcmp(dataDir,hmmOptions); 0336 if ~any(hmmIndex) -0337 error(['Pre-trained HMMs are only provided with proteins clustered at 90% sequence identity (i.e. prok90_kegg105 and euk90_kegg105). ' ... +0337 error(['Pre-trained HMMs are only provided with proteins clustered at 90% sequence identity (i.e. prok90_kegg116 and euk90_kegg116). ' ... 0338 'Use either of these datasets, or otherwise download the relevant sequence data from KEGG to train HMMs with your desired sequence identity']) 0339 else 0340 fprintf('Downloading the HMMs archive file... '); 0341 try -0342 websave([dataDir,'.zip'],['https://github.com/SysBioChalmers/RAVEN/releases/download/v2.8.0/',hmmOptions{hmmIndex},'.zip']); +0342 websave([dataDir,'.zip'],['https://github.com/SysBioChalmers/RAVEN/releases/download/v2.11.0/',hmmOptions{hmmIndex},'.zip']); 0343 catch ME 0344 if strcmp(ME.identifier,'MATLAB:webservices:HTTP404StatusCodeError') 0345 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') 0346 end 0347 end 0348 end -0349 +0349 0350 fprintf('COMPLETE\n'); 0351 fprintf('Extracting the HMMs archive file... '); 0352 unzip([dataDir,'.zip']); @@ -690,7 +690,7 @@

    SOURCE CODE ^if ~ismember(organismID,[phylDistsFull.ids 'eukaryotes' 'prokaryotes']) 0407 error('Provided organismID is incorrect. Only species abbreviations from KEGG Species List or "eukaryotes"/"prokaryotes" are allowed.'); 0408 end -0409 +0409 0410 fprintf(['Pruning the model from <strong>non-' organismID '</strong> genes... ']); 0411 if ismember(organismID,{'eukaryotes','prokaryotes'}) 0412 phylDists=getPhylDist(fullfile(dataDir,'keggdb'),maxPhylDist==-1); @@ -836,496 +836,507 @@

    SOURCE CODE ^return 0553 end 0554 -0555 %Check if alignment of FASTA files should be performed -0556 missingAligned=setdiff(KOModel.rxns,[alignedFiles;hmmFiles;alignedWorking;outFiles]); -0557 if ~isempty(missingAligned) -0558 if seqIdentity==-1 -0559 fprintf('Performing the multiple alignment for KEGG Orthology specific protein sets... 0%% complete'); -0560 else -0561 fprintf('Performing clustering and multiple alignment for KEGG Orthology specific protein sets... 0%% complete'); -0562 end -0563 missingAligned=missingAligned(randperm(RandStream.create('mrg32k3a','Seed',cputime()),numel(missingAligned))); -0564 tmpFile=tempname; -0565 %On Windows, paths need to be translated to Unix before parsing it to WSL -0566 if ispc -0567 wslPath.tmpFile=getWSLpath(tmpFile); -0568 %mafft has problems writing to terminal (/dev/stderr) when running -0569 %on WSL via MATLAB, instead write and read progress file -0570 mafftOutput = tempname; -0571 wslPath.mafftOutput=getWSLpath(mafftOutput); -0572 wslPath.mafft=getWSLpath(fullfile(ravenPath,'software','mafft','mafft-linux64','mafft.bat')); -0573 wslPath.cdhit=getWSLpath(fullfile(ravenPath,'software','cd-hit','cd-hit')); -0574 end -0575 -0576 for i=1:numel(missingAligned) -0577 %This is checked here because it could be that it is created by a -0578 %parallel process. The faw-files are saved as temporary files to -0579 %kept track of which files are being worked on -0580 if ~isfile(fullfile(dataDir,'aligned',[missingAligned{i} '.faw'])) &&... -0581 ~isfile(fullfile(dataDir,'aligned',[missingAligned{i} '.fa'])) -0582 %Check that the multi-FASTA file exists. It should do so since -0583 %we are saving empty files as well. Print a warning and -0584 %continue if not -0585 if ~isfile(fullfile(dataDir,'fasta',[missingAligned{i} '.fa'])) -0586 EM=['WARNING: The multi-FASTA file for ' missingAligned{i} ' does not exist']; -0587 dispEM(EM,false); -0588 continue; -0589 end -0590 -0591 %If the multi-FASTA file is empty then save an empty aligned -0592 %file and continue -0593 s=dir(fullfile(dataDir,'fasta',[missingAligned{i} '.fa'])); -0594 if s.bytes<=0 -0595 fid=fopen(fullfile(dataDir,'aligned',[missingAligned{i} '.fa']),'w'); -0596 fclose(fid); -0597 continue; -0598 end -0599 -0600 %Create an empty file to prevent other threads to start to work -0601 %on the same alignment -0602 fid=fopen(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),'w'); -0603 fclose(fid); -0604 -0605 %First load the FASTA file, then select up to nSequences -0606 %sequences of the most closely related species, apply any -0607 %constraints from maxPhylDist, and save it as a temporary file, -0608 %and create the model from that -0609 -0610 fastaStruct=fastaread(fullfile(dataDir,'fasta',[missingAligned{i} '.fa'])); -0611 phylDist=inf(numel(fastaStruct),1); -0612 for j=1:numel(fastaStruct) -0613 %Get the organism abbreviation -0614 index=strfind(fastaStruct(j).Header,':'); -0615 if any(index) -0616 abbrev=fastaStruct(j).Header(1:index(1)-1); -0617 [~, index]=ismember(abbrev,phylDistStruct.ids); -0618 if any(index) -0619 phylDist(j)=phylDistStruct.distMat(index(1),phylDistId); -0620 end -0621 end -0622 end -0623 -0624 %Inf means that it should not be included -0625 phylDist(phylDist>maxPhylDist)=[]; -0626 -0627 %Sort based on phylDist -0628 [~, order]=sort(phylDist); -0629 -0630 %Save the first nSequences hits to a temporary FASTA file -0631 if nSequences<=numel(fastaStruct) -0632 fastaStruct=fastaStruct(order(1:nSequences)); -0633 else -0634 fastaStruct=fastaStruct(order); -0635 end -0636 -0637 %Do the clustering and alignment if there are more than one -0638 %sequences, otherwise just save the sequence (or an empty file) -0639 if numel(fastaStruct)>1 -0640 if seqIdentity~=-1 -0641 cdhitInpCustom=tempname; -0642 fastawrite(cdhitInpCustom,fastaStruct); -0643 if seqIdentity<=1 && seqIdentity>0.7 -0644 nparam='5'; -0645 elseif seqIdentity>0.6 -0646 nparam='4'; -0647 elseif seqIdentity>0.5 -0648 nparam='3'; -0649 elseif seqIdentity>0.4 -0650 nparam='2'; -0651 else -0652 EM='The provided seqIdentity must be between 0 and 1\n'; -0653 dispEM(EM); -0654 end -0655 if ispc -0656 wslPath.cdhitInpCustom=getWSLpath(cdhitInpCustom); -0657 [status, output]=system(['wsl "' wslPath.cdhit '" -T "' num2str(cores) '" -i "' wslPath.cdhitInpCustom '" -o "' wslPath.tmpFile '" -c "' num2str(seqIdentity) '" -n ' nparam ' -M 2000']); -0658 elseif ismac || isunix -0659 [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']); -0660 end -0661 if status~=0 -0662 EM=['Error when performing clustering of ' missingAligned{i} ':\n' output]; -0663 dispEM(EM); -0664 end -0665 %Remove the old tempfile -0666 if exist(cdhitInpCustom, 'file') -0667 delete([cdhitInpCustom '*']); -0668 end -0669 else -0670 %This means that CD-HIT should be skipped since -0671 %seqIdentity is equal to -1 -0672 fastawrite(tmpFile,fastaStruct); -0673 end -0674 %Do the alignment for this file -0675 if ismac -0676 [status, output]=system(['"' fullfile(ravenPath,'software','mafft','mafft-mac','mafft.bat') '" --auto --anysymbol --thread "' num2str(cores) '" "' tmpFile '" > "' fullfile(dataDir,'aligned',[missingAligned{i} '.faw']) '"']); -0677 elseif isunix -0678 [status, output]=system(['"' fullfile(ravenPath,'software','mafft','mafft-linux64','mafft.bat') '" --auto --anysymbol --thread "' num2str(cores) '" "' tmpFile '" > "' fullfile(dataDir,'aligned',[missingAligned{i} '.faw']) '"']); -0679 elseif ispc -0680 wslPath.fawFile=getWSLpath(fullfile(dataDir,'aligned',[missingAligned{i} '.faw'])); -0681 [status, ~]=system(['wsl "' wslPath.mafft '" --auto --anysymbol --progress "' wslPath.mafftOutput '" --thread "' num2str(cores) '" --out "' wslPath.fawFile '" "' wslPath.tmpFile '"']); -0682 output=fileread(mafftOutput); -0683 delete(mafftOutput); -0684 end -0685 if status~=0 -0686 %It could be that alignment failed because only one -0687 %sequence was left after clustering. If that is the -0688 %case, then the clustered file is just copied as 'faw' -0689 %file -0690 if any(regexp(output,'Only 1 sequence found')) -0691 movefile(tmpFile,fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),'f'); -0692 else -0693 EM=['Error when performing alignment of ' missingAligned{i} ':\n' output]; -0694 dispEM(EM); -0695 end -0696 end -0697 %Remove the old tempfile -0698 if exist(tmpFile, 'file') -0699 delete([tmpFile '*']); -0700 end -0701 else -0702 %If there is only one sequence then it's not possible to do -0703 %a multiple alignment. Just print the sequence instead. An -0704 %empty file was written previously so that doesn't have to -0705 %be dealt with -0706 if numel(fastaStruct)==1 -0707 warnState = warning; %Save the current warning state -0708 warning('off','Bioinfo:fastawrite:AppendToFile'); -0709 fastawrite(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),fastaStruct); -0710 warning(warnState) %Reset warning state to previous settings -0711 end -0712 end -0713 %Move the temporary file to the real one -0714 movefile(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),fullfile(dataDir,'aligned',[missingAligned{i} '.fa']),'f'); -0715 -0716 %Print the progress every 25 files -0717 if rem(i-1,25) == 0 -0718 progress=num2str(floor(100*numel(listFiles(fullfile(dataDir,'aligned','*.fa')))/numel(KOModel.rxns))); -0719 progress=pad(progress,3,'left'); -0720 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); -0721 end -0722 end -0723 end -0724 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); -0725 else -0726 if seqIdentity==-1 -0727 fprintf('Performing the multiple alignment for KEGG Orthology specific protein sets... COMPLETE\n'); -0728 else -0729 fprintf('Performing clustering and multiple alignment for KEGG Orthology specific protein sets... COMPLETE\n'); -0730 end -0731 end -0732 -0733 %Check if training of Hidden Markov models should be performed -0734 missingHMMs=setdiff(KOModel.rxns,[hmmFiles;outFiles]); -0735 if ~isempty(missingHMMs) -0736 fprintf('Training the KEGG Orthology specific HMMs... 0%% complete'); -0737 missingHMMs=missingHMMs(randperm(RandStream.create('mrg32k3a','Seed',cputime()),numel(missingHMMs))); -0738 %Train models for all missing KOs -0739 for i=1:numel(missingHMMs) -0740 %This is checked here because it could be that it is created by a -0741 %parallel process -0742 if ~isfile(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm'])) && ~isfile(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmw'])) -0743 %Check that the aligned FASTA file exists. It could be that it -0744 %is still being worked on by some other instance of the program -0745 %(the .faw file should then exist). This should not happen on a -0746 %single computer. It doesn't throw an error, because it should -0747 %finalize the ones it can -0748 if ~isfile(fullfile(dataDir,'aligned',[missingHMMs{i} '.fa'])) -0749 EM=['The aligned FASTA file for ' missingHMMs{i} ' does not exist']; -0750 dispEM(EM,false); -0751 continue; -0752 end -0753 -0754 %If the multi-FASTA file is empty then save an empty aligned -0755 %file and continue -0756 s=dir(fullfile(dataDir,'aligned',[missingHMMs{i} '.fa'])); -0757 if s.bytes<=0 -0758 fid=fopen(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm']),'w'); -0759 fclose(fid); -0760 continue; -0761 end -0762 %Create a temporary file to indicate that it is working on the -0763 %KO. This is because hmmbuild cannot overwrite existing files -0764 fid=fopen(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmw']),'w'); -0765 fclose(fid); -0766 -0767 %Create HMM -0768 [status, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmbuild' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm']) '" "' fullfile(dataDir,'aligned',[missingHMMs{i} '.fa']) '"']); -0769 if status~=0 -0770 EM=['Error when training HMM for ' missingHMMs{i} ':\n' output]; -0771 dispEM(EM); -0772 end -0773 -0774 %Delete the temporary file -0775 delete(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmw'])); -0776 -0777 %Print the progress every 25 files -0778 if rem(i-1,25) == 0 -0779 progress=num2str(floor(100*numel(listFiles(fullfile(dataDir,'hmms','*.hmm')))/numel(KOModel.rxns))); -0780 progress=pad(progress,3,'left'); -0781 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); -0782 end -0783 end -0784 end -0785 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); -0786 else -0787 fprintf('Training the KEGG Orthology specific HMMs... COMPLETE\n'); -0788 end -0789 -0790 %Check which new .out files that should be generated. Check if training of -0791 %Hidden Markov models should be performed -0792 missingOUT=setdiff(KOModel.rxns,outFiles); -0793 if ~isempty(missingOUT) -0794 fprintf('Querying the user-specified FASTA file against the KEGG Orthology specific HMMs... 0%% complete'); -0795 missingOUT=missingOUT(randperm(RandStream.create('mrg32k3a','Seed',cputime()),numel(missingOUT))); -0796 for i=1:numel(missingOUT) -0797 %This is checked here because it could be that it is created by a -0798 %parallel process -0799 if ~isfile(fullfile(outDir,[missingOUT{i} '.out'])) -0800 %Check that the HMM file exists. It should do so since %we are -0801 %saving empty files as well. Print a warning and continue if -0802 %not -0803 if ~isfile(fullfile(dataDir,'hmms',[missingOUT{i} '.hmm'])) -0804 EM=['The HMM file for ' missingOUT{i} ' does not exist']; -0805 dispEM(EM,false); -0806 continue; -0807 end -0808 -0809 %Save an empty file to prevent several threads working on the -0810 %same file -0811 fid=fopen(fullfile(outDir,[missingOUT{i} '.out']),'w'); -0812 fclose(fid); -0813 -0814 %If the HMM file is empty then save an out file and continue -0815 s=dir(fullfile(dataDir,'hmms',[missingOUT{i} '.hmm'])); -0816 if s.bytes<=0 -0817 continue; -0818 end -0819 -0820 %Check each gene in the input file against this model -0821 [status, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmsearch' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(dataDir,'hmms',[missingOUT{i} '.hmm']) '" "' fastaFile '"']); -0822 if status~=0 -0823 EM=['Error when querying HMM for ' missingOUT{i} ':\n' output]; -0824 dispEM(EM); -0825 end -0826 -0827 %Save the output to a file -0828 fid=fopen(fullfile(outDir,[missingOUT{i} '.out']),'w'); -0829 fwrite(fid,output); -0830 fclose(fid); -0831 -0832 %Print the progress every 25 files -0833 if rem(i-1,25) == 0 -0834 progress=num2str(floor(100*numel(listFiles(fullfile(outDir,'*.out')))/numel(KOModel.rxns))); -0835 progress=pad(progress,3,'left'); -0836 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); -0837 end -0838 end -0839 end -0840 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); -0841 else -0842 fprintf('Querying the user-specified FASTA file against the KEGG Orthology specific HMMs... COMPLETE\n'); -0843 end -0844 -0845 -0846 %***Begin retrieving the output and putting together the resulting model -0847 -0848 fprintf('Parsing the HMM search results... '); -0849 %Retrieve matched genes from the HMMs -0850 koGeneMat=zeros(numel(KOModel.rxns),3000); %Make room for 3000 genes -0851 genes=cell(3000,1); -0852 %Store the best score for a gene in a hash list (since it will be searching -0853 %many times) -0854 hTable = java.util.Hashtable; -0855 -0856 geneCounter=0; -0857 for i=1:numel(KOModel.rxns) -0858 if exist(fullfile(outDir,[KOModel.rxns{i} '.out']), 'file') -0859 fid=fopen(fullfile(outDir,[KOModel.rxns{i} '.out']),'r'); -0860 beginMatches=false; -0861 while 1 -0862 %Get the next line -0863 tline = fgetl(fid); -0864 -0865 %Abort at end of file -0866 if ~ischar(tline) -0867 break; -0868 end -0869 -0870 if and(beginMatches,strcmp(tline,' ------ inclusion threshold ------')) -0871 break; -0872 end -0873 -0874 if beginMatches==false -0875 %This is how the listing of matches begins -0876 if any(strfind(tline,'E-value ')) -0877 %Read one more line that is only padding -0878 tline = fgetl(fid); -0879 beginMatches=true; -0880 end -0881 else -0882 %If matches should be read -0883 if ~strcmp(tline,' [No hits detected that satisfy reporting thresholds]') && ~isempty(tline) -0884 elements=regexp(tline,' ','split'); -0885 elements=elements(cellfun(@any,elements)); -0886 -0887 %Check if the match is below the treshhold -0888 score=str2double(elements{1}); -0889 gene=elements{9}; -0890 if score<=cutOff -0891 %If the score is exactly 0, change it to a very -0892 %small value to avoid NaN -0893 if score==0 -0894 score=10^-250; -0895 end -0896 %Check if the gene is added already and, is so, get -0897 %the best score for it -0898 I=hTable.get(gene); -0899 if any(I) -0900 koGeneMat(i,I)=score; -0901 else -0902 geneCounter=geneCounter+1; -0903 %The gene was not present yet so add it -0904 hTable.put(gene,geneCounter); -0905 genes{geneCounter}=gene; -0906 koGeneMat(i,geneCounter)=score; -0907 end -0908 end -0909 else -0910 break; -0911 end -0912 end -0913 end -0914 fclose(fid); -0915 end -0916 end -0917 fprintf('COMPLETE\n'); -0918 -0919 fprintf('Removing gene, KEGG Orthology associations below minScoreRatioKO, minScoreRatioG... '); -0920 koGeneMat=koGeneMat(:,1:geneCounter); -0921 -0922 %Remove the genes for each KO that are below minScoreRatioKO. -0923 for i=1:size(koGeneMat,1) -0924 J=find(koGeneMat(i,:)); -0925 if any(J) -0926 koGeneMat(i,J(log(koGeneMat(i,J))/log(min(koGeneMat(i,J)))<minScoreRatioKO))=0; -0927 end -0928 end -0929 -0930 %Remove the KOs for each gene that are below minScoreRatioG -0931 for i=1:size(koGeneMat,2) -0932 J=find(koGeneMat(:,i)); -0933 if any(J) -0934 koGeneMat(J(log(koGeneMat(J,i))/log(min(koGeneMat(J,i)))<minScoreRatioG),i)=0; -0935 end -0936 end -0937 fprintf('COMPLETE\n'); -0938 -0939 fprintf('Adding gene annotations to the model... '); -0940 %Create the new model -0941 model.genes=genes(1:geneCounter); -0942 model.grRules=cell(numel(model.rxns),1); -0943 model.grRules(:)={''}; -0944 model.rxnGeneMat=sparse(numel(model.rxns),numel(model.genes)); -0945 -0946 %Loop through the reactions and add the corresponding genes -0947 for i=1:numel(model.rxns) -0948 if isstruct(model.rxnMiriams{i}) -0949 %Get all KOs -0950 I=find(strcmpi(model.rxnMiriams{i}.name,'kegg.orthology')); -0951 KOs=model.rxnMiriams{i}.value(I); -0952 %Find the KOs and the corresponding genes -0953 J=ismember(KOModel.rxns,KOs); -0954 [~, K]=find(koGeneMat(J,:)); -0955 -0956 if any(K) -0957 model.rxnGeneMat(i,K)=1; -0958 %Also delete KOs for which no genes were found. If no genes at -0959 %all were matched to the reaction it will be deleted later -0960 L=sum(koGeneMat(J,:),2)==0; -0961 model.rxnMiriams{i}.value(I(L))=[]; -0962 model.rxnMiriams{i}.name(I(L))=[]; -0963 end -0964 end -0965 end -0966 fprintf('COMPLETE\n'); -0967 -0968 %Find and delete all reactions without genes. This also removes genes that -0969 %are not used (which could happen because minScoreRatioG and -0970 %minScoreRatioKO). If keepSpontaneous==true, the spontaneous reactions -0971 %without genes are kept in the model. Spontaneous reactions with original -0972 %gene associations are treated in the same way, like the rest of the -0973 %reactions - if gene associations were removed during HMM search, such -0974 %reactions are deleted from the model -0975 if keepSpontaneous==true -0976 %Not the most comprise way to delete reactions without genes, but this -0977 %makes the code easier to understand. Firstly the non-spontaneous -0978 %reactions without genes are removed. After that, the second deletion -0979 %step removes spontaneous reactions, which had gene associations before -0980 %HMM search, but no longer have after it -0981 fprintf('Removing non-spontaneous reactions which after HMM search no longer have GPR rules... '); -0982 I=~any(model.rxnGeneMat,2)&~ismember(model.rxns,isSpontaneous); -0983 model=removeReactions(model,I,true,true); -0984 I=~any(model.rxnGeneMat,2)&ismember(model.rxns,spontRxnsWithGenes); -0985 model=removeReactions(model,I,true,true); -0986 else -0987 %Just simply check for any new reactions without genes and remove -0988 %it -0989 fprintf('Removing reactions which after HMM search no longer have GPR rules... '); -0990 I=~any(model.rxnGeneMat,2); -0991 model=removeReactions(model,I,true,true); -0992 end -0993 fprintf('COMPLETE\n'); -0994 -0995 fprintf('Constructing GPR rules and finalizing the model... '); -0996 %Add the gene associations as 'or' -0997 for i=1:numel(model.rxns) -0998 %Find the involved genes -0999 I=find(model.rxnGeneMat(i,:)); -1000 if any(I) -1001 model.grRules{i}=['(' model.genes{I(1)}]; -1002 for j=2:numel(I) -1003 model.grRules{i}=[model.grRules{i} ' or ' model.genes{I(j)}]; -1004 end -1005 model.grRules{i}=[model.grRules{i} ')']; -1006 end +0555 tmpFile=tempname; +0556 %On Windows, paths need to be translated to Unix before parsing it to WSL +0557 if ispc +0558 wslPath.tmpFile=getWSLpath(tmpFile); +0559 %mafft has problems writing to terminal (/dev/stderr) when running +0560 %on WSL via MATLAB, instead write and read progress file +0561 mafftOutput = tempname; +0562 wslPath.mafftOutput=getWSLpath(mafftOutput); +0563 wslPath.mafft=getWSLpath(fullfile(ravenPath,'software','mafft','mafft-linux64','mafft.bat')); +0564 wslPath.hmmbuild=getWSLpath(fullfile(ravenPath,'software','hmmer','hmmbuild')); +0565 wslPath.hmmsearch=getWSLpath(fullfile(ravenPath,'software','hmmer','hmmsearch')); +0566 wslPath.cdhit=getWSLpath(fullfile(ravenPath,'software','cd-hit','cd-hit')); +0567 end +0568 +0569 %Check if alignment of FASTA files should be performed +0570 missingAligned=setdiff(KOModel.rxns,[alignedFiles;hmmFiles;alignedWorking;outFiles]); +0571 if ~isempty(missingAligned) +0572 if seqIdentity==-1 +0573 fprintf('Performing the multiple alignment for KEGG Orthology specific protein sets... 0%% complete'); +0574 else +0575 fprintf('Performing clustering and multiple alignment for KEGG Orthology specific protein sets... 0%% complete'); +0576 end +0577 missingAligned=missingAligned(randperm(RandStream.create('mrg32k3a','Seed',cputime()),numel(missingAligned))); +0578 +0579 for i=1:numel(missingAligned) +0580 %This is checked here because it could be that it is created by a +0581 %parallel process. The faw-files are saved as temporary files to +0582 %kept track of which files are being worked on +0583 if ~isfile(fullfile(dataDir,'aligned',[missingAligned{i} '.faw'])) &&... +0584 ~isfile(fullfile(dataDir,'aligned',[missingAligned{i} '.fa'])) +0585 %Check that the multi-FASTA file exists. It should do so since +0586 %we are saving empty files as well. Print a warning and +0587 %continue if not +0588 if ~isfile(fullfile(dataDir,'fasta',[missingAligned{i} '.fa'])) +0589 EM=['WARNING: The multi-FASTA file for ' missingAligned{i} ' does not exist']; +0590 dispEM(EM,false); +0591 continue; +0592 end +0593 +0594 %If the multi-FASTA file is empty then save an empty aligned +0595 %file and continue +0596 s=dir(fullfile(dataDir,'fasta',[missingAligned{i} '.fa'])); +0597 if s.bytes<=0 +0598 fid=fopen(fullfile(dataDir,'aligned',[missingAligned{i} '.fa']),'w'); +0599 fclose(fid); +0600 continue; +0601 end +0602 +0603 %Create an empty file to prevent other threads to start to work +0604 %on the same alignment +0605 fid=fopen(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),'w'); +0606 fclose(fid); +0607 +0608 %First load the FASTA file, then select up to nSequences +0609 %sequences of the most closely related species, apply any +0610 %constraints from maxPhylDist, and save it as a temporary file, +0611 %and create the model from that +0612 +0613 fastaStruct=fastaread(fullfile(dataDir,'fasta',[missingAligned{i} '.fa'])); +0614 phylDist=inf(numel(fastaStruct),1); +0615 for j=1:numel(fastaStruct) +0616 %Get the organism abbreviation +0617 index=strfind(fastaStruct(j).Header,':'); +0618 if any(index) +0619 abbrev=fastaStruct(j).Header(1:index(1)-1); +0620 [~, index]=ismember(abbrev,phylDistStruct.ids); +0621 if any(index) +0622 phylDist(j)=phylDistStruct.distMat(index(1),phylDistId); +0623 end +0624 end +0625 end +0626 +0627 %Inf means that it should not be included +0628 phylDist(phylDist>maxPhylDist)=[]; +0629 +0630 %Sort based on phylDist +0631 [~, order]=sort(phylDist); +0632 +0633 %Save the first nSequences hits to a temporary FASTA file +0634 if nSequences<=numel(fastaStruct) +0635 fastaStruct=fastaStruct(order(1:nSequences)); +0636 else +0637 fastaStruct=fastaStruct(order); +0638 end +0639 +0640 %Do the clustering and alignment if there are more than one +0641 %sequences, otherwise just save the sequence (or an empty file) +0642 if numel(fastaStruct)>1 +0643 if seqIdentity~=-1 +0644 cdhitInpCustom=tempname; +0645 fastawrite(cdhitInpCustom,fastaStruct); +0646 if seqIdentity<=1 && seqIdentity>0.7 +0647 nparam='5'; +0648 elseif seqIdentity>0.6 +0649 nparam='4'; +0650 elseif seqIdentity>0.5 +0651 nparam='3'; +0652 elseif seqIdentity>0.4 +0653 nparam='2'; +0654 else +0655 EM='The provided seqIdentity must be between 0 and 1\n'; +0656 dispEM(EM); +0657 end +0658 if ispc +0659 wslPath.cdhitInpCustom=getWSLpath(cdhitInpCustom); +0660 [status, output]=system(['wsl "' wslPath.cdhit '" -T "' num2str(cores) '" -i "' wslPath.cdhitInpCustom '" -o "' wslPath.tmpFile '" -c "' num2str(seqIdentity) '" -n ' nparam ' -M 2000']); +0661 elseif ismac || isunix +0662 [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']); +0663 end +0664 if status~=0 +0665 EM=['Error when performing clustering of ' missingAligned{i} ':\n' output]; +0666 dispEM(EM); +0667 end +0668 %Remove the old tempfile +0669 if exist(cdhitInpCustom, 'file') +0670 delete([cdhitInpCustom '*']); +0671 end +0672 else +0673 %This means that CD-HIT should be skipped since +0674 %seqIdentity is equal to -1 +0675 fastawrite(tmpFile,fastaStruct); +0676 end +0677 %Do the alignment for this file +0678 if ismac +0679 [status, output]=system(['"' fullfile(ravenPath,'software','mafft','mafft-mac','mafft.bat') '" --auto --anysymbol --thread "' num2str(cores) '" "' tmpFile '" > "' fullfile(dataDir,'aligned',[missingAligned{i} '.faw']) '"']); +0680 elseif isunix +0681 [status, output]=system(['"' fullfile(ravenPath,'software','mafft','mafft-linux64','mafft.bat') '" --auto --anysymbol --thread "' num2str(cores) '" "' tmpFile '" > "' fullfile(dataDir,'aligned',[missingAligned{i} '.faw']) '"']); +0682 elseif ispc +0683 wslPath.fawFile=getWSLpath(fullfile(dataDir,'aligned',[missingAligned{i} '.faw'])); +0684 [status, ~]=system(['wsl "' wslPath.mafft '" --auto --anysymbol --progress "' wslPath.mafftOutput '" --thread "' num2str(cores) '" --out "' wslPath.fawFile '" "' wslPath.tmpFile '"']); +0685 output=fileread(mafftOutput); +0686 delete(mafftOutput); +0687 end +0688 if status~=0 +0689 %It could be that alignment failed because only one +0690 %sequence was left after clustering. If that is the +0691 %case, then the clustered file is just copied as 'faw' +0692 %file +0693 if any(regexp(output,'Only 1 sequence found')) +0694 movefile(tmpFile,fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),'f'); +0695 else +0696 EM=['Error when performing alignment of ' missingAligned{i} ':\n' output]; +0697 dispEM(EM); +0698 end +0699 end +0700 %Remove the old tempfile +0701 if exist(tmpFile, 'file') +0702 delete([tmpFile '*']); +0703 end +0704 else +0705 %If there is only one sequence then it's not possible to do +0706 %a multiple alignment. Just print the sequence instead. An +0707 %empty file was written previously so that doesn't have to +0708 %be dealt with +0709 if numel(fastaStruct)==1 +0710 warnState = warning; %Save the current warning state +0711 warning('off','Bioinfo:fastawrite:AppendToFile'); +0712 fastawrite(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),fastaStruct); +0713 warning(warnState) %Reset warning state to previous settings +0714 end +0715 end +0716 %Move the temporary file to the real one +0717 movefile(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),fullfile(dataDir,'aligned',[missingAligned{i} '.fa']),'f'); +0718 +0719 %Print the progress every 25 files +0720 if rem(i-1,25) == 0 +0721 progress=num2str(floor(100*numel(listFiles(fullfile(dataDir,'aligned','*.fa')))/numel(KOModel.rxns))); +0722 progress=pad(progress,3,'left'); +0723 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); +0724 end +0725 end +0726 end +0727 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); +0728 else +0729 if seqIdentity==-1 +0730 fprintf('Performing the multiple alignment for KEGG Orthology specific protein sets... COMPLETE\n'); +0731 else +0732 fprintf('Performing clustering and multiple alignment for KEGG Orthology specific protein sets... COMPLETE\n'); +0733 end +0734 end +0735 +0736 %Check if training of Hidden Markov models should be performed +0737 missingHMMs=setdiff(KOModel.rxns,[hmmFiles;outFiles]); +0738 if ~isempty(missingHMMs) +0739 fprintf('Training the KEGG Orthology specific HMMs... 0%% complete'); +0740 missingHMMs=missingHMMs(randperm(RandStream.create('mrg32k3a','Seed',cputime()),numel(missingHMMs))); +0741 %Train models for all missing KOs +0742 for i=1:numel(missingHMMs) +0743 %This is checked here because it could be that it is created by a +0744 %parallel process +0745 if ~isfile(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm'])) && ~isfile(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmw'])) +0746 %Check that the aligned FASTA file exists. It could be that it +0747 %is still being worked on by some other instance of the program +0748 %(the .faw file should then exist). This should not happen on a +0749 %single computer. It doesn't throw an error, because it should +0750 %finalize the ones it can +0751 if ~isfile(fullfile(dataDir,'aligned',[missingHMMs{i} '.fa'])) +0752 EM=['The aligned FASTA file for ' missingHMMs{i} ' does not exist']; +0753 dispEM(EM,false); +0754 continue; +0755 end +0756 +0757 %If the multi-FASTA file is empty then save an empty aligned +0758 %file and continue +0759 s=dir(fullfile(dataDir,'aligned',[missingHMMs{i} '.fa'])); +0760 if s.bytes<=0 +0761 fid=fopen(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm']),'w'); +0762 fclose(fid); +0763 continue; +0764 end +0765 %Create a temporary file to indicate that it is working on the +0766 %KO. This is because hmmbuild cannot overwrite existing files +0767 fid=fopen(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmw']),'w'); +0768 fclose(fid); +0769 +0770 %Create HMM +0771 if ismac || isunix +0772 [status, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmbuild' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm']) '" "' fullfile(dataDir,'aligned',[missingHMMs{i} '.fa']) '"']); +0773 else +0774 wslPath.hmmFile = getWSLpath(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm'])); +0775 wslPath.alignFile = getWSLpath(fullfile(dataDir,'aligned',[missingHMMs{i} '.fa'])); +0776 [status, output] = system(['wsl "' wslPath.hmmbuild '" --cpu "' num2str(cores) '" "' wslPath.hmmFile '" "' wslPath.alignFile '"']); +0777 end +0778 if status~=0 +0779 EM=['Error when training HMM for ' missingHMMs{i} ':\n' output]; +0780 dispEM(EM); +0781 end +0782 +0783 %Delete the temporary file +0784 delete(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmw'])); +0785 +0786 %Print the progress every 25 files +0787 if rem(i-1,25) == 0 +0788 progress=num2str(floor(100*numel(listFiles(fullfile(dataDir,'hmms','*.hmm')))/numel(KOModel.rxns))); +0789 progress=pad(progress,3,'left'); +0790 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); +0791 end +0792 end +0793 end +0794 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); +0795 else +0796 fprintf('Training the KEGG Orthology specific HMMs... COMPLETE\n'); +0797 end +0798 +0799 %Check which new .out files that should be generated. Check if training of +0800 %Hidden Markov models should be performed +0801 missingOUT=setdiff(KOModel.rxns,outFiles); +0802 if ~isempty(missingOUT) +0803 fprintf('Querying the user-specified FASTA file against the KEGG Orthology specific HMMs... 0%% complete'); +0804 missingOUT=missingOUT(randperm(RandStream.create('mrg32k3a','Seed',cputime()),numel(missingOUT))); +0805 for i=1:numel(missingOUT) +0806 %This is checked here because it could be that it is created by a +0807 %parallel process +0808 if ~isfile(fullfile(outDir,[missingOUT{i} '.out'])) +0809 %Check that the HMM file exists. It should do so since %we are +0810 %saving empty files as well. Print a warning and continue if +0811 %not +0812 if ~isfile(fullfile(dataDir,'hmms',[missingOUT{i} '.hmm'])) +0813 EM=['The HMM file for ' missingOUT{i} ' does not exist']; +0814 dispEM(EM,false); +0815 continue; +0816 end +0817 +0818 %Save an empty file to prevent several threads working on the +0819 %same file +0820 fid=fopen(fullfile(outDir,[missingOUT{i} '.out']),'w'); +0821 fclose(fid); +0822 +0823 %If the HMM file is empty then save an out file and continue +0824 s=dir(fullfile(dataDir,'hmms',[missingOUT{i} '.hmm'])); +0825 if s.bytes<=0 +0826 continue; +0827 end +0828 +0829 %Check each gene in the input file against this model +0830 if ismac || isunix +0831 [status, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmsearch' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(dataDir,'hmms',[missingOUT{i} '.hmm']) '" "' fastaFile '"']); +0832 else +0833 wslPath.hmmFile = getWSLpath(fullfile(dataDir,'hmms',[missingOUT{i} '.hmm'])); +0834 wslPath.fastaFile = getWSLpath(fastaFile); +0835 [status, output]=system(['wsl "' wslPath.hmmsearch '" --cpu "' num2str(cores) '" "' wslPath.hmmFile '" "' wslPath.fastaFile '"']); +0836 end +0837 if status~=0 +0838 EM=['Error when querying HMM for ' missingOUT{i} ':\n' output]; +0839 dispEM(EM); +0840 end +0841 +0842 %Save the output to a file +0843 fid=fopen(fullfile(outDir,[missingOUT{i} '.out']),'w'); +0844 fwrite(fid,output); +0845 fclose(fid); +0846 +0847 %Print the progress every 25 files +0848 if rem(i-1,25) == 0 +0849 progress=num2str(floor(100*numel(listFiles(fullfile(outDir,'*.out')))/numel(KOModel.rxns))); +0850 progress=pad(progress,3,'left'); +0851 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress); +0852 end +0853 end +0854 end +0855 fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\bCOMPLETE\n'); +0856 else +0857 fprintf('Querying the user-specified FASTA file against the KEGG Orthology specific HMMs... COMPLETE\n'); +0858 end +0859 +0860 +0861 %***Begin retrieving the output and putting together the resulting model +0862 +0863 fprintf('Parsing the HMM search results... '); +0864 %Retrieve matched genes from the HMMs +0865 koGeneMat=zeros(numel(KOModel.rxns),3000); %Make room for 3000 genes +0866 genes=cell(3000,1); +0867 %Store the best score for a gene in a hash list (since it will be searching +0868 %many times) +0869 hTable = java.util.Hashtable; +0870 +0871 geneCounter=0; +0872 for i=1:numel(KOModel.rxns) +0873 if exist(fullfile(outDir,[KOModel.rxns{i} '.out']), 'file') +0874 fid=fopen(fullfile(outDir,[KOModel.rxns{i} '.out']),'r'); +0875 beginMatches=false; +0876 while 1 +0877 %Get the next line +0878 tline = fgetl(fid); +0879 +0880 %Abort at end of file +0881 if ~ischar(tline) +0882 break; +0883 end +0884 +0885 if and(beginMatches,strcmp(tline,' ------ inclusion threshold ------')) +0886 break; +0887 end +0888 +0889 if beginMatches==false +0890 %This is how the listing of matches begins +0891 if any(strfind(tline,'E-value ')) +0892 %Read one more line that is only padding +0893 tline = fgetl(fid); +0894 beginMatches=true; +0895 end +0896 else +0897 %If matches should be read +0898 if ~strcmp(tline,' [No hits detected that satisfy reporting thresholds]') && ~isempty(tline) +0899 elements=regexp(tline,' ','split'); +0900 elements=elements(cellfun(@any,elements)); +0901 +0902 %Check if the match is below the treshhold +0903 score=str2double(elements{1}); +0904 gene=elements{9}; +0905 if score<=cutOff +0906 %If the score is exactly 0, change it to a very +0907 %small value to avoid NaN +0908 if score==0 +0909 score=10^-250; +0910 end +0911 %Check if the gene is added already and, is so, get +0912 %the best score for it +0913 I=hTable.get(gene); +0914 if any(I) +0915 koGeneMat(i,I)=score; +0916 else +0917 geneCounter=geneCounter+1; +0918 %The gene was not present yet so add it +0919 hTable.put(gene,geneCounter); +0920 genes{geneCounter}=gene; +0921 koGeneMat(i,geneCounter)=score; +0922 end +0923 end +0924 else +0925 break; +0926 end +0927 end +0928 end +0929 fclose(fid); +0930 end +0931 end +0932 fprintf('COMPLETE\n'); +0933 +0934 fprintf('Removing gene, KEGG Orthology associations below minScoreRatioKO, minScoreRatioG... '); +0935 koGeneMat=koGeneMat(:,1:geneCounter); +0936 +0937 %Remove the genes for each KO that are below minScoreRatioKO. +0938 for i=1:size(koGeneMat,1) +0939 J=find(koGeneMat(i,:)); +0940 if any(J) +0941 koGeneMat(i,J(log(koGeneMat(i,J))/log(min(koGeneMat(i,J)))<minScoreRatioKO))=0; +0942 end +0943 end +0944 +0945 %Remove the KOs for each gene that are below minScoreRatioG +0946 for i=1:size(koGeneMat,2) +0947 J=find(koGeneMat(:,i)); +0948 if any(J) +0949 koGeneMat(J(log(koGeneMat(J,i))/log(min(koGeneMat(J,i)))<minScoreRatioG),i)=0; +0950 end +0951 end +0952 fprintf('COMPLETE\n'); +0953 +0954 fprintf('Adding gene annotations to the model... '); +0955 %Create the new model +0956 model.genes=genes(1:geneCounter); +0957 model.grRules=cell(numel(model.rxns),1); +0958 model.grRules(:)={''}; +0959 model.rxnGeneMat=sparse(numel(model.rxns),numel(model.genes)); +0960 +0961 %Loop through the reactions and add the corresponding genes +0962 for i=1:numel(model.rxns) +0963 if isstruct(model.rxnMiriams{i}) +0964 %Get all KOs +0965 I=find(strcmpi(model.rxnMiriams{i}.name,'kegg.orthology')); +0966 KOs=model.rxnMiriams{i}.value(I); +0967 %Find the KOs and the corresponding genes +0968 J=ismember(KOModel.rxns,KOs); +0969 [~, K]=find(koGeneMat(J,:)); +0970 +0971 if any(K) +0972 model.rxnGeneMat(i,K)=1; +0973 %Also delete KOs for which no genes were found. If no genes at +0974 %all were matched to the reaction it will be deleted later +0975 L=sum(koGeneMat(J,:),2)==0; +0976 model.rxnMiriams{i}.value(I(L))=[]; +0977 model.rxnMiriams{i}.name(I(L))=[]; +0978 end +0979 end +0980 end +0981 fprintf('COMPLETE\n'); +0982 +0983 %Find and delete all reactions without genes. This also removes genes that +0984 %are not used (which could happen because minScoreRatioG and +0985 %minScoreRatioKO). If keepSpontaneous==true, the spontaneous reactions +0986 %without genes are kept in the model. Spontaneous reactions with original +0987 %gene associations are treated in the same way, like the rest of the +0988 %reactions - if gene associations were removed during HMM search, such +0989 %reactions are deleted from the model +0990 if keepSpontaneous==true +0991 %Not the most comprise way to delete reactions without genes, but this +0992 %makes the code easier to understand. Firstly the non-spontaneous +0993 %reactions without genes are removed. After that, the second deletion +0994 %step removes spontaneous reactions, which had gene associations before +0995 %HMM search, but no longer have after it +0996 fprintf('Removing non-spontaneous reactions which after HMM search no longer have GPR rules... '); +0997 I=~any(model.rxnGeneMat,2)&~ismember(model.rxns,isSpontaneous); +0998 model=removeReactions(model,I,true,true); +0999 I=~any(model.rxnGeneMat,2)&ismember(model.rxns,spontRxnsWithGenes); +1000 model=removeReactions(model,I,true,true); +1001 else +1002 %Just simply check for any new reactions without genes and remove +1003 %it +1004 fprintf('Removing reactions which after HMM search no longer have GPR rules... '); +1005 I=~any(model.rxnGeneMat,2); +1006 model=removeReactions(model,I,true,true); 1007 end -1008 -1009 %Fix grRules and reconstruct rxnGeneMat -1010 [grRules,rxnGeneMat] = standardizeGrRules(model,false); %Give detailed output -1011 model.grRules = grRules; -1012 model.rxnGeneMat = rxnGeneMat; -1013 -1014 %Fix subsystems -1015 emptySubSystems=cellfun(@isempty, model.subSystems); -1016 model.subSystems(emptySubSystems)={{''}}; -1017 -1018 %Add the description to the reactions -1019 for i=1:numel(model.rxns) -1020 if ~isempty(model.rxnNotes{i}) -1021 model.rxnNotes(i)=strcat('Included by getKEGGModelForOrganism (using HMMs).',model.rxnNotes(i)); -1022 model.rxnNotes(i)=strrep(model.rxnNotes(i),'.','. '); -1023 else -1024 model.rxnNotes(i)={'Included by getKEGGModelForOrganism (using HMMs)'}; -1025 end -1026 end -1027 %Remove the temp fasta file -1028 delete(fastaFile) -1029 fprintf('COMPLETE\n\n*** Model reconstruction complete ***\n'); -1030 end -1031 -1032 function files=listFiles(directory) -1033 %Supporter function to list the files in a directory and return them as a -1034 %cell array -1035 temp=dir(directory); -1036 files=cell(numel(temp),1); -1037 for i=1:numel(temp) -1038 files{i}=temp(i,1).name; -1039 end -1040 files=strrep(files,'.fa',''); -1041 files=strrep(files,'.hmm',''); -1042 files=strrep(files,'.out',''); -1043 files=strrep(files,'.faw',''); -1044 end +1008 fprintf('COMPLETE\n'); +1009 +1010 fprintf('Constructing GPR rules and finalizing the model... '); +1011 %Add the gene associations as 'or' +1012 for i=1:numel(model.rxns) +1013 %Find the involved genes +1014 I=find(model.rxnGeneMat(i,:)); +1015 if any(I) +1016 model.grRules{i}=['(' model.genes{I(1)}]; +1017 for j=2:numel(I) +1018 model.grRules{i}=[model.grRules{i} ' or ' model.genes{I(j)}]; +1019 end +1020 model.grRules{i}=[model.grRules{i} ')']; +1021 end +1022 end +1023 +1024 %Fix grRules and reconstruct rxnGeneMat +1025 [grRules,rxnGeneMat] = standardizeGrRules(model,false); %Give detailed output +1026 model.grRules = grRules; +1027 model.rxnGeneMat = rxnGeneMat; +1028 +1029 %Add the description to the reactions +1030 for i=1:numel(model.rxns) +1031 if ~isempty(model.rxnNotes{i}) +1032 model.rxnNotes(i)=strcat('Included by getKEGGModelForOrganism (using HMMs).',model.rxnNotes(i)); +1033 model.rxnNotes(i)=strrep(model.rxnNotes(i),'.','. '); +1034 else +1035 model.rxnNotes(i)={'Included by getKEGGModelForOrganism (using HMMs)'}; +1036 end +1037 end +1038 %Remove the temp fasta file +1039 delete(fastaFile) +1040 fprintf('COMPLETE\n\n*** Model reconstruction complete ***\n'); +1041 end +1042 +1043 function files=listFiles(directory) +1044 %Supporter function to list the files in a directory and return them as a +1045 %cell array +1046 temp=dir(directory); +1047 files=cell(numel(temp),1); +1048 for i=1:numel(temp) +1049 files{i}=temp(i,1).name; +1050 end +1051 files=strrep(files,'.fa',''); +1052 files=strrep(files,'.hmm',''); +1053 files=strrep(files,'.out',''); +1054 files=strrep(files,'.faw',''); +1055 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 4649eab5..ae4dd1a3 100644 --- a/doc/external/kegg/getModelFromKEGG.html +++ b/doc/external/kegg/getModelFromKEGG.html @@ -132,249 +132,250 @@

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

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

    SOURCE CODE ^if x -0247 metaCycRxns.subSystems{rxnCounter,1}{1,numel(metaCycRxns.subSystems{rxnCounter,1})+1}=pwyNames{y}; +0247 metaCycRxns.subSystems{rxnCounter,1}{numel(metaCycRxns.subSystems{rxnCounter,1})+1,1}=pwyNames{y}; 0248 end 0249 end 0250 diff --git a/doc/external/parseScores.html b/doc/external/parseScores.html index 70766632..d82f859d 100644 --- a/doc/external/parseScores.html +++ b/doc/external/parseScores.html @@ -150,7 +150,7 @@

    SOURCE CODE ^%Read the title line and fetch the list of compartments 0093 tline = fgetl(fid); 0094 GSS.compartments=regexp(tline,',','split'); -0095 GSS.compartments=GSS.compartments(4:end); +0095 GSS.compartments=transpose(GSS.compartments(4: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 diff --git a/doc/index.html b/doc/index.html index 25c6ef92..025e7fcb 100644 --- a/doc/index.html +++ b/doc/index.html @@ -3,8 +3,8 @@ Matlab Index - - + + @@ -15,63 +15,64 @@

    Matlab Index

    Matlab Directories

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

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FSEOF editMiriam getModelFromMetaCyc qMOMA
    INITStepDesc expandModel getObjectiveString randomSampling
    ManualINITTests exportForGit getPathwayDimensions ravenCobraWrapper
    SBMLFromExcel exportModel getPhylDist readYAMLmodel
    addExchangeRxns exportModelToSIF getRxnsFromKEGG removeBadRxns
    addGenesRaven exportToExcelFormat getRxnsFromMetaCyc removeGenes
    addIdentifierPrefix exportToTabDelimited getRxnsInComp removeIdentifierPrefix
    addJavaPaths extractMiriam getToolboxVersion removeLowScoreGenes
    addMets fillGaps getTransportRxns removeMets
    addRavenToUserPath fillGapsLargeTests getWSLpath removeRavenFromPath
    addRxns fillGapsSmallTests getWoLFScores removeReactions
    addRxnsGenesMets findGeneDeletions groupRxnScores replaceMets
    addSpontaneousRxns findRAVENroot guessComposition reporterMetabolites
    addTransport fitParameters haveFlux rescaleModelForINIT
    analyzeSampling fitTasks hmmerTests reverseRxns
    blastPlusTests followChanged importExcelModel runDynamicFBA
    buildEquation followFluxes importExportTests runINIT
    canConsume ftINIT importModel runPhenotypePhasePlane
    canProduce ftINITFillGaps linkMetaCycKEGGRxns runProductionEnvelope
    cdhitTests ftINITFillGapsForAllTasks loadSheet runRobustnessAnalysis
    changeGeneAssoc ftINITFillGapsMILP loadWorkbook runSimpleOptKnock
    changeGrRules ftINITInternalAlg mafftTests scoreComplexModel
    changeRxns gapReport makeFakeBlastStructure scoreModel
    checkFileExistence generateNewIds makeSomething setColorToMapRxns
    checkFunctionUniqueness getAllRxnsFromGenes mapCompartments setExchangeBounds
    checkInstallation getAllSubGraphs mapPathwayRxnNames setOmicDataToRxns
    checkModelStruct getAllowedBounds markPathwayWithExpression setParam
    checkProduction getBlast markPathwayWithFluxes setRavenSolver
    checkRxn getBlastFromExcel mergeCompartments setTitle
    checkSolution getColorCodes mergeLinear simplifyModel
    checkTasks getDiamond mergeModels solveLP
    checkTasksTests getElementalBalance miriamTests solveQP
    cleanSheet getEnzymesFromMetaCyc modelAbilitiesTests solverTests
    closeModel getEssentialRxns modelConversionTests sortIdentifiers
    colorPathway getExchangeRxns modelCurationTests sortModel
    colorSubsystem getExprForRxnScore modelSortingTests standardizeGrRules
    combineMetaCycKEGGModels getExpressionStructure optimizeProb standardizeModelFieldOrder
    compareMultipleModels getFluxZ parallelPoolRAVEN startup
    compareRxnsGenesMetsComps getFullPath parseFormulas tinitTests
    constructEquations getGenesFromGrRules parseHPA trimPathway
    constructMultiFasta getGenesFromKEGG parseHPArna tutorial1
    constructPathwayFromCelldesigner getINITModel parseRxnEqu tutorial2
    constructS getINITSteps parseScores tutorial2_solutions
    consumeSomething getIndexes parseTaskList tutorial3
    contractModel getKEGGModelForOrganism permuteModel tutorial3_solutions
    convertCharArray getMD5Hash plotAdditionalInfo tutorial4
    convertToIrrev getMetaCycModelForOrganism plotLabels tutorial4_solutions
    copyToComps getMetsFromKEGG predictLocalization tutorial5
    deleteUnusedGenes getMetsFromMetaCyc prepINITModel tutorial6
    diamondTests getMetsInComp printFluxes updateDocumentation
    dispEM getMinNrFluxes printModel writeSheet
    drawMap getModelFromHomology printModelStats writeYAMLmodel
    drawPathway getModelFromKEGG printOrange
    + FSEOF emptyOrLogicalScalar getModelFromKEGG qMOMA + INITStepDesc emptyOrTextOrCellOfText getModelFromMetaCyc randomSampling + ManualINITTests emptyOrTextScalar getObjectiveString ravenCobraWrapper + SBMLFromExcel expandModel getPathwayDimensions readYAMLmodel + addExchangeRxns exportForGit getPhylDist removeBadRxns + addGenesRaven exportModel getRxnsFromKEGG removeGenes + addIdentifierPrefix exportModelToSIF getRxnsFromMetaCyc removeIdentifierPrefix + addJavaPaths exportToExcelFormat getRxnsInComp removeLowScoreGenes + addMets exportToTabDelimited getToolboxVersion removeMets + addRavenToUserPath extractMiriam getTransportRxns removeRavenFromPath + addRxns fillGaps getWSLpath removeReactions + addRxnsGenesMets fillGapsLargeTests getWoLFScores replaceMets + addSpontaneousRxns fillGapsSmallTests groupRxnScores reporterMetabolites + addTransport findGeneDeletions guessComposition rescaleModelForINIT + analyzeSampling findRAVENroot haveFlux reverseRxns + blastPlusTests fitParameters hmmerTests runDynamicFBA + buildEquation fitTasks importExcelModel runINIT + canConsume followChanged importExportTests runPhenotypePhasePlane + canProduce followFluxes importModel runProductionEnvelope + cdhitTests ftINIT linkMetaCycKEGGRxns runRAVENtests + changeGeneAssoc ftINITFillGaps loadSheet runRobustnessAnalysis + changeGrRules ftINITFillGapsForAllTasks loadWorkbook runSimpleOptKnock + changeRxns ftINITFillGapsMILP mafftTests scoreComplexModel + checkFileExistence ftINITInternalAlg makeFakeBlastStructure scoreModel + checkFunctionUniqueness gapReport makeSomething setColorToMapRxns + checkInstallation generateNewIds mapCompartments setExchangeBounds + checkModelStruct getAllRxnsFromGenes mapPathwayRxnNames setOmicDataToRxns + checkProduction getAllSubGraphs markPathwayWithExpression setParam + checkRxn getAllowedBounds markPathwayWithFluxes setRavenSolver + checkSolution getBlast mergeCompartments setTitle + checkTasks getBlastFromExcel mergeLinear simplifyModel + checkTasksTests getColorCodes mergeModels solveLP + cleanSheet getDiamond miriamTests solveQP + closeModel getElementalBalance modelAbilitiesTests solverTests + colorPathway getEnzymesFromMetaCyc modelConversionTests sortIdentifiers + colorSubsystem getEssentialRxns modelCurationTests sortModel + combineMetaCycKEGGModels getExchangeRxns modelSortingTests standardizeGrRules + compareMultipleModels getExprForRxnScore optimizeProb standardizeModelFieldOrder + compareRxnsGenesMetsComps getExpressionStructure parallelPoolRAVEN startup + constructEquations getFluxZ parseFormulas tinitTests + constructMultiFasta getFullPath parseHPA trimPathway + constructPathwayFromCelldesigner getGenesFromGrRules parseHPArna tutorial1 + constructS getGenesFromKEGG parseRxnEqu tutorial2 + consumeSomething getINITModel parseScores tutorial2_solutions + contractModel getINITSteps parseTaskList tutorial3 + convertCharArray getIndexes permuteModel tutorial3_solutions + convertToIrrev getKEGGModelForOrganism plotAdditionalInfo tutorial4 + copyToComps getMD5Hash plotLabels tutorial4_solutions + deleteUnusedGenes getMetaCycModelForOrganism predictLocalization tutorial5 + diamondTests getMetsFromKEGG prepINITModel tutorial6 + dispEM getMetsFromMetaCyc printFluxes updateDocumentation + drawMap getMetsInComp printModel writeSheet + drawPathway getMinNrFluxes printModelStats writeYAMLmodel + editMiriam getModelFromHomology printOrange
    Generated by m2html © 2005
    diff --git a/doc/installation/checkFunctionUniqueness.html b/doc/installation/checkFunctionUniqueness.html index a8d2ddee..5b55f77a 100644 --- a/doc/installation/checkFunctionUniqueness.html +++ b/doc/installation/checkFunctionUniqueness.html @@ -48,7 +48,7 @@

    CROSS-REFERENCE INFORMATION ^
 </ul>
 This function is called by:
 <ul style= -
  • checkInstallation checkInstallation
  • +
  • checkInstallation checkInstallation
  • diff --git a/doc/installation/checkInstallation.html b/doc/installation/checkInstallation.html index 3f5370a0..3ee04260 100644 --- a/doc/installation/checkInstallation.html +++ b/doc/installation/checkInstallation.html @@ -24,7 +24,7 @@

    PURPOSE ^checkInstallation

    SYNOPSIS ^

    -
    function [currVer, installType] = checkInstallation(developMode)
    +
    function [currVer, installType] = checkInstallation(developMode,checkBinaries)

    DESCRIPTION ^

     checkInstallation
    @@ -39,6 +39,9 @@ 

    DESCRIPTION ^SUBFUNCTIONS ^function res = interpretResults(results)
  • function str = myStr(InputStr,len)
  • function status = makeBinaryExecutable(ravenDir)
  • function printOrange(stringToPrint)
  • SOURCE CODE ^

    -
    0001 function [currVer, installType] = checkInstallation(developMode)
    +
    0001 function [currVer, installType] = checkInstallation(developMode,checkBinaries)
     0002 % checkInstallation
     0003 %   The purpose of this function is to check if all necessary functions are
     0004 %   installed and working. It also checks whether there are any functions
    @@ -80,373 +83,390 @@ 

    SOURCE CODE ^% HMMs (optional, default false). If 'versionOnly' is 0012 % specified, only the version is reported as currVer, no 0013 % further installation or tests are performed. -0014 % -0015 % Output: -0016 % currVer current RAVEN version -0017 % installType how RAVEN is installed -0018 % 0: via git (as .git folder is found) -0019 % 1: as MATLAB Add-On -0020 % 2: neither of the above, direct download of ZIP file -0021 % This matches the installations mentioned in the wiki: -0022 % https://github.com/SysBioChalmers/RAVEN/wiki/Installation -0023 % 0 = advanced / 1 = easy / 2 = medium -0024 % -0025 % Usage: [currVer, installType] = checkInstallation(developMode) -0026 -0027 if nargin<1 -0028 developMode=false; -0029 end -0030 if ischar(developMode) && strcmp(developMode,'versionOnly') -0031 versionOnly = true; -0032 else -0033 versionOnly = false; -0034 end -0035 -0036 %Get the RAVEN path -0037 [ST, I]=dbstack('-completenames'); -0038 [ravenDir,~,~]=fileparts(fileparts(ST(I).file)); -0039 -0040 installType = 2; % If neither git nor add-on, then ZIP was downloaded -0041 addList = matlab.addons.installedAddons; -0042 if isfolder(fullfile(ravenDir,'.git')) -0043 installType = 0; -0044 elseif any(strcmp(addList.Name,'RAVEN Toolbox')) -0045 installType = 1; -0046 end -0047 -0048 % Do not print first few lines if only version should be reported -0049 if ~versionOnly -0050 fprintf('\n*** THE RAVEN TOOLBOX ***\n\n'); -0051 %Print the RAVEN version if it is not the development version -0052 fprintf(myStr(' > Installation type',40)); -0053 switch installType -0054 case 0 -0055 fprintf('Advanced (via git)\n'); -0056 case 1 -0057 fprintf('Easy (as MATLAB Add-On)\n'); -0058 case 2 -0059 fprintf('Medium (as downloaded ZIP file)\n'); -0060 end -0061 fprintf(myStr(' > Installing from location',40)); -0062 fprintf('%s\n',ravenDir) -0063 fprintf(myStr(' > Checking RAVEN release',40)); -0064 end -0065 -0066 if exist(fullfile(ravenDir,'version.txt'), 'file') == 2 -0067 currVer = fgetl(fopen(fullfile(ravenDir,'version.txt'))); -0068 fclose('all'); -0069 if ~versionOnly -0070 fprintf([currVer '\n']); -0071 try -0072 newVer=strtrim(webread('https://raw.githubusercontent.com/SysBioChalmers/RAVEN/main/version.txt')); -0073 newVerNum=str2double(strsplit(newVer,'.')); -0074 currVerNum=str2double(strsplit(currVer,'.')); -0075 for i=1:3 -0076 if currVerNum(i)<newVerNum(i) -0077 fprintf(myStr(' > Latest RAVEN release available',40)) -0078 printOrange([newVer,'\n']) -0079 switch installType -0080 case 0 -0081 printOrange(' Run git pull in your favourite git client\n') -0082 printOrange(' to get the latest RAVEN release\n'); -0083 case 1 -0084 printOrange(myStr(' Instructions on how to upgrade',40)) -0085 fprintf('<a href="https://github.com/SysBioChalmers/RAVEN/wiki/Installation#upgrade-raven-after-easy-installation">here</a>\n'); -0086 case 2 -0087 printOrange(myStr(' Instructions on how to upgrade',40)) -0088 fprintf('<a href="https://github.com/SysBioChalmers/RAVEN/wiki/Installation#upgrade-raven-after-medium-installation">here</a>\n'); -0089 end -0090 break -0091 elseif i==3 -0092 fprintf(' > You are running the latest RAVEN release\n'); -0093 end -0094 end -0095 catch -0096 fprintf(myStr(' > Checking for latest RAVEN release',40)) -0097 printOrange('Fail\n'); -0098 printOrange(' Cannot reach GitHub for release info\n'); -0099 end -0100 end -0101 else -0102 currVer = 'develop'; -0103 if ~versionOnly; fprintf('DEVELOPMENT\n'); end -0104 end -0105 if strcmp(developMode,'versionOnly') -0106 return; -0107 end -0108 -0109 fprintf(myStr(' > Checking MATLAB release',40)) -0110 fprintf([version('-release') '\n']) -0111 fprintf(myStr(' > Checking system architecture',40)) -0112 fprintf([computer('arch'),'\n']) -0113 -0114 fprintf(myStr(' > Set RAVEN in MATLAB path',40)) -0115 subpath=regexp(genpath(ravenDir),pathsep,'split'); %List all subdirectories -0116 pathsToKeep=cellfun(@(x) ~contains(x,'.git'),subpath) & cellfun(@(x) ~contains(x,'doc'),subpath); -0117 try -0118 addpath(strjoin(subpath(pathsToKeep),pathsep)); -0119 fprintf('Pass\n'); -0120 fprintf(myStr(' > Save MATLAB path',40)) -0121 try -0122 savepath -0123 fprintf('Pass\n') -0124 catch -0125 printOrange('Fail\n') -0126 fprintf([' You might have to rerun checkInstallation again\n'... -0127 ' next time you start up MATLAB\n']) -0128 end -0129 catch -0130 printOrange('Fail\n') -0131 end -0132 -0133 if isunix -0134 fprintf(myStr(' > Make binaries executable',40)) -0135 status = makeBinaryExecutable(ravenDir); -0136 if status == 0 -0137 fprintf('Pass\n') -0138 else -0139 printOrange('Fail\n') -0140 end -0141 end -0142 -0143 %Check if it is possible to parse an Excel file -0144 fprintf('\n=== Model import and export ===\n'); -0145 fprintf(myStr(' > Add Java paths for Excel format',40)) -0146 try -0147 %Add the required classes to the static Java path if not already added -0148 addJavaPaths(); -0149 fprintf('Pass\n') -0150 catch -0151 printOrange('Fail\n') -0152 end -0153 fprintf(myStr(' > Checking libSBML version',40)) -0154 try -0155 evalc('importModel(fullfile(ravenDir,''tutorial'',''empty.xml''))'); -0156 try -0157 libSBMLver=OutputSBML_RAVEN; % Only works in libSBML 5.17.0+ -0158 fprintf([libSBMLver.libSBML_version_string '\n']); -0159 catch -0160 printOrange('Fail\n') -0161 fprintf(' An older libSBML version was found, update to version 5.17.0 or higher for a significant improvement of model import\n'); -0162 end +0014 % checkBinaries logical whether non-developMode binaries should be +0015 % checked for functionality. If false, it overwrites +0016 % developMode. Default true. +0017 % +0018 % Output: +0019 % currVer current RAVEN version +0020 % installType how RAVEN is installed +0021 % 0: via git (as .git folder is found) +0022 % 1: as MATLAB Add-On +0023 % 2: neither of the above, direct download of ZIP file +0024 % This matches the installations mentioned in the wiki: +0025 % https://github.com/SysBioChalmers/RAVEN/wiki/Installation +0026 % 0 = advanced / 1 = easy / 2 = medium +0027 % +0028 % Usage: [currVer, installType] = checkInstallation(developMode) +0029 +0030 if nargin<1 +0031 developMode=false; +0032 end +0033 if nargin<2 +0034 checkBinaries=true; +0035 end +0036 if ischar(developMode) && strcmp(developMode,'versionOnly') +0037 versionOnly = true; +0038 else +0039 versionOnly = false; +0040 end +0041 +0042 %Get the RAVEN path +0043 [ST, I]=dbstack('-completenames'); +0044 [ravenDir,~,~]=fileparts(fileparts(ST(I).file)); +0045 +0046 installType = 2; % If neither git nor add-on, then ZIP was downloaded +0047 addList = matlab.addons.installedAddons; +0048 if isfolder(fullfile(ravenDir,'.git')) +0049 installType = 0; +0050 elseif any(strcmp(addList.Name,'RAVEN Toolbox')) +0051 installType = 1; +0052 end +0053 +0054 % Do not print first few lines if only version should be reported +0055 if ~versionOnly +0056 fprintf('\n*** THE RAVEN TOOLBOX ***\n\n'); +0057 %Print the RAVEN version if it is not the development version +0058 fprintf(myStr(' > Installation type',40)); +0059 switch installType +0060 case 0 +0061 fprintf('Advanced (via git)\n'); +0062 case 1 +0063 fprintf('Easy (as MATLAB Add-On)\n'); +0064 case 2 +0065 fprintf('Medium (as downloaded ZIP file)\n'); +0066 end +0067 fprintf(myStr(' > Installing from location',40)); +0068 fprintf('%s\n',ravenDir) +0069 fprintf(myStr(' > Checking RAVEN release',40)); +0070 end +0071 +0072 if exist(fullfile(ravenDir,'version.txt'), 'file') == 2 +0073 currVer = fgetl(fopen(fullfile(ravenDir,'version.txt'))); +0074 fclose('all'); +0075 if ~versionOnly +0076 fprintf([currVer '\n']); +0077 try +0078 newVer=strtrim(webread('https://raw.githubusercontent.com/SysBioChalmers/RAVEN/main/version.txt')); +0079 newVerNum=str2double(strsplit(newVer,'.')); +0080 currVerNum=str2double(strsplit(currVer,'.')); +0081 for i=1:3 +0082 if currVerNum(i)<newVerNum(i) +0083 fprintf(myStr(' > Latest RAVEN release available',40)) +0084 printOrange([newVer,'\n']) +0085 switch installType +0086 case 0 +0087 printOrange(' Run git pull in your favourite git client\n') +0088 printOrange(' to get the latest RAVEN release\n'); +0089 case 1 +0090 printOrange(myStr(' Instructions on how to upgrade',40)) +0091 fprintf('<a href="https://github.com/SysBioChalmers/RAVEN/wiki/Installation#upgrade-raven-after-easy-installation">here</a>\n'); +0092 case 2 +0093 printOrange(myStr(' Instructions on how to upgrade',40)) +0094 fprintf('<a href="https://github.com/SysBioChalmers/RAVEN/wiki/Installation#upgrade-raven-after-medium-installation">here</a>\n'); +0095 end +0096 break +0097 elseif i==3 +0098 fprintf(' > You are running the latest RAVEN release\n'); +0099 end +0100 end +0101 catch +0102 fprintf(myStr(' > Checking for latest RAVEN release',40)) +0103 printOrange('Fail\n'); +0104 printOrange(' Cannot reach GitHub for release info\n'); +0105 end +0106 end +0107 else +0108 currVer = 'develop'; +0109 if ~versionOnly; fprintf('DEVELOPMENT\n'); end +0110 end +0111 if strcmp(developMode,'versionOnly') +0112 return; +0113 end +0114 +0115 fprintf(myStr(' > Checking MATLAB release',40)) +0116 fprintf([version('-release') '\n']) +0117 fprintf(myStr(' > Checking system architecture',40)) +0118 fprintf([computer('arch'),'\n']) +0119 +0120 fprintf(myStr(' > Set RAVEN in MATLAB path',40)) +0121 subpath=regexp(genpath(ravenDir),pathsep,'split'); %List all subdirectories +0122 pathsToKeep=cellfun(@(x) ~contains(x,'.git'),subpath) & cellfun(@(x) ~contains(x,'doc'),subpath); +0123 try +0124 addpath(strjoin(subpath(pathsToKeep),pathsep)); +0125 fprintf('Pass\n'); +0126 fprintf(myStr(' > Save MATLAB path',40)) +0127 try +0128 savepath +0129 fprintf('Pass\n') +0130 catch +0131 printOrange('Fail\n') +0132 fprintf([' You might have to rerun checkInstallation again\n'... +0133 ' next time you start up MATLAB\n']) +0134 end +0135 catch +0136 printOrange('Fail\n') +0137 end +0138 fprintf(myStr(' > Store RAVEN path as MATLAB pref',40)) +0139 try +0140 setpref('RAVEN','ravenPath',ravenDir); +0141 fprintf('Pass\n'); +0142 catch +0143 printOrange('Fail\n') +0144 end +0145 +0146 if isunix +0147 fprintf(myStr(' > Make binaries executable',40)) +0148 status = makeBinaryExecutable(ravenDir); +0149 if status == 0 +0150 fprintf('Pass\n') +0151 else +0152 printOrange('Fail\n') +0153 end +0154 end +0155 +0156 %Check if it is possible to parse an Excel file +0157 fprintf('\n=== Model import and export ===\n'); +0158 fprintf(myStr(' > Add Java paths for Excel format',40)) +0159 try +0160 %Add the required classes to the static Java path if not already added +0161 addJavaPaths(); +0162 fprintf('Pass\n') 0163 catch 0164 printOrange('Fail\n') -0165 fprintf(' Download libSBML from http://sbml.org/Software/libSBML/Downloading_libSBML and add to MATLAB path\n'); -0166 end -0167 fprintf(' > Checking model import and export\n') -0168 [~,res]=evalc("runtests('importExportTests.m');"); -0169 -0170 fprintf(myStr(' > Import Excel format',40)) -0171 if res(1).Passed == 1 -0172 fprintf('Pass\n') -0173 else -0174 printOrange('Fail\n') -0175 if any(strcmpi(addList.Name,'Text Analytics Toolbox')) -0176 fprintf([' Excel import/export is incompatible with MATLAB Text Analytics Toolbox.\n' ... -0177 ' Further instructions => https://github.com/SysBioChalmers/RAVEN/issues/55#issuecomment-1514369299\n']) -0178 end +0165 end +0166 fprintf(myStr(' > Checking libSBML version',40)) +0167 try +0168 evalc('importModel(fullfile(ravenDir,''tutorial'',''empty.xml''))'); +0169 try +0170 libSBMLver=OutputSBML_RAVEN; % Only works in libSBML 5.17.0+ +0171 fprintf([libSBMLver.libSBML_version_string '\n']); +0172 catch +0173 printOrange('Fail\n') +0174 fprintf(' An older libSBML version was found, update to version 5.17.0 or higher for a significant improvement of model import\n'); +0175 end +0176 catch +0177 printOrange('Fail\n') +0178 fprintf(' Download libSBML from http://sbml.org/Software/libSBML/Downloading_libSBML and add to MATLAB path\n'); 0179 end -0180 -0181 fprintf(myStr(' > Export Excel format',40)) -0182 if res(4).Passed == 1 -0183 fprintf('Pass\n') -0184 else -0185 printOrange('Fail\n') -0186 end -0187 -0188 fprintf(myStr(' > Import SBML format',40)) -0189 if res(2).Passed == 1 -0190 fprintf('Pass\n') -0191 else -0192 printOrange('Fail\n') -0193 end -0194 -0195 fprintf(myStr(' > Export SBML format',40)) -0196 if res(5).Passed == 1 -0197 fprintf('Pass\n') -0198 else -0199 printOrange('Fail\n') -0200 end -0201 -0202 fprintf(myStr(' > Import YAML format',40)) -0203 if res(3).Passed == 1 -0204 fprintf('Pass\n') -0205 else -0206 printOrange('Fail\n') -0207 end -0208 -0209 fprintf(myStr(' > Export YAML format',40)) -0210 if res(6).Passed == 1 -0211 fprintf('Pass\n') -0212 else -0213 printOrange('Fail\n') -0214 end -0215 -0216 fprintf('\n=== Model solvers ===\n'); -0217 -0218 %Get current solver. Set it to 'none', if it is not set -0219 fprintf(' > Checking for LP solvers\n') -0220 [~,res]=evalc("runtests('solverTests.m');"); +0180 fprintf(' > Checking model import and export\n') +0181 [~,res]=evalc("runtests('importExportTests.m');"); +0182 +0183 fprintf(myStr(' > Import Excel format',40)) +0184 if res(1).Passed == 1 +0185 fprintf('Pass\n') +0186 else +0187 printOrange('Fail\n') +0188 if any(strcmpi(addList.Name,'Text Analytics Toolbox')) +0189 fprintf([' Excel import/export is incompatible with MATLAB Text Analytics Toolbox.\n' ... +0190 ' Further instructions => https://github.com/SysBioChalmers/RAVEN/issues/55#issuecomment-1514369299\n']) +0191 end +0192 end +0193 +0194 fprintf(myStr(' > Export Excel format',40)) +0195 if res(4).Passed == 1 +0196 fprintf('Pass\n') +0197 else +0198 printOrange('Fail\n') +0199 end +0200 +0201 fprintf(myStr(' > Import SBML format',40)) +0202 if res(2).Passed == 1 +0203 fprintf('Pass\n') +0204 else +0205 printOrange('Fail\n') +0206 end +0207 +0208 fprintf(myStr(' > Export SBML format',40)) +0209 if res(5).Passed == 1 +0210 fprintf('Pass\n') +0211 else +0212 printOrange('Fail\n') +0213 end +0214 +0215 fprintf(myStr(' > Import YAML format',40)) +0216 if res(3).Passed == 1 +0217 fprintf('Pass\n') +0218 else +0219 printOrange('Fail\n') +0220 end 0221 -0222 fprintf(myStr(' > glpk',40)) -0223 if res(1).Passed == 1 +0222 fprintf(myStr(' > Export YAML format',40)) +0223 if res(6).Passed == 1 0224 fprintf('Pass\n') 0225 else 0226 printOrange('Fail\n') 0227 end 0228 -0229 fprintf(myStr(' > gurobi',40)) -0230 if res(2).Passed == 1 -0231 fprintf('Pass\n') -0232 else -0233 printOrange('Fail\n') -0234 end -0235 -0236 fprintf(myStr(' > scip',40)) -0237 if res(3).Passed == 1 -0238 fprintf('Pass\n') -0239 else -0240 printOrange('Fail\n') -0241 end -0242 -0243 fprintf(myStr(' > cobra',40)) -0244 if res(4).Passed == 1 -0245 fprintf('Pass\n') -0246 else -0247 printOrange('Fail\n') -0248 end -0249 fprintf(myStr(' > Set RAVEN solver',40)) -0250 try -0251 oldSolver=getpref('RAVEN','solver'); -0252 solverIdx=find(strcmp(oldSolver,{'glpk','gurobi','scip','cobra'})); -0253 catch -0254 solverIdx=0; -0255 end -0256 % Do not change old solver if functional -0257 if solverIdx~=0 && res(solverIdx).Passed == 1 -0258 fprintf([oldSolver '\n']) -0259 % Order of preference: gurobi > glpk > scip > cobra -0260 elseif res(2).Passed == 1 -0261 fprintf('gurobi\n') -0262 setRavenSolver('gurobi'); -0263 elseif res(1).Passed == 1 -0264 fprintf('glpk\n') -0265 setRavenSolver('glpk'); -0266 elseif res(3).Passed == 1 -0267 fprintf('scip\n') -0268 setRavenSolver('scip'); -0269 elseif res(4).Passed == 1 -0270 fprintf('cobra\n') -0271 setRavenSolver('cobra'); -0272 else -0273 fprintf('None, no functional solvers\n') -0274 fprintf(' The glpk should always be working, check your RAVEN installation to make sure all files are present\n') -0275 end -0276 -0277 fprintf('\n=== Essential binary executables ===\n'); -0278 fprintf(myStr(' > Checking BLAST+',40)) -0279 [~,res]=evalc("runtests('blastPlusTests.m');"); -0280 res=interpretResults(res); -0281 if res==false -0282 fprintf(' This is essential to run getBlast()\n') -0283 end -0284 -0285 fprintf(myStr(' > Checking DIAMOND',40)) -0286 [~,res]=evalc("runtests('diamondTests.m');"); -0287 res=interpretResults(res); -0288 if res==false -0289 fprintf(' This is essential to run the getDiamond()\n') -0290 end -0291 -0292 fprintf(myStr(' > Checking HMMER',40)) -0293 [~,res]=evalc("runtests('hmmerTests.m')"); -0294 res=interpretResults(res); -0295 if res==false -0296 fprintf([' This is essential to run getKEGGModelFromHomology()\n'... -0297 ' when using a FASTA file as input\n']) -0298 end -0299 -0300 if developMode -0301 fprintf('\n=== Development binary executables ===\n'); -0302 fprintf('NOTE: These binaries are only required when using KEGG FTP dump files in getKEGGModelForOrganism\n'); -0303 -0304 fprintf(myStr(' > Checking CD-HIT',40)) -0305 [~,res]=evalc("runtests('cdhitTests.m');"); -0306 interpretResults(res); +0229 fprintf('\n=== Model solvers ===\n'); +0230 +0231 %Get current solver. Set it to 'none', if it is not set +0232 fprintf(' > Checking for LP solvers\n') +0233 [~,res]=evalc("runtests('solverTests.m');"); +0234 +0235 fprintf(myStr(' > glpk',40)) +0236 if res(1).Passed == 1 +0237 fprintf('Pass\n') +0238 else +0239 printOrange('Fail\n') +0240 end +0241 +0242 fprintf(myStr(' > gurobi',40)) +0243 if res(2).Passed == 1 +0244 fprintf('Pass\n') +0245 else +0246 printOrange('Fail\n') +0247 end +0248 +0249 fprintf(myStr(' > scip',40)) +0250 if res(3).Passed == 1 +0251 fprintf('Pass\n') +0252 else +0253 printOrange('Fail\n') +0254 end +0255 +0256 fprintf(myStr(' > cobra',40)) +0257 if res(4).Passed == 1 +0258 fprintf('Pass\n') +0259 else +0260 printOrange('Fail\n') +0261 end +0262 fprintf(myStr(' > Set RAVEN solver',40)) +0263 try +0264 oldSolver=getpref('RAVEN','solver'); +0265 solverIdx=find(strcmp(oldSolver,{'glpk','gurobi','scip','cobra'})); +0266 catch +0267 solverIdx=0; +0268 end +0269 % Do not change old solver if functional +0270 if solverIdx~=0 && res(solverIdx).Passed == 1 +0271 fprintf([oldSolver '\n']) +0272 % Order of preference: gurobi > glpk > scip > cobra +0273 elseif res(2).Passed == 1 +0274 fprintf('gurobi\n') +0275 setRavenSolver('gurobi'); +0276 elseif res(1).Passed == 1 +0277 fprintf('glpk\n') +0278 setRavenSolver('glpk'); +0279 elseif res(3).Passed == 1 +0280 fprintf('scip\n') +0281 setRavenSolver('scip'); +0282 elseif res(4).Passed == 1 +0283 fprintf('cobra\n') +0284 setRavenSolver('cobra'); +0285 else +0286 fprintf('None, no functional solvers\n') +0287 fprintf(' The glpk should always be working, check your RAVEN installation to make sure all files are present\n') +0288 end +0289 +0290 fprintf('\n=== Essential binary executables ===\n'); +0291 if ~checkBinaries +0292 printOrange(' Skipping check of binary executables\n') +0293 else +0294 fprintf(myStr(' > Checking BLAST+',40)) +0295 [~,res]=evalc("runtests('blastPlusTests.m');"); +0296 res=interpretResults(res); +0297 if res==false +0298 fprintf(' This is essential to run getBlast()\n') +0299 end +0300 +0301 fprintf(myStr(' > Checking DIAMOND',40)) +0302 [~,res]=evalc("runtests('diamondTests.m');"); +0303 res=interpretResults(res); +0304 if res==false +0305 fprintf(' This is essential to run the getDiamond()\n') +0306 end 0307 -0308 fprintf(myStr(' > Checking MAFFT',40)) -0309 [~,res]=evalc("runtests('mafftTests.m');"); -0310 interpretResults(res); -0311 end -0312 -0313 fprintf('\n=== Compatibility ===\n'); -0314 fprintf(myStr(' > Checking function uniqueness',40)) -0315 checkFunctionUniqueness(); -0316 -0317 fprintf('\n*** checkInstallation complete ***\n\n'); -0318 end +0308 fprintf(myStr(' > Checking HMMER',40)) +0309 [~,res]=evalc("runtests('hmmerTests.m')"); +0310 res=interpretResults(res); +0311 if res==false +0312 fprintf([' This is essential to run getKEGGModelFromHomology()\n'... +0313 ' when using a FASTA file as input\n']) +0314 end +0315 +0316 if developMode +0317 fprintf('\n=== Development binary executables ===\n'); +0318 fprintf('NOTE: These binaries are only required when using KEGG FTP dump files in getKEGGModelForOrganism\n'); 0319 -0320 function res = interpretResults(results) -0321 if results.Failed==0 && results.Incomplete==0 -0322 fprintf('Pass\n'); -0323 res=true; -0324 else -0325 printOrange('Fail\n') -0326 fprintf(' Download/compile the binary and rerun checkInstallation\n'); -0327 res=false; +0320 fprintf(myStr(' > Checking CD-HIT',40)) +0321 [~,res]=evalc("runtests('cdhitTests.m');"); +0322 interpretResults(res); +0323 +0324 fprintf(myStr(' > Checking MAFFT',40)) +0325 [~,res]=evalc("runtests('mafftTests.m');"); +0326 interpretResults(res); +0327 end 0328 end -0329 end -0330 -0331 function str = myStr(InputStr,len) -0332 str=InputStr; -0333 lenDiff = len - length(str); -0334 if lenDiff < 0 -0335 warning('String too long'); -0336 else -0337 str = [str blanks(lenDiff)]; -0338 end -0339 end -0340 -0341 function status = makeBinaryExecutable(ravenDir) -0342 % This function is required to run when RAVEN is downloaded as MATLAB -0343 % Add-On, in which case the file permissions are not correctly set -0344 if ispc -0345 status = 0; % No need to run on Windows -0346 return; -0347 end -0348 binDir = fullfile(ravenDir,'software'); -0349 -0350 binList = {fullfile(binDir,'blast+','blastp'); fullfile(binDir,'blast+','blastp.mac'); -0351 fullfile(binDir,'blast+','makeblastdb'); fullfile(binDir,'blast+','makeblastdb.mac'); -0352 fullfile(binDir,'cd-hit','cd-hit'); fullfile(binDir,'cd-hit','cd-hit.mac'); -0353 fullfile(binDir,'diamond','diamond'); fullfile(binDir,'diamond','diamond.mac'); -0354 fullfile(binDir,'hmmer','hmmbuild'); fullfile(binDir,'hmmer','hmmbuild.mac'); -0355 fullfile(binDir,'hmmer','hmmsearch'); fullfile(binDir,'hmmer','hmmsearch.mac'); -0356 fullfile(binDir,'GLPKmex','glpkcc.mexa64'); fullfile(binDir,'GLPKmex','glpkcc.mexglx'); fullfile(binDir,'GLPKmex','glpkcc.mexmaci64'); fullfile(binDir,'GLPKmex','glpkcc.mexmaca64'); -0357 fullfile(binDir,'libSBML','TranslateSBML_RAVEN.mexa64'); fullfile(binDir,'libSBML','TranslateSBML_RAVEN.mexglx'); fullfile(binDir,'libSBML','TranslateSBML_RAVEN.mexmaci64'); fullfile(binDir,'libSBML','TranslateSBML_RAVEN.mexmaca64'); -0358 fullfile(binDir,'libSBML','OutputSBML_RAVEN.mexa64'); fullfile(binDir,'libSBML','OutputSBML_RAVEN.mexglx'); fullfile(binDir,'libSBML','OutputSBML_RAVEN.mexmaci64'); fullfile(binDir,'libSBML','OutputSBML_RAVEN.mexmaca64'); -0359 fullfile(binDir,'mafft','mafft-linux64','mafft.bat'); -0360 fullfile(binDir,'mafft','mafft-mac','mafft.bat');}; -0361 -0362 for i=1:numel(binList) -0363 [status,cmdout] = system(['chmod +x "' binList{i} '"']); -0364 if status ~= 0 -0365 warning('Failed to make %s executable: %s ',binList{i},strip(cmdout)) -0366 end -0367 end -0368 end -0369 -0370 function printOrange(stringToPrint) -0371 % printOrange -0372 % Duplicate of RAVEN/core/printOrange is also kept here, as this function -0373 % should be able to run before adding RAVEN to the MATLAB path. -0374 try useDesktop = usejava('desktop'); catch, useDesktop = false; end -0375 if useDesktop -0376 fprintf(['[\b' stringToPrint,']\b']) -0377 else -0378 fprintf(stringToPrint) -0379 end -0380 end

    +0329 +0330 fprintf('\n=== Compatibility ===\n'); +0331 fprintf(myStr(' > Checking function uniqueness',40)) +0332 checkFunctionUniqueness(); +0333 +0334 fprintf('\n*** checkInstallation complete ***\n'); +0335 end +0336 +0337 function res = interpretResults(results) +0338 if results.Failed==0 && results.Incomplete==0 +0339 fprintf('Pass\n'); +0340 res=true; +0341 else +0342 printOrange('Fail\n') +0343 fprintf(' Download/compile the binary and rerun checkInstallation\n'); +0344 res=false; +0345 end +0346 end +0347 +0348 function str = myStr(InputStr,len) +0349 str=InputStr; +0350 lenDiff = len - length(str); +0351 if lenDiff < 0 +0352 warning('String too long'); +0353 else +0354 str = [str blanks(lenDiff)]; +0355 end +0356 end +0357 +0358 function status = makeBinaryExecutable(ravenDir) +0359 % This function is required to run when RAVEN is downloaded as MATLAB +0360 % Add-On, in which case the file permissions are not correctly set +0361 if ispc +0362 status = 0; % No need to run on Windows +0363 return; +0364 end +0365 binDir = fullfile(ravenDir,'software'); +0366 +0367 binList = {fullfile(binDir,'blast+','blastp'); fullfile(binDir,'blast+','blastp.mac'); +0368 fullfile(binDir,'blast+','makeblastdb'); fullfile(binDir,'blast+','makeblastdb.mac'); +0369 fullfile(binDir,'cd-hit','cd-hit'); fullfile(binDir,'cd-hit','cd-hit.mac'); +0370 fullfile(binDir,'diamond','diamond'); fullfile(binDir,'diamond','diamond.mac'); +0371 fullfile(binDir,'hmmer','hmmbuild'); fullfile(binDir,'hmmer','hmmbuild.mac'); +0372 fullfile(binDir,'hmmer','hmmsearch'); fullfile(binDir,'hmmer','hmmsearch.mac'); +0373 fullfile(binDir,'GLPKmex','glpkcc.mexa64'); fullfile(binDir,'GLPKmex','glpkcc.mexglx'); fullfile(binDir,'GLPKmex','glpkcc.mexmaci64'); fullfile(binDir,'GLPKmex','glpkcc.mexmaca64'); +0374 fullfile(binDir,'libSBML','TranslateSBML_RAVEN.mexa64'); fullfile(binDir,'libSBML','TranslateSBML_RAVEN.mexglx'); fullfile(binDir,'libSBML','TranslateSBML_RAVEN.mexmaci64'); fullfile(binDir,'libSBML','TranslateSBML_RAVEN.mexmaca64'); +0375 fullfile(binDir,'libSBML','OutputSBML_RAVEN.mexa64'); fullfile(binDir,'libSBML','OutputSBML_RAVEN.mexglx'); fullfile(binDir,'libSBML','OutputSBML_RAVEN.mexmaci64'); fullfile(binDir,'libSBML','OutputSBML_RAVEN.mexmaca64'); +0376 fullfile(binDir,'mafft','mafft-linux64','mafft.bat'); +0377 fullfile(binDir,'mafft','mafft-mac','mafft.bat');}; +0378 +0379 for i=1:numel(binList) +0380 [status,cmdout] = system(['chmod +x "' binList{i} '"']); +0381 if status ~= 0 +0382 warning('Failed to make %s executable: %s ',binList{i},strip(cmdout)) +0383 end +0384 end +0385 end +0386 +0387 function printOrange(stringToPrint) +0388 % printOrange +0389 % Duplicate of RAVEN/core/printOrange is also kept here, as this function +0390 % should be able to run before adding RAVEN to the MATLAB path. +0391 try useDesktop = usejava('desktop'); catch, useDesktop = false; end +0392 if useDesktop +0393 fprintf(['[\b' stringToPrint,']\b']) +0394 else +0395 fprintf(stringToPrint) +0396 end +0397 end

    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/exportModel.html b/doc/io/exportModel.html index 57f67266..f538d90b 100644 --- a/doc/io/exportModel.html +++ b/doc/io/exportModel.html @@ -308,7 +308,7 @@

    SOURCE CODE ^if i<numel(model.comps) 0246 modelSBML.compartment(i+1)=modelSBML.compartment(i); 0247 end -0248 +0248 0249 if isfield(modelSBML.compartment,'metaid') 0250 modelSBML.compartment(i).metaid=model.comps{i}; 0251 end @@ -334,7 +334,7 @@

    SOURCE CODE ^if isfield(modelSBML.compartment, 'id') 0272 modelSBML.compartment(i).id=model.comps{i}; 0273 end -0274 +0274 0275 end 0276 0277 %Begin writing species @@ -362,7 +362,7 @@

    SOURCE CODE ^if i<numel(model.mets) 0300 modelSBML.species(i+1)=modelSBML.species(i); 0301 end -0302 +0302 0303 if isfield(modelSBML.species,'metaid') 0304 modelSBML.species(i).metaid=model.mets{i}; 0305 end @@ -440,7 +440,7 @@

    SOURCE CODE ^if i<numel(model.genes) 0378 modelSBML.fbc_geneProduct(i+1)=modelSBML.fbc_geneProduct(i); 0379 end -0380 +0380 0381 if isfield(modelSBML.fbc_geneProduct,'metaid') 0382 modelSBML.fbc_geneProduct(i).metaid=model.genes{i}; 0383 end @@ -523,11 +523,11 @@

    SOURCE CODE ^if i<numel(model.rxns) 0461 modelSBML.reaction(i+1)=modelSBML.reaction(i); 0462 end -0463 +0463 0464 if isfield(modelSBML.reaction,'metaid') 0465 modelSBML.reaction(i).metaid=model.rxns{i}; 0466 end -0467 +0467 0468 %Export notes information 0469 if (~isnan(model.rxnConfidenceScores(i)) || ~isempty(model.rxnReferences{i}) || ~isempty(model.rxnNotes{i})) 0470 modelSBML.reaction(i).notes='<notes><body xmlns="http://www.w3.org/1999/xhtml">'; @@ -542,7 +542,7 @@

    SOURCE CODE ^end 0480 modelSBML.reaction(i).notes=[modelSBML.reaction(i).notes '</body></notes>']; 0481 end -0482 +0482 0483 % Export SBO terms from rxnMiriams 0484 if ~isempty(model.rxnMiriams{i}) 0485 [~,sbo_ind] = ismember('sbo',model.rxnMiriams{i}.name); @@ -554,7 +554,7 @@

    SOURCE CODE ^end 0493 end -0494 +0494 0495 %Export annotation information from rxnMiriams 0496 if (~isempty(model.rxnMiriams{i}) && isfield(modelSBML.reaction(i),'annotation')) || ~isempty(model.eccodes{i}) 0497 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_' model.rxns{i} '">']; @@ -567,14 +567,14 @@

    SOURCE CODE ^end 0505 modelSBML.reaction(i).annotation=[modelSBML.reaction(i).annotation getMiriam(model.rxnMiriams{i}) '</rdf:Bag></bqbiol:is></rdf:Description></rdf:RDF></annotation>']; 0506 end -0507 +0507 0508 if isfield(modelSBML.reaction, 'name') 0509 modelSBML.reaction(i).name=model.rxnNames{i}; 0510 end 0511 if isfield(modelSBML.reaction, 'id') 0512 modelSBML.reaction(i).id=model.rxns{i}; 0513 end -0514 +0514 0515 %Add the information about reactants and products 0516 involvedMets=addReactantsProducts(model,modelSBML,i); 0517 for j=1:numel(involvedMets.reactant) @@ -616,241 +616,250 @@

    SOURCE CODE ^end 0555 -0556 %Prepare subSystems Code taken from COBRA functions getModelSubSystems, -0557 %writeSBML, findRxnsFromSubSystem under GNU General Public License v3.0, -0558 %license file in readme/GPL.MD. Code modified for RAVEN -0559 if modelHasSubsystems -0560 modelSBML.groups_group.groups_kind = 'partonomy'; -0561 modelSBML.groups_group.sboTerm = 633; -0562 tmpStruct=modelSBML.groups_group; -0563 -0564 rxns=model.rxns; -0565 if ~any(cellfun(@iscell,model.subSystems)) -0566 if ~any(~cellfun(@isempty,model.subSystems)) -0567 subSystems = {}; -0568 else -0569 subSystems = setdiff(model.subSystems,''); -0570 end -0571 else -0572 orderedSubs = cellfun(@(x) columnVector(x),model.subSystems,'UniformOUtput',false); -0573 subSystems = setdiff(vertcat(orderedSubs{:}),''); -0574 end -0575 if isempty(subSystems) -0576 subSystems = {}; -0577 end -0578 if ~isempty(subSystems) -0579 %Build the groups for the group package -0580 groupIDs = strcat('group',cellfun(@num2str, num2cell(1:length(subSystems)),'UniformOutput',false)); -0581 for i = 1:length(subSystems) -0582 cgroup = tmpStruct; -0583 if ~any(cellfun(@iscell,model.subSystems)) -0584 present = ismember(model.subSystems,subSystems{i}); -0585 else -0586 present = cellfun(@(x) any(ismember(x,subSystems{i})),model.subSystems); -0587 end -0588 groupMembers = rxns(present); -0589 for j = 1:numel(groupMembers) -0590 cMember = tmpStruct.groups_member; -0591 cMember.groups_idRef = groupMembers{j}; -0592 if j == 1 -0593 cgroup.groups_member = cMember; -0594 else -0595 cgroup.groups_member(j) = cMember; -0596 end -0597 end -0598 cgroup.groups_id = groupIDs{i}; -0599 cgroup.groups_name = subSystems{i}; -0600 if i == 1 -0601 modelSBML.groups_group = cgroup; -0602 else -0603 modelSBML.groups_group(i) = cgroup; -0604 end -0605 end -0606 end -0607 end -0608 -0609 %Prepare fbc_objective subfield +0556 %Prepare subSystems +0557 if modelHasSubsystems +0558 modelSBML.groups_group.groups_kind = 'partonomy'; +0559 modelSBML.groups_group.sboTerm = 633; +0560 grpTemplate = modelSBML.groups_group; +0561 +0562 % === 1) Normalize: make every entry a cell array of chars (vectorized) === +0563 isChar = cellfun(@ischar, model.subSystems); +0564 model.subSystems(isChar) = cellfun(@(s){s}, model.subSystems(isChar), 'UniformOutput', false); +0565 model.subSystems(cellfun(@isempty, model.subSystems)) = {{}}; +0566 +0567 % If some entries contain string scalars by mistake, coerce them: +0568 model.subSystems = cellfun(@(c) cellfun(@char, c, 'UniformOutput', false), model.subSystems, 'UniformOutput', false); +0569 +0570 % === 2) Flatten once: names and their reaction indices (vectorized) === +0571 flatNames = vertcat(model.subSystems{:}); % 1×M cellstr of all subsystem labels +0572 if isempty(flatNames) +0573 % Nothing to do: no subsystems present +0574 return +0575 end +0576 +0577 counts = cellfun(@numel, model.subSystems); % reactions -> how many subsystems +0578 % For each reaction r, repeat r exactly counts(r) times +0579 flatIdx = arrayfun(@(r,c) repmat(r, c, 1), (1:numel(model.subSystems)).', counts, 'UniformOutput', false); +0580 flatIdx = vertcat(flatIdx{:}); % M×1 vector of reaction indices +0581 +0582 % === 3) Group in one shot: unique subsystems + members per subsystem === +0583 [subSystems, ~, g] = unique(flatNames, 'stable'); % stable preserves first appearance +0584 membersIdx = accumarray(g, flatIdx, [], @(v){v}); % cell: one vector of r-idx per group +0585 nSubs = numel(subSystems); +0586 +0587 % === 4) Preallocate and build SBML groups (single simple loop) === +0588 modelSBML.groups_group(1:nSubs) = grpTemplate; +0589 groupIDs = "group" + (1:nSubs); +0590 +0591 if isfield(grpTemplate,'groups_member') +0592 memTemplate = grpTemplate.groups_member; +0593 else +0594 memTemplate = struct('groups_idRef',''); +0595 end +0596 +0597 for i = 1:nSubs +0598 rIdx = membersIdx{i}; +0599 groupRXNs = model.rxns(rIdx); +0600 cgroup = grpTemplate; +0601 +0602 % Preallocate and fill members +0603 nM = numel(groupRXNs); +0604 if nM > 0 +0605 cgroup.groups_member(1:nM) = memTemplate; +0606 [cgroup.groups_member.groups_idRef] = deal(groupRXNs{:}); +0607 else +0608 cgroup.groups_member = repmat(memTemplate, 0, 1); +0609 end 0610 -0611 modelSBML.fbc_objective.fbc_type='maximize'; -0612 modelSBML.fbc_objective.fbc_id='obj'; -0613 -0614 ind=find(model.c); -0615 -0616 if isempty(ind) -0617 modelSBML.fbc_objective.fbc_fluxObjective.fbc_coefficient=0; -0618 else -0619 for i=1:length(ind) -0620 %Copy the default values to the next index as long as it is not the -0621 %last one -0622 if i<numel(ind) -0623 modelSBML.reaction(i+1)=modelSBML.reaction(i); -0624 end -0625 values=model.c(model.c~=0); -0626 modelSBML.fbc_objective(i).fbc_fluxObjective.fbc_reaction=modelSBML.reaction(ind(i)).id; -0627 modelSBML.fbc_objective(i).fbc_fluxObjective.fbc_coefficient=values(i); -0628 modelSBML.fbc_objective(i).fbc_fluxObjective.isSetfbc_coefficient=1; -0629 end -0630 end -0631 -0632 modelSBML.fbc_activeObjective=modelSBML.fbc_objective.fbc_id; -0633 -0634 fbcStr=['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/fbc/version',num2str(sbmlPackageVersions(1))]; -0635 if modelHasSubsystems -0636 groupStr=['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/groups/version',num2str(sbmlPackageVersions(2))]; -0637 modelSBML.namespaces=struct('prefix',{'','fbc','groups'},... -0638 'uri',{['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/core'],... -0639 fbcStr,groupStr}); -0640 else -0641 modelSBML.namespaces=struct('prefix',{'','fbc'},... -0642 'uri',{['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/core'],... -0643 fbcStr}); -0644 end -0645 -0646 if sbmlPackageVersions(1) == 2 -0647 modelSBML.fbc_strict=1; -0648 modelSBML.isSetfbc_strict = 1; -0649 end -0650 -0651 modelSBML.rule=[]; -0652 modelSBML.constraint=[]; -0653 -0654 [ravenDir,prevDir]=findRAVENroot(); -0655 fileName=checkFileExistence(fileName,1,true,false); -0656 -0657 OutputSBML_RAVEN(modelSBML,fileName,1,0,[1,0]); +0611 cgroup.groups_id = char(groupIDs(i)); % keep as char for SBML compatibility +0612 cgroup.groups_name = subSystems{i}; +0613 modelSBML.groups_group(i) = cgroup; +0614 end +0615 end +0616 +0617 +0618 %Prepare fbc_objective subfield +0619 +0620 modelSBML.fbc_objective.fbc_type='maximize'; +0621 modelSBML.fbc_objective.fbc_id='obj'; +0622 +0623 ind=find(model.c); +0624 +0625 if isempty(ind) +0626 modelSBML.fbc_objective.fbc_fluxObjective.fbc_coefficient=0; +0627 else +0628 for i=1:length(ind) +0629 %Copy the default values to the next index as long as it is not the +0630 %last one +0631 if i<numel(ind) +0632 modelSBML.reaction(i+1)=modelSBML.reaction(i); +0633 end +0634 values=model.c(model.c~=0); +0635 modelSBML.fbc_objective(i).fbc_fluxObjective.fbc_reaction=modelSBML.reaction(ind(i)).id; +0636 modelSBML.fbc_objective(i).fbc_fluxObjective.fbc_coefficient=values(i); +0637 modelSBML.fbc_objective(i).fbc_fluxObjective.isSetfbc_coefficient=1; +0638 end +0639 end +0640 +0641 modelSBML.fbc_activeObjective=modelSBML.fbc_objective.fbc_id; +0642 +0643 fbcStr=['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/fbc/version',num2str(sbmlPackageVersions(1))]; +0644 if modelHasSubsystems +0645 groupStr=['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/groups/version',num2str(sbmlPackageVersions(2))]; +0646 modelSBML.namespaces=struct('prefix',{'','fbc','groups'},... +0647 'uri',{['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/core'],... +0648 fbcStr,groupStr}); +0649 else +0650 modelSBML.namespaces=struct('prefix',{'','fbc'},... +0651 'uri',{['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/core'],... +0652 fbcStr}); +0653 end +0654 +0655 if sbmlPackageVersions(1) == 2 +0656 modelSBML.fbc_strict=1; +0657 modelSBML.isSetfbc_strict = 1; 0658 end 0659 -0660 -0661 function modelSBML=getSBMLStructure(sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions) -0662 %Returns the blank SBML model structure by using appropriate libSBML -0663 %functions. This creates structure by considering three levels -0664 -0665 sbmlFieldNames=getStructureFieldnames('model',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0666 sbmlDefaultValues=getDefaultValues('model',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0667 -0668 for i=1:numel(sbmlFieldNames) -0669 modelSBML.(sbmlFieldNames{1,i})=sbmlDefaultValues{1,i}; -0670 sbmlSubfieldNames=getStructureFieldnames(sbmlFieldNames{1,i},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0671 sbmlSubfieldValues=getDefaultValues(sbmlFieldNames{1,i},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0672 if ~strcmp(sbmlFieldNames{1,i},'event') && ~strcmp(sbmlFieldNames{1,i},'functionDefinition') && ~strcmp(sbmlFieldNames{1,i},'initialAssignment') -0673 for j=1:numel(sbmlSubfieldNames) -0674 modelSBML.(sbmlFieldNames{1,i}).(sbmlSubfieldNames{1,j})=sbmlSubfieldValues{1,j}; -0675 sbmlSubsubfieldNames=getStructureFieldnames(sbmlSubfieldNames{1,j},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0676 sbmlSubsubfieldValues=getDefaultValues(sbmlSubfieldNames{1,j},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0677 if ~strcmp(sbmlSubfieldNames{1,j},'modifier') && ~strcmp(sbmlSubfieldNames{1,j},'kineticLaw') -0678 for k=1:numel(sbmlSubsubfieldNames) -0679 %'compartment' and 'species' fields are not supposed to -0680 %have their standalone structures if they are subfields -0681 %or subsubfields -0682 if ~strcmp(sbmlSubfieldNames{1,j},'compartment') && ~strcmp(sbmlSubfieldNames{1,j},'species') -0683 modelSBML.(sbmlFieldNames{1,i}).(sbmlSubfieldNames{1,j}).(sbmlSubsubfieldNames{1,k})=sbmlSubsubfieldValues{1,k}; -0684 end -0685 %If it is fbc_association in the third level, we need -0686 %to establish the fourth level, since libSBML requires -0687 %it -0688 if strcmp(sbmlSubsubfieldNames{1,k},'fbc_association') -0689 fbc_associationFieldNames=getStructureFieldnames('fbc_association',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0690 fbc_associationFieldValues=getDefaultValues('fbc_association',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0691 for l=1:numel(fbc_associationFieldNames) -0692 modelSBML.(sbmlFieldNames{1,i}).(sbmlSubfieldNames{1,j}).(sbmlSubsubfieldNames{1,k}).(fbc_associationFieldNames{1,l})=fbc_associationFieldValues{1,l}; -0693 end -0694 end -0695 end -0696 end -0697 end -0698 end -0699 if ~isstruct(modelSBML.(sbmlFieldNames{1,i})) -0700 modelSBML.(sbmlFieldNames{1,i})=sbmlDefaultValues{1,i}; -0701 end -0702 end -0703 -0704 modelSBML.unitDefinition.id='mmol_per_gDW_per_hr'; -0705 -0706 unitFieldNames=getStructureFieldnames('unit',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0707 unitDefaultValues=getDefaultValues('unit',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); -0708 -0709 kinds={'mole','gram','second'}; -0710 exponents=[1 -1 -1]; -0711 scales=[-3 0 0]; -0712 multipliers=[1 1 1*60*60]; -0713 -0714 for i=1:numel(unitFieldNames) -0715 modelSBML.unitDefinition.unit(1).(unitFieldNames{1,i})=unitDefaultValues{1,i}; -0716 for j=1:3 -0717 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=unitDefaultValues{1,i}; -0718 if strcmp(unitFieldNames{1,i},'kind') -0719 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=kinds{j}; -0720 elseif strcmp(unitFieldNames{1,i},'exponent') -0721 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=exponents(j); -0722 elseif strcmp(unitFieldNames{1,i},'scale') -0723 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=scales(j); -0724 elseif strcmp(unitFieldNames{1,i},'multiplier') -0725 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=multipliers(j); -0726 end -0727 end -0728 end -0729 end -0730 -0731 function miriamString=getMiriam(miriamStruct) -0732 %Returns a string with list elements for a miriam structure ('<rdf:li -0733 %rdf:resource="https://identifiers.org/go/GO:0005739"/>' for example). This -0734 %is just to speed up things since this is done many times during the -0735 %exporting -0736 -0737 miriamString=''; -0738 if isfield(miriamStruct,'name') -0739 for i=1:numel(miriamStruct.name) -0740 miriamString=[miriamString '<rdf:li rdf:resource="https://identifiers.org/' miriamStruct.name{i} '/' miriamStruct.value{i} '"/>']; -0741 end -0742 end -0743 end -0744 -0745 function [tmp_Rxn]=addReactantsProducts(model,sbmlModel,i) -0746 %This function provides reactants and products for particular reaction. The -0747 %function was 'borrowed' from writeSBML in COBRA toolbox, lines 663-679 -0748 -0749 met_idx = find(model.S(:, i)); -0750 tmp_Rxn.product=[]; -0751 tmp_Rxn.reactant=[]; -0752 for j_met=1:size(met_idx,1) -0753 tmp_idx = met_idx(j_met,1); -0754 sbml_tmp_species_ref.species = sbmlModel.species(tmp_idx).id; -0755 met_stoich = model.S(tmp_idx, i); -0756 sbml_tmp_species_ref.stoichiometry = abs(met_stoich); -0757 sbml_tmp_species_ref.isSetStoichiometry=1; -0758 sbml_tmp_species_ref.constant=1; -0759 if (met_stoich > 0) -0760 tmp_Rxn.product = [ tmp_Rxn.product, sbml_tmp_species_ref ]; -0761 else -0762 tmp_Rxn.reactant = [ tmp_Rxn.reactant, sbml_tmp_species_ref]; -0763 end -0764 end -0765 end -0766 -0767 function vecT = columnVector(vec) -0768 % Code below taken from COBRA Toolbox under GNU General Public License v3.0 -0769 % license file in readme/GPL.MD. -0770 % -0771 % Converts a vector to a column vector -0772 % -0773 % USAGE: -0774 % -0775 % vecT = columnVector(vec) -0776 % -0777 % INPUT: -0778 % vec: a vector +0660 modelSBML.rule=[]; +0661 modelSBML.constraint=[]; +0662 +0663 [ravenDir,prevDir]=findRAVENroot(); +0664 fileName=checkFileExistence(fileName,1,true,false); +0665 +0666 OutputSBML_RAVEN(modelSBML,fileName,1,0,[1,0]); +0667 end +0668 +0669 +0670 function modelSBML=getSBMLStructure(sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions) +0671 %Returns the blank SBML model structure by using appropriate libSBML +0672 %functions. This creates structure by considering three levels +0673 +0674 sbmlFieldNames=getStructureFieldnames('model',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0675 sbmlDefaultValues=getDefaultValues('model',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0676 +0677 for i=1:numel(sbmlFieldNames) +0678 modelSBML.(sbmlFieldNames{1,i})=sbmlDefaultValues{1,i}; +0679 sbmlSubfieldNames=getStructureFieldnames(sbmlFieldNames{1,i},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0680 sbmlSubfieldValues=getDefaultValues(sbmlFieldNames{1,i},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0681 if ~strcmp(sbmlFieldNames{1,i},'event') && ~strcmp(sbmlFieldNames{1,i},'functionDefinition') && ~strcmp(sbmlFieldNames{1,i},'initialAssignment') +0682 for j=1:numel(sbmlSubfieldNames) +0683 modelSBML.(sbmlFieldNames{1,i}).(sbmlSubfieldNames{1,j})=sbmlSubfieldValues{1,j}; +0684 sbmlSubsubfieldNames=getStructureFieldnames(sbmlSubfieldNames{1,j},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0685 sbmlSubsubfieldValues=getDefaultValues(sbmlSubfieldNames{1,j},sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0686 if ~strcmp(sbmlSubfieldNames{1,j},'modifier') && ~strcmp(sbmlSubfieldNames{1,j},'kineticLaw') +0687 for k=1:numel(sbmlSubsubfieldNames) +0688 %'compartment' and 'species' fields are not supposed to +0689 %have their standalone structures if they are subfields +0690 %or subsubfields +0691 if ~strcmp(sbmlSubfieldNames{1,j},'compartment') && ~strcmp(sbmlSubfieldNames{1,j},'species') +0692 modelSBML.(sbmlFieldNames{1,i}).(sbmlSubfieldNames{1,j}).(sbmlSubsubfieldNames{1,k})=sbmlSubsubfieldValues{1,k}; +0693 end +0694 %If it is fbc_association in the third level, we need +0695 %to establish the fourth level, since libSBML requires +0696 %it +0697 if strcmp(sbmlSubsubfieldNames{1,k},'fbc_association') +0698 fbc_associationFieldNames=getStructureFieldnames('fbc_association',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0699 fbc_associationFieldValues=getDefaultValues('fbc_association',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0700 for l=1:numel(fbc_associationFieldNames) +0701 modelSBML.(sbmlFieldNames{1,i}).(sbmlSubfieldNames{1,j}).(sbmlSubsubfieldNames{1,k}).(fbc_associationFieldNames{1,l})=fbc_associationFieldValues{1,l}; +0702 end +0703 end +0704 end +0705 end +0706 end +0707 end +0708 if ~isstruct(modelSBML.(sbmlFieldNames{1,i})) +0709 modelSBML.(sbmlFieldNames{1,i})=sbmlDefaultValues{1,i}; +0710 end +0711 end +0712 +0713 modelSBML.unitDefinition.id='mmol_per_gDW_per_hr'; +0714 +0715 unitFieldNames=getStructureFieldnames('unit',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0716 unitDefaultValues=getDefaultValues('unit',sbmlLevel,sbmlVersion,sbmlPackages,sbmlPackageVersions); +0717 +0718 kinds={'mole','gram','second'}; +0719 exponents=[1 -1 -1]; +0720 scales=[-3 0 0]; +0721 multipliers=[1 1 1*60*60]; +0722 +0723 for i=1:numel(unitFieldNames) +0724 modelSBML.unitDefinition.unit(1).(unitFieldNames{1,i})=unitDefaultValues{1,i}; +0725 for j=1:3 +0726 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=unitDefaultValues{1,i}; +0727 if strcmp(unitFieldNames{1,i},'kind') +0728 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=kinds{j}; +0729 elseif strcmp(unitFieldNames{1,i},'exponent') +0730 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=exponents(j); +0731 elseif strcmp(unitFieldNames{1,i},'scale') +0732 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=scales(j); +0733 elseif strcmp(unitFieldNames{1,i},'multiplier') +0734 modelSBML.unitDefinition.unit(j).(unitFieldNames{1,i})=multipliers(j); +0735 end +0736 end +0737 end +0738 end +0739 +0740 function miriamString=getMiriam(miriamStruct) +0741 %Returns a string with list elements for a miriam structure ('<rdf:li +0742 %rdf:resource="https://identifiers.org/go/GO:0005739"/>' for example). This +0743 %is just to speed up things since this is done many times during the +0744 %exporting +0745 +0746 miriamString=''; +0747 if isfield(miriamStruct,'name') +0748 for i=1:numel(miriamStruct.name) +0749 miriamString=[miriamString '<rdf:li rdf:resource="https://identifiers.org/' miriamStruct.name{i} '/' miriamStruct.value{i} '"/>']; +0750 end +0751 end +0752 end +0753 +0754 function [tmp_Rxn]=addReactantsProducts(model,sbmlModel,i) +0755 %This function provides reactants and products for particular reaction. The +0756 %function was 'borrowed' from writeSBML in COBRA toolbox, lines 663-679 +0757 +0758 met_idx = find(model.S(:, i)); +0759 tmp_Rxn.product=[]; +0760 tmp_Rxn.reactant=[]; +0761 for j_met=1:size(met_idx,1) +0762 tmp_idx = met_idx(j_met,1); +0763 sbml_tmp_species_ref.species = sbmlModel.species(tmp_idx).id; +0764 met_stoich = model.S(tmp_idx, i); +0765 sbml_tmp_species_ref.stoichiometry = abs(met_stoich); +0766 sbml_tmp_species_ref.isSetStoichiometry=1; +0767 sbml_tmp_species_ref.constant=1; +0768 if (met_stoich > 0) +0769 tmp_Rxn.product = [ tmp_Rxn.product, sbml_tmp_species_ref ]; +0770 else +0771 tmp_Rxn.reactant = [ tmp_Rxn.reactant, sbml_tmp_species_ref]; +0772 end +0773 end +0774 end +0775 +0776 function vecT = columnVector(vec) +0777 % Code below taken from COBRA Toolbox under GNU General Public License v3.0 +0778 % license file in readme/GPL.MD. 0779 % -0780 % OUTPUT: -0781 % vecT: a column vector -0782 -0783 [n, m] = size(vec); -0784 -0785 if n < m -0786 vecT = vec'; -0787 else -0788 vecT = vec; -0789 end -0790 end

    +0780 % Converts a vector to a column vector +0781 % +0782 % USAGE: +0783 % +0784 % vecT = columnVector(vec) +0785 % +0786 % INPUT: +0787 % vec: a vector +0788 % +0789 % OUTPUT: +0790 % vecT: a column vector +0791 +0792 [n, m] = size(vec); +0793 +0794 if n < m +0795 vecT = vec'; +0796 else +0797 vecT = vec; +0798 end +0799 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/exportToExcelFormat.html b/doc/io/exportToExcelFormat.html index 70b7328f..72adbf32 100644 --- a/doc/io/exportToExcelFormat.html +++ b/doc/io/exportToExcelFormat.html @@ -243,214 +243,217 @@

    SOURCE CODE ^''; 0186 if isfield(model,'subSystems') 0187 for i=1:numel(model.subSystems) -0188 if ~isempty(model.subSystems{i,1}) -0189 subsystems{i,1}=strjoin(model.subSystems{i,1},';'); -0190 else -0191 subsystems{i,1}=''; -0192 end -0193 end -0194 rxnSheet=[rxnSheet subsystems]; -0195 else -0196 rxnSheet=[rxnSheet emptyColumn]; -0197 end -0198 -0199 %For REPLACEMENT ID which isn't in the model -0200 rxnSheet=[rxnSheet emptyColumn]; +0188 if ~iscell(model.subSystems{i}) +0189 model.subSystems{i} = {model.subSystems{i}}; +0190 end +0191 if ~isempty(model.subSystems{i,1}) +0192 subsystems{i,1}=strjoin(model.subSystems{i,1},';'); +0193 else +0194 subsystems{i,1}=''; +0195 end +0196 end +0197 rxnSheet=[rxnSheet subsystems]; +0198 else +0199 rxnSheet=[rxnSheet emptyColumn]; +0200 end 0201 -0202 if isfield(model,'rxnNotes') -0203 rxnSheet=[rxnSheet model.rxnNotes]; -0204 else -0205 rxnSheet=[rxnSheet emptyColumn]; -0206 end -0207 -0208 if isfield(model,'rxnReferences') -0209 rxnSheet=[rxnSheet model.rxnReferences]; -0210 else -0211 rxnSheet=[rxnSheet emptyColumn]; -0212 end -0213 -0214 if isfield(model,'rxnConfidenceScores') -0215 rxnSheet=[rxnSheet num2cell(model.rxnConfidenceScores)]; -0216 else -0217 rxnSheet=[rxnSheet emptyColumn]; -0218 end -0219 -0220 wb=writeSheet(wb,'RXNS',0,headers,[],rxnSheet); -0221 -0222 headers={'#';'ID';'NAME';'UNCONSTRAINED';'MIRIAM';'COMPOSITION';'InChI';'COMPARTMENT';'REPLACEMENT ID';'CHARGE'}; -0223 -0224 metSheet=cell(numel(model.mets),numel(headers)); -0225 -0226 for i=1:numel(model.mets) -0227 metSheet{i,2}=[model.metNames{i} '[' model.comps{model.metComps(i)} ']']; -0228 -0229 if isfield(model,'metNames') -0230 metSheet(i,3)=model.metNames(i); -0231 end -0232 -0233 if isfield(model,'unconstrained') -0234 if model.unconstrained(i)~=0 -0235 metSheet{i,4}=true; -0236 end -0237 end -0238 -0239 if isfield(model,'metMiriams') -0240 if ~isempty(model.metMiriams{i}) -0241 toPrint=[]; -0242 for j=1:numel(model.metMiriams{i}.name) -0243 toPrint=[toPrint strtrim(model.metMiriams{i}.name{j}) '/' strtrim(model.metMiriams{i}.value{j}) ';']; -0244 end -0245 metSheet{i,5}=toPrint(1:end-1); -0246 end -0247 end -0248 -0249 % Making sure that only these metFormulas are exported, which don't -0250 % have InChI strings -0251 if isfield(model,'metFormulas') -0252 if isfield(model,'inchis') -0253 if isempty(model.inchis{i}) -0254 metSheet(i,6)=model.metFormulas(i); -0255 end -0256 else -0257 metSheet(i,6)=model.metFormulas(i); -0258 end -0259 end -0260 -0261 if isfield(model,'inchis') -0262 metSheet(i,7)=model.inchis(i); -0263 end -0264 -0265 if isfield(model,'metComps') -0266 metSheet(i,8)=model.comps(model.metComps(i)); -0267 end -0268 -0269 metSheet(i,9)=model.mets(i); -0270 -0271 if isfield(model,'metCharges') -0272 metSheet{i,10}=model.metCharges(i); -0273 end -0274 end -0275 -0276 wb=writeSheet(wb,'METS',1,headers,[],metSheet); -0277 -0278 %Add the COMPS sheet -0279 -0280 %Create the header row -0281 headers={'#';'ABBREVIATION';'NAME';'INSIDE';'MIRIAM'}; +0202 %For REPLACEMENT ID which isn't in the model +0203 rxnSheet=[rxnSheet emptyColumn]; +0204 +0205 if isfield(model,'rxnNotes') +0206 rxnSheet=[rxnSheet model.rxnNotes]; +0207 else +0208 rxnSheet=[rxnSheet emptyColumn]; +0209 end +0210 +0211 if isfield(model,'rxnReferences') +0212 rxnSheet=[rxnSheet model.rxnReferences]; +0213 else +0214 rxnSheet=[rxnSheet emptyColumn]; +0215 end +0216 +0217 if isfield(model,'rxnConfidenceScores') +0218 rxnSheet=[rxnSheet num2cell(model.rxnConfidenceScores)]; +0219 else +0220 rxnSheet=[rxnSheet emptyColumn]; +0221 end +0222 +0223 wb=writeSheet(wb,'RXNS',0,headers,[],rxnSheet); +0224 +0225 headers={'#';'ID';'NAME';'UNCONSTRAINED';'MIRIAM';'COMPOSITION';'InChI';'COMPARTMENT';'REPLACEMENT ID';'CHARGE'}; +0226 +0227 metSheet=cell(numel(model.mets),numel(headers)); +0228 +0229 for i=1:numel(model.mets) +0230 metSheet{i,2}=[model.metNames{i} '[' model.comps{model.metComps(i)} ']']; +0231 +0232 if isfield(model,'metNames') +0233 metSheet(i,3)=model.metNames(i); +0234 end +0235 +0236 if isfield(model,'unconstrained') +0237 if model.unconstrained(i)~=0 +0238 metSheet{i,4}=true; +0239 end +0240 end +0241 +0242 if isfield(model,'metMiriams') +0243 if ~isempty(model.metMiriams{i}) +0244 toPrint=[]; +0245 for j=1:numel(model.metMiriams{i}.name) +0246 toPrint=[toPrint strtrim(model.metMiriams{i}.name{j}) '/' strtrim(model.metMiriams{i}.value{j}) ';']; +0247 end +0248 metSheet{i,5}=toPrint(1:end-1); +0249 end +0250 end +0251 +0252 % Making sure that only these metFormulas are exported, which don't +0253 % have InChI strings +0254 if isfield(model,'metFormulas') +0255 if isfield(model,'inchis') +0256 if isempty(model.inchis{i}) +0257 metSheet(i,6)=model.metFormulas(i); +0258 end +0259 else +0260 metSheet(i,6)=model.metFormulas(i); +0261 end +0262 end +0263 +0264 if isfield(model,'inchis') +0265 metSheet(i,7)=model.inchis(i); +0266 end +0267 +0268 if isfield(model,'metComps') +0269 metSheet(i,8)=model.comps(model.metComps(i)); +0270 end +0271 +0272 metSheet(i,9)=model.mets(i); +0273 +0274 if isfield(model,'metCharges') +0275 metSheet{i,10}=model.metCharges(i); +0276 end +0277 end +0278 +0279 wb=writeSheet(wb,'METS',1,headers,[],metSheet); +0280 +0281 %Add the COMPS sheet 0282 -0283 compSheet=cell(numel(model.comps),numel(headers)); -0284 -0285 for i=1:numel(model.comps) -0286 compSheet(i,2)=model.comps(i); -0287 -0288 if isfield(model,'compNames') -0289 compSheet(i,3)=model.compNames(i); -0290 end -0291 -0292 if isfield(model,'compOutside') -0293 compSheet(i,4)=model.compOutside(i); -0294 end -0295 -0296 if isfield(model,'compMiriams') -0297 if ~isempty(model.compMiriams{i}) -0298 toPrint=[]; -0299 for j=1:numel(model.compMiriams{i}.name) -0300 toPrint=[toPrint strtrim(model.compMiriams{i}.name{j}) '/' strtrim(model.compMiriams{i}.value{j}) ';']; -0301 end -0302 compSheet{i,5}=toPrint(1:end-1); -0303 end -0304 end -0305 end -0306 -0307 wb=writeSheet(wb,'COMPS',2,headers,[],compSheet); -0308 -0309 %Add the GENES sheet -0310 if isfield(model,'genes') -0311 %Create the header row -0312 headers={'#';'NAME';'MIRIAM';'SHORT NAME';'COMPARTMENT'}; -0313 -0314 geneSheet=cell(numel(model.genes),numel(headers)); -0315 -0316 for i=1:numel(model.genes) -0317 geneSheet(i,2)=model.genes(i); -0318 -0319 if isfield(model,'geneMiriams') -0320 if ~isempty(model.geneMiriams{i}) -0321 toPrint=[]; -0322 for j=1:numel(model.geneMiriams{i}.name) -0323 toPrint=[toPrint strtrim(model.geneMiriams{i}.name{j}) '/' strtrim(model.geneMiriams{i}.value{j}) ';']; -0324 end -0325 geneSheet{i,3}=toPrint(1:end-1); -0326 end -0327 end -0328 if isfield(model,'geneShortNames') -0329 geneSheet(i,4)=model.geneShortNames(i); +0283 %Create the header row +0284 headers={'#';'ABBREVIATION';'NAME';'INSIDE';'MIRIAM'}; +0285 +0286 compSheet=cell(numel(model.comps),numel(headers)); +0287 +0288 for i=1:numel(model.comps) +0289 compSheet(i,2)=model.comps(i); +0290 +0291 if isfield(model,'compNames') +0292 compSheet(i,3)=model.compNames(i); +0293 end +0294 +0295 if isfield(model,'compOutside') +0296 compSheet(i,4)=model.compOutside(i); +0297 end +0298 +0299 if isfield(model,'compMiriams') +0300 if ~isempty(model.compMiriams{i}) +0301 toPrint=[]; +0302 for j=1:numel(model.compMiriams{i}.name) +0303 toPrint=[toPrint strtrim(model.compMiriams{i}.name{j}) '/' strtrim(model.compMiriams{i}.value{j}) ';']; +0304 end +0305 compSheet{i,5}=toPrint(1:end-1); +0306 end +0307 end +0308 end +0309 +0310 wb=writeSheet(wb,'COMPS',2,headers,[],compSheet); +0311 +0312 %Add the GENES sheet +0313 if isfield(model,'genes') +0314 %Create the header row +0315 headers={'#';'NAME';'MIRIAM';'SHORT NAME';'COMPARTMENT'}; +0316 +0317 geneSheet=cell(numel(model.genes),numel(headers)); +0318 +0319 for i=1:numel(model.genes) +0320 geneSheet(i,2)=model.genes(i); +0321 +0322 if isfield(model,'geneMiriams') +0323 if ~isempty(model.geneMiriams{i}) +0324 toPrint=[]; +0325 for j=1:numel(model.geneMiriams{i}.name) +0326 toPrint=[toPrint strtrim(model.geneMiriams{i}.name{j}) '/' strtrim(model.geneMiriams{i}.value{j}) ';']; +0327 end +0328 geneSheet{i,3}=toPrint(1:end-1); +0329 end 0330 end -0331 if isfield(model,'geneComps') -0332 geneSheet(i,5)=model.comps(model.geneComps(i)); +0331 if isfield(model,'geneShortNames') +0332 geneSheet(i,4)=model.geneShortNames(i); 0333 end -0334 end -0335 -0336 wb=writeSheet(wb,'GENES',3,headers,[],geneSheet); -0337 end -0338 -0339 %Add the MODEL sheet -0340 -0341 %Create the header row -0342 headers={'#';'ID';'NAME';'TAXONOMY';'DEFAULT LOWER';'DEFAULT UPPER';'CONTACT GIVEN NAME';'CONTACT FAMILY NAME';'CONTACT EMAIL';'ORGANIZATION';'NOTES'}; +0334 if isfield(model,'geneComps') +0335 geneSheet(i,5)=model.comps(model.geneComps(i)); +0336 end +0337 end +0338 +0339 wb=writeSheet(wb,'GENES',3,headers,[],geneSheet); +0340 end +0341 +0342 %Add the MODEL sheet 0343 -0344 modelSheet=cell(1,numel(headers)); -0345 -0346 if ~isfield(model,'annotation') -0347 model.annotation = []; -0348 end -0349 -0350 if isfield(model,'id') -0351 modelSheet{1,2}=model.id; -0352 else -0353 modelSheet{1,2}='blankID'; -0354 end -0355 if isfield(model,'name') -0356 modelSheet{1,3}=model.name; -0357 else -0358 modelSheet{1,3}='blankName'; -0359 end -0360 if isfield(model.annotation,'taxonomy') -0361 modelSheet{1,4}=model.annotation.taxonomy; +0344 %Create the header row +0345 headers={'#';'ID';'NAME';'TAXONOMY';'DEFAULT LOWER';'DEFAULT UPPER';'CONTACT GIVEN NAME';'CONTACT FAMILY NAME';'CONTACT EMAIL';'ORGANIZATION';'NOTES'}; +0346 +0347 modelSheet=cell(1,numel(headers)); +0348 +0349 if ~isfield(model,'annotation') +0350 model.annotation = []; +0351 end +0352 +0353 if isfield(model,'id') +0354 modelSheet{1,2}=model.id; +0355 else +0356 modelSheet{1,2}='blankID'; +0357 end +0358 if isfield(model,'name') +0359 modelSheet{1,3}=model.name; +0360 else +0361 modelSheet{1,3}='blankName'; 0362 end -0363 if isfield(model.annotation,'defaultLB') -0364 modelSheet{1,5}=model.annotation.defaultLB; +0363 if isfield(model.annotation,'taxonomy') +0364 modelSheet{1,4}=model.annotation.taxonomy; 0365 end -0366 if isfield(model.annotation,'defaultUB') -0367 modelSheet{1,6}=model.annotation.defaultUB; +0366 if isfield(model.annotation,'defaultLB') +0367 modelSheet{1,5}=model.annotation.defaultLB; 0368 end -0369 if isfield(model.annotation,'givenName') -0370 modelSheet{1,7}=model.annotation.givenName; +0369 if isfield(model.annotation,'defaultUB') +0370 modelSheet{1,6}=model.annotation.defaultUB; 0371 end -0372 if isfield(model.annotation,'familyName') -0373 modelSheet{1,8}=model.annotation.familyName; +0372 if isfield(model.annotation,'givenName') +0373 modelSheet{1,7}=model.annotation.givenName; 0374 end -0375 if isfield(model.annotation,'email') -0376 modelSheet{1,9}=model.annotation.email; +0375 if isfield(model.annotation,'familyName') +0376 modelSheet{1,8}=model.annotation.familyName; 0377 end -0378 if isfield(model.annotation,'organization') -0379 modelSheet{1,10}=model.annotation.organization; +0378 if isfield(model.annotation,'email') +0379 modelSheet{1,9}=model.annotation.email; 0380 end -0381 if isfield(model.annotation,'note') -0382 modelSheet{1,11}=model.annotation.note; +0381 if isfield(model.annotation,'organization') +0382 modelSheet{1,10}=model.annotation.organization; 0383 end -0384 -0385 if isfield(model,'genes') -0386 wb=writeSheet(wb,'MODEL',4,headers,[],modelSheet); -0387 else -0388 wb=writeSheet(wb,'MODEL',3,headers,[],modelSheet); -0389 end -0390 -0391 %Open the output stream -0392 out = FileOutputStream(fileName); -0393 wb.write(out); -0394 out.close(); -0395 end +0384 if isfield(model.annotation,'note') +0385 modelSheet{1,11}=model.annotation.note; +0386 end +0387 +0388 if isfield(model,'genes') +0389 wb=writeSheet(wb,'MODEL',4,headers,[],modelSheet); +0390 else +0391 wb=writeSheet(wb,'MODEL',3,headers,[],modelSheet); +0392 end +0393 +0394 %Open the output stream +0395 out = FileOutputStream(fileName); +0396 wb.write(out); +0397 out.close(); +0398 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/exportToTabDelimited.html b/doc/io/exportToTabDelimited.html index 827b0d7e..11fe1e42 100644 --- a/doc/io/exportToTabDelimited.html +++ b/doc/io/exportToTabDelimited.html @@ -167,238 +167,241 @@

    SOURCE CODE ^if isfield(model,'subSystems') 0108 if ~isempty(model.subSystems{i}) -0109 fprintf(rxnFile,[strjoin(model.subSystems{i,1},';') '\t']); -0110 else -0111 fprintf(rxnFile,'\t'); -0112 end -0113 end -0114 -0115 %Print replacement IDs -0116 fprintf(rxnFile,'\t'); +0109 if ~iscell(model.subSystems{i}) +0110 model.subSystems{i} = {model.subSystems{i}}; +0111 end +0112 fprintf(rxnFile,[strjoin(model.subSystems{i,1},';') '\t']); +0113 else +0114 fprintf(rxnFile,'\t'); +0115 end +0116 end 0117 -0118 if isfield(model,'rxnNotes') -0119 fprintf(rxnFile,[model.rxnNotes{i} '\t']); -0120 else -0121 fprintf(rxnFile,'\t'); -0122 end -0123 -0124 if isfield(model,'rxnReferences') -0125 fprintf(rxnFile,[model.rxnReferences{i} '\t']); -0126 else -0127 fprintf(rxnFile,'\t'); -0128 end -0129 -0130 if isfield(model,'rxnConfidenceScores') -0131 fprintf(rxnFile,[num2str(model.rxnConfidenceScores(i)) '\t' ]); -0132 else -0133 fprintf(rxnFile,'\t'); -0134 end -0135 -0136 fprintf(rxnFile,'\n'); -0137 end -0138 -0139 fclose(rxnFile); -0140 -0141 %Open for printing the metabolites sheet -0142 metFile=fopen(fullfile(path,'excelMets.txt'),'wt'); +0118 %Print replacement IDs +0119 fprintf(rxnFile,'\t'); +0120 +0121 if isfield(model,'rxnNotes') +0122 fprintf(rxnFile,[model.rxnNotes{i} '\t']); +0123 else +0124 fprintf(rxnFile,'\t'); +0125 end +0126 +0127 if isfield(model,'rxnReferences') +0128 fprintf(rxnFile,[model.rxnReferences{i} '\t']); +0129 else +0130 fprintf(rxnFile,'\t'); +0131 end +0132 +0133 if isfield(model,'rxnConfidenceScores') +0134 fprintf(rxnFile,[num2str(model.rxnConfidenceScores(i)) '\t' ]); +0135 else +0136 fprintf(rxnFile,'\t'); +0137 end +0138 +0139 fprintf(rxnFile,'\n'); +0140 end +0141 +0142 fclose(rxnFile); 0143 -0144 %Print header -0145 fprintf(metFile,'#\tID\tNAME\tUNCONSTRAINED\tMIRIAM\tCOMPOSITION\tInChI\tCOMPARTMENT\tREPLACEMENT ID\tMETS FIELD\tCHARGE\n'); +0144 %Open for printing the metabolites sheet +0145 metFile=fopen(fullfile(path,'excelMets.txt'),'wt'); 0146 -0147 %Loop through the metabolites -0148 for i=1:numel(model.mets) -0149 fprintf(metFile,['\t' model.metNames{i} '[' model.comps{model.metComps(i)} ']\t' model.metNames{i} '\t']); -0150 -0151 if isfield(model,'unconstrained') -0152 if model.unconstrained(i)~=0 -0153 fprintf(metFile,'TRUE\t'); -0154 else -0155 fprintf(metFile,'\t'); -0156 end -0157 else -0158 fprintf(metFile,'\t'); -0159 end -0160 -0161 if isfield(model,'metMiriams') -0162 if ~isempty(model.metMiriams{i}) -0163 toPrint=[]; -0164 for j=1:numel(model.metMiriams{i}.name) -0165 toPrint=[toPrint strtrim(model.metMiriams{i}.name{j}) '/' strtrim(model.metMiriams{i}.value{j}) ';']; -0166 end -0167 fprintf(rxnFile,[toPrint(1:end-1) '\t']); -0168 else -0169 fprintf(metFile,'\t'); -0170 end -0171 else -0172 fprintf(metFile,'\t'); -0173 end -0174 -0175 if isfield(model,'metFormulas') -0176 fprintf(metFile,[model.metFormulas{i} '\t']); -0177 else -0178 fprintf(metFile,'\t'); -0179 end -0180 -0181 if isfield(model,'inchis') -0182 fprintf(metFile,[model.inchis{i} '\t']); -0183 else -0184 fprintf(metFile,'\t'); -0185 end -0186 -0187 fprintf(metFile,[model.comps{model.metComps(i)} '\t']); -0188 -0189 %There can be no replacement IDs in the structure, but it has to be -0190 %something to give working met IDs. -0191 fprintf(metFile,['m' int2str(i) '\t']); -0192 -0193 %Print the model.mets field. The reason for not putting this as -0194 %replacement ID is that it's not guaranteed to be a valid SBML id. -0195 fprintf(metFile,[model.mets{i} '\t']); -0196 -0197 if isfield(model,'metCharges') -0198 fprintf(metFile,[num2str(model.metCharges(i)) '\t']); -0199 else -0200 fprintf(metFile,'\t'); -0201 end -0202 -0203 fprintf(metFile,'\n'); -0204 end -0205 -0206 fclose(metFile); -0207 -0208 if isfield(model,'genes') -0209 %Open for printing the genes sheet -0210 geneFile=fopen(fullfile(path,'excelGenes.txt'),'wt'); -0211 -0212 %Print header -0213 fprintf(geneFile,'#\tNAME\tMIRIAM\tSHORT NAME\tCOMPARTMENT\n'); +0147 %Print header +0148 fprintf(metFile,'#\tID\tNAME\tUNCONSTRAINED\tMIRIAM\tCOMPOSITION\tInChI\tCOMPARTMENT\tREPLACEMENT ID\tMETS FIELD\tCHARGE\n'); +0149 +0150 %Loop through the metabolites +0151 for i=1:numel(model.mets) +0152 fprintf(metFile,['\t' model.metNames{i} '[' model.comps{model.metComps(i)} ']\t' model.metNames{i} '\t']); +0153 +0154 if isfield(model,'unconstrained') +0155 if model.unconstrained(i)~=0 +0156 fprintf(metFile,'TRUE\t'); +0157 else +0158 fprintf(metFile,'\t'); +0159 end +0160 else +0161 fprintf(metFile,'\t'); +0162 end +0163 +0164 if isfield(model,'metMiriams') +0165 if ~isempty(model.metMiriams{i}) +0166 toPrint=[]; +0167 for j=1:numel(model.metMiriams{i}.name) +0168 toPrint=[toPrint strtrim(model.metMiriams{i}.name{j}) '/' strtrim(model.metMiriams{i}.value{j}) ';']; +0169 end +0170 fprintf(rxnFile,[toPrint(1:end-1) '\t']); +0171 else +0172 fprintf(metFile,'\t'); +0173 end +0174 else +0175 fprintf(metFile,'\t'); +0176 end +0177 +0178 if isfield(model,'metFormulas') +0179 fprintf(metFile,[model.metFormulas{i} '\t']); +0180 else +0181 fprintf(metFile,'\t'); +0182 end +0183 +0184 if isfield(model,'inchis') +0185 fprintf(metFile,[model.inchis{i} '\t']); +0186 else +0187 fprintf(metFile,'\t'); +0188 end +0189 +0190 fprintf(metFile,[model.comps{model.metComps(i)} '\t']); +0191 +0192 %There can be no replacement IDs in the structure, but it has to be +0193 %something to give working met IDs. +0194 fprintf(metFile,['m' int2str(i) '\t']); +0195 +0196 %Print the model.mets field. The reason for not putting this as +0197 %replacement ID is that it's not guaranteed to be a valid SBML id. +0198 fprintf(metFile,[model.mets{i} '\t']); +0199 +0200 if isfield(model,'metCharges') +0201 fprintf(metFile,[num2str(model.metCharges(i)) '\t']); +0202 else +0203 fprintf(metFile,'\t'); +0204 end +0205 +0206 fprintf(metFile,'\n'); +0207 end +0208 +0209 fclose(metFile); +0210 +0211 if isfield(model,'genes') +0212 %Open for printing the genes sheet +0213 geneFile=fopen(fullfile(path,'excelGenes.txt'),'wt'); 0214 -0215 %Loop through the genes -0216 for i=1:numel(model.genes) -0217 fprintf(geneFile,['\t' model.genes{i} '\t']); -0218 -0219 if isfield(model,'geneMiriams') -0220 if ~isempty(model.geneMiriams{i}) -0221 toPrint=[]; -0222 for j=1:numel(model.geneMiriams{i}.name) -0223 toPrint=[toPrint strtrim(model.geneMiriams{i}.name{j}) '/' strtrim(model.geneMiriams{i}.value{j}) ';']; -0224 end -0225 fprintf(geneFile,[toPrint(1:end-1) '\t']); -0226 else -0227 fprintf(geneFile,'\t'); -0228 end -0229 else -0230 fprintf(geneFile,'\t'); -0231 end -0232 -0233 if isfield(model,'geneShortNames') -0234 fprintf(geneFile,[model.geneShortNames{i} '\t']); -0235 else -0236 fprintf(geneFile,'\t'); -0237 end -0238 -0239 if isfield(model,'geneComps') -0240 fprintf(geneFile,[model.comps{model.geneComps(i)} '\t']); -0241 else -0242 fprintf(geneFile,'\t'); -0243 end -0244 -0245 fprintf(geneFile,'\n'); -0246 end -0247 fclose(geneFile); -0248 end -0249 -0250 if isfield(model,'id') -0251 %Open for printing the model sheet -0252 modelFile=fopen(fullfile(path,'excelModel.txt'),'wt'); -0253 -0254 %Print header -0255 fprintf(geneFile,'#\tID\tNAME\tDEFAULT LOWER\tDEFAULT UPPER\tCONTACT GIVEN NAME\tCONTACT FAMILY NAME\tCONTACT EMAIL\tORGANIZATION\tTAXONOMY\tNOTES\n'); +0215 %Print header +0216 fprintf(geneFile,'#\tNAME\tMIRIAM\tSHORT NAME\tCOMPARTMENT\n'); +0217 +0218 %Loop through the genes +0219 for i=1:numel(model.genes) +0220 fprintf(geneFile,['\t' model.genes{i} '\t']); +0221 +0222 if isfield(model,'geneMiriams') +0223 if ~isempty(model.geneMiriams{i}) +0224 toPrint=[]; +0225 for j=1:numel(model.geneMiriams{i}.name) +0226 toPrint=[toPrint strtrim(model.geneMiriams{i}.name{j}) '/' strtrim(model.geneMiriams{i}.value{j}) ';']; +0227 end +0228 fprintf(geneFile,[toPrint(1:end-1) '\t']); +0229 else +0230 fprintf(geneFile,'\t'); +0231 end +0232 else +0233 fprintf(geneFile,'\t'); +0234 end +0235 +0236 if isfield(model,'geneShortNames') +0237 fprintf(geneFile,[model.geneShortNames{i} '\t']); +0238 else +0239 fprintf(geneFile,'\t'); +0240 end +0241 +0242 if isfield(model,'geneComps') +0243 fprintf(geneFile,[model.comps{model.geneComps(i)} '\t']); +0244 else +0245 fprintf(geneFile,'\t'); +0246 end +0247 +0248 fprintf(geneFile,'\n'); +0249 end +0250 fclose(geneFile); +0251 end +0252 +0253 if isfield(model,'id') +0254 %Open for printing the model sheet +0255 modelFile=fopen(fullfile(path,'excelModel.txt'),'wt'); 0256 -0257 %Print model ID and name. It is assumed that the default lower/upper -0258 %bound correspond to min/max of the bounds -0259 toPrint=['\t' model.id '\t' model.name '\t']; -0260 if isfield(model,'annotation') -0261 if isfield(model.annotation,'defaultLB') -0262 toPrint=[toPrint num2str(model.annotation.defaultLB) '\t']; -0263 else -0264 toPrint=[toPrint num2str(min(model.lb)) '\t']; -0265 end -0266 if isfield(model.annotation,'defaultUB') -0267 toPrint=[toPrint num2str(model.annotation.defaultUB) '\t']; -0268 else -0269 toPrint=[toPrint num2str(max(model.ub)) '\t']; -0270 end -0271 if isfield(model.annotation,'givenName') -0272 toPrint=[toPrint model.annotation.givenName '\t']; -0273 else -0274 toPrint=[toPrint '\t']; -0275 end -0276 if isfield(model.annotation,'familyName') -0277 toPrint=[toPrint model.annotation.familyName '\t']; -0278 else -0279 toPrint=[toPrint '\t']; -0280 end -0281 if isfield(model.annotation,'email') -0282 toPrint=[toPrint model.annotation.email '\t']; -0283 else -0284 toPrint=[toPrint '\t']; -0285 end -0286 if isfield(model.annotation,'organization') -0287 toPrint=[toPrint model.annotation.organization '\t']; -0288 else -0289 toPrint=[toPrint '\t']; -0290 end -0291 if isfield(model.annotation,'taxonomy') -0292 toPrint=[toPrint model.annotation.taxonomy '\t']; -0293 else -0294 toPrint=[toPrint '\t']; -0295 end -0296 if isfield(model.annotation,'note') -0297 toPrint=[toPrint model.annotation.note '\t']; -0298 else -0299 toPrint=[toPrint '\t']; -0300 end -0301 else -0302 toPrint=[toPrint num2str(min(model.lb)) '\t' num2str(max(model.ub)) '\t\t\t\t\t\t\n']; -0303 end -0304 fprintf(modelFile,toPrint); -0305 fclose(modelFile); -0306 end -0307 -0308 if isfield(model,'comps') -0309 %Open for printing the model sheet -0310 compsFile=fopen(fullfile(path,'excelComps.txt'),'wt'); -0311 -0312 %Print header -0313 fprintf(compsFile,'#\tABBREVIATION\tNAME\tINSIDE\tMIRIAM\n'); +0257 %Print header +0258 fprintf(geneFile,'#\tID\tNAME\tDEFAULT LOWER\tDEFAULT UPPER\tCONTACT GIVEN NAME\tCONTACT FAMILY NAME\tCONTACT EMAIL\tORGANIZATION\tTAXONOMY\tNOTES\n'); +0259 +0260 %Print model ID and name. It is assumed that the default lower/upper +0261 %bound correspond to min/max of the bounds +0262 toPrint=['\t' model.id '\t' model.name '\t']; +0263 if isfield(model,'annotation') +0264 if isfield(model.annotation,'defaultLB') +0265 toPrint=[toPrint num2str(model.annotation.defaultLB) '\t']; +0266 else +0267 toPrint=[toPrint num2str(min(model.lb)) '\t']; +0268 end +0269 if isfield(model.annotation,'defaultUB') +0270 toPrint=[toPrint num2str(model.annotation.defaultUB) '\t']; +0271 else +0272 toPrint=[toPrint num2str(max(model.ub)) '\t']; +0273 end +0274 if isfield(model.annotation,'givenName') +0275 toPrint=[toPrint model.annotation.givenName '\t']; +0276 else +0277 toPrint=[toPrint '\t']; +0278 end +0279 if isfield(model.annotation,'familyName') +0280 toPrint=[toPrint model.annotation.familyName '\t']; +0281 else +0282 toPrint=[toPrint '\t']; +0283 end +0284 if isfield(model.annotation,'email') +0285 toPrint=[toPrint model.annotation.email '\t']; +0286 else +0287 toPrint=[toPrint '\t']; +0288 end +0289 if isfield(model.annotation,'organization') +0290 toPrint=[toPrint model.annotation.organization '\t']; +0291 else +0292 toPrint=[toPrint '\t']; +0293 end +0294 if isfield(model.annotation,'taxonomy') +0295 toPrint=[toPrint model.annotation.taxonomy '\t']; +0296 else +0297 toPrint=[toPrint '\t']; +0298 end +0299 if isfield(model.annotation,'note') +0300 toPrint=[toPrint model.annotation.note '\t']; +0301 else +0302 toPrint=[toPrint '\t']; +0303 end +0304 else +0305 toPrint=[toPrint num2str(min(model.lb)) '\t' num2str(max(model.ub)) '\t\t\t\t\t\t\n']; +0306 end +0307 fprintf(modelFile,toPrint); +0308 fclose(modelFile); +0309 end +0310 +0311 if isfield(model,'comps') +0312 %Open for printing the model sheet +0313 compsFile=fopen(fullfile(path,'excelComps.txt'),'wt'); 0314 -0315 for i=1:numel(model.comps) -0316 toPrint=['\t' model.comps{i} '\t' model.compNames{i} '\t']; -0317 if isfield(model,'compOutside') -0318 toPrint=[toPrint model.compOutside{i} '\t']; -0319 else -0320 toPrint=[toPrint '\t']; -0321 end -0322 if isfield(model,'compMiriams') -0323 if ~isempty(model.compMiriams{i}) -0324 for j=1:numel(model.compMiriams{i}.name) -0325 toPrint=[toPrint strtrim(model.compMiriams{i}.name{j}) '/' strtrim(model.compMiriams{i}.value{j}) ';']; -0326 end -0327 toPrint(end)=[]; -0328 toPrint=[toPrint '\t']; -0329 else -0330 toPrint=[toPrint '\t']; -0331 end -0332 else -0333 toPrint=[toPrint '\t']; -0334 end -0335 toPrint=[toPrint '\n']; -0336 fprintf(compsFile,toPrint); -0337 end -0338 fclose(compsFile); -0339 end -0340 end +0315 %Print header +0316 fprintf(compsFile,'#\tABBREVIATION\tNAME\tINSIDE\tMIRIAM\n'); +0317 +0318 for i=1:numel(model.comps) +0319 toPrint=['\t' model.comps{i} '\t' model.compNames{i} '\t']; +0320 if isfield(model,'compOutside') +0321 toPrint=[toPrint model.compOutside{i} '\t']; +0322 else +0323 toPrint=[toPrint '\t']; +0324 end +0325 if isfield(model,'compMiriams') +0326 if ~isempty(model.compMiriams{i}) +0327 for j=1:numel(model.compMiriams{i}.name) +0328 toPrint=[toPrint strtrim(model.compMiriams{i}.name{j}) '/' strtrim(model.compMiriams{i}.value{j}) ';']; +0329 end +0330 toPrint(end)=[]; +0331 toPrint=[toPrint '\t']; +0332 else +0333 toPrint=[toPrint '\t']; +0334 end +0335 else +0336 toPrint=[toPrint '\t']; +0337 end +0338 toPrint=[toPrint '\n']; +0339 fprintf(compsFile,toPrint); +0340 end +0341 fclose(compsFile); +0342 end +0343 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/importModel.html b/doc/io/importModel.html index 95ea0716..dff37de8 100644 --- a/doc/io/importModel.html +++ b/doc/io/importModel.html @@ -1102,158 +1102,162 @@

    SOURCE CODE ^'subSystems'); 0993 else 0994 model.subSystems(cellfun(@isempty,subsystems))={{''}}; -0995 end -0996 if isempty(model.eccodes) -0997 model=rmfield(model,'eccodes'); -0998 end -0999 if isempty(model.rxnMiriams) -1000 model=rmfield(model,'rxnMiriams'); -1001 end -1002 if cellfun(@isempty,model.rxnNotes) -1003 model=rmfield(model,'rxnNotes'); -1004 end -1005 if cellfun(@isempty,model.rxnReferences) -1006 model=rmfield(model,'rxnReferences'); -1007 end -1008 if isempty(model.rxnConfidenceScores) || all(isnan(model.rxnConfidenceScores)) -1009 model=rmfield(model,'rxnConfidenceScores'); -1010 end -1011 if isempty(model.genes) -1012 model=rmfield(model,'genes'); -1013 elseif isrow(model.genes) -1014 model.genes=transpose(model.genes); -1015 end -1016 if isempty(model.geneComps) -1017 model=rmfield(model,'geneComps'); -1018 end -1019 if isempty(model.geneMiriams) -1020 model=rmfield(model,'geneMiriams'); -1021 end -1022 if isempty(model.geneShortNames) -1023 model=rmfield(model,'geneShortNames'); -1024 end -1025 if isempty(model.proteins) -1026 model=rmfield(model,'proteins'); -1027 end -1028 if isempty(model.inchis) -1029 model=rmfield(model,'inchis'); -1030 end -1031 if isempty(model.metFormulas) -1032 model=rmfield(model,'metFormulas'); -1033 end -1034 if isempty(model.metMiriams) -1035 model=rmfield(model,'metMiriams'); -1036 end -1037 if ~any(model.metCharges) -1038 model=rmfield(model,'metCharges'); -1039 end -1040 -1041 %This just removes the grRules if no genes have been loaded -1042 if ~isfield(model,'genes') && isfield(model,'grRules') -1043 model=rmfield(model,'grRules'); -1044 end -1045 -1046 %Print warnings about bad structure -1047 if supressWarnings==false -1048 checkModelStruct(model,false); -1049 end -1050 -1051 if removeExcMets==true -1052 model=simplifyModel(model); +0995 % If all subSystems have single entries, then unnest them +0996 if all(cellfun(@(x) iscell(x) && isscalar(x), model.subSystems)) +0997 model.subSystems = transpose([model.subSystems{:}]); +0998 end +0999 end +1000 if isempty(model.eccodes) +1001 model=rmfield(model,'eccodes'); +1002 end +1003 if isempty(model.rxnMiriams) +1004 model=rmfield(model,'rxnMiriams'); +1005 end +1006 if cellfun(@isempty,model.rxnNotes) +1007 model=rmfield(model,'rxnNotes'); +1008 end +1009 if cellfun(@isempty,model.rxnReferences) +1010 model=rmfield(model,'rxnReferences'); +1011 end +1012 if isempty(model.rxnConfidenceScores) || all(isnan(model.rxnConfidenceScores)) +1013 model=rmfield(model,'rxnConfidenceScores'); +1014 end +1015 if isempty(model.genes) +1016 model=rmfield(model,'genes'); +1017 elseif isrow(model.genes) +1018 model.genes=transpose(model.genes); +1019 end +1020 if isempty(model.geneComps) +1021 model=rmfield(model,'geneComps'); +1022 end +1023 if isempty(model.geneMiriams) +1024 model=rmfield(model,'geneMiriams'); +1025 end +1026 if isempty(model.geneShortNames) +1027 model=rmfield(model,'geneShortNames'); +1028 end +1029 if isempty(model.proteins) +1030 model=rmfield(model,'proteins'); +1031 end +1032 if isempty(model.inchis) +1033 model=rmfield(model,'inchis'); +1034 end +1035 if isempty(model.metFormulas) +1036 model=rmfield(model,'metFormulas'); +1037 end +1038 if isempty(model.metMiriams) +1039 model=rmfield(model,'metMiriams'); +1040 end +1041 if ~any(model.metCharges) +1042 model=rmfield(model,'metCharges'); +1043 end +1044 +1045 %This just removes the grRules if no genes have been loaded +1046 if ~isfield(model,'genes') && isfield(model,'grRules') +1047 model=rmfield(model,'grRules'); +1048 end +1049 +1050 %Print warnings about bad structure +1051 if supressWarnings==false +1052 checkModelStruct(model,false); 1053 end -1054 end -1055 -1056 function fieldContent=parseNote(searchString,fieldName) -1057 %The function obtains the particular information from 'notes' field, using -1058 %fieldName as the dummy string +1054 +1055 if removeExcMets==true +1056 model=simplifyModel(model); +1057 end +1058 end 1059 -1060 fieldContent=''; -1061 -1062 if strfind(searchString,fieldName) -1063 [~,targetString] = regexp(searchString,['<p>' fieldName '.*?</p>'],'tokens','match'); -1064 targetString=regexprep(targetString,'<p>|</p>',''); -1065 targetString=regexprep(targetString,[fieldName, ':'],''); -1066 for i=1:numel(targetString) -1067 fieldContent=[fieldContent ';' strtrim(targetString{1,i})]; -1068 end -1069 fieldContent=regexprep(fieldContent,'^;|;$',''); -1070 else -1071 fieldContent=''; -1072 end -1073 end -1074 -1075 function fieldContent=parseAnnotation(searchString,startString,midString,fieldName) -1076 -1077 fieldContent=''; +1060 function fieldContent=parseNote(searchString,fieldName) +1061 %The function obtains the particular information from 'notes' field, using +1062 %fieldName as the dummy string +1063 +1064 fieldContent=''; +1065 +1066 if strfind(searchString,fieldName) +1067 [~,targetString] = regexp(searchString,['<p>' fieldName '.*?</p>'],'tokens','match'); +1068 targetString=regexprep(targetString,'<p>|</p>',''); +1069 targetString=regexprep(targetString,[fieldName, ':'],''); +1070 for i=1:numel(targetString) +1071 fieldContent=[fieldContent ';' strtrim(targetString{1,i})]; +1072 end +1073 fieldContent=regexprep(fieldContent,'^;|;$',''); +1074 else +1075 fieldContent=''; +1076 end +1077 end 1078 -1079 %Removing whitespace characters from the ending strings, which may occur in -1080 %several cases -1081 searchString=regexprep(searchString,'" />','"/>'); -1082 [~,targetString] = regexp(searchString,['<rdf:li rdf:resource="' startString fieldName midString '.*?"/>'],'tokens','match'); -1083 targetString=regexprep(targetString,'<rdf:li rdf:resource="|"/>',''); -1084 targetString=regexprep(targetString,startString,''); -1085 targetString=regexprep(targetString,[fieldName midString],''); -1086 -1087 for i=1:numel(targetString) -1088 fieldContent=[fieldContent ';' strtrim(targetString{1,i})]; -1089 end +1079 function fieldContent=parseAnnotation(searchString,startString,midString,fieldName) +1080 +1081 fieldContent=''; +1082 +1083 %Removing whitespace characters from the ending strings, which may occur in +1084 %several cases +1085 searchString=regexprep(searchString,'" />','"/>'); +1086 [~,targetString] = regexp(searchString,['<rdf:li rdf:resource="' startString fieldName midString '.*?"/>'],'tokens','match'); +1087 targetString=regexprep(targetString,'<rdf:li rdf:resource="|"/>',''); +1088 targetString=regexprep(targetString,startString,''); +1089 targetString=regexprep(targetString,[fieldName midString],''); 1090 -1091 fieldContent=regexprep(fieldContent,'^;|;$',''); -1092 end -1093 -1094 function miriamStruct=parseMiriam(searchString) -1095 %Generates miriam structure from annotation field -1096 -1097 %Finding whether miriams are written in the old or the new way -1098 if strfind(searchString,'urn:miriam:') -1099 startString='urn:miriam:'; -1100 elseif strfind(searchString,'http://identifiers.org/') -1101 startString='http://identifiers.org/'; -1102 elseif strfind(searchString,'https://identifiers.org/') -1103 startString='https://identifiers.org/'; -1104 else -1105 miriamStruct=[]; -1106 return; -1107 end -1108 -1109 miriamStruct=[]; -1110 -1111 searchString=regexprep(searchString,'" />','"/>'); -1112 [~,targetString] = regexp(searchString,'<rdf:li rdf:resource=".*?"/>','tokens','match'); -1113 targetString=regexprep(targetString,'<rdf:li rdf:resource="|"/>',''); -1114 targetString=regexprep(targetString,startString,''); -1115 -1116 fwdslash = contains(targetString,'/'); -1117 midString = cell(numel(targetString),1); -1118 midString(fwdslash) = {'/'}; -1119 midString(~fwdslash) = {':'}; -1120 -1121 counter=0; -1122 for i=1:numel(targetString) -1123 if isempty(regexp(targetString{1,i},'inchi|ec-code', 'once')) -1124 counter=counter+1; -1125 miriamStruct.name{counter,1} = regexprep(targetString{1,i},[midString{i} '.+'],'','once'); -1126 miriamStruct.value{counter,1} = regexprep(targetString{1,i},[miriamStruct.name{counter,1} midString{i}],'','once'); -1127 miriamStruct.name{counter,1} = regexprep(miriamStruct.name{counter,1},'^obo\.',''); -1128 end -1129 end -1130 end -1131 -1132 function miriam = addSBOtoMiriam(miriam,sboTerm) -1133 %Appends SBO term to miriam structure -1134 -1135 sboTerm = {['SBO:' sprintf('%07u',sboTerm)]}; % convert to proper format -1136 if isempty(miriam) -1137 miriam.name = {'sbo'}; -1138 miriam.value = sboTerm; -1139 elseif any(strcmp('sbo',miriam.name)) -1140 currSbo = strcmp('sbo',miriam.name); -1141 miriam.value(currSbo) = sboTerm; -1142 else -1143 miriam.name(end+1) = {'sbo'}; -1144 miriam.value(end+1) = sboTerm; -1145 end -1146 end +1091 for i=1:numel(targetString) +1092 fieldContent=[fieldContent ';' strtrim(targetString{1,i})]; +1093 end +1094 +1095 fieldContent=regexprep(fieldContent,'^;|;$',''); +1096 end +1097 +1098 function miriamStruct=parseMiriam(searchString) +1099 %Generates miriam structure from annotation field +1100 +1101 %Finding whether miriams are written in the old or the new way +1102 if strfind(searchString,'urn:miriam:') +1103 startString='urn:miriam:'; +1104 elseif strfind(searchString,'http://identifiers.org/') +1105 startString='http://identifiers.org/'; +1106 elseif strfind(searchString,'https://identifiers.org/') +1107 startString='https://identifiers.org/'; +1108 else +1109 miriamStruct=[]; +1110 return; +1111 end +1112 +1113 miriamStruct=[]; +1114 +1115 searchString=regexprep(searchString,'" />','"/>'); +1116 [~,targetString] = regexp(searchString,'<rdf:li rdf:resource=".*?"/>','tokens','match'); +1117 targetString=regexprep(targetString,'<rdf:li rdf:resource="|"/>',''); +1118 targetString=regexprep(targetString,startString,''); +1119 +1120 fwdslash = contains(targetString,'/'); +1121 midString = cell(numel(targetString),1); +1122 midString(fwdslash) = {'/'}; +1123 midString(~fwdslash) = {':'}; +1124 +1125 counter=0; +1126 for i=1:numel(targetString) +1127 if isempty(regexp(targetString{1,i},'inchi|ec-code', 'once')) +1128 counter=counter+1; +1129 miriamStruct.name{counter,1} = regexprep(targetString{1,i},[midString{i} '.+'],'','once'); +1130 miriamStruct.value{counter,1} = regexprep(targetString{1,i},[miriamStruct.name{counter,1} midString{i}],'','once'); +1131 miriamStruct.name{counter,1} = regexprep(miriamStruct.name{counter,1},'^obo\.',''); +1132 end +1133 end +1134 end +1135 +1136 function miriam = addSBOtoMiriam(miriam,sboTerm) +1137 %Appends SBO term to miriam structure +1138 +1139 sboTerm = {['SBO:' sprintf('%07u',sboTerm)]}; % convert to proper format +1140 if isempty(miriam) +1141 miriam.name = {'sbo'}; +1142 miriam.value = sboTerm; +1143 elseif any(strcmp('sbo',miriam.name)) +1144 currSbo = strcmp('sbo',miriam.name); +1145 miriam.value(currSbo) = sboTerm; +1146 else +1147 miriam.name(end+1) = {'sbo'}; +1148 miriam.value(end+1) = sboTerm; +1149 end +1150 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/readYAMLmodel.html b/doc/io/readYAMLmodel.html index e8c684be..d1e03747 100644 --- a/doc/io/readYAMLmodel.html +++ b/doc/io/readYAMLmodel.html @@ -649,93 +649,102 @@

    SOURCE CODE ^% end 0593 % end 0594 -0595 % Make rxnGeneMat fields and map to the existing model.genes field -0596 [genes, rxnGeneMat] = getGenesFromGrRules(model.grRules); -0597 model.rxnGeneMat = sparse(numel(model.rxns),numel(model.genes)); -0598 [~,geneOrder] = ismember(genes,model.genes); -0599 if any(geneOrder == 0) -0600 error(['The grRules includes the following gene(s), that are not in '... -0601 'the list of model genes: ', genes{~geneOrder}]) -0602 end -0603 model.rxnGeneMat(:,geneOrder) = rxnGeneMat; -0604 -0605 % Finalize GECKO model -0606 if isGECKO -0607 % Fill in empty fields and empty entries -0608 for i={'kcat','source','notes','eccodes'} % Even keep empty -0609 model.ec = emptyOrFill(model.ec,i{1},{''},'rxns',true); +0595 if isfield(model,'subSystems') +0596 % If all entries are 1x1, then flatten +0597 if all(cellfun(@(x) numel(x) <= 1, model.subSystems)) +0598 model.subSystems = transpose([model.subSystems{:}]); +0599 end +0600 end +0601 +0602 % Make rxnGeneMat fields and map to the existing model.genes field +0603 if isfield(model,'grRules') +0604 [genes, rxnGeneMat] = getGenesFromGrRules(model.grRules); +0605 model.rxnGeneMat = sparse(numel(model.rxns),numel(model.genes)); +0606 [~,geneOrder] = ismember(genes,model.genes); +0607 if any(geneOrder == 0) +0608 error(['The grRules includes the following gene(s), that are not in '... +0609 'the list of model genes: ', genes{~geneOrder}]) 0610 end -0611 for i={'enzymes','mw','sequence'} -0612 model.ec = emptyOrFill(model.ec,i{1},{''},'genes',true); -0613 end -0614 model.ec = emptyOrFill(model.ec,'concs',{'NaN'},'genes',true); -0615 model.ec = emptyOrFill(model.ec,'kcat',{'0'},'genes',true); -0616 % Change string to double -0617 for i={'kcat','mw','concs'} -0618 if isfield(model.ec,i{1}) -0619 model.ec.(i{1}) = str2double(model.ec.(i{1})); -0620 end -0621 end -0622 % Fill rxnEnzMat -0623 rxnIdx = cellfun('isempty', enzStoich(:,1)); -0624 enzStoich(rxnIdx,:) = ''; -0625 rxnIdx = cell2mat(enzStoich(:,1)); -0626 [~,enzIdx] = ismember(enzStoich(:,2),model.ec.enzymes); -0627 coeffs = cell2mat(enzStoich(:,3)); -0628 model.ec.rxnEnzMat = zeros(numel(model.ec.rxns), numel(model.ec.genes)); -0629 linearIndices = sub2ind([numel(model.ec.rxns), numel(model.ec.genes)], rxnIdx, enzIdx); -0630 model.ec.rxnEnzMat(linearIndices) = coeffs; -0631 %Parse ec-codes -0632 if ~isempty(ecGecko) -0633 locs = cell2mat(ecGecko(:,1)); -0634 for i=unique(locs)' -0635 ecGeckoCat=strjoin(ecGecko(locs==i,2),';'); -0636 model.ec.eccodes{i,1}=ecGeckoCat; -0637 end -0638 emptyEc=cellfun('isempty',model.ec.eccodes); -0639 model.ec.eccodes(emptyEc)={''}; -0640 end -0641 end -0642 -0643 if verbose -0644 fprintf(' Done!\n'); -0645 end -0646 end -0647 -0648 function model = emptyOrFill(model,field,emptyEntry,type,keepEmpty) -0649 if nargin<5 -0650 keepEmpty=false; -0651 end -0652 if isnumeric(emptyEntry) -0653 emptyCells=isempty(model.(field)); -0654 else -0655 emptyCells=cellfun('isempty',model.(field)); -0656 end -0657 if all(emptyCells) && ~keepEmpty -0658 model = rmfield(model, field); -0659 elseif numel(model.(field))<numel(model.(type)) -0660 model.(field)(end+1:numel(model.(type)),1)=emptyEntry; -0661 end -0662 end -0663 -0664 function model = readFieldValue(model, fieldName, value, pos) -0665 if numel(model.(fieldName))<pos-1 -0666 model.(fieldName)(end+1:pos,1) = {''}; -0667 end -0668 model.(fieldName)(pos,1) = {value}; -0669 end -0670 -0671 function [miriams,miriamKey,entryNumber] = gatherAnnotation(pos,miriams,key,value,miriamKey,entryNumber) -0672 if isempty(key) -0673 key=miriamKey; -0674 else -0675 miriamKey=key; +0611 model.rxnGeneMat(:,geneOrder) = rxnGeneMat; +0612 end +0613 +0614 % Finalize GECKO model +0615 if isGECKO +0616 % Fill in empty fields and empty entries +0617 for i={'kcat','source','notes','eccodes'} % Even keep empty +0618 model.ec = emptyOrFill(model.ec,i{1},{''},'rxns',true); +0619 end +0620 for i={'enzymes','mw','sequence'} +0621 model.ec = emptyOrFill(model.ec,i{1},{''},'genes',true); +0622 end +0623 model.ec = emptyOrFill(model.ec,'concs',{'NaN'},'genes',true); +0624 model.ec = emptyOrFill(model.ec,'kcat',{'0'},'genes',true); +0625 % Change string to double +0626 for i={'kcat','mw','concs'} +0627 if isfield(model.ec,i{1}) +0628 model.ec.(i{1}) = str2double(model.ec.(i{1})); +0629 end +0630 end +0631 % Fill rxnEnzMat +0632 rxnIdx = cellfun('isempty', enzStoich(:,1)); +0633 enzStoich(rxnIdx,:) = ''; +0634 rxnIdx = cell2mat(enzStoich(:,1)); +0635 [~,enzIdx] = ismember(enzStoich(:,2),model.ec.enzymes); +0636 coeffs = cell2mat(enzStoich(:,3)); +0637 model.ec.rxnEnzMat = zeros(numel(model.ec.rxns), numel(model.ec.genes)); +0638 linearIndices = sub2ind([numel(model.ec.rxns), numel(model.ec.genes)], rxnIdx, enzIdx); +0639 model.ec.rxnEnzMat(linearIndices) = coeffs; +0640 %Parse ec-codes +0641 if ~isempty(ecGecko) +0642 locs = cell2mat(ecGecko(:,1)); +0643 for i=unique(locs)' +0644 ecGeckoCat=strjoin(ecGecko(locs==i,2),';'); +0645 model.ec.eccodes{i,1}=ecGeckoCat; +0646 end +0647 emptyEc=cellfun('isempty',model.ec.eccodes); +0648 model.ec.eccodes(emptyEc)={''}; +0649 end +0650 end +0651 +0652 if verbose +0653 fprintf(' Done!\n'); +0654 end +0655 end +0656 +0657 function model = emptyOrFill(model,field,emptyEntry,type,keepEmpty) +0658 if nargin<5 +0659 keepEmpty=false; +0660 end +0661 if isnumeric(emptyEntry) +0662 emptyCells=isempty(model.(field)); +0663 else +0664 emptyCells=cellfun('isempty',model.(field)); +0665 end +0666 if all(emptyCells) && ~keepEmpty +0667 model = rmfield(model, field); +0668 elseif numel(model.(field))<numel(model.(type)) +0669 model.(field)(end+1:numel(model.(type)),1)=emptyEntry; +0670 end +0671 end +0672 +0673 function model = readFieldValue(model, fieldName, value, pos) +0674 if numel(model.(fieldName))<pos-1 +0675 model.(fieldName)(end+1:pos,1) = {''}; 0676 end -0677 if ~isempty(value) -0678 miriams(entryNumber,1:3) = {pos, key, strip(value)}; -0679 entryNumber = entryNumber + 1; -0680 end -0681 end +0677 model.(fieldName)(pos,1) = {value}; +0678 end +0679 +0680 function [miriams,miriamKey,entryNumber] = gatherAnnotation(pos,miriams,key,value,miriamKey,entryNumber) +0681 if isempty(key) +0682 key=miriamKey; +0683 else +0684 miriamKey=key; +0685 end +0686 if ~isempty(value) +0687 miriams(entryNumber,1:3) = {pos, key, strip(value)}; +0688 entryNumber = entryNumber + 1; +0689 end +0690 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/io/writeYAMLmodel.html b/doc/io/writeYAMLmodel.html index 8894eeb0..e4120416 100644 --- a/doc/io/writeYAMLmodel.html +++ b/doc/io/writeYAMLmodel.html @@ -170,277 +170,279 @@

    SOURCE CODE ^end 0112 0113 %Genes: -0114 fprintf(fid,'- genes:\n'); -0115 for i = 1:length(model.genes) -0116 fprintf(fid,' - !!omap\n'); -0117 writeField(model, fid, 'genes', 'txt', i, ' - id', preserveQuotes) -0118 writeField(model, fid, 'geneShortNames', 'txt', i, ' - name', preserveQuotes) -0119 writeField(model, fid, 'proteins', 'txt', i, ' - protein', preserveQuotes) -0120 writeField(model, fid, 'geneMiriams', 'txt', i, ' - annotation', preserveQuotes) -0121 end -0122 -0123 %Compartments: -0124 fprintf(fid,'- compartments: !!omap\n'); -0125 for i = 1:length(model.comps) -0126 writeField(model, fid, 'compNames', 'txt', i, ['- ' model.comps{i}], preserveQuotes) -0127 writeField(model, fid, 'compMiriams', 'txt', i, '- annotation', preserveQuotes) -0128 end -0129 -0130 -0131 %EC-model: -0132 if isfield(model,'ec') -0133 fprintf(fid,'- ec-rxns:\n'); -0134 for i = 1:length(model.ec.rxns) -0135 fprintf(fid,' - !!omap\n'); -0136 writeField(model.ec, fid, 'rxns', 'txt', i, '- id', preserveQuotes) -0137 writeField(model.ec, fid, 'kcat', 'num', i, '- kcat', preserveQuotes) -0138 writeField(model.ec, fid, 'source', 'txt', i, '- source', preserveQuotes) -0139 writeField(model.ec, fid, 'notes', 'txt', i, '- notes', preserveQuotes) -0140 writeField(model.ec, fid, 'eccodes', 'txt', i, '- eccodes', preserveQuotes) -0141 writeField(model.ec, fid, 'rxnEnzMat', 'txt', i, '- enzymes', preserveQuotes) -0142 end -0143 -0144 fprintf(fid,'- ec-enzymes:\n'); -0145 for i = 1:length(model.ec.genes) -0146 fprintf(fid,' - !!omap\n'); -0147 writeField(model.ec, fid, 'genes', 'txt', i, '- genes', preserveQuotes) -0148 writeField(model.ec, fid, 'enzymes', 'txt', i, '- enzymes', preserveQuotes) -0149 writeField(model.ec, fid, 'mw', 'num', i, '- mw', preserveQuotes) -0150 writeField(model.ec, fid, 'sequence', 'txt', i, '- sequence', preserveQuotes) -0151 writeField(model.ec, fid, 'concs', 'num', i, '- concs', preserveQuotes) -0152 end -0153 end -0154 -0155 %Close file: -0156 fclose(fid); -0157 -0158 end +0114 if isfield(model,'genes') +0115 fprintf(fid,'- genes:\n'); +0116 for i = 1:length(model.genes) +0117 fprintf(fid,' - !!omap\n'); +0118 writeField(model, fid, 'genes', 'txt', i, ' - id', preserveQuotes) +0119 writeField(model, fid, 'geneShortNames', 'txt', i, ' - name', preserveQuotes) +0120 writeField(model, fid, 'proteins', 'txt', i, ' - protein', preserveQuotes) +0121 writeField(model, fid, 'geneMiriams', 'txt', i, ' - annotation', preserveQuotes) +0122 end +0123 end +0124 +0125 %Compartments: +0126 fprintf(fid,'- compartments: !!omap\n'); +0127 for i = 1:length(model.comps) +0128 writeField(model, fid, 'compNames', 'txt', i, ['- ' model.comps{i}], preserveQuotes) +0129 writeField(model, fid, 'compMiriams', 'txt', i, '- annotation', preserveQuotes) +0130 end +0131 +0132 +0133 %EC-model: +0134 if isfield(model,'ec') +0135 fprintf(fid,'- ec-rxns:\n'); +0136 for i = 1:length(model.ec.rxns) +0137 fprintf(fid,' - !!omap\n'); +0138 writeField(model.ec, fid, 'rxns', 'txt', i, '- id', preserveQuotes) +0139 writeField(model.ec, fid, 'kcat', 'num', i, '- kcat', preserveQuotes) +0140 writeField(model.ec, fid, 'source', 'txt', i, '- source', preserveQuotes) +0141 writeField(model.ec, fid, 'notes', 'txt', i, '- notes', preserveQuotes) +0142 writeField(model.ec, fid, 'eccodes', 'txt', i, '- eccodes', preserveQuotes) +0143 writeField(model.ec, fid, 'rxnEnzMat', 'txt', i, '- enzymes', preserveQuotes) +0144 end +0145 +0146 fprintf(fid,'- ec-enzymes:\n'); +0147 for i = 1:length(model.ec.genes) +0148 fprintf(fid,' - !!omap\n'); +0149 writeField(model.ec, fid, 'genes', 'txt', i, '- genes', preserveQuotes) +0150 writeField(model.ec, fid, 'enzymes', 'txt', i, '- enzymes', preserveQuotes) +0151 writeField(model.ec, fid, 'mw', 'num', i, '- mw', preserveQuotes) +0152 writeField(model.ec, fid, 'sequence', 'txt', i, '- sequence', preserveQuotes) +0153 writeField(model.ec, fid, 'concs', 'num', i, '- concs', preserveQuotes) +0154 end +0155 end +0156 +0157 %Close file: +0158 fclose(fid); 0159 -0160 function writeField(model,fid,fieldName,type,pos,name,preserveQuotes) -0161 %Writes a new line in the yaml file if the field exists and the field is -0162 %not empty at the correspoinding position. It's recursive for some fields -0163 %(metMiriams, rxnMiriams, and S) -0164 -0165 if isfield(model,fieldName) -0166 if strcmp(fieldName,'metComps') -0167 %metComps: write full name -0168 fieldName = 'comps'; -0169 pos = model.metComps(pos); -0170 end -0171 -0172 field = model.(fieldName); +0160 end +0161 +0162 function writeField(model,fid,fieldName,type,pos,name,preserveQuotes) +0163 %Writes a new line in the yaml file if the field exists and the field is +0164 %not empty at the correspoinding position. It's recursive for some fields +0165 %(metMiriams, rxnMiriams, and S) +0166 +0167 if isfield(model,fieldName) +0168 if strcmp(fieldName,'metComps') +0169 %metComps: write full name +0170 fieldName = 'comps'; +0171 pos = model.metComps(pos); +0172 end 0173 -0174 if strcmp(fieldName,'metMiriams') -0175 if ~isempty(model.metMiriams{pos}) -0176 fprintf(fid,' %s: !!omap\n',name); -0177 for i=1:size(model.newMetMiriams,2) -0178 %'i' represents the different miriam names, e.g. -0179 %kegg.compound or chebi -0180 if ~isempty(model.newMetMiriams{pos,i}) -0181 %As during the following writeField call the value of -0182 %'i' would be lost, it is temporarily concatenated to -0183 %'name' parameter, which will be edited later -0184 writeField(model, fid, 'newMetMiriams', 'txt', pos, [' - ' model.newMetMiriamNames{i} '_' sprintf('%d',i)], preserveQuotes) -0185 end -0186 end -0187 end -0188 -0189 elseif strcmp(fieldName,'rxnMiriams') -0190 if ~isempty(model.rxnMiriams{pos}) -0191 fprintf(fid,' %s: !!omap\n',name); -0192 for i=1:size(model.newRxnMiriams,2) -0193 if ~isempty(model.newRxnMiriams{pos,i}) -0194 writeField(model, fid, 'newRxnMiriams', 'txt', pos, [' - ' model.newRxnMiriamNames{i} '_' sprintf('%d',i)], preserveQuotes) -0195 end -0196 end -0197 end -0198 -0199 elseif strcmp(fieldName,'geneMiriams') -0200 if ~isempty(model.geneMiriams{pos}) -0201 fprintf(fid,' %s: !!omap\n',name); -0202 for i=1:size(model.newGeneMiriams,2) -0203 if ~isempty(model.newGeneMiriams{pos,i}) -0204 writeField(model, fid, 'newGeneMiriams', 'txt', pos, [' - ' model.newGeneMiriamNames{i} '_' sprintf('%d',i)], preserveQuotes) -0205 end -0206 end -0207 end -0208 -0209 elseif strcmp(fieldName,'compMiriams') -0210 if ~isempty(model.compMiriams{pos}) -0211 fprintf(fid,' %s: !!omap\n',name); -0212 for i=1:size(model.newCompMiriams,2) -0213 if ~isempty(model.newCompMiriams{pos,i}) -0214 writeField(model, fid, 'newCompMiriams', 'txt', pos, [' - ' model.newCompMiriamNames{i} '_' sprintf('%d',i)], preserveQuotes) -0215 end -0216 end -0217 end -0218 -0219 elseif strcmp(fieldName,'S') -0220 %S: create header & write each metabolite in a new line -0221 fprintf(fid,' %s: !!omap\n',name); -0222 if sum(field(:,pos) ~= 0) > 0 -0223 model.mets = model.mets(field(:,pos) ~= 0); -0224 model.coeffs = field(field(:,pos) ~= 0,pos); -0225 %Sort metabolites: -0226 [model.mets,order] = sort(model.mets); -0227 model.coeffs = model.coeffs(order); -0228 for i = 1:length(model.mets) -0229 writeField(model, fid, 'coeffs', 'num', i, [' - ' model.mets{i}], preserveQuotes) -0230 end -0231 end -0232 -0233 elseif strcmp(fieldName,'rxnEnzMat') -0234 %S: create header & write each enzyme in a new line -0235 fprintf(fid,' %s: !!omap\n',name); -0236 if sum(field(pos,:) ~= 0) > 0 -0237 model.enzymes = model.enzymes(field(pos,:) ~= 0); -0238 model.coeffs = field(pos,field(pos,:) ~= 0); -0239 %Sort metabolites: -0240 [model.enzymes,order] = sort(model.enzymes); -0241 model.coeffs = model.coeffs(order); -0242 for i = 1:length(model.enzymes) -0243 writeField(model, fid, 'coeffs', 'num', i, [' - ' model.enzymes{i}], preserveQuotes) -0244 end -0245 end -0246 -0247 elseif sum(strcmp({'subSystems','newMetMiriams','newRxnMiriams','newGeneMiriams','newCompMiriams','eccodes'},fieldName)) > 0 -0248 %eccodes/rxnNotes: if 1 write in 1 line, if more create header and list -0249 if strcmp(fieldName,'subSystems') -0250 list = field{pos}; %subSystems already comes in a cell array -0251 if isempty(list) -0252 return -0253 end -0254 elseif strcmp(fieldName,'newMetMiriams') -0255 index = str2double(regexprep(name,'^.+_','')); -0256 name = regexprep(name,'_\d+$',''); -0257 list = strsplit(model.newMetMiriams{pos,index},'; '); -0258 elseif strcmp(fieldName,'newRxnMiriams') -0259 index = str2double(regexprep(name,'^.+_','')); -0260 name = regexprep(name,'_\d+$',''); -0261 list = strsplit(model.newRxnMiriams{pos,index},'; '); -0262 elseif strcmp(fieldName,'newGeneMiriams') -0263 index = str2double(regexprep(name,'^.+_','')); -0264 name = regexprep(name,'_\d+$',''); -0265 list = strsplit(model.newGeneMiriams{pos,index},'; '); -0266 elseif strcmp(fieldName,'newCompMiriams') -0267 index = str2double(regexprep(name,'^.+_','')); -0268 name = regexprep(name,'_\d+$',''); -0269 list = strsplit(model.newCompMiriams{pos,index},'; '); -0270 elseif ~isempty(field{pos}) -0271 list = strrep(field{pos},' ',''); -0272 list = strsplit(list,';'); -0273 else -0274 return % empty, needs no line in file -0275 end -0276 list=strip(list); -0277 -0278 if length(list) == 1 && ~strcmp(list{1},'') && ~strcmp(fieldName,'subSystems') -0279 if preserveQuotes -0280 list = ['"' list{1} '"']; -0281 end -0282 if iscell(list) -0283 list=list{1}; -0284 end -0285 fprintf(fid,' %s: %s\n',name,list); -0286 elseif ischar(list) && strcmp(fieldName,'subSystems') -0287 if preserveQuotes -0288 list = ['"' list '"']; -0289 end -0290 fprintf(fid,' %s: %s\n',name,list); -0291 elseif length(list) > 1 || strcmp(fieldName,'subSystems') -0292 if preserveQuotes -0293 for j=1:numel(list) -0294 list{j} = ['"' list{j} '"']; -0295 end -0296 end -0297 fprintf(fid,' %s:\n',name); -0298 for i = 1:length(list) -0299 fprintf(fid,'%s - %s\n',regexprep(name,'(^\s*).*','$1'),list{i}); -0300 end -0301 end -0302 -0303 elseif sum(pos) > 0 -0304 %All other fields: -0305 if strcmp(type,'txt') -0306 value = field{pos}; -0307 if preserveQuotes && ~isempty(value) -0308 value = ['"',value,'"']; -0309 end -0310 elseif strcmp(type,'num') -0311 if isnan(field(pos)) -0312 value = []; -0313 else -0314 value = sprintf('%.15g',full(field(pos))); -0315 end -0316 end -0317 if ~isempty(value) -0318 fprintf(fid,' %s: %s\n',name,value); -0319 end -0320 end -0321 end -0322 end -0323 -0324 function writeMetadata(model,fid) -0325 % Writes model metadata to the yaml file. This information will eventually -0326 % be extracted entirely from the model, but for now, many of the entries -0327 % are hard-coded defaults for HumanGEM. -0328 -0329 fprintf(fid, '- metaData:\n'); -0330 if isfield(model,'id') -0331 fprintf(fid, ' id: "%s"\n', model.id); -0332 else -0333 fprintf(fid, ' id: "blankID"\n'); -0334 end -0335 if isfield(model,'name') -0336 fprintf(fid, ' name: "%s"\n',model.name); -0337 else -0338 fprintf(fid, ' name: "blankName"\n'); -0339 end -0340 if isfield(model,'version') -0341 fprintf(fid, ' version: "%s"\n',model.version); -0342 end -0343 fprintf(fid, ' date: "%s"\n',datestr(now,29)); % 29=YYYY-MM-DD -0344 if isfield(model,'annotation') -0345 if isfield(model.annotation,'defaultLB') -0346 fprintf(fid, ' defaultLB: "%g"\n', model.annotation.defaultLB); -0347 end -0348 if isfield(model.annotation,'defaultUB') -0349 fprintf(fid, ' defaultUB: "%g"\n', model.annotation.defaultUB); -0350 end -0351 if isfield(model.annotation,'givenName') -0352 fprintf(fid, ' givenName: "%s"\n', model.annotation.givenName); -0353 end -0354 if isfield(model.annotation,'familyName') -0355 fprintf(fid, ' familyName: "%s"\n', model.annotation.familyName); -0356 end -0357 if isfield(model.annotation,'authors') -0358 fprintf(fid, ' authors: "%s"\n', model.annotation.authors); -0359 end -0360 if isfield(model.annotation,'email') -0361 fprintf(fid, ' email: "%s"\n', model.annotation.email); -0362 end -0363 if isfield(model.annotation,'organization') -0364 fprintf(fid, ' organization: "%s"\n',model.annotation.organization); -0365 end -0366 if isfield(model.annotation,'taxonomy') -0367 fprintf(fid, ' taxonomy: "%s"\n', model.annotation.taxonomy); -0368 end -0369 if isfield(model.annotation,'note') -0370 fprintf(fid, ' note: "%s"\n', model.annotation.note); -0371 end -0372 if isfield(model.annotation,'sourceUrl') -0373 fprintf(fid, ' sourceUrl: "%s"\n', model.annotation.sourceUrl); -0374 end -0375 end -0376 if isfield(model,'ec') -0377 if model.ec.geckoLight -0378 geckoLight = 'true'; -0379 else -0380 geckoLight = 'false'; -0381 end -0382 fprintf(fid,' geckoLight: "%s"\n',geckoLight); -0383 end -0384 end +0174 field = model.(fieldName); +0175 +0176 if strcmp(fieldName,'metMiriams') +0177 if ~isempty(model.metMiriams{pos}) +0178 fprintf(fid,' %s: !!omap\n',name); +0179 for i=1:size(model.newMetMiriams,2) +0180 %'i' represents the different miriam names, e.g. +0181 %kegg.compound or chebi +0182 if ~isempty(model.newMetMiriams{pos,i}) +0183 %As during the following writeField call the value of +0184 %'i' would be lost, it is temporarily concatenated to +0185 %'name' parameter, which will be edited later +0186 writeField(model, fid, 'newMetMiriams', 'txt', pos, [' - ' model.newMetMiriamNames{i} '_' sprintf('%d',i)], preserveQuotes) +0187 end +0188 end +0189 end +0190 +0191 elseif strcmp(fieldName,'rxnMiriams') +0192 if ~isempty(model.rxnMiriams{pos}) +0193 fprintf(fid,' %s: !!omap\n',name); +0194 for i=1:size(model.newRxnMiriams,2) +0195 if ~isempty(model.newRxnMiriams{pos,i}) +0196 writeField(model, fid, 'newRxnMiriams', 'txt', pos, [' - ' model.newRxnMiriamNames{i} '_' sprintf('%d',i)], preserveQuotes) +0197 end +0198 end +0199 end +0200 +0201 elseif strcmp(fieldName,'geneMiriams') +0202 if ~isempty(model.geneMiriams{pos}) +0203 fprintf(fid,' %s: !!omap\n',name); +0204 for i=1:size(model.newGeneMiriams,2) +0205 if ~isempty(model.newGeneMiriams{pos,i}) +0206 writeField(model, fid, 'newGeneMiriams', 'txt', pos, [' - ' model.newGeneMiriamNames{i} '_' sprintf('%d',i)], preserveQuotes) +0207 end +0208 end +0209 end +0210 +0211 elseif strcmp(fieldName,'compMiriams') +0212 if ~isempty(model.compMiriams{pos}) +0213 fprintf(fid,' %s: !!omap\n',name); +0214 for i=1:size(model.newCompMiriams,2) +0215 if ~isempty(model.newCompMiriams{pos,i}) +0216 writeField(model, fid, 'newCompMiriams', 'txt', pos, [' - ' model.newCompMiriamNames{i} '_' sprintf('%d',i)], preserveQuotes) +0217 end +0218 end +0219 end +0220 +0221 elseif strcmp(fieldName,'S') +0222 %S: create header & write each metabolite in a new line +0223 fprintf(fid,' %s: !!omap\n',name); +0224 if sum(field(:,pos) ~= 0) > 0 +0225 model.mets = model.mets(field(:,pos) ~= 0); +0226 model.coeffs = field(field(:,pos) ~= 0,pos); +0227 %Sort metabolites: +0228 [model.mets,order] = sort(model.mets); +0229 model.coeffs = model.coeffs(order); +0230 for i = 1:length(model.mets) +0231 writeField(model, fid, 'coeffs', 'num', i, [' - ' model.mets{i}], preserveQuotes) +0232 end +0233 end +0234 +0235 elseif strcmp(fieldName,'rxnEnzMat') +0236 %S: create header & write each enzyme in a new line +0237 fprintf(fid,' %s: !!omap\n',name); +0238 if sum(field(pos,:) ~= 0) > 0 +0239 model.enzymes = model.enzymes(field(pos,:) ~= 0); +0240 model.coeffs = field(pos,field(pos,:) ~= 0); +0241 %Sort metabolites: +0242 [model.enzymes,order] = sort(model.enzymes); +0243 model.coeffs = model.coeffs(order); +0244 for i = 1:length(model.enzymes) +0245 writeField(model, fid, 'coeffs', 'num', i, [' - ' model.enzymes{i}], preserveQuotes) +0246 end +0247 end +0248 +0249 elseif sum(strcmp({'subSystems','newMetMiriams','newRxnMiriams','newGeneMiriams','newCompMiriams','eccodes'},fieldName)) > 0 +0250 %eccodes/rxnNotes: if 1 write in 1 line, if more create header and list +0251 if strcmp(fieldName,'subSystems') +0252 list = field{pos}; %subSystems already comes in a cell array +0253 if isempty(list) +0254 return +0255 end +0256 elseif strcmp(fieldName,'newMetMiriams') +0257 index = str2double(regexprep(name,'^.+_','')); +0258 name = regexprep(name,'_\d+$',''); +0259 list = strsplit(model.newMetMiriams{pos,index},'; '); +0260 elseif strcmp(fieldName,'newRxnMiriams') +0261 index = str2double(regexprep(name,'^.+_','')); +0262 name = regexprep(name,'_\d+$',''); +0263 list = strsplit(model.newRxnMiriams{pos,index},'; '); +0264 elseif strcmp(fieldName,'newGeneMiriams') +0265 index = str2double(regexprep(name,'^.+_','')); +0266 name = regexprep(name,'_\d+$',''); +0267 list = strsplit(model.newGeneMiriams{pos,index},'; '); +0268 elseif strcmp(fieldName,'newCompMiriams') +0269 index = str2double(regexprep(name,'^.+_','')); +0270 name = regexprep(name,'_\d+$',''); +0271 list = strsplit(model.newCompMiriams{pos,index},'; '); +0272 elseif ~isempty(field{pos}) +0273 list = strrep(field{pos},' ',''); +0274 list = strsplit(list,';'); +0275 else +0276 return % empty, needs no line in file +0277 end +0278 list=strip(list); +0279 +0280 if length(list) == 1 && ~strcmp(list{1},'') && ~strcmp(fieldName,'subSystems') +0281 if preserveQuotes +0282 list = ['"' list{1} '"']; +0283 end +0284 if iscell(list) +0285 list=list{1}; +0286 end +0287 fprintf(fid,' %s: %s\n',name,list); +0288 elseif ischar(list) && strcmp(fieldName,'subSystems') +0289 if preserveQuotes +0290 list = ['"' list '"']; +0291 end +0292 fprintf(fid,' %s: %s\n',name,list); +0293 elseif length(list) > 1 || strcmp(fieldName,'subSystems') +0294 if preserveQuotes +0295 for j=1:numel(list) +0296 list{j} = ['"' list{j} '"']; +0297 end +0298 end +0299 fprintf(fid,' %s:\n',name); +0300 for i = 1:length(list) +0301 fprintf(fid,'%s - %s\n',regexprep(name,'(^\s*).*','$1'),list{i}); +0302 end +0303 end +0304 +0305 elseif sum(pos) > 0 +0306 %All other fields: +0307 if strcmp(type,'txt') +0308 value = field{pos}; +0309 if preserveQuotes && ~isempty(value) +0310 value = ['"',value,'"']; +0311 end +0312 elseif strcmp(type,'num') +0313 if isnan(field(pos)) +0314 value = []; +0315 else +0316 value = sprintf('%.15g',full(field(pos))); +0317 end +0318 end +0319 if ~isempty(value) +0320 fprintf(fid,' %s: %s\n',name,value); +0321 end +0322 end +0323 end +0324 end +0325 +0326 function writeMetadata(model,fid) +0327 % Writes model metadata to the yaml file. This information will eventually +0328 % be extracted entirely from the model, but for now, many of the entries +0329 % are hard-coded defaults for HumanGEM. +0330 +0331 fprintf(fid, '- metaData:\n'); +0332 if isfield(model,'id') +0333 fprintf(fid, ' id: "%s"\n', model.id); +0334 else +0335 fprintf(fid, ' id: "blankID"\n'); +0336 end +0337 if isfield(model,'name') +0338 fprintf(fid, ' name: "%s"\n',model.name); +0339 else +0340 fprintf(fid, ' name: "blankName"\n'); +0341 end +0342 if isfield(model,'version') +0343 fprintf(fid, ' version: "%s"\n',model.version); +0344 end +0345 fprintf(fid, ' date: "%s"\n',datestr(now,29)); % 29=YYYY-MM-DD +0346 if isfield(model,'annotation') +0347 if isfield(model.annotation,'defaultLB') +0348 fprintf(fid, ' defaultLB: "%g"\n', model.annotation.defaultLB); +0349 end +0350 if isfield(model.annotation,'defaultUB') +0351 fprintf(fid, ' defaultUB: "%g"\n', model.annotation.defaultUB); +0352 end +0353 if isfield(model.annotation,'givenName') +0354 fprintf(fid, ' givenName: "%s"\n', model.annotation.givenName); +0355 end +0356 if isfield(model.annotation,'familyName') +0357 fprintf(fid, ' familyName: "%s"\n', model.annotation.familyName); +0358 end +0359 if isfield(model.annotation,'authors') +0360 fprintf(fid, ' authors: "%s"\n', model.annotation.authors); +0361 end +0362 if isfield(model.annotation,'email') +0363 fprintf(fid, ' email: "%s"\n', model.annotation.email); +0364 end +0365 if isfield(model.annotation,'organization') +0366 fprintf(fid, ' organization: "%s"\n',model.annotation.organization); +0367 end +0368 if isfield(model.annotation,'taxonomy') +0369 fprintf(fid, ' taxonomy: "%s"\n', model.annotation.taxonomy); +0370 end +0371 if isfield(model.annotation,'note') +0372 fprintf(fid, ' note: "%s"\n', model.annotation.note); +0373 end +0374 if isfield(model.annotation,'sourceUrl') +0375 fprintf(fid, ' sourceUrl: "%s"\n', model.annotation.sourceUrl); +0376 end +0377 end +0378 if isfield(model,'ec') +0379 if model.ec.geckoLight +0380 geckoLight = 'true'; +0381 else +0382 geckoLight = 'false'; +0383 end +0384 fprintf(fid,' geckoLight: "%s"\n',geckoLight); +0385 end +0386 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/solver/optimizeProb.html b/doc/solver/optimizeProb.html index 6a0138bd..5fd16c55 100644 --- a/doc/solver/optimizeProb.html +++ b/doc/solver/optimizeProb.html @@ -296,7 +296,7 @@

    SOURCE CODE ^switch exitflag 0243 case 11 0244 res.stat = 1; -0245 case [5, 6, 7, 8, 9, 10, 13] +0245 case {1, 5, 6, 7, 8, 9, 10, 13} % If user-interrupted, not sure if optimal 0246 res.stat = 2; 0247 otherwise 0248 res.stat = 0; diff --git a/doc/struct_conversion/ravenCobraWrapper.html b/doc/struct_conversion/ravenCobraWrapper.html index 6bb7c386..fdbcf58d 100644 --- a/doc/struct_conversion/ravenCobraWrapper.html +++ b/doc/struct_conversion/ravenCobraWrapper.html @@ -260,7 +260,7 @@

    SOURCE CODE ^'E',size(model.mets)); 0188 if isfield(model,'geneMiriams') -0189 [miriams,extractedMiriamNames]=extractMiriam(model.geneMiriams); +0189 [~,extractedMiriamNames]=extractMiriam(model.geneMiriams); 0190 for i = 1:length(geneCOBRAfields) 0191 j=ismember(extractedMiriamNames,geneNamespaces{i}); 0192 if any(j) @@ -276,242 +276,253 @@

    SOURCE CODE ^else 0203 fprintf('WARNING: no genes detected. The model therefore may not be exportable to SBML file with writeCbModel\n'); 0204 end -0205 newModel.osenseStr='max'; -0206 else -0207 fprintf('Converting COBRA structure to RAVEN..\n'); -0208 %Convert from COBRA to RAVEN structure -0209 -0210 %Mandatory RAVEN fields -0211 newModel.mets=model.mets; -0212 if ~isfield(model,'comps') -0213 %Since 'comps' field is not mandatory in COBRA, it may be required -0214 %to obtain the non-redundant list of comps from metabolite ids, if -0215 %'comps' field is not available -0216 newModel.comps = unique(regexprep(model.mets,'.*\[([^\]]+)\]$','$1')); -0217 newModel.compNames = newModel.comps; -0218 end -0219 for i=1:numel(newModel.comps) -0220 newModel.mets=regexprep(newModel.mets,['\[', newModel.comps{i}, '\]$'],''); -0221 newModel.mets=regexprep(newModel.mets,['\[', newModel.compNames{i}, '\]$'],''); -0222 end -0223 -0224 %In some cases (e.g. any model that uses BiGG ids as main ids), there -0225 %may be overlapping mets due to removal of compartment info. To avoid -0226 %this, we change compartments from e.g. [c] into _c -0227 if numel(unique(newModel.mets))~=numel(model.mets) -0228 newModel.mets=model.mets; -0229 for i=1:numel(newModel.comps) -0230 newModel.mets=regexprep(newModel.mets,['\[' newModel.comps{i} '\]$'],['_' newModel.comps{i}]); -0231 end -0232 end -0233 %Since COBRA no longer contains rev field it is assumed that rxn is -0234 %reversible if its lower bound is set below zero -0235 if ~isfield(model,'rev') -0236 for i=1:numel(model.rxns) -0237 if model.lb(i)<0 -0238 newModel.rev(i,1)=1; -0239 else -0240 newModel.rev(i,1)=0; -0241 end -0242 end -0243 end -0244 newModel.b=zeros(numel(model.mets),1); -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') && ~isfield(model,'grRules') -0261 model.grRules = rulesTogrrules(model); -0262 end -0263 if isfield(model,'grRules') -0264 [grRules,rxnGeneMat] = standardizeGrRules(model,true); -0265 newModel.grRules = grRules; -0266 newModel.rxnGeneMat = rxnGeneMat; +0205 % If needed, normalise subSystems to cell-of-cells format +0206 if isfield(newModel,'subSystems') && ~isempty(newModel.subSystems) +0207 if ~iscell(newModel.subSystems{1}) +0208 newModel.subSystems = cellfun(@(x) {x}, newModel.subSystems, 'UniformOutput', false); +0209 end +0210 end +0211 else +0212 fprintf('Converting COBRA structure to RAVEN..\n'); +0213 %Convert from COBRA to RAVEN structure +0214 +0215 %Mandatory RAVEN fields +0216 newModel.mets=model.mets; +0217 if ~isfield(model,'comps') +0218 %Since 'comps' field is not mandatory in COBRA, it may be required +0219 %to obtain the non-redundant list of comps from metabolite ids, if +0220 %'comps' field is not available +0221 newModel.comps = unique(regexprep(model.mets,'.*\[([^\]]+)\]$','$1')); +0222 newModel.compNames = newModel.comps; +0223 end +0224 for i=1:numel(newModel.comps) +0225 newModel.mets=regexprep(newModel.mets,['\[', newModel.comps{i}, '\]$'],''); +0226 newModel.mets=regexprep(newModel.mets,['\[', newModel.compNames{i}, '\]$'],''); +0227 end +0228 +0229 %In some cases (e.g. any model that uses BiGG ids as main ids), there +0230 %may be overlapping mets due to removal of compartment info. To avoid +0231 %this, we change compartments from e.g. [c] into _c +0232 if numel(unique(newModel.mets))~=numel(model.mets) +0233 newModel.mets=model.mets; +0234 for i=1:numel(newModel.comps) +0235 newModel.mets=regexprep(newModel.mets,['\[' newModel.comps{i} '\]$'],['_' newModel.comps{i}]); +0236 end +0237 end +0238 %Since COBRA no longer contains rev field it is assumed that rxn is +0239 %reversible if its lower bound is set below zero +0240 if ~isfield(model,'rev') +0241 for i=1:numel(model.rxns) +0242 if model.lb(i)<0 +0243 newModel.rev(i,1)=1; +0244 else +0245 newModel.rev(i,1)=0; +0246 end +0247 end +0248 end +0249 newModel.b=zeros(numel(model.mets),1); +0250 +0251 %metComps is also mandatory, but defined later to match the order of +0252 %fields +0253 +0254 %Fields 'name' and 'id' are also considered as mandatory, but +0255 %these are added to the model during exportModel/exportToExcelFormat +0256 %anyway, so there is no point to add this information here +0257 +0258 %Optional RAVEN fields +0259 if isfield(model,'modelID') +0260 newModel.id=model.modelID; +0261 end +0262 if isfield(model,'modelName') +0263 newModel.name=model.modelName; +0264 end +0265 if isfield(model,'rules') && ~isfield(model,'grRules') +0266 model.grRules = rulesTogrrules(model); 0267 end -0268 if isfield(model,'rxnECNumbers') -0269 newModel.eccodes=regexprep(model.rxnECNumbers,'EC|EC:',''); -0270 end -0271 if any(isfield(model,rxnCOBRAfields)) -0272 for i=1:numel(model.rxns) -0273 counter=1; -0274 newModel.rxnMiriams{i,1}=[]; -0275 if isfield(model,'rxnReferences') -0276 if ~isempty(model.rxnReferences{i}) -0277 pmids = model.rxnReferences{i}; -0278 pmids = strsplit(pmids,'; '); -0279 nonPmids = cellfun(@isempty,regexp(pmids,'^\d+$','match','once')); -0280 if any(nonPmids) %Not a pubmed id, keep in rxnReferences instead -0281 newModel.rxnReferences{i,1} = strjoin(pmids(nonPmids),', '); -0282 pmids(nonPmids)=[]; -0283 end -0284 for j = 1:length(pmids) -0285 newModel.rxnMiriams{i,1}.name{counter,1} = 'pubmed'; -0286 newModel.rxnMiriams{i,1}.value{counter,1} = pmids{j}; -0287 counter=counter+1; +0268 if isfield(model,'grRules') +0269 [grRules,rxnGeneMat] = standardizeGrRules(model,true); +0270 newModel.grRules = grRules; +0271 newModel.rxnGeneMat = rxnGeneMat; +0272 end +0273 if isfield(model,'rxnECNumbers') +0274 newModel.eccodes=regexprep(model.rxnECNumbers,'EC|EC:',''); +0275 end +0276 if any(isfield(model,rxnCOBRAfields)) +0277 for i=1:numel(model.rxns) +0278 counter=1; +0279 newModel.rxnMiriams{i,1}=[]; +0280 if isfield(model,'rxnReferences') +0281 if ~isempty(model.rxnReferences{i}) +0282 pmids = model.rxnReferences{i}; +0283 pmids = strsplit(pmids,'; '); +0284 nonPmids = cellfun(@isempty,regexp(pmids,'^\d+$','match','once')); +0285 if any(nonPmids) %Not a pubmed id, keep in rxnReferences instead +0286 newModel.rxnReferences{i,1} = strjoin(pmids(nonPmids),', '); +0287 pmids(nonPmids)=[]; 0288 end -0289 end -0290 end -0291 for j = 2:length(rxnCOBRAfields) %Start from 2, as 1 is rxnReferences -0292 if isfield(model,rxnCOBRAfields{j}) -0293 rxnAnnotation = eval(['model.' rxnCOBRAfields{j} '{i}']); -0294 if ~isempty(rxnAnnotation) -0295 rxnAnnotation = strtrim(strsplit(rxnAnnotation,';')); -0296 for a=1:length(rxnAnnotation) -0297 newModel.rxnMiriams{i,1}.name{counter,1} = rxnNamespaces{j}; -0298 newModel.rxnMiriams{i,1}.value{counter,1} = rxnAnnotation{a}; -0299 counter=counter+1; -0300 end -0301 end -0302 end -0303 end -0304 end -0305 end -0306 if isfield(newModel,'rxnReferences') -0307 emptyEntry = cellfun(@isempty,newModel.rxnReferences); -0308 newModel.rxnReferences(emptyEntry)={''}; -0309 diffNumel = numel(newModel.rxns) - numel(newModel.rxnReferences); -0310 if diffNumel > 0 -0311 newModel.rxnReferences(end+1:end+diffNumel) = {''}; -0312 end -0313 end -0314 if any(isfield(model,geneCOBRAfields)) -0315 for i=1:numel(model.genes) -0316 counter=1; -0317 newModel.geneMiriams{i,1}=[]; -0318 for j = 1:length(geneCOBRAfields) -0319 if isfield(model,geneCOBRAfields{j}) -0320 geneAnnotation = eval(['model.' geneCOBRAfields{j} '{i}']); -0321 if ~isempty(geneAnnotation) -0322 geneAnnotation = strtrim(strsplit(geneAnnotation,';')); -0323 for a=1:length(geneAnnotation) -0324 newModel.geneMiriams{i,1}.name{counter,1} = geneNamespaces{j}; -0325 newModel.geneMiriams{i,1}.value{counter,1} = geneAnnotation{a}; -0326 counter=counter+1; -0327 end -0328 end -0329 end -0330 end -0331 end -0332 end -0333 if isfield(model,'geneNames') -0334 newModel.geneShortNames=model.geneNames; -0335 end -0336 newModel.metNames=model.metNames; -0337 for i=1:numel(newModel.comps) -0338 newModel.metNames=regexprep(newModel.metNames,['\[', newModel.comps{i}, '\]$'],''); -0339 newModel.metNames=regexprep(newModel.metNames,['\[', newModel.compNames{i}, '\]$'],''); +0289 for j = 1:length(pmids) +0290 newModel.rxnMiriams{i,1}.name{counter,1} = 'pubmed'; +0291 newModel.rxnMiriams{i,1}.value{counter,1} = pmids{j}; +0292 counter=counter+1; +0293 end +0294 end +0295 end +0296 for j = 2:length(rxnCOBRAfields) %Start from 2, as 1 is rxnReferences +0297 if isfield(model,rxnCOBRAfields{j}) +0298 rxnAnnotation = eval(['model.' rxnCOBRAfields{j} '{i}']); +0299 if ~isempty(rxnAnnotation) +0300 rxnAnnotation = strtrim(strsplit(rxnAnnotation,';')); +0301 for a=1:length(rxnAnnotation) +0302 newModel.rxnMiriams{i,1}.name{counter,1} = rxnNamespaces{j}; +0303 newModel.rxnMiriams{i,1}.value{counter,1} = rxnAnnotation{a}; +0304 counter=counter+1; +0305 end +0306 end +0307 end +0308 end +0309 end +0310 end +0311 if isfield(newModel,'rxnReferences') +0312 emptyEntry = cellfun(@isempty,newModel.rxnReferences); +0313 newModel.rxnReferences(emptyEntry)={''}; +0314 diffNumel = numel(newModel.rxns) - numel(newModel.rxnReferences); +0315 if diffNumel > 0 +0316 newModel.rxnReferences(end+1:end+diffNumel) = {''}; +0317 end +0318 end +0319 if any(isfield(model,geneCOBRAfields)) +0320 for i=1:numel(model.genes) +0321 counter=1; +0322 newModel.geneMiriams{i,1}=[]; +0323 for j = 1:length(geneCOBRAfields) +0324 if isfield(model,geneCOBRAfields{j}) +0325 geneAnnotation = eval(['model.' geneCOBRAfields{j} '{i}']); +0326 if ~isempty(geneAnnotation) +0327 geneAnnotation = strtrim(strsplit(geneAnnotation,';')); +0328 for a=1:length(geneAnnotation) +0329 newModel.geneMiriams{i,1}.name{counter,1} = geneNamespaces{j}; +0330 newModel.geneMiriams{i,1}.value{counter,1} = geneAnnotation{a}; +0331 counter=counter+1; +0332 end +0333 end +0334 end +0335 end +0336 end +0337 end +0338 if isfield(model,'geneNames') +0339 newModel.geneShortNames=model.geneNames; 0340 end -0341 newModel.metNames=deblank(newModel.metNames); -0342 newModel.metComps=regexprep(model.mets,'^.+\[',''); -0343 newModel.metComps=regexprep(newModel.metComps,'\]$',''); -0344 [~, newModel.metComps]=ismember(newModel.metComps,newModel.comps); -0345 if isfield(model,'metInChIString') -0346 newModel.inchis=regexprep(model.metInChIString,'^InChI=',''); -0347 end -0348 printWarning=false; -0349 if any(isfield(model,[metCOBRAfields;'metKEGGID';'metPubChemID'])) -0350 for i=1:numel(model.mets) -0351 counter=1; -0352 newModel.metMiriams{i,1}=[]; -0353 if isfield(model,'metKEGGID') -0354 if ~isempty(model.metKEGGID{i}) -0355 if strcmp(model.metKEGGID{i}(1),'C') -0356 newModel.metMiriams{i,1}.name{counter,1} = 'kegg.compound'; -0357 newModel.metMiriams{i,1}.value{counter,1} = model.metKEGGID{i}; -0358 counter=counter+1; -0359 elseif strcmp(model.metKEGGID{i}(1),'G') -0360 newModel.metMiriams{i,1}.name{counter,1} = 'kegg.glycan'; -0361 newModel.metMiriams{i,1}.value{counter,1} = model.metKEGGID{i}; -0362 counter=counter+1; -0363 end -0364 end -0365 end -0366 if isfield(model,'metPubChemID') -0367 if ~isempty(model.metPubChemID{i}) -0368 if length(model.metPubChemID{i})>3 && strcmp(model.metPubChemID{i}(1:4),'CID:') -0369 newModel.metMiriams{i,1}.name{counter,1} = 'pubchem.compound'; -0370 newModel.metMiriams{i,1}.value{counter,1} = model.metPubChemID{i}; -0371 counter=counter+1; -0372 elseif length(model.metPubChemID{i})>3 && strcmp(model.metPubChemID{i}(1:4),'SID:') -0373 newModel.metMiriams{i,1}.name{counter,1} = 'pubchem.substance'; -0374 newModel.metMiriams{i,1}.value{counter,1} = model.metPubChemID{i}; -0375 counter=counter+1; -0376 else -0377 newModel.metMiriams{i,1}.name{counter,1} = 'pubchem.compound'; -0378 newModel.metMiriams{i,1}.value{counter,1} = model.metPubChemID{i}; -0379 counter=counter+1; -0380 printWarning=true; -0381 end -0382 end -0383 end -0384 for j = 1:length(metCOBRAfields) -0385 if isfield(model,metCOBRAfields{j}) -0386 metAnnotation = eval(['model.' metCOBRAfields{j} '{i}']); -0387 if ~isempty(metAnnotation) -0388 metAnnotation = strtrim(strsplit(metAnnotation,';')); -0389 for a=1:length(metAnnotation) -0390 newModel.metMiriams{i,1}.name{counter,1} = metNamespaces{j}; -0391 newModel.metMiriams{i,1}.value{counter,1} = metAnnotation{a}; -0392 counter=counter+1; -0393 end -0394 end -0395 end -0396 end -0397 end -0398 end -0399 if printWarning -0400 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'); -0401 end -0402 end -0403 -0404 % Order fields -0405 newModel=standardizeModelFieldOrder(newModel); % Corrects for both RAVEN and COBRA models -0406 end -0407 -0408 function rules=grrulesToRules(model) -0409 %This function just takes grRules, changes all gene names to -0410 %'x(geneNumber)' and also changes 'or' and 'and' relations to corresponding -0411 %symbols -0412 replacingGenes=cell([size(model.genes,1) 1]); -0413 for i=1:numel(replacingGenes) -0414 replacingGenes{i}=strcat('x(',num2str(i),')'); -0415 end -0416 rules = strcat({' '},model.grRules,{' '}); -0417 for i=1:length(model.genes) -0418 rules=regexprep(rules,[' ' model.genes{i} ' '],[' ' replacingGenes{i} ' ']); -0419 rules=regexprep(rules,['(' model.genes{i} ' '],['(' replacingGenes{i} ' ']); -0420 rules=regexprep(rules,[' ' model.genes{i} ')'],[' ' replacingGenes{i} ')']); -0421 end -0422 rules=regexprep(rules,' and ',' & '); -0423 rules=regexprep(rules,' or ',' | '); -0424 rules=strtrim(rules); -0425 end -0426 -0427 function grRules=rulesTogrrules(model) -0428 %This function takes rules, replaces &/| for and/or, replaces the x(i) -0429 %format with the actual gene ID, and takes out extra whitespace and -0430 %redundant parenthesis introduced by COBRA, to create grRules. -0431 grRules = strrep(model.rules,'&','and'); -0432 grRules = strrep(grRules,'|','or'); -0433 for i = 1:length(model.genes) -0434 grRules = strrep(grRules,['x(' num2str(i) ')'],model.genes{i}); -0435 end -0436 grRules = strrep(grRules,'( ','('); -0437 grRules = strrep(grRules,' )',')'); -0438 grRules = regexprep(grRules,'^(',''); %rules that start with a "(" -0439 grRules = regexprep(grRules,')$',''); %rules that end with a ")" -0440 end +0341 newModel.metNames=model.metNames; +0342 for i=1:numel(newModel.comps) +0343 newModel.metNames=regexprep(newModel.metNames,['\[', newModel.comps{i}, '\]$'],''); +0344 newModel.metNames=regexprep(newModel.metNames,['\[', newModel.compNames{i}, '\]$'],''); +0345 end +0346 newModel.metNames=deblank(newModel.metNames); +0347 newModel.metComps=regexprep(model.mets,'^.+\[',''); +0348 newModel.metComps=regexprep(newModel.metComps,'\]$',''); +0349 [~, newModel.metComps]=ismember(newModel.metComps,newModel.comps); +0350 if isfield(model,'metInChIString') +0351 newModel.inchis=regexprep(model.metInChIString,'^InChI=',''); +0352 end +0353 printWarning=false; +0354 if any(isfield(model,[metCOBRAfields;'metKEGGID';'metPubChemID'])) +0355 for i=1:numel(model.mets) +0356 counter=1; +0357 newModel.metMiriams{i,1}=[]; +0358 if isfield(model,'metKEGGID') +0359 if ~isempty(model.metKEGGID{i}) +0360 if strcmp(model.metKEGGID{i}(1),'C') +0361 newModel.metMiriams{i,1}.name{counter,1} = 'kegg.compound'; +0362 newModel.metMiriams{i,1}.value{counter,1} = model.metKEGGID{i}; +0363 counter=counter+1; +0364 elseif strcmp(model.metKEGGID{i}(1),'G') +0365 newModel.metMiriams{i,1}.name{counter,1} = 'kegg.glycan'; +0366 newModel.metMiriams{i,1}.value{counter,1} = model.metKEGGID{i}; +0367 counter=counter+1; +0368 end +0369 end +0370 end +0371 if isfield(model,'metPubChemID') +0372 if ~isempty(model.metPubChemID{i}) +0373 if length(model.metPubChemID{i})>3 && strcmp(model.metPubChemID{i}(1:4),'CID:') +0374 newModel.metMiriams{i,1}.name{counter,1} = 'pubchem.compound'; +0375 newModel.metMiriams{i,1}.value{counter,1} = model.metPubChemID{i}; +0376 counter=counter+1; +0377 elseif length(model.metPubChemID{i})>3 && strcmp(model.metPubChemID{i}(1:4),'SID:') +0378 newModel.metMiriams{i,1}.name{counter,1} = 'pubchem.substance'; +0379 newModel.metMiriams{i,1}.value{counter,1} = model.metPubChemID{i}; +0380 counter=counter+1; +0381 else +0382 newModel.metMiriams{i,1}.name{counter,1} = 'pubchem.compound'; +0383 newModel.metMiriams{i,1}.value{counter,1} = model.metPubChemID{i}; +0384 counter=counter+1; +0385 printWarning=true; +0386 end +0387 end +0388 end +0389 for j = 1:length(metCOBRAfields) +0390 if isfield(model,metCOBRAfields{j}) +0391 metAnnotation = eval(['model.' metCOBRAfields{j} '{i}']); +0392 if ~isempty(metAnnotation) +0393 metAnnotation = strtrim(strsplit(metAnnotation,';')); +0394 for a=1:length(metAnnotation) +0395 newModel.metMiriams{i,1}.name{counter,1} = metNamespaces{j}; +0396 newModel.metMiriams{i,1}.value{counter,1} = metAnnotation{a}; +0397 counter=counter+1; +0398 end +0399 end +0400 end +0401 end +0402 end +0403 end +0404 % Flatten subSystems if every reaction has exactly one subsystem. +0405 if isfield(newModel,'subSystems') && ~isempty(newModel.subSystems) +0406 if all(cellfun(@(x) iscell(x) && isscalar(x), newModel.subSystems)) +0407 newModel.subSystems = transpose([newModel.subSystems{:}]); +0408 end +0409 end +0410 if printWarning +0411 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'); +0412 end +0413 end +0414 +0415 % Order fields +0416 newModel=standardizeModelFieldOrder(newModel); % Corrects for both RAVEN and COBRA models +0417 end +0418 +0419 function rules=grrulesToRules(model) +0420 %This function just takes grRules, changes all gene names to +0421 %'x(geneNumber)' and also changes 'or' and 'and' relations to corresponding +0422 %symbols +0423 replacingGenes=cell([size(model.genes,1) 1]); +0424 for i=1:numel(replacingGenes) +0425 replacingGenes{i}=strcat('x(',num2str(i),')'); +0426 end +0427 rules = strcat({' '},model.grRules,{' '}); +0428 for i=1:length(model.genes) +0429 rules=regexprep(rules,[' ' model.genes{i} ' '],[' ' replacingGenes{i} ' ']); +0430 rules=regexprep(rules,['(' model.genes{i} ' '],['(' replacingGenes{i} ' ']); +0431 rules=regexprep(rules,[' ' model.genes{i} ')'],[' ' replacingGenes{i} ')']); +0432 end +0433 rules=regexprep(rules,' and ',' & '); +0434 rules=regexprep(rules,' or ',' | '); +0435 rules=strtrim(rules); +0436 end +0437 +0438 function grRules=rulesTogrrules(model) +0439 %This function takes rules, replaces &/| for and/or, replaces the x(i) +0440 %format with the actual gene ID, and takes out extra whitespace and +0441 %redundant parenthesis introduced by COBRA, to create grRules. +0442 grRules = strrep(model.rules,'&','and'); +0443 grRules = strrep(grRules,'|','or'); +0444 for i = 1:length(model.genes) +0445 grRules = strrep(grRules,['x(' num2str(i) ')'],model.genes{i}); +0446 end +0447 grRules = strrep(grRules,'( ','('); +0448 grRules = strrep(grRules,' )',')'); +0449 grRules = regexprep(grRules,'^(',''); %rules that start with a "(" +0450 grRules = regexprep(grRules,')$',''); %rules that end with a ")" +0451 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/testing/unit_tests/hmmerTests.html b/doc/testing/unit_tests/hmmerTests.html index dec29c58..121a6d33 100644 --- a/doc/testing/unit_tests/hmmerTests.html +++ b/doc/testing/unit_tests/hmmerTests.html @@ -68,124 +68,136 @@

    SOURCE CODE ^'-completenames'); 0022 ravenPath=fileparts(fileparts(fileparts(ST(I).file))); 0023 -0024 %Identify the operating system -0025 if isunix -0026 if ismac -0027 binEnd='.mac'; -0028 else -0029 binEnd=''; -0030 end -0031 elseif ispc -0032 binEnd='.exe'; -0033 else -0034 dispEM('Unknown OS, exiting.') -0035 return -0036 end -0037 -0038 %Create empty structures needed for HMMER results -0039 actHmmResult.genes = {}; -0040 actHmmResult.scores = []; -0041 -0042 %Create structures that contain expected HMMER results -0043 expHmmResult.genes = {'sp|P41947|MEL6_YEASX','sp|P41946|MEL5_YEASX', 'sp|P41945|MEL2_YEASX', 'sp|P04824|MEL1_YEASX'}; -0044 expHmmResult.scores = [10^-250, 10^-250, 10^-250, 10^-250]; -0045 -0046 %Generate temporary names for working directory and outFile -0047 tmpDIR=tempname; -0048 outFile=tempname; -0049 -0050 %Run HMMER multi-threaded to use all logical cores assigned to MATLAB -0051 cores = evalc('feature(''numcores'')'); -0052 cores = strsplit(cores, 'MATLAB was assigned: '); -0053 cores = regexp(cores{2},'^\d*','match'); -0054 cores = cores{1}; -0055 -0056 %Create a temporary folder and copy multi-FASTA file there -0057 [~, ~]=system(['mkdir "' tmpDIR '"']); -0058 -0059 sourceDir = fileparts(which(mfilename)); -0060 copyfile(fullfile(sourceDir,'test_data','yeast_galactosidases.fa'),tmpDIR); -0061 copyfile(fullfile(sourceDir,'test_data','human_galactosidases.fa'),tmpDIR); -0062 -0063 %% -0064 %Train a hidden Markov model -0065 [~, ~]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmbuild' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(tmpDIR,'human_galactosidases.hmm') '" "' fullfile(tmpDIR,'yeast_galactosidases.fa') '"']); +0024 %Generate temporary names for working directory and outFile +0025 tmpDIR=tempname; +0026 outFile=tempname; +0027 +0028 %Create a temporary folder and copy multi-FASTA file there +0029 [~, ~]=system(['mkdir "' tmpDIR '"']); +0030 +0031 sourceDir = fileparts(which(mfilename)); +0032 copyfile(fullfile(sourceDir,'test_data','yeast_galactosidases.fa'),tmpDIR); +0033 copyfile(fullfile(sourceDir,'test_data','human_galactosidases.fa'),tmpDIR); +0034 +0035 +0036 %Identify the operating system +0037 if isunix +0038 if ismac +0039 binEnd='.mac'; +0040 else +0041 binEnd=''; +0042 end +0043 elseif ispc +0044 wslPath.tmpDIR = getWSLpath(tmpDIR); +0045 wslPath.hmmbuild = getWSLpath(fullfile(ravenPath,'software','hmmer','hmmbuild')); +0046 wslPath.hmmsearch = getWSLpath(fullfile(ravenPath,'software','hmmer','hmmsearch')); +0047 filesep='/'; +0048 else +0049 dispEM('Unknown OS, exiting.') +0050 return +0051 end +0052 +0053 %Create empty structures needed for HMMER results +0054 actHmmResult.genes = {}; +0055 actHmmResult.scores = []; +0056 +0057 %Create structures that contain expected HMMER results +0058 expHmmResult.genes = {'sp|P41947|MEL6_YEASX','sp|P41946|MEL5_YEASX', 'sp|P41945|MEL2_YEASX', 'sp|P04824|MEL1_YEASX'}; +0059 expHmmResult.scores = [10^-250, 10^-250, 10^-250, 10^-250]; +0060 +0061 %Run HMMER multi-threaded to use all logical cores assigned to MATLAB +0062 cores = evalc('feature(''numcores'')'); +0063 cores = strsplit(cores, 'MATLAB was assigned: '); +0064 cores = regexp(cores{2},'^\d*','match'); +0065 cores = cores{1}; 0066 -0067 %Run a homology search against the newly-trained HMM -0068 [~, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmsearch' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(tmpDIR,'human_galactosidases.hmm') '" "' fullfile(tmpDIR,'yeast_galactosidases.fa') '"']); -0069 -0070 %Save the output to a file -0071 fid=fopen(outFile,'w'); -0072 fwrite(fid,output); -0073 fclose(fid); +0067 %% +0068 %Train a hidden Markov model +0069 if ismac || isunix +0070 [~, ~]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmbuild' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(tmpDIR,'human_galactosidases.hmm') '" "' fullfile(tmpDIR,'yeast_galactosidases.fa') '"']); +0071 else +0072 [~, ~]=system(['wsl "' wslPath.hmmbuild '" --cpu "' num2str(cores) '" "' wslPath.tmpDIR '/human_galactosidases.hmm" "' wslPath.tmpDIR '/yeast_galactosidases.fa"']); +0073 end 0074 -0075 %% -0076 %Parse the results -0077 geneCounter=0; -0078 fid=fopen(outFile,'r'); -0079 beginMatches=false; -0080 while 1 -0081 %Get the next line -0082 tline = fgetl(fid); -0083 -0084 %Abort at end of file -0085 if ~ischar(tline) -0086 break; -0087 end -0088 -0089 if and(beginMatches,strcmp(tline,' ------ inclusion threshold ------')) -0090 break; -0091 end -0092 -0093 if beginMatches==false -0094 %This is how the listing of matches begins -0095 if any(strfind(tline,'E-value ')) -0096 %Read one more line that is only padding -0097 tline = fgetl(fid); -0098 beginMatches=true; -0099 end -0100 else -0101 %If matches should be read -0102 if ~strcmp(tline,' [No hits detected that satisfy reporting thresholds]') && ~isempty(tline) -0103 elements=regexp(tline,' ','split'); -0104 elements=elements(cellfun(@any,elements)); -0105 -0106 %Check if the match is below the treshhold -0107 score=str2double(elements{1}); -0108 gene=elements{9}; -0109 if score<=10^-50 -0110 %If the score is exactly 0, change it to a very -0111 %small value to avoid NaN -0112 if score==0 -0113 score=10^-250; -0114 end -0115 %Check if the gene is added already and, is so, get -0116 %the best score for it -0117 geneCounter=geneCounter+1; -0118 actHmmResult.genes{geneCounter}=gene; -0119 actHmmResult.scores(geneCounter)=score; -0120 end -0121 else -0122 break; -0123 end -0124 end -0125 end -0126 fclose(fid); -0127 -0128 %Remove the old tempfiles -0129 delete([outFile '*']); -0130 -0131 %Remove temporary folder, since testing is finished -0132 [~, ~]=system(['rm "' tmpDIR '" -r']); -0133 -0134 %% -0135 %Test 1a: Check if HMMER results match the expected ones -0136 verifyEqual(testCase,actHmmResult,expHmmResult); -0137 -0138 %Test 1b: Modify actual HMMER results structure and check if test fails -0139 actHmmResult.score(2)=1; -0140 verifyNotEqual(testCase,actHmmResult,expHmmResult); -0141 end +0075 %Run a homology search against the newly-trained HMM +0076 if ismac || isunix +0077 [~, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmsearch' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(tmpDIR,'human_galactosidases.hmm') '" "' fullfile(tmpDIR,'yeast_galactosidases.fa') '"']); +0078 else +0079 [~, output]=system(['wsl "' wslPath.hmmsearch '" --cpu "' num2str(cores) '" "' wslPath.tmpDIR '/human_galactosidases.hmm" "' wslPath.tmpDIR '/yeast_galactosidases.fa"']); +0080 end +0081 +0082 %Save the output to a file +0083 fid=fopen(outFile,'w'); +0084 fwrite(fid,output); +0085 fclose(fid); +0086 +0087 %% +0088 %Parse the results +0089 geneCounter=0; +0090 fid=fopen(outFile,'r'); +0091 beginMatches=false; +0092 while 1 +0093 %Get the next line +0094 tline = fgetl(fid); +0095 +0096 %Abort at end of file +0097 if ~ischar(tline) +0098 break; +0099 end +0100 +0101 if and(beginMatches,strcmp(tline,' ------ inclusion threshold ------')) +0102 break; +0103 end +0104 +0105 if beginMatches==false +0106 %This is how the listing of matches begins +0107 if any(strfind(tline,'E-value ')) +0108 %Read one more line that is only padding +0109 tline = fgetl(fid); +0110 beginMatches=true; +0111 end +0112 else +0113 %If matches should be read +0114 if ~strcmp(tline,' [No hits detected that satisfy reporting thresholds]') && ~isempty(tline) +0115 elements=regexp(tline,' ','split'); +0116 elements=elements(cellfun(@any,elements)); +0117 +0118 %Check if the match is below the treshhold +0119 score=str2double(elements{1}); +0120 gene=elements{9}; +0121 if score<=10^-50 +0122 %If the score is exactly 0, change it to a very +0123 %small value to avoid NaN +0124 if score==0 +0125 score=10^-250; +0126 end +0127 %Check if the gene is added already and, is so, get +0128 %the best score for it +0129 geneCounter=geneCounter+1; +0130 actHmmResult.genes{geneCounter}=gene; +0131 actHmmResult.scores(geneCounter)=score; +0132 end +0133 else +0134 break; +0135 end +0136 end +0137 end +0138 fclose(fid); +0139 +0140 %Remove the old tempfiles +0141 delete([outFile '*']); +0142 +0143 %Remove temporary folder, since testing is finished +0144 [~, ~]=system(['rm "' tmpDIR '" -r']); +0145 +0146 %% +0147 %Test 1a: Check if HMMER results match the expected ones +0148 verifyEqual(testCase,actHmmResult,expHmmResult); +0149 +0150 %Test 1b: Modify actual HMMER results structure and check if test fails +0151 actHmmResult.score(2)=1; +0152 verifyNotEqual(testCase,actHmmResult,expHmmResult); +0153 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 index 6e32b08f..60dc50cf 100644 --- a/doc/testing/unit_tests/importExportTests.html +++ b/doc/testing/unit_tests/importExportTests.html @@ -83,7 +83,7 @@

    SOURCE CODE ^function testExcelExport(testCase) 0037 sourceDir=fileparts(fileparts(fileparts(which(mfilename)))); 0038 load(fullfile(sourceDir,'testing','unit_tests','test_data','ecoli_textbook.mat'), 'model'); -0039 exportToExcelFormat(model,fullfile(sourceDir,'testing','unit_tests','test_data','_test.xlsx')); +0039 evalc('exportToExcelFormat(model,fullfile(sourceDir,''testing'',''unit_tests'',''test_data'',''_test.xlsx''))'); 0040 %File will not be exactly equal as it contains the current date and time, 0041 %so md5 or similar would not work. Just check whether file is reasonably 0042 %sized. diff --git a/doc/utils/emptyOrLogicalScalar.html b/doc/utils/emptyOrLogicalScalar.html new file mode 100644 index 00000000..a7371337 --- /dev/null +++ b/doc/utils/emptyOrLogicalScalar.html @@ -0,0 +1,53 @@ + + + + Description of emptyOrLogicalScalar + + + + + + + + + +
    Home > utils > emptyOrLogicalScalar.m
    + + + +

    emptyOrLogicalScalar +

    + +

    PURPOSE ^

    +
    + +

    SYNOPSIS ^

    +
    function emptyOrLogical(x)
    + +

    DESCRIPTION ^

    +
    + + +

    CROSS-REFERENCE INFORMATION ^

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

    SOURCE CODE ^

    +
    0001 function emptyOrLogical(x)
    +0002     if isempty(x)
    +0003         return;
    +0004     end
    +0005     validateattributes(x, {'logical'}, {'scalar'});
    +0006 end
    +
    Generated by m2html © 2005
    + + \ No newline at end of file diff --git a/doc/utils/emptyOrTextOrCellOfText.html b/doc/utils/emptyOrTextOrCellOfText.html new file mode 100644 index 00000000..72298c9a --- /dev/null +++ b/doc/utils/emptyOrTextOrCellOfText.html @@ -0,0 +1,90 @@ + + + + Description of emptyOrTextOrCellOfText + + + + + + + + + +
    Home > utils > emptyOrTextOrCellOfText.m
    + + + +

    emptyOrTextOrCellOfText +

    + +

    PURPOSE ^

    +
    Validate [] OR text scalar (char row or string scalar) OR cell array of such text.
    + +

    SYNOPSIS ^

    +
    function mustBeEmptyOrTextOrCellOfText(x)
    + +

    DESCRIPTION ^

    +
     Validate [] OR text scalar (char row or string scalar) OR cell array of such text.
    + + +

    CROSS-REFERENCE INFORMATION ^

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

    SOURCE CODE ^

    +
    0001 function mustBeEmptyOrTextOrCellOfText(x)
    +0002 % Validate [] OR text scalar (char row or string scalar) OR cell array of such text.
    +0003 
    +0004 % Allow explicit empty
    +0005 if isempty(x)
    +0006     return;
    +0007 end
    +0008 
    +0009 % Allow a single text scalar
    +0010 if ischar(x)
    +0011     if ~isrow(x)
    +0012         error('Text must be a character row vector, a string scalar, or empty.');
    +0013     end
    +0014     return;
    +0015 elseif isstring(x)
    +0016     if ~isscalar(x)
    +0017         error('Text must be a string scalar, a character row vector, or empty.');
    +0018     end
    +0019     return;
    +0020 end
    +0021 
    +0022 % Allow a cell array of text
    +0023 if iscell(x)
    +0024     for k = 1:numel(x)
    +0025         v = x{k};
    +0026         if ischar(v)
    +0027             if ~isrow(v)   % '' is 1x0 char, which is a row -> allowed
    +0028                 error('Each cell element must be a character row vector or a string scalar.');
    +0029             end
    +0030         elseif isstring(v)
    +0031             if ~isscalar(v)  % "" is a scalar string -> allowed
    +0032                 error('Each cell element must be a string scalar or a character row vector.');
    +0033             end
    +0034         else
    +0035             error('Each cell element must be text (string scalar or character row vector).');
    +0036         end
    +0037     end
    +0038     return;
    +0039 end
    +0040 
    +0041 % Anything else is invalid
    +0042 error('Value must be empty, a text value, or a cell array of text values.');
    +0043 end
    +
    Generated by m2html © 2005
    + + \ No newline at end of file diff --git a/doc/utils/emptyOrTextScalar.html b/doc/utils/emptyOrTextScalar.html new file mode 100644 index 00000000..7d53acd3 --- /dev/null +++ b/doc/utils/emptyOrTextScalar.html @@ -0,0 +1,59 @@ + + + + Description of emptyOrTextScalar + + + + + + + + + +
    Home > utils > emptyOrTextScalar.m
    + + + +

    emptyOrTextScalar +

    + +

    PURPOSE ^

    +
    + +

    SYNOPSIS ^

    +
    function mustBeEmptyOrTextScalar(x)
    + +

    DESCRIPTION ^

    +
    + + +

    CROSS-REFERENCE INFORMATION ^

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

    SOURCE CODE ^

    +
    0001 function mustBeEmptyOrTextScalar(x)
    +0002     if isempty(x)
    +0003         return;
    +0004     end
    +0005     if isstring(x)
    +0006         if ~isscalar(x), error('Value must be a string scalar or empty.'); end
    +0007     elseif ischar(x)
    +0008         if ~isrow(x), error('Char input must be a row vector or empty.'); end
    +0009     else
    +0010         error('Value must be a string/char scalar or empty.');
    +0011     end
    +0012 end
    +
    Generated by m2html © 2005
    + + \ No newline at end of file diff --git a/doc/utils/index.html b/doc/utils/index.html new file mode 100644 index 00000000..9a1637b6 --- /dev/null +++ b/doc/utils/index.html @@ -0,0 +1,29 @@ + + + + Index for Directory utils + + + + + + + + + + +
    < Master indexIndex for utils >
    + +

    Index for utils

    + +

    Matlab files in this directory:

    + +
     emptyOrLogicalScalar
     emptyOrTextOrCellOfTextValidate [] OR text scalar (char row or string scalar) OR cell array of such text.
     emptyOrTextScalar
     runRAVENtestsrunRAVENtests
    + + + + +
    Generated by m2html © 2005
    + + \ No newline at end of file diff --git a/doc/utils/runRAVENtests.html b/doc/utils/runRAVENtests.html new file mode 100644 index 00000000..da9c79b7 --- /dev/null +++ b/doc/utils/runRAVENtests.html @@ -0,0 +1,60 @@ + + + + Description of runRAVENtests + + + + + + + + + +
    Home > utils > runRAVENtests.m
    + + + +

    runRAVENtests +

    + +

    PURPOSE ^

    +
    runRAVENtests
    + +

    SYNOPSIS ^

    +
    function testResults = runRAVENtests
    + +

    DESCRIPTION ^

    +
     runRAVENtests
    +  Runs all unit tests found at RAVEN/test/unit_tests, and prints output in
    +  command window.
    + + +

    CROSS-REFERENCE INFORMATION ^

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

    SOURCE CODE ^

    +
    0001 function testResults = runRAVENtests
    +0002 % runRAVENtests
    +0003 %  Runs all unit tests found at RAVEN/test/unit_tests, and prints output in
    +0004 %  command window.
    +0005 
    +0006 ravenPath = findRAVENroot;
    +0007 curwd = pwd;
    +0008 cd(fullfile(ravenPath,'testing','unit_tests'));
    +0009 testResults = runtests(struct2table(dir('*.m')).name);
    +0010 
    +0011 cd(curwd);
    +
    Generated by m2html © 2005
    + + \ No newline at end of file diff --git a/external/kegg/getKEGGModelForOrganism.m b/external/kegg/getKEGGModelForOrganism.m index 24355620..24b69bdc 100755 --- a/external/kegg/getKEGGModelForOrganism.m +++ b/external/kegg/getKEGGModelForOrganism.m @@ -38,7 +38,7 @@ % The hidden Markov models as generated in 2b or % downloaded from BioMet Toolbox (see below) % The final directory in dataDir should be styled as -% prok90_kegg105 or euk90_kegg105, indicating whether +% prok90_kegg116 or euk90_kegg116, indicating whether % the HMMs were trained on pro- or eukaryotic % sequences; using which sequence similarity treshold % (first set of digits); using which KEGG version @@ -99,12 +99,12 @@ % If -1 is provided, CD-HIT is skipped (optional, default 0.9) % globalModel structure containing both model and KOModel % structures as generated by getModelFromKEGG. These -% will otherwise be loaded by via getModelFromKEGG. +% will otherwise be loaded by via getModelFromKEGG. % Providing globalKEGGmodel can speed up model % generation if getKEGGModelForOrganism is run % multiple times for different strains. Example: % [globalModel.model,globalModel.KOModel] = getModelFromKEGG; -% (optional, default empty, global model is loaded by +% (optional, default empty, global model is loaded by % getModelFromKEGG) % % Output: @@ -259,36 +259,36 @@ else outDir=char(outDir); end -if nargin<5 +if nargin<5 || isempty(keepSpontaneous) keepSpontaneous=true; end -if nargin<6 +if nargin<6 || isempty(keepUndefinedStoich) keepUndefinedStoich=true; end -if nargin<7 +if nargin<7 || isempty(keepIncomplete) keepIncomplete=true; end -if nargin<8 +if nargin<8 || isempty(keepGeneral) keepGeneral=false; end -if nargin<9 +if nargin<9 || isempty(cutOff) cutOff=10^-50; end -if nargin<10 +if nargin<10 || isempty(minScoreRatioKO) minScoreRatioKO=0.3; end -if nargin<11 +if nargin<11 || isempty(minScoreRatioG) minScoreRatioG=0.8; end -if nargin<12 +if nargin<12 || isempty(maxPhylDist) maxPhylDist=inf; %Include all sequences for each reaction end -if nargin<13 +if nargin<13 || isempty(nSequences) nSequences=inf; %Include all sequences for each reaction end -if nargin<14 +if nargin<14 || isempty(seqIdentity) seqIdentity=0.9; end @@ -315,9 +315,9 @@ %required zip file already in working directory or have it extracted. If %the zip file and directory is not here, it is downloaded from the cloud if ~isempty(dataDir) - hmmOptions={'euk90_kegg105','prok90_kegg105'}; + hmmOptions={'euk90_kegg116','prok90_kegg116'}; if ~endsWith(dataDir,hmmOptions) %Check if dataDir ends with any of the hmmOptions. - %If not, then check whether the required folders exist anyway. + %If not, then check whether the required folders exist anyway. if ~isfile(fullfile(dataDir,'keggdb','genes.pep')) && ... ~isfolder(fullfile(dataDir,'fasta')) && ... ~isfolder(fullfile(dataDir,'aligned')) && ... @@ -334,19 +334,19 @@ else hmmIndex=strcmp(dataDir,hmmOptions); if ~any(hmmIndex) - error(['Pre-trained HMMs are only provided with proteins clustered at 90% sequence identity (i.e. prok90_kegg105 and euk90_kegg105). ' ... + error(['Pre-trained HMMs are only provided with proteins clustered at 90% sequence identity (i.e. prok90_kegg116 and euk90_kegg116). ' ... 'Use either of these datasets, or otherwise download the relevant sequence data from KEGG to train HMMs with your desired sequence identity']) else fprintf('Downloading the HMMs archive file... '); try - websave([dataDir,'.zip'],['https://github.com/SysBioChalmers/RAVEN/releases/download/v2.8.0/',hmmOptions{hmmIndex},'.zip']); + websave([dataDir,'.zip'],['https://github.com/SysBioChalmers/RAVEN/releases/download/v2.11.0/',hmmOptions{hmmIndex},'.zip']); catch ME if strcmp(ME.identifier,'MATLAB:webservices:HTTP404StatusCodeError') 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') end end end - + fprintf('COMPLETE\n'); fprintf('Extracting the HMMs archive file... '); unzip([dataDir,'.zip']); @@ -406,7 +406,7 @@ if ~ismember(organismID,[phylDistsFull.ids 'eukaryotes' 'prokaryotes']) error('Provided organismID is incorrect. Only species abbreviations from KEGG Species List or "eukaryotes"/"prokaryotes" are allowed.'); end - + fprintf(['Pruning the model from non-' organismID ' genes... ']); if ismember(organismID,{'eukaryotes','prokaryotes'}) phylDists=getPhylDist(fullfile(dataDir,'keggdb'),maxPhylDist==-1); @@ -552,6 +552,20 @@ return end +tmpFile=tempname; +%On Windows, paths need to be translated to Unix before parsing it to WSL +if ispc + wslPath.tmpFile=getWSLpath(tmpFile); + %mafft has problems writing to terminal (/dev/stderr) when running + %on WSL via MATLAB, instead write and read progress file + mafftOutput = tempname; + wslPath.mafftOutput=getWSLpath(mafftOutput); + wslPath.mafft=getWSLpath(fullfile(ravenPath,'software','mafft','mafft-linux64','mafft.bat')); + wslPath.hmmbuild=getWSLpath(fullfile(ravenPath,'software','hmmer','hmmbuild')); + wslPath.hmmsearch=getWSLpath(fullfile(ravenPath,'software','hmmer','hmmsearch')); + wslPath.cdhit=getWSLpath(fullfile(ravenPath,'software','cd-hit','cd-hit')); +end + %Check if alignment of FASTA files should be performed missingAligned=setdiff(KOModel.rxns,[alignedFiles;hmmFiles;alignedWorking;outFiles]); if ~isempty(missingAligned) @@ -561,18 +575,7 @@ fprintf('Performing clustering and multiple alignment for KEGG Orthology specific protein sets... 0%% complete'); end missingAligned=missingAligned(randperm(RandStream.create('mrg32k3a','Seed',cputime()),numel(missingAligned))); - tmpFile=tempname; - %On Windows, paths need to be translated to Unix before parsing it to WSL - if ispc - wslPath.tmpFile=getWSLpath(tmpFile); - %mafft has problems writing to terminal (/dev/stderr) when running - %on WSL via MATLAB, instead write and read progress file - mafftOutput = tempname; - wslPath.mafftOutput=getWSLpath(mafftOutput); - wslPath.mafft=getWSLpath(fullfile(ravenPath,'software','mafft','mafft-linux64','mafft.bat')); - wslPath.cdhit=getWSLpath(fullfile(ravenPath,'software','cd-hit','cd-hit')); - end - + for i=1:numel(missingAligned) %This is checked here because it could be that it is created by a %parallel process. The faw-files are saved as temporary files to @@ -587,7 +590,7 @@ dispEM(EM,false); continue; end - + %If the multi-FASTA file is empty then save an empty aligned %file and continue s=dir(fullfile(dataDir,'fasta',[missingAligned{i} '.fa'])); @@ -596,17 +599,17 @@ fclose(fid); continue; end - + %Create an empty file to prevent other threads to start to work %on the same alignment fid=fopen(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),'w'); fclose(fid); - + %First load the FASTA file, then select up to nSequences %sequences of the most closely related species, apply any %constraints from maxPhylDist, and save it as a temporary file, %and create the model from that - + fastaStruct=fastaread(fullfile(dataDir,'fasta',[missingAligned{i} '.fa'])); phylDist=inf(numel(fastaStruct),1); for j=1:numel(fastaStruct) @@ -620,24 +623,24 @@ end end end - + %Inf means that it should not be included phylDist(phylDist>maxPhylDist)=[]; - + %Sort based on phylDist [~, order]=sort(phylDist); - + %Save the first nSequences hits to a temporary FASTA file if nSequences<=numel(fastaStruct) fastaStruct=fastaStruct(order(1:nSequences)); else fastaStruct=fastaStruct(order); end - + %Do the clustering and alignment if there are more than one %sequences, otherwise just save the sequence (or an empty file) if numel(fastaStruct)>1 - if seqIdentity~=-1 + if seqIdentity~=-1 cdhitInpCustom=tempname; fastawrite(cdhitInpCustom,fastaStruct); if seqIdentity<=1 && seqIdentity>0.7 @@ -712,7 +715,7 @@ end %Move the temporary file to the real one movefile(fullfile(dataDir,'aligned',[missingAligned{i} '.faw']),fullfile(dataDir,'aligned',[missingAligned{i} '.fa']),'f'); - + %Print the progress every 25 files if rem(i-1,25) == 0 progress=num2str(floor(100*numel(listFiles(fullfile(dataDir,'aligned','*.fa')))/numel(KOModel.rxns))); @@ -750,7 +753,7 @@ dispEM(EM,false); continue; end - + %If the multi-FASTA file is empty then save an empty aligned %file and continue s=dir(fullfile(dataDir,'aligned',[missingHMMs{i} '.fa'])); @@ -763,14 +766,20 @@ %KO. This is because hmmbuild cannot overwrite existing files fid=fopen(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmw']),'w'); fclose(fid); - + %Create HMM - [status, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmbuild' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm']) '" "' fullfile(dataDir,'aligned',[missingHMMs{i} '.fa']) '"']); + if ismac || isunix + [status, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmbuild' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm']) '" "' fullfile(dataDir,'aligned',[missingHMMs{i} '.fa']) '"']); + else + wslPath.hmmFile = getWSLpath(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmm'])); + wslPath.alignFile = getWSLpath(fullfile(dataDir,'aligned',[missingHMMs{i} '.fa'])); + [status, output] = system(['wsl "' wslPath.hmmbuild '" --cpu "' num2str(cores) '" "' wslPath.hmmFile '" "' wslPath.alignFile '"']); + end if status~=0 EM=['Error when training HMM for ' missingHMMs{i} ':\n' output]; dispEM(EM); end - + %Delete the temporary file delete(fullfile(dataDir,'hmms',[missingHMMs{i} '.hmw'])); @@ -805,30 +814,36 @@ dispEM(EM,false); continue; end - + %Save an empty file to prevent several threads working on the %same file fid=fopen(fullfile(outDir,[missingOUT{i} '.out']),'w'); fclose(fid); - + %If the HMM file is empty then save an out file and continue s=dir(fullfile(dataDir,'hmms',[missingOUT{i} '.hmm'])); if s.bytes<=0 continue; end - + %Check each gene in the input file against this model - [status, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmsearch' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(dataDir,'hmms',[missingOUT{i} '.hmm']) '" "' fastaFile '"']); + if ismac || isunix + [status, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmsearch' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(dataDir,'hmms',[missingOUT{i} '.hmm']) '" "' fastaFile '"']); + else + wslPath.hmmFile = getWSLpath(fullfile(dataDir,'hmms',[missingOUT{i} '.hmm'])); + wslPath.fastaFile = getWSLpath(fastaFile); + [status, output]=system(['wsl "' wslPath.hmmsearch '" --cpu "' num2str(cores) '" "' wslPath.hmmFile '" "' wslPath.fastaFile '"']); + end if status~=0 EM=['Error when querying HMM for ' missingOUT{i} ':\n' output]; dispEM(EM); end - + %Save the output to a file fid=fopen(fullfile(outDir,[missingOUT{i} '.out']),'w'); fwrite(fid,output); fclose(fid); - + %Print the progress every 25 files if rem(i-1,25) == 0 progress=num2str(floor(100*numel(listFiles(fullfile(outDir,'*.out')))/numel(KOModel.rxns))); @@ -861,16 +876,16 @@ while 1 %Get the next line tline = fgetl(fid); - + %Abort at end of file if ~ischar(tline) break; end - + if and(beginMatches,strcmp(tline,' ------ inclusion threshold ------')) break; end - + if beginMatches==false %This is how the listing of matches begins if any(strfind(tline,'E-value ')) @@ -883,7 +898,7 @@ if ~strcmp(tline,' [No hits detected that satisfy reporting thresholds]') && ~isempty(tline) elements=regexp(tline,' ','split'); elements=elements(cellfun(@any,elements)); - + %Check if the match is below the treshhold score=str2double(elements{1}); gene=elements{9}; @@ -952,7 +967,7 @@ %Find the KOs and the corresponding genes J=ismember(KOModel.rxns,KOs); [~, K]=find(koGeneMat(J,:)); - + if any(K) model.rxnGeneMat(i,K)=1; %Also delete KOs for which no genes were found. If no genes at @@ -1011,10 +1026,6 @@ model.grRules = grRules; model.rxnGeneMat = rxnGeneMat; -%Fix subsystems -emptySubSystems=cellfun(@isempty, model.subSystems); -model.subSystems(emptySubSystems)={{''}}; - %Add the description to the reactions for i=1:numel(model.rxns) if ~isempty(model.rxnNotes{i}) diff --git a/external/kegg/getModelFromKEGG.m b/external/kegg/getModelFromKEGG.m index d9871a9f..9530ba72 100755 --- a/external/kegg/getModelFromKEGG.m +++ b/external/kegg/getModelFromKEGG.m @@ -44,8 +44,10 @@ % Usage: [model,KOModel]=getModelFromKEGG(keggPath,keepSpontaneous,... % keepUndefinedStoich,keepIncomplete,keepGeneral) +ravenPath=findRAVENroot(); + if nargin<1 - keggPath='RAVEN/external/kegg'; + keggPath=fullfile(ravenPath,'external','kegg'); else keggPath=char(keggPath); end @@ -62,7 +64,6 @@ keepGeneral=false; end -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/getRxnsFromKEGG.m b/external/kegg/getRxnsFromKEGG.m index eab27d87..ed94d8b9 100755 --- a/external/kegg/getRxnsFromKEGG.m +++ b/external/kegg/getRxnsFromKEGG.m @@ -68,15 +68,16 @@ % (except for '///') % +ravenPath=findRAVENroot(); + if nargin<1 - keggPath='RAVEN/external/kegg'; + keggPath=fullfile(ravenPath,'external','kegg'); else keggPath=char(keggPath); end %Check if the reactions have been parsed before and saved. If so, load the %model -ravenPath=findRAVENroot(); rxnsFile=fullfile(ravenPath,'external','kegg','keggRxns.mat'); if exist(rxnsFile, 'file') fprintf(['Importing KEGG reactions from ' strrep(rxnsFile,'\','/') '... ']); @@ -130,7 +131,12 @@ if numel(tline)<12 continue; end - + % Skip other lines with unused information + if strcmp(tline(1:5),'BRITE') + pathway = false; + continue; + end + %Check if it's a new reaction if strcmp(tline(1:12),'ENTRY ') rxnCounter=rxnCounter+1; @@ -138,7 +144,7 @@ %Add empty strings where there should be such model.rxnNames{rxnCounter}=''; model.eccodes{rxnCounter}=''; - %model.subSystems{rxnCounter}=''; %remain empty cell + %model.subSystems{rxnCounter}={''}; %remain empty cell model.rxnNotes{rxnCounter}=''; equations{rxnCounter}=''; @@ -304,7 +310,7 @@ model.subSystems{rxnCounter}=tline(28:end); else %The new format - model.subSystems{rxnCounter,1}{1,numel(model.subSystems{rxnCounter,1})+1}=tline(22:end); + model.subSystems{rxnCounter,1}{numel(model.subSystems{rxnCounter,1})+1,1}=tline(22:end); end end end @@ -329,6 +335,9 @@ model.rxnNotes=model.rxnNotes(1:rxnCounter); model.subSystems=model.subSystems(1:rxnCounter); + emptySubSys = cellfun(@isempty,model.subSystems); + model.subSystems(emptySubSys) = {{''}}; + %Then load the equations from another file. This is because the %equations are easier to retrieve from there diff --git a/external/kegg/keggGenes.mat b/external/kegg/keggGenes.mat index 2456d77a..2494cbe9 100644 Binary files a/external/kegg/keggGenes.mat and b/external/kegg/keggGenes.mat differ diff --git a/external/kegg/keggMets.mat b/external/kegg/keggMets.mat index bbe4a90d..784901c0 100644 Binary files a/external/kegg/keggMets.mat and b/external/kegg/keggMets.mat differ diff --git a/external/kegg/keggPhylDist.mat b/external/kegg/keggPhylDist.mat index 9cdde3b9..0f05bf94 100644 Binary files a/external/kegg/keggPhylDist.mat and b/external/kegg/keggPhylDist.mat differ diff --git a/external/kegg/keggRxns.mat b/external/kegg/keggRxns.mat index 78802a41..f5a62f8d 100644 Binary files a/external/kegg/keggRxns.mat and b/external/kegg/keggRxns.mat differ diff --git a/external/metacyc/getRxnsFromMetaCyc.m b/external/metacyc/getRxnsFromMetaCyc.m index d5611c43..8d6b0b8a 100755 --- a/external/metacyc/getRxnsFromMetaCyc.m +++ b/external/metacyc/getRxnsFromMetaCyc.m @@ -244,7 +244,7 @@ [x, y]=ismember(tline(14:end),pwys); if x - metaCycRxns.subSystems{rxnCounter,1}{1,numel(metaCycRxns.subSystems{rxnCounter,1})+1}=pwyNames{y}; + metaCycRxns.subSystems{rxnCounter,1}{numel(metaCycRxns.subSystems{rxnCounter,1})+1,1}=pwyNames{y}; end end diff --git a/external/metacyc/metaCycEnzymes.mat b/external/metacyc/metaCycEnzymes.mat index 1caf660f..7b03db05 100644 Binary files a/external/metacyc/metaCycEnzymes.mat and b/external/metacyc/metaCycEnzymes.mat differ diff --git a/external/metacyc/metaCycMets.mat b/external/metacyc/metaCycMets.mat index cb86ac0c..26707d6a 100644 Binary files a/external/metacyc/metaCycMets.mat and b/external/metacyc/metaCycMets.mat differ diff --git a/external/metacyc/metaCycRxns.mat b/external/metacyc/metaCycRxns.mat index 97a069a1..e5c680ce 100644 Binary files a/external/metacyc/metaCycRxns.mat and b/external/metacyc/metaCycRxns.mat differ diff --git a/external/parseScores.m b/external/parseScores.m index 662320c2..ae865b26 100755 --- a/external/parseScores.m +++ b/external/parseScores.m @@ -92,7 +92,7 @@ %Read the title line and fetch the list of compartments tline = fgetl(fid); GSS.compartments=regexp(tline,',','split'); - GSS.compartments=GSS.compartments(4:end); + GSS.compartments=transpose(GSS.compartments(4:end)); %Now iterate through the following lines in the file. Each row %corresponds to one gene and it consists of the scores for diff --git a/installation/checkInstallation.m b/installation/checkInstallation.m index 4a1784fa..de8c1236 100755 --- a/installation/checkInstallation.m +++ b/installation/checkInstallation.m @@ -1,4 +1,4 @@ -function [currVer, installType] = checkInstallation(developMode) +function [currVer, installType] = checkInstallation(developMode,checkBinaries) % checkInstallation % The purpose of this function is to check if all necessary functions are % installed and working. It also checks whether there are any functions @@ -11,6 +11,9 @@ % HMMs (optional, default false). If 'versionOnly' is % specified, only the version is reported as currVer, no % further installation or tests are performed. +% checkBinaries logical whether non-developMode binaries should be +% checked for functionality. If false, it overwrites +% developMode. Default true. % % Output: % currVer current RAVEN version @@ -27,6 +30,9 @@ if nargin<1 developMode=false; end +if nargin<2 + checkBinaries=true; +end if ischar(developMode) && strcmp(developMode,'versionOnly') versionOnly = true; else @@ -129,6 +135,13 @@ catch printOrange('Fail\n') end +fprintf(myStr(' > Store RAVEN path as MATLAB pref',40)) +try + setpref('RAVEN','ravenPath',ravenDir); + fprintf('Pass\n'); +catch + printOrange('Fail\n') +end if isunix fprintf(myStr(' > Make binaries executable',40)) @@ -275,46 +288,50 @@ end fprintf('\n=== Essential binary executables ===\n'); -fprintf(myStr(' > Checking BLAST+',40)) -[~,res]=evalc("runtests('blastPlusTests.m');"); -res=interpretResults(res); -if res==false - fprintf(' This is essential to run getBlast()\n') -end +if ~checkBinaries + printOrange(' Skipping check of binary executables\n') +else + fprintf(myStr(' > Checking BLAST+',40)) + [~,res]=evalc("runtests('blastPlusTests.m');"); + res=interpretResults(res); + if res==false + fprintf(' This is essential to run getBlast()\n') + end -fprintf(myStr(' > Checking DIAMOND',40)) -[~,res]=evalc("runtests('diamondTests.m');"); -res=interpretResults(res); -if res==false - fprintf(' This is essential to run the getDiamond()\n') -end + fprintf(myStr(' > Checking DIAMOND',40)) + [~,res]=evalc("runtests('diamondTests.m');"); + res=interpretResults(res); + if res==false + fprintf(' This is essential to run the getDiamond()\n') + end -fprintf(myStr(' > Checking HMMER',40)) -[~,res]=evalc("runtests('hmmerTests.m')"); -res=interpretResults(res); -if res==false - fprintf([' This is essential to run getKEGGModelFromHomology()\n'... - ' when using a FASTA file as input\n']) -end + fprintf(myStr(' > Checking HMMER',40)) + [~,res]=evalc("runtests('hmmerTests.m')"); + res=interpretResults(res); + if res==false + fprintf([' This is essential to run getKEGGModelFromHomology()\n'... + ' when using a FASTA file as input\n']) + end -if developMode - fprintf('\n=== Development binary executables ===\n'); - fprintf('NOTE: These binaries are only required when using KEGG FTP dump files in getKEGGModelForOrganism\n'); + if developMode + 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)) - [~,res]=evalc("runtests('cdhitTests.m');"); - interpretResults(res); + fprintf(myStr(' > Checking CD-HIT',40)) + [~,res]=evalc("runtests('cdhitTests.m');"); + interpretResults(res); - fprintf(myStr(' > Checking MAFFT',40)) - [~,res]=evalc("runtests('mafftTests.m');"); - interpretResults(res); + fprintf(myStr(' > Checking MAFFT',40)) + [~,res]=evalc("runtests('mafftTests.m');"); + interpretResults(res); + end end fprintf('\n=== Compatibility ===\n'); fprintf(myStr(' > Checking function uniqueness',40)) checkFunctionUniqueness(); -fprintf('\n*** checkInstallation complete ***\n\n'); +fprintf('\n*** checkInstallation complete ***\n'); end function res = interpretResults(results) diff --git a/io/exportModel.m b/io/exportModel.m index 8beef3b2..27c9bb6f 100755 --- a/io/exportModel.m +++ b/io/exportModel.m @@ -245,7 +245,7 @@ function exportModel(model,fileName,neverPrefix,supressWarnings,sortIds) if i']; end - + % Export SBO terms from rxnMiriams if ~isempty(model.rxnMiriams{i}) [~,sbo_ind] = ismember('sbo',model.rxnMiriams{i}.name); @@ -491,7 +491,7 @@ function exportModel(model,fileName,neverPrefix,supressWarnings,sortIds) model.rxnMiriams{i}.value(sbo_ind) = []; end end - + %Export annotation information from rxnMiriams if (~isempty(model.rxnMiriams{i}) && isfield(modelSBML.reaction(i),'annotation')) || ~isempty(model.eccodes{i}) modelSBML.reaction(i).annotation=['']; @@ -504,14 +504,14 @@ function exportModel(model,fileName,neverPrefix,supressWarnings,sortIds) end modelSBML.reaction(i).annotation=[modelSBML.reaction(i).annotation getMiriam(model.rxnMiriams{i}) '']; end - + if isfield(modelSBML.reaction, 'name') modelSBML.reaction(i).name=model.rxnNames{i}; end if isfield(modelSBML.reaction, 'id') modelSBML.reaction(i).id=model.rxns{i}; end - + %Add the information about reactants and products involvedMets=addReactantsProducts(model,modelSBML,i); for j=1:numel(involvedMets.reactant) @@ -553,59 +553,68 @@ function exportModel(model,fileName,neverPrefix,supressWarnings,sortIds) modelSBML.reaction(i).fbc_upperFluxBound=totalNames{length(model.lb)+i}; end -%Prepare subSystems Code taken from COBRA functions getModelSubSystems, -%writeSBML, findRxnsFromSubSystem under GNU General Public License v3.0, -%license file in readme/GPL.MD. Code modified for RAVEN +%Prepare subSystems if modelHasSubsystems modelSBML.groups_group.groups_kind = 'partonomy'; - modelSBML.groups_group.sboTerm = 633; - tmpStruct=modelSBML.groups_group; + modelSBML.groups_group.sboTerm = 633; + grpTemplate = modelSBML.groups_group; - rxns=model.rxns; - if ~any(cellfun(@iscell,model.subSystems)) - if ~any(~cellfun(@isempty,model.subSystems)) - subSystems = {}; - else - subSystems = setdiff(model.subSystems,''); - end + % === 1) Normalize: make every entry a cell array of chars (vectorized) === + isChar = cellfun(@ischar, model.subSystems); + model.subSystems(isChar) = cellfun(@(s){s}, model.subSystems(isChar), 'UniformOutput', false); + model.subSystems(cellfun(@isempty, model.subSystems)) = {{}}; + + % If some entries contain string scalars by mistake, coerce them: + model.subSystems = cellfun(@(c) cellfun(@char, c, 'UniformOutput', false), model.subSystems, 'UniformOutput', false); + + % === 2) Flatten once: names and their reaction indices (vectorized) === + flatNames = vertcat(model.subSystems{:}); % 1×M cellstr of all subsystem labels + if isempty(flatNames) + % Nothing to do: no subsystems present + return + end + + counts = cellfun(@numel, model.subSystems); % reactions -> how many subsystems + % For each reaction r, repeat r exactly counts(r) times + flatIdx = arrayfun(@(r,c) repmat(r, c, 1), (1:numel(model.subSystems)).', counts, 'UniformOutput', false); + flatIdx = vertcat(flatIdx{:}); % M×1 vector of reaction indices + + % === 3) Group in one shot: unique subsystems + members per subsystem === + [subSystems, ~, g] = unique(flatNames, 'stable'); % stable preserves first appearance + membersIdx = accumarray(g, flatIdx, [], @(v){v}); % cell: one vector of r-idx per group + nSubs = numel(subSystems); + + % === 4) Preallocate and build SBML groups (single simple loop) === + modelSBML.groups_group(1:nSubs) = grpTemplate; + groupIDs = "group" + (1:nSubs); + + if isfield(grpTemplate,'groups_member') + memTemplate = grpTemplate.groups_member; else - orderedSubs = cellfun(@(x) columnVector(x),model.subSystems,'UniformOUtput',false); - subSystems = setdiff(vertcat(orderedSubs{:}),''); - end - if isempty(subSystems) - subSystems = {}; - end - if ~isempty(subSystems) - %Build the groups for the group package - groupIDs = strcat('group',cellfun(@num2str, num2cell(1:length(subSystems)),'UniformOutput',false)); - for i = 1:length(subSystems) - cgroup = tmpStruct; - if ~any(cellfun(@iscell,model.subSystems)) - present = ismember(model.subSystems,subSystems{i}); - else - present = cellfun(@(x) any(ismember(x,subSystems{i})),model.subSystems); - end - groupMembers = rxns(present); - for j = 1:numel(groupMembers) - cMember = tmpStruct.groups_member; - cMember.groups_idRef = groupMembers{j}; - if j == 1 - cgroup.groups_member = cMember; - else - cgroup.groups_member(j) = cMember; - end - end - cgroup.groups_id = groupIDs{i}; - cgroup.groups_name = subSystems{i}; - if i == 1 - modelSBML.groups_group = cgroup; - else - modelSBML.groups_group(i) = cgroup; - end + memTemplate = struct('groups_idRef',''); + end + + for i = 1:nSubs + rIdx = membersIdx{i}; + groupRXNs = model.rxns(rIdx); + cgroup = grpTemplate; + + % Preallocate and fill members + nM = numel(groupRXNs); + if nM > 0 + cgroup.groups_member(1:nM) = memTemplate; + [cgroup.groups_member.groups_idRef] = deal(groupRXNs{:}); + else + cgroup.groups_member = repmat(memTemplate, 0, 1); end + + cgroup.groups_id = char(groupIDs(i)); % keep as char for SBML compatibility + cgroup.groups_name = subSystems{i}; + modelSBML.groups_group(i) = cgroup; end end + %Prepare fbc_objective subfield modelSBML.fbc_objective.fbc_type='maximize'; @@ -635,12 +644,12 @@ function exportModel(model,fileName,neverPrefix,supressWarnings,sortIds) if modelHasSubsystems groupStr=['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/groups/version',num2str(sbmlPackageVersions(2))]; modelSBML.namespaces=struct('prefix',{'','fbc','groups'},... - 'uri',{['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/core'],... - fbcStr,groupStr}); + 'uri',{['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/core'],... + fbcStr,groupStr}); else modelSBML.namespaces=struct('prefix',{'','fbc'},... - 'uri',{['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/core'],... - fbcStr}); + 'uri',{['http://www.sbml.org/sbml/level', num2str(sbmlLevel), '/version', num2str(sbmlVersion), '/core'],... + fbcStr}); end if sbmlPackageVersions(1) == 2 diff --git a/io/exportToExcelFormat.m b/io/exportToExcelFormat.m index 7274c387..9337e76e 100755 --- a/io/exportToExcelFormat.m +++ b/io/exportToExcelFormat.m @@ -185,6 +185,9 @@ function exportToExcelFormat(model,fileName,sortIds) subsystems=''; if isfield(model,'subSystems') for i=1:numel(model.subSystems) + if ~iscell(model.subSystems{i}) + model.subSystems{i} = {model.subSystems{i}}; + end if ~isempty(model.subSystems{i,1}) subsystems{i,1}=strjoin(model.subSystems{i,1},';'); else diff --git a/io/exportToTabDelimited.m b/io/exportToTabDelimited.m index 8a773407..98ad6bb7 100755 --- a/io/exportToTabDelimited.m +++ b/io/exportToTabDelimited.m @@ -106,6 +106,9 @@ function exportToTabDelimited(model,path,sortIds) if isfield(model,'subSystems') if ~isempty(model.subSystems{i}) + if ~iscell(model.subSystems{i}) + model.subSystems{i} = {model.subSystems{i}}; + end fprintf(rxnFile,[strjoin(model.subSystems{i,1},';') '\t']); else fprintf(rxnFile,'\t'); diff --git a/io/importModel.m b/io/importModel.m index 68bfe6fc..dae96063 100755 --- a/io/importModel.m +++ b/io/importModel.m @@ -992,6 +992,10 @@ model=rmfield(model,'subSystems'); else model.subSystems(cellfun(@isempty,subsystems))={{''}}; + % If all subSystems have single entries, then unnest them + if all(cellfun(@(x) iscell(x) && isscalar(x), model.subSystems)) + model.subSystems = transpose([model.subSystems{:}]); + end end if isempty(model.eccodes) model=rmfield(model,'eccodes'); diff --git a/io/readYAMLmodel.m b/io/readYAMLmodel.m index bc93d78c..1eb65f3b 100755 --- a/io/readYAMLmodel.m +++ b/io/readYAMLmodel.m @@ -592,15 +592,24 @@ % end % end +if isfield(model,'subSystems') +% If all entries are 1x1, then flatten + if all(cellfun(@(x) numel(x) <= 1, model.subSystems)) + model.subSystems = transpose([model.subSystems{:}]); + end +end + % Make rxnGeneMat fields and map to the existing model.genes field -[genes, rxnGeneMat] = getGenesFromGrRules(model.grRules); -model.rxnGeneMat = sparse(numel(model.rxns),numel(model.genes)); -[~,geneOrder] = ismember(genes,model.genes); -if any(geneOrder == 0) - error(['The grRules includes the following gene(s), that are not in '... - 'the list of model genes: ', genes{~geneOrder}]) -end -model.rxnGeneMat(:,geneOrder) = rxnGeneMat; +if isfield(model,'grRules') + [genes, rxnGeneMat] = getGenesFromGrRules(model.grRules); + model.rxnGeneMat = sparse(numel(model.rxns),numel(model.genes)); + [~,geneOrder] = ismember(genes,model.genes); + if any(geneOrder == 0) + error(['The grRules includes the following gene(s), that are not in '... + 'the list of model genes: ', genes{~geneOrder}]) + end + model.rxnGeneMat(:,geneOrder) = rxnGeneMat; +end % Finalize GECKO model if isGECKO diff --git a/io/writeYAMLmodel.m b/io/writeYAMLmodel.m index 2042c5e3..2ada7074 100755 --- a/io/writeYAMLmodel.m +++ b/io/writeYAMLmodel.m @@ -111,13 +111,15 @@ function writeYAMLmodel(model,fileName,preserveQuotes,sortIds) end %Genes: -fprintf(fid,'- genes:\n'); -for i = 1:length(model.genes) - fprintf(fid,' - !!omap\n'); - writeField(model, fid, 'genes', 'txt', i, ' - id', preserveQuotes) - writeField(model, fid, 'geneShortNames', 'txt', i, ' - name', preserveQuotes) - writeField(model, fid, 'proteins', 'txt', i, ' - protein', preserveQuotes) - writeField(model, fid, 'geneMiriams', 'txt', i, ' - annotation', preserveQuotes) +if isfield(model,'genes') + fprintf(fid,'- genes:\n'); + for i = 1:length(model.genes) + fprintf(fid,' - !!omap\n'); + writeField(model, fid, 'genes', 'txt', i, ' - id', preserveQuotes) + writeField(model, fid, 'geneShortNames', 'txt', i, ' - name', preserveQuotes) + writeField(model, fid, 'proteins', 'txt', i, ' - protein', preserveQuotes) + writeField(model, fid, 'geneMiriams', 'txt', i, ' - annotation', preserveQuotes) + end end %Compartments: diff --git a/software/blast+/blastp b/software/blast+/blastp index 807f90c2..5b2e6e8e 100755 Binary files a/software/blast+/blastp and b/software/blast+/blastp differ diff --git a/software/blast+/blastp.exe b/software/blast+/blastp.exe index 3927fb36..fadea7fd 100644 Binary files a/software/blast+/blastp.exe and b/software/blast+/blastp.exe differ diff --git a/software/blast+/blastp.mac b/software/blast+/blastp.mac index c94f53aa..9f1e81cc 100755 Binary files a/software/blast+/blastp.mac and b/software/blast+/blastp.mac differ diff --git a/software/blast+/makeblastdb b/software/blast+/makeblastdb index d191a43d..a4e4d9fd 100755 Binary files a/software/blast+/makeblastdb and b/software/blast+/makeblastdb differ diff --git a/software/blast+/makeblastdb.exe b/software/blast+/makeblastdb.exe index 331a2bfb..7866a977 100644 Binary files a/software/blast+/makeblastdb.exe and b/software/blast+/makeblastdb.exe differ diff --git a/software/blast+/makeblastdb.mac b/software/blast+/makeblastdb.mac index 578acabf..c632a8ef 100755 Binary files a/software/blast+/makeblastdb.mac and b/software/blast+/makeblastdb.mac differ diff --git a/software/blast+/nghttp2.dll b/software/blast+/nghttp2.dll index 850efeb8..cb71384f 100644 Binary files a/software/blast+/nghttp2.dll and b/software/blast+/nghttp2.dll differ diff --git a/software/diamond/diamond b/software/diamond/diamond index 546b8e06..db7effdb 100755 Binary files a/software/diamond/diamond and b/software/diamond/diamond differ diff --git a/software/diamond/diamond.exe b/software/diamond/diamond.exe index ad36d58b..df530e04 100644 Binary files a/software/diamond/diamond.exe and b/software/diamond/diamond.exe differ diff --git a/software/diamond/diamond.mac b/software/diamond/diamond.mac index b5e1c833..508d0fd9 100755 Binary files a/software/diamond/diamond.mac and b/software/diamond/diamond.mac differ diff --git a/software/hmmer/cygwin1.dll b/software/hmmer/cygwin1.dll deleted file mode 100644 index 350a74ba..00000000 Binary files a/software/hmmer/cygwin1.dll and /dev/null differ diff --git a/software/hmmer/hmmbuild b/software/hmmer/hmmbuild index a6f81a95..e759997c 100755 Binary files a/software/hmmer/hmmbuild and b/software/hmmer/hmmbuild differ diff --git a/software/hmmer/hmmbuild.exe b/software/hmmer/hmmbuild.exe deleted file mode 100644 index 950a8394..00000000 Binary files a/software/hmmer/hmmbuild.exe and /dev/null differ diff --git a/software/hmmer/hmmbuild.mac b/software/hmmer/hmmbuild.mac index 1f457757..57fe27e7 100755 Binary files a/software/hmmer/hmmbuild.mac and b/software/hmmer/hmmbuild.mac differ diff --git a/software/hmmer/hmmsearch b/software/hmmer/hmmsearch index ab090fdc..34bc2aca 100755 Binary files a/software/hmmer/hmmsearch and b/software/hmmer/hmmsearch differ diff --git a/software/hmmer/hmmsearch.exe b/software/hmmer/hmmsearch.exe deleted file mode 100644 index 66856d57..00000000 Binary files a/software/hmmer/hmmsearch.exe and /dev/null differ diff --git a/software/hmmer/hmmsearch.mac b/software/hmmer/hmmsearch.mac index 0f393cfd..342f6d26 100755 Binary files a/software/hmmer/hmmsearch.mac and b/software/hmmer/hmmsearch.mac differ diff --git a/software/m2html/private/m2htmltoolbarimages.mat b/software/m2html/private/m2htmltoolbarimages.mat index 2fd358ee..19e9f16b 100644 Binary files a/software/m2html/private/m2htmltoolbarimages.mat and b/software/m2html/private/m2htmltoolbarimages.mat differ diff --git a/software/mafft/mafft-linux64/mafftdir/bin/mafft b/software/mafft/mafft-linux64/mafftdir/bin/mafft index cc0af8e6..defcc4e9 100755 --- a/software/mafft/mafft-linux64/mafftdir/bin/mafft +++ b/software/mafft/mafft-linux64/mafftdir/bin/mafft @@ -1,7 +1,7 @@ #! /bin/bash er=0; myself=`dirname "$0"`/`basename "$0"`; export myself -version="v7.490 (2021/Oct/30)"; export version +version="v7.526 (2024/Apr/26)"; export version LANG=C; export LANG os=`uname` progname=`basename "$0"` @@ -175,6 +175,7 @@ elif [ $progname = "nwnsi" -o $progname = "mafft-nwnsi" ]; then fi outputfile="" namelength=-1 +linelength=60 # Will change to -1 in the future anysymbol=0 parallelizationstrategy="BAATARI2" kappa=$defaultkappa @@ -216,7 +217,9 @@ contrafold=$defaultcontrafold progressfile="/dev/stderr" anchorfile="/dev/null" anchoropt="" -maxanchorseparation=1000 +#maxanchorseparation=1000 +#maxanchorseparation=-1 # 2023/Jan/11 +terminalmargin=100 # 2024/Mar debug=0 sw=0 algopt=$defaultalgopt @@ -241,6 +244,7 @@ partorderopt=" -x " treeout=0 nodeout=0 distout=0 +distformat="hat2" treein=0 topin=0 treeinopt=" " @@ -252,12 +256,15 @@ strdir="$PWD" scorematrix="/dev/null" textmatrix="/dev/null" treeinfile="/dev/null" +codonposfile="/dev/null" +codonscorefile="/dev/null" rnascoremtx=" " laraparams="/dev/null" foldalignopt=" " treealg=" -X 0.1 " sueff="1.0" maxambiguous="1.0" +dofilter=0 scoreoutarg=" " numthreads=0 numthreadsit=-1 @@ -352,6 +359,13 @@ if [ $# -gt 0 ]; then echo "" 1>&2 exit 1; # algspecified=1 + elif [ "$1" = "--linelength" ]; then + shift + linelength=`expr "$1" - 0` + if [ $linelength -eq 0 ]; then + echo "Line length = 0 ?" 1>&2 + exit + fi elif [ "$1" = "--namelength" ]; then shift namelength=`expr "$1" - 0` @@ -389,6 +403,10 @@ if [ $# -gt 0 ]; then treeout=1 elif [ "$1" = "--distout" ]; then distout=1 + distformat="hat2" + elif [ "$1" = "--distoutclustalo" ]; then + distout=1 + distformat="clodist" elif [ "$1" = "--fastswpair" ]; then distance="fasta" pairspecified=1 @@ -410,6 +428,25 @@ if [ $# -gt 0 ]; then elif [ "$1" = "--maxambiguous" ]; then shift maxambiguous="$1" + dofilter=1 + elif [ "$1" = "--codonpos" ]; then + shift + codonposfile="$1" + if [ ! -e "$codonposfile" ]; then + echo "Cannot open $codonposfile" 1>&2 + echo "" 1>&2 + exit + fi + codonposopt=" -R " + elif [ "$1" = "--codonscore" ]; then + shift + codonscorefile="$1" + if [ ! -e "$codonscorefile" ]; then + echo "Cannot open $codonscorefile" 1>&2 + echo "" 1>&2 + exit + fi + codonscoreopt=" -S " elif [ "$1" = "--noscore" ]; then scorecalcopt=" -Z " elif [ "$1" = "--6mermultipair" ]; then @@ -544,13 +581,13 @@ if [ $# -gt 0 ]; then elif [ "$1" = "--out" ]; then shift outputfile="$1" - elif [ "$1" = "--skipanchorsremoterthan" ]; then + elif [ "$1" = "--terminalmargin" ]; then shift if ! expr "$1" : "[0-9]" > /dev/null ; then - echo "Specify maximum gap length between anchors." 1>&2 + echo "set --terminalmargin (int)." 1>&2 exit fi - maxanchorseparation=`expr "$1" - 0` + terminalmargin=`expr "$1" - 0` elif [ "$1" = "--anchors" ]; then shift anchorfile="$1" @@ -645,10 +682,26 @@ if [ $# -gt 0 ]; then addarg0="-K -I" addfile="$1" fragment=-2 + elif [ "$1" = "--addtotop" ]; then + shift + addarg0="-K -I" + addfile="$1" + fragment=-3 + elif [ "$1" = "--addtoroot" ]; then + shift + addarg0="-K -I" + addfile="$1" + fragment=-4 elif [ "$1" = "--smoothing" ]; then add2ndhalfarg=$add2ndhalfarg" -p " elif [ "$1" = "--keeplength" ]; then add2ndhalfarg=$add2ndhalfarg" -Y " + elif [ "$1" = "--compactmapout" ]; then + add2ndhalfarg=$add2ndhalfarg" -z -Y " + elif [ "$1" = "--compactmapoutfile" ]; then + shift + add2ndhalfarg=$add2ndhalfarg" -z -Y " + mapoutfile="$1" elif [ "$1" = "--mapout" ]; then add2ndhalfarg=$add2ndhalfarg" -Z -Y " elif [ "$1" = "--mapoutfile" ]; then @@ -684,7 +737,8 @@ if [ $# -gt 0 ]; then f2clext="-E" seqtype="-P" fft=0 - sbstmodel=" -b -2 -a " +# sbstmodel=" -b -2 -a " + sbstmodel=" -b -2 " # 2022/Jul, hauretsu no kawari ni scoremtx wo miru scorematrix="$1" if [ ! -e "$scorematrix" ]; then echo "Cannot open $scorematrix" 1>&2 @@ -1079,9 +1133,9 @@ function removetmpfile() { # for MPI echo "" >> "$TMPFILE/infile" cat "$addfile" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_addfile" - if [ $maxambiguous != "1.0" ]; then - mv "$TMPFILE/infile" "$TMPFILE/_tofilter" - "$prefix/filter" -m $maxambiguous $seqtype -i "$TMPFILE/_tofilter" > "$TMPFILE/infile" 2>>"$progressfile" || exit 1 + if [ $dofilter -eq 1 ]; then +# mv "$TMPFILE/infile" "$TMPFILE/_tofilter" +# "$prefix/filter" -m $maxambiguous $seqtype -i "$TMPFILE/_tofilter" > "$TMPFILE/infile" 2>>"$progressfile" || exit 1 mv "$TMPFILE/_addfile" "$TMPFILE/_tofilter" "$prefix/filter" -m $maxambiguous $seqtype -i "$TMPFILE/_tofilter" > "$TMPFILE/_addfile" 2>>"$progressfile" || exit 1 fi @@ -1090,6 +1144,8 @@ function removetmpfile() { # for MPI cat "$scorematrix" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_aamtx" cat "$mergetable" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_subalignmentstable" cat "$treeinfile" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_guidetree" + cat "$codonposfile" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_codonpos" + cat "$codonscorefile" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_codonscore" cat "$seedtablefile" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_seedtablefile" cat "$laraparams" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_lara.params" cat "$pdblist" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/pdblist" @@ -1104,6 +1160,8 @@ $addfile $scorematrix $mergetable $treeinfile +$codonposfile +$codonscorefile $seedtablefile $laraparams $pdblist @@ -1335,10 +1393,11 @@ $ownlist" exit 1; fi # nagasa check! -# - if [ $npair -gt 10000000 -o $nlen -gt 5000 ]; then # 2017/Oct +# if [ $npair -gt 10000000 -o $nlen -gt 5000 ]; then # 2017/Oct + if [ $npair -gt 10000000 -o $nlen -gt 5000 -o $nadd -gt 500000 ]; then # 2021/Dec pairlocalalign to buntan distance="ktuples" echo "use ktuples, size=$tuplesize!" 1>>"$progressfile" +# elif [ $npair -gt 3000000 -o $nlen -gt 5000 ]; then # 2017/Oct elif [ $npair -gt 3000000 -o $nlen -gt 5000 ]; then # 2017/Oct distance="multi" weighti="0.0" @@ -1739,7 +1798,7 @@ $ownlist" parttreeoutopt=" " fi if [ $distout -eq 1 ]; then - distoutopt="-y -T" + distoutopt="-y ${distformat} -T" if [ $treeout -eq 0 ]; then treeoutopt="" fi @@ -1760,7 +1819,7 @@ $ownlist" treeoutopt=" " fi if [ $distout -eq 1 ]; then - distoutopt="-y" + distoutopt="-y ${distformat}" fi fi # @@ -2000,6 +2059,16 @@ $ownlist" laof=0.0 # 2015Jun01 lexp=0.0 # 2015Jun01 iterate=0 + elif [ $fragment -eq "-3" ]; then + addarg="$addarg0 $nadd" + addsinglearg="-x" # add to top, 2021/12/31 + cycle=1 # chuui 2014Aug25 + iterate=0 + elif [ $fragment -eq "-4" ]; then + addarg="$addarg0 $nadd" + addsinglearg="-s" # add to root, 2023/2/11 + cycle=1 # chuui 2014Aug25 + iterate=0 else addarg="$addarg0 $nadd" addsinglearg="" @@ -2032,6 +2101,21 @@ $ownlist" fi fi + if [ "$codonposfile" != "/dev/null" -o "$codonscorefile" != "/dev/null" ]; then + if [ $nadd -eq "0" -o $fragment -eq "0" ]; then + echo '' 1>>"$progressfile" + echo "'--codonpos' and '--codonscore' options are supported only with the '--6merpair --addfragments' option." 1>>"$progressfile" + echo '' 1>>"$progressfile" + exit 1 + fi + if [ $distance != "ktuples" ]; then # ato de taiou + echo '' 1>>"$progressfile" + echo "'--codonpos' and '--codonscore' options are supported only with the '--6merpair --addfragments' option, at this point." 1>>"$progressfile" + echo '' 1>>"$progressfile" + exit 1 + fi + fi + if [ -z "$localparam" -a $fragment -eq 0 -a $distance != "parttree" ]; then # echo "use disttbfast" @@ -2143,6 +2227,8 @@ $ownlist" strategy=$strategy"full" elif [ $fragment -eq -2 ]; then strategy=$strategy"long" + elif [ $fragment -eq -3 ]; then + strategy=$strategy"top" else strategy=$strategy$cycle fi @@ -2194,9 +2280,9 @@ $ownlist" elif [ $outputformat = "phylip" -a $outorder = "input" ]; then outputopt=" -y " elif [ $outputformat = "pir" -a $outorder = "aligned" ]; then - outputopt=" -f -r $TMPFILE/order " + outputopt=" -f -l $linelength -r $TMPFILE/order " else - outputopt="-f" + outputopt="-f -l $linelength" fi if [ $newdash_originalsequenceonly -eq 1 ]; then @@ -2502,7 +2588,7 @@ $ownlist" "$prefix/pairlocalalign" $localparam $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -Q $spfactor -h $laof -L $usenaivepairscore < infile > /dev/null 2>>"$progressfile" || exit 1 cat hat3.seed hat3 > hatx mv hatx hat3 - "$prefix/addsingle" -Q 100 $legacygapopt -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/addsingle" $codonposopt $codonscoreopt -Q 100 $legacygapopt -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 else "$prefix/tbfast" _ -u $unalignlevel $localparam -C $numthreads $seqtype $model -g $lexp -f $lgop -Q $spfactor -h $laof -L $usenaivepairscore $focusarg _ -+ $iterate -W $minimumweight -V "-"$gopdist -s $unalignlevel $legacygapopt $mergearg $termgapopt $outnum $addarg $add2ndhalfarg -C $numthreadstb $rnaopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -Q $spfactor -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg $focusarg < infile > /dev/null 2>>"$progressfile" || exit 1 fi @@ -2518,7 +2604,7 @@ $ownlist" "$prefix/pairlocalalign" $addarg -C $numthreads $seqtype $model -e $last_e -w $last_m -g $lexp -f $lgop -Q $spfactor -h $laof -R $last_subopt $last_once -d "$prefix" < infile > /dev/null 2>>"$progressfile" || exit 1 cat hat3.seed hat3 > hatx mv hatx hat3 - "$prefix/addsingle" -Q 100 $legacygapopt -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/addsingle" $codonposopt $codonscoreopt -Q 100 $legacygapopt -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 else "$prefix/pairlocalalign" -C $numthreads $seqtype $model -e $last_e -w $last_m -g $lexp -f $lgop -Q $spfactor -h $laof -R $last_subopt $last_once -d "$prefix" < infile > /dev/null 2>>"$progressfile" || exit 1 # addarg wo watasanai @@ -2527,27 +2613,27 @@ $ownlist" "$prefix/tbfast" -W $minimumweight -V "-"$gopdist -s $unalignlevel $legacygapopt $mergearg $termgapopt $outnum $addarg $add2ndhalfarg -C $numthreadstb $rnaopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -Q $spfactor -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 fi elif [ $distance = "lastmulti" ]; then - "$prefix/dndpre" $model -M 2 $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -Q $spfactor -h $laof < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/dndpre" -y $distformat $model -M 2 $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -Q $spfactor -h $laof < infile > /dev/null 2>>"$progressfile" || exit 1 mv hat2 hat2i "$prefix/pairlocalalign" $addarg -C $numthreads $seqtype $model -e $last_e -w $last_m -g $lexp -f $lgop -Q $spfactor -h $laof -r $last_subopt $last_once -d "$prefix" < infile > /dev/null 2>>"$progressfile" || exit 1 cat hat3.seed hat3 > hatx mv hat2 hat2n mv hatx hat3 if [ $fragment -ne 0 ]; then - "$prefix/addsingle" -Q 100 $legacygapopt -d -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/addsingle" $codonposopt $codonscoreopt -Q 100 $legacygapopt -d -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 else echo "Impossible" 1>&2 exit 1 fi elif [ $distance = "multi" ]; then - "$prefix/dndpre" $model -M 2 $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -h $laof $usenaivepairscore < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/dndpre" -y $distformat $model -M 2 $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -h $laof $usenaivepairscore < infile > /dev/null 2>>"$progressfile" || exit 1 mv hat2 hat2i "$prefix/pairlocalalign" $localparam $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -Q $spfactor -h $laof -Y $usenaivepairscore < infile > /dev/null 2>>"$progressfile" || exit 1 cat hat3.seed hat3 > hatx mv hat2 hat2n mv hatx hat3 if [ $fragment -ne 0 ]; then - "$prefix/addsingle" -Q 100 $legacygapopt -d -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/addsingle" $codonposopt $codonscoreopt -Q 100 $legacygapopt -d -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 else echo "Impossible" 1>&2 exit 1 @@ -2558,7 +2644,7 @@ $ownlist" mv hatx hat3 "$prefix/disttbfast" -E 1 -s $unalignlevel $legacygapopt -W $tuplesize $termgapopt $outnum $addarg $add2ndhalfarg -C $numthreads-$numthreadstb $memopt $weightopt $treeinopt $treeoutopt -T -y $seqtype $model -f "-"$gop -Q $spfactor -h $aof $param_fft $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 if [ $fragment -ne 0 ]; then - "$prefix/addsingle" -Q 100 $legacygapopt -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/addsingle" $codonposopt $codonscoreopt -Q 100 $legacygapopt -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 else "$prefix/tbfast" -W $minimumweight -V "-"$gopdist -s $unalignlevel $legacygapopt $mergearg $termgapopt $outnum $addarg $add2ndhalfarg -C $numthreadstb $rnaopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -Q $spfactor -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 fi @@ -2569,22 +2655,22 @@ $ownlist" "$prefix/splittbfast" $legacygapopt $algopt $splitopt $partorderopt $parttreeoutopt $memopt $seqtype $model -f "-"$gop -Q $spfactor -h $aof -p $partsize -s $groupsize $treealg $outnum -i infile > pre 2>>"$progressfile" || exit 1 mv hat3.seed hat3 elif [ $distance = "ktuplesmulti" ]; then -# "$prefix/dndpre" $model -M 1 $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -h $laof < infile > /dev/null 2>>"$progressfile" || exit 1 +# "$prefix/dndpre" -y $distformat $model -M 1 $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -h $laof < infile > /dev/null 2>>"$progressfile" || exit 1 # mv hat2 hat2i # "$prefix/disttbfast" -E 1 -s $unalignlevel $legacygapopt -W $tuplesize $termgapopt $outnum $addarg $add2ndhalfarg -C $numthreads-$numthreadstb $memopt $weightopt $treeinopt $treeoutopt -T -y $seqtype $model -f "-"$gop -Q $spfactor -h $aof $param_fft $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 # mv hat2 hat2n if [ $fragment -ne 0 ]; then - "$prefix/addsingle" -Q 100 $legacygapopt -d -W $tuplesize -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 -# "$prefix/addsingle" -Q 100 $legacygapopt -d -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/addsingle" $codonposopt $codonscoreopt -Q 100 $legacygapopt -d -W $tuplesize -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 +# "$prefix/addsingle" -Q 100 $legacygapopt -d -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 else echo "Impossible" 1>&2 exit 1 fi else if [ $fragment -ne 0 ]; then - "$prefix/addsingle" -Q 100 $legacygapopt -W $tuplesize -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/addsingle" $codonposopt $codonscoreopt -Q 100 $legacygapopt -W $tuplesize -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 else - "$prefix/disttbfast" -q $npickup -E $cycledisttbfast -V "-"$gopdist -s $unalignlevel $legacygapopt $mergearg -W $tuplesize $termgapopt $outnum $addarg $add2ndhalfarg -C $numthreads-$numthreadstb $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -g $gexp -f "-"$gop -Q $spfactor -h $aof $param_fft $algopt $treealg $scoreoutarg $anchoropt -x $maxanchorseparation $oneiterationopt < infile > pre 2>>"$progressfile" || exit 1 + "$prefix/disttbfast" -q $npickup -E $cycledisttbfast -V "-"$gopdist -s $unalignlevel $legacygapopt $mergearg -W $tuplesize $termgapopt $outnum $addarg $add2ndhalfarg -C $numthreads-$numthreadstb $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -g $gexp -f "-"$gop -Q $spfactor -h $aof $param_fft $algopt $treealg $scoreoutarg $anchoropt -x $terminalmargin $oneiterationopt < infile > pre 2>>"$progressfile" || exit 1 mv hat3.seed hat3 fi fi @@ -2602,7 +2688,7 @@ $ownlist" done if [ $iterate -gt 0 ]; then if [ $distance = "ktuples" ]; then - "$prefix/dndpre" $seqtype $model -M 2 -C $numthreads < pre > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/dndpre" -y $distformat $seqtype $model -M 2 -C $numthreads < pre > /dev/null 2>>"$progressfile" || exit 1 fi "$prefix/dvtditr" -W $minimumweight $bunkatsuopt -E $fixthreshold -s $unalignlevel $legacygapopt $mergearg $outnum -C $numthreadsit -t $randomseed $rnaoptit $memopt $scorecalcopt $localparam -z 50 $seqtype $model -f "-"$gop -Q $spfactor -h $aof -I $iterate $weightopt $treeinopt $algoptit $treealg -p $parallelizationstrategy $scoreoutarg -K $nadd < pre > /dev/null 2>>"$progressfile" || exit 1 fi @@ -2711,7 +2797,7 @@ $ownlist" popd > /dev/null - if [ "$outputopt" != "-f" -o "$windows" = "yes" ]; then # Windows deha kaigyo code wo f2cl de modosu. + if [ "$outputopt" != "-f -l -1" -o "$windows" = "yes" ]; then # Windows deha kaigyo code wo f2cl de modosu. # ln -s "$TMPFILE/order" _order$$ # f2cl ga space ari filename ni taiou shiteinainode # cp "$TMPFILE/order" _order$$ # ln -s no error wo sakeru if [ "$outputfile" = "" ]; then @@ -2737,7 +2823,7 @@ $ownlist" fi if [ $distout -eq 1 ]; then - cp "$TMPFILE/hat2" "$infilename.hat2" + cp "$TMPFILE/${distformat}" "$infilename.${distformat}" fi if [ $npickup -ne 0 ]; then diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/addsingle b/software/mafft/mafft-linux64/mafftdir/libexec/addsingle index 11a61d6d..5aa4e300 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/addsingle and b/software/mafft/mafft-linux64/mafftdir/libexec/addsingle differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/contrafoldwrap b/software/mafft/mafft-linux64/mafftdir/libexec/contrafoldwrap index 0e1beac9..b67965f0 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/contrafoldwrap and b/software/mafft/mafft-linux64/mafftdir/libexec/contrafoldwrap differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/countlen b/software/mafft/mafft-linux64/mafftdir/libexec/countlen index 0efbbab1..829d67b5 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/countlen and b/software/mafft/mafft-linux64/mafftdir/libexec/countlen differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/disttbfast b/software/mafft/mafft-linux64/mafftdir/libexec/disttbfast index 4d950cf7..0a0699dd 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/disttbfast and b/software/mafft/mafft-linux64/mafftdir/libexec/disttbfast differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/dndblast b/software/mafft/mafft-linux64/mafftdir/libexec/dndblast index b4b112d0..636ea9fb 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/dndblast and b/software/mafft/mafft-linux64/mafftdir/libexec/dndblast differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/dndfast7 b/software/mafft/mafft-linux64/mafftdir/libexec/dndfast7 index 0ee51697..3a064967 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/dndfast7 and b/software/mafft/mafft-linux64/mafftdir/libexec/dndfast7 differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/dndpre b/software/mafft/mafft-linux64/mafftdir/libexec/dndpre index 4b27abed..49c249e1 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/dndpre and b/software/mafft/mafft-linux64/mafftdir/libexec/dndpre differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/dvtditr b/software/mafft/mafft-linux64/mafftdir/libexec/dvtditr index 115b2ec7..ebb46dd7 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/dvtditr and b/software/mafft/mafft-linux64/mafftdir/libexec/dvtditr differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/f2cl b/software/mafft/mafft-linux64/mafftdir/libexec/f2cl index d740559a..fd685023 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/f2cl and b/software/mafft/mafft-linux64/mafftdir/libexec/f2cl differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/filter b/software/mafft/mafft-linux64/mafftdir/libexec/filter index f0ad2ead..35d6e241 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/filter and b/software/mafft/mafft-linux64/mafftdir/libexec/filter differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/getlag b/software/mafft/mafft-linux64/mafftdir/libexec/getlag index 7c4ea918..6c57fff0 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/getlag and b/software/mafft/mafft-linux64/mafftdir/libexec/getlag differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/mafft-distance b/software/mafft/mafft-linux64/mafftdir/libexec/mafft-distance index be7f77a2..cd02da5b 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/mafft-distance and b/software/mafft/mafft-linux64/mafftdir/libexec/mafft-distance differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/mafft-profile b/software/mafft/mafft-linux64/mafftdir/libexec/mafft-profile index 73936551..f4bf0db1 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/mafft-profile and b/software/mafft/mafft-linux64/mafftdir/libexec/mafft-profile differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/makedirectionlist b/software/mafft/mafft-linux64/mafftdir/libexec/makedirectionlist index 89f3ccb3..1f1cae6f 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/makedirectionlist and b/software/mafft/mafft-linux64/mafftdir/libexec/makedirectionlist differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/mccaskillwrap b/software/mafft/mafft-linux64/mafftdir/libexec/mccaskillwrap index 85bd1665..7e8d4613 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/mccaskillwrap and b/software/mafft/mafft-linux64/mafftdir/libexec/mccaskillwrap differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/multi2hat3s b/software/mafft/mafft-linux64/mafftdir/libexec/multi2hat3s index 4b06fcf4..a7154fef 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/multi2hat3s and b/software/mafft/mafft-linux64/mafftdir/libexec/multi2hat3s differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/nodepair b/software/mafft/mafft-linux64/mafftdir/libexec/nodepair index 581fefea..fba0428c 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/nodepair and b/software/mafft/mafft-linux64/mafftdir/libexec/nodepair differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/pairash b/software/mafft/mafft-linux64/mafftdir/libexec/pairash index 307a0534..ed40c2fc 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/pairash and b/software/mafft/mafft-linux64/mafftdir/libexec/pairash differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/pairlocalalign b/software/mafft/mafft-linux64/mafftdir/libexec/pairlocalalign index 475cba76..6858df36 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/pairlocalalign and b/software/mafft/mafft-linux64/mafftdir/libexec/pairlocalalign differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/regtable2seq b/software/mafft/mafft-linux64/mafftdir/libexec/regtable2seq index 45e90d17..9c364cf4 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/regtable2seq and b/software/mafft/mafft-linux64/mafftdir/libexec/regtable2seq differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/replaceu b/software/mafft/mafft-linux64/mafftdir/libexec/replaceu index fcd6ab7e..97a933eb 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/replaceu and b/software/mafft/mafft-linux64/mafftdir/libexec/replaceu differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/restoreu b/software/mafft/mafft-linux64/mafftdir/libexec/restoreu index ff6bbb5f..6144e53a 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/restoreu and b/software/mafft/mafft-linux64/mafftdir/libexec/restoreu differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/score b/software/mafft/mafft-linux64/mafftdir/libexec/score index c815992f..1f270504 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/score and b/software/mafft/mafft-linux64/mafftdir/libexec/score differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/seq2regtable b/software/mafft/mafft-linux64/mafftdir/libexec/seq2regtable index 4b2b440e..990929e1 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/seq2regtable and b/software/mafft/mafft-linux64/mafftdir/libexec/seq2regtable differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/setcore b/software/mafft/mafft-linux64/mafftdir/libexec/setcore index 30472e54..4c886d20 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/setcore and b/software/mafft/mafft-linux64/mafftdir/libexec/setcore differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/setdirection b/software/mafft/mafft-linux64/mafftdir/libexec/setdirection index 95b15080..b9981ff0 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/setdirection and b/software/mafft/mafft-linux64/mafftdir/libexec/setdirection differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/sextet5 b/software/mafft/mafft-linux64/mafftdir/libexec/sextet5 index 0df7bbc5..e9fc9242 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/sextet5 and b/software/mafft/mafft-linux64/mafftdir/libexec/sextet5 differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/splittbfast b/software/mafft/mafft-linux64/mafftdir/libexec/splittbfast index c35e2881..f49ea46e 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/splittbfast and b/software/mafft/mafft-linux64/mafftdir/libexec/splittbfast differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/tbfast b/software/mafft/mafft-linux64/mafftdir/libexec/tbfast index 1ab0e605..090e35db 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/tbfast and b/software/mafft/mafft-linux64/mafftdir/libexec/tbfast differ diff --git a/software/mafft/mafft-linux64/mafftdir/libexec/version b/software/mafft/mafft-linux64/mafftdir/libexec/version index e30b3a86..91b987cb 100755 Binary files a/software/mafft/mafft-linux64/mafftdir/libexec/version and b/software/mafft/mafft-linux64/mafftdir/libexec/version differ diff --git a/software/mafft/mafft-mac/mafftdir/bin/mafft b/software/mafft/mafft-mac/mafftdir/bin/mafft index 91b5fc97..ea696b6b 100755 --- a/software/mafft/mafft-mac/mafftdir/bin/mafft +++ b/software/mafft/mafft-mac/mafftdir/bin/mafft @@ -1,7 +1,7 @@ #! /bin/bash er=0; myself=`dirname "$0"`/`basename "$0"`; export myself -version="v7.490 (2021/Oct/30)"; export version +version="v7.526 (2024/Apr/26)"; export version LANG=C; export LANG os=`uname` progname=`basename "$0"` @@ -175,6 +175,7 @@ elif [ $progname = "nwnsi" -o $progname = "mafft-nwnsi" ]; then fi outputfile="" namelength=-1 +linelength=60 # Will change to -1 in the future anysymbol=0 parallelizationstrategy="BAATARI2" kappa=$defaultkappa @@ -216,7 +217,9 @@ contrafold=$defaultcontrafold progressfile="/dev/stderr" anchorfile="/dev/null" anchoropt="" -maxanchorseparation=1000 +#maxanchorseparation=1000 +#maxanchorseparation=-1 # 2023/Jan/11 +terminalmargin=100 # 2024/Mar debug=0 sw=0 algopt=$defaultalgopt @@ -241,6 +244,7 @@ partorderopt=" -x " treeout=0 nodeout=0 distout=0 +distformat="hat2" treein=0 topin=0 treeinopt=" " @@ -252,12 +256,15 @@ strdir="$PWD" scorematrix="/dev/null" textmatrix="/dev/null" treeinfile="/dev/null" +codonposfile="/dev/null" +codonscorefile="/dev/null" rnascoremtx=" " laraparams="/dev/null" foldalignopt=" " treealg=" -X 0.1 " sueff="1.0" maxambiguous="1.0" +dofilter=0 scoreoutarg=" " numthreads=0 numthreadsit=-1 @@ -352,6 +359,13 @@ if [ $# -gt 0 ]; then echo "" 1>&2 exit 1; # algspecified=1 + elif [ "$1" = "--linelength" ]; then + shift + linelength=`expr "$1" - 0` + if [ $linelength -eq 0 ]; then + echo "Line length = 0 ?" 1>&2 + exit + fi elif [ "$1" = "--namelength" ]; then shift namelength=`expr "$1" - 0` @@ -389,6 +403,10 @@ if [ $# -gt 0 ]; then treeout=1 elif [ "$1" = "--distout" ]; then distout=1 + distformat="hat2" + elif [ "$1" = "--distoutclustalo" ]; then + distout=1 + distformat="clodist" elif [ "$1" = "--fastswpair" ]; then distance="fasta" pairspecified=1 @@ -410,6 +428,25 @@ if [ $# -gt 0 ]; then elif [ "$1" = "--maxambiguous" ]; then shift maxambiguous="$1" + dofilter=1 + elif [ "$1" = "--codonpos" ]; then + shift + codonposfile="$1" + if [ ! -e "$codonposfile" ]; then + echo "Cannot open $codonposfile" 1>&2 + echo "" 1>&2 + exit + fi + codonposopt=" -R " + elif [ "$1" = "--codonscore" ]; then + shift + codonscorefile="$1" + if [ ! -e "$codonscorefile" ]; then + echo "Cannot open $codonscorefile" 1>&2 + echo "" 1>&2 + exit + fi + codonscoreopt=" -S " elif [ "$1" = "--noscore" ]; then scorecalcopt=" -Z " elif [ "$1" = "--6mermultipair" ]; then @@ -544,13 +581,13 @@ if [ $# -gt 0 ]; then elif [ "$1" = "--out" ]; then shift outputfile="$1" - elif [ "$1" = "--skipanchorsremoterthan" ]; then + elif [ "$1" = "--terminalmargin" ]; then shift if ! expr "$1" : "[0-9]" > /dev/null ; then - echo "Specify maximum gap length between anchors." 1>&2 + echo "set --terminalmargin (int)." 1>&2 exit fi - maxanchorseparation=`expr "$1" - 0` + terminalmargin=`expr "$1" - 0` elif [ "$1" = "--anchors" ]; then shift anchorfile="$1" @@ -645,10 +682,26 @@ if [ $# -gt 0 ]; then addarg0="-K -I" addfile="$1" fragment=-2 + elif [ "$1" = "--addtotop" ]; then + shift + addarg0="-K -I" + addfile="$1" + fragment=-3 + elif [ "$1" = "--addtoroot" ]; then + shift + addarg0="-K -I" + addfile="$1" + fragment=-4 elif [ "$1" = "--smoothing" ]; then add2ndhalfarg=$add2ndhalfarg" -p " elif [ "$1" = "--keeplength" ]; then add2ndhalfarg=$add2ndhalfarg" -Y " + elif [ "$1" = "--compactmapout" ]; then + add2ndhalfarg=$add2ndhalfarg" -z -Y " + elif [ "$1" = "--compactmapoutfile" ]; then + shift + add2ndhalfarg=$add2ndhalfarg" -z -Y " + mapoutfile="$1" elif [ "$1" = "--mapout" ]; then add2ndhalfarg=$add2ndhalfarg" -Z -Y " elif [ "$1" = "--mapoutfile" ]; then @@ -684,7 +737,8 @@ if [ $# -gt 0 ]; then f2clext="-E" seqtype="-P" fft=0 - sbstmodel=" -b -2 -a " +# sbstmodel=" -b -2 -a " + sbstmodel=" -b -2 " # 2022/Jul, hauretsu no kawari ni scoremtx wo miru scorematrix="$1" if [ ! -e "$scorematrix" ]; then echo "Cannot open $scorematrix" 1>&2 @@ -1079,9 +1133,9 @@ function removetmpfile() { # for MPI echo "" >> "$TMPFILE/infile" cat "$addfile" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_addfile" - if [ $maxambiguous != "1.0" ]; then - mv "$TMPFILE/infile" "$TMPFILE/_tofilter" - "$prefix/filter" -m $maxambiguous $seqtype -i "$TMPFILE/_tofilter" > "$TMPFILE/infile" 2>>"$progressfile" || exit 1 + if [ $dofilter -eq 1 ]; then +# mv "$TMPFILE/infile" "$TMPFILE/_tofilter" +# "$prefix/filter" -m $maxambiguous $seqtype -i "$TMPFILE/_tofilter" > "$TMPFILE/infile" 2>>"$progressfile" || exit 1 mv "$TMPFILE/_addfile" "$TMPFILE/_tofilter" "$prefix/filter" -m $maxambiguous $seqtype -i "$TMPFILE/_tofilter" > "$TMPFILE/_addfile" 2>>"$progressfile" || exit 1 fi @@ -1090,6 +1144,8 @@ function removetmpfile() { # for MPI cat "$scorematrix" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_aamtx" cat "$mergetable" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_subalignmentstable" cat "$treeinfile" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_guidetree" + cat "$codonposfile" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_codonpos" + cat "$codonscorefile" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_codonscore" cat "$seedtablefile" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_seedtablefile" cat "$laraparams" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/_lara.params" cat "$pdblist" | tr "\r" "\n" | grep -v "^$" > "$TMPFILE/pdblist" @@ -1104,6 +1160,8 @@ $addfile $scorematrix $mergetable $treeinfile +$codonposfile +$codonscorefile $seedtablefile $laraparams $pdblist @@ -1335,10 +1393,11 @@ $ownlist" exit 1; fi # nagasa check! -# - if [ $npair -gt 10000000 -o $nlen -gt 5000 ]; then # 2017/Oct +# if [ $npair -gt 10000000 -o $nlen -gt 5000 ]; then # 2017/Oct + if [ $npair -gt 10000000 -o $nlen -gt 5000 -o $nadd -gt 500000 ]; then # 2021/Dec pairlocalalign to buntan distance="ktuples" echo "use ktuples, size=$tuplesize!" 1>>"$progressfile" +# elif [ $npair -gt 3000000 -o $nlen -gt 5000 ]; then # 2017/Oct elif [ $npair -gt 3000000 -o $nlen -gt 5000 ]; then # 2017/Oct distance="multi" weighti="0.0" @@ -1739,7 +1798,7 @@ $ownlist" parttreeoutopt=" " fi if [ $distout -eq 1 ]; then - distoutopt="-y -T" + distoutopt="-y ${distformat} -T" if [ $treeout -eq 0 ]; then treeoutopt="" fi @@ -1760,7 +1819,7 @@ $ownlist" treeoutopt=" " fi if [ $distout -eq 1 ]; then - distoutopt="-y" + distoutopt="-y ${distformat}" fi fi # @@ -2000,6 +2059,16 @@ $ownlist" laof=0.0 # 2015Jun01 lexp=0.0 # 2015Jun01 iterate=0 + elif [ $fragment -eq "-3" ]; then + addarg="$addarg0 $nadd" + addsinglearg="-x" # add to top, 2021/12/31 + cycle=1 # chuui 2014Aug25 + iterate=0 + elif [ $fragment -eq "-4" ]; then + addarg="$addarg0 $nadd" + addsinglearg="-s" # add to root, 2023/2/11 + cycle=1 # chuui 2014Aug25 + iterate=0 else addarg="$addarg0 $nadd" addsinglearg="" @@ -2032,6 +2101,21 @@ $ownlist" fi fi + if [ "$codonposfile" != "/dev/null" -o "$codonscorefile" != "/dev/null" ]; then + if [ $nadd -eq "0" -o $fragment -eq "0" ]; then + echo '' 1>>"$progressfile" + echo "'--codonpos' and '--codonscore' options are supported only with the '--6merpair --addfragments' option." 1>>"$progressfile" + echo '' 1>>"$progressfile" + exit 1 + fi + if [ $distance != "ktuples" ]; then # ato de taiou + echo '' 1>>"$progressfile" + echo "'--codonpos' and '--codonscore' options are supported only with the '--6merpair --addfragments' option, at this point." 1>>"$progressfile" + echo '' 1>>"$progressfile" + exit 1 + fi + fi + if [ -z "$localparam" -a $fragment -eq 0 -a $distance != "parttree" ]; then # echo "use disttbfast" @@ -2143,6 +2227,8 @@ $ownlist" strategy=$strategy"full" elif [ $fragment -eq -2 ]; then strategy=$strategy"long" + elif [ $fragment -eq -3 ]; then + strategy=$strategy"top" else strategy=$strategy$cycle fi @@ -2194,9 +2280,9 @@ $ownlist" elif [ $outputformat = "phylip" -a $outorder = "input" ]; then outputopt=" -y " elif [ $outputformat = "pir" -a $outorder = "aligned" ]; then - outputopt=" -f -r $TMPFILE/order " + outputopt=" -f -l $linelength -r $TMPFILE/order " else - outputopt="-f" + outputopt="-f -l $linelength" fi if [ $newdash_originalsequenceonly -eq 1 ]; then @@ -2502,7 +2588,7 @@ $ownlist" "$prefix/pairlocalalign" $localparam $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -Q $spfactor -h $laof -L $usenaivepairscore < infile > /dev/null 2>>"$progressfile" || exit 1 cat hat3.seed hat3 > hatx mv hatx hat3 - "$prefix/addsingle" -Q 100 $legacygapopt -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/addsingle" $codonposopt $codonscoreopt -Q 100 $legacygapopt -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 else "$prefix/tbfast" _ -u $unalignlevel $localparam -C $numthreads $seqtype $model -g $lexp -f $lgop -Q $spfactor -h $laof -L $usenaivepairscore $focusarg _ -+ $iterate -W $minimumweight -V "-"$gopdist -s $unalignlevel $legacygapopt $mergearg $termgapopt $outnum $addarg $add2ndhalfarg -C $numthreadstb $rnaopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -Q $spfactor -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg $focusarg < infile > /dev/null 2>>"$progressfile" || exit 1 fi @@ -2518,7 +2604,7 @@ $ownlist" "$prefix/pairlocalalign" $addarg -C $numthreads $seqtype $model -e $last_e -w $last_m -g $lexp -f $lgop -Q $spfactor -h $laof -R $last_subopt $last_once -d "$prefix" < infile > /dev/null 2>>"$progressfile" || exit 1 cat hat3.seed hat3 > hatx mv hatx hat3 - "$prefix/addsingle" -Q 100 $legacygapopt -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/addsingle" $codonposopt $codonscoreopt -Q 100 $legacygapopt -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 else "$prefix/pairlocalalign" -C $numthreads $seqtype $model -e $last_e -w $last_m -g $lexp -f $lgop -Q $spfactor -h $laof -R $last_subopt $last_once -d "$prefix" < infile > /dev/null 2>>"$progressfile" || exit 1 # addarg wo watasanai @@ -2527,27 +2613,27 @@ $ownlist" "$prefix/tbfast" -W $minimumweight -V "-"$gopdist -s $unalignlevel $legacygapopt $mergearg $termgapopt $outnum $addarg $add2ndhalfarg -C $numthreadstb $rnaopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -Q $spfactor -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 fi elif [ $distance = "lastmulti" ]; then - "$prefix/dndpre" $model -M 2 $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -Q $spfactor -h $laof < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/dndpre" -y $distformat $model -M 2 $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -Q $spfactor -h $laof < infile > /dev/null 2>>"$progressfile" || exit 1 mv hat2 hat2i "$prefix/pairlocalalign" $addarg -C $numthreads $seqtype $model -e $last_e -w $last_m -g $lexp -f $lgop -Q $spfactor -h $laof -r $last_subopt $last_once -d "$prefix" < infile > /dev/null 2>>"$progressfile" || exit 1 cat hat3.seed hat3 > hatx mv hat2 hat2n mv hatx hat3 if [ $fragment -ne 0 ]; then - "$prefix/addsingle" -Q 100 $legacygapopt -d -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/addsingle" $codonposopt $codonscoreopt -Q 100 $legacygapopt -d -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 else echo "Impossible" 1>&2 exit 1 fi elif [ $distance = "multi" ]; then - "$prefix/dndpre" $model -M 2 $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -h $laof $usenaivepairscore < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/dndpre" -y $distformat $model -M 2 $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -h $laof $usenaivepairscore < infile > /dev/null 2>>"$progressfile" || exit 1 mv hat2 hat2i "$prefix/pairlocalalign" $localparam $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -Q $spfactor -h $laof -Y $usenaivepairscore < infile > /dev/null 2>>"$progressfile" || exit 1 cat hat3.seed hat3 > hatx mv hat2 hat2n mv hatx hat3 if [ $fragment -ne 0 ]; then - "$prefix/addsingle" -Q 100 $legacygapopt -d -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/addsingle" $codonposopt $codonscoreopt -Q 100 $legacygapopt -d -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 else echo "Impossible" 1>&2 exit 1 @@ -2558,7 +2644,7 @@ $ownlist" mv hatx hat3 "$prefix/disttbfast" -E 1 -s $unalignlevel $legacygapopt -W $tuplesize $termgapopt $outnum $addarg $add2ndhalfarg -C $numthreads-$numthreadstb $memopt $weightopt $treeinopt $treeoutopt -T -y $seqtype $model -f "-"$gop -Q $spfactor -h $aof $param_fft $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 if [ $fragment -ne 0 ]; then - "$prefix/addsingle" -Q 100 $legacygapopt -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/addsingle" $codonposopt $codonscoreopt -Q 100 $legacygapopt -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 else "$prefix/tbfast" -W $minimumweight -V "-"$gopdist -s $unalignlevel $legacygapopt $mergearg $termgapopt $outnum $addarg $add2ndhalfarg -C $numthreadstb $rnaopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -Q $spfactor -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 fi @@ -2569,22 +2655,22 @@ $ownlist" "$prefix/splittbfast" $legacygapopt $algopt $splitopt $partorderopt $parttreeoutopt $memopt $seqtype $model -f "-"$gop -Q $spfactor -h $aof -p $partsize -s $groupsize $treealg $outnum -i infile > pre 2>>"$progressfile" || exit 1 mv hat3.seed hat3 elif [ $distance = "ktuplesmulti" ]; then -# "$prefix/dndpre" $model -M 1 $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -h $laof < infile > /dev/null 2>>"$progressfile" || exit 1 +# "$prefix/dndpre" -y $distformat $model -M 1 $addarg -C $numthreads $seqtype $model -g $lexp -f $lgop -h $laof < infile > /dev/null 2>>"$progressfile" || exit 1 # mv hat2 hat2i # "$prefix/disttbfast" -E 1 -s $unalignlevel $legacygapopt -W $tuplesize $termgapopt $outnum $addarg $add2ndhalfarg -C $numthreads-$numthreadstb $memopt $weightopt $treeinopt $treeoutopt -T -y $seqtype $model -f "-"$gop -Q $spfactor -h $aof $param_fft $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 # mv hat2 hat2n if [ $fragment -ne 0 ]; then - "$prefix/addsingle" -Q 100 $legacygapopt -d -W $tuplesize -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 -# "$prefix/addsingle" -Q 100 $legacygapopt -d -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/addsingle" $codonposopt $codonscoreopt -Q 100 $legacygapopt -d -W $tuplesize -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 +# "$prefix/addsingle" -Q 100 $legacygapopt -d -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 else echo "Impossible" 1>&2 exit 1 fi else if [ $fragment -ne 0 ]; then - "$prefix/addsingle" -Q 100 $legacygapopt -W $tuplesize -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg $scoreoutarg < infile > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/addsingle" $codonposopt $codonscoreopt -Q 100 $legacygapopt -W $tuplesize -O $outnum $addsinglearg $addarg $add2ndhalfarg -C $numthreads $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -f "-"$gop -h $aof $param_fft $localparam $algopt $treealg < infile > /dev/null 2>>"$progressfile" || exit 1 else - "$prefix/disttbfast" -q $npickup -E $cycledisttbfast -V "-"$gopdist -s $unalignlevel $legacygapopt $mergearg -W $tuplesize $termgapopt $outnum $addarg $add2ndhalfarg -C $numthreads-$numthreadstb $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -g $gexp -f "-"$gop -Q $spfactor -h $aof $param_fft $algopt $treealg $scoreoutarg $anchoropt -x $maxanchorseparation $oneiterationopt < infile > pre 2>>"$progressfile" || exit 1 + "$prefix/disttbfast" -q $npickup -E $cycledisttbfast -V "-"$gopdist -s $unalignlevel $legacygapopt $mergearg -W $tuplesize $termgapopt $outnum $addarg $add2ndhalfarg -C $numthreads-$numthreadstb $memopt $weightopt $treeinopt $treeoutopt $distoutopt $seqtype $model -g $gexp -f "-"$gop -Q $spfactor -h $aof $param_fft $algopt $treealg $scoreoutarg $anchoropt -x $terminalmargin $oneiterationopt < infile > pre 2>>"$progressfile" || exit 1 mv hat3.seed hat3 fi fi @@ -2602,7 +2688,7 @@ $ownlist" done if [ $iterate -gt 0 ]; then if [ $distance = "ktuples" ]; then - "$prefix/dndpre" $seqtype $model -M 2 -C $numthreads < pre > /dev/null 2>>"$progressfile" || exit 1 + "$prefix/dndpre" -y $distformat $seqtype $model -M 2 -C $numthreads < pre > /dev/null 2>>"$progressfile" || exit 1 fi "$prefix/dvtditr" -W $minimumweight $bunkatsuopt -E $fixthreshold -s $unalignlevel $legacygapopt $mergearg $outnum -C $numthreadsit -t $randomseed $rnaoptit $memopt $scorecalcopt $localparam -z 50 $seqtype $model -f "-"$gop -Q $spfactor -h $aof -I $iterate $weightopt $treeinopt $algoptit $treealg -p $parallelizationstrategy $scoreoutarg -K $nadd < pre > /dev/null 2>>"$progressfile" || exit 1 fi @@ -2711,7 +2797,7 @@ $ownlist" popd > /dev/null - if [ "$outputopt" != "-f" -o "$windows" = "yes" ]; then # Windows deha kaigyo code wo f2cl de modosu. + if [ "$outputopt" != "-f -l -1" -o "$windows" = "yes" ]; then # Windows deha kaigyo code wo f2cl de modosu. # ln -s "$TMPFILE/order" _order$$ # f2cl ga space ari filename ni taiou shiteinainode # cp "$TMPFILE/order" _order$$ # ln -s no error wo sakeru if [ "$outputfile" = "" ]; then @@ -2737,7 +2823,7 @@ $ownlist" fi if [ $distout -eq 1 ]; then - cp "$TMPFILE/hat2" "$infilename.hat2" + cp "$TMPFILE/${distformat}" "$infilename.${distformat}" fi if [ $npickup -ne 0 ]; then diff --git a/software/mafft/mafft-mac/mafftdir/libexec/addsingle b/software/mafft/mafft-mac/mafftdir/libexec/addsingle index 1ff0f8f6..f6500531 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/addsingle and b/software/mafft/mafft-mac/mafftdir/libexec/addsingle differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/contrafoldwrap b/software/mafft/mafft-mac/mafftdir/libexec/contrafoldwrap index 1402942a..4fd93968 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/contrafoldwrap and b/software/mafft/mafft-mac/mafftdir/libexec/contrafoldwrap differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/countlen b/software/mafft/mafft-mac/mafftdir/libexec/countlen index 84789f2a..62850080 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/countlen and b/software/mafft/mafft-mac/mafftdir/libexec/countlen differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/dash_client b/software/mafft/mafft-mac/mafftdir/libexec/dash_client index 86d8de74..e0e22560 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/dash_client and b/software/mafft/mafft-mac/mafftdir/libexec/dash_client differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/disttbfast b/software/mafft/mafft-mac/mafftdir/libexec/disttbfast index 8a1c0147..99dcd2e7 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/disttbfast and b/software/mafft/mafft-mac/mafftdir/libexec/disttbfast differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/dndblast b/software/mafft/mafft-mac/mafftdir/libexec/dndblast index dafe7731..21194f9a 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/dndblast and b/software/mafft/mafft-mac/mafftdir/libexec/dndblast differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/dndfast7 b/software/mafft/mafft-mac/mafftdir/libexec/dndfast7 index 66ebce1c..792960c6 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/dndfast7 and b/software/mafft/mafft-mac/mafftdir/libexec/dndfast7 differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/dndpre b/software/mafft/mafft-mac/mafftdir/libexec/dndpre index 4fe0bc7b..889f2ea4 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/dndpre and b/software/mafft/mafft-mac/mafftdir/libexec/dndpre differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/dvtditr b/software/mafft/mafft-mac/mafftdir/libexec/dvtditr index d72a3d38..ce67fbe4 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/dvtditr and b/software/mafft/mafft-mac/mafftdir/libexec/dvtditr differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/f2cl b/software/mafft/mafft-mac/mafftdir/libexec/f2cl index 461549c1..f74b9f2d 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/f2cl and b/software/mafft/mafft-mac/mafftdir/libexec/f2cl differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/filter b/software/mafft/mafft-mac/mafftdir/libexec/filter index f5c6dd2e..f4cd6089 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/filter and b/software/mafft/mafft-mac/mafftdir/libexec/filter differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/getlag b/software/mafft/mafft-mac/mafftdir/libexec/getlag index 71cdce71..a685e29e 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/getlag and b/software/mafft/mafft-mac/mafftdir/libexec/getlag differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/hex2maffttext b/software/mafft/mafft-mac/mafftdir/libexec/hex2maffttext index d5a9601f..2f84bc69 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/hex2maffttext and b/software/mafft/mafft-mac/mafftdir/libexec/hex2maffttext differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/mafft-distance b/software/mafft/mafft-mac/mafftdir/libexec/mafft-distance index fcd8f50e..8b9e2054 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/mafft-distance and b/software/mafft/mafft-mac/mafftdir/libexec/mafft-distance differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/mafft-profile b/software/mafft/mafft-mac/mafftdir/libexec/mafft-profile index ecb9e93c..82325e96 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/mafft-profile and b/software/mafft/mafft-mac/mafftdir/libexec/mafft-profile differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/maffttext2hex b/software/mafft/mafft-mac/mafftdir/libexec/maffttext2hex index f33f5b60..a4dfcc73 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/maffttext2hex and b/software/mafft/mafft-mac/mafftdir/libexec/maffttext2hex differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/makedirectionlist b/software/mafft/mafft-mac/mafftdir/libexec/makedirectionlist index 53db353a..b117cbbd 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/makedirectionlist and b/software/mafft/mafft-mac/mafftdir/libexec/makedirectionlist differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/mccaskillwrap b/software/mafft/mafft-mac/mafftdir/libexec/mccaskillwrap index ddf86a43..12814622 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/mccaskillwrap and b/software/mafft/mafft-mac/mafftdir/libexec/mccaskillwrap differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/multi2hat3s b/software/mafft/mafft-mac/mafftdir/libexec/multi2hat3s index 5599e514..f6377bc3 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/multi2hat3s and b/software/mafft/mafft-mac/mafftdir/libexec/multi2hat3s differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/nodepair b/software/mafft/mafft-mac/mafftdir/libexec/nodepair index acf55903..53040ef7 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/nodepair and b/software/mafft/mafft-mac/mafftdir/libexec/nodepair differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/pairash b/software/mafft/mafft-mac/mafftdir/libexec/pairash index b64df32f..6d6750c1 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/pairash and b/software/mafft/mafft-mac/mafftdir/libexec/pairash differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/pairlocalalign b/software/mafft/mafft-mac/mafftdir/libexec/pairlocalalign index 80e7b591..0987d920 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/pairlocalalign and b/software/mafft/mafft-mac/mafftdir/libexec/pairlocalalign differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/regtable2seq b/software/mafft/mafft-mac/mafftdir/libexec/regtable2seq index b5c4af47..875250f0 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/regtable2seq and b/software/mafft/mafft-mac/mafftdir/libexec/regtable2seq differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/replaceu b/software/mafft/mafft-mac/mafftdir/libexec/replaceu index 4e7bbbf8..b8a31030 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/replaceu and b/software/mafft/mafft-mac/mafftdir/libexec/replaceu differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/restoreu b/software/mafft/mafft-mac/mafftdir/libexec/restoreu index a8eeac63..0c0c2191 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/restoreu and b/software/mafft/mafft-mac/mafftdir/libexec/restoreu differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/score b/software/mafft/mafft-mac/mafftdir/libexec/score index 66977105..ac0f43cf 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/score and b/software/mafft/mafft-mac/mafftdir/libexec/score differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/seq2regtable b/software/mafft/mafft-mac/mafftdir/libexec/seq2regtable index f283d554..b91999a8 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/seq2regtable and b/software/mafft/mafft-mac/mafftdir/libexec/seq2regtable differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/setcore b/software/mafft/mafft-mac/mafftdir/libexec/setcore index ba798fea..97472142 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/setcore and b/software/mafft/mafft-mac/mafftdir/libexec/setcore differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/setdirection b/software/mafft/mafft-mac/mafftdir/libexec/setdirection index 1f06ecf4..4f670165 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/setdirection and b/software/mafft/mafft-mac/mafftdir/libexec/setdirection differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/sextet5 b/software/mafft/mafft-mac/mafftdir/libexec/sextet5 index 25d8d165..3e44da5c 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/sextet5 and b/software/mafft/mafft-mac/mafftdir/libexec/sextet5 differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/splittbfast b/software/mafft/mafft-mac/mafftdir/libexec/splittbfast index 14741baf..afe1e6f7 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/splittbfast and b/software/mafft/mafft-mac/mafftdir/libexec/splittbfast differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/tbfast b/software/mafft/mafft-mac/mafftdir/libexec/tbfast index 174b5772..133da2b5 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/tbfast and b/software/mafft/mafft-mac/mafftdir/libexec/tbfast differ diff --git a/software/mafft/mafft-mac/mafftdir/libexec/version b/software/mafft/mafft-mac/mafftdir/libexec/version index de766d27..a75621ad 100755 Binary files a/software/mafft/mafft-mac/mafftdir/libexec/version and b/software/mafft/mafft-mac/mafftdir/libexec/version differ diff --git a/software/versions.txt b/software/versions.txt index e4bb821b..71ba35ca 100644 --- a/software/versions.txt +++ b/software/versions.txt @@ -1,13 +1,13 @@ Apache-POI: 3.8 -BLAST+: 2.12.0 +BLAST+: 2.17.0 CD-HIT: 4.8.1 -DIAMOND: 2.0.13 +DIAMOND: 2.1.17 GLPK: 4.40 GLPK (.mexmaca64 only): 5.0 libSBML: 5.20.2 libSBML (.mexmaci64 only): 5.19.0 M2HTML: 1.5 -HMMER: 3.3.2 -MAFFT: 7.490 +HMMER: 3.4.0 +MAFFT: 7.526 WoLFPSORT: v0.2 progressbar: 1.2.0.0 \ No newline at end of file diff --git a/solver/optimizeProb.m b/solver/optimizeProb.m index 3aa3bce2..3430c45d 100755 --- a/solver/optimizeProb.m +++ b/solver/optimizeProb.m @@ -242,7 +242,7 @@ switch exitflag case 11 res.stat = 1; - case [5, 6, 7, 8, 9, 10, 13] + case {1, 5, 6, 7, 8, 9, 10, 13} % If user-interrupted, not sure if optimal res.stat = 2; otherwise res.stat = 0; diff --git a/struct_conversion/ravenCobraWrapper.m b/struct_conversion/ravenCobraWrapper.m index 6bb14d7c..47b48525 100755 --- a/struct_conversion/ravenCobraWrapper.m +++ b/struct_conversion/ravenCobraWrapper.m @@ -186,7 +186,7 @@ newModel.b=zeros(numel(model.mets),1); newModel.csense=repmat('E',size(model.mets)); if isfield(model,'geneMiriams') - [miriams,extractedMiriamNames]=extractMiriam(model.geneMiriams); + [~,extractedMiriamNames]=extractMiriam(model.geneMiriams); for i = 1:length(geneCOBRAfields) j=ismember(extractedMiriamNames,geneNamespaces{i}); if any(j) @@ -202,11 +202,16 @@ else fprintf('WARNING: no genes detected. The model therefore may not be exportable to SBML file with writeCbModel\n'); end - newModel.osenseStr='max'; + % If needed, normalise subSystems to cell-of-cells format + if isfield(newModel,'subSystems') && ~isempty(newModel.subSystems) + if ~iscell(newModel.subSystems{1}) + newModel.subSystems = cellfun(@(x) {x}, newModel.subSystems, 'UniformOutput', false); + end + end else fprintf('Converting COBRA structure to RAVEN..\n'); %Convert from COBRA to RAVEN structure - + %Mandatory RAVEN fields newModel.mets=model.mets; if ~isfield(model,'comps') @@ -396,6 +401,12 @@ end end end + % Flatten subSystems if every reaction has exactly one subsystem. + if isfield(newModel,'subSystems') && ~isempty(newModel.subSystems) + if all(cellfun(@(x) iscell(x) && isscalar(x), newModel.subSystems)) + newModel.subSystems = transpose([newModel.subSystems{:}]); + end + end if printWarning 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'); end diff --git a/testing/unit_tests/hmmerTests.m b/testing/unit_tests/hmmerTests.m index d17b8e8d..1a3fdf3a 100755 --- a/testing/unit_tests/hmmerTests.m +++ b/testing/unit_tests/hmmerTests.m @@ -21,6 +21,18 @@ function testHmmer(testCase) [ST, I]=dbstack('-completenames'); ravenPath=fileparts(fileparts(fileparts(ST(I).file))); +%Generate temporary names for working directory and outFile +tmpDIR=tempname; +outFile=tempname; + +%Create a temporary folder and copy multi-FASTA file there +[~, ~]=system(['mkdir "' tmpDIR '"']); + +sourceDir = fileparts(which(mfilename)); +copyfile(fullfile(sourceDir,'test_data','yeast_galactosidases.fa'),tmpDIR); +copyfile(fullfile(sourceDir,'test_data','human_galactosidases.fa'),tmpDIR); + + %Identify the operating system if isunix if ismac @@ -29,7 +41,10 @@ function testHmmer(testCase) binEnd=''; end elseif ispc - binEnd='.exe'; + wslPath.tmpDIR = getWSLpath(tmpDIR); + wslPath.hmmbuild = getWSLpath(fullfile(ravenPath,'software','hmmer','hmmbuild')); + wslPath.hmmsearch = getWSLpath(fullfile(ravenPath,'software','hmmer','hmmsearch')); + filesep='/'; else dispEM('Unknown OS, exiting.') return @@ -43,29 +58,26 @@ function testHmmer(testCase) expHmmResult.genes = {'sp|P41947|MEL6_YEASX','sp|P41946|MEL5_YEASX', 'sp|P41945|MEL2_YEASX', 'sp|P04824|MEL1_YEASX'}; expHmmResult.scores = [10^-250, 10^-250, 10^-250, 10^-250]; -%Generate temporary names for working directory and outFile -tmpDIR=tempname; -outFile=tempname; - %Run HMMER multi-threaded to use all logical cores assigned to MATLAB cores = evalc('feature(''numcores'')'); cores = strsplit(cores, 'MATLAB was assigned: '); cores = regexp(cores{2},'^\d*','match'); cores = cores{1}; -%Create a temporary folder and copy multi-FASTA file there -[~, ~]=system(['mkdir "' tmpDIR '"']); - -sourceDir = fileparts(which(mfilename)); -copyfile(fullfile(sourceDir,'test_data','yeast_galactosidases.fa'),tmpDIR); -copyfile(fullfile(sourceDir,'test_data','human_galactosidases.fa'),tmpDIR); - %% %Train a hidden Markov model -[~, ~]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmbuild' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(tmpDIR,'human_galactosidases.hmm') '" "' fullfile(tmpDIR,'yeast_galactosidases.fa') '"']); +if ismac || isunix + [~, ~]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmbuild' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(tmpDIR,'human_galactosidases.hmm') '" "' fullfile(tmpDIR,'yeast_galactosidases.fa') '"']); +else + [~, ~]=system(['wsl "' wslPath.hmmbuild '" --cpu "' num2str(cores) '" "' wslPath.tmpDIR '/human_galactosidases.hmm" "' wslPath.tmpDIR '/yeast_galactosidases.fa"']); +end %Run a homology search against the newly-trained HMM -[~, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmsearch' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(tmpDIR,'human_galactosidases.hmm') '" "' fullfile(tmpDIR,'yeast_galactosidases.fa') '"']); +if ismac || isunix + [~, output]=system(['"' fullfile(ravenPath,'software','hmmer',['hmmsearch' binEnd]) '" --cpu "' num2str(cores) '" "' fullfile(tmpDIR,'human_galactosidases.hmm') '" "' fullfile(tmpDIR,'yeast_galactosidases.fa') '"']); +else + [~, output]=system(['wsl "' wslPath.hmmsearch '" --cpu "' num2str(cores) '" "' wslPath.tmpDIR '/human_galactosidases.hmm" "' wslPath.tmpDIR '/yeast_galactosidases.fa"']); +end %Save the output to a file fid=fopen(outFile,'w'); diff --git a/testing/unit_tests/importExportTests.m b/testing/unit_tests/importExportTests.m index 4db6eb9f..ff670f57 100755 --- a/testing/unit_tests/importExportTests.m +++ b/testing/unit_tests/importExportTests.m @@ -36,7 +36,7 @@ function testYAMLimport(testCase) 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')); +evalc('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. diff --git a/testing/unit_tests/test_data/ecoli_textbook.mat b/testing/unit_tests/test_data/ecoli_textbook.mat index ac202963..67e344ad 100644 Binary files a/testing/unit_tests/test_data/ecoli_textbook.mat and b/testing/unit_tests/test_data/ecoli_textbook.mat differ diff --git a/testing/unit_tests/test_data/expBlastResults.mat b/testing/unit_tests/test_data/expBlastResults.mat index 051bfa72..7b81eac8 100644 Binary files a/testing/unit_tests/test_data/expBlastResults.mat and b/testing/unit_tests/test_data/expBlastResults.mat differ diff --git a/testing/unit_tests/test_data/expCdhitMafftOutput.mat b/testing/unit_tests/test_data/expCdhitMafftOutput.mat index 6d80662d..d13059f6 100644 Binary files a/testing/unit_tests/test_data/expCdhitMafftOutput.mat and b/testing/unit_tests/test_data/expCdhitMafftOutput.mat differ diff --git a/testing/unit_tests/test_data/expDiamondResults.mat b/testing/unit_tests/test_data/expDiamondResults.mat index d064d42c..c242a16a 100644 Binary files a/testing/unit_tests/test_data/expDiamondResults.mat and b/testing/unit_tests/test_data/expDiamondResults.mat differ diff --git a/testing/unit_tests/test_data/importExportResults.mat b/testing/unit_tests/test_data/importExportResults.mat index 83f86ac8..4a3f9c35 100644 Binary files a/testing/unit_tests/test_data/importExportResults.mat and b/testing/unit_tests/test_data/importExportResults.mat differ diff --git a/testing/unit_tests/test_data/miriamTestOutput.mat b/testing/unit_tests/test_data/miriamTestOutput.mat index d5fc3b09..8035ad4e 100644 Binary files a/testing/unit_tests/test_data/miriamTestOutput.mat and b/testing/unit_tests/test_data/miriamTestOutput.mat differ diff --git a/testing/unit_tests/test_data/solverTestOutput.mat b/testing/unit_tests/test_data/solverTestOutput.mat index a0e8dd76..aaec2fc2 100644 Binary files a/testing/unit_tests/test_data/solverTestOutput.mat and b/testing/unit_tests/test_data/solverTestOutput.mat differ diff --git a/tutorial/empty.mat b/tutorial/empty.mat index 936aead1..7e05da08 100644 Binary files a/tutorial/empty.mat and b/tutorial/empty.mat differ diff --git a/tutorial/iMK1208+suppInfo.mat b/tutorial/iMK1208+suppInfo.mat index 9aa45a08..86a5fc7c 100644 Binary files a/tutorial/iMK1208+suppInfo.mat and b/tutorial/iMK1208+suppInfo.mat differ diff --git a/tutorial/pathway.mat b/tutorial/pathway.mat index bc01714f..5ffd49bc 100644 Binary files a/tutorial/pathway.mat and b/tutorial/pathway.mat differ diff --git a/tutorial/pcPathway.mat b/tutorial/pcPathway.mat index acfa80b5..d696b633 100644 Binary files a/tutorial/pcPathway.mat and b/tutorial/pcPathway.mat differ diff --git a/utils/emptyOrLogicalScalar.m b/utils/emptyOrLogicalScalar.m new file mode 100644 index 00000000..1583901d --- /dev/null +++ b/utils/emptyOrLogicalScalar.m @@ -0,0 +1,6 @@ +function emptyOrLogical(x) + if isempty(x) + return; + end + validateattributes(x, {'logical'}, {'scalar'}); +end diff --git a/utils/emptyOrTextOrCellOfText.m b/utils/emptyOrTextOrCellOfText.m new file mode 100644 index 00000000..7dc95d5f --- /dev/null +++ b/utils/emptyOrTextOrCellOfText.m @@ -0,0 +1,43 @@ +function mustBeEmptyOrTextOrCellOfText(x) +% Validate [] OR text scalar (char row or string scalar) OR cell array of such text. + +% Allow explicit empty +if isempty(x) + return; +end + +% Allow a single text scalar +if ischar(x) + if ~isrow(x) + error('Text must be a character row vector, a string scalar, or empty.'); + end + return; +elseif isstring(x) + if ~isscalar(x) + error('Text must be a string scalar, a character row vector, or empty.'); + end + return; +end + +% Allow a cell array of text +if iscell(x) + for k = 1:numel(x) + v = x{k}; + if ischar(v) + if ~isrow(v) % '' is 1x0 char, which is a row -> allowed + error('Each cell element must be a character row vector or a string scalar.'); + end + elseif isstring(v) + if ~isscalar(v) % "" is a scalar string -> allowed + error('Each cell element must be a string scalar or a character row vector.'); + end + else + error('Each cell element must be text (string scalar or character row vector).'); + end + end + return; +end + +% Anything else is invalid +error('Value must be empty, a text value, or a cell array of text values.'); +end diff --git a/utils/emptyOrTextScalar.m b/utils/emptyOrTextScalar.m new file mode 100644 index 00000000..3c61cdd7 --- /dev/null +++ b/utils/emptyOrTextScalar.m @@ -0,0 +1,12 @@ +function mustBeEmptyOrTextScalar(x) + if isempty(x) + return; + end + if isstring(x) + if ~isscalar(x), error('Value must be a string scalar or empty.'); end + elseif ischar(x) + if ~isrow(x), error('Char input must be a row vector or empty.'); end + else + error('Value must be a string/char scalar or empty.'); + end +end diff --git a/utils/runRAVENtests.m b/utils/runRAVENtests.m new file mode 100644 index 00000000..cd72cc6a --- /dev/null +++ b/utils/runRAVENtests.m @@ -0,0 +1,11 @@ +function testResults = runRAVENtests +% runRAVENtests +% Runs all unit tests found at RAVEN/test/unit_tests, and prints output in +% command window. + +ravenPath = findRAVENroot; +curwd = pwd; +cd(fullfile(ravenPath,'testing','unit_tests')); +testResults = runtests(struct2table(dir('*.m')).name); + +cd(curwd); \ No newline at end of file