strainOptimizer 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- strainOptimizer/__init__.py +12 -0
- strainOptimizer/analysis/FCC.py +109 -0
- strainOptimizer/analysis/__init__.py +4 -0
- strainOptimizer/analysis/dataset.py +73 -0
- strainOptimizer/analysis/ecGEM_utils.py +47 -0
- strainOptimizer/analysis/enzyme_variety_analysis.py +139 -0
- strainOptimizer/analysis/etfl_utils.py +54 -0
- strainOptimizer/analysis/flux_variety_analysis.py +1 -0
- strainOptimizer/analysis/model_process.py +512 -0
- strainOptimizer/analysis/network.py +251 -0
- strainOptimizer/analysis/optimal_yield.py +37 -0
- strainOptimizer/analysis/protein_process.py +737 -0
- strainOptimizer/etfl/__init__.py +0 -0
- strainOptimizer/etfl/analysis/__init__.py +0 -0
- strainOptimizer/etfl/analysis/dynamic.py +633 -0
- strainOptimizer/etfl/analysis/summary.py +103 -0
- strainOptimizer/etfl/analysis/utils.py +33 -0
- strainOptimizer/etfl/core/__init__.py +3 -0
- strainOptimizer/etfl/core/allocation.py +845 -0
- strainOptimizer/etfl/core/carbohydrate.py +36 -0
- strainOptimizer/etfl/core/dna.py +60 -0
- strainOptimizer/etfl/core/enzyme.py +152 -0
- strainOptimizer/etfl/core/expression.py +315 -0
- strainOptimizer/etfl/core/genes.py +237 -0
- strainOptimizer/etfl/core/ion.py +36 -0
- strainOptimizer/etfl/core/lipid.py +36 -0
- strainOptimizer/etfl/core/macromolecule.py +102 -0
- strainOptimizer/etfl/core/memodel.py +2163 -0
- strainOptimizer/etfl/core/reactions.py +273 -0
- strainOptimizer/etfl/core/rna.py +129 -0
- strainOptimizer/etfl/core/thermomemodel.py +112 -0
- strainOptimizer/etfl/data/__init__.py +0 -0
- strainOptimizer/etfl/data/ecoli.py +1064 -0
- strainOptimizer/etfl/data/ecoli_utils.py +65 -0
- strainOptimizer/etfl/debugging/__init__.py +1 -0
- strainOptimizer/etfl/debugging/debugging.py +400 -0
- strainOptimizer/etfl/integration/__init__.py +0 -0
- strainOptimizer/etfl/integration/transcriptomics.py +82 -0
- strainOptimizer/etfl/io/__init__.py +0 -0
- strainOptimizer/etfl/io/dict.py +938 -0
- strainOptimizer/etfl/io/json.py +70 -0
- strainOptimizer/etfl/optim/__init__.py +0 -0
- strainOptimizer/etfl/optim/config.py +87 -0
- strainOptimizer/etfl/optim/constraints.py +307 -0
- strainOptimizer/etfl/optim/utils.py +500 -0
- strainOptimizer/etfl/optim/variables.py +210 -0
- strainOptimizer/etfl/tests/__init__.py +0 -0
- strainOptimizer/etfl/tests/small_model.py +400 -0
- strainOptimizer/etfl/utils/__init__.py +0 -0
- strainOptimizer/etfl/utils/parsing.py +115 -0
- strainOptimizer/etfl/utils/utils.py +87 -0
- strainOptimizer/io.py +68 -0
- strainOptimizer/manipulation/__init__.py +0 -0
- strainOptimizer/manipulation/constraint/__init__.py +2 -0
- strainOptimizer/manipulation/constraint/enzyme.py +129 -0
- strainOptimizer/manipulation/constraint/reaction.py +11 -0
- strainOptimizer/manipulation/constraint/total_resource_allocation.py +122 -0
- strainOptimizer/manipulation/integration/__init__.py +1 -0
- strainOptimizer/manipulation/integration/gimme.py +121 -0
- strainOptimizer/manipulation/integration/proteome.py +2 -0
- strainOptimizer/manipulation/integration/transcriptome.py +46 -0
- strainOptimizer/manipulation/mainFunction.py +621 -0
- strainOptimizer/manipulation/model_process.py +536 -0
- strainOptimizer/manipulation/protein_process.py +737 -0
- strainOptimizer/manipulation/variable/__init__.py +6 -0
- strainOptimizer/manipulation/variable/enzyme.py +52 -0
- strainOptimizer/manipulation/variable/metabolite.py +2 -0
- strainOptimizer/manipulation/variable/reaction.py +2 -0
- strainOptimizer/simulation/FBA.py +14 -0
- strainOptimizer/simulation/MOMA.py +152 -0
- strainOptimizer/simulation/MOPA.py +162 -0
- strainOptimizer/simulation/TFA.py +123 -0
- strainOptimizer/simulation/__init__.py +8 -0
- strainOptimizer/simulation/ecYeastFlux.py +434 -0
- strainOptimizer/simulation/pFBA.py +32 -0
- strainOptimizer/simulation/pprotFBA.py +156 -0
- strainOptimizer/simulation/utils.py +42 -0
- strainOptimizer/strainDesign/__init__.py +7 -0
- strainOptimizer/strainDesign/ecFactory/__init__.py +2 -0
- strainOptimizer/strainDesign/ecFactory/ecFactory_other.py +309 -0
- strainOptimizer/strainDesign/ecFactory/ecfseof.py +386 -0
- strainOptimizer/strainDesign/ecFactory/find_min_sets.py +109 -0
- strainOptimizer/strainDesign/ecFactory/run_ecFactory.py +424 -0
- strainOptimizer/strainDesign/iBridge/__init__.py +6 -0
- strainOptimizer/strainDesign/iBridge/ibridge.py +486 -0
- strainOptimizer/strainDesign/workflow_engine.py +396 -0
- strainOptimizer/visualization/__init__.py +1 -0
- strainOptimizer/visualization/phase_plane.py +85 -0
- strainoptimizer-0.1.0.dist-info/METADATA +161 -0
- strainoptimizer-0.1.0.dist-info/RECORD +93 -0
- strainoptimizer-0.1.0.dist-info/WHEEL +5 -0
- strainoptimizer-0.1.0.dist-info/licenses/LICENSE +21 -0
- strainoptimizer-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from strainOptimizer.simulation import mopa,moma
|
|
2
|
+
|
|
3
|
+
def calculate_FCC_by_abundance(protID,model,productID,c_source='r_1714_REV', c_uptake=10, growthID='r_2111',objective='r_4046',objective_direction='max',delta_conc=1):
|
|
4
|
+
"""
|
|
5
|
+
Calculate the flux control coefficient (FCC) for a given product and growth reaction by disturb enzyme abundance.
|
|
6
|
+
|
|
7
|
+
Args:
|
|
8
|
+
model (cobra.Model): The GEM model object.
|
|
9
|
+
c_source (str): The reaction ID of the carbon source uptake reaction. default is 'r_1714_REV' (glucose uptake).
|
|
10
|
+
c_uptake (float): The uptake rate of the carbon source.
|
|
11
|
+
productID (str): The reaction ID of the product output reaction.
|
|
12
|
+
growthID (str): The reaction ID of the growth reaction.
|
|
13
|
+
protID (str): The protein ID to calculate FCC for.
|
|
14
|
+
objective (str): The reaction ID of the objective reaction. default is NGAM (r_4046).
|
|
15
|
+
objective_direction (str): The direction of the objective reaction. 'max' or 'min'. default is 'max'.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
tuple: FCCg, FCCp
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
# calculate the reference strain by maximizing NGAM
|
|
22
|
+
# ref_growth=0.2
|
|
23
|
+
with model:
|
|
24
|
+
model.reactions.get_by_id(c_source).bounds = (c_uptake, c_uptake) # set uptake rate
|
|
25
|
+
model.objective = growthID
|
|
26
|
+
model.objective_direction='max'
|
|
27
|
+
ref_growth=model.slim_optimize()/4 # set growth rate to 25% of max to allow for production
|
|
28
|
+
model.objective=productID
|
|
29
|
+
model.objective_direction='max'
|
|
30
|
+
max_production=model.slim_optimize()
|
|
31
|
+
ref_production=max_production/4
|
|
32
|
+
model.reactions.get_by_id(productID).bounds = (ref_production, 1000)
|
|
33
|
+
model.reactions.get_by_id(growthID).bounds = (ref_growth, 1000) # set growth reaction bounds
|
|
34
|
+
|
|
35
|
+
model.objective = objective # NGAM maximize as objective
|
|
36
|
+
model.objective_direction=objective_direction
|
|
37
|
+
ref_solution= model.optimize()
|
|
38
|
+
|
|
39
|
+
# calculate FCCg and FCCp
|
|
40
|
+
with model:
|
|
41
|
+
# overexpression for target protein
|
|
42
|
+
ref_conc=ref_solution.fluxes[protID]
|
|
43
|
+
new_conc=ref_conc*(1+delta_conc) # increase protein concentration by delta_conc
|
|
44
|
+
# set the protein concentration
|
|
45
|
+
model.reactions.get_by_id(protID).lower_bound= new_conc
|
|
46
|
+
|
|
47
|
+
solution=mopa(model,reference_solution=ref_solution,linear=True)
|
|
48
|
+
# solution=moma(model,reference_solution=ref_solution,linear=False)
|
|
49
|
+
|
|
50
|
+
new_growth=solution.fluxes[growthID]
|
|
51
|
+
new_production=solution.fluxes[productID]
|
|
52
|
+
|
|
53
|
+
# FCCg
|
|
54
|
+
FCCg= ((new_growth-ref_growth)/ref_growth)/delta_conc
|
|
55
|
+
# calculate FCCp
|
|
56
|
+
FCCp=((new_production-ref_production)/ref_production)/delta_conc
|
|
57
|
+
# print('growth:',new_growth,'vs',ref_growth,'production:',new_production,'vs',ref_production)
|
|
58
|
+
|
|
59
|
+
return FCCg, FCCp
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def calculate_FCC_by_kcat(protID,model,productID, c_uptake=10, growthID='r_2111',delta_kcat=1):
|
|
63
|
+
'''
|
|
64
|
+
Calculate the flux control coefficient (FCC) for a given product and growth reaction by disturb enzyme kcat.
|
|
65
|
+
v/kcat<=protein_pool/MW
|
|
66
|
+
v/(kcat*(1+delta_kcat))<=protein_pool/MW
|
|
67
|
+
therefore, disturb kcat could be processed by modify the draw protein reaction coefficient
|
|
68
|
+
v/kcat<=protein_pool*(1+delta_kcat)/MW
|
|
69
|
+
v/kcat<=protein_pool/(MW/(1+delta_kcat))
|
|
70
|
+
MW'=MW/(1+delta_kcat)
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
model (cobra.Model): The GEM model object.
|
|
74
|
+
c_uptake (float): The uptake rate of the carbon source.
|
|
75
|
+
productID (str): The reaction ID of the product output reaction.
|
|
76
|
+
growthID (str): The reaction ID of the growth reaction.
|
|
77
|
+
protID (str): The protein ID to calculate FCC for.
|
|
78
|
+
'''
|
|
79
|
+
c_source='r_1714_REV' # glucose uptake reaction
|
|
80
|
+
model.reactions.get_by_id(c_source).bounds = 0, c_uptake # set uptake rate
|
|
81
|
+
with model:
|
|
82
|
+
model.objective=productID
|
|
83
|
+
model.objective_direction='max'
|
|
84
|
+
ref_production=model.slim_optimize()
|
|
85
|
+
|
|
86
|
+
model.objective = growthID
|
|
87
|
+
model.objective_direction='max'
|
|
88
|
+
ref_growth=model.slim_optimize()
|
|
89
|
+
|
|
90
|
+
# desturbe kcat
|
|
91
|
+
with model:
|
|
92
|
+
prot_pool=model.metabolites.get_by_id('prot_pool[c]')
|
|
93
|
+
ref_mw=model.reactions.get_by_id(protID).metabolites[prot_pool]
|
|
94
|
+
model.reactions.get_by_id(protID).metabolites[prot_pool]=ref_mw/(1+delta_kcat)
|
|
95
|
+
|
|
96
|
+
model.objective = productID
|
|
97
|
+
model.objective_direction='max'
|
|
98
|
+
new_production=model.slim_optimize()
|
|
99
|
+
|
|
100
|
+
model.objective = growthID
|
|
101
|
+
model.objective_direction='max'
|
|
102
|
+
new_growth=model.slim_optimize()
|
|
103
|
+
|
|
104
|
+
FCCg=((new_growth-ref_growth)/ref_growth)/delta_kcat
|
|
105
|
+
FCCp=((new_production-ref_production)/ref_production)/delta_kcat
|
|
106
|
+
|
|
107
|
+
return FCCg,FCCp
|
|
108
|
+
|
|
109
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
'''Load standard datasets foe strain design algorithm evaluation
|
|
3
|
+
'''
|
|
4
|
+
|
|
5
|
+
import pandas as pd
|
|
6
|
+
import os
|
|
7
|
+
# get the path of this file
|
|
8
|
+
FILE_PATH = os.path.dirname(os.path.abspath(__file__))
|
|
9
|
+
def load_experiment_targets(product:str, data_dir=FILE_PATH+'/../../../data/experiment_targets'):
|
|
10
|
+
'''Load experiment targets for a specific product
|
|
11
|
+
'''
|
|
12
|
+
available_products = [f.replace('_exp_targets.tsv','') for f in os.listdir(data_dir) if f.endswith('_exp_targets.tsv')]
|
|
13
|
+
if product not in available_products:
|
|
14
|
+
print('Available products:', available_products)
|
|
15
|
+
raise ValueError('The product %s is not available!' % product)
|
|
16
|
+
else:
|
|
17
|
+
df = pd.read_csv(os.path.join(data_dir, product+'_exp_targets.tsv'), sep='\t', index_col=0)
|
|
18
|
+
return df
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def calculate_exp_consistency(predict_result, exp_data, show=True, merge_ko_kd=False):
|
|
22
|
+
'''
|
|
23
|
+
Calculate the experimental consistency of the prediction results by comparing the predicted gene targets with the experimental gene targets.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
merge_ko_kd: if True, treat KO and KD as one down-regulation category ('KD') before comparison.
|
|
27
|
+
'''
|
|
28
|
+
predict_result = predict_result[predict_result['action'].isin(['OE', 'KD', 'KO'])].copy()
|
|
29
|
+
exp_data = exp_data.copy()
|
|
30
|
+
|
|
31
|
+
if merge_ko_kd:
|
|
32
|
+
predict_result['action'] = predict_result['action'].replace('KO', 'KD')
|
|
33
|
+
exp_data['action'] = exp_data['action'].replace('KO', 'KD')
|
|
34
|
+
|
|
35
|
+
predict_group = predict_result.groupby('action')
|
|
36
|
+
exp_group = exp_data.groupby('action')
|
|
37
|
+
exp_consistency = dict()
|
|
38
|
+
overall_exp_num = 0
|
|
39
|
+
overall_hit_num = 0
|
|
40
|
+
overall_predict_num = 0
|
|
41
|
+
for key in exp_group.groups.keys():
|
|
42
|
+
exp_geneList = exp_group.get_group(key).index.tolist()
|
|
43
|
+
try:
|
|
44
|
+
predict_geneList = predict_group.get_group(key).index.tolist()
|
|
45
|
+
except:
|
|
46
|
+
predict_geneList = []
|
|
47
|
+
hit_geneList = list(set(exp_geneList).intersection(set(predict_geneList)))
|
|
48
|
+
overall_exp_num += len(exp_geneList)
|
|
49
|
+
overall_hit_num += len(hit_geneList)
|
|
50
|
+
overall_predict_num += len(predict_geneList)
|
|
51
|
+
exp_consistency[key] = {'exp': exp_geneList, 'predict': predict_geneList, 'hit': hit_geneList,
|
|
52
|
+
'exp_num': len(exp_geneList), 'hit_num': len(hit_geneList),
|
|
53
|
+
'consistency': len(set(exp_geneList).intersection(set(hit_geneList))) / len(
|
|
54
|
+
exp_geneList)}
|
|
55
|
+
if overall_predict_num==0:
|
|
56
|
+
return None
|
|
57
|
+
exp_consistency['overall'] = {'exp_num': overall_exp_num, 'hit_num': overall_hit_num,
|
|
58
|
+
'predict_num': overall_predict_num,
|
|
59
|
+
'consistency': overall_hit_num / overall_exp_num,
|
|
60
|
+
'precision': overall_hit_num / overall_predict_num}
|
|
61
|
+
|
|
62
|
+
if show==True:
|
|
63
|
+
for key in exp_consistency.keys():
|
|
64
|
+
print(f'{key}:')
|
|
65
|
+
print(exp_consistency[key])
|
|
66
|
+
|
|
67
|
+
return exp_consistency
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def gene_id_to_name(geneIDlist,annotation_file=FILE_PATH+'/../../../data/s288c_geneNames.csv'):
|
|
71
|
+
df=pd.read_csv(annotation_file,index_col=0)
|
|
72
|
+
df_geneName=df[df.index.isin(geneIDlist)]['geneName']
|
|
73
|
+
return df_geneName
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# date : 2024/3/20
|
|
3
|
+
# author : wangh
|
|
4
|
+
import pandas as pd
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def prepare_prot_solution_for_ec(solution, enzymeIDlist=None):
|
|
8
|
+
'''Extract the protein abundances result from solution for ecGEM model.
|
|
9
|
+
parameters:
|
|
10
|
+
solution: Cobra solution
|
|
11
|
+
enzymeIDlist: a list of enzyme ID(optional)
|
|
12
|
+
return:
|
|
13
|
+
prots_solution: pd.Series, the protein abundances result
|
|
14
|
+
'''
|
|
15
|
+
prots_solution = pd.Series()
|
|
16
|
+
|
|
17
|
+
if enzymeIDlist is None:
|
|
18
|
+
for id in solution.fluxes.index:
|
|
19
|
+
if 'draw_prot_' in id:
|
|
20
|
+
prots_solution[id] = solution.fluxes[id]
|
|
21
|
+
|
|
22
|
+
else:
|
|
23
|
+
for enz in enzymeIDlist:
|
|
24
|
+
prots_solution[enz] = solution.fluxes[enz]
|
|
25
|
+
|
|
26
|
+
return prots_solution
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def prepare_metabolic_solution_for_ec(solution, rxnList=None):
|
|
30
|
+
'''Ectract all metabolic fluxes data result from solution for etfl model.
|
|
31
|
+
parameters:
|
|
32
|
+
solution: Cobra solution
|
|
33
|
+
rxnList: a list of reaction ID
|
|
34
|
+
return:
|
|
35
|
+
fluxes: pd.Series, the fluxes data
|
|
36
|
+
'''
|
|
37
|
+
metabolic_solution = pd.Series()
|
|
38
|
+
if rxnList is None:
|
|
39
|
+
for id in solution.fluxes.index:
|
|
40
|
+
if id.startswith('r_'):
|
|
41
|
+
metabolic_solution[id] = solution.fluxes[id]
|
|
42
|
+
else:
|
|
43
|
+
for rxn in rxnList:
|
|
44
|
+
if rxn in solution.fluxes.index:
|
|
45
|
+
metabolic_solution[rxn] = solution.fluxes[rxn]
|
|
46
|
+
|
|
47
|
+
return metabolic_solution
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# date : 2023/3/18
|
|
3
|
+
# author : wangh
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
6
|
+
from tqdm import tqdm
|
|
7
|
+
from pytfa.analysis.variability import _variability_analysis_element
|
|
8
|
+
from ..etfl.optim.utils import safe_optim
|
|
9
|
+
from cobra.flux_analysis import flux_variability_analysis
|
|
10
|
+
from strainOptimizer.manipulation.constraint.enzyme import saturate_enzymes
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def etfl_EVA(model,target_id,enzymeIDlist,c_source,c_uptake,fraction_of_optimum=0.99,obj_direction='max'):
|
|
14
|
+
'''do enzyme variety analysis for ETFL model
|
|
15
|
+
para:
|
|
16
|
+
model: ETFL model
|
|
17
|
+
enzymeIDlist: a list of enzyme ID
|
|
18
|
+
fraction_of_optimum: Requires that the objective value is at least the
|
|
19
|
+
fraction times maximum objective value.Must be <= 1.0. (default 0.95)
|
|
20
|
+
return:
|
|
21
|
+
a dataframe of FVA result
|
|
22
|
+
'''
|
|
23
|
+
with model:
|
|
24
|
+
# fix substrate uptake
|
|
25
|
+
model.reactions.get_by_id(c_source).bounds = -c_uptake, -c_uptake
|
|
26
|
+
|
|
27
|
+
# 1.Optimize a given objective
|
|
28
|
+
model.objective = target_id
|
|
29
|
+
model.objective_direction = obj_direction
|
|
30
|
+
sol = safe_optim(model)
|
|
31
|
+
obj_value = sol.objective_value
|
|
32
|
+
|
|
33
|
+
# 1.5 saturate the model
|
|
34
|
+
all_rxnList = [reaction for reaction in model.reactions if type(reaction).__name__ == 'EnzymaticReaction']
|
|
35
|
+
all_rxnList = [reaction for reaction in all_rxnList if reaction.id.startswith('r_')]
|
|
36
|
+
rxnList=[]
|
|
37
|
+
for rxn in all_rxnList:
|
|
38
|
+
for enz in rxn.enzymes:
|
|
39
|
+
if enz.id in enzymeIDlist:
|
|
40
|
+
rxnList.append(rxn)
|
|
41
|
+
break
|
|
42
|
+
# remove duplicated rxns
|
|
43
|
+
rxnlist=list(set(rxnList))
|
|
44
|
+
model=saturate_enzymes(model,rxnList=rxnlist,sol=sol)
|
|
45
|
+
|
|
46
|
+
# 2. get all enzyme variable
|
|
47
|
+
all_enz = model.get_variables_of_type('EnzymeVariable')
|
|
48
|
+
all_enzIDlist = [enz.id for enz in all_enz]
|
|
49
|
+
# get the target enzyme list
|
|
50
|
+
target_enzlist = {}
|
|
51
|
+
for enzID in enzymeIDlist:
|
|
52
|
+
if enzID in all_enzIDlist:
|
|
53
|
+
target_enzlist[enzID] = model.enzymes.get_by_id(enzID).variable
|
|
54
|
+
else:
|
|
55
|
+
print(f"can't find Enzyme {enzID} in the {model.name}")
|
|
56
|
+
|
|
57
|
+
# 3. fix old objective value and add constraint
|
|
58
|
+
if model.solver.objective.direction == "max":
|
|
59
|
+
fva_old_objective = model.problem.Variable(
|
|
60
|
+
"fva_old_objective",
|
|
61
|
+
lb=fraction_of_optimum * obj_value,
|
|
62
|
+
)
|
|
63
|
+
else:
|
|
64
|
+
fva_old_objective = model.problem.Variable(
|
|
65
|
+
"fva_old_objective",
|
|
66
|
+
ub=fraction_of_optimum * obj_value,
|
|
67
|
+
)
|
|
68
|
+
fva_old_obj_constraint = model.problem.Constraint(
|
|
69
|
+
model.solver.objective.expression - fva_old_objective,
|
|
70
|
+
lb=0,
|
|
71
|
+
ub=0,
|
|
72
|
+
name="fva_old_objective_constraint",
|
|
73
|
+
)
|
|
74
|
+
model.add_cons_vars([fva_old_objective, fva_old_obj_constraint])
|
|
75
|
+
# model.repiar()
|
|
76
|
+
|
|
77
|
+
# 5.do enzyme variety analysis
|
|
78
|
+
results = {'min': {}, 'max': {}}
|
|
79
|
+
for sense in ['min', 'max']:
|
|
80
|
+
for k, var in tqdm(target_enzlist.items(), desc=sense + 'imizing'):
|
|
81
|
+
model.logger.debug(sense + '-' + k)
|
|
82
|
+
results[sense][k] = _variability_analysis_element(model, var, sense)
|
|
83
|
+
|
|
84
|
+
# 6.remove fixed constraint and old objective
|
|
85
|
+
model.remove_cons_vars([fva_old_objective, fva_old_obj_constraint])
|
|
86
|
+
# restore old objective
|
|
87
|
+
model.objective = target_id
|
|
88
|
+
|
|
89
|
+
df = pd.DataFrame(results)
|
|
90
|
+
df.rename(columns={'min': 'minimum', 'max': 'maximum'}, inplace=True)
|
|
91
|
+
|
|
92
|
+
return df
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def ecGEM_EVA(model,target_id,enzymeIDlist,c_source,c_uptake,fraction_of_optimum=1,obj_direction='max'):
|
|
96
|
+
'''do enzyme variety analysis for ecGEM
|
|
97
|
+
para:
|
|
98
|
+
model: ecGEM model
|
|
99
|
+
enzymeIDlist: a list of enzyme ID
|
|
100
|
+
fraction_of_optimum: Requires that the objective value is at least the
|
|
101
|
+
fraction times maximum objective value.Must be <= 1.0. (default 0.95)
|
|
102
|
+
return:
|
|
103
|
+
a dataframe of FVA result
|
|
104
|
+
'''
|
|
105
|
+
# fix substrate uptake
|
|
106
|
+
model.reactions.get_by_id(c_source).bounds = c_uptake, c_uptake
|
|
107
|
+
|
|
108
|
+
# set the objective function
|
|
109
|
+
model.objective = target_id
|
|
110
|
+
model.objective_direction = obj_direction
|
|
111
|
+
|
|
112
|
+
df_fva_result=flux_variability_analysis(model=model,reaction_list=enzymeIDlist,fraction_of_optimum=fraction_of_optimum)
|
|
113
|
+
|
|
114
|
+
return df_fva_result
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def enzymeVA(model,target_id,enzymeIDlist,c_source,c_uptake,fraction_of_optimum=0.99,obj_direction='max',model_type='etfl'):
|
|
118
|
+
'''do enzyme variety analysis for ecGEM/ETFL model
|
|
119
|
+
para:
|
|
120
|
+
model: ecGEM/ETFL model
|
|
121
|
+
target_id: the target reaction ID
|
|
122
|
+
enzymeIDlist: a list of enzyme ID
|
|
123
|
+
c_source: the carbon source ID
|
|
124
|
+
c_uptake: the carbon source uptake rate(default=1 mmol/gDW/h)
|
|
125
|
+
fraction_of_optimum: Requires that the objective value is at least the
|
|
126
|
+
fraction times maximum objective value.Must be <= 1.0. (default 0.99)
|
|
127
|
+
obj_direction: the direction of the objective function(default='max')
|
|
128
|
+
model_type: the type of the model(default='etfl')
|
|
129
|
+
|
|
130
|
+
return:
|
|
131
|
+
a dataframe of FVA result
|
|
132
|
+
'''
|
|
133
|
+
|
|
134
|
+
if model_type=='etfl':
|
|
135
|
+
eva_result= etfl_EVA(model=model,target_id=target_id,enzymeIDlist=enzymeIDlist,c_source=c_source,c_uptake=c_uptake,fraction_of_optimum=fraction_of_optimum,obj_direction=obj_direction)
|
|
136
|
+
elif model_type=='ecGEM':
|
|
137
|
+
eva_result=ecGEM_EVA(model=model,target_id=target_id,enzymeIDlist=enzymeIDlist,c_source=c_source,c_uptake=c_uptake,fraction_of_optimum=fraction_of_optimum,obj_direction=obj_direction)
|
|
138
|
+
|
|
139
|
+
return eva_result
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# date : 2024/3/20
|
|
3
|
+
# author : wangh
|
|
4
|
+
import pandas as pd
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def prepare_prot_solution_for_etfl(solution,enzymeIDlist=None):
|
|
8
|
+
'''Extract the protein abundances result from solution for ecGEM model.
|
|
9
|
+
parameters:
|
|
10
|
+
solution: Cobra solution
|
|
11
|
+
enzymeIDlist: a list of enzyme ID(optional)
|
|
12
|
+
return:
|
|
13
|
+
prots_solution: pd.Series, the protein abundances result
|
|
14
|
+
'''
|
|
15
|
+
prots_solution = pd.Series()
|
|
16
|
+
|
|
17
|
+
if enzymeIDlist is None:
|
|
18
|
+
for id in solution.raw.index:
|
|
19
|
+
if id.startswith('EZ_'):
|
|
20
|
+
prots_solution[id]=solution.raw[id]
|
|
21
|
+
|
|
22
|
+
else:
|
|
23
|
+
for enz in enzymeIDlist:
|
|
24
|
+
prots_solution[enz]=solution.raw[enz]
|
|
25
|
+
|
|
26
|
+
return prots_solution
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def prepare_metabolic_solution_for_etfl(solution, rxnList=None, flux_tol=1e-6):
|
|
30
|
+
'''Extract metabolic fluxes from an ETFL solution for use as MOMA reference.
|
|
31
|
+
|
|
32
|
+
Only reactions with |flux| > flux_tol are returned. Filtering out near-zero
|
|
33
|
+
fluxes avoids over-constraining the MOMA problem when the perturbed model
|
|
34
|
+
has a slightly different feasible region.
|
|
35
|
+
|
|
36
|
+
parameters:
|
|
37
|
+
solution: pyTFA solution
|
|
38
|
+
rxnList: a list of reaction IDs (None = all r_ reactions)
|
|
39
|
+
flux_tol: minimum absolute flux to include (default 1e-6)
|
|
40
|
+
return:
|
|
41
|
+
fluxes: pd.Series, the fluxes data
|
|
42
|
+
'''
|
|
43
|
+
metabolic_solution = pd.Series(dtype=float)
|
|
44
|
+
if rxnList is None:
|
|
45
|
+
for id in solution.fluxes.index:
|
|
46
|
+
if id.startswith('r_') and abs(solution.fluxes[id]) > flux_tol:
|
|
47
|
+
metabolic_solution[id] = solution.fluxes[id]
|
|
48
|
+
else:
|
|
49
|
+
for rxn in rxnList:
|
|
50
|
+
if rxn in solution.fluxes.index and abs(solution.fluxes[rxn]) > flux_tol:
|
|
51
|
+
metabolic_solution[rxn] = solution.fluxes[rxn]
|
|
52
|
+
|
|
53
|
+
return metabolic_solution
|
|
54
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|