From e4c1a236e0b77f699227bc6300ac1fde6c04c666 Mon Sep 17 00:00:00 2001 From: Eduard Kerkhoven Date: Sat, 21 Dec 2024 21:42:53 +0100 Subject: [PATCH 1/2] fix: various minor bugs (#575) * fix: closeModel comps-related fields * fix: generateNewIds default quantity * fix: readYAMLmodel if multiple annotations * chore: updateDocumentation * fix: read- and writeYAMLmodel empty fields * fix: generateNewIds if prefix used without numbers --- core/generateNewIds.m | 8 +- doc/core/generateNewIds.html | 52 +- doc/io/closeModel.html | 30 +- doc/io/readYAMLmodel.html | 1218 +++++++++++++++++----------------- doc/io/writeYAMLmodel.html | 181 ++--- io/closeModel.m | 30 +- io/readYAMLmodel.m | 18 +- io/writeYAMLmodel.m | 3 + 8 files changed, 779 insertions(+), 761 deletions(-) diff --git a/core/generateNewIds.m b/core/generateNewIds.m index d8b535c8..f66c6aa5 100755 --- a/core/generateNewIds.m +++ b/core/generateNewIds.m @@ -26,6 +26,9 @@ else error('type should be either ''rxns'' or ''mets''.') end +if nargin<4 + quantity=1; +end if nargin<5 numLength=4; end @@ -44,7 +47,10 @@ fprintf(['No ' type ' ids with prefix "' prefix ... '" currently exist in the model. The first new id will be "' ... [prefix,num2str(1,['%0' num2str(numLength) 'd'])] '"\n'],'%s') - lastId=0; +end + +if isnan(lastId) + lastId = 0; end newIds=cell(quantity,1); diff --git a/doc/core/generateNewIds.html b/doc/core/generateNewIds.html index 9bd3b1ea..557c9603 100644 --- a/doc/core/generateNewIds.html +++ b/doc/core/generateNewIds.html @@ -85,33 +85,39 @@

SOURCE CODE ^else 0027 error('type should be either ''rxns'' or ''mets''.') 0028 end -0029 if nargin<5 -0030 numLength=4; +0029 if nargin<4 +0030 quantity=1; 0031 end -0032 -0033 % Subset only existingIds that have the prefix -0034 existingIds=existingIds(~cellfun(@isempty,regexp(existingIds,['^' prefix]))); +0032 if nargin<5 +0033 numLength=4; +0034 end 0035 -0036 if ~isempty(existingIds) -0037 existingIds=regexprep(existingIds,['^' prefix],''); -0038 existingIds=sort(existingIds); -0039 lastId=existingIds{end}; -0040 numLength=length(lastId); -0041 lastId=str2double(lastId); -0042 else -0043 lastId=0; -0044 fprintf(['No ' type ' ids with prefix "' prefix ... -0045 '" currently exist in the model. The first new id will be "' ... -0046 [prefix,num2str(1,['%0' num2str(numLength) 'd'])] '"\n'],'%s') -0047 lastId=0; -0048 end -0049 -0050 newIds=cell(quantity,1); +0036 % Subset only existingIds that have the prefix +0037 existingIds=existingIds(~cellfun(@isempty,regexp(existingIds,['^' prefix]))); +0038 +0039 if ~isempty(existingIds) +0040 existingIds=regexprep(existingIds,['^' prefix],''); +0041 existingIds=sort(existingIds); +0042 lastId=existingIds{end}; +0043 numLength=length(lastId); +0044 lastId=str2double(lastId); +0045 else +0046 lastId=0; +0047 fprintf(['No ' type ' ids with prefix "' prefix ... +0048 '" currently exist in the model. The first new id will be "' ... +0049 [prefix,num2str(1,['%0' num2str(numLength) 'd'])] '"\n'],'%s') +0050 end 0051 -0052 for k=1:quantity -0053 newIds{k}=[prefix,num2str(k+lastId,['%0' num2str(numLength) 'd'])]; +0052 if isnan(lastId) +0053 lastId = 0; 0054 end -0055 end +0055 +0056 newIds=cell(quantity,1); +0057 +0058 for k=1:quantity +0059 newIds{k}=[prefix,num2str(k+lastId,['%0' num2str(numLength) 'd'])]; +0060 end +0061 end
Generated by m2html © 2005
\ No newline at end of file diff --git a/doc/io/closeModel.html b/doc/io/closeModel.html index aeb88f3d..a8db94c9 100644 --- a/doc/io/closeModel.html +++ b/doc/io/closeModel.html @@ -63,11 +63,11 @@

SOURCE CODE ^'b'; -0015 closedModel.compNames{numel(closedModel.compNames)+1}='boundary'; +0014 closedModel.comps{numel(closedModel.comps)+1,1}='b'; +0015 closedModel.compNames{numel(closedModel.compNames)+1,1}='boundary'; 0016 if isfield(closedModel,'compMiriams') -0017 closedModel.compMiriams{numel(closedModel.compMiriams)+1}=[]; -0018 end; +0017 closedModel.compMiriams{numel(closedModel.compMiriams)+1,1}=[]; +0018 end 0019 closedModel.unconstrained=zeros(numel(closedModel.mets),1); 0020 0021 for i=1:numel(closedModel.rxns) @@ -75,29 +75,29 @@

SOURCE CODE ^'_b'); 0024 if isfield(closedModel,'metNames') 0025 closedModel.metNames{numel(closedModel.metNames)+1}=closedModel.metNames{find(closedModel.S(:,i))}; -0026 end; +0026 end 0027 closedModel.metComps(numel(closedModel.metComps)+1)=numel(closedModel.comps); 0028 if isfield(closedModel,'inchis') 0029 closedModel.inchis{numel(closedModel.inchis)+1}=closedModel.inchis{find(closedModel.S(:,i))}; -0030 end; +0030 end 0031 if isfield(closedModel,'metSmiles') 0032 closedModel.metSmiles{numel(closedModel.metSmiles)+1}=closedModel.metSmiles{find(closedModel.S(:,i))}; -0033 end; +0033 end 0034 if isfield(closedModel,'metFormulas') 0035 closedModel.metFormulas{numel(closedModel.metFormulas)+1}=closedModel.metFormulas{find(closedModel.S(:,i))}; -0036 end; +0036 end 0037 if isfield(closedModel,'metMiriams') 0038 closedModel.metMiriams{numel(closedModel.metMiriams)+1}=closedModel.metMiriams{find(closedModel.S(:,i))}; -0039 end; +0039 end 0040 if isfield(closedModel,'metFrom') 0041 closedModel.metFrom{numel(closedModel.metFrom)+1}=''; -0042 end; +0042 end 0043 if isfield(closedModel,'metCharges') 0044 closedModel.metCharges(numel(closedModel.metCharges)+1)=closedModel.metCharges(find(closedModel.S(:,i))); -0045 end; +0045 end 0046 if isfield(closedModel,'metDeltaG') 0047 closedModel.metDeltaG(numel(closedModel.metDeltaG)+1)=closedModel.metDeltaG(find(closedModel.S(:,i))); -0048 end; +0048 end 0049 closedModel.unconstrained(numel(closedModel.unconstrained)+1)=1; 0050 closedModel.b(numel(closedModel.b)+1)=0; 0051 closedModel.S=[closedModel.S;sparse(1,size(closedModel.S,2))]; @@ -105,9 +105,9 @@

SOURCE CODE ^else 0055 closedModel.S(numel(closedModel.mets),i)=1; -0056 end; -0057 end; -0058 end; +0056 end +0057 end +0058 end 0059 0060 end
Generated by m2html © 2005
diff --git a/doc/io/readYAMLmodel.html b/doc/io/readYAMLmodel.html index 348b94b7..3a96f8c3 100644 --- a/doc/io/readYAMLmodel.html +++ b/doc/io/readYAMLmodel.html @@ -52,7 +52,7 @@

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

+
  • function model = emptyOrFill(model,field,emptyEntry,type,keepEmpty)
  • function model = readFieldValue(model, fieldName, value, pos)
  • function [miriams,miriamKey,entryNumber] = gatherAnnotation(pos,miriams,key,value,miriamKey,entryNumber)
  • SOURCE CODE ^

    0001 function model=readYAMLmodel(fileName, verbose)
    @@ -109,631 +109,631 @@ 

    SOURCE CODE ^end 0053 line_raw(brokenLine)=[]; 0054 -0055 line_key = regexprep(line_raw,'^ *-? ([^:]+)(:).*','$1'); +0055 line_key = regexprep(line_raw,'^ *-? ([^:]+)(:)($| .*)','$1'); 0056 line_key = regexprep(line_key,'(.*!!omap)|(---)|( {4,}.*)',''); 0057 0058 line_value = regexprep(line_raw, '.*:$',''); 0059 line_value = regexprep(line_value, '[^":]+: "?(.+)"?$','$1'); 0060 line_value = regexprep(line_value, '(")|(^ {4,}- )',''); 0061 -0062 modelFields = {'id',char();... -0063 'name',char();... -0064 'description',char();... -0065 'version',char();... -0066 'date',char();... -0067 'annotation',struct();... -0068 'rxns',{};... -0069 'rxnNames',{};... -0070 'mets',{};... -0071 'metNames',{};... -0072 'S',sparse([]);... -0073 'lb',{};... %Changed to double in the end. -0074 'ub',{};... %Changed to double in the end. -0075 'rev',{};... %Changed to double in the end. -0076 'c',[];... -0077 'b',cell(0,0);... %Changed to double in the end. -0078 'genes',cell(0,0);... -0079 'grRules',cell(0,0);... -0080 'rxnGeneMat',sparse([]);... -0081 'rxnComps',cell(0,0);... %Changed to double in the end. -0082 'subSystems',cell(0,0);... -0083 'eccodes',cell(0,0);... -0084 'rxnMiriams',cell(0,0);... -0085 'rxnDeltaG',{};... %Changed to double in the end. -0086 'rxnNotes',cell(0,0);... -0087 'rxnReferences',cell(0,0);... -0088 'rxnConfidenceScores',cell(0,0);... -0089 'metComps',cell(0,0);... %Changed to double in the end. -0090 'inchis',cell(0,0);... -0091 'metSmiles',cell(0,0);... -0092 'metFormulas',cell(0,0);... -0093 'metMiriams',cell(0,0);... -0094 'metDeltaG',{};... %Changed to double in the end. -0095 'metCharges',cell(0,0);... %Changed to double in the end. -0096 'metNotes',cell(0,0);... -0097 'comps',cell(0,0);... -0098 'compNames',cell(0,0);... -0099 'compOutside',cell(0,0);... -0100 'geneComps',cell(0,0);... %Changed to double in the end. -0101 'geneMiriams',cell(0,0);... -0102 'geneShortNames',cell(0,0);... -0103 'proteins',cell(0,0);... -0104 'unconstrained',cell(0,0);... %Changed to double in the end. -0105 'metFrom',cell(0,0);... -0106 'rxnFrom',cell(0,0)}; -0107 for i=1:size(modelFields,1) -0108 model.(modelFields{i,1})=modelFields{i,2}; -0109 end -0110 -0111 % If GECKO model -0112 if any(contains(line_key,'geckoLight')) -0113 isGECKO=true; -0114 ecFields = {'geckoLight', false;... -0115 'rxns', {};... -0116 'kcat', {};... -0117 'source', cell(0,0);... -0118 'notes', cell(0,0);... -0119 'eccodes', cell(0,0);... -0120 'genes', cell(0,0);... -0121 'enzymes', cell(0,0);... -0122 'mw', cell(0,0);... -0123 'sequence', cell(0,0);... -0124 'concs', cell(0,0);... -0125 'rxnEnzMat', []}; -0126 for i=1:size(ecFields,1) -0127 model.ec.(ecFields{i,1})=ecFields{i,2}; -0128 end -0129 ecGecko=cell(25000,2); ecGeckoNo=1; -0130 enzStoich=cell(100000,3); enzStoichNo=1; -0131 else -0132 isGECKO=false; -0133 end -0134 -0135 section = 0; -0136 metMiriams=cell(100000,3); metMirNo=1; -0137 rxnMiriams=cell(100000,3); rxnMirNo=1; -0138 geneMiriams=cell(100000,3); genMirNo=1; -0139 subSystems=cell(100000,2); subSysNo=1; -0140 eccodes=cell(100000,2); ecCodeNo=1; -0141 equations=cell(100000,3); equatiNo=1; -0142 -0143 for i=1:numel(line_key) -0144 tline_raw = line_raw{i}; -0145 tline_key = line_key{i}; -0146 tline_value = line_value{i}; -0147 % import different sections -0148 switch tline_raw -0149 case '- metaData:' -0150 section = 1; -0151 if verbose -0152 fprintf('\t%d\n', section); -0153 end -0154 continue % Go to next line -0155 case '- metabolites:' -0156 section = 2; -0157 if verbose -0158 fprintf('\t%d\n', section); -0159 end -0160 pos=0; -0161 continue -0162 case '- reactions:' -0163 section = 3; -0164 if verbose -0165 fprintf('\t%d\n', section); -0166 end -0167 pos=0; -0168 continue -0169 case '- genes:' -0170 section = 4; -0171 if verbose -0172 fprintf('\t%d\n', section); -0173 end -0174 pos=0; -0175 continue -0176 case '- compartments: !!omap' -0177 section = 5; -0178 if verbose -0179 fprintf('\t%d\n', section); -0180 end -0181 pos=0; -0182 continue -0183 case '- ec-rxns:' -0184 section = 6; -0185 if verbose -0186 fprintf('\t%d\n', section); -0187 end -0188 pos=0; -0189 continue -0190 case '- ec-enzymes:' -0191 section = 7; -0192 if verbose -0193 fprintf('\t%d\n', section); -0194 end -0195 pos=0; -0196 continue -0197 end -0198 -0199 % skip over empty keys -0200 if isempty(tline_raw) || (isempty(tline_key) && contains(tline_raw,'!!omap')) -0201 continue; -0202 end -0203 -0204 % import metaData -0205 if section == 1 -0206 switch tline_key -0207 case {'short_name','id'} %short_name used by human-GEM -0208 model.id = tline_value; -0209 case 'name' -0210 model.name = tline_value; -0211 case 'full_name' %used by human-GEM -0212 model.description = tline_value; -0213 case 'version' -0214 model.version = tline_value; -0215 case 'date' -0216 model.date = tline_value; -0217 case 'taxonomy' -0218 model.annotation.taxonomy = tline_value; -0219 case {'description','note'} %description used by human-GEM -0220 model.annotation.note = tline_value; -0221 case 'github' -0222 model.annotation.sourceUrl = tline_value; -0223 case 'givenName' -0224 model.annotation.givenName = tline_value; -0225 case 'familyName' -0226 model.annotation.familyName = tline_value; -0227 case 'authors' -0228 model.annotation.authorList = tline_value; -0229 case 'email' -0230 model.annotation.email = tline_value; -0231 case 'organization' -0232 model.annotation.organization = tline_value; -0233 case 'geckoLight' -0234 if strcmp(tline_value,'true') -0235 model.ec.geckoLight = true; -0236 end -0237 end; continue -0238 end -0239 -0240 % import metabolites: -0241 if section == 2 -0242 switch tline_key -0243 case 'id' -0244 pos = pos + 1; -0245 model = readFieldValue(model, 'mets', tline_value,pos); -0246 readList=''; miriamKey=''; -0247 case 'name' -0248 model = readFieldValue(model, 'metNames', tline_value, pos); -0249 readList=''; miriamKey=''; -0250 case 'compartment' -0251 model = readFieldValue(model, 'metComps', tline_value, pos); -0252 readList=''; miriamKey=''; -0253 case 'formula' -0254 model = readFieldValue(model, 'metFormulas', tline_value, pos); -0255 readList=''; miriamKey=''; -0256 case 'charge' -0257 model = readFieldValue(model, 'metCharges', tline_value, pos); -0258 readList=''; miriamKey=''; -0259 case 'notes' -0260 model = readFieldValue(model, 'metNotes', tline_value, pos); -0261 readList=''; miriamKey=''; -0262 case 'inchis' -0263 model = readFieldValue(model, 'inchis', tline_value, pos); -0264 readList=''; miriamKey=''; -0265 case 'smiles' -0266 model = readFieldValue(model, 'metSmiles', tline_value, pos); -0267 readList=''; miriamKey=''; -0268 case 'deltaG' -0269 model = readFieldValue(model, 'metDeltaG', tline_value, pos); -0270 readList=''; miriamKey=''; -0271 case 'metFrom' -0272 model = readFieldValue(model, 'metFrom', tline_value, pos); -0273 readList=''; miriamKey=''; -0274 case 'annotation' -0275 readList = 'annotation'; -0276 otherwise -0277 switch readList -0278 case 'annotation' -0279 [metMiriams, miriamKey] = gatherAnnotation(pos,metMiriams,tline_key,tline_value,miriamKey,metMirNo); -0280 metMirNo = metMirNo + 1; -0281 otherwise -0282 error(['Unknown entry in yaml file: ' tline_raw]) -0283 end -0284 end; continue -0285 end -0286 -0287 % import reactions: -0288 if section == 3 -0289 switch tline_key -0290 case 'id' -0291 pos = pos + 1; -0292 model = readFieldValue(model, 'rxns', tline_value,pos); -0293 readList=''; miriamKey=''; -0294 case 'name' -0295 model = readFieldValue(model, 'rxnNames', tline_value, pos); +0062 line_value(strcmp(line_value,line_raw)) = {''}; +0063 +0064 modelFields = {'id',char();... +0065 'name',char();... +0066 'description',char();... +0067 'version',char();... +0068 'date',char();... +0069 'annotation',struct();... +0070 'rxns',{};... +0071 'rxnNames',{};... +0072 'mets',{};... +0073 'metNames',{};... +0074 'S',sparse([]);... +0075 'lb',{};... %Changed to double in the end. +0076 'ub',{};... %Changed to double in the end. +0077 'rev',{};... %Changed to double in the end. +0078 'c',[];... +0079 'b',cell(0,0);... %Changed to double in the end. +0080 'genes',cell(0,0);... +0081 'grRules',cell(0,0);... +0082 'rxnGeneMat',sparse([]);... +0083 'rxnComps',cell(0,0);... %Changed to double in the end. +0084 'subSystems',cell(0,0);... +0085 'eccodes',cell(0,0);... +0086 'rxnMiriams',cell(0,0);... +0087 'rxnDeltaG',{};... %Changed to double in the end. +0088 'rxnNotes',cell(0,0);... +0089 'rxnReferences',cell(0,0);... +0090 'rxnConfidenceScores',cell(0,0);... +0091 'metComps',cell(0,0);... %Changed to double in the end. +0092 'inchis',cell(0,0);... +0093 'metSmiles',cell(0,0);... +0094 'metFormulas',cell(0,0);... +0095 'metMiriams',cell(0,0);... +0096 'metDeltaG',{};... %Changed to double in the end. +0097 'metCharges',cell(0,0);... %Changed to double in the end. +0098 'metNotes',cell(0,0);... +0099 'comps',cell(0,0);... +0100 'compNames',cell(0,0);... +0101 'compOutside',cell(0,0);... +0102 'geneComps',cell(0,0);... %Changed to double in the end. +0103 'geneMiriams',cell(0,0);... +0104 'geneShortNames',cell(0,0);... +0105 'proteins',cell(0,0);... +0106 'unconstrained',cell(0,0);... %Changed to double in the end. +0107 'metFrom',cell(0,0);... +0108 'rxnFrom',cell(0,0)}; +0109 for i=1:size(modelFields,1) +0110 model.(modelFields{i,1})=modelFields{i,2}; +0111 end +0112 +0113 % If GECKO model +0114 if any(contains(line_key,'geckoLight')) +0115 isGECKO=true; +0116 ecFields = {'geckoLight', false;... +0117 'rxns', {};... +0118 'kcat', {};... +0119 'source', cell(0,0);... +0120 'notes', cell(0,0);... +0121 'eccodes', cell(0,0);... +0122 'genes', cell(0,0);... +0123 'enzymes', cell(0,0);... +0124 'mw', cell(0,0);... +0125 'sequence', cell(0,0);... +0126 'concs', cell(0,0);... +0127 'rxnEnzMat', []}; +0128 for i=1:size(ecFields,1) +0129 model.ec.(ecFields{i,1})=ecFields{i,2}; +0130 end +0131 ecGecko=cell(25000,2); ecGeckoNo=1; +0132 enzStoich=cell(100000,3); enzStoichNo=1; +0133 else +0134 isGECKO=false; +0135 end +0136 +0137 section = 0; +0138 metMiriams=cell(100000,3); metMirNo=1; +0139 rxnMiriams=cell(100000,3); rxnMirNo=1; +0140 geneMiriams=cell(100000,3); genMirNo=1; +0141 subSystems=cell(100000,2); subSysNo=1; +0142 eccodes=cell(100000,2); ecCodeNo=1; +0143 equations=cell(100000,3); equatiNo=1; +0144 +0145 for i=1:numel(line_key) +0146 tline_raw = line_raw{i}; +0147 tline_key = line_key{i}; +0148 tline_value = line_value{i}; +0149 % import different sections +0150 switch tline_raw +0151 case '- metaData:' +0152 section = 1; +0153 if verbose +0154 fprintf('\t%d\n', section); +0155 end +0156 continue % Go to next line +0157 case '- metabolites:' +0158 section = 2; +0159 if verbose +0160 fprintf('\t%d\n', section); +0161 end +0162 pos=0; +0163 continue +0164 case '- reactions:' +0165 section = 3; +0166 if verbose +0167 fprintf('\t%d\n', section); +0168 end +0169 pos=0; +0170 continue +0171 case '- genes:' +0172 section = 4; +0173 if verbose +0174 fprintf('\t%d\n', section); +0175 end +0176 pos=0; +0177 continue +0178 case '- compartments: !!omap' +0179 section = 5; +0180 if verbose +0181 fprintf('\t%d\n', section); +0182 end +0183 pos=0; +0184 continue +0185 case '- ec-rxns:' +0186 section = 6; +0187 if verbose +0188 fprintf('\t%d\n', section); +0189 end +0190 pos=0; +0191 continue +0192 case '- ec-enzymes:' +0193 section = 7; +0194 if verbose +0195 fprintf('\t%d\n', section); +0196 end +0197 pos=0; +0198 continue +0199 end +0200 +0201 % skip over empty keys +0202 if isempty(tline_raw) || (isempty(tline_key) && contains(tline_raw,'!!omap')) +0203 continue; +0204 end +0205 +0206 % import metaData +0207 if section == 1 +0208 switch tline_key +0209 case {'short_name','id'} %short_name used by human-GEM +0210 model.id = tline_value; +0211 case 'name' +0212 model.name = tline_value; +0213 case 'full_name' %used by human-GEM +0214 model.description = tline_value; +0215 case 'version' +0216 model.version = tline_value; +0217 case 'date' +0218 model.date = tline_value; +0219 case 'taxonomy' +0220 model.annotation.taxonomy = tline_value; +0221 case {'description','note'} %description used by human-GEM +0222 model.annotation.note = tline_value; +0223 case 'github' +0224 model.annotation.sourceUrl = tline_value; +0225 case 'sourceUrl' +0226 model.annotation.sourceUrl = tline_value; +0227 case 'givenName' +0228 model.annotation.givenName = tline_value; +0229 case 'familyName' +0230 model.annotation.familyName = tline_value; +0231 case 'authors' +0232 model.annotation.authorList = tline_value; +0233 case 'email' +0234 model.annotation.email = tline_value; +0235 case 'organization' +0236 model.annotation.organization = tline_value; +0237 case 'geckoLight' +0238 if strcmp(tline_value,'true') +0239 model.ec.geckoLight = true; +0240 end +0241 end; continue +0242 end +0243 +0244 % import metabolites: +0245 if section == 2 +0246 switch tline_key +0247 case 'id' +0248 pos = pos + 1; +0249 model = readFieldValue(model, 'mets', tline_value,pos); +0250 readList=''; miriamKey=''; +0251 case 'name' +0252 model = readFieldValue(model, 'metNames', tline_value, pos); +0253 readList=''; miriamKey=''; +0254 case 'compartment' +0255 model = readFieldValue(model, 'metComps', tline_value, pos); +0256 readList=''; miriamKey=''; +0257 case 'formula' +0258 model = readFieldValue(model, 'metFormulas', tline_value, pos); +0259 readList=''; miriamKey=''; +0260 case 'charge' +0261 model = readFieldValue(model, 'metCharges', tline_value, pos); +0262 readList=''; miriamKey=''; +0263 case 'notes' +0264 model = readFieldValue(model, 'metNotes', tline_value, pos); +0265 readList=''; miriamKey=''; +0266 case 'inchis' +0267 model = readFieldValue(model, 'inchis', tline_value, pos); +0268 readList=''; miriamKey=''; +0269 case 'smiles' +0270 model = readFieldValue(model, 'metSmiles', tline_value, pos); +0271 readList=''; miriamKey=''; +0272 case 'deltaG' +0273 model = readFieldValue(model, 'metDeltaG', tline_value, pos); +0274 readList=''; miriamKey=''; +0275 case 'metFrom' +0276 model = readFieldValue(model, 'metFrom', tline_value, pos); +0277 readList=''; miriamKey=''; +0278 case 'annotation' +0279 readList = 'annotation'; +0280 otherwise +0281 switch readList +0282 case 'annotation' +0283 [metMiriams, miriamKey, metMirNo] = gatherAnnotation(pos,metMiriams,tline_key,tline_value,miriamKey,metMirNo); +0284 otherwise +0285 error(['Unknown entry in yaml file: ' tline_raw]) +0286 end +0287 end; continue +0288 end +0289 +0290 % import reactions: +0291 if section == 3 +0292 switch tline_key +0293 case 'id' +0294 pos = pos + 1; +0295 model = readFieldValue(model, 'rxns', tline_value,pos); 0296 readList=''; miriamKey=''; -0297 case 'lower_bound' -0298 model.lb(pos,1) = {tline_value}; +0297 case 'name' +0298 model = readFieldValue(model, 'rxnNames', tline_value, pos); 0299 readList=''; miriamKey=''; -0300 case 'upper_bound' -0301 model.ub(pos,1) = {tline_value}; +0300 case 'lower_bound' +0301 model.lb(pos,1) = {tline_value}; 0302 readList=''; miriamKey=''; -0303 case 'rev' -0304 model.rev(pos,1) = {tline_value}; +0303 case 'upper_bound' +0304 model.ub(pos,1) = {tline_value}; 0305 readList=''; miriamKey=''; -0306 case 'gene_reaction_rule' -0307 model = readFieldValue(model, 'grRules', tline_value, pos); +0306 case 'rev' +0307 model.rev(pos,1) = {tline_value}; 0308 readList=''; miriamKey=''; -0309 case 'rxnNotes' -0310 model = readFieldValue(model, 'rxnNotes', tline_value, pos); +0309 case 'gene_reaction_rule' +0310 model = readFieldValue(model, 'grRules', tline_value, pos); 0311 readList=''; miriamKey=''; -0312 case 'rxnFrom' -0313 model = readFieldValue(model, 'rxnFrom', tline_value, pos); +0312 case 'rxnNotes' +0313 model = readFieldValue(model, 'rxnNotes', tline_value, pos); 0314 readList=''; miriamKey=''; -0315 case 'deltaG' -0316 model = readFieldValue(model, 'rxnDeltaG', tline_value, pos); -0317 readList=''; miriamKey=''; -0318 case 'objective_coefficient' -0319 model.c(pos,1) = 1; -0320 readList=''; miriamKey=''; -0321 case 'references' -0322 model = readFieldValue(model, 'rxnReferences', tline_value, pos); +0315 case 'rxnFrom' +0316 model = readFieldValue(model, 'rxnFrom', tline_value, pos); +0317 readList=''; miriamKey=''; +0318 case 'deltaG' +0319 model = readFieldValue(model, 'rxnDeltaG', tline_value, pos); +0320 readList=''; miriamKey=''; +0321 case 'objective_coefficient' +0322 model.c(pos,1) = 1; 0323 readList=''; miriamKey=''; -0324 case 'confidence_score' -0325 model = readFieldValue(model, 'rxnConfidenceScores', tline_value, pos); +0324 case 'references' +0325 model = readFieldValue(model, 'rxnReferences', tline_value, pos); 0326 readList=''; miriamKey=''; -0327 case 'eccodes' -0328 if isempty(tline_value) -0329 readList = 'eccodes'; -0330 else -0331 eccodes(ecCodeNo,1:2)={pos,tline_value}; -0332 ecCodeNo=ecCodeNo+1; -0333 end -0334 case 'subsystem' -0335 if isempty(tline_value) -0336 readList = 'subsystem'; -0337 else -0338 subSystems(subSysNo,1:2)={pos,tline_value}; -0339 subSysNo=subSysNo+1; -0340 end -0341 case 'metabolites' -0342 readList = 'equation'; -0343 case 'annotation' -0344 readList = 'annotation'; -0345 -0346 otherwise -0347 switch readList -0348 case 'eccodes' -0349 eccodes(ecCodeNo,1:2)={pos,regexprep(tline_value,'^ +- "?(.*)"?$','$1')}; -0350 ecCodeNo=ecCodeNo+1; -0351 case 'subsystem' -0352 subSystems(subSysNo,1:2)={pos,regexprep(tline_value,'^ +- "?(.*)"?$','$1')}; -0353 subSysNo=subSysNo+1; -0354 case 'annotation' -0355 [rxnMiriams, miriamKey,rxnMirNo] = gatherAnnotation(pos,rxnMiriams,tline_key,tline_value,miriamKey,rxnMirNo); -0356 rxnMirNo=rxnMirNo+1; -0357 case 'equation' -0358 coeff = sscanf(tline_value,'%f'); -0359 equations(equatiNo,1:3)={pos,tline_key,coeff}; -0360 equatiNo=equatiNo+1; -0361 otherwise -0362 error(['Unknown entry in yaml file: ' tline_raw]) -0363 end -0364 end; continue -0365 end -0366 -0367 % import genes: -0368 if section == 4 -0369 switch tline_key -0370 case 'id' -0371 pos = pos + 1; -0372 model = readFieldValue(model, 'genes', tline_value, pos); -0373 readList = ''; -0374 miriamKey = ''; -0375 case 'name' -0376 model = readFieldValue(model, 'geneShortNames', tline_value, pos); -0377 case 'protein' -0378 model = readFieldValue(model, 'proteins', tline_value, pos); -0379 case 'annotation' -0380 readList = 'annotation'; -0381 otherwise -0382 switch readList -0383 case 'annotation' -0384 [geneMiriams, miriamKey] = gatherAnnotation(pos,geneMiriams,tline_key,tline_value,miriamKey,genMirNo); -0385 genMirNo = genMirNo + 1; -0386 otherwise -0387 error(['Unknown entry in yaml file: ' tline_raw]) -0388 end -0389 end; continue -0390 end -0391 -0392 % import compartments: -0393 if section == 5 -0394 model.comps(end+1,1) = {tline_key}; -0395 model.compNames(end+1,1) = {tline_value}; -0396 end -0397 -0398 % import ec reaction info -0399 if section == 6 -0400 switch tline_key -0401 case 'id' -0402 pos = pos + 1; -0403 model.ec = readFieldValue(model.ec, 'rxns', tline_value, pos); -0404 readList=''; -0405 case 'kcat' -0406 model.ec = readFieldValue(model.ec, 'kcat', tline_value, pos); -0407 readList=''; -0408 case 'source' -0409 model.ec = readFieldValue(model.ec, 'source', tline_value, pos); -0410 readList=''; -0411 case 'notes' -0412 model.ec = readFieldValue(model.ec, 'notes', tline_value, pos); -0413 readList=''; -0414 case 'eccodes' -0415 if isempty(tline_value) -0416 readList = 'eccodes'; -0417 else -0418 ecGecko(ecGeckoNo,1:2)={pos,tline_value}; -0419 ecGeckoNo=ecGeckoNo+1; -0420 end -0421 case 'enzymes' -0422 readList = 'enzStoich'; -0423 otherwise -0424 switch readList -0425 case 'eccodes' -0426 ecGecko(ecGeckoNo,1:2)={pos,regexprep(tline_value,'^ +- "?(.*)"?$','$1')}; -0427 ecGeckoNo=ecGeckoNo+1; -0428 case 'enzStoich' -0429 coeff = sscanf(tline_value,'%f'); -0430 enzStoich(enzStoichNo,1:3)={pos,tline_key,coeff}; -0431 enzStoichNo=enzStoichNo+1; -0432 otherwise -0433 error(['Unknown entry in yaml file: ' tline_raw]) -0434 end -0435 end; continue -0436 end -0437 -0438 % import ec enzyme info -0439 if section == 7 -0440 switch tline_key -0441 case 'genes' -0442 pos = pos + 1; -0443 model.ec = readFieldValue(model.ec, 'genes', tline_value, pos); -0444 case 'enzymes' -0445 model.ec = readFieldValue(model.ec, 'enzymes', tline_value, pos); -0446 case 'mw' -0447 model.ec = readFieldValue(model.ec, 'mw', tline_value, pos); -0448 case 'sequence' -0449 model.ec = readFieldValue(model.ec, 'sequence', tline_value, pos); -0450 case 'concs' -0451 model.ec = readFieldValue(model.ec, 'concs', tline_value, pos); -0452 otherwise -0453 error(['Unknown entry in yaml file: ' tline_raw]) -0454 end; continue -0455 end -0456 end -0457 -0458 %Parse annotations -0459 if ~isempty(metMiriams) -0460 locs = cell2mat(metMiriams(:,1)); -0461 for i=unique(locs)' -0462 model.metMiriams{i,1}.name=metMiriams(locs==i,2); -0463 model.metMiriams{i,1}.value=metMiriams(locs==i,3); -0464 end -0465 end -0466 if ~isempty(rxnMiriams) -0467 locs = cell2mat(rxnMiriams(:,1)); -0468 for i=unique(locs)' -0469 model.rxnMiriams{i,1}.name=rxnMiriams(locs==i,2); -0470 model.rxnMiriams{i,1}.value=rxnMiriams(locs==i,3); -0471 end -0472 end -0473 if ~isempty(geneMiriams) -0474 locs = cell2mat(geneMiriams(:,1)); -0475 for i=unique(locs)' -0476 model.geneMiriams{i,1}.name=geneMiriams(locs==i,2); -0477 model.geneMiriams{i,1}.value=geneMiriams(locs==i,3); -0478 end -0479 end -0480 -0481 %Parse subSystems -0482 if ~isempty(subSystems) -0483 locs = cell2mat(subSystems(:,1)); -0484 for i=unique(locs)' -0485 model.subSystems{i,1}=subSystems(locs==i,2); -0486 end -0487 end -0488 -0489 %Parse ec-codes -0490 if ~isempty(eccodes) -0491 locs = cell2mat(eccodes(:,1)); -0492 for i=unique(locs)' -0493 eccodesCat=strjoin(eccodes(locs==i,2),';'); -0494 model.eccodes{i,1}=eccodesCat; -0495 end -0496 emptyEc=cellfun('isempty',model.eccodes); -0497 model.eccodes(emptyEc)={''}; -0498 end -0499 -0500 % follow-up data processing -0501 if verbose -0502 fprintf('\nimporting completed\nfollow-up processing...'); -0503 end -0504 [~, model.metComps] = ismember(model.metComps, model.comps); -0505 [~, model.geneComps] = ismember(model.geneComps, model.comps); -0506 [~, model.rxnComps] = ismember(model.rxnComps, model.comps); -0507 -0508 % Fill S-matrix -0509 rxnIdx = cellfun('isempty', equations(:,1)); -0510 equations(rxnIdx,:) = ''; -0511 rxnIdx = cell2mat(equations(:,1)); -0512 [~,metIdx] = ismember(equations(:,2),model.mets); -0513 coeffs = cell2mat(equations(:,3)); -0514 model.S=sparse(max(metIdx),max(rxnIdx)); -0515 linearIndices = sub2ind([max(metIdx), max(rxnIdx)],metIdx,rxnIdx); -0516 model.S(linearIndices) = coeffs; -0517 -0518 % Convert strings to numeric -0519 model.metCharges = str2double(model.metCharges); -0520 model.lb = str2double(model.lb); -0521 model.ub = str2double(model.ub); -0522 model.rxnConfidenceScores = str2double(model.rxnConfidenceScores); -0523 model.b = zeros(length(model.mets),1); -0524 model.metDeltaG = str2double(model.metDeltaG); -0525 model.rxnDeltaG = str2double(model.rxnDeltaG); -0526 -0527 % Fill some other fields -0528 model.annotation.defaultLB = min(model.lb); -0529 model.annotation.defaultUB = max(model.ub); -0530 if numel(model.lb)<numel(model.rxns) %No LB reported = min -0531 model.lb(end+1:numel(model.rxns)-numel(model.lb),1) = double(model.annotation.defaultLB); -0532 end -0533 if numel(model.ub)<numel(model.rxns) %No UB reported = max -0534 model.ub(end+1:numel(model.rxns)-numel(model.ub),1) = double(model.annotation.defaultUB); -0535 end -0536 if ~all(cellfun('isempty',model.rev)) -0537 model.rev = str2double(model.rev); -0538 else -0539 model.rev = []; -0540 end -0541 if numel(model.rev)<numel(model.rxns) %No rev reported, assume from LB and UB -0542 model.rev(end+1:numel(model.rxns)-numel(model.rev),1) = double(model.lb<0 & model.ub>0); -0543 end -0544 -0545 % Remove empty fields, otherwise fill to correct length -0546 % Reactions -0547 for i={'rxnNames','grRules','eccodes','rxnNotes','rxnReferences',... -0548 'rxnFrom','subSystems','rxnMiriams'} % Empty strings -0549 model = emptyOrFill(model,i{1},{''},'rxns'); -0550 end -0551 for i={'c'} % Zeros -0552 model = emptyOrFill(model,i{1},0,'rxns',true); -0553 end -0554 for i={'rxnConfidenceScores','rxnDeltaG'} % NaNs -0555 model = emptyOrFill(model,i{1},NaN,'rxns'); -0556 end -0557 for i={'rxnComps'} % Ones, assume first compartment -0558 model = emptyOrFill(model,i{1},1,'rxns'); -0559 end -0560 % Metabolites -0561 for i={'metNames','inchis','metFormulas','metMiriams','metFrom','metSmiles','metNotes'} % Empty strings -0562 model = emptyOrFill(model,i{1},{''},'mets'); -0563 end -0564 for i={'metCharges','unconstrained'} % Zeros -0565 model = emptyOrFill(model,i{1},0,'mets'); -0566 end -0567 for i={'metDeltaG'} % % NaNs -0568 model = emptyOrFill(model,i{1},NaN,'mets'); -0569 end -0570 for i={'metComps'} % Ones, assume first compartment -0571 model = emptyOrFill(model,i{1},1,'mets'); -0572 end -0573 % Genes -0574 for i={'geneMiriams','geneShortNames','proteins'} % Empty strings -0575 model = emptyOrFill(model,i{1},{''},'genes'); -0576 end -0577 for i={'geneComps'} % Ones, assume first compartment -0578 model = emptyOrFill(model,i{1},1,'genes'); -0579 end -0580 % Comps -0581 for i={'compNames'} % Empty strings -0582 model = emptyOrFill(model,i{1},{''},'comps'); -0583 end -0584 for i={'compOutside'} % First comp -0585 model = emptyOrFill(model,i{1},model.comps{1},'comps'); -0586 end -0587 % Single fields are kept, even if empty -0588 % for i={'description','name','version','date','annotation'} -0589 % if isempty(model.(i{1})) -0590 % model = rmfield(model,i{1}); -0591 % end -0592 % end -0593 -0594 % Make rxnGeneMat fields and map to the existing model.genes field -0595 [genes, rxnGeneMat] = getGenesFromGrRules(model.grRules); -0596 model.rxnGeneMat = sparse(numel(model.rxns),numel(model.genes)); -0597 [~,geneOrder] = ismember(genes,model.genes); -0598 if any(geneOrder == 0) -0599 error(['The grRules includes the following gene(s), that are not in '... -0600 'the list of model genes: ', genes{~geneOrder}]) -0601 end -0602 model.rxnGeneMat(:,geneOrder) = rxnGeneMat; -0603 -0604 % Finalize GECKO model -0605 if isGECKO -0606 % Fill in empty fields and empty entries -0607 for i={'kcat','source','notes','eccodes'} % Even keep empty -0608 model.ec = emptyOrFill(model.ec,i{1},{''},'rxns',true); -0609 end -0610 for i={'enzymes','mw','sequence'} -0611 model.ec = emptyOrFill(model.ec,i{1},{''},'genes',true); -0612 end -0613 model.ec = emptyOrFill(model.ec,'concs',{'NaN'},'genes',true); -0614 model.ec = emptyOrFill(model.ec,'kcat',{'0'},'genes',true); -0615 % Change string to double -0616 for i={'kcat','mw','concs'} -0617 if isfield(model.ec,i{1}) -0618 model.ec.(i{1}) = str2double(model.ec.(i{1})); -0619 end -0620 end -0621 % Fill rxnEnzMat -0622 rxnIdx = cellfun('isempty', enzStoich(:,1)); -0623 enzStoich(rxnIdx,:) = ''; -0624 rxnIdx = cell2mat(enzStoich(:,1)); -0625 [~,enzIdx] = ismember(enzStoich(:,2),model.ec.enzymes); -0626 coeffs = cell2mat(enzStoich(:,3)); -0627 model.ec.rxnEnzMat = zeros(numel(model.ec.rxns), numel(model.ec.genes)); -0628 linearIndices = sub2ind([numel(model.ec.rxns), numel(model.ec.genes)], rxnIdx, enzIdx); -0629 model.ec.rxnEnzMat(linearIndices) = coeffs; -0630 %Parse ec-codes -0631 if ~isempty(ecGecko) -0632 locs = cell2mat(ecGecko(:,1)); -0633 for i=unique(locs)' -0634 ecGeckoCat=strjoin(ecGecko(locs==i,2),';'); -0635 model.ec.eccodes{i,1}=ecGeckoCat; -0636 end -0637 emptyEc=cellfun('isempty',model.ec.eccodes); -0638 model.ec.eccodes(emptyEc)={''}; -0639 end -0640 end -0641 -0642 if verbose -0643 fprintf(' Done!\n'); -0644 end +0327 case 'confidence_score' +0328 model = readFieldValue(model, 'rxnConfidenceScores', tline_value, pos); +0329 readList=''; miriamKey=''; +0330 case 'eccodes' +0331 if isempty(tline_value) +0332 readList = 'eccodes'; +0333 else +0334 eccodes(ecCodeNo,1:2)={pos,tline_value}; +0335 ecCodeNo=ecCodeNo+1; +0336 end +0337 case 'subsystem' +0338 if isempty(tline_value) +0339 readList = 'subsystem'; +0340 else +0341 subSystems(subSysNo,1:2)={pos,tline_value}; +0342 subSysNo=subSysNo+1; +0343 end +0344 case 'metabolites' +0345 readList = 'equation'; +0346 case 'annotation' +0347 readList = 'annotation'; +0348 +0349 otherwise +0350 switch readList +0351 case 'eccodes' +0352 eccodes(ecCodeNo,1:2)={pos,regexprep(tline_value,'^ +- "?(.*)"?$','$1')}; +0353 ecCodeNo=ecCodeNo+1; +0354 case 'subsystem' +0355 subSystems(subSysNo,1:2)={pos,regexprep(tline_value,'^ +- "?(.*)"?$','$1')}; +0356 subSysNo=subSysNo+1; +0357 case 'annotation' +0358 [rxnMiriams, miriamKey,rxnMirNo] = gatherAnnotation(pos,rxnMiriams,tline_key,tline_value,miriamKey,rxnMirNo); +0359 case 'equation' +0360 coeff = sscanf(tline_value,'%f'); +0361 equations(equatiNo,1:3)={pos,tline_key,coeff}; +0362 equatiNo=equatiNo+1; +0363 otherwise +0364 error(['Unknown entry in yaml file: ' tline_raw]) +0365 end +0366 end; continue +0367 end +0368 +0369 % import genes: +0370 if section == 4 +0371 switch tline_key +0372 case 'id' +0373 pos = pos + 1; +0374 model = readFieldValue(model, 'genes', tline_value, pos); +0375 readList = ''; +0376 miriamKey = ''; +0377 case 'name' +0378 model = readFieldValue(model, 'geneShortNames', tline_value, pos); +0379 case 'protein' +0380 model = readFieldValue(model, 'proteins', tline_value, pos); +0381 case 'annotation' +0382 readList = 'annotation'; +0383 otherwise +0384 switch readList +0385 case 'annotation' +0386 [geneMiriams, miriamKey,genMirNo] = gatherAnnotation(pos,geneMiriams,tline_key,tline_value,miriamKey,genMirNo); +0387 otherwise +0388 error(['Unknown entry in yaml file: ' tline_raw]) +0389 end +0390 end; continue +0391 end +0392 +0393 % import compartments: +0394 if section == 5 +0395 model.comps(end+1,1) = {tline_key}; +0396 model.compNames(end+1,1) = {tline_value}; +0397 end +0398 +0399 % import ec reaction info +0400 if section == 6 +0401 switch tline_key +0402 case 'id' +0403 pos = pos + 1; +0404 model.ec = readFieldValue(model.ec, 'rxns', tline_value, pos); +0405 readList=''; +0406 case 'kcat' +0407 model.ec = readFieldValue(model.ec, 'kcat', tline_value, pos); +0408 readList=''; +0409 case 'source' +0410 model.ec = readFieldValue(model.ec, 'source', tline_value, pos); +0411 readList=''; +0412 case 'notes' +0413 model.ec = readFieldValue(model.ec, 'notes', tline_value, pos); +0414 readList=''; +0415 case 'eccodes' +0416 if isempty(tline_value) +0417 readList = 'eccodes'; +0418 else +0419 ecGecko(ecGeckoNo,1:2)={pos,tline_value}; +0420 ecGeckoNo=ecGeckoNo+1; +0421 end +0422 case 'enzymes' +0423 readList = 'enzStoich'; +0424 otherwise +0425 switch readList +0426 case 'eccodes' +0427 ecGecko(ecGeckoNo,1:2)={pos,regexprep(tline_value,'^ +- "?(.*)"?$','$1')}; +0428 ecGeckoNo=ecGeckoNo+1; +0429 case 'enzStoich' +0430 coeff = sscanf(tline_value,'%f'); +0431 enzStoich(enzStoichNo,1:3)={pos,tline_key,coeff}; +0432 enzStoichNo=enzStoichNo+1; +0433 otherwise +0434 error(['Unknown entry in yaml file: ' tline_raw]) +0435 end +0436 end; continue +0437 end +0438 +0439 % import ec enzyme info +0440 if section == 7 +0441 switch tline_key +0442 case 'genes' +0443 pos = pos + 1; +0444 model.ec = readFieldValue(model.ec, 'genes', tline_value, pos); +0445 case 'enzymes' +0446 model.ec = readFieldValue(model.ec, 'enzymes', tline_value, pos); +0447 case 'mw' +0448 model.ec = readFieldValue(model.ec, 'mw', tline_value, pos); +0449 case 'sequence' +0450 model.ec = readFieldValue(model.ec, 'sequence', tline_value, pos); +0451 case 'concs' +0452 model.ec = readFieldValue(model.ec, 'concs', tline_value, pos); +0453 otherwise +0454 error(['Unknown entry in yaml file: ' tline_raw]) +0455 end; continue +0456 end +0457 end +0458 +0459 %Parse annotations +0460 if ~isempty(metMiriams) +0461 locs = cell2mat(metMiriams(:,1)); +0462 for i=unique(locs)' +0463 model.metMiriams{i,1}.name=metMiriams(locs==i,2); +0464 model.metMiriams{i,1}.value=metMiriams(locs==i,3); +0465 end +0466 end +0467 if ~isempty(rxnMiriams) +0468 locs = cell2mat(rxnMiriams(:,1)); +0469 for i=unique(locs)' +0470 model.rxnMiriams{i,1}.name=rxnMiriams(locs==i,2); +0471 model.rxnMiriams{i,1}.value=rxnMiriams(locs==i,3); +0472 end +0473 end +0474 if ~isempty(geneMiriams) +0475 locs = cell2mat(geneMiriams(:,1)); +0476 for i=unique(locs)' +0477 model.geneMiriams{i,1}.name=geneMiriams(locs==i,2); +0478 model.geneMiriams{i,1}.value=geneMiriams(locs==i,3); +0479 end +0480 end +0481 +0482 %Parse subSystems +0483 if ~isempty(subSystems) +0484 locs = cell2mat(subSystems(:,1)); +0485 for i=unique(locs)' +0486 model.subSystems{i,1}=subSystems(locs==i,2); +0487 end +0488 end +0489 +0490 %Parse ec-codes +0491 if ~isempty(eccodes) +0492 locs = cell2mat(eccodes(:,1)); +0493 for i=unique(locs)' +0494 eccodesCat=strjoin(eccodes(locs==i,2),';'); +0495 model.eccodes{i,1}=eccodesCat; +0496 end +0497 emptyEc=cellfun('isempty',model.eccodes); +0498 model.eccodes(emptyEc)={''}; +0499 end +0500 +0501 % follow-up data processing +0502 if verbose +0503 fprintf('\nimporting completed\nfollow-up processing...'); +0504 end +0505 [~, model.metComps] = ismember(model.metComps, model.comps); +0506 [~, model.geneComps] = ismember(model.geneComps, model.comps); +0507 [~, model.rxnComps] = ismember(model.rxnComps, model.comps); +0508 +0509 % Fill S-matrix +0510 rxnIdx = cellfun('isempty', equations(:,1)); +0511 equations(rxnIdx,:) = ''; +0512 rxnIdx = cell2mat(equations(:,1)); +0513 [~,metIdx] = ismember(equations(:,2),model.mets); +0514 coeffs = cell2mat(equations(:,3)); +0515 model.S=sparse(max(metIdx),max(rxnIdx)); +0516 linearIndices = sub2ind([max(metIdx), max(rxnIdx)],metIdx,rxnIdx); +0517 model.S(linearIndices) = coeffs; +0518 +0519 % Convert strings to numeric +0520 model.metCharges = str2double(model.metCharges); +0521 model.lb = str2double(model.lb); +0522 model.ub = str2double(model.ub); +0523 model.rxnConfidenceScores = str2double(model.rxnConfidenceScores); +0524 model.b = zeros(length(model.mets),1); +0525 model.metDeltaG = str2double(model.metDeltaG); +0526 model.rxnDeltaG = str2double(model.rxnDeltaG); +0527 +0528 % Fill some other fields +0529 model.annotation.defaultLB = min(model.lb); +0530 model.annotation.defaultUB = max(model.ub); +0531 if numel(model.lb)<numel(model.rxns) %No LB reported = min +0532 model.lb(end+1:numel(model.rxns)-numel(model.lb),1) = double(model.annotation.defaultLB); +0533 end +0534 if numel(model.ub)<numel(model.rxns) %No UB reported = max +0535 model.ub(end+1:numel(model.rxns)-numel(model.ub),1) = double(model.annotation.defaultUB); +0536 end +0537 if ~all(cellfun('isempty',model.rev)) +0538 model.rev = str2double(model.rev); +0539 else +0540 model.rev = []; +0541 end +0542 if numel(model.rev)<numel(model.rxns) %No rev reported, assume from LB and UB +0543 model.rev(end+1:numel(model.rxns)-numel(model.rev),1) = double(model.lb<0 & model.ub>0); +0544 end +0545 +0546 % Remove empty fields, otherwise fill to correct length +0547 % Reactions +0548 for i={'rxnNames','grRules','eccodes','rxnNotes','rxnReferences',... +0549 'rxnFrom','subSystems','rxnMiriams'} % Empty strings +0550 model = emptyOrFill(model,i{1},{''},'rxns'); +0551 end +0552 for i={'c'} % Zeros +0553 model = emptyOrFill(model,i{1},0,'rxns',true); +0554 end +0555 for i={'rxnConfidenceScores','rxnDeltaG'} % NaNs +0556 model = emptyOrFill(model,i{1},NaN,'rxns'); +0557 end +0558 for i={'rxnComps'} % Ones, assume first compartment +0559 model = emptyOrFill(model,i{1},1,'rxns'); +0560 end +0561 % Metabolites +0562 for i={'metNames','inchis','metFormulas','metMiriams','metFrom','metSmiles','metNotes'} % Empty strings +0563 model = emptyOrFill(model,i{1},{''},'mets'); +0564 end +0565 for i={'metCharges','unconstrained'} % Zeros +0566 model = emptyOrFill(model,i{1},0,'mets'); +0567 end +0568 for i={'metDeltaG'} % % NaNs +0569 model = emptyOrFill(model,i{1},NaN,'mets'); +0570 end +0571 for i={'metComps'} % Ones, assume first compartment +0572 model = emptyOrFill(model,i{1},1,'mets'); +0573 end +0574 % Genes +0575 for i={'geneMiriams','geneShortNames','proteins'} % Empty strings +0576 model = emptyOrFill(model,i{1},{''},'genes'); +0577 end +0578 for i={'geneComps'} % Ones, assume first compartment +0579 model = emptyOrFill(model,i{1},1,'genes'); +0580 end +0581 % Comps +0582 for i={'compNames'} % Empty strings +0583 model = emptyOrFill(model,i{1},{''},'comps'); +0584 end +0585 for i={'compOutside'} % First comp +0586 model = emptyOrFill(model,i{1},model.comps{1},'comps'); +0587 end +0588 % Single fields are kept, even if empty +0589 % for i={'description','name','version','date','annotation'} +0590 % if isempty(model.(i{1})) +0591 % model = rmfield(model,i{1}); +0592 % 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); +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 -0647 function model = emptyOrFill(model,field,emptyEntry,type,keepEmpty) -0648 if nargin<5 -0649 keepEmpty=false; -0650 end -0651 if isnumeric(emptyEntry) -0652 emptyCells=isempty(model.(field)); -0653 else -0654 emptyCells=cellfun('isempty',model.(field)); -0655 end -0656 if all(emptyCells) && ~keepEmpty -0657 model = rmfield(model, field); -0658 elseif numel(model.(field))<numel(model.(type)) -0659 model.(field)(end+1:numel(model.(type)),1)=emptyEntry; -0660 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 -0663 function model = readFieldValue(model, fieldName, value, pos) -0664 if numel(model.(fieldName))<pos-1 -0665 model.(fieldName)(end+1:pos,1) = {''}; -0666 end -0667 model.(fieldName)(pos,1) = {value}; -0668 end -0669 -0670 function [miriams, miriamKey,entryNumber] = gatherAnnotation(pos,miriams,key,value,miriamKey,entryNumber) -0671 if isempty(key) -0672 key=miriamKey; -0673 else -0674 miriamKey=key; -0675 end -0676 if ~isempty(value) -0677 miriams(entryNumber,1:3) = {pos, key, strip(value)}; -0678 else -0679 entryNumber = entryNumber - 1; +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; +0676 end +0677 if ~isempty(value) +0678 miriams(entryNumber,1:3) = {pos, key, strip(value)}; +0679 entryNumber = entryNumber + 1; 0680 end 0681 end


    Generated by m2html © 2005
    diff --git a/doc/io/writeYAMLmodel.html b/doc/io/writeYAMLmodel.html index 8aafb9ee..d2f385a9 100644 --- a/doc/io/writeYAMLmodel.html +++ b/doc/io/writeYAMLmodel.html @@ -335,106 +335,109 @@

    SOURCE CODE ^if preserveQuotes 0277 list = ['"' list{1} '"']; 0278 end -0279 fprintf(fid,' %s: %s\n',name,list); -0280 elseif ischar(list) && strcmp(fieldName,'subSystems') -0281 if preserveQuotes -0282 list = ['"' list '"']; -0283 end -0284 fprintf(fid,' %s: %s\n',name,list); -0285 elseif length(list) > 1 || strcmp(fieldName,'subSystems') -0286 if preserveQuotes -0287 for j=1:numel(list) -0288 list{j} = ['"' list{j} '"']; -0289 end -0290 end -0291 fprintf(fid,' %s:\n',name); -0292 for i = 1:length(list) -0293 fprintf(fid,'%s - %s\n',regexprep(name,'(^\s*).*','$1'),list{i}); -0294 end -0295 end -0296 -0297 elseif sum(pos) > 0 -0298 %All other fields: -0299 if strcmp(type,'txt') -0300 value = field{pos}; -0301 if preserveQuotes && ~isempty(value) -0302 value = ['"',value,'"']; -0303 end -0304 elseif strcmp(type,'num') -0305 if isnan(field(pos)) -0306 value = []; -0307 else -0308 value = sprintf('%.15g',full(field(pos))); -0309 end -0310 end -0311 if ~isempty(value) -0312 fprintf(fid,' %s: %s\n',name,value); +0279 if iscell(list) +0280 list=list{1}; +0281 end +0282 fprintf(fid,' %s: %s\n',name,list); +0283 elseif ischar(list) && strcmp(fieldName,'subSystems') +0284 if preserveQuotes +0285 list = ['"' list '"']; +0286 end +0287 fprintf(fid,' %s: %s\n',name,list); +0288 elseif length(list) > 1 || strcmp(fieldName,'subSystems') +0289 if preserveQuotes +0290 for j=1:numel(list) +0291 list{j} = ['"' list{j} '"']; +0292 end +0293 end +0294 fprintf(fid,' %s:\n',name); +0295 for i = 1:length(list) +0296 fprintf(fid,'%s - %s\n',regexprep(name,'(^\s*).*','$1'),list{i}); +0297 end +0298 end +0299 +0300 elseif sum(pos) > 0 +0301 %All other fields: +0302 if strcmp(type,'txt') +0303 value = field{pos}; +0304 if preserveQuotes && ~isempty(value) +0305 value = ['"',value,'"']; +0306 end +0307 elseif strcmp(type,'num') +0308 if isnan(field(pos)) +0309 value = []; +0310 else +0311 value = sprintf('%.15g',full(field(pos))); +0312 end 0313 end -0314 end -0315 end -0316 end -0317 -0318 function writeMetadata(model,fid) -0319 % Writes model metadata to the yaml file. This information will eventually -0320 % be extracted entirely from the model, but for now, many of the entries -0321 % are hard-coded defaults for HumanGEM. -0322 -0323 fprintf(fid, '- metaData:\n'); -0324 if isfield(model,'id') -0325 fprintf(fid, ' id: "%s"\n', model.id); -0326 else -0327 fprintf(fid, ' id: "blankID"\n'); -0328 end -0329 if isfield(model,'name') -0330 fprintf(fid, ' name: "%s"\n',model.name); -0331 else -0332 fprintf(fid, ' name: "blankName"\n'); -0333 end -0334 if isfield(model,'version') -0335 fprintf(fid, ' version: "%s"\n',model.version); +0314 if ~isempty(value) +0315 fprintf(fid,' %s: %s\n',name,value); +0316 end +0317 end +0318 end +0319 end +0320 +0321 function writeMetadata(model,fid) +0322 % Writes model metadata to the yaml file. This information will eventually +0323 % be extracted entirely from the model, but for now, many of the entries +0324 % are hard-coded defaults for HumanGEM. +0325 +0326 fprintf(fid, '- metaData:\n'); +0327 if isfield(model,'id') +0328 fprintf(fid, ' id: "%s"\n', model.id); +0329 else +0330 fprintf(fid, ' id: "blankID"\n'); +0331 end +0332 if isfield(model,'name') +0333 fprintf(fid, ' name: "%s"\n',model.name); +0334 else +0335 fprintf(fid, ' name: "blankName"\n'); 0336 end -0337 fprintf(fid, ' date: "%s"\n',datestr(now,29)); % 29=YYYY-MM-DD -0338 if isfield(model,'annotation') -0339 if isfield(model.annotation,'defaultLB') -0340 fprintf(fid, ' defaultLB: "%g"\n', model.annotation.defaultLB); -0341 end -0342 if isfield(model.annotation,'defaultUB') -0343 fprintf(fid, ' defaultUB: "%g"\n', model.annotation.defaultUB); +0337 if isfield(model,'version') +0338 fprintf(fid, ' version: "%s"\n',model.version); +0339 end +0340 fprintf(fid, ' date: "%s"\n',datestr(now,29)); % 29=YYYY-MM-DD +0341 if isfield(model,'annotation') +0342 if isfield(model.annotation,'defaultLB') +0343 fprintf(fid, ' defaultLB: "%g"\n', model.annotation.defaultLB); 0344 end -0345 if isfield(model.annotation,'givenName') -0346 fprintf(fid, ' givenName: "%s"\n', model.annotation.givenName); +0345 if isfield(model.annotation,'defaultUB') +0346 fprintf(fid, ' defaultUB: "%g"\n', model.annotation.defaultUB); 0347 end -0348 if isfield(model.annotation,'familyName') -0349 fprintf(fid, ' familyName: "%s"\n', model.annotation.familyName); +0348 if isfield(model.annotation,'givenName') +0349 fprintf(fid, ' givenName: "%s"\n', model.annotation.givenName); 0350 end -0351 if isfield(model.annotation,'authors') -0352 fprintf(fid, ' authors: "%s"\n', model.annotation.authors); +0351 if isfield(model.annotation,'familyName') +0352 fprintf(fid, ' familyName: "%s"\n', model.annotation.familyName); 0353 end -0354 if isfield(model.annotation,'email') -0355 fprintf(fid, ' email: "%s"\n', model.annotation.email); +0354 if isfield(model.annotation,'authors') +0355 fprintf(fid, ' authors: "%s"\n', model.annotation.authors); 0356 end -0357 if isfield(model.annotation,'organization') -0358 fprintf(fid, ' organization: "%s"\n',model.annotation.organization); +0357 if isfield(model.annotation,'email') +0358 fprintf(fid, ' email: "%s"\n', model.annotation.email); 0359 end -0360 if isfield(model.annotation,'taxonomy') -0361 fprintf(fid, ' taxonomy: "%s"\n', model.annotation.taxonomy); +0360 if isfield(model.annotation,'organization') +0361 fprintf(fid, ' organization: "%s"\n',model.annotation.organization); 0362 end -0363 if isfield(model.annotation,'note') -0364 fprintf(fid, ' note: "%s"\n', model.annotation.note); +0363 if isfield(model.annotation,'taxonomy') +0364 fprintf(fid, ' taxonomy: "%s"\n', model.annotation.taxonomy); 0365 end -0366 if isfield(model.annotation,'sourceUrl') -0367 fprintf(fid, ' sourceUrl: "%s"\n', model.annotation.sourceUrl); +0366 if isfield(model.annotation,'note') +0367 fprintf(fid, ' note: "%s"\n', model.annotation.note); 0368 end -0369 end -0370 if isfield(model,'ec') -0371 if model.ec.geckoLight -0372 geckoLight = 'true'; -0373 else -0374 geckoLight = 'false'; -0375 end -0376 fprintf(fid,' geckoLight: "%s"\n',geckoLight); -0377 end -0378 end +0369 if isfield(model.annotation,'sourceUrl') +0370 fprintf(fid, ' sourceUrl: "%s"\n', model.annotation.sourceUrl); +0371 end +0372 end +0373 if isfield(model,'ec') +0374 if model.ec.geckoLight +0375 geckoLight = 'true'; +0376 else +0377 geckoLight = 'false'; +0378 end +0379 fprintf(fid,' geckoLight: "%s"\n',geckoLight); +0380 end +0381 end
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/io/closeModel.m b/io/closeModel.m index fbee581f..b91d69f0 100755 --- a/io/closeModel.m +++ b/io/closeModel.m @@ -11,11 +11,11 @@ closedModel=model; -closedModel.comps{numel(closedModel.comps)+1}='b'; -closedModel.compNames{numel(closedModel.compNames)+1}='boundary'; +closedModel.comps{numel(closedModel.comps)+1,1}='b'; +closedModel.compNames{numel(closedModel.compNames)+1,1}='boundary'; if isfield(closedModel,'compMiriams') - closedModel.compMiriams{numel(closedModel.compMiriams)+1}=[]; -end; + closedModel.compMiriams{numel(closedModel.compMiriams)+1,1}=[]; +end closedModel.unconstrained=zeros(numel(closedModel.mets),1); for i=1:numel(closedModel.rxns) @@ -23,29 +23,29 @@ closedModel.mets{numel(closedModel.mets)+1}=strcat(closedModel.mets{find(closedModel.S(:,i))},'_b'); if isfield(closedModel,'metNames') closedModel.metNames{numel(closedModel.metNames)+1}=closedModel.metNames{find(closedModel.S(:,i))}; - end; + end closedModel.metComps(numel(closedModel.metComps)+1)=numel(closedModel.comps); if isfield(closedModel,'inchis') closedModel.inchis{numel(closedModel.inchis)+1}=closedModel.inchis{find(closedModel.S(:,i))}; - end; + end if isfield(closedModel,'metSmiles') closedModel.metSmiles{numel(closedModel.metSmiles)+1}=closedModel.metSmiles{find(closedModel.S(:,i))}; - end; + end if isfield(closedModel,'metFormulas') closedModel.metFormulas{numel(closedModel.metFormulas)+1}=closedModel.metFormulas{find(closedModel.S(:,i))}; - end; + end if isfield(closedModel,'metMiriams') closedModel.metMiriams{numel(closedModel.metMiriams)+1}=closedModel.metMiriams{find(closedModel.S(:,i))}; - end; + end if isfield(closedModel,'metFrom') closedModel.metFrom{numel(closedModel.metFrom)+1}=''; - end; + end if isfield(closedModel,'metCharges') closedModel.metCharges(numel(closedModel.metCharges)+1)=closedModel.metCharges(find(closedModel.S(:,i))); - end; + end if isfield(closedModel,'metDeltaG') closedModel.metDeltaG(numel(closedModel.metDeltaG)+1)=closedModel.metDeltaG(find(closedModel.S(:,i))); - end; + end closedModel.unconstrained(numel(closedModel.unconstrained)+1)=1; closedModel.b(numel(closedModel.b)+1)=0; closedModel.S=[closedModel.S;sparse(1,size(closedModel.S,2))]; @@ -53,8 +53,8 @@ closedModel.S(numel(closedModel.mets),i)=-1; else closedModel.S(numel(closedModel.mets),i)=1; - end; - end; -end; + end + end +end end diff --git a/io/readYAMLmodel.m b/io/readYAMLmodel.m index dd5e692f..ac3f256a 100755 --- a/io/readYAMLmodel.m +++ b/io/readYAMLmodel.m @@ -52,13 +52,15 @@ end line_raw(brokenLine)=[]; -line_key = regexprep(line_raw,'^ *-? ([^:]+)(:).*','$1'); +line_key = regexprep(line_raw,'^ *-? ([^:]+)(:)($| .*)','$1'); line_key = regexprep(line_key,'(.*!!omap)|(---)|( {4,}.*)',''); line_value = regexprep(line_raw, '.*:$',''); line_value = regexprep(line_value, '[^":]+: "?(.+)"?$','$1'); line_value = regexprep(line_value, '(")|(^ {4,}- )',''); +line_value(strcmp(line_value,line_raw)) = {''}; + modelFields = {'id',char();... 'name',char();... 'description',char();... @@ -220,6 +222,8 @@ model.annotation.note = tline_value; case 'github' model.annotation.sourceUrl = tline_value; + case 'sourceUrl' + model.annotation.sourceUrl = tline_value; case 'givenName' model.annotation.givenName = tline_value; case 'familyName' @@ -276,8 +280,7 @@ otherwise switch readList case 'annotation' - [metMiriams, miriamKey] = gatherAnnotation(pos,metMiriams,tline_key,tline_value,miriamKey,metMirNo); - metMirNo = metMirNo + 1; + [metMiriams, miriamKey, metMirNo] = gatherAnnotation(pos,metMiriams,tline_key,tline_value,miriamKey,metMirNo); otherwise error(['Unknown entry in yaml file: ' tline_raw]) end @@ -353,7 +356,6 @@ subSysNo=subSysNo+1; case 'annotation' [rxnMiriams, miriamKey,rxnMirNo] = gatherAnnotation(pos,rxnMiriams,tline_key,tline_value,miriamKey,rxnMirNo); - rxnMirNo=rxnMirNo+1; case 'equation' coeff = sscanf(tline_value,'%f'); equations(equatiNo,1:3)={pos,tline_key,coeff}; @@ -381,8 +383,7 @@ otherwise switch readList case 'annotation' - [geneMiriams, miriamKey] = gatherAnnotation(pos,geneMiriams,tline_key,tline_value,miriamKey,genMirNo); - genMirNo = genMirNo + 1; + [geneMiriams, miriamKey,genMirNo] = gatherAnnotation(pos,geneMiriams,tline_key,tline_value,miriamKey,genMirNo); otherwise error(['Unknown entry in yaml file: ' tline_raw]) end @@ -667,7 +668,7 @@ model.(fieldName)(pos,1) = {value}; end -function [miriams, miriamKey,entryNumber] = gatherAnnotation(pos,miriams,key,value,miriamKey,entryNumber) +function [miriams,miriamKey,entryNumber] = gatherAnnotation(pos,miriams,key,value,miriamKey,entryNumber) if isempty(key) key=miriamKey; else @@ -675,7 +676,6 @@ end if ~isempty(value) miriams(entryNumber,1:3) = {pos, key, strip(value)}; -else - entryNumber = entryNumber - 1; + entryNumber = entryNumber + 1; end end diff --git a/io/writeYAMLmodel.m b/io/writeYAMLmodel.m index b40bf18e..2b2bd612 100755 --- a/io/writeYAMLmodel.m +++ b/io/writeYAMLmodel.m @@ -276,6 +276,9 @@ function writeField(model,fid,fieldName,type,pos,name,preserveQuotes) if preserveQuotes list = ['"' list{1} '"']; end + if iscell(list) + list=list{1}; + end fprintf(fid,' %s: %s\n',name,list); elseif ischar(list) && strcmp(fieldName,'subSystems') if preserveQuotes From 8bfb82b777cba36ebff64ece251f1b513b220afb Mon Sep 17 00:00:00 2001 From: Eduard Kerkhoven Date: Sat, 21 Dec 2024 22:19:18 +0100 Subject: [PATCH 2/2] doc: updated PR template, refer to Wiki on how to make new release --- .github/pull_request_template.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 547498d1..35742302 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,14 +1,14 @@ ### Main improvements in this PR: +- documentation: + - updated all documentation +- features: + - introduced option to do function Y (solves #12345) --> #### Instructions on merging this PR: - [ ] This PR has `develop` as target branch, and will be resolved with a *squash-merge*. -- [ ] This PR has `main` as target branch, and will be resolved with a *merge commit*. +- [ ] This PR has `main` as target branch, and will be resolved as descriped [here](https://github.com/SysBioChalmers/RAVEN/wiki/Development-policy#make-a-new-release).