Many metabolic enzymes depend on co-factors to function. Keeping balance between co-factors is important for homeostasis and that balance might interact unfavorable with metabolic engineering. And example of such balance is that between the two similar co-factor pairs NAD+/NADH and NADP+/NADPH. These co-factors are not only similar there are even enzymes that catalyze the same reaction but depend on different co-factors. Enzymes can also be enigneered to change their co-factor preference.
This opens an opportunity for using co-factor swaps to optimize production of a target metabolite. Figuring out which reactions should be subjected to co-factor swap can be done using the OptSwap algorithm. Briefly, the algorithm uses a genetic algorithm to test combinations of reactions to co-factor swap and then reports those that results in higher theoretical maximum yield.
We have implemented a variant of OptSwap in cameo and here we test it to reproduce the results in that paper for the aerobic yeast metabolism.
Get the model and import modules.
from cameo import models
model_orig = models.bigg.iJO1366
from cameo.strain_design.heuristic.evolutionary.optimization import CofactorSwapOptimization
from cameo.strain_design.heuristic.evolutionary.objective_functions import product_yield
from cameo.strain_design.heuristic.evolutionary.objective_functions import biomass_product_coupled_yield
from cameo.util import TimeMachine
from cameo.flux_analysis.analysis import flux_variability_analysis as fva
We make a copy of the model for easy testing.
model = model_orig.copy()
Make model changes as indicated in the paper.
for rid in ['FHL', 'CAT', 'SPODM', 'SPODMpp']:
model.reactions.get_by_id(rid).knock_out()
model.reactions.POR5.lower_bound = 0
model.reactions.EX_glc__D_e.lower_bound = -10
model.reactions.EX_o2_e.lower_bound = -10
model.reactions.BIOMASS_Ec_iJO1366_core_53p95M.lower_bound = 0.1
In the paper they get 0.77 maximum product yield for l-threonine, which we also get
model.objective = model.reactions.EX_thr__L_e
(model.solve().f * 4) / (model.reactions.EX_glc__D_e.flux * 6)
-0.7697175225044568
Let's run optswap using the CofactorSwapOptimization
class in cameo. We use a product-yield function to evaluate how good a solution is, but there are other possibilities like biomass_coupled_product_yield
.
GAPD is suggested in the paper as a suitable reactions
py = product_yield(model.reactions.EX_thr__L_e, model.reactions.EX_glc__D_e)
optswap = CofactorSwapOptimization(model=model, objective_function=py)
We also observe GAPD among the best options even though we considered many more reactions than in the original paper
optswap.run(max_evaluations=2000, max_size=2)
Starting optimization at Fri, 23 Sep 2016 10:03:41
The installed widget Javascript is the wrong version.
Finished after 00:03:20
reactions | knockouts | fitness | |
---|---|---|---|
0 | (TRSARr,) | (TRSARr,) | 0.805496 |
1 | (MDH, GAPD) | (MDH, GAPD) | 0.798618 |
2 | (PGCD, GAPD) | (PGCD, GAPD) | 0.788334 |
3 | (GAPD, KARA1) | (GAPD, KARA1) | 0.788223 |
4 | (IPMD, GAPD) | (IPMD, GAPD) | 0.788168 |
5 | (DHDPRy, GAPD) | (DHDPRy, GAPD) | 0.788157 |
6 | (KARA2, GAPD) | (KARA2, GAPD) | 0.788147 |
7 | (GTHOr, GAPD) | (GTHOr, GAPD) | 0.788141 |
8 | (P5CR, GAPD) | (P5CR, GAPD) | 0.788137 |
9 | (HISTD, GAPD) | (HISTD, GAPD) | 0.788133 |
10 | (3OAR140, GAPD) | (3OAR140, GAPD) | 0.788119 |
11 | (UAPGR, GAPD) | (UAPGR, GAPD) | 0.788112 |
12 | (GAPD, DHFR) | (GAPD, DHFR) | 0.788112 |
13 | (GAPD, GLUTRR) | (GAPD, GLUTRR) | 0.788109 |
14 | (GAPD,) | (GAPD,) | 0.788108 |
15 | (HACD2, GAPD) | (HACD2, GAPD) | 0.788061 |
16 | (HACD3, GAPD) | (HACD3, GAPD) | 0.788061 |
17 | (FADRx, GAPD) | (FADRx, GAPD) | 0.787821 |
18 | (ICDHyr, GAPD) | (ICDHyr, GAPD) | 0.786520 |
19 | (GND, GAPD) | (GND, GAPD) | 0.783726 |
20 | (GLUDy, 3OAR140) | (GLUDy, 3OAR140) | 0.783205 |
21 | (GLUDy,) | (GLUDy,) | 0.783197 |
22 | (ASAD,) | (ASAD,) | 0.782383 |
23 | (PDH,) | (PDH,) | 0.773008 |
24 | (MDH,) | (MDH,) | 0.772544 |
25 | (GLTPD, AKGDH) | (GLTPD, AKGDH) | 0.771216 |
26 | (PGCD,) | (PGCD,) | 0.769901 |
27 | (KARA1,) | (KARA1,) | 0.769811 |
28 | (SULRi,) | (SULRi,) | 0.769797 |
29 | (IPMD,) | (IPMD,) | 0.769766 |
... | ... | ... | ... |
70 | (TDPDRR,) | (TDPDRR,) | 0.769718 |
71 | (GLYCLTDx,) | (GLYCLTDx,) | 0.769718 |
72 | (OXCOAHDH,) | (OXCOAHDH,) | 0.769718 |
73 | (3OAR160,) | (3OAR160,) | 0.769718 |
74 | (ALDD19xr,) | (ALDD19xr,) | 0.769718 |
75 | (EAR161y,) | (EAR161y,) | 0.769718 |
76 | (LCARS,) | (LCARS,) | 0.769718 |
77 | (DMPPS,) | (DMPPS,) | 0.769718 |
78 | (TAGURr,) | (TAGURr,) | 0.769718 |
79 | (ALR2,) | (ALR2,) | 0.769718 |
80 | (2DGULRGx,) | (2DGULRGx,) | 0.769718 |
81 | (3OAR141,) | (3OAR141,) | 0.769718 |
82 | (2DGULRx,) | (2DGULRx,) | 0.769718 |
83 | (LALDO2x,) | (LALDO2x,) | 0.769718 |
84 | (EAR100x,) | (EAR100x,) | 0.769718 |
85 | (PDX5PS,) | (PDX5PS,) | 0.769718 |
86 | (EAR140y,) | (EAR140y,) | 0.769718 |
87 | (CDGR,) | (CDGR,) | 0.769718 |
88 | (3OAR60,) | (3OAR60,) | 0.769718 |
89 | (PERD,) | (PERD,) | 0.769718 |
90 | (BETALDHx,) | (BETALDHx,) | 0.769718 |
91 | (HPYRRx,) | (HPYRRx,) | 0.769718 |
92 | (GLYCLTDy,) | (GLYCLTDy,) | 0.769718 |
93 | (NADPHQR4,) | (NADPHQR4,) | 0.769718 |
94 | (UACMAMO,) | (UACMAMO,) | 0.769718 |
95 | (ALDD3y,) | (ALDD3y,) | 0.769718 |
96 | (PPPNDO,) | (PPPNDO,) | 0.769718 |
97 | (DOGULNR,) | (DOGULNR,) | 0.769718 |
98 | (3OAR161,) | (3OAR161,) | 0.769718 |
99 | (3OAR181,) | (3OAR181,) | 0.769718 |
100 rows × 3 columns
The created optswap
class has properties to check which reactions were tested and to perform swapping, let's list the first 10.
list(optswap.model.swapped_reactions)[0:10]
['HACD2', 'LCARS', '3OAR180', 'TAGURr', 'ALCD19', 'DHCIND', 'GLYCDx', 'BSORy', 'FLDR2', 'SSALx']
optswap.model.reactions.EX_thr__L_e.model = optswap.model
optswap.model.objective = optswap.model.reactions.EX_thr__L_e
original = (optswap.model.solve().f * 4) / (-optswap.model.reactions.EX_glc__D_e.flux * 6)
with TimeMachine() as tm:
optswap.model.swap_reaction('GAPD', tm)
swapped = (optswap.model.solve().f * 4) / (-optswap.model.reactions.EX_glc__D_e.flux * 6)
print("product/substrate yield without swap: {}\nproduct/substrate yield with swap: {}".format(original, swapped))
product/substrate yield without swap: 0.7697175225044552 product/substrate yield with swap: 0.7881083210964924