def get_h(self, keep1=True): """ c = h(p) """ hs = [poly.get_h(keep1=keep1) for poly in self] yids = butil.flatten([h_.yids for h_ in hs]) coefstrs = butil.flatten([h_.frepr.tolist() for h_ in hs]) senstrs = [[exprmanip.simplify_expr(exprmanip.diff_expr(coefstr, pid)) for pid in self.pids] for coefstr in coefstrs] hstr = str(coefstrs).replace("'", "") Dhstr = str(senstrs).replace("'", "") subs0 = dict(butil.flatten([poly.convarvals.items() for poly in self], depth=1)) def f(p): subs = subs0.copy() subs.update(dict(zip(self.pids, p))) return np.array(eval(hstr, subs)) def Df(p): subs = subs0.copy() subs.update(dict(zip(self.pids, p))) return np.array(eval(Dhstr, subs)) h = predict.Predict(f=f, Df=Df, pids=self.pids, p0=self.p0, yids=yids, frepr=butil.Series(coefstrs, yids), Dfrepr=butil.DF(senstrs, yids, self.pids)) return h
def __init__(self, data=None, index=None, columns=None, dtype='float', copy=False): """Make a *simple* or *composite* ensemble. Simple ensembles have ``pandas.Index`` as columns, while composite ensembles have ``pandas.MultiIndex`` as columns. Input: varids: {list-like, map-like} """ if isinstance(columns, OD): columns = [[(vartype, varid) for varid in varids] for vartype, varids in columns.items()] columns = butil.flatten(columns, depth=1) columns = pd.MultiIndex.from_tuples(columns) super(DF, self).__init__(data=data, index=index, columns=columns, dtype='float', copy=copy) self.index.name = 'step'
def list2predict2(l, pids, uids=None, us=None, yids=None, c=None, p0=None): """ pred = list2predict(['exp(-p1*1)+exp(-p2*1)', 'exp(-p1*2)+exp(-p2*2)', 'exp(-p1*1)-exp(-p2*1)'], pids=['p1','p2'], p0=None) pred = list2predict(['(k1f*C1-k1r*X1)-(k2f*X1-k2r*X2)', '(k2f*X1-k2r*X2)-(k3f*X2-k3r*C2)'], uids=['X1','X2'], us=butil.get_product([1,2,3],[1,2,3]), pids=['k1f','k1r','k2f','k2r','k3f','k3r'], c={'C1':2,'C2':1}) Input: c: a mapping """ if c is not None: l = [exprmanip.sub_for_vars(s, c) for s in l] ystr = str(l).replace("'", "") ycode = compile(ystr, '', 'eval') def f(p): return np.array(eval(ycode, dict(zip(pids, p)), mathsubs)) jaclist = [] for s in l: jacrow = [exprmanip.simplify_expr(exprmanip.diff_expr(s, pid)) for pid in pids] jaclist.append(jacrow) if us is not None: jaclist = [[[exprmanip.sub_for_vars(jacentry, dict(zip(uids, u))) for jacentry in jacrow] for jacrow in jaclist] for u in us] jaclist = butil.flatten(jaclist, depth=1) jacstr = str(jaclist).replace("'", "") jaccode = compile(jacstr, '', 'eval') def Df(p): return np.array(eval(jaccode, dict(zip(pids, p)), mathsubs)) if p0 is None: p0 = [1] * len(pids) if yids is None: yids = ['y%d'%i for i in range(1, len(l)+1)] if us is not None: uids = ['u%d'%i for i in range(1, len(us)+1)] yids = butil.get_product(yids, uids) return Predict(f=f, Df=Df, p0=p0, pids=pids, yids=yids)
def add(self, row=None, **kwargs): """ Use sparingly as it makes a copy each time ? Time it: FIXME ** Input: row: {list-like, map-like} """ if row is None: row = kwargs if isinstance(row, Mapping): row = butil.flatten([row[vartype] for vartype in self.vartypes]) self.loc[self.nrow] = row
def __init__(self, data=None, index=None, columns=None, **kwargs): """Make a *simple* or *composite* ensemble. Simple ensembles have ``pandas.Index`` as columns, while composite ensembles have ``pandas.MultiIndex`` as columns. Input: varids: {list-like, map-like} """ if isinstance(columns, OD): columns = [[(vartype, varid) for varid in varids] for vartype, varids in columns.items()] columns = butil.flatten(columns, depth=1) columns = pd.MultiIndex.from_tuples(columns) super(DF, self).__init__(data=data, index=index, columns=columns, **kwargs) self.index.name = 'step'
def get_predict(net, expts, **kwargs_ss): """ """ varids = list(set(butil.flatten(expts['varids']))) if set(varids) <= set(net.xids): vartype = 's' idxs = [idx for idx, xid in enumerate(net.xids) if xid in varids] elif set(varids) <= set(net.Jids): vartype = 'J' idxs = [idx for idx, Jid in enumerate(net.Jids) if Jid in varids] else: vartype = 'sJ' xJids = net.xids + net.Jids idxs = [idx for idx, xJid in enumerate(xJids) if xJid in varids] net0 = net.copy() if not net0.compiled: net0.compile() nets = [net0.perturb(cond) for cond in expts.conds] [net.get_Ep_str() for net in nets] [net.get_Ex_str() for net in nets] L, Nr = net.L.values, net.Nr.values def f(p): y = [] for net in nets: net.update_optimizable_vars(p) s = get_s(net, **kwargs_ss) if vartype == 's': y_cond = s[idxs].tolist() if vartype == 'J': y_cond = [ net.evaluate_expr(net.reactions[idx].kineticLaw) for idx in idxs ] if vartype == 'sJ': sJ = np.concatenate( (get_s(net, **kwargs_ss), get_J(net, **kwargs_ss))) y_cond = sJ[idxs].tolist() y.extend(y_cond) return np.array(y) def Df(p): jac = [] for net in nets: net.update_optimizable_vars(p) if vartype == 's': #jac_cond = get_Rs(net, p, Nr, L, to_mat=1, **kwargs_ss).loc[varids].dropna() # why dropna? jac_cond = get_Rs(net, Nr, L, **kwargs_ss)[idxs] if vartype == 'J': jac_cond = get_RJ(net, Nr, L, **kwargs_ss)[idxs] if vartype == 'sJ': # to be refined R = np.vstack( (get_Rs(net, Nr, L, **kwargs_ss), get_RJ(net, Nr, L, **kwargs_ss))) jac_cond = R[idxs] jac.extend(jac_cond.tolist()) return np.array(jac) pred = predict.Predict(f=f, Df=Df, p0=net.p0, pids=net.pids, yids=expts.yids, expts=expts, nets=nets) return pred
def get_stoich_mat(net=None, rxnid2stoich=None, only_dynvar=True, integerize=False, to_mat=True): """Return the stoichiometry matrix (N) of the given network or dict rxnid2stoich. Rows correspond to species, and columns correspond to reactions. Input: rxnid2stoich: eg, {'R1':{'A1:1}, 'R2':{'A1':1}}; net & rxnid2stoich: one and only one should be given only_dynvar: if True, use *dynamic* species as rows (keep out constant/buffered species); if False, use species as row integerize: if True, make all stoichcoefs integers """ if net: try: ## assume network structure has not changed and # precalculated N is up-to-date return net.stoich_mat except (AttributeError, ValueError): if only_dynvar: rowvarids = net.xids else: rowvarids = net.spids N = Matrix(np.zeros((len(rowvarids), len(net.rxnids))), rowvarids, net.rxnids) for spid in rowvarids: for rxnid in net.rxnids: try: stoichcoef = net.rxns[rxnid].stoichiometry[spid] # sometimes stoichcoefs are strings if isinstance(stoichcoef, str): stoichcoef = net.evaluate_expr(stoichcoef) N.loc[spid, rxnid] = stoichcoef except KeyError: pass # mat[i,j] remains zero if rxnid2stoich: rxnids = rxnid2stoich.keys() spids = [] for stoich in rxnid2stoich.values(): for spid, stoichcoef in stoich.items(): if int(stoichcoef) != 0 and spid not in spids: spids.append(spid) N = Matrix(np.zeros((len(spids), len(rxnids))), spids, rxnids) for spid in spids: for rxnid in rxnids: try: N.loc[spid, rxnid] = rxnid2stoich[rxnid][spid] except KeyError: pass # mat[i,j] remains zero # make all stoichcoefs integers by first expressing them in fractions if integerize: for i in range(N.ncol): col = N.iloc[:, i] nonzeros = [num for num in butil.flatten(col) if num] denoms = [ fractions.Fraction(nonzero).limit_denominator().denominator for nonzero in nonzeros ] denom = np.prod(list(set(denoms))) N.iloc[:, i] = col * denom if net is not None: net.stoich_mat = N if not to_mat: N = N.values return N
def get_ss_flux_mat(net, integerize=True, to_mat=True): """ Input: net & stoichmat: one and only one of them should be given integerize: does not work very well so far: eg, for N = RBCO PGAK GAPDH REGN RK PGAT GAPT RuBP -1 0 0 0 1 0 0 PGA 2 -1 0 0 0 -1 0 BPGA 0 1 -1 0 0 0 0 GAP 0 0 1 -5 0 0 -1 Ru5P 0 0 0 3 -1 0 0, or: N = array([[-1., 0., 0., 0., 1., 0., 0.], [ 2., -1., 0., 0., 0., -1., 0.], [ 0., 1., -1., 0., 0., 0., 0.], [ 0., 0., 1., -5., 0., 0., -1.], [ 0., 0., 0., 3., -1., 0., 0.]]) K should be: RBCO 3 0 PGAK 0 1 GAPDH 0 1 REGN 1 0 RK 3 0 PGAT 6 -1 GAPT -5 1 But this code, using "integerize" gives: RBCO 3 0 PGAK 0 1 GAPDH 0 1 REGN 0 0 RK 3 0 PGAT 6 -1 GAPT -5 1 For this reason, "integerize" should not be used for now unless debugged and more testings have been done, and integer N is required for now. """ try: K = net.ss_flux_mat N = net.N if (K.ncol == 0 and N.rank == N.ncol) or\ ((N*K).is_zero() and K.ncol + N.rank == N.ncol): return K else: raise ValueError("") except (AttributeError, ValueError): ## The following codes compute the INTEGER basis of right null space ## of stoichiometry matrix. ## convert the matrix into a string recognizable by sage N = net.N N_int = Matrix.astype(N, np.int) if np.allclose(N, N_int): N = N_int else: raise ValueError("N is not in integers.") if N.rank == N.ncol: K = Matrix(None, net.rxnids) else: matstr = re.sub('\s|[a-z]|\(|\)', '', np.matrix(N).__repr__()) ## write a (sage) python script ".tmp_sage.py" # for more info of the sage commands: # http://www.sagemath.org/doc/faq/faq-usage.html#how-do-i # -import-sage-into-a-python-script # http://www.sagemath.org/doc/tutorial/tour_linalg.html f = open('.tmp_sage.py', 'w') f.write('from sage.all import *\n\n') if np.float in N.dtypes.values: f.write('A = matrix(RR, %s)\n\n' % matstr) # real field else: f.write('A = matrix(ZZ, %s)\n\n' % matstr) # integer field f.write('print kernel(A.transpose())' ) # return right nullspace vectors f.close() ## call sage and run .tmp_sage.py out = subprocess.Popen(['sage', '-python', '.tmp_sage.py'], stdout=subprocess.PIPE) ## process the output from sage vecstrs = out.communicate()[0].split('\n')[2:-1] #vecs = [eval(re.sub('(?<=\d)\s*(?=\d|-)', ',', vec)) # for vec in vecstrs] vecs = [ filter(None, vec.strip('[]').split(' ')) for vec in vecstrs ] try: vecs = [[int(elem) for elem in vec if elem] for vec in vecs] except ValueError: vecs = [[float(elem) for elem in vec if elem] for vec in vecs] fdids = ['J%d' % idx for idx in range(1, len(vecs) + 1)] K = Matrix(np.transpose(vecs), net.rxnids, fdids) if integerize: # buggy, see the docstring FIXME ** for i in range(K.ncol): col = K.iloc[:, i] nonzeros = [num for num in butil.flatten(col) if num] denoms = [ fractions.Fraction(nonzero).limit_denominator( 1000).denominator for nonzero in nonzeros ] denom = np.prod(list(set(denoms))) K.iloc[:, i] = np.asarray(col * denom, dtype='int') assert (N*K).is_zero(), "The calculated K is not really in"\ "the nullspace of N!" net.ss_flux_mat = K if not to_mat: K = K.values return K
def get_stoich_mat(net=None, rxnid2stoich=None, only_dynvar=True, integerize=True): """Return the stoichiometry matrix (N) of the given network or dict rxnid2stoich. Rows correspond to species, and columns correspond to reactions. Input: rxnid2stoich: eg, {'R1':{'A1:1}, 'R2':{'A1':1}}; net & rxnid2stoich: one and only one should be given only_dynvar: if True, use *dynamic* species as rows (keep out constant/buffered species); if False, use species as row integerize: if True, make all stoichcoefs integers """ if net: try: N = net.stoich_mat ## need to check what structures are examined... FIXME if net._get_structure() == net._last_structure: return N else: net.compile() # it does the assignment net._last_structure = net._get_structure() raise ValueError("Net's structure has been changed and\ N potentially outdated.") except (AttributeError, ValueError): if only_dynvar: rowvarids = net.xids else: rowvarids = net.spids N = Matrix(np.zeros((len(rowvarids), len(net.rxnids))), rowvarids, net.rxnids) for spid in rowvarids: for rxnid in net.rxnids: try: stoichcoef = net.rxns[rxnid].stoichiometry[spid] # sometimes stoichcoefs are strings if isinstance(stoichcoef, str): stoichcoef = net.evaluate_expr(stoichcoef) N.loc[spid, rxnid] = stoichcoef except KeyError: pass # mat[i,j] remains zero if rxnid2stoich: rxnids = rxnid2stoich.keys() spids = [] for stoich in rxnid2stoich.values(): for spid, stoichcoef in stoich.items(): if int(stoichcoef) != 0 and spid not in spids: spids.append(spid) N = Matrix(np.zeros((len(spids), len(rxnids))), spids, rxnids) for spid in spids: for rxnid in rxnids: try: N.loc[spid, rxnid] = rxnid2stoich[rxnid][spid] except KeyError: pass # mat[i,j] remains zero # make all stoichcoefs integers by first expressing them in fractions if integerize: for i in range(N.ncol): col = N.iloc[:,i] nonzeros = [num for num in butil.flatten(col) if num] denoms = [fractions.Fraction(str(round(nonzero,2))).denominator for nonzero in nonzeros] denom = np.prod(list(set(denoms))) N.iloc[:,i] = col * denom if net is not None: net.stoich_mat = N return N