From 70dfc32ab95887d993d4a063f421bf682d66b7be Mon Sep 17 00:00:00 2001 From: Ivan Domenzain Date: Fri, 30 Sep 2022 17:11:13 +0200 Subject: [PATCH 1/4] feat: add ecFactory_test function --- code/ecFactory_test.m | 317 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 code/ecFactory_test.m diff --git a/code/ecFactory_test.m b/code/ecFactory_test.m new file mode 100644 index 0000000..9bc6640 --- /dev/null +++ b/code/ecFactory_test.m @@ -0,0 +1,317 @@ +%function [optStrain,remaining,step] = ecFactory_test(model,modelParam,expYield,results_folder,graphPlot) +graphPlot = false; +model = const_ecModel; +if ~isfolder('GECKO') + git clone --quiet --depth=1 https://github.com/SysBioChalmers/GECKO.git +end +mkdir(results_folder) +current = pwd; +%method parameters +tol = 1E-13; %numeric tolerance for determining non-zero enzyme usages +OEF = 2; %overexpression factor for enzyme targets +KDF = 0.5; %down-regulation factor for enzyme targets +step = 0; +%Parameters for FSEOF method +Nsteps = 16; %number of FBA steps in ecFSEOF +alphaLims = [0.5*expYield 2*expYield]; %biomass yield limits for ecFSEOF +lowerK = 0.5/2; +thresholds = [0.5 1.05]; %K-score thresholds for valid gene targets +delLimit = 0.05; %K-score limit for considering a target as deletion +%read file with essential genes list +essential = readtable('../data/essential_genes.txt','Delimiter','\t'); +essential = strtrim(essential.Ids); +%Get relevant rxn indexes +modelParam.targetIndx = find(strcmpi(model.rxns,modelParam.rxnTarget)); +modelParam.CUR_indx = find(strcmpi(model.rxns,modelParam.CSrxn)); +modelParam.prot_indx = find(strcmpi(model.rxns,'prot_pool_exchange')); +modelParam.growth_indx = find(strcmpi(model.rxns,modelParam.growthRxn)); +%ecModel verification steps +model = check_enzyme_fields(model); +if ~isempty(modelParam.targetIndx) + %Check if model can carry flux for the target rxn + flux = haveFlux(model,1-12,modelParam.rxnTarget); + if flux + disp(['* Your ecModel can carry flux through the reaction: ' model.rxnNames{modelParam.targetIndx}]) + else + disp(['* Your ecModel cannot carry flux through the reaction: ' model.rxnNames{modelParam.targetIndx} ', please check the applied constraints']) + end +else + error('The provided target reaction is not part of the ecModel.rxns field') +end +%output files for genes and rxn targets +file1 = 'results/genesResults_ecFSEOF.txt'; +file2 = 'results/rxnsResults_ecFSEOF.txt'; + +% 1.- Run FSEOF to find gene candidates +cd GECKO/geckomat/utilities/ecFSEOF +mkdir('results') +step = step+1; +disp([num2str(step) '.- **** Running ecFSEOF method (from GECKO utilities) ****']) +results = run_ecFSEOF(model,modelParam.rxnTarget,modelParam.CSrxn,alphaLims,Nsteps,file1,file2); +genes = results.geneTable(:,1); +disp(' ') +disp(['ecFSEOF returned ' num2str(length(genes)) ' targets']) +disp(' ') +%Format results table +geneShorts = results.geneTable(:,2); +k_scores = cell2mat(results.geneTable(:,3)); +actions = cell(numel(k_scores),1); +actions(k_scores>=thresholds(2)) = {'OE'}; +actions(k_scores0 + candidates = [candidates; model.enzymes(iB(i))]; + MWeigths = [MWeigths; model.MWs(iB(i))]; + pathways = [pathways; model.pathways(iB(i))]; + else + candidates = [candidates; {''}]; + MWeigths = [MWeigths; nan]; + pathways = [pathways; {''}]; + end +end +disp(' ') +%Get results table +candidates = table(genes,candidates,geneShorts,MWeigths,pathways,actions,k_scores,'VariableNames',{'genes' 'enzymes' 'shortNames' 'MWs' 'pathways' 'actions' 'k_scores'}); +%Keep results that comply with the specified K-score thresholds +disp(['Removing targets ' num2str(thresholds(1)) ' < K_score < ' num2str(thresholds(2))]) +toKeep = find((candidates.k_scores>=thresholds(2)|candidates.k_scores<=thresholds(1))); +candidates = candidates(toKeep,:); +disp([' * ' num2str(height(candidates)) ' gene targets remain']) +disp(' ') + +%2.- Add flux leak targets (those genes not optimal for production that may +%consume the product of interest. (probaly extend the approach to inmediate +%precurssors) +step = step+1; +cd (current) +disp([num2str(step) '.- **** Find flux leak targets to block ****']) +candidates = find_flux_leaks(candidates,modelParam.targetIndx,model); +disp([' * ' num2str(height(candidates)) ' gene targets remain']) +disp(' ') +% 3.- discard essential genes from deletion targets +step = step+1; +disp([num2str(step) '.- **** Removing essential genes from KD and KO targets list ****']) +[~,iB] = ismember(candidates.genes,essential); +toRemove = iB & candidates.k_scores<=delLimit; +candidates(toRemove,:) = []; +disp([' * ' num2str(height(candidates)) ' gene targets remain']) +disp(' ') +writetable(candidates,[results_folder '/candidates_L1.txt'],'Delimiter','\t','QuoteStrings',false); +proteins = strcat('draw_prot_',candidates.enzymes); +[~,enz_pos] = ismember(proteins,model.rxns); +candidates.enz_pos = enz_pos; +% 4.- Construct Genes-metabolites network for classification of targets +step = step+1; +disp([num2str(step) '.- **** Construct Genes-metabolites network for classification of targets ****']) +disp(' ') +%Get Genes-metabolites network +disp(' Constructing genes-metabolites graph') +disp(' ') +[GeneMetMatrix,~,Gconect] = getMetGeneMatrix(model,candidates.genes); +%Get independent genes from GeneMetMatrix +disp(' Obtain redundant vectors in genes-metabolites graph (redundant targets)') +disp(' ') +%generate gene-gene matrix and identify linearly independent targets +[indGenes,G2Gmatrix,~] = getGeneDepMatrix(GeneMetMatrix); +%find unique targets (with no isoenzymes or not part of complexes) +candidates.unique = indGenes; +%number of metabolites connected to each gene +candidates.conectivity = Gconect.mets_number; +%Get gene target groups (those connected to exactly the same metabolites) +[~,groups] = getGenesGroups(G2Gmatrix,candidates.genes); +candidates.groups = groups; + +% 5.- Enzyme usage variability analysis (EVA) and prioritization of targets +step = step+1; +disp([num2str(step) '.- **** Running EUVA for optimal production conditions (minimal biomass) ****']) +tempModel = model; +disp(' ') +disp(' - Fixed unit glucose uptake rate') +%Fix unit C source uptake +tempModel.lb(modelParam.CUR_indx) = (1-tol)*1; +tempModel.ub(modelParam.CUR_indx) = (1+tol)*1; +disp(' - Fixed suboptimal biomass production, according to provided experimental yield') +%Fix suboptimal experimental biomass yield conditions +V_bio = expYield*modelParam.CS_MW; +tempModel.lb(modelParam.growth_indx) = V_bio; +disp([' V_bio = ' num2str(V_bio) ' h-1']) +disp(' - Production rate constrained to its maximum attainable value') +%Get and fix optimal production rate +tempModel = setParam(tempModel, 'obj', modelParam.targetIndx, +1); +sol = solveLP(tempModel,1); +max_prod = sol.x(modelParam.targetIndx); +tempModel.lb(modelParam.targetIndx) = (1-tol)*max_prod; +tempModel.ub(modelParam.targetIndx) = (1+tol)*max_prod; +disp([' V_prod_max = ' num2str(max_prod) ' mmol/gDwh']) +modelParam.WT_prod = max_prod; +modelParam.V_bio = V_bio; + +disp(' ') +%Run FVA for all enzyme usages subject to fixed CUR and Grates +EVAtable = enzymeUsage_FVA(tempModel,candidates.enzymes); + +disp('* Discard targets according to EUVA results for optimal production ****') +%Classify targets according to enzyme variability ranges +candidateUsages = EVAtable.pU; +disp(' ') +candidates.EV_type = cell(height(candidates),1); +candidates.EV_type(:) = {''}; +idxs = find(EVAtable.minU<=tol & EVAtable.maxU<=tol); +candidates.EV_type(idxs) = {'unusable'}; +idxs = find(EVAtable.minU>tol); +candidates.EV_type(idxs) = {'essential'}; %enzymes needed for optimal production +idxs = find(EVAtable.minU<=tol & EVAtable.maxU>tol); +candidates.EV_type(idxs) = {'totally_variable'}; %enzymes that can take any flux (ussually isoenzymes) +idxs = find((EVAtable.minU./EVAtable.maxU)>=0.99 & EVAtable.minU>tol); +candidates.EV_type(idxs) = {'essential_tightly_const'}; %enzymes that are needed up to its maximum capacity +idxs = find(strcmpi(candidates.EV_type,'totally_variable') & candidateUsages>tol); +candidates.EV_type(idxs) = {'production_opt'}; %isoenzymes that are chosen for optimal production +idxs = find(strcmpi(candidates.EV_type,'production_opt') & (candidateUsages./EVAtable.maxU)>=0.99); +candidates.EV_type(idxs) = {'production_opt_tight'}; %isoenzymes that are chosen for optimal production, up to its maximum capacity +idxs = find(strcmpi(candidates.EV_type,'totally_variable') & candidateUsages<=tol); +candidates.EV_type(idxs) = {'unnecessary_prod'}; %isoenzymes that are not chosen for optimal production +%Append EUVA results to target candidates table +candidates.OE(strcmpi(candidates.actions,'OE')) = OEF; +candidates.OE(strcmpi(candidates.actions,'KD')) = KDF; +candidates.OE(strcmpi(candidates.actions,'KO')) = 0; +candidates.minUsage = EVAtable.minU; +candidates.maxUsage = EVAtable.maxU; +candidates.pUsage = candidateUsages; +%Discard enzymes +disp(' - Discard OE targets with lb=ub=0') +toRemove = (strcmpi(candidates.EV_type,'unusable') & strcmpi(candidates.actions,'OE')) | isnan(candidates.minUsage); +candidates(toRemove,:) = []; +disp(' - Discard enzymes essential for production from deletion targets') +toRemove = (strcmpi(candidates.EV_type,'essential_tightly_const') | strcmpi(candidates.EV_type,'essential')) & ... + (candidates.k_scores<=delLimit); +candidates(toRemove,:) = []; +disp(' - Discard isoenzyme groups for KD/KO that contain an optimal isoform (redundant groups that increase mutant complexity)') +toRemove = []; +for k=1:max(candidates.groups) + idx = find(candidates.groups==k & ~strcmpi(candidates.actions,'OE')); + if length(idx)>1 + if ~isempty(candidates.enzymes(idx(1))) & any(candidates.pUsage(idx)>0) + toRemove = [toRemove;idx]; + end + end +end +candidates(toRemove,:) = []; +disp(' ') +disp([' * ' num2str(height(candidates)) ' gene targets remain']) +disp(' ') + +%7.- EUVA for suboptimal biomasss production subject to a minimal (1%) +% production rate of the target product and a unit CS uptake rate +%Get max biomass +step = step+1; +disp(' ') +disp([num2str(step) '.- **** Running EUVA for reference strain ****']) +disp(' - Fixed unit glucose uptake rate') +disp(' - Production rate subject to a LB of 1% of its max. value') +disp(' - Biomass production fixed to its maximum attainable value') +tempModel = setParam(tempModel, 'obj', modelParam.growth_indx, +1); +tempModel.lb(modelParam.targetIndx) = 0.01*max_prod; +tempModel.ub(modelParam.targetIndx) = 1000; +sol = solveLP(tempModel,1); +maxVBio = sol.x(modelParam.growth_indx); +%Fix optimal biomass formation rate +tempModel.lb(modelParam.growth_indx) = (1-tol)*maxVBio; +tempModel.ub(modelParam.growth_indx) = (1+tol)*maxVBio; +%run EUVA for optimal biomass formation +EVAbio = enzymeUsage_FVA(tempModel,candidates.enzymes); +candidates.minUsageBio = EVAbio.minU; +candidates.maxUsageBio = EVAbio.maxU; +candidates.pUsageBio = EVAbio.pU; +disp(' ') +%discard something +disp('* Discard targets according to EUVA results for reference strain ****') +candidates = compare_EUVR(candidates); +disp(' - Discarding enzymes with inconsistent enzyme usage variability patterns') +toRemove = strcmpi(candidates.EUV_comparison,'embedded') | ... + (~strcmpi(candidates.actions,'OE') & contains(candidates.EUV_comparison,'up_')) | ... + (strcmpi(candidates.actions,'OE') & contains(candidates.EUV_comparison,'down_'));% |... +%disp(candidates(toRemove,:)) +candidates(toRemove,:) = []; +disp(' ') +disp([' ' num2str(height(candidates)) ' gene targets remain']) +disp(' ') + +step = step+1; +disp([num2str(step) '.- **** Rank targets by priority levels ****']) +disp(' ') +%Rank targets by priority +candidates.priority = zeros(height(candidates),1)+3; +candidates.priority(contains(candidates.EUV_comparison,'up_') | contains(candidates.EUV_comparison,'down_')) = 2; % second priority for genes with overlaped demand ranges +candidates.priority(contains(candidates.EUV_comparison,'_distinct')) = 1; %higher priority to the clearly up-down regulated genes +disp([' - ' num2str(sum(candidates.priority==1)) ' targets with priority level 1 (distinct enzyme demand levels between optimal production and optimal biomass cases)']) +disp([' - ' num2str(sum(candidates.priority==2)) ' targets with priority level 2 (overlapped enzyme demand levels between optimal production and optimal biomass cases)']) +disp([' - ' num2str(sum(candidates.priority==3)) ' targets with priority level 3 (other cases)']) +disp(' ') +%Rename enzyme variability type for KDs and KOs according to their +%variability ranges for maximum biomass production +disp(' * Classifying targets according to their enzyme usage variability range type') +idxs = ~strcmpi(candidates.actions,'OE') & candidates.pUsage < candidates.pUsageBio & candidates.pUsageBio>0 & ~contains(candidates.EV_type,'unnecessary'); +candidates.EV_type(idxs) = {'biomass_opt'}; +bioRatio = V_bio/maxVBio; +ratios = candidates.pUsage./candidates.pUsageBio; +idxs = ratios < bioRatio+1E-9 & ratios > bioRatio-1E-9; +candidates.EV_type(idxs) = {'biomass_coupled'}; +disp(' ') +writetable(candidates,[results_folder '/candidates_L2.txt'],'Delimiter','\t','QuoteStrings',false); +% 8.- Combine targets +step = step+1; +disp([num2str(step) '.- **** Find an optimal combination of remaining targets ****']) +disp(' ') +%Unconstrain CUR, unconstrain product formation +%and set a minimal biomass formation +tempModel = setParam(tempModel,'ub',modelParam.CUR_indx,1000); +tempModel = setParam(tempModel,'lb',modelParam.CUR_indx,0); +tempModel = setParam(tempModel,'ub',modelParam.growth_indx,1000); +tempModel = setParam(tempModel,'lb',modelParam.growth_indx,0.99*V_bio); +tempModel = setParam(tempModel,'ub',modelParam.targetIndx,1000); +tempModel = setParam(tempModel,'lb',modelParam.targetIndx,0); +%set Max product formation as objective function +tempModel = setParam(tempModel,'obj',modelParam.targetIndx,+1); +%constrain enzyme usages with optimal biomass formation profile (WT) +tempModel.lb(candidates.enz_pos(find(candidates.enz_pos))) = 0.99*candidates.pUsageBio(find(candidates.enz_pos)); +tempModel.ub(candidates.enz_pos(find(candidates.enz_pos))) = 1.01*candidates.maxUsageBio(find(candidates.enz_pos)); +%Run mechanistic validation of targets +% [optStrain,remaining] = constructMinimalMutant(tempModel,candidates,modelParam); +% %get a gene-mets graph with the remaining targets +% if graphPlot +% MetsIndxs = (~contains(optStrain.metNames,'prot_')); +% nodeMets = optStrain.mets(MetsIndxs); +% toKeep = (remaining.priority>0 & remaining.conectivity<15); +% [GeneMetMatrix,~,~] = getMetGeneMatrix(optStrain,remaining.genes); +% tempGMmatrix = GeneMetMatrix(:,toKeep); +% getMGgraph(tempGMmatrix,nodeMets,tempModel,'force',remaining(toKeep,:)); +% end +% disp([' * The predicted optimal strain contains ' num2str(height(remaining)) ' gene modifications']) +% disp(' ') +% +% cd (current) +% writetable(remaining,[results_folder '/candidates_L3.txt'],'Delimiter','\t','QuoteStrings',false); +% %Generate transporter targets file (lists a number of transport steps +% %with no enzymatic annotation that are relevant for enhancing target +% %product formation. +% origin = 'GECKO/geckomat/utilities/ecFSEOF/results/*'; +% copyfile(origin,results_folder) +% step = step+1; +% disp([num2str(step) '.- **** Find transporter reactions with no enzyme association predicted as targets by ecFSEOF ****']) +% disp(' ') +% rxnsTable = readtable([results_folder '/rxnsResults_ecFSEOF.txt'],'Delimiter','\t'); +% transpTargets = getTransportTargets(rxnsTable,tempModel); +% disp([' * ' num2str(height(transpTargets)) ' transport reaction targets were found']) +% disp(' ') +% writetable(transpTargets,[results_folder '/transporter_targets.txt'],'Delimiter','\t','QuoteStrings',false); +% delete([results_folder '/rxnsResults_ecFSEOF.txt']) +% delete([results_folder '/genesResults_ecFSEOF.txt']) +% %end \ No newline at end of file From 69adeba9930dc35b101abdb2dd96ed93a1053d91 Mon Sep 17 00:00:00 2001 From: Ivan Domenzain Date: Fri, 30 Sep 2022 17:11:30 +0200 Subject: [PATCH 2/4] feat: add randomized version of constructMinimalMutant --- code/constructMinimalMutant_random.m | 139 +++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 code/constructMinimalMutant_random.m diff --git a/code/constructMinimalMutant_random.m b/code/constructMinimalMutant_random.m new file mode 100644 index 0000000..0235b2f --- /dev/null +++ b/code/constructMinimalMutant_random.m @@ -0,0 +1,139 @@ +function [optMutant,remaining] = constructMinimalMutant_random(model,candidates,modelParam) +tol =-1E-12;%-1E-6; +%get mutant with all modifications +optMutant=model; +toRemove = []; +[candidates,~] = sortrows(candidates,{'priority' 'k_scores'},{'ascend' 'ascend'}); +%candidates = candidates(randperm(height(candidates)),:); +for i=1:height(candidates) + gene = candidates.genes(i); + action = candidates.actions(i); + mutF = 1;%candidates.OE(i); + enzIdx = candidates.enz_pos(i); + tempModel = optMutant; + + if enzIdx>0 + tempModel.ub(enzIdx) = 1.01*candidates.maxUsage(i); + tempModel.lb(enzIdx) = 0; + if tempModel.ub(enzIdx) <=tempModel.lb(enzIdx) + tempModel.lb(enzIdx) = 0.95*tempModel.ub(enzIdx); + end + optMutant = tempModel; + %for reactions without enzymatic reaction + + else + if strcmpi(action,'OE') + enzUsage = 1.01*candidates.maxUsage(i); + if enzUsage <= 1E-15 + enzUsage = 1.01*candidates.maxUsage(i); + end + else + enzUsage = candidates.pUsage(i); + if strcmpi(action,'KO') + action = {'KD'}; + enzUsage = 0; + end + end + modifications = {gene action mutF}; + + [tempModel,success] = getMutantModel(optMutant,modifications,enzUsage); + if success + optMutant = tempModel; + else + toRemove = [toRemove; i]; + end + end + +end + +if ~isempty(toRemove) + %disp('The following gene modifications are not compatible with the rest of remaining candidate targets') + %disp(candidates(toRemove,[1 2 3 6])) + candidates(toRemove,:) = []; +end + +optMutant = setParam(optMutant,'obj',modelParam.targetIndx,1); +%obtain optimal production rate and yield +[mutSol_r,~] = solveECmodel(optMutant,model,'pFBA',modelParam.prot_indx); +[mutSol_y,~] = solveECmodel(optMutant,model,'pFBA',modelParam.CUR_indx); +OptprodR = mutSol_y(modelParam.targetIndx);%mutSol_r(modelParam.targetIndx); +Optyield = mutSol_y(modelParam.targetIndx)/(mutSol_y(modelParam.CUR_indx)); +%Randomize order of targets +levelCandidates = candidates(randperm(height(candidates)),:); +counter = 0; +remaining = table(); +for i=1:height(levelCandidates) + %reverse modifications + gene = levelCandidates.genes(i); + action = levelCandidates.actions(i); + enzIdx = levelCandidates.enz_pos(i); + short = levelCandidates.shortNames{i}; + mutF = 1; + tempMutant = optMutant; + %revert mutation + if enzIdx>0 + saturationOpt = mutSol_r(enzIdx)/(optMutant.ub(enzIdx)+1E-15); + tempMutant.ub(enzIdx) = 1.01*model.ub(enzIdx); + tempMutant.lb(enzIdx) = 0.99*model.lb(enzIdx); + if tempMutant.ub(enzIdx) <=tempMutant.lb(enzIdx) + tempMutant.lb(enzIdx) = 0.95*tempMutant.ub(enzIdx); + end + + %for reactions without enzymatic reaction + else + enzUsage = 1E-12; + if strcmpi(action,'KO') + reversal = {'OE'}; + else + if strcmpi(action,'KD') + reversal = {'OE'}; + else + reversal = {'KD'}; + end + end + modifications = {gene reversal mutF}; + tempMutant = getMutantModel(optMutant,modifications,enzUsage); + saturationOpt = NaN; + end + %Get max WT production rate + mutsol_prod = solveECmodel(tempMutant,tempMutant,'pFBA',modelParam.prot_indx); + %Get max WT production yield + mutsol_yield = solveECmodel(tempMutant,tempMutant,'pFBA',modelParam.CUR_indx); + mutprodR = mutsol_prod(modelParam.targetIndx); + mutyield = mutsol_yield(modelParam.targetIndx)/(mutsol_yield(modelParam.CUR_indx)); + flag = true; + if enzIdx>0 && numel(enzIdx)==1 + saturationM = mutsol_yield(enzIdx)/(tempMutant.ub(enzIdx)+1E-15); + if (strcmpi(action,'OE') & saturationM <= (model.ub(enzIdx)/levelCandidates.maxUsage(i))) + flag = false; + end + + else + saturationM = NaN; + end + FC_y = mutyield/Optyield; + FC_p = mutprodR/OptprodR; + score = mean([FC_y,FC_p]); + %Discard genes that don't affect the optimal phenotype + %discard OE targets that show low saturation after reversing the + %modification + + if isnan(score) + score = 0; + end + + if flag && ... + (... + (score<=1+tol) || ... + (strcmpi(action,'OE') && saturationOpt >= 0.99) ...%%|| ((~strcmpi(action,'OE') && saturationOpt <= saturationM)) ... + ) + + remaining = [remaining;levelCandidates(i,:)]; + counter = counter+1; + else + optMutant = tempMutant; + end +end +remaining = sortrows(remaining,{'priority' 'k_scores'},{'ascend' 'descend'}); +remaining= removevars(remaining,{'enz_pos' 'OE' 'minUsage' 'maxUsage' 'pUsage' 'minUsageBio' 'maxUsageBio' 'pUsageBio'}); +end \ No newline at end of file From 64aa302717268515204254291a0e903d0c2f3b1b Mon Sep 17 00:00:00 2001 From: Ivan Domenzain Date: Fri, 30 Sep 2022 17:12:23 +0200 Subject: [PATCH 3/4] feat: add test_randperm live. script --- tutorials/test_randperm.mlx | Bin 0 -> 7642 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tutorials/test_randperm.mlx diff --git a/tutorials/test_randperm.mlx b/tutorials/test_randperm.mlx new file mode 100644 index 0000000000000000000000000000000000000000..058066d1594d6aa2501f1c25a9c431f1dacd966d GIT binary patch literal 7642 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 literal 0 HcmV?d00001 From c92ede331e7ce755f238c91ff8d652f759353c30 Mon Sep 17 00:00:00 2001 From: Ivan Domenzain Date: Fri, 30 Sep 2022 17:21:53 +0200 Subject: [PATCH 4/4] fix: typo in tutorials script --- .../2_phenylethanol_targets/transporter_targets.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tutorials/results/2_phenylethanol_targets/transporter_targets.txt b/tutorials/results/2_phenylethanol_targets/transporter_targets.txt index 1cf7771..f1e9b60 100644 --- a/tutorials/results/2_phenylethanol_targets/transporter_targets.txt +++ b/tutorials/results/2_phenylethanol_targets/transporter_targets.txt @@ -1,8 +1,8 @@ rxn_IDs rxnNames K_score grRules rxn_formula r_1128_REV citrate transport (reversible) 1000 YBR291C citrate[m] + isocitrate[c] => citrate[c] + isocitrate[m] -r_1112_REV AKG transporter, mitochonrial (reversible) 425.647803399839 YMR241W 2-oxoglutarate[m] + citrate[c] => 2-oxoglutarate[c] + citrate[m] +r_1112_REV AKG transporter, mitochonrial (reversible) 425.647803399838 YMR241W 2-oxoglutarate[m] + citrate[c] => 2-oxoglutarate[c] + citrate[m] r_1127_REV citrate transport (reversible) 13.4215454204906 YBR291C citrate[m] + phosphoenolpyruvate[c] => citrate[c] + phosphoenolpyruvate[m] -r_1194 L-glutamate transport 4.0525558176872 YPR021C L-glutamate[c] => L-glutamate[m] +r_1194 L-glutamate transport 4.05255581768719 YPR021C L-glutamate[c] => L-glutamate[m] r_1099 2-oxoadipate and 2-oxoglutarate transport 0.296253123520671 YOR222W or YPL134C 2-oxoadipic acid[m] + 2-oxoglutarate[c] => 2-oxoadipic acid[c] + 2-oxoglutarate[m] -r_3545 L-serine transport, cytoplasm-ER membrane 0.295624238597653 YKR039W L-serine[c] => L-serine[erm] -r_2132 oxoglutarate/malate exchange 0.225323081273778 YOR222W or YPL134C (S)-malate[c] + 2-oxoglutarate[m] => (S)-malate[m] + 2-oxoglutarate[c] +r_3545 L-serine transport, cytoplasm-ER membrane 0.295624238597654 YKR039W L-serine[c] => L-serine[erm] +r_2132 oxoglutarate/malate exchange 0.225323081273779 YOR222W or YPL134C (S)-malate[c] + 2-oxoglutarate[m] => (S)-malate[m] + 2-oxoglutarate[c]