def ParseReactionFormula(name, formula): """ parse a two-sided formula such as: 2 C00001 = C00002 + C00003 return the set of substrates, products and the direction of the reaction """ try: left, right = formula.split(' = ', 1) except ValueError: raise KeggParseException("There should be exactly one '=' sign") sparse_reaction = {} for cid, amount in NistRowData.ParseReactionFormulaSide( left).iteritems(): sparse_reaction[cid] = -amount for cid, amount in NistRowData.ParseReactionFormulaSide( right).iteritems(): if (cid in sparse_reaction): raise KeggParseException( "C%05d appears on both sides of this formula" % cid) sparse_reaction[cid] = amount reaction = Reaction([name], sparse_reaction, None, '=>') kegg = Kegg.getInstance() rid = kegg.reaction2rid(reaction) or kegg.reaction2rid( reaction.reverse()) reaction.rid = rid return reaction
def GetFullOxidationReaction(cid): kegg = Kegg.getInstance() basic_cids = [1, 7, 9, 11, 14] # H2O, O2, Pi, CO2, NH3 basic_elements = ['C', 'O', 'P', 'N', 'e-'] element_mat = np.matrix(np.zeros((len(basic_elements), len(basic_cids)))) for j in xrange(len(basic_cids)): atom_bag = kegg.cid2atom_bag(basic_cids[j]) atom_bag['e-'] = kegg.cid2num_electrons(basic_cids[j]) for i in xrange(len(basic_elements)): element_mat[i, j] = atom_bag.get(basic_elements[i], 0) cs_element_vec = np.zeros((len(basic_elements), 1)) atom_bag = kegg.cid2atom_bag(cid) atom_bag['e-'] = kegg.cid2num_electrons(cid) for i in xrange(len(basic_elements)): cs_element_vec[i, 0] = atom_bag.get(basic_elements[i], 0) x = np.linalg.inv(element_mat) * cs_element_vec sparse = dict([(basic_cids[i], np.round(x[i, 0], 3)) for i in xrange(len(basic_cids))]) sparse[cid] = -1 r = Reaction("complete oxidation of %s" % kegg.cid2name(cid), sparse) return r
def row2string(S_row, cids): active_cids = list(np.nonzero(S_row)[0].flat) sparse = dict((cids[c], S_row[c]) for c in active_cids if abs(S_row[c]) > 1e-10) r = Reaction("", sparse) return r.FullReactionString(show_cids=False)
def MakeReaction(self, rid, vec): sparse_reaction = {} for j, stoich in enumerate(vec): if stoich == 0: continue sparse_reaction[self.compound_ids[j]] = stoich return Reaction(rid, sparse_reaction)
def write_module_to_html(html_writer, S, rids, fluxes, cids): from pygibbs.kegg_reaction import Reaction reactions = [] for r in xrange(S.shape[0]): sparse = dict([(cids[c], S[r, c]) for c in pylab.find(S[r, :])]) reaction = Reaction('R%05d' % rids[r], sparse, rid=rids[r]) reactions.append(reaction) write_kegg_pathway(html_writer, reactions, fluxes)
def GetReactionString(self, r, show_cids=False): rid = self.rids[r] sparse = dict([(self.cids[c], self.S[c, r]) for c in self.S[:, r].nonzero()[0].flat]) if self.fluxes[0, r] >= 0: direction = '=>' else: direction = '<=' reaction = Reaction(self.kegg.rid2string(rid), sparse, rid=rid, direction=direction) return reaction.to_hypertext(show_cids=show_cids)
def stoichiometric_matrix2html(html_writer, A, cids, eps=1e-10): """ Print a table in HTML format. A is a stoichiometric matrix where each row is a reaction and each column is a compound, corresponding in position to the list "cids". """ dict_list = [] for i in xrange(A.shape[0]): sparse_reaction = dict([(cids[j], A[i, j]) for j in xrange(A.shape[1]) if abs(A[i, j]) > eps]) r = Reaction("reaction%d" % i, sparse_reaction=sparse_reaction) dict_list.append({'reaction': r.to_hypertext()}) html_writer.write_ul([ '%d rows' % A.shape[0], '%d columns' % A.shape[1], '%d rank' % LinearRegression.MatrixRank(A) ]) html_writer.write_table(dict_list, headers=['#', 'reaction'])
def AddRedoxCarriers(self, anchored=True): redox_carriers = RedoxCarriers() for name, rc in redox_carriers.iteritems(): # make sure all redox carriers have a pKa table. # for some which don't (usually because their structure is not explicit) # we assume that the table is empty (i.e. no pKas exist). if self.dissociation.GetDissociationTable(rc.cid_ox) is None: self.dissociation.SetOnlyPseudoisomer(rc.cid_ox, rc.nH_ox, rc.z_ox) if self.dissociation.GetDissociationTable(rc.cid_red) is None: self.dissociation.SetOnlyPseudoisomer(rc.cid_red, rc.nH_red, rc.z_red) obs_id = name + " redox" self.cid2nH_nMg[rc.cid_ox] = (rc.nH_ox, 0) self.cid2nH_nMg[rc.cid_red] = (rc.nH_red, 0) sparse = {rc.cid_ox: -1, rc.cid_red: 1} dG0 = rc.ddG0_prime if not self.transformed: reaction = Reaction(obs_id, sparse) ddG0 = self.dissociation.ReverseTransformReaction( reaction, pH=rc.pH, I=0, pMg=default_pMg, T=default_T, cid2nH_nMg=self.cid2nH_nMg) dG0 -= ddG0 self.AddObservation(obs_id=obs_id, obs_type=KeggObservation.TYPE_REDOX, url="", anchored=anchored, dG0=dG0, sparse=sparse)
def FromFiles(): feist = Feist() reaction_file = '../data/metabolic_models/iAF1260_reactions.csv' # Read compounds ids 2 Kegg cid's mapping file into a dict counters = { 'kegg_error': 0, 'translocation': 0, 'exchange': 0, 'sink': 0, 'unbalanced': 0, 'okay': 0 } for row in csv.DictReader(open(reaction_file, 'r')): #if 'Transport' in row['subSystem']: # counters['translocation'] += 1 # continue if row['abbreviation'][0:3] == 'EX_': counters['exchange'] += 1 continue if row['abbreviation'][0:3] == 'DM_': counters['sink'] += 1 continue sparse = Feist.parse_equation(row['equation']) kegg_sparse = {} for biggID, coeff in sparse.iteritems(): keggID = feist.bigg2kegg[biggID] kegg_sparse[keggID] = kegg_sparse.get(keggID, 0) + coeff if 0 in kegg_sparse: logging.debug('Some compounds are missing KEGG IDs in %s: %s' % (row['abbreviation'], row['equation'])) counters['kegg_error'] += 1 continue for keggID in [k for k, v in kegg_sparse.iteritems() if v == 0]: del kegg_sparse[keggID] directionality = row["directionality without uncertainty (pH 7.2)"] #directionaliry = row['reconstruction directionality'] if directionality == 'reversible': direction = '<=>' elif directionality == 'forward only': direction = '=>' elif directionality == 'reverse only': direction = '<=' else: raise ValueError('unknown directionality tag: ' + directionality) reaction = Reaction(row['abbreviation'], kegg_sparse, direction=direction) if row['delta G (pH 7)'] == 'Not calculated': dG0 = np.nan else: dG0 = float(row['delta G (pH 7)']) * J_per_cal try: reaction.Balance(balance_water=True, exception_if_unknown=False) counters['okay'] += 1 except KeggReactionNotBalancedException as e: logging.debug(str(e) + ' - ' + str(reaction)) counters['unbalanced'] += 1 continue feist.reactions.append(reaction) feist.dG0s.append(dG0) logging.debug(" ; ".join( ["%s : %d" % (key, val) for (key, val) in counters.iteritems()])) return feist
def ReverseTransform(self, cid2nH_nMg=None): """ Performs the reverse Legendre transform on all the data in NIST where it is possible, i.e. where we have pKa data. Arguments: cid2nH_nMg - a dictionary mapping each compound ID to its chosen pseudoisomer (described by nH and nMg). """ logging.info("Reverse transforming the NIST data") nist_rows = self.nist.SelectRowsFromNist() logging.info("Selected %d NIST rows out of %d" % (len(nist_rows), len(self.nist.data))) data = self.GetDissociation().ReverseTransformNistRows( nist_rows, cid2nH_nMg=cid2nH_nMg) nist_rows_final = data['nist_rows'] stoichiometric_matrix = data['S'] cids_to_estimate = data['cids_to_estimate'] n_cols = stoichiometric_matrix.shape[1] logging.info("Only %d out of %d NIST measurements can be used" % (n_cols, len(nist_rows))) # squeeze the regression matrix by leaving only unique rows unique_cols_S, col_mapping = LinearRegression.ColumnUnique(stoichiometric_matrix) logging.info("There are %d unique reactions" % len(col_mapping)) unique_rids = set([nist_row.reaction.rid for nist_row in nist_rows if nist_row.reaction.rid is not None]) logging.info("Out of which %d have KEGG reaction IDs" % len(unique_rids)) # for every unique column, calculate the average dG0_r of all the columns that # are the same reaction # full_data_mat will contain these columns: dG0, dG0_tag, dG0 - E[dG0], # dG0_tag - E[dG0_tag], N # the averages are over the equivalence set of each reaction (i.e. the # average dG of all the rows in NIST with that same reaction). # 'N' is the unique row number (i.e. the ID of the equivalence set) full_data_mat = np.matrix(np.zeros((5, n_cols))) full_data_mat[0, :] = np.matrix(data['dG0_r']) full_data_mat[1, :] = np.matrix(data['dG0_r_tag']) # unique_data_mat will contain these columns: E[dG0], E[dG0_tag], # std(dG0), std(dG0_tag), no. rows # there is exactly one row for each equivalence set (i.e. unique reaction) # no. rows holds the number of times this unique reaction appears in NIST unique_data_mat = np.matrix(np.zeros((5, len(col_mapping)))) unique_sparse_reactions = [] unique_nist_row_representatives = [] for i, col_indices in col_mapping.iteritems(): col_vector = unique_cols_S[:, i] # convert the rows of unique_rows_S to a list of sparse reactions sparse = {} for j in col_vector.nonzero()[0].flat: sparse[cids_to_estimate[j]] = unique_cols_S[j, i] reaction = Reaction(names=['NIST%03d' % i], sparse_reaction=sparse) unique_sparse_reactions.append(reaction) # find the list of indices which are equal to row i in unique_rows_S unique_nist_row_representatives.append(nist_rows_final[col_indices[0]]) # take the mean and std of the dG0_r of these rows sub_data_mat = full_data_mat[0:2, col_indices] unique_data_mat[0:2, i] = np.mean(sub_data_mat, 1) unique_data_mat[2:4, i] = np.std(sub_data_mat, 1) unique_data_mat[4, i] = sub_data_mat.shape[1] full_data_mat[4, col_indices] = i full_data_mat[2:4, col_indices] = sub_data_mat for k in col_indices: # subtract the mean from each row with this reaction full_data_mat[2:4, k] -= unique_data_mat[0:2, i] # write a table that lists the variances of each unique reaction # before and after the reverse transform self.WriteUniqueReactionReport(unique_sparse_reactions, unique_nist_row_representatives, unique_data_mat, full_data_mat) return unique_cols_S, unique_data_mat[0:1, :], cids_to_estimate
H_nopka = Hatzi(use_pKa=False) H_withpka = Hatzi(use_pKa=True) H_withpka.ToDatabase(db, 'hatzi_thermodynamics') #H.ToDatabase(db, 'hatzi_gc') #H.I = 0.25 #H.T = 300; #sparse_reaction = {13:-1, 1:-1, 9:2} #sparse_reaction = {36:-1, 3981:1} #sparse_reaction = {6:-1, 143:-1, 234:1, 5:1} #sparse_reaction = {1:-1, 499:-1, 603:1, 86:1} #sparse_reaction = {1:-1, 6:-1, 311:-1, 288:1, 5:1, 80:2, 26:1} #sparse_reaction = {408:-1, 6:-1, 4092:1, 5:1} #sparse_reaction = {588:-1, 1:-1, 114:1, 9:1} #sparse_reaction = {1:-1, 3:-1, 149:-1, 288:1, 4:1, 80:2, 22:1} react = Reaction("reaction", {408: -1, 6: -1, 4092: 1, 5: 1}) #sys.stdout.write("The dG0_r of PPi + H20 <=> 2 Pi: \n\n") react.Balance() print react.FullReactionString() sys.stdout.write("%5s | %5s | %6s | %6s\n" % ("pH", "I", "T", "dG0_r")) for pH in np.arange(5, 10.01, 0.25): H_withpka.pH = pH sys.stdout.write("%5.2f | %5.2f | %6.1f | %6.2f\n" % (H_withpka.pH, H_withpka.I, H_withpka.T, react.PredictReactionEnergy(H_withpka))) for cid in react.get_cids(): print '-' * 50
def GetTotalReactionString(self, show_cids=False): total_S = self.S * self.fluxes.T sparse = dict([(self.cids[c], total_S[c, 0]) for c in total_S.nonzero()[0].flat]) reaction = Reaction("Total", sparse, direction="=>") return reaction.to_hypertext(show_cids=show_cids)
def ConvertFormation2Reaction(self, output_fname): logging.info("Converting all formation energies to reactions") output_csv = csv.writer(open(output_fname, 'w')) # keep the format used for TECRDB output_csv.writerow( ('ref', 'ID', 'method', 'eval', 'EC', 'name', 'kegg_reaction', 'reaction', 'dG0\'', 'T', 'I', 'pH', 'pMg')) atom2cid = {} for atom, (name, stoich) in KeggObservation.ATOM2ELEMENT.iteritems(): cid, _, _ = self.kegg.name2cid(name, 0) if cid is None: raise Exception( "Cannot find the element %s in the KEGG database" % name) atom2cid[atom] = (cid, stoich) #output_csv.writerow(('element', # 'C%05d' % cid, 'formation', 'A', '', # 'formation of %s' % self.kegg.cid2name(cid), # "C%05d" % cid, # name, 0, self.T, self.I, self.pH, self.pMg)) for label in ['training', 'testing']: ptable = PsuedoisomerTableThermodynamics.FromCsvFile( self.FormationEnergyFileName, label=label) for cid in ptable.get_all_cids(): pmatrix = ptable.cid2PseudoisomerMap(cid).ToMatrix() if len(pmatrix) != 1: raise Exception("multiple training species for C%05d" % cid) nH, _charge, nMg, dG0 = pmatrix[0] diss_table = dissociation.GetDissociationTable(cid, False) if diss_table is None: continue diss_table.SetFormationEnergyByNumHydrogens(dG0, nH, nMg) dG0_prime = diss_table.Transform(pH=self.pH, I=self.I, pMg=self.pMg, T=self.T) ref = ptable.cid2SourceString(cid) atom_bag = self.kegg.cid2atom_bag(cid) if not atom_bag: continue ne = self.kegg.cid2num_electrons(cid) elem_ne = 0 sparse = {cid: 1} for elem, count in atom_bag.iteritems(): if elem == 'H': continue elem_ne += count * Molecule.GetAtomicNum(elem) elem_cid, elem_coeff = atom2cid[elem] sparse.setdefault(elem_cid, 0) sparse[elem_cid] += -count * elem_coeff # use the H element to balance the electrons in the formation # reactions (we don't need to balance protons since this is # a biochemical reaction, so H+ are 'free'). H_cid, H_coeff = atom2cid['H'] sparse[H_cid] = (elem_ne - ne) * H_coeff reaction = Reaction( "formation of %s" % self.kegg.cid2name(cid), sparse) output_csv.writerow( (ref, 'C%05d' % cid, 'formation', 'A', '', 'formation of %s' % self.kegg.cid2name(cid), reaction.FullReactionString(), reaction.FullReactionString(show_cids=False), '%.2f' % dG0_prime, self.T, self.I, self.pH, self.pMg))
if __name__ == "__main__": html_writer = HtmlWriter("../res/nist/example_reaction.html") db = SqliteDatabase('../res/gibbs.sqlite') kegg = Kegg.getInstance() nist_regression = NistRegression(db, html_writer) nist_regression.nist.T_range = (273.15 + 24, 273.15 + 40) #nist_regression.nist.override_I = 0.25 #nist_regression.nist.override_pMg = 10.0 reactions = [] #reactions.append(Reaction('methyl-THF hydrolase', {1:-1, 445:-1, 234:1})) reactions.append(Reaction('D-glucose kinase', { 2: -1, 31: -1, 8: 1, 92: 1 })) #reactions.append(Reaction('creatine kinase', {2:-1, 300:-1, 8:1, 2305:1})) #reactions.append(Reaction('pyrophosphatase', {1:-1, 13:-1, 9:2})) #reactions.append(Reaction('fructose-bisphosphatase', {1:-1, 354:-1, 9:1, 85:1})) #reactions.append(Reaction('glutamate => 2-oxoglutarate', {1:-1, 3:-1, 25:-1, 4:1, 14:1, 26:1, 80:1})) #reactions.append(Reaction('choline-phosphatase', {1:-1, 588:-1, 9:1, 114:1})) #reactions.append(Reaction('2 ADP => ATP + AMP', {8:-2, 2:1, 20:1})) #reactions.append(Reaction('galactose dehydrogenase', {124:-1, 3:-1, 4:1, 3383:1})) for r in reactions: r.Balance() nist_regression.AnalyzeSingleReaction(r)
nist_row_data = NistRowData() nist_row_data.pH = 7.77 nist_row_data.I = 0.722 nist_row_data.T = 298.15 nist_row_data.pMg = 14 nist_row_data.evaluation = "A" nist_row_data.url = "" nist_row_data.ref_id = "" #nist_row_data.reaction = Reaction(["triose isomerase"], {111:-1, 118:1}) #cid2nH = {111:6, 118:5} #cid2min_dG0 = {111:-1296.3, 118:-1288.6} nist_row_data.reaction = Reaction(["triose isomerase"], { 1: -1, 78: -1, 22: 1, 14: 1, 463: 1 }) train_species = PsuedoisomerTableThermodynamics.FromCsvFile( '../data/thermodynamics/dG0.csv') cid2nH = {} cid2dG0 = {} for cid in train_species.get_all_cids(): pmap = train_species.cid2PseudoisomerMap(cid) pmatrix = pmap.ToMatrix() if len(pmatrix) != 1: raise Exception("C%05d has more than one species in the training set" % cid) cid2nH[cid] = pmatrix[0][0] # ToMatrix returns tuples of (nH, z, nMg, dG0) cid2dG0[cid] = pmatrix[0][3]
['C%05d' % all_cids[c], '%8.1f' % dG0_f[c, 0], 'Calculated']) #figure() #plot(b, dot(S_red, dG0_f[unknown_columns]), '.') figure() plot(dG0_r[known_rows], dot(S[known_rows, :], dG0_f), '.') show() csv_out = csv.writer(open('../res/acetogens_reactions.csv', 'w')) csv_out.writerow([ "RID", "EC", "REACTION", "dG0 measured", "dG0 calculated", "pH", "I", "T" ]) for r in xrange(len(reactions)): (rid, ec, sparse, dG0, pH, I, T) = reactions[r] reaction = Reaction(ec, sparse, rid=rid) dG0_calculated = dot(S[r, :], dG0_f) if r in known_rows: csv_out.writerow([ rid, ec, reaction.FullReactionString(), '%.1f' % dG0, '%.1f' % dG0_calculated, pH, I, T ]) else: csv_out.writerow([ rid, ec, reaction.FullReactionString(), 'N/A', '%.1f' % dG0_calculated, pH, I, T ])
def pH_dependence(): analyze_this_reaction = [] I_mid = [] I_tolerance = [] T_mid = [] T_tolerance = [] analyze_this_reaction += [Reaction(['glucose kinase'], {2:-1, 31:-1, 8:1, 92:1})] I_mid += [0.01] I_tolerance += [0.02] T_mid += [303.1] T_tolerance += [0.1] analyze_this_reaction += [Reaction(['L-serine kinase'], {1:-1, 1005:-1, 9:1, 65:1})] I_mid += [0.25] I_tolerance += [0.01] T_mid += [311.15] T_tolerance += [0.1] analyze_this_reaction += [Reaction(['pyrophosphatase'], {1:-1, 13:-1, 9:2}, rid=4)] I_mid += [0.05] I_tolerance += [0.05] T_mid += [298.1] T_tolerance += [15] analyze_this_reaction += [Reaction(['Fructose bisphosphate aldolase'], {354:-1, 111:1, 118:1})] I_mid += [0.01] I_tolerance += [0.011] T_mid += [300] T_tolerance += [12] pylab.figure() pylab.rcParams['text.usetex'] = True pylab.rcParams['legend.fontsize'] = 4 pylab.rcParams['font.family'] = 'sans-serif' pylab.rcParams['font.size'] = 6 pylab.rcParams['lines.linewidth'] = 0.5 pylab.rcParams['lines.markersize'] = 3 for i, reaction in enumerate(analyze_this_reaction): pylab.subplot(2,2,i+1) logging.info("Compound parameters from Alberty's table:") for cid in reaction.get_cids(): A.cid2PseudoisomerMap(cid).Display() logging.info("Compound parameters from Hatzimanikatis' table:") for cid in reaction.get_cids(): H.cid2PseudoisomerMap(cid).Display() M_obs = [] sys.stdout.write("%5s | %5s | %5s | %6s | %6s | %s\n" % ("Match", "pH", "I", "T", "dG0(N)", "link")) for row in nist.data: if (reaction != None and reaction != row.reaction): continue try: #evaluation = row[3] # A, B, C, D if (reaction == row.reaction and abs(row.I-I_mid[i]) < I_tolerance[i] and abs(row.T-T_mid[i]) < T_tolerance[i]): M_obs.append([row.pH, row.dG0_r]) sys.stdout.write(" *** | ") else: sys.stdout.write(" | ") sys.stdout.write("%5.2f | %5.2f | %6.1f | %6.2f | %s\n" % (row.pH, row.I, row.T, row.dG0_r, row.ref_id)) except MissingCompoundFormationEnergy: continue if len(M_obs) == 0: sys.stderr.write("There are now data points matching this reaction with the specific I and T") continue M_obs = pylab.matrix(M_obs) leg = ['NIST'] pH_range = pylab.arange(M_obs[:,0].min()-1, M_obs[:,0].max()+1, 0.01) M_est = [] I_low = max(I_mid[i]-I_tolerance[i], 0.0) I_high = I_mid[i]+I_tolerance[i] for pH in pH_range: predictions = [] for predictor in [A, H]: predictions.append(reaction.PredictReactionEnergy(predictor, pH=pH, I=I_low ,T=T_mid[i])) predictions.append(reaction.PredictReactionEnergy(predictor, pH=pH, I=I_mid[i] ,T=T_mid[i])) predictions.append(reaction.PredictReactionEnergy(predictor, pH=pH, I=I_high ,T=T_mid[i])) M_est.append(predictions) M_est = pylab.matrix(M_est) pylab.plot(M_obs[:,0], M_obs[:,1], 'co') pylab.plot(pH_range, M_est[:,0], 'b:') pylab.plot(pH_range, M_est[:,1], 'b-') pylab.plot(pH_range, M_est[:,2], 'b:') pylab.plot(pH_range, M_est[:,3], 'g:') pylab.plot(pH_range, M_est[:,4], 'g-') pylab.plot(pH_range, M_est[:,5], 'g:') pylab.plot(pH_range, M_est[:,6], 'r:') pylab.plot(pH_range, M_est[:,7], 'r-') pylab.plot(pH_range, M_est[:,8], 'r:') for predictor_name in ['Alberty', 'Hatzi', 'Rugged']: for I in [I_low, I_mid[i], I_high]: leg.append("%s (I = %.2f)" % (predictor_name, I)) pylab.legend(leg, loc='best') if (i == 2 or i == 3): pylab.xlabel('pH') if (i == 0 or i == 2): pylab.ylabel(r"$\Delta_r G'^\circ$ [kJ/mol]") s_title = gc.kegg.reaction2string(reaction, cids=False) + "\n" s_title += "($I = %.2f \pm %.2f$ $M$, $T = %.1f \pm %.1f$ $K$)" % (I_mid[i], I_tolerance[i], T_mid[i]-273.15, T_tolerance[i]) pylab.title(s_title, fontsize=5) pylab.savefig('../res/compare_pH.pdf', format='pdf')
def write_current_solution(self, exp_html, lp, experiment_name, output_kegg_file=None): solution = lp.get_active_reaction_data() solution_id = '%03d' % lp.solution_index exp_html.write('%d reactions, flux = %g, \n' % (len(solution.reactions), float(solution.fluxes.sum(1)))) # draw network as a graph and link to it Gdot = self.kegg_pathologic.draw_pathway(solution.reactions, list(solution.fluxes.flat)) svg_fname = '%s/%s_graph' % (experiment_name, solution_id) exp_html.embed_dot_inline(Gdot, width=240, height=320, name=svg_fname) # write the solution for the concentrations in a table if solution.concentrations is not None: exp_html.insert_toggle(start_here=True) rowdicts = [] for c, compound in enumerate(solution.compounds): rowdict = {} rowdict['KEGG ID'] = '<a href="%s">C%05d</a>' % (compound.get_link(), compound.cid) rowdict['Compound'] = compound.name rowdict[symbol_df_G0_prime + "[kJ/mol]"] = solution.dG0_f[0, c] rowdict[symbol_df_G_prime + "[kJ/mol]"] = solution.dG_f[0, c] if np.isfinite(solution.concentrations[0, c]): rowdict['Conc. [M]'] = '%.1e' % solution.concentrations[0, c] else: rowdict['Conc. [M]'] = 'N/A' rowdicts.append(rowdict) headers=['KEGG ID', 'Compound', symbol_df_G0_prime + "[kJ/mol]", symbol_df_G_prime + "[kJ/mol]", 'Conc. [M]'] exp_html.write('Compound Concentrations<br>\n') exp_html.write_table(rowdicts, headers, decimal=1) total_reaction = Reaction('total', {}) rowdicts = [] for r, reaction in enumerate(solution.reactions): rowdict = {} flux = solution.fluxes[0, r] rowdict['KEGG ID'] = '<a href="%s">R%05d</a>' % (reaction.get_link(), reaction.rid) rowdict['Reaction'] = reaction.to_hypertext(show_cids=False) rowdict['Flux'] = flux rowdict[symbol_dr_Gc_prime + "[kJ/mol]"] = solution.dGc_r[0, r] rowdict[symbol_dr_G_prime + "[kJ/mol]"] = solution.dG_r[0, r] rowdicts.append(rowdict) total_reaction += (flux * reaction) rowdict = {} rowdict['KEGG ID'] = 'total' rowdict['Reaction'] = total_reaction.to_hypertext(show_cids=False) rowdict[symbol_dr_Gc_prime + "[kJ/mol]"] = float(solution.dGc_r.sum(1)) rowdict[symbol_dr_G_prime + "[kJ/mol]"] = float(solution.dG_r.sum(1)) rowdicts.append(rowdict) headers=['KEGG ID', 'Reaction', symbol_dr_Gc_prime + "[kJ/mol]", symbol_dr_G_prime + "[kJ/mol]", "Flux"] exp_html.write('Reaction Gibbs energies<br>\n') exp_html.write_table(rowdicts, headers, decimal=1) exp_html.div_end() # write the pathway in KEGG format if output_kegg_file is not None: write_kegg_pathway(output_kegg_file, entry=experiment_name + ' ' + solution_id, reactions=solution.reactions, fluxes=list(solution.fluxes.flat)) exp_html.write('<br>\n')