Commit 2b1a22da authored by Florian Centler's avatar Florian Centler

Initial microbialSim version

parent 391b28c3
......@@ -631,7 +631,7 @@ to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
microbialSim
microbialSimDev
Copyright (C) 2019 UMBSysBio
This program is free software: you can redistribute it and/or modify
......@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
microbialSim Copyright (C) 2019 UMBSysBio
microbialSimDev Copyright (C) 2019 UMBSysBio
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
......
# microbialSim
# µbialSim
This is µbialSim, a dynamic Flux-Balance-Analysis simulator for complex microbial communities.
This is µbialSim (pronounced *microbialsim*), a dynamic Flux-Balance-Analysis-based simulator for complex microbial communities. Batch and chemostat operation can be simulated. Simulation results detail the temporal evolution of compound concentrations and biomass concentrations for each microbial species in the bioreactor, and internal flux distributions. For low diversity microbiomes Matlab's ODE solvers can be used, while for more complex communities an augmented forward Euler method is implemented in µbialSim.
Developed by Florian Centler and Denny Popp at UFZ Leipzig, Germany.
\ No newline at end of file
## Getting Started
The latest version of µbialSim can be obtained via git:
```
git clone https://git.ufz.de/UMBSysBio/microbialSim.git
```
### Prerequisites
µbialSim is implemented in Matlab and requires the COBRA Toolbox and/or CellNetAnalyzer for FBA computations. The examples make use of the former.
Information on the COBRA Toolbox is available here:
https://opencobra.github.io/cobratoolbox/stable/index.html
Information on CellNetAnalyzer is available here:
https://www2.mpi-magdeburg.mpg.de/projects/cna/cna.html
### Installing
For using the COBRA Toolbox, its location must be specified in the main simulator file `microbialSimMain.m` in lines 87ff, note that multiple locations can be specified, easing operation in different environments:
```
placesToLookForCobraToolbox = {
'C:\Users\centlerf\cobratoolbox', ...
'Y:\Home\centlerf\Projects\MetabolicModeling\FBATools\cobratoolbox', ...
'/data/cobratoolbox' ...
'..\cobratoolbox'
};
```
## Running the Examples
Three examples are included with µbialSim and can be run as follows.
### Example 1
The first example in which batch-culture growth of a single hydrogenotrophic species (*Methanococcus maripaludis*) is simulated can be run with the command:
```
microbialSimMain(1)
```
The FBA model is taken from *M. A. Richards, T. J. Lie, J. Zhang, S. W. Ragsdale, J. A. Leigh, and N. D. Price, “Exploring hydrogenotrophic methanogenesis: A genome scale metabolic reconstruction of Methanococcus maripaludis,” J. Bacteriol., vol. 198, no. 24, pp. 3379–3390, 2016.*
### Example 2
Batch-culture growth of a binary syntrophic, methanogenic community (*Syntrophobacter fumaroxidans* and *Methanospirillium hungatei*) transforming propionate to methane is started by:
```
microbialSimMain(2)
```
The FBA models are taken from *J. J. Hamilton, M. Calixto Contreras, and J. L. Reed, “Thermodynamics and H2 Transfer in a Methanogenic, Syntrophic Community,” PLOS Comput. Biol., vol. 11, no. 7, p. e1004364, 2015.*
### Example 3
Simulating batch growth of a 773 species human gut microbiome first requires the unpacking of the file `AGORA-1.01-Western-Diet.zip` containing the AGORA model collection. Note that for running the simulation with all species, 64GB of RAM are necessary (loading models as a Matlab data structure after the initial loading as SBML files cuts memory demand in half). The simulation of batch growth can then be started by:
```
microbialSimMain(3)
```
Simulation time can considerably be reduced by setting the parameter `maxDeviation` to `inf` in `microbialSimMain.m` at the expense of numerical accuracy. Note that also arbitrary subsets of the model collection can be selected for the simulation.
The FBA models stem from *S. Magnúsdóttir et al., “Generation of genome-scale metabolic reconstructions for 773 members of the human gut microbiota,” Nat. Publ. Gr., vol. 35, no. 1, 2016.*
### Simulation Output
Two files are generated at the end of the simulation with a date and time stamp in the filename indicating the start of the simulation. Both files hold Matlab data structures. The file `*_restartInit.mat` records the final state of the simulator and can be used as the initial conditions to continue the simulation in a subsequent run of µbialSim. The other file holds the simulated trajectory in the Matlab structure trajectory. The fields `time`, `compounds`, `biomass`, and `mu` hold the time, compound concentrations, biomass concentrations, and specific growth rates for each integration step. The field `FBA` stores data for each FBA model, including the temporal dynamics of all metabolic fluxes, and the mass balance for all exchange reactions.
Additionally, once the simulation is finished, the trajectory is automatically visualized in three Matlab figures detailing the evolution of compound and biomass concentrations as well as exchange fluxes for all species.
## Built With
* [Matlab](https://www.mathworks.com/products/matlab.html) - Implementation language and numerical ODE solver
* [COBRA Toolbox](https://opencobra.github.io/cobratoolbox/stable/index.html) - For loading SBML models and running FBA computations
* [CellNetAnalyzer](https://www2.mpi-magdeburg.mpg.de/projects/cna/cna.html) - For loading SBML models and running FBA computations
## Contributing
Please read [CONTRIBUTING.md](https://gist.github.com/PurpleBooth/b24679402957c63ec426) for details on our code of conduct, and the process for submitting pull requests to us.
## Versioning
We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://git.ufz.de/UMBSysBio/microbialSim/tags).
## Authors
* **Florian Centler**, UFZ - Helmholtz Centre for Environmental Research, Leipzig, Germany
* **Denny Popp**, UFZ - Helmholtz Centre for Environmental Research, Leipzig, Germany
Contact: florian.centler@ufz.de
## License
This project is licensed under the GNU General Public License v3.0 - see the [LICENSE](LICENSE) file for details
## Acknowledgments
* This code was made possible by funding from the German Federal Ministry of Education and Research to Florian Centler (e:Bio project McBiogas, FKZ 031A317)
This diff is collapsed.
function [ dbio, dmetab, flux, success ] = getDy(metabolicModel, reactor, metabolites, biomass, inflowBiomass, timePars)
function [ dbio, dcompound, flux, success ] = getDy(metabolicModel, reactor, compounds, biomass, inflowBiomass, timePars)
%GETDY Compute the current rate of change for biomass and reactor compounds
%based on the current reactor state
% Detailed info
......@@ -14,13 +14,13 @@ function [ dbio, dmetab, flux, success ] = getDy(metabolicModel, reactor, metabo
end
success = 1;
dbio = 0.0;
dmetab = 0.0 * ones(1, length(metabolicModel.coupledReactions.ReacID));
dcompound = 0.0 * ones(1, length(metabolicModel.coupledReactions.ReacID));
return
end
% SET UPTAKE LIMITS
for i = 1:length(metabolicModel.coupledReactions.ReacID)
limit = getLimitFlux(metabolicModel, i, metabolites(metabolicModel.reactorMetaboliteIDs(i)));
limit = getLimitFlux(metabolicModel, i, compounds(metabolicModel.reactorCompoundIDs(i)));
if metabolicModel.coupledReactions{i, 'SecretionSense'} > 0
switch metabolicModel.FBAsolver
case 1
......@@ -432,9 +432,9 @@ function [ dbio, dmetab, flux, success ] = getDy(metabolicModel, reactor, metabo
dbio = flux(metabolicModel.biomassReac) * biomass; % g/l/hour
for i = 1:length(metabolicModel.coupledReactions.ReacID)
dmetab(i) = flux(metabolicModel.coupledReactions.ReacID(i)) * metabolicModel.coupledReactions.SecretionSense(i) * biomass;
% if dmetab(i) > 0 % don't feed back production to reactor to test what happens without metabolite exchange!
% dmetab(i) = 0;
dcompound(i) = flux(metabolicModel.coupledReactions.ReacID(i)) * metabolicModel.coupledReactions.SecretionSense(i) * biomass;
% if dcompound(i) > 0 % don't feed back production to reactor to test what happens without compound exchange!
% dcompound(i) = 0;
% end
end
end
......
......@@ -8,7 +8,7 @@ global ODEresult
numberOfSpecies = length(metabolicModel);
biomass = y(1:numberOfSpecies);
metabolites = y((numberOfSpecies+1):end);
compounds = y((numberOfSpecies+1):end);
for i = 1:numberOfSpecies
metabolicModel(i).lastFlux = ODEresult.metabolicModel(i).lastFlux;
......@@ -16,31 +16,31 @@ end
if timePars.parallel == 1
parfor i = 1:numberOfSpecies
[ dbio(i), dmetabRAW{i}, flux{i}, success(i) ] = getDy(metabolicModel(i), reactor, transpose(metabolites), biomass(i), reactor.biomassInflow(i), timePars);
[ dbio(i), dcompoundRAW{i}, flux{i}, success(i) ] = getDy(metabolicModel(i), reactor, transpose(compounds), biomass(i), reactor.biomassInflow(i), timePars);
end
else
for i = 1:numberOfSpecies
[ dbio(i), dmetabRAW{i}, flux{i}, success(i) ] = getDy(metabolicModel(i), reactor, transpose(metabolites), biomass(i), reactor.biomassInflow(i), timePars);
[ dbio(i), dcompoundRAW{i}, flux{i}, success(i) ] = getDy(metabolicModel(i), reactor, transpose(compounds), biomass(i), reactor.biomassInflow(i), timePars);
end
end
for i = 1:numberOfSpecies
dmetab(i,:) = mapExchangeToReactorMetabolites(dmetabRAW{i}, metabolicModel(i).reactorMetaboliteIDs, length(reactor.metabolites));
dcompound(i,:) = mapExchangeToReactorCompounds(dcompoundRAW{i}, metabolicModel(i).reactorCompoundIDs, length(reactor.compounds));
% consider flow (biomasses)
dbio(i) = dbio(i) + considerFlow(reactor.biomassInflow(i), biomass(i), reactor);
end
ODEresult.ODElastFlux = flux;
% consider flow (metabolites)
% consider flow (compounds)
if numberOfSpecies > 1
myDmetab = sum(dmetab);
myDcompound = sum(dcompound);
else
myDmetab = dmetab;
myDcompound = dcompound;
end
dmetab = myDmetab + considerFlow(reactor.metabolitesInflow, metabolites', reactor);
dcompound = myDcompound + considerFlow(reactor.compoundsInflow, compounds', reactor);
dydt = transpose([dbio dmetab]);
dydt = transpose([dbio dcompound]);
end
function [ result ] = getFluxLimits( flux, metabolicModel, metabolites )
function [ result ] = getFluxLimits( flux, metabolicModel, compounds )
%GETFLUXLIMITS Identify reactions, for which the current flux is identical
%to a set flux boundary
% Fluxes at lower limit are indicated by -1, at upper limit by +1, fixed
......@@ -29,7 +29,7 @@ end
% get current uptake limits
for i = 1:length(metabolicModel.coupledReactions.ReacID)
limit = getLimitFlux(metabolicModel, i, metabolites(metabolicModel.reactorMetaboliteIDs(i)));
limit = getLimitFlux(metabolicModel, i, compounds(metabolicModel.reactorCompoundIDs(i)));
if metabolicModel.coupledReactions{i, 'SecretionSense'} > 0
lb(metabolicModel.coupledReactions{i, 'ReacID'}) = limit;
else
......
function [ deltaTime ] = getTimeToSteadyState(metabolicModel, metaboliteID, metabConc, deltaMetab, deltaFlow, slope, biomass, reactor, solverPars)
function [ deltaTime ] = getTimeToSteadyState(metabolicModel, compoundID, metabConc, deltaCompound, deltaFlow, slope, biomass, reactor, solverPars)
%GETTIMETOSTEADYSTATE Summary of this function goes here
% Detailed explanation goes here
......@@ -9,11 +9,11 @@ productionRate = 0;
consumptionRate = 0;
for i = 1:length(metabolicModel)
if deltaMetab(i) > 0
productionRate = productionRate + deltaMetab(i);
else if deltaMetab(i) < 0
if deltaCompound(i) > 0
productionRate = productionRate + deltaCompound(i);
else if deltaCompound(i) < 0
consumers(end + 1) = i;
consumptionRate = consumptionRate + deltaMetab(i);
consumptionRate = consumptionRate + deltaCompound(i);
end
end
end
......@@ -23,7 +23,7 @@ end
reacIndexStr = cell(1,1);
for i = 1:length(consumers)
tmp = find(~(metabolicModel(consumers(i)).reactorMetaboliteIDs - metaboliteID)); % find index at which position value metaboliteID is located (finding the index of the coupled reaction which refers to the reactor metabolite)
tmp = find(~(metabolicModel(consumers(i)).reactorCompoundIDs - compoundID)); % find index at which position value compoundID is located (finding the index of the coupled reaction which refers to the reactor compound)
reacIndexStr{i} = int2str(metabolicModel(consumers(i)).coupledReactions{tmp, 'ReacID'});
end
......@@ -44,7 +44,7 @@ else % consumption & producing processes present
consRate = consRate * biomass(consumers(i));
consumptionRate = consumptionRate + consRate;
end
consumptionRate = consumptionRate + considerFlow(reactor.metabolitesInflow(metaboliteID), targetConcentration, reactor);
consumptionRate = consumptionRate + considerFlow(reactor.compoundsInflow(compoundID), targetConcentration, reactor);
if productionRate + consumptionRate < 0
topBound = targetConcentration;
else
......@@ -60,4 +60,4 @@ else % consumption & producing processes present
end
% compute deltaTime at which steady state concentration is reached
deltaTime = (targetConcentration - metabConc) / slope;
end
\ No newline at end of file
end
......@@ -42,6 +42,7 @@ function [ status ] = integrator_output(t, y, flag, metabolicModel, timePars)
else
ODEresult.FBA(i).fluxes(n, :) = flux{i};
end
ODEresult.mu(n, i) = ODEresult.FBA(i).fluxes(n, metabolicModel(i).biomassReac);
end
fprintf('\nTime %f (%2.1f%% done)\n\n', t(1), t(1) / timePars.tend * 100);
......
function [ dcompound ] = mapExchangeToReactorCompounds( dcompoundRAW, reactorMapping, numOfReactorCompounds )
%MAPEXCHANGETOREACTORMETABOLITES Summary of this function goes here
% Detailed explanation goes here
% dcompound(i,:) = mapExchangeToReactorCompounds(dcompoundRAWE, metabolicModel(i).reactorCompoundIDs);
dcompound = zeros(1,numOfReactorCompounds);
for i = 1:length(reactorMapping)
dcompound(reactorMapping(i)) = dcompoundRAW(i);
end
end
function [ dmetab ] = mapExchangeToReactorMetabolites( dmetabRAW, reactorMapping, numOfReactorMetabolites )
%MAPEXCHANGETOREACTORMETABOLITES Summary of this function goes here
% Detailed explanation goes here
%dmetab(i,:) = mapExchangeToReactorMetabolites(dmetabRAW, metabolicModel(i).reactorMetabolitesIDs);
dmetab = zeros(1,numOfReactorMetabolites);
for i = 1:length(reactorMapping)
dmetab(reactorMapping(i)) = dmetabRAW(i);
end
end
function [ trajectory ] = microbialSimMain(scenarioID)
%test
%microbialSimMain v1.0
% This is the main routine of the dFBA simulator bialSim. Different
%microbialSimMain v1.0.0
% This is the main routine of the dFBA simulator �bialSim. Different
% simulation scenarios can be set up by configuring "scenarioID"s. Out of
% the box, bialSim can simulate two microbiomes:
% the box, bialSim can simulate two microbiomes:
% scenarioID == 1: a Methanococcus maripaludis single culture (Richards et al., 2016)
% scenarioID == 2: a syntrophic methanogenesis biculture (Hamilton et al., 2015)
% scenarioID == 3: a 773 species human gut microbiome (or selection
......@@ -18,7 +17,7 @@ solverPars.saveLoadedModelsToFile = 0; % Set to 1 to save loaded SBML
% models in Matlab format for speeding up subsequent simulation runs.
% Models are stored in "loadedModels<date><time>.mat".
solverPars.readInitialStateFrom = ''; % Provide trajectory file name to
% continue a previous simulation run ("simulatedTrajectory_*.mat*").
% continue a previous simulation run ("simulatedTrajectory_*.mat_restartInit.mat").
solverPars.parallel = 0; % Set to 1 to compute FBA models in parallel using
% Matlab's parfor command. Note that model data need to be tansferred
% to workers at each individual iteration again and again, limiting
......@@ -33,17 +32,20 @@ solverPars.minimalGrowth = 1e-6; % If predicted growth rate is below this
% threshold, assume that no growth is possible
solverPars.solverType = 0; % Set to 0 for augmented forward Euler method,
% 1 for direct approach (using Matlab's ODE solver)
solverPars.doMassBalance = 1; % Set to 0 to avoid calculation of mass balances
% for all exchange fluxes at the end of the simulation (can take a long
% time)
% Only used if augmented forward Euler method is used:
solverPars.myAccuracy = 1e-15; % Metabolite concentrations below this value
solverPars.myAccuracy = 1e-15; % Compound concentrations below this value
% are evaluated to be zero.
solverPars.myBioAccuracy = 1e-15; % Biomass concentrations below this
% vaue are evaluated to be zero.
solverPars.SteadyStateAccuracy = 1e-5; % Allow for this deviation between
% production and consumption rate when computing steady state during
% time step size reduction
solverPars.maxDeviation = 5.0; % For metabolites of high demand, reduce
% time step size so that metabolite change is not bigger than this value
solverPars.maxDeviation = 5.0; % For compounds of high demand, reduce
% time step size so that compound change is not bigger than this value
% (specified in %). This helps to avoid oscillatory behavior. To disable
% this feature and speed up simulation, set to "inf"
solverPars.recording = 0; % Set to 1 to save reactor state at each iteration
......@@ -83,7 +85,7 @@ switch solverPars.FBAsolver
currDir = pwd;
% ADD PATH TO YOUR COBRA INSTALLATION HERE (REPLACE OR APPEND AT END OF LIST)
placesToLookForCobraToolbox = {
'C:\Users\centlerf\Nextcloud2\Home\Projects\MetabolicModeling\FBATools\cobratoolbox', ...
'C:\Users\centlerf\cobratoolbox', ...
'Y:\Home\centlerf\Projects\MetabolicModeling\FBATools\cobratoolbox', ...
'/data/cobratoolbox' ...
'..\cobratoolbox'
......@@ -114,31 +116,34 @@ clearvars models
switch scenarioID
case 1 % M. maripaluids monoculture
solverPars.tend = 1;
solverPars.timeStepSize = 0.02;
solverPars.tend = 1.0;
solverPars.timeStepSize = 0.002;
solverPars.solverType = 0; % 0 dFBA or 1 for ODE
model = prepareFBAmodel_iMR539('models\MODELRICHARDS 2016.xml', solverPars.FBAsolver);
model = convertToOnlyIrrevReac(model);
model = parametrizeiMR539(model);
model = parametrizeFBAmodel_iMR539(model);
models(1) = model;
reactor = reactorDefinition_iMR539;
case 2 % Reed Consortium
solverPars.tend = 1;
solverPars.timeStepSize = 0.02;
case 2 % syntrophic propionate degrading binary consortium
solverPars.tend = 1.0;
solverPars.timeStepSize = 0.002;
solverPars.solverType = 0; % 0 dFBA or 1 ODE
iSfu648Model = prepareFBAmodel_iSfu648Model('models\S5_Dataset_SDH_Coupling.xml', solverPars.FBAsolver);
iSfu648Model = convertToOnlyIrrevReac(iSfu648Model);
iSfu648Model = parametrizeiSfu648Model(iSfu648Model);
iSfu648Model = parametrizeFBAmodel_iSfu648(iSfu648Model);
iMhu428Model = prepareFBAmodel_iMhu428Model('models\S3_Dataset.xml', solverPars.FBAsolver);
iMhu428Model = convertToOnlyIrrevReac(iMhu428Model);
iMhu428Model = parametrizeiMhu428Model(iMhu428Model);
iMhu428Model = parametrizeFBAmodel_iMhu428(iMhu428Model);
models(1) = iSfu648Model;
models(2) = iMhu428Model;
reactor = reactorDefinitionReed;
reactor = reactorDefinition_synProp;
case 3 % 773 gut microbiome
solverPars.tend = 1.0;
solverPars.timeStepSize = 0.002;
% consider all species
speciesToConsider = 1:773;
......@@ -146,13 +151,10 @@ switch scenarioID
%speciesToConsider = [1, 2, 3];
%speciesToConsider = [46, 125, 164, 178, 245, 270, 362, 482];
[models, externalMetabolites] = prepare773Model(speciesToConsider, 'models\AGORA-1.01-Western-Diet\', solverPars.FBAsolver);
[models, externalCompounds] = prepareFBAmodel_773Agora(speciesToConsider, 'models\AGORA-1.01-Western-Diet\', solverPars.FBAsolver);
solverPars.saveLoadedModelsToFile = 1; % look for "loadedModels_*.mat" in current directory, can be used in subsequent runs for speed-up (see next line)
%load('.\loadedModels_26-Mar-2019 11_34_00.mat');
solverPars.tend = 0.3;
solverPars.timeStepSize = 0.002;
solverPars.readInitialStateFrom = '';
solverPars.parallel = 0;
......@@ -166,7 +168,7 @@ switch scenarioID
end
end
reactor = reactorDefinition773(length(models), externalMetabolites);
reactor = reactorDefinition_773Agora(length(models), externalCompounds);
otherwise
error('Unknown model scenario. Aborting')
......@@ -181,7 +183,12 @@ if solverPars.parallel == 1
end
if solverPars.saveLoadedModelsToFile == 1
save(modelFile, 'models', 'externalMetabolites', '-v7.3'); % for > 2GB
switch scenarioID
case 3
save(modelFile, 'models', 'externalCompounds', '-v7.3'); % for > 2GB
otherwise
save(modelFile, 'models', '-v7.3'); % for > 2GB
end
end
tic
......@@ -196,11 +203,13 @@ save(solverPars.trajectoryFile, 'trajectory', 'reactor', 'elapsedHours', '-v7.3'
figure
subplot(2,1,1)
plot(trajectory.time, trajectory.biomass)
legend(trajectory.modelNames)
title('Biomass')
xlabel('Time (hours)')
ylabel('Concentration (gDW/L)')
subplot(2,1,2)
plot(trajectory.time, trajectory.metabolites)
plot(trajectory.time, trajectory.compounds)
legend(trajectory.compoundNames)
title('Compounds')
xlabel('Time (hours)')
ylabel('Concentration (mmol/L)')
......
function [ model ] = parametrizeiSfu648Model(model)
function [ model ] = parametrizeFBAmodel_iSfu648Model(model)
%PARAMETRIZE Setting the parameters (NGAM and uptake kinetics)for the model
% Detailed explanation goes here
......@@ -18,6 +18,6 @@ end
%% UPTAKE KINETICS
%CO2, H2, Acetate, Methane
model.coupledReactions.vmax = [50 50 50 0]';
model.coupledReactions.ks = [0.1 0.1 0.1 0]';
model.coupledReactions.vmax = [1000 189.3 0]';
model.coupledReactions.ks = [0 4.375e-4 0]';
function [ model ] = parametrizeiMhu428(model)
function [ model ] = parametrizeFBAmodel_iMhu428(model)
%PARAMETRIZE Setting the parameters (NGAM and uptake kinetics)for the model
% Detailed explanation goes here
......@@ -18,6 +18,6 @@ end
%% UPTAKE KINETICS
% acetate, co2, h2, Formate, methane
model.coupledReactions.vmax = [0 75.7 102.5*2/2*2 955*0 0]';
model.coupledReactions.ks = [1 1 1 1 1]';
model.coupledReactions.vmax = [0 100.0 27.6 0 0]';
model.coupledReactions.ks = [0 0 0.006 0 0]';
function [ model ] = parametrizeiSfu648Model(model)
function [ model ] = parametrizeFBAmodel_iSfu648Model(model)
%PARAMETRIZE Setting the parameters (NGAM and uptake kinetics)for the model
% Detailed explanation goes here
......@@ -18,6 +18,6 @@ end
%% UPTAKE KINETICS
%prop, ac, fum, CO2, H2, for
model.coupledReactions.vmax = [37.7 0 0 0 0 0 0]';
model.coupledReactions.ks = [1 1 1 1 1 1 1]';
model.coupledReactions.vmax = [1.1738 0 0 0 0 0 0]';
model.coupledReactions.ks = [2.7 0 0 0 0 0 0]';
function [ output_args ] = plotExchangeFluxes(trajectory)
function [ f ] = plotExchangeFluxes(trajectory)
%PLOTRUN Plot the simulated trajectory
% Detailed explanation goes here
%
figure
f = figure;
% prep time coordinate: fluxes are valid between iteration time points
......@@ -35,7 +35,7 @@ function [ output_args ] = plotExchangeFluxes(trajectory)
plot(time, trajectory.FBA(i).fluxes(:,finalIds))
xlabel('Time (hours)')
ylabel('Fluxes (mmol/gDW/h)')
ylabel('Flux (mmol/gDW/h)')
title({string(trajectory.modelNames(i)), 'Coupled (non-zero) fluxes'})
legend(myLegend, 'Interpreter', 'none'); % no super/subscripting
end
......@@ -58,7 +58,7 @@ function [ output_args ] = plotExchangeFluxes(trajectory)
if finalIds(1) ~= -1
plot(time, trajectory.FBA(i).fluxes(:,finalIds))
xlabel('Time (hours)')
ylabel('Fluxes (mmol/gDW/h)')
ylabel('Flux (mmol/gDW/h)')
title({string(trajectory.modelNames(i)), 'Uncoupled (non-zero) exchange fluxes'})
legend(myLegend, 'Interpreter', 'none'); % no super/subscripting
end
......
function [ output_args ] = plotTrajectoryCmp( varargin )
function [ f ] = plotTrajectoryCmp( varargin )
%PLOTRUN Plot two trajectories together
% Expected arguments: trajectory1 trajectory2 label1 label2...
figure
f = figure;
runsToCmp = nargin / 2;
runsToCmp = nargin / 2;
numberOfPlots = 1 + length(varargin{1,1}.metaboliteNames);
numberOfPlots = 1 + length(varargin{1,1}.compoundNames);
xsize = 3;
ysize = ceil(numberOfPlots/3.0);
xsize = 3;
ysize = ceil(numberOfPlots/3.0);
plotSymbols = {'o', '-', 'x', '-.'};
plotSymbols = {'o', '-', 'x', '-.'};
providedLegend = {varargin{1,(runsToCmp + 1):nargin}};
myLegend = {};
providedLegend = {varargin{1,(runsToCmp + 1):nargin}};
myLegend = {};
subplot(ysize, xsize, 1)
subplot(ysize, xsize, 1)
% Biomass plots
% Biomass plots
for j = 1:runsToCmp
for k = 1:size(varargin{1,j}.biomass, 2)
plot(varargin{1,j}.time, varargin{1,j}.biomass(:, k) - varargin{1,j}.biomass(1, k), plotSymbols{j})
myLegend{length(myLegend) + 1} = strcat(providedLegend{j}, {' '}, varargin{1,j}.modelNames{k});
hold on
end
end
xlabel('Time (hours)')
ylabel('Concentration change (gDW/L)')
title('Biomass')
legend([myLegend{:}])
hold off
for i = 1:(numberOfPlots - 1)
subplot(ysize, xsize, i + 1)
for j = 1:runsToCmp
plot(varargin{1,j}.time, varargin{1,j}.metabolites(:, i), plotSymbols{j})
hold on
for k = 1:size(varargin{1,j}.biomass, 2)
plot(varargin{1,j}.time, varargin{1,j}.biomass(:, k) - varargin{1,j}.biomass(1, k), plotSymbols{j})
myLegend{length(myLegend) + 1} = strcat(providedLegend{j}, {' '}, varargin{1,j}.modelNames{k});
hold on
end
end
xlabel('Time (hours)')
ylabel('Concentration (mmol/L)')
title(varargin{1,1}.metaboliteNames(i))
ylabel('Concentration offset (gDW/L)')
title('Biomass')
legend([myLegend{:}])
hold off
end
for i = 1:(numberOfPlots - 1)
subplot(ysize, xsize, i + 1)
for j = 1:runsToCmp
plot(varargin{1,j}.time, varargin{1,j}.compounds(:, i), plotSymbols{j})
hold on
end
xlabel('Time (hours)')
ylabel('Concentration (mmol/L)')
title(varargin{1,1}.compoundNames(i))
hold off
end
end
function [ returnModels, extMetab ] = prepare773Model(speciesToConsider, directory, FBAsolver)
%PREPARE773MODEL Loading species given as index list in speciesToConsider
function [ returnModels, extMetab ] = prepareFBAmodel_773Agora(speciesToConsider, directory, FBAsolver)
%prepareFBAmodel Loading species given as index list in speciesToConsider
% Detailed explanation goes here
filenames = {
......@@ -837,22 +837,22 @@ for i = 1:length(speciesToConsider)
returnModels(i) = convertToOnlyIrrevReac(models(i));
end
% save external metabolites to file, sort & make unique for later loading
% save external compounds to file, sort & make unique for later loading
extMetab = [extMetab{:}]';
extMetab = unique(extMetab);
% prepare mapping to reactor metabolites
% prepare mapping to reactor compounds
for i = 1:length(speciesToConsider)
ids = [];
for j = 1:length(returnModels(i).coupledReactions.ReacID)
% get metabolite of reaction
metab = returnModels(i).COBRAmodel.mets(find(returnModels(i).COBRAmodel.S(:,returnModels(i).coupledReactions.ReacID(j))));
% get index in reactor metabolites
ids(length(ids) + 1) = find(ismember(extMetab, metab));
% get compound of reaction
compound = returnModels(i).COBRAmodel.mets(find(returnModels(i).COBRAmodel.S(:,returnModels(i).coupledReactions.ReacID(j))));
% get index in reactor compounds
ids(length(ids) + 1) = find(ismember(extMetab, compound));
end
returnModels(i).reactorMetaboliteIDs = ids;
returnModels(i).reactorCompoundIDs = ids;
end
end
function [ model ] = prepareFBAmodel_iSfu648Model(filename, FBAsolver)
%PREPAREFBAModel
%prepareFBAModel
% Load FBA model and, if necessary, adapt flux boundaries. Functions for
% doing this vary between CellNetAnalyzer and COBRA Toolbox, hence the
% switch over FBAsolver. Additionally, reaction indices for the NGAM and
......@@ -32,17 +32,20 @@ switch FBAsolver
ReactionIDName = COBRAmodel.rxns(IDs, :);
end
%prohibit acetate uptake
COBRAmodel.lb(531) = 0;
% reaction sense: 1 means: positive flux is metabolite excretion, -1 means: negative flux is excretion
Sense = ones(length(IDs), 1);
exchangeReactions = table(IDs', cellstr(ReactionIDName), Sense, 'VariableNames',{'ReacID' 'ReacName' 'SecretionSense'}, 'RowNames', strtrim(cellstr(num2str(IDs'))'));
% SUBSTRATES / PRODUCTS to couple to medium
IDs = [498 515 531 514]; %
IDs = [498 515 514]; %
% DUMMY VALUES, UPDATED in PARAMETRIZATION FUNCTION!
vmax = [10 10 10 0];
ks = [0.1 0.1 0.1 0];
inhibitedCoupledReactions = [0 0 0 0]; % never allow uptake through these reactions
vmax = [10 10 0];
ks = [0.1 0.1 0];
inhibitedCoupledReactions = [0 0 0]; % never allow uptake through these reactions
switch FBAsolver
case 1
ReacNames = CNAmodel.reacID(IDs, :);
......@@ -51,8 +54,8 @@ switch FBAsolver
end
coupledReactions = table(IDs', cellstr(ReacNames), exchangeReactions.SecretionSense(strtrim(cellstr(num2str(IDs'))')), vmax', ks', inhibitedCoupledReactions' ,'VariableNames',{'ReacID' 'ReacName' 'SecretionSense' 'vmax' 'ks' 'inhibited'}, 'RowNames', strtrim(cellstr(num2str(IDs'))'));
% couple model fluxes to reactor metabolites
reactorMetaboliteIDs = [1 2 3 4]; % Position: as in coupled reactions, number: refers to position in reactor metabolites
% couple model fluxes to reactor compounds
reactorCompoundIDs = [1 2 3]; % Position: as in coupled reactions, number: refers to position in reactor compounds
% prepare return values
switch FBAsolver
......@@ -66,6 +69,6 @@ model.biomassReac = biomassReac;
model.ngamReac = ngamReac;
model.exchangeReactions = exchangeReactions;
model.coupledReactions = coupledReactions;
model.reactorMetaboliteIDs = reactorMetaboliteIDs;
model.reactorCompoundIDs = reactorCompoundIDs;
model.FBAsolver = FBAsolver;
model.modelName = 'iMR539';