Skip to content

Commit a9c0643

Browse files
authored
fix: findRAVENroot, subSystems, keggRxns, YAML without genes (#601)
* fix: store ravenPath as MATLAB preference * fix: subSystems either nested or not * fix: regenerate keggRxns, bug in subSystems * fix: fully support subSystems as nested or not * fix: YAML file allowed to have no genes * chore: updateDocumentation * fix: subSystems * fix: ravenCobraWrapper subSystems, init-params * fix: mergeModels giving useless output * fix: ravenCobraWrapper
1 parent f595c49 commit a9c0643

50 files changed

Lines changed: 4403 additions & 4197 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

INIT/runINIT.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
function [outModel, deletedRxns, metProduction, fValue]=runINIT(model,rxnScores,presentMets,essentialRxns,prodWeight,allowExcretion,noRevLoops)
1+
function [outModel, deletedRxns, metProduction, fValue]=runINIT(model,rxnScores,presentMets,essentialRxns,prodWeight,allowExcretion,noRevLoops,params)
22
% runINIT
33
% Generates a model using the INIT algorithm, based on proteomics and/or
44
% transcriptomics and/or metabolomics and/or metabolic tasks. This is the
@@ -38,6 +38,7 @@
3838
% problem significantly more computationally intensive to
3939
% solve (two more integer constraints per reversible reaction)
4040
% (optional, default false)
41+
% params parameter structure for use by optimizeProb
4142
%
4243
% outModel the resulting model structure
4344
% deletedRxns reactions which were deleted by the algorithm

core/FSEOF.m

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,12 @@
119119
A2=char(model.rxns(num)); %enzyme ID
120120
A3=char(model.rxnNames(num)); %enzyme Name
121121
if isfield(model,'subSystems') && ~isempty(model.subSystems{num});
122-
A4=char(strjoin(model.subSystems{num,1},';')); %Subsystems
122+
if ~any(cellfun(@(x) iscell(x), model.subSystems));
123+
subSys = cellfun(@(x) {x}, model.subSystems, 'uni', 0);
124+
else
125+
subSys = model.subSystems;
126+
end
127+
A4=char(strjoin(subSys{num},';')); %Subsystems
123128
else
124129
A4='';
125130
end

core/addExchangeRxns.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@
6363
end
6464
if isfield(model,'subSystems')
6565
fillerSub = filler;
66-
if iscell(model.subSystems(1,1))
67-
fillerSub = repmat({fillerSub},numel(J),1);
66+
if any(cellfun(@(x) iscell(x), model.subSystems))
67+
fillerSub(:)={{''}};
6868
end
6969
model.subSystems=[model.subSystems;fillerSub];
7070
end

core/addRxns.m

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,12 @@
227227
nOldRxns=numel(model.rxns);
228228
filler=cell(nRxns,1);
229229
filler(:)={''};
230-
cellfiller=cellfun(@(x) cell(0,0),filler,'UniformOutput',false);
230+
cellfiller=cell(nRxns,1);
231+
cellfiller(:)={{''}};
231232
largeFiller=cell(nOldRxns,1);
232233
largeFiller(:)={''};
233-
celllargefiller=cellfun(@(x) cell(0,0),largeFiller,'UniformOutput',false);
234+
largeCellFiller=cell(nOldRxns,1);
235+
largeCellFiller(:)={{''}};
234236

235237
%***Add everything to the model except for the equations.
236238
if numel(rxnsToAdd.equations)~=nRxns
@@ -350,28 +352,45 @@
350352
end
351353

352354
if isfield(rxnsToAdd,'subSystems')
355+
% Has to be cell array
353356
if ischar(rxnsToAdd.subSystems)
354-
rxnsToAdd.subSystems = {{rxnsToAdd.subSystems}};
357+
rxnsToAdd.subSystems = {rxnsToAdd.subSystems};
358+
end
359+
% If all nested cells are 1x1, then unnest
360+
if all(cellfun(@(x) iscell(x) && isscalar(x), rxnsToAdd.subSystems))
361+
rxnsToAdd.subSystems = transpose([rxnsToAdd.subSystems{:}]);
362+
end
363+
% Cell array should now be as simple as possible. Check if it is nested
364+
subSysRxnsNested = any(cellfun(@(x) iscell(x), rxnsToAdd.subSystems));
365+
if isfield(newModel,'subSystems')
366+
subSysModelNested = any(cellfun(@(x) iscell(x), newModel.subSystems));
355367
else
356-
for i=1:numel(rxnsToAdd.subSystems)
357-
if ischar(rxnsToAdd.subSystems{i})
358-
rxnsToAdd.subSystems{i}=rxnsToAdd.subSystems(i);
359-
end
368+
subSysModelNested = subSysRxnsNested;
369+
if subSysRxnsNested
370+
newModel.subSystems=largeCellFiller;
371+
else
372+
newModel.subSystems=largeFiller;
360373
end
361374
end
375+
if subSysRxnsNested && ~subSysModelNested
376+
% Make all existing subSystems nested
377+
newModel.subSystems = cellfun(@(x) {x}, newModel.subSystems, 'uni', 0);
378+
elseif ~subSysRxnsNested && subSysModelNested
379+
rxnsToAdd.subSystems = cellfun(@(x) {x}, rxnsToAdd.subSystems, 'uni', 0);
380+
end
362381
if numel(rxnsToAdd.subSystems)~=nRxns
363382
EM='rxnsToAdd.subSystems must have the same number of elements as rxnsToAdd.rxns';
364383
dispEM(EM);
365384
end
366-
%Fill with standard if it doesn't exist
367-
if ~isfield(newModel,'subSystems')
368-
newModel.subSystems=celllargefiller;
369-
end
370385
newModel.subSystems=[newModel.subSystems;rxnsToAdd.subSystems(:)];
371386
else
372-
%Fill with standard if it doesn't exist
387+
%Fill with standard if it does not exist
373388
if isfield(newModel,'subSystems')
374-
newModel.subSystems=[newModel.subSystems;cellfiller];
389+
if any(cellfun(@(x) iscell(x), newModel.subSystems))
390+
newModel.subSystems=[newModel.subSystems;cellfiller];
391+
else
392+
newModel.subSystems=[newModel.subSystems;filler];
393+
end
375394
end
376395
end
377396
if isfield(rxnsToAdd,'rxnMiriams')

core/addTransport.m

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,15 @@
134134
model.eccodes=[model.eccodes;filler];
135135
end
136136
if isfield(model,'subSystems')
137-
ssFiller=filler;
137+
isNested = any(cellfun(@(x) iscell(x), model.subSystems));
138+
ssFiller = filler;
138139
if isRev==1
139-
ssFiller(:)={{['Transport between ' fromComp ' and ' toComps{i}]}};
140+
ssFiller(:) = {['Transport between ' fromComp ' and ' toComps{i}]};
140141
else
141-
ssFiller(:)={{['Transport from ' fromComp ' to ' toComps{i}]}};
142+
ssFiller(:) = {['Transport from ' fromComp ' to ' toComps{i}]};
143+
end
144+
if isNested
145+
ssFiller = cellfun(@(x) {x}, ssFiller, 'uni', 0);
142146
end
143147
model.subSystems=[model.subSystems;ssFiller];
144148
end

core/checkModelStruct.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,11 @@ function checkModelStruct(model,throwErrors,trimWarnings)
175175
end
176176
end
177177
if isfield(model,'subSystems')
178-
for i=1:numel(model.subSystems)
179-
if ~iscell(model.subSystems{i,1})
180-
EM='The "subSystems" field must be a cell array';
178+
isNested = any(cellfun(@(x) iscell(x), model.subSystems));
179+
isCellStr = any(cellfun(@(x) ischar(x), model.subSystems));
180+
if ~xor(isNested,isCellStr)
181+
EM='The "subSystems" field must be a cell array of chars, *or* a cell array of cell arrays of chars';
181182
dispEM(EM,throwErrors);
182-
end
183183
end
184184
end
185185
if isfield(model,'eccodes')

core/compareMultipleModels.m

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,6 @@
9292
fprintf('*** Done \n\n')
9393

9494

95-
%% Flatten models' subSystems field
96-
% Convert from cell array of cells to cell array of strings
97-
% NOTE: this function currently only recognizes one subSystem per reaction;
98-
% additional subSystems will be ignored!
99-
for i = 1:numel(models)
100-
cells = cellfun(@iscell,models{i}.subSystems);
101-
models{i}.subSystems(cells) = cellfun(@(s) s{1}, models{i}.subSystems(cells), 'UniformOutput', false);
102-
end
103-
104-
10595
%% Compare models structure & function based on high-dimensional methods
10696
% Compare number of reactions in each subsystem in each model using a heatmap
10797
field = 'subSystems';
@@ -110,6 +100,16 @@
110100
fprintf('\nWARNING: At least one model does not contain the field "subSystems". \n')
111101
fprintf(' Skipping subsystem comparison. \n\n')
112102
else
103+
%% Flatten model subSystems field
104+
% Convert from cell array of cells to cell array of strings
105+
% NOTE: this function currently only recognizes one subSystem per reaction;
106+
% additional subSystems will be ignored!
107+
for i = 1:numel(models)
108+
if any(cellfun(@(x) iscell(x), models{i}.subSystems));
109+
cells = cellfun(@iscell,models{i}.subSystems);
110+
models{i}.subSystems(cells) = cellfun(@(s) s{1}, models{i}.subSystems(cells), 'UniformOutput', false);
111+
end
112+
end
113113
[id,compMat] = compareModelField(models,field);
114114
compStruct.subsystems.ID = id;
115115
compStruct.subsystems.matrix = compMat;

core/findRAVENroot.m

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
11
function [ravenPath, prevDir] = findRAVENroot()
22
% findRAVENroot
3-
% Finds the root of the RAVEN directory, by searching for the path to
3+
% Finds the root of the RAVEN directory, first by by searching for the path to
44
% RAVEN2.png. Can also record the current directory, in case a function will
55
% use the ravenPath to navigate to a precise folder, and it should return to
66
% the previous directory afterwards. See e.g. optimizeProb calling glpk.
77

88
ST=dbstack('-completenames');
99
prevDir = pwd();
10-
ravenPath = ST(strcmp({ST.name},'findRAVENroot')).file;
11-
rootFound = 0;
12-
while rootFound == 0
13-
isRoot = isfile(fullfile(ravenPath,'RAVEN2.png'));
14-
if isRoot
15-
rootFound = 1;
16-
else
17-
ravenPathOld = ravenPath;
18-
ravenPath = fileparts(ravenPath);
19-
if strcmp(ravenPathOld,ravenPath)
20-
error('Cannot find the RAVEN root directory. Make sure you have not removed the RAVEN2.png file from your RAVEN installation.')
10+
if ispref('RAVEN','ravenPath')
11+
ravenPath = getpref('RAVEN','ravenPath');
12+
else
13+
ravenPath = ST(strcmp({ST.name},'findRAVENroot')).file;
14+
rootFound = 0;
15+
while rootFound == 0
16+
isRoot = isfile(fullfile(ravenPath,'RAVEN2.png'));
17+
if isRoot
18+
rootFound = 1;
19+
else
20+
ravenPathOld = ravenPath;
21+
ravenPath = fileparts(ravenPath);
22+
if strcmp(ravenPathOld,ravenPath)
23+
error('Cannot find the RAVEN root directory. Make sure you have not removed the RAVEN2.png file from your RAVEN installation.')
24+
end
2125
end
2226
end
2327
end

core/fitTasks.m

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
% the result.
3535
%
3636
% Usage: [outModel, addedRxns]=fitTasks(model,refModel,inputFile,printOutput,...
37-
% rxnScores,taskStructure,params)
37+
% rxnScores,taskStructure)
3838

3939
if nargin<4
4040
printOutput=true;
@@ -48,9 +48,6 @@
4848
if nargin<6
4949
taskStructure=[];
5050
end
51-
if nargin<7
52-
params=[];
53-
end
5451

5552
if isempty(taskStructure) && ~isfile(inputFile)
5653
error('Task file %s cannot be found',string(inputFile));
@@ -268,7 +265,7 @@
268265
try
269266
[~, ~, newRxns, newModel, exitFlag]=fillGaps(tModel,refModel,false,true,supressWarnings,rxnScores);
270267
if exitFlag==-2
271-
EM=['"[' taskStructure(i).id '] ' taskStructure(i).description '" was aborted before reaching optimality. Consider increasing params.maxTime\n'];
268+
EM=['"[' taskStructure(i).id '] ' taskStructure(i).description '" was aborted before reaching optimality.\n'];
272269
dispEM(EM,false);
273270
end
274271
catch

core/mergeModels.m

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@
8282
model=rmfield(model,'equations');
8383
end
8484

85+
for i=1:numel(models)
86+
if isfield(models{i},'subSystems')
87+
models{i}.subSystems = cellfun(@(x) {x}, models{i}.subSystems, 'uni', 0);
88+
end
89+
end
8590
for i=2:numel(models)
8691
%Add the model id to the rxn id id it already exists in the model (id
8792
%have to be unique) This is because it makes a '[]' string if no new
@@ -283,7 +288,6 @@
283288
if strcmpi(metParam,'mets')
284289
%Get the new metabolites from matching the models. Metabolites are matched by metabolite ID (model.mets).
285290

286-
oldMetComps=model.comps(model.metComps);
287291
oldMets=model.mets;
288292

289293
if ~isempty(models{i}.mets)
@@ -613,7 +617,7 @@
613617
end
614618

615619
%Remap the genes from the new model. The same thing as with
616-
%mets; this is a wasteful way to do it but I don't care right
620+
%mets; this is a wasteful way to do it but I do not care right
617621
%now
618622
a = ismember(models{i}.genes,model.genes);
619623

@@ -637,4 +641,10 @@
637641
[grRules,rxnGeneMat] = standardizeGrRules(model,true);
638642
model.grRules = grRules;
639643
model.rxnGeneMat = rxnGeneMat;
644+
%Flatten subSystems if possible
645+
if isfield(model,'subSystems')
646+
if all(cellfun(@(x) iscell(x) && isscalar(x), model.subSystems))
647+
model.subSystems = transpose([model.subSystems{:}]);
648+
end
649+
end
640650
end

0 commit comments

Comments
 (0)