Skip to content

Commit

Permalink
Merge pull request #3 from BenjaSanchez/feat/non-ecFSEOF-analysis
Browse files Browse the repository at this point in the history
feat: non-ecFSEOF analysis
  • Loading branch information
IVANDOMENZAIN authored Jul 3, 2022
2 parents 5e67a84 + f148214 commit 2c18a0a
Show file tree
Hide file tree
Showing 14 changed files with 694 additions and 830 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.DS_Store
3 changes: 0 additions & 3 deletions code/find_hemeTargets_Sce.m
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
%Clone GECKO and go to the right branch
git('clone https://github.com/SysBioChalmers/GECKO.git')
cd GECKO
git checkout feat/add_FSEOF_utilities
cd ..
clc
%Load model
load('../models/ecYeastGEM_batch.mat')
Expand Down
10 changes: 4 additions & 6 deletions code/getMutant.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
genes2mod = modifications(:,1);
actions = modifications(:,2);
OE = modifications(:,3);
pool_index = (strcmpi(model.rxnNames,'prot_pool_exchange'));
for i=1:length(genes2mod)
gene = genes2mod{i};
action = actions{i};
Expand All @@ -54,14 +53,10 @@
else
enzyme = [];
end
%Deletion mutants
switch action
%Deletion mutants
case 0
mutantModel = removeGenes(mutantModel,gene,false,false,false);
if ~isempty(enzUsage) && ~isempty(gene2modIndex)
releasedMass = enzUsage*mutantModel.MWs(gene2modIndex);
mutantModel.ub(pool_index) = mutantModel.ub(pool_index)+releasedMass;
end
%Overexpression mutants
case 1
if ~isempty(enzyme)
Expand Down Expand Up @@ -94,6 +89,9 @@
enzKcats = find(mutantModel.S(enzMetIndx,:));
enzKcats = enzKcats(1:end-1);
mutantModel.S(enzMetIndx,enzKcats) = mutantModel.S(enzMetIndx,enzKcats)./OEFactor;
% Don't allow overall expression to decrease:
enzRxn = find(contains(mutantModel.rxnNames,enzyme));
mutantModel.lb(enzRxn) = enzUsage/OEFactor;
end
%Change endogenous for Heterologous enzymes
case 3
Expand Down
135 changes: 135 additions & 0 deletions code/non-ecFSEOF-analysis/compareDist.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function results = compareDist

%Load model:
model = load('../../models/yeast801.mat');
model = model.model;

%Block alternative phosphofruktokinase:
model.ub(strcmp(model.rxns,'r_0887')) = 0; %ATP + sedohept-7P -> ADP + H+ + sedohept-1,7biP

%Make irreversible with RAVEN function:
model = ravenCobraWrapper(model);
model = convertToIrrev(model);

%Add heme reaction:
posH = strcmp(model.mets,'s_3714'); %heme a [cytoplasm]
model = addReaction(model, 'rEx', ...
'reactionName', 'heme exchange', ...
'metaboliteList', model.mets(posH), ...
'stoichCoeffList', -1, ...
'lowerBound', 0, ...
'upperBound', 1000);

%Analysis will be around the experimental biomass yield:
Ysx = 0.122; %gDW/g(gluc)
Ysx = Ysx*180; %gDW/mol(gluc)
Ysx = Ysx/1000; %gDW/mmol(gluc)

%Simulation:
results.model = model;
results.glucose = compare_substrate(model,'heme exchange','glucose',Ysx);

%Create gene table:
results.geneTable = cell(length(results.glucose.genes),3);
results.geneTable(:,1) = results.glucose.genes;
results.geneTable(:,2) = results.glucose.geneNames;
results.geneTable(:,3) = num2cell(results.glucose.k_genes);

end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function FC = compare_substrate(model,product,substrate,Ysx)

%Simulate WT (100% growth):
FC.flux_WT = simulateGrowth(model,product,substrate,1);

%Simulate forced (X% growth and the rest towards product) based on yield:
posX = strcmp(model.rxnNames,'growth');
alphaExp = Ysx/FC.flux_WT(posX);
alpha = (alphaExp/2):(alphaExp/10):(2*alphaExp);
FC.alpha = alpha;
v_matrix = zeros(length(model.rxns),length(alpha));
k_matrix = zeros(length(model.rxns),length(alpha));
for i = 1:length(alpha)
FC.flux_MAX = simulateGrowth(model,product,substrate,alpha(i));
v_matrix(:,i) = FC.flux_MAX;
k_matrix(:,i) = FC.flux_MAX./FC.flux_WT;
end

%Generate rxn equations:
rxnEqs = printRxnFormula(model,model.rxns,true,true,true);

%Take out rxns with no grRule:
withGR = ~cellfun(@isempty,model.grRules);
v_matrix = v_matrix(withGR,:);
k_matrix = k_matrix(withGR,:);
gene_rxn = model.rxnGeneMat(withGR,:);
FC.rxns = [model.rxns(withGR) model.rxnNames(withGR) model.grRules(withGR) rxnEqs(withGR)];

%Filter out rxns that are always zero -> k=0/0=NaN:
non_nan = sum(~isnan(k_matrix),2) > 0;
v_matrix = v_matrix(non_nan,:);
k_matrix = k_matrix(non_nan,:);
gene_rxn = gene_rxn(non_nan,:);
FC.rxns = FC.rxns(non_nan,:);

%Replace remaining NaNs with 1s:
k_matrix(isnan(k_matrix)) = 1;

%Replace any Inf value with 1000 (maximum value is ~700):
k_matrix(isinf(k_matrix)) = 1000;

%Filter out values that are inconsistent at different alphas:
always_down = sum(k_matrix <= 1,2) == length(alpha);
always_up = sum(k_matrix >= 1,2) == length(alpha);
incons_rxns = always_down + always_up == 0;
incons_genes = sum(gene_rxn(incons_rxns,:),1) > 0;
incons_rxns = sum(gene_rxn(:,incons_genes),2) > 0;
v_matrix = v_matrix(~incons_rxns,:);
k_matrix = k_matrix(~incons_rxns,:);
gene_rxn = gene_rxn(~incons_rxns,:);
FC.rxns = FC.rxns(~incons_rxns,:);

%Order from highest to lowest k:
FC.k_rxns = mean(k_matrix,2);
[~,order] = sort(FC.k_rxns,'descend');
FC.k_rxns = FC.k_rxns(order,:);
FC.v_matrix = v_matrix(order,:);
FC.k_matrix = k_matrix(order,:);
gene_rxn = gene_rxn(order,:);
FC.rxns = FC.rxns(order,:);

%Create list of remaining genes and filter out any inconsistent score:
FC.genes = model.genes(sum(gene_rxn,1) > 0);
FC.geneNames = model.geneShortNames(sum(gene_rxn,1) > 0);
FC.k_genes = zeros(size(FC.genes));
gene_rxn = gene_rxn(:,sum(gene_rxn,1) > 0);
cons_genes = false(size(FC.genes));
for i = 1:length(FC.genes)
k_set = FC.k_rxns(gene_rxn(:,i) > 0);
always_down = sum(k_set <= 1) == length(k_set);
always_up = sum(k_set >= 1) == length(k_set);
cons_genes(i) = always_down + always_up == 1;
FC.k_genes(i) = mean(k_set);
end
FC.genes = FC.genes(cons_genes);
FC.geneNames = FC.geneNames(cons_genes);
FC.k_genes = FC.k_genes(cons_genes);

%Filter any value between mean(alpha) and 1:
unchanged = (FC.k_genes >= mean(alpha) - 1e-3) + (FC.k_genes <= 1 + 1e-3) == 2;
FC.genes = FC.genes(~unchanged);
FC.geneNames = FC.geneNames(~unchanged);
FC.k_genes = FC.k_genes(~unchanged);

%Order from highest to lowest k:
[~,order] = sort(FC.k_genes,'descend');
FC.genes = FC.genes(order,:);
FC.geneNames = FC.geneNames(order,:);
FC.k_genes = FC.k_genes(order,:);

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
62 changes: 62 additions & 0 deletions code/non-ecFSEOF-analysis/simulateGrowth.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function flux = simulateGrowth(model,rxn,substrate,alpha)

if strcmp(substrate,'glucose')
model.ub(strcmp(model.rxnNames,'D-glucose exchange')) = 0;
model.ub(strcmp(model.rxnNames,'D-glucose exchange (reversible)')) = 1;
model.ub(strcmp(model.rxnNames,'ethanol exchange')) = 1000;
model.ub(strcmp(model.rxnNames,'ethanol exchange (reversible)')) = 0;
elseif strcmp(substrate,'ethanol')
model.ub(strcmp(model.rxnNames,'D-glucose exchange')) = 1000;
model.ub(strcmp(model.rxnNames,'D-glucose exchange (reversible)')) = 0;
model.ub(strcmp(model.rxnNames,'ethanol exchange')) = 0;
model.ub(strcmp(model.rxnNames,'ethanol exchange (reversible)')) = 1;
end

%Positions of biomass & target rxn:
posX = strcmp(model.rxnNames,'growth');
posP = strcmp(model.rxnNames,rxn);

%Max growth:
sol = optModel(model,posX,+1);

%Fix growth suboptimal and then max product:
model.lb(posX) = sol.x(posX)*0.999*alpha;
sol = optModel(model,posP,+1);

%Fix also product and minimize fluxes:
model.lb(posP) = sol.x(posP)*0.999;
sol = optModel(model,1:length(model.rxns),-1);
flux = sol.x;

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function sol = optModel(model,pos,c,base_sol)

if length(pos) == 1
rxn_code = model.rxns{pos};
if strcmp(rxn_code(end-3:end),'_REV')
rev_pos = strcmp(model.rxns,rxn_code(1:end-4));
else
rev_pos = strcmp(model.rxns,[rxn_code '_REV']);
end
model.lb(rev_pos) = 0;
model.ub(rev_pos) = 0;
end

model.c = zeros(size(model.rxns));
model.c(pos) = c;
sol = optimizeCbModel(model);

if isempty(sol.x) && length(pos) == 1
model.lb(rev_pos) = base_sol.x(rev_pos);
model.ub(rev_pos) = base_sol.x(rev_pos);
sol = optimizeCbModel(model);
end

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
23 changes: 10 additions & 13 deletions code/robust_ecFSEOF.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
% clone GECKO
git ('clone https://github.com/SysBioChalmers/GECKO')
cd GECKO
git checkout feat/add_FSEOF_utilities
%Get model parameters
cd geckomat
parameters = getModelParameters;
Expand All @@ -23,12 +22,12 @@
cd utilities/ecFSEOF
mkdir('results')
results = run_ecFSEOF(model,rxnTarget,c_source,alphaLims,Nsteps,file1,file2);
genes = results.genes;
genes = results.geneTable(:,1);
disp(['ecFSEOF yielded ' num2str(length(genes)) ' targets'])
disp(' ')
%Format results table
geneShorts = results.geneNames;
actions = results.k_genes;
geneShorts = results.geneTable(:,2);
actions = cell2mat(results.geneTable(:,3));
actions(actions<0.5) = 0;
actions(actions>1) = 1;
MWeigths = [];
Expand All @@ -45,12 +44,13 @@
end
end
%Get results files structures
candidates = table(genes,candidates,geneShorts,MWeigths,actions,results.k_genes,'VariableNames',{'genes' 'enzymes' 'shortNames' 'MWs' 'actions' 'k_scores'});
candidates = table(genes,candidates,geneShorts,MWeigths,actions,cell2mat(results.geneTable(:,3)),'VariableNames',{'genes' 'enzymes' 'shortNames' 'MWs' 'actions' 'k_scores'});
% Keep top results
%candidates = candidates(((candidates.actions==1)|(candidates.actions==0)),:);
toKeep = find((candidates.k_scores>=thresholds(2)|candidates.k_scores<=thresholds(1)));
candidates = candidates(toKeep,:);
cd (current)
candidates = sortrows(candidates,{'k_scores', 'genes'}, {'descend', 'ascend'});
writetable(candidates,[resultsFolder '/candidates_ecFSEOF.txt'],'Delimiter','\t','QuoteStrings',false);
disp(['Remove targets ' num2str(thresholds(1)) ' < K_score < ' num2str(thresholds(2))])
disp([num2str(height(candidates)) ' gene targets remain'])
Expand Down Expand Up @@ -100,6 +100,7 @@
candidates.pUsage = candidateUsages;
%Generate table with FVA results
t = table(candidates.enzymes,FVAtable.minU,FVAtable.maxU,FVAtable.ranges,candidateUsages,'VariableNames',{'enzNames' 'minUsages' 'maxUsages' 'ranges' 'pUsages'});
candidates = sortrows(candidates,{'k_scores', 'genes'}, {'descend', 'ascend'});
writetable(candidates,[resultsFolder '/candidates_enzUsageFVA.txt'],'Delimiter','\t','QuoteStrings',false);
%Discard enzymes whose usage LB = UB = 0
tempMat = table2array(t(:,[2 3]));
Expand All @@ -126,6 +127,7 @@
disp('Discard gene modifications with a negative impact on product yield')
disp([num2str(height(candidates)) ' gene targets remain'])
disp(' ')
candidates = sortrows(candidates,{'k_scores', 'genes'}, {'descend', 'ascend'});
writetable(candidates,[resultsFolder '/candidates_mech_validated.txt'],'Delimiter','\t','QuoteStrings',false);
% Assess genes redundancy
%Get Genes-metabolites network
Expand Down Expand Up @@ -189,7 +191,7 @@
disp('Discard genes with priority level = 0')
disp([num2str(height(candidates)) ' gene targets remain'])
disp(' ')
candidates = sortrows(candidates,'priority','ascend');
candidates = sortrows(candidates,{'priority', 'k_scores', 'genes'}, {'ascend', 'descend', 'ascend'});
writetable(candidates,[resultsFolder '/candidates_priority.txt'],'Delimiter','\t','QuoteStrings',false);
% get optimal strain according to priority candidates
disp('Constructing optimal strain')
Expand All @@ -202,6 +204,7 @@
filtered.actions = actions;
disp([num2str(height(filtered)) ' gene targets remain'])
disp(' ')
filtered = sortrows(filtered,{'priority', 'k_scores', 'genes'}, {'ascend', 'descend', 'ascend'});
writetable(filtered,[resultsFolder '/compatible_genes_results.txt'],'Delimiter','\t','QuoteStrings',false);
origin = 'GECKO/geckomat/utilities/ecFSEOF/results/*';
copyfile(origin,resultsFolder)
Expand All @@ -214,7 +217,6 @@
FoldChanges = [];
CUR_indx = indexes(1);
targetIndx = indexes(2);
medianUsage = (candidates.maxUsage-candidates.minUsage)/2.001;
%Index to minimize (bi-level optimization)
minIndex = find(contains(tempModel.rxnNames,'prot_pool'));
for i=1:height(candidates)
Expand All @@ -223,12 +225,7 @@
action = candidates.actions(i);
OEf = candidates.OE(i);
modifications = {gene action OEf};
if action == 0
pUsage = candidates.maxUsage(i);
else
pUsage = medianUsage(i);
end
mutantModel = getMutant(tempModel,modifications,pUsage);
mutantModel = getMutant(tempModel,modifications,candidates.pUsage(i));
[mutSolution,~] = solveECmodel(mutantModel,mutantModel,'pFBA',minIndex);
if ~isempty(mutSolution)
yield = mutSolution(targetIndx)/mutSolution(CUR_indx);
Expand Down
Binary file added models/yeast801.mat
Binary file not shown.
Loading

0 comments on commit 2c18a0a

Please sign in to comment.