<jupyter_start><jupyter_text>Summary of the changes in the model: E. coli full model *i*ML1515 with some changes ('WT' ref):	* Corrected the transhydrogenase (THD2pp) to one proton translocation;* Corrected homoserine dehydrogenase to be irreversible, towards homoserine. * Knocked out: pyruvate synthase (POR5), 3pg producing glycerate kinase (GLYCK), pyrroloquinoline quinone (PQQ)-glucose dehydrogenase (GLCDpp), and the reactions for unrealistic AcCoA production DRPA & PAI2T. Knock out of them does not change the biomass yield on glucose. * Knocked out exchange reactions for Fe2+, H2S, Met, and Cys to avoid using Fe or S as electron acceptor.* Knocked out threonine cleavage routes: L-Thr aldolase (THRA), Thr dehydrogenase (THRD), and glycine C-acetyltransferase (GLYAT).* Added irreversible hydrogen dehydrogenase (H2DH, H2 + NAD+ -> NADH + H+). * Deactivated pyruvate formate lyase (PFL), 2-oxobutanoate formate lyase (OBTFL) under aerobic coditions. In the case of GED pathway, modify phosphogluconate dehydrogenase (GND) to be reversible.  In the case of rPP pathway, add phosphoribulokinase (PRK) and ribulose-bisphosphate carboxylase (RBPC) reactions.  Validation of the pathway/cycle: * CO2 is the only carbon source and with no constraint;* H2 is the source of electrons and energy and constrained (EX_h2_e lower bound to be -100);* Modified glyceraldehyde-3-phosphate dehydrogenase (GAPD) to be NADP dependent.  For the shunts:* Xylose or glucose is the main carbon source, their uptake rates under aerobic/anaerobic conditions were taken from [Gonzalez et al Metabolic Engineering 2017](https://doi.org/10.1016/j.ymben.2016.11.003).* To create the shunt variants of GED and rPP, reactions phosphofructokinase (PFK), S7P reacting phosphofructokinase (PFK_3), fructose 6-phosphate aldolase (F6PA), glucose 6-phosphate dehydrogenase (G6PDH2r), and fructose-bisphosphatase (FBP).<jupyter_code>model = cobra.io.load_json_model(r'..\0_ecoli_models\iML1515.json')

model.reactions.THD2pp.add_metabolites({"h_p": 1, "h_c": -1})
model.reactions.HSDy.bounds = (-1000, 0)
KORxn_base = ['POR5', 'GLYCK', 'GART', 'DRPA', 'PAI2T','GLCDpp']
KORxn(model, KORxn_base)
# Set medium: CO2 as the sole carbon source, no limitation
for rxn in model.boundary:
    if "C" in rxn.check_mass_balance(): # knock out all other carbon-related transporters
        rxn.bounds = (0, 1000)
model.reactions.get_by_id('EX_co2_e').bounds = (-1000, 1000)

# to avoid S as electron acceptor
model.reactions.get_by_id('EX_h2s_e').bounds = (0,0)
model.reactions.get_by_id('EX_met__L_e').bounds = (0,0)
model.reactions.get_by_id('EX_cys__L_e').bounds = (0,0)

model.reactions.get_by_id('EX_fe2_e').bounds = (0,0)  # to avoid Fe as electron acceptor<jupyter_output><empty_output><jupyter_text>first validate the models of the cycleschange the glyceraldehyde-3-phosphate dehydrogenase (GAPD) to NADP dependent to be fair.add hydrogen dehydrogenase to generate elections.<jupyter_code>KORxn(model, ['GAPD'])

GAPDn = cobra.Reaction(id="GAPDn", name="glyceraldehyde-3-phosphate dehydrogenase (NADP)", lower_bound=-1000, upper_bound=1000)
model.add_reaction(GAPDn)
GAPDn.add_metabolites({"g3p_c": -1, "nadp_c": -1, "pi_c": -1, "13dpg_c": 1, "h_c": 1, "nadph_c": 1})

model.reactions.get_by_id('EX_h2_e').bounds = (-100, 1000)  # this is the constraint 
H2DH = cobra.Reaction(id="H2DH", name="hydrogen dehydrogenase", lower_bound=0, upper_bound=1000) 
model.add_reaction(H2DH)
H2DH.add_metabolites({"h2_c": -1, "nad_c": -1, "h_c": 1, "nadh_c": 1})

def Rxn4rPP(model):
    # add PRK and RuBisCO reactions
    rb15bp_c = cobra.Metabolite(id='rb15bp_c',
                                formula='C5H8O11P2',
                                name='D-Ribulose 1,5-bisphosphate',
                                compartment='c')
    PRK = cobra.Reaction(id="PRK", name="Phosphoribulokinase", lower_bound=0, upper_bound=1000)
    model.add_reaction(PRK)
    PRK.add_metabolites({"atp_c": -1, "ru5p__D_c": -1, "adp_c": 1, "h_c": 1, rb15bp_c: 1})

    RBPC = cobra.Reaction(id="RBPC", name="Ribulose-bisphosphate carboxylase", lower_bound=0, upper_bound=1000)
    model.add_reaction(RBPC)
    RBPC.add_metabolites({"co2_c": -1, rb15bp_c: -1, "h2o_c": -1, "3pg_c": 2, "h_c": 2})
# validation of rPP (CBB) with biomass
with model:
    # add Rxns to the model
    Rxn4rPP(model)
    KORxn(model,['PFL', 'OBTFL']) # aerobic condition: PFL, OBTFL.
    model.optimize()
    model.summary()
    flux2file(model,'biomass','rPP')
# validation of GED, with biomass
with model:
    # change GND to be reversible
    model.reactions.GND.bounds = (-1000, 1000)
    KORxn(model,['PFL', 'OBTFL']) # aerobic condition: PFL, OBTFL.
    model.optimize()
    model.summary()
    flux2file(model,'biomass', 'GED')

with model:
    # change GND to be reversible
    model.reactions.GND.bounds = (-1000, 1000)
    KORxn(model,['PFL', 'OBTFL']) # aerobic condition: PFL, OBTFL.
    KORxn(model, ['THRA','THRD','GLYAT'])
    model.optimize()
    model.summary()
    flux2file(model,'biomass_4', 'GED')

with model:
    Rxn4rPP(model)
    KORxn(model,['PFL', 'OBTFL']) # aerobic condition: PFL, OBTFL.   
    KORxn(model, ['THRA','THRD','GLYAT'])
    model.optimize()
    model.summary()
    flux2file(model,'biomass_4','rPP')
products = ['biomass', 'pyr_e', 'lac__D_e', 'ibtol_e', '23btdl_e',
            'ac_e', 'etoh_e', 'acetone_e', 'but_e', 'buoh_e',
            'hdca_e', 'cit_e', 'itacon_e', 'akg_e', 'succ_e','levu_e']<jupyter_output><empty_output><jupyter_text>Add new reactions for those pathways do not exist natively* acetone: DOI: 10.1016/j.ymben.2012.08.001 * butyrate: but_e; DOI: 10.1002/bit.24925* 1-butanol: buoh_e; DOI: 10.1186/1475-2859-7-36* Hexadecanoate (n-C16:0): hdca_e; DOI: 10.1038/nature10333* isobutanol: ibtol_e; DOI: 10.1007/s00253-009-2085-6* 2,3-butanediol: 23btdl_e; DOI: 10.1021/acssynbio.5b00057* itaconate: itacon_e; DOI: 10.1007/s10529-017-2500-5* levulinic acid: levu_e; DOI: 10.1038/nbt.3505<jupyter_code>model = AddRxn(model, 'NewRxn4Production.csv')

KORxn(model, ['THRA','THRD','GLYAT'])<jupyter_output>unknown metabolite '2mbald_c' created
unknown metabolite 'ibtol_c' created
unknown metabolite 'actn__R_c' created
unknown metabolite '23btdl_c' created
unknown metabolite 'acetone_c' created
unknown metabolite 'buoh_c' created
unknown metabolite 'itacon_c' created
unknown metabolite 'levu_c' created<jupyter_text>Then, check the linear variant of the pathway for production. On glucose or xylose (constraint) as a source of ru5p.Use a modified WT as a reference.<jupyter_code>uProd = ['ibtol_e','23btdl_e','acetone_e','but_e',
          'buoh_e','itacon_e','levu_e']  # unnatural products
# KO unnatural exchange reactions to aviod as byproducts when fermentating
for product in uProd:
    model.reactions.get_by_id(f'EX_{product}').bounds = (0,0)

# change back GAPD to be NAD dependent
model.reactions.GAPD.bounds = (-1000, 1000)
model.reactions.GAPDn.knock_out()
CSs = ['glc','xyl']
PSWs = ['ref','rPP','GED']
o2 = [-1000, 0]
cs_up = [-8.8, -13.1, -9.5, -10.8]  # DOI 10.1016/j.ymben.2016.11.003
h2 = [-1000, 0]
conds = zip(itertools.product(CSs, o2), cs_up)

columns = pd.MultiIndex.from_product([CSs,PSWs,o2,h2],names=['CS','PSW','O2','H2'])
shunt_prod = pd.DataFrame(columns=columns, index=products[1:], dtype=float)  # biomass is not an interested product
by_prod_ex = pd.DataFrame(columns=columns, index=products[1:])
# for reducing running time
EXrxns = []
for rxn in set(model.boundary).difference([model.reactions.EX_co2_e]):
    if 'C' in rxn.check_mass_balance():
        EXrxns.append(rxn)
def shunt_production(model,psw,cs,o2_lb,cs_lb,h2_lb,product,path):
    if psw == 'rPP':
        KORxn(model,['PFK', 'F6PA', 'G6PDH2r', 'PFK_3','FBP']) # to break the cyclic rPP to a linear shunt
        Rxn4rPP(model)
    elif psw == 'GED':
        KORxn(model,['PFK', 'F6PA', 'G6PDH2r', 'PFK_3','FBP'])
        model.reactions.GND.bounds = (-1000, 1000)
    
    model.reactions.get_by_id(f'EX_{cs}__D_e').lower_bound = cs_lb
    model.reactions.get_by_id('EX_o2_e').lower_bound = o2_lb
    if o2_lb == -1000:
        KORxn(model,['PFL', 'OBTFL']) # aerobic condition: PFL, OBTFL.
    model.reactions.get_by_id('EX_h2_e').lower_bound = h2_lb

    if product in uProd:
        model.reactions.get_by_id(f'EX_{product}').upper_bound = 1000
    
    change_objective(model, product)

    shunt_prod.loc[product, 
                   (cs,psw,o2_lb,h2_lb)] = prodFBA(model, 
                                             psw, 
                                             '_'.join([cs,product,'O2',str(o2_lb),'H2',str(h2_lb)]), 
                                             path)
    
    for rxn in set(EXrxns).difference([model.reactions.get_by_id(f'EX_{product}')]):
        if rxn.flux > 0.001:
            by_prod_ex.loc[product,(cs,psw,o2_lb,h2_lb)] = True
            break
        
# save = True 
save = False
path = None

for ((cs, o2_lb), cs_lb), h2_lb, psw, product in itertools.product(conds, h2, PSWs, products[1:]):  # biomass is not an interested product
    with model:
        if product == 'hdca_e':
            model.genes.b1093.knock_out() # block the ACP route by KO FabG
        if save:
            path = '_'.join([cs,psw])
        shunt_production(model,psw,cs,o2_lb,cs_lb,h2_lb,product,path)

by_prod_ex.fillna(value=False,inplace=True)

def highlight(v):
    """To highlight the cases with by-product secretion"""
    return by_prod_ex.applymap(lambda x: 'background-color: yellow' if x else '')

shunt_prod.style.apply(highlight, axis=None)
shunt_prod.style.apply(highlight, axis=None).to_excel('2_GED shunt results.xlsx')
yield_norm_shunt = pd.concat([shunt_prod.glc.div(shunt_prod.glc.ref,axis=0) * 100,
                              shunt_prod.xyl.div(shunt_prod.xyl.ref,axis=0) * 100],
                              axis=1, keys=CSs, names=['CS'])

yield_norm_shunt.drop(columns='ref',level=3,inplace=True)  # remove the ref column
yield_norm_shunt.round(1)
fig, axs = plt.subplots(nrows=4,ncols=2,sharex=True,sharey=True,figsize=(20, 15))

for i, j, n in itertools.product([0,1],  # O2 
                                 [0,1],  # H2
                                 [0,1]): # CS
    yield_norm_shunt.plot.bar(y=(CSs[n],o2[i],h2[j]),
                              title='_'.join([CSs[n],f'O2({o2[i]})',f'H2({h2[j]})']),
                              ax=axs[i+2*n,j])
    axs[i+2*n,j].grid(which='both', axis='y')
    
fig.savefig('figure_GED shunt.eps', dpi=300, bbox_inches='tight')
plt.show()<jupyter_output>The PostScript backend does not support transparency; partially transparent artists will be rendered opaque.
The PostScript backend does not support transparency; partially transparent artists will be rendered opaque.
The PostScript backend does not support transparency; partially transparent artists will be rendered opaque.
The PostScript backend does not support transparency; partially transparent artists will be rendered opaque.
The PostScript backend does not support transparency; partially transparent artists will be rendered opaque.
The PostScript backend does not support transparency; partially transparent artists will be rendered opaque.
The PostScript backend does not support transparency; partially transparent artists will be rendered opaque.
The PostScript backend does not support transparency; partially transparent artists will be rendered opaque.
The PostScript backend does not support transparency; partially transparent artists will be rendered opaque.
The PostScript back[...]
{'fraction_non_alphanumeric': 0.13261058109280138, 'fraction_numerical': 0.04058976582827407, 'mean_word_length': 4.093197879858657, 'pattern_counts': {'":': 20, '<': 15, '<?xml version=': 0, '>': 17, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '93277', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 4668, 'n_tokens_neox': 4096, 'n_words': 1002, 'path': '2020_GED/GED_FBA.ipynb', 'repo_name': 'he-hai/PubSuppl', 'size': '11530'}