Source code for fluxpyt.solve_mid_networks
# -*- coding: utf-8 -*-
"""
Solves the elementory metabolite unit networks.
Solves mids for only one set of flux_distribution
Created on Fri Jul 15 10:57:23 2016
@author: Trunil
"""
import numpy as np
from fluxpyt.utility import split_rxn
from scipy.signal import convolve
from copy import deepcopy
[docs]def solve_mid_networks(rxnId_networks,rxn_networks,substrate_mids,rates,flux_dist):
#make matrices and solve.
known_mids = deepcopy(substrate_mids) #initialize before testing each individual set of fluxes
# f = open('tmp.txt','w')
# f.close()
for i in range(len(rxn_networks)):
emu_net = rxn_networks[i]
rxn_ids = rxnId_networks[i]
cal_mids = solve_network(rxn_ids,emu_net,known_mids,rates,flux_dist)
if cal_mids == None:
return None
else:
known_mids = append_mids(known_mids,cal_mids)
return known_mids
[docs]def solve_network(rxn_ids,emu_net,known_mids,rates,flux_dist):
#rearrange fluxdist and rates
fluxes = [[],[]] # [ids,values]
for i in range(len(rxn_ids)):
r = rxn_ids[i]
if r in flux_dist[0]:
ind = flux_dist[0].index(r)
fluxes[0].append(r)
fluxes[1].append(flux_dist[1][ind])
elif r in rates[0]:
ind = rates[0].index(r)
fluxes[0].append(r)
fluxes[1].append(float(rates[1][ind]))
# get number of known and unknown mids and sort them
known = []
unknown = []
dim_known = 0
dim_unknown = 0
for i in range(len(rxn_ids)):
rxn = emu_net[i]
rxn_split = split_rxn(rxn)
coeff = rxn_split[0::2]
rxn_split = rxn_split[1::2]
if len(rxn_split) == 2: #linear reactions
for el in rxn_split:
if el in known_mids[0] and el not in known: #if a known mid but not added yet
known.append(el)
dim_known += 1
elif el not in unknown and el not in known: #not a known mid but not added in unknown || added on 18Apr2017
unknown.append(el)
dim_unknown += 1
else: #convolutions
reac = rxn_split[0:-1]
prod = rxn_split[-1]
# print('\n\n\nprod: ',prod)
if prod in known_mids[0] and prod not in known:#check product
known.append(prod)
dim_known += 1
elif prod not in unknown and prod not in known: #part after and was added on 18Apr2017
unknown.append(prod)
dim_unknown += 1
con_val = [1]
for el in reac: #check reactant
if el not in known_mids[0]:
add_to = 'unknown'
break
elif el in known_mids[0]:
add_to = 'known'
ix = known_mids[0].index(el)
con_val = convolve(con_val,known_mids[1][ix])
if add_to == 'unknown':
unknown.append(reac) #appended as whole list in form of string
dim_unknown += 1
elif add_to == 'known':
known.append(reac) #appended as whole list
known_mids[0].append(reac)
known_mids[1].append(list(con_val))
dim_known +=1
#create matrices: AB = CD
#initialize
'''where,
A = square matrix with combination of reaction rates as elements
B = unknown emus to be solved for
C = matrix (num_unknown X emusize+1) matrix
D = known emus'''
#if there is no known mid in network
if len(known) == 0:
return None
A = np.zeros((dim_unknown,dim_unknown))
C = np.zeros((dim_unknown,dim_known))
D = [] #this would be just set of known/previously calculated mids
for k in known:
k_ind = known_mids[0].index(k)
D.append(known_mids[1][k_ind])
D = np.array(D)
#fill the matrices with values
for i in range(len(rxn_ids)):
rid = rxn_ids[i]
rxn_ind = fluxes[0].index(rid) #indice of reaction in flux list
rxn_split = split_rxn(emu_net[i]) #fluxes[0] = rxn_ids
coeff = rxn_split[0::2]
rxn_split = rxn_split[1::2]
if len(rxn_split) > 2:
convolve_tag = True
# \n*************************\nconvolution'
else:
convolve_tag = False
# \n###########################\nlinear'
inds_unknown = []
coeff_unknown = []
inds_known = []
coeff_known = []
if convolve_tag == False:
for p in range(len(rxn_split)): #find indices of emus in known or unknown list
el = rxn_split[p]
if el in unknown: #for matrix A
inds_unknown.append(unknown.index(el))
coeff_unknown.append(float(coeff[p]))
elif el in known:
inds_known.append(known.index(el))
coeff_known.append(float(coeff[p]))
u_rxn = rxn_split.copy()
if convolve_tag == True:
conl = [rxn_split[0:-1]] #all reactants
conl.append(rxn_split[-1])
for el in conl:
if el in unknown:
inds_unknown.append(unknown.index(el))
coeff_unknown.append(1) #have to figure if convolution reactions have diff coefficients
elif el in known:
inds_known.append(known.index(el))
coeff_known.append(1)
u_rxn = conl.copy()
if len(inds_unknown) == len(u_rxn): #both molecules have unknown mids
A[inds_unknown[1]][inds_unknown[1]] += fluxes[1][rxn_ind]*(-coeff_unknown[1])
A[inds_unknown[1]][inds_unknown[0]] += fluxes[1][rxn_ind]*coeff_unknown[1]
elif u_rxn[1] in unknown: #product has unknown mids or reactant has known mids
A[inds_unknown[0]][inds_unknown[0]] += fluxes[1][rxn_ind]*(-coeff_unknown[0])
C[inds_unknown[0]][inds_known[0]] += fluxes[1][rxn_ind]*(-coeff_known[0])
#############################
#write matrices if necessary
# print(A.shape)
# print(np.linalg.det(A))
# f = open('tmp.txt','a')
# for k in A:
# for l in k:
# w = str(l)+','
# f.write(w)
# f.write('\n')
# f.close()
# #sys.exit()
# #############################
if np.linalg.det(A) == 0:
return None
#solve matrices
CdotD = np.dot(C,D)
B = np.linalg.solve(A,CdotD)
nm = [list(x) for x in B]
cal_mids = [unknown,nm]
return cal_mids
[docs]def append_mids(mids1,mids2):
'''used when we have two lists of mids. Joins these two '''
for i in range(len(mids2[0])):
emu = mids2[0][i]
mid = mids2[1][i]
if not(emu in mids1[0]):
mids1[0].append(emu)
mids1[1].append(mid)
return mids1
[docs]def update_mids(rxnIds,rxns,mids):
from collections import Counter
#check known mids and derive mids of emus of linear reactions
productList = []
for rxn in rxns:
productList.append(rxn.split()[-1])
emuFreq = Counter(productList) #stores the number of times an emu is formed in the emu reactions
for rxn in rxns:
rxn_split = rxn.split()
rxn_split.remove('->')
if len(rxn_split) > 2:
rxn_split.remove('+')
# print('rxn_split',rxn_split,'\n\n')
product = rxn_split[-1]
if len(rxn_split) == 2 and product in mids[0] and emuFreq[product] == 1:
'''if products mid is known,
occurs only one in emu reaction,
and not involved in convolution reaction
Its reactant will have same mid'''
ind = mids[0].index(product)
# print('\nproduct is found in linear reaction')
mids[0].append(rxn_split[0])
mids[1].append(mids[1][ind])
'''This code is invcomplete and does not include convolution reactions'''
return mids
[docs]def get_mids(mids):
'''arranges mid values and emus in list'''
modified_mids = [[],[]]
measured_emus = mids[0]
i = 0
while i < len(mids[1]):
vals = float(mids[1][i])
err = float(mids[2][i])
modified_mids[0].append(vals)
modified_mids[1].append(err)
i+=1
modified_mids.append(measured_emus)
return modified_mids