def export(self): """Export Python code for simulation of a model without PySB. Returns ------- string String containing the standalone Python code. """ if self.model.expressions: raise ExpressionsNotSupported() if self.model.compartments: raise CompartmentsNotSupported() output = StringIO() pysb.bng.generate_equations(self.model) # Note: This has a lot of duplication from pysb.integrate. # Can that be helped? code_eqs = '\n'.join([ 'ydot[%d] = %s;' % (i, sympy.ccode(self.model.odes[i])) for i in range(len(self.model.odes)) ]) code_eqs = re.sub(r'__s(\d+)', lambda m: 'y[%s]' % (int(m.group(1))), code_eqs) for i, p in enumerate(self.model.parameters): code_eqs = re.sub(r'\b(%s)\b' % p.name, 'p[%d]' % i, code_eqs) if self.docstring: output.write('"""') output.write(self.docstring) output.write('"""\n\n') output.write("# exported from PySB model '%s'\n" % self.model.name) output.write( pad(r""" import numpy import scipy.integrate import collections import itertools import distutils.errors """)) output.write( pad(r""" _use_cython = False # try to inline a C statement to see if Cython is functional try: import Cython except ImportError: Cython = None if Cython: from Cython.Compiler.Errors import CompileError try: Cython.inline('x = 1', force=True, quiet=True) _use_cython = True except (CompileError, distutils.errors.CompileError, ValueError): pass Parameter = collections.namedtuple('Parameter', 'name value') Observable = collections.namedtuple('Observable', 'name species coefficients') Initial = collections.namedtuple('Initial', 'param_index species_index') """)) output.write("\n") output.write("class Model(object):\n") init_data = { 'num_species': len(self.model.species), 'num_params': len(self.model.parameters), 'num_observables': len(self.model.observables), 'num_ics': len(self.model.initials), } output.write( pad( r""" def __init__(self): self.y = None self.yobs = None self.y0 = numpy.empty(%(num_species)d) self.ydot = numpy.empty(%(num_species)d) self.sim_param_values = numpy.empty(%(num_params)d) self.parameters = [None] * %(num_params)d self.observables = [None] * %(num_observables)d self.initials = [None] * %(num_ics)d """, 4) % init_data) for i, p in enumerate(self.model.parameters): p_data = (i, repr(p.name), p.value) output.write(" " * 8) output.write("self.parameters[%d] = Parameter(%s, %.17g)\n" % p_data) output.write("\n") for i, obs in enumerate(self.model.observables): obs_data = (i, repr(obs.name), repr(obs.species), repr(obs.coefficients)) output.write(" " * 8) output.write("self.observables[%d] = Observable(%s, %s, %s)\n" % obs_data) output.write("\n") for i, ic in enumerate(self.model.initials): ic_data = (i, self.model.parameters.index(ic.value), self.model.get_species_index(ic.pattern)) output.write(" " * 8) output.write("self.initials[%d] = Initial(%d, %d)\n" % ic_data) output.write("\n") output.write(" " * 8) if 'math.' in code_eqs: code_eqs = 'import math\n' + code_eqs output.write('code_eqs = \'\'\'\n%s\n\'\'\'\n' % code_eqs.replace(';', '')) output.write(" " * 8) output.write("if _use_cython:\n") output.write( pad( r""" def ode_rhs(t, y, p): ydot = self.ydot Cython.inline(code_eqs, quiet=True) return ydot """, 12)) output.write(" else:\n") output.write( pad( r""" def ode_rhs(t, y, p): ydot = self.ydot exec(code_eqs) return ydot """, 12)) output.write(" " * 8) output.write('self.integrator = scipy.integrate.ode(ode_rhs)\n') output.write(" " * 8) output.write("self.integrator.set_integrator('vode', method='bdf', " "with_jacobian=True)\n") # note the simulate method is fixed, i.e. it doesn't require any templating output.write( pad( r""" def simulate(self, tspan, param_values=None, view=False): if param_values is not None: # accept vector of parameter values as an argument if len(param_values) != len(self.parameters): raise Exception("param_values must have length %d" % len(self.parameters)) self.sim_param_values[:] = param_values else: # create parameter vector from the values in the model self.sim_param_values[:] = [p.value for p in self.parameters] self.y0.fill(0) for ic in self.initials: self.y0[ic.species_index] = self.sim_param_values[ic.param_index] if self.y is None or len(tspan) != len(self.y): self.y = numpy.empty((len(tspan), len(self.y0))) if len(self.observables): self.yobs = numpy.ndarray(len(tspan), list(zip((obs.name for obs in self.observables), itertools.repeat(float)))) else: self.yobs = numpy.ndarray((len(tspan), 0)) self.yobs_view = self.yobs.view(float).reshape(len(self.yobs), -1) # perform the actual integration self.integrator.set_initial_value(self.y0, tspan[0]) self.integrator.set_f_params(self.sim_param_values) self.y[0] = self.y0 t = 1 while self.integrator.successful() and self.integrator.t < tspan[-1]: self.y[t] = self.integrator.integrate(tspan[t]) t += 1 for i, obs in enumerate(self.observables): self.yobs_view[:, i] = \ (self.y[:, obs.species] * obs.coefficients).sum(1) if view: y_out = self.y.view() yobs_out = self.yobs.view() for a in y_out, yobs_out: a.flags.writeable = False else: y_out = self.y.copy() yobs_out = self.yobs.copy() return (y_out, yobs_out) """, 4)) return output.getvalue()
def export(self): """Generate a MATLAB class definition containing the ODEs for the PySB model associated with the exporter. Returns ------- string String containing the MATLAB code for an implementation of the model's ODEs. """ output = StringIO() pysb.bng.generate_equations(self.model) docstring = '' if self.docstring: docstring += self.docstring.replace('\n', '\n % ') # Substitute underscores for any dots in the model name model_name = self.model.name.replace('.', '_') # -- Parameters and Initial conditions ------- # Declare the list of parameters as a struct params_str = 'self.parameters = struct( ...\n'+' '*16 params_str_list = [] for i, p in enumerate(self.model.parameters): # Add parameter to struct along with nominal value cur_p_str = "'%s', %.17g" % (_fix_underscores(p.name), p.value) # Decide whether to continue or terminate the struct declaration: if i == len(self.model.parameters) - 1: cur_p_str += ');' # terminate else: cur_p_str += ', ...' # continue params_str_list.append(cur_p_str) # Format and indent the params struct declaration params_str += ('\n'+' '*16).join(params_str_list) # Fill in an array of the initial conditions based on the named # parameter values initial_values_str = ('initial_values = zeros(1,%d);\n'+' '*12) % \ len(self.model.species) initial_values_str += ('\n'+' '*12).join( ['initial_values(%d) = self.parameters.%s; %% %s' % (i+1, _fix_underscores(ic[1].name), ic[0]) for i, ic in enumerate(self.model.initial_conditions)]) # -- Build observables declaration -- observables_str = 'self.observables = struct( ...\n'+' '*16 observables_str_list = [] for i, obs in enumerate(self.model.observables): # Associate species and coefficient lists with observable names, # changing from zero- to one-based indexing cur_obs_str = "'%s', [%s; %s]" % \ (_fix_underscores(obs.name), ' '.join([str(sp+1) for sp in obs.species]), ' '.join([str(c) for c in obs.coefficients])) # Decide whether to continue or terminate the struct declaration: if i == len(self.model.observables) - 1: cur_obs_str += ');' # terminate else: cur_obs_str += ', ...' # continue observables_str_list.append(cur_obs_str) # Format and indent the observables struct declaration observables_str += ('\n'+' '*16).join(observables_str_list) # -- Build ODEs ------- # Build a stringified list of species species_list = ['%% %s;' % s for i, s in enumerate(self.model.species)] # Build the ODEs as strings from the model.odes array odes_list = ['y(%d,1) = %s;' % (i+1, sympy.ccode(self.model.odes[i])) for i in range(len(self.model.odes))] # Zip the ODEs and species string lists and then flatten them # (results in the interleaving of the two lists) odes_species_list = [item for sublist in zip(species_list, odes_list) for item in sublist] # Flatten to a string and add correct indentation odes_str = ('\n'+' '*12).join(odes_species_list) # Change species names from, e.g., '__s(0)' to 'y0(1)' (note change # from zero-based indexing to 1-based indexing) odes_str = re.sub(r'__s(\d+)', \ lambda m: 'y0(%s)' % (int(m.group(1))+1), odes_str) # Change C code 'pow' function to MATLAB 'power' function odes_str = re.sub(r'pow\(', 'power(', odes_str) # Prepend 'p.' to named parameters and fix any underscores for i, p in enumerate(self.model.parameters): odes_str = re.sub(r'\b(%s)\b' % p.name, 'p.%s' % _fix_underscores(p.name), odes_str) # -- Build final output -- output.write(pad(r""" classdef %(model_name)s %% %(docstring)s %% A class implementing the ordinary differential equations %% for the %(model_name)s model. %% %% Save as %(model_name)s.m. %% %% Generated by pysb.export.matlab.MatlabExporter. %% %% Properties %% ---------- %% observables : struct %% A struct containing the names of the observables from the %% PySB model as field names. Each field in the struct %% maps the observable name to a matrix with two rows: %% the first row specifies the indices of the species %% associated with the observable, and the second row %% specifies the coefficients associated with the species. %% For any given timecourse of model species resulting from %% integration, the timecourse for an observable can be %% retrieved using the get_observable method, described %% below. %% %% parameters : struct %% A struct containing the names of the parameters from the %% PySB model as field names. The nominal values are set by %% the constructor and their values can be overriden %% explicitly once an instance has been created. %% %% Methods %% ------- %% %(model_name)s.odes(tspan, y0) %% The right-hand side function for the ODEs of the model, %% for use with MATLAB ODE solvers (see Examples). %% %% %(model_name)s.get_initial_values() %% Returns a vector of initial values for all species, %% specified in the order that they occur in the original %% PySB model (i.e., in the order found in model.species). %% Non-zero initial conditions are specified using the %% named parameters included as properties of the instance. %% Hence initial conditions other than the defaults can be %% used by assigning a value to the named parameter and then %% calling this method. The vector returned by the method %% is used for integration by passing it to the MATLAB %% solver as the y0 argument. %% %% %(model_name)s.get_observables(y) %% Given a matrix of timecourses for all model species %% (i.e., resulting from an integration of the model), %% get the trajectories corresponding to the observables. %% Timecourses are returned as a struct which can be %% indexed by observable name. %% %% Examples %% -------- %% Example integration using default initial and parameter %% values: %% %% >> m = %(model_name)s(); %% >> tspan = [0 100]; %% >> [t y] = ode15s(@m.odes, tspan, m.get_initial_values()); %% %% Retrieving the observables: %% %% >> y_obs = m.get_observables(y) %% properties observables parameters end methods function self = %(model_name)s() %% Assign default parameter values %(params_str)s %% Define species indices (first row) and coefficients %% (second row) of named observables %(observables_str)s end function initial_values = get_initial_values(self) %% Return the vector of initial conditions for all %% species based on the values of the parameters %% as currently defined in the instance. %(initial_values_str)s end function y = odes(self, tspan, y0) %% Right hand side function for the ODEs %% Shorthand for the struct of model parameters p = self.parameters; %(odes_str)s end function y_obs = get_observables(self, y) %% Retrieve the trajectories for the model observables %% from a matrix of the trajectories of all model %% species. %% Initialize the struct of observable timecourses %% that we will return y_obs = struct(); %% Iterate over the observables; observable_names = fieldnames(self.observables); for i = 1:numel(observable_names) obs_matrix = self.observables.(observable_names{i}); species = obs_matrix(1, :); coefficients = obs_matrix(2, :); y_obs.(observable_names{i}) = ... y(:, species) * coefficients'; end end end end """, 0) % {'docstring': docstring, 'model_name': model_name, 'params_str':params_str, 'initial_values_str': initial_values_str, 'observables_str': observables_str, 'params_str': params_str, 'odes_str': odes_str}) return output.getvalue()
def export(self): """Export STAN code for simulation of a model using STAN Returns ------- string String containing the STAN code. """ output = StringIO() pysb.bng.generate_equations(self.model) # Note: This has a lot of duplication from pysb.integrate. # Can that be helped? code_eqs = '\n'.join(['ydot[%d] = %s;' % (i+1, sympy.ccode(self.model.odes[i])) for i in range(len(self.model.odes))]) code_eqs = re.sub(r's(\d+)', lambda m: 'y[%s]' % (int(m.group(1))+1), code_eqs) for i, p in enumerate(self.model.parameters): code_eqs = re.sub(r'\b(%s)\b' % p.name, 'p[%s]' % str(i+1), code_eqs) init_data = { 'num_species': len(self.model.species), 'num_params': len(self.model.parameters), 'num_observables': len(self.model.observables), 'num_ics': len(self.model.initial_conditions), } if self.docstring: output.write('"""') output.write(self.docstring) output.write('"""\n\n') output.write("// exported from PySB model '%s'\n" % self.model.name) # output independent STAN model and simulation code # first write the STAN code as a string #output.write('stan_code = r"""') output.write("functions{") # EDIT BY DUNCAN KIRBY: REMOVE '_' FROM code_eqs TO GET SIMULATIONS TO RUN code_eqs = re.sub('_','',code_eqs) output.write(pad(r""" real[] ode_rhs(real t, real[] y, real[] p, real[] x_r, int[] x_i){ real ydot[%d];""",4) % init_data['num_species']) output.write(r""" %s return ydot; } } """ % pad('\n' + code_eqs, 8).strip()) # note the simulate method is fixed, i.e. it doesn't require any templating output.write(r""" data { int<lower=1> T; real t0; real ts[%d]; } transformed data { real x_r[0]; int x_i[0]; } parameters{ } transformed parameters { real y0[%d]; real p[%d]; """ % (72,init_data['num_species'],init_data['num_params'])) # initial conditions species_stringList = [str(el) for el in self.model.species] used_indices=[] for ic in self.model.initial_conditions: y_index = species_stringList.index(str(ic[0]))+1 used_indices.append(y_index) output.write(" y0[%d] = %d;\n" % (y_index, ic[1].value)) for i in range(1,init_data['num_species']+1): if i not in used_indices: output.write(" y0[%d] = 0;\n" % i) # model parameter vector for i, p in enumerate(self.model.parameters): p_data = (i+1, p.value, repr(p.name)) output.write(" p[%d] = %.8g; // %s\n" % p_data) output.write(r""" } model { real y[72,%d]; real observables[72,%d]; y = integrate_ode_rk45(ode_rhs, y0, t0, ts, p, x_r, x_i); """ % (init_data['num_species'],init_data['num_observables'])) # observables output.write(""" for (t in 1:72) {""") output.write("\n") for i, obs in enumerate(self.model.observables): ycoords = [j for j in obs.species] for ind in range(len(ycoords)):# offset indices by 1 ycoords[ind]+=1 if ycoords == []:# pass 0 to observables which don't appear in ODE equations ycoords = 0 obs_data = (i+1, str(ycoords).replace(", ","]+y[t,")[1:], repr(obs.name)) output.write(" " * 8) if ycoords==0: output.write("observables[t,%d] =%s 0; // %s\n" % obs_data) else: output.write("observables[t,%d] = y[t,%s; // %s\n" % obs_data) output.write(""" } }""") #output.write('"""') # now write the simulation code output.write(r""" # suggested python code: /* # Import the required libraries import pystan import numpy as np import scipy import os import pickle from matplotlib import pyplot as plt # Check to see if we can avoid compiling the model: cwd=os.getcwd() if os.path.isfile(cwd+'/STAN_alpha.pkl'): print('Model has been compiled') sm = pickle.load(open('STAN_alpha.pkl','rb')) else: sm = pystan.StanModel(file='STAN_alpha.stan') # save the compiled model for later use with open('STAN_alpha.pkl','wb') as f: pickle.dump(sm,f) # Simulate the model deltaT = 50 t_end = 3600 t0 = -1 ts = np.arange(0,t_end*deltaT,deltaT)""") output.write(r""" samples = sm.sampling(data={'T':t_end,'t0':t0,'ts':ts}, algorithm='Fixed_param', seed=42, chains=1, iter=1) #samples.plot() #plt.show() # Plot TotalpSTAT res = samples.extract("observables",permuted=False)['observables'][0][0] plt.plot(range(0,t_end,deltaT),res[:,11]) plt.show() */""") return output.getvalue()
def export(self): """Generate a MATLAB class definition containing the ODEs for the PySB model associated with the exporter. Returns ------- string String containing the MATLAB code for an implementation of the model's ODEs. """ output = StringIO() pysb.bng.generate_equations(self.model) docstring = '' if self.docstring: docstring += self.docstring.replace('\n', '\n % ') # Substitute underscores for any dots in the model name model_name = self.model.name.replace('.', '_') # -- Parameters and Initial conditions ------- # Declare the list of parameters as a struct params_str = 'self.parameters = struct( ...\n' + ' ' * 16 params_str_list = [] for i, p in enumerate(self.model.parameters): # Add parameter to struct along with nominal value cur_p_str = "'%s', %.17g" % (_fix_underscores(p.name), p.value) # Decide whether to continue or terminate the struct declaration: if i == len(self.model.parameters) - 1: cur_p_str += ');' # terminate else: cur_p_str += ', ...' # continue params_str_list.append(cur_p_str) # Format and indent the params struct declaration params_str += ('\n' + ' ' * 16).join(params_str_list) # Fill in an array of the initial conditions based on the named # parameter values initial_values_str = ('initial_values = zeros(1,%d);\n'+' '*12) % \ len(self.model.species) initial_values_str += ('\n' + ' ' * 12).join([ 'initial_values(%d) = self.parameters.%s; %% %s' % (i + 1, _fix_underscores(ic[1].name), ic[0]) for i, ic in enumerate(self.model.initial_conditions) ]) # -- Build observables declaration -- observables_str = 'self.observables = struct( ...\n' + ' ' * 16 observables_str_list = [] for i, obs in enumerate(self.model.observables): # Associate species and coefficient lists with observable names, # changing from zero- to one-based indexing cur_obs_str = "'%s', [%s; %s]" % \ (_fix_underscores(obs.name), ' '.join([str(sp+1) for sp in obs.species]), ' '.join([str(c) for c in obs.coefficients])) # Decide whether to continue or terminate the struct declaration: if i == len(self.model.observables) - 1: cur_obs_str += ');' # terminate else: cur_obs_str += ', ...' # continue observables_str_list.append(cur_obs_str) # Format and indent the observables struct declaration observables_str += ('\n' + ' ' * 16).join(observables_str_list) # -- Build ODEs ------- # Build a stringified list of species species_list = ['%% %s;' % s for i, s in enumerate(self.model.species)] # Build the ODEs as strings from the model.odes array odes_list = [ 'y(%d,1) = %s;' % (i + 1, sympy.ccode(self.model.odes[i])) for i in range(len(self.model.odes)) ] # Zip the ODEs and species string lists and then flatten them # (results in the interleaving of the two lists) odes_species_list = [ item for sublist in zip(species_list, odes_list) for item in sublist ] # Flatten to a string and add correct indentation odes_str = ('\n' + ' ' * 12).join(odes_species_list) # Change species names from, e.g., '__s(0)' to 'y0(1)' (note change # from zero-based indexing to 1-based indexing) odes_str = re.sub(r'__s(\d+)', \ lambda m: 'y0(%s)' % (int(m.group(1))+1), odes_str) # Change C code 'pow' function to MATLAB 'power' function odes_str = re.sub(r'pow\(', 'power(', odes_str) # Prepend 'p.' to named parameters and fix any underscores for i, p in enumerate(self.model.parameters): odes_str = re.sub(r'\b(%s)\b' % p.name, 'p.%s' % _fix_underscores(p.name), odes_str) # -- Build final output -- output.write( pad( r""" classdef %(model_name)s %% %(docstring)s %% A class implementing the ordinary differential equations %% for the %(model_name)s model. %% %% Save as %(model_name)s.m. %% %% Generated by pysb.export.matlab.MatlabExporter. %% %% Properties %% ---------- %% observables : struct %% A struct containing the names of the observables from the %% PySB model as field names. Each field in the struct %% maps the observable name to a matrix with two rows: %% the first row specifies the indices of the species %% associated with the observable, and the second row %% specifies the coefficients associated with the species. %% For any given timecourse of model species resulting from %% integration, the timecourse for an observable can be %% retrieved using the get_observable method, described %% below. %% %% parameters : struct %% A struct containing the names of the parameters from the %% PySB model as field names. The nominal values are set by %% the constructor and their values can be overriden %% explicitly once an instance has been created. %% %% Methods %% ------- %% %(model_name)s.odes(tspan, y0) %% The right-hand side function for the ODEs of the model, %% for use with MATLAB ODE solvers (see Examples). %% %% %(model_name)s.get_initial_values() %% Returns a vector of initial values for all species, %% specified in the order that they occur in the original %% PySB model (i.e., in the order found in model.species). %% Non-zero initial conditions are specified using the %% named parameters included as properties of the instance. %% Hence initial conditions other than the defaults can be %% used by assigning a value to the named parameter and then %% calling this method. The vector returned by the method %% is used for integration by passing it to the MATLAB %% solver as the y0 argument. %% %% %(model_name)s.get_observables(y) %% Given a matrix of timecourses for all model species %% (i.e., resulting from an integration of the model), %% get the trajectories corresponding to the observables. %% Timecourses are returned as a struct which can be %% indexed by observable name. %% %% Examples %% -------- %% Example integration using default initial and parameter %% values: %% %% >> m = %(model_name)s(); %% >> tspan = [0 100]; %% >> [t y] = ode15s(@m.odes, tspan, m.get_initial_values()); %% %% Retrieving the observables: %% %% >> y_obs = m.get_observables(y) %% properties observables parameters end methods function self = %(model_name)s() %% Assign default parameter values %(params_str)s %% Define species indices (first row) and coefficients %% (second row) of named observables %(observables_str)s end function initial_values = get_initial_values(self) %% Return the vector of initial conditions for all %% species based on the values of the parameters %% as currently defined in the instance. %(initial_values_str)s end function y = odes(self, tspan, y0) %% Right hand side function for the ODEs %% Shorthand for the struct of model parameters p = self.parameters; %(odes_str)s end function y_obs = get_observables(self, y) %% Retrieve the trajectories for the model observables %% from a matrix of the trajectories of all model %% species. %% Initialize the struct of observable timecourses %% that we will return y_obs = struct(); %% Iterate over the observables; observable_names = fieldnames(self.observables); for i = 1:numel(observable_names) obs_matrix = self.observables.(observable_names{i}); if isempty(obs_matrix) y_obs.(observable_names{i}) = zeros(size(y, 1), 1); continue end species = obs_matrix(1, :); coefficients = obs_matrix(2, :); y_obs.(observable_names{i}) = ... y(:, species) * coefficients'; end end end end """, 0) % { 'docstring': docstring, 'model_name': model_name, 'params_str': params_str, 'initial_values_str': initial_values_str, 'observables_str': observables_str, 'params_str': params_str, 'odes_str': odes_str }) return output.getvalue()
def export(self): """Export Python code for simulation of a model without PySB. Returns ------- string String containing the standalone Python code. """ output = StringIO() pysb.bng.generate_equations(self.model) # Note: This has a lot of duplication from pysb.integrate. # Can that be helped? code_eqs = '\n'.join(['ydot[%d] = %s;' % (i, sympy.ccode(self.model.odes[i])) for i in range(len(self.model.odes))]) code_eqs = re.sub(r's(\d+)', lambda m: 'y[%s]' % (int(m.group(1))), code_eqs) for i, p in enumerate(self.model.parameters): code_eqs = re.sub(r'\b(%s)\b' % p.name, 'p[%d]' % i, code_eqs) if self.docstring: output.write('"""') output.write(self.docstring) output.write('"""\n\n') output.write("# exported from PySB model '%s'\n" % self.model.name) output.write(pad(r""" import numpy import scipy.weave, scipy.integrate import collections import itertools import distutils.errors """)) output.write(pad(r""" _use_inline = False # try to inline a C statement to see if inline is functional try: scipy.weave.inline('int i;', force=1) _use_inline = True except distutils.errors.CompileError: pass Parameter = collections.namedtuple('Parameter', 'name value') Observable = collections.namedtuple('Observable', 'name species coefficients') Initial = collections.namedtuple('Initial', 'param_index species_index') """)) output.write("\n") output.write("class Model(object):\n") init_data = { 'num_species': len(self.model.species), 'num_params': len(self.model.parameters), 'num_observables': len(self.model.observables), 'num_ics': len(self.model.initial_conditions), } output.write(pad(r""" def __init__(self): self.y = None self.yobs = None self.integrator = scipy.integrate.ode(self.ode_rhs) self.integrator.set_integrator('vode', method='bdf', with_jacobian=True) self.y0 = numpy.empty(%(num_species)d) self.ydot = numpy.empty(%(num_species)d) self.sim_param_values = numpy.empty(%(num_params)d) self.parameters = [None] * %(num_params)d self.observables = [None] * %(num_observables)d self.initial_conditions = [None] * %(num_ics)d """, 4) % init_data) for i, p in enumerate(self.model.parameters): p_data = (i, repr(p.name), p.value) output.write(" " * 8) output.write("self.parameters[%d] = Parameter(%s, %.17g)\n" % p_data) output.write("\n") for i, obs in enumerate(self.model.observables): obs_data = (i, repr(obs.name), repr(obs.species), repr(obs.coefficients)) output.write(" " * 8) output.write("self.observables[%d] = Observable(%s, %s, %s)\n" % obs_data) output.write("\n") for i, (cp, param) in enumerate(self.model.initial_conditions): ic_data = (i, self.model.parameters.index(param), self.model.get_species_index(cp)) output.write(" " * 8) output.write("self.initial_conditions[%d] = Initial(%d, %d)\n" % ic_data) output.write("\n") output.write(" if _use_inline:\n") output.write(pad(r""" def ode_rhs(self, t, y, p): ydot = self.ydot scipy.weave.inline(r'''%s''', ['ydot', 't', 'y', 'p']) return ydot """, 8) % (pad('\n' + code_eqs, 16) + ' ' * 16)) output.write(" else:\n") output.write(pad(r""" def ode_rhs(self, t, y, p): ydot = self.ydot %s return ydot """, 8) % pad('\n' + code_eqs, 12).replace(';','').strip()) # note the simulate method is fixed, i.e. it doesn't require any templating output.write(pad(r""" def simulate(self, tspan, param_values=None, view=False): if param_values is not None: # accept vector of parameter values as an argument if len(param_values) != len(self.parameters): raise Exception("param_values must have length %d" % len(self.parameters)) self.sim_param_values[:] = param_values else: # create parameter vector from the values in the model self.sim_param_values[:] = [p.value for p in self.parameters] self.y0.fill(0) for ic in self.initial_conditions: self.y0[ic.species_index] = self.sim_param_values[ic.param_index] if self.y is None or len(tspan) != len(self.y): self.y = numpy.empty((len(tspan), len(self.y0))) if len(self.observables): self.yobs = numpy.ndarray(len(tspan), zip((obs.name for obs in self.observables), itertools.repeat(float))) else: self.yobs = numpy.ndarray((len(tspan), 0)) self.yobs_view = self.yobs.view(float).reshape(len(self.yobs), -1) # perform the actual integration self.integrator.set_initial_value(self.y0, tspan[0]) self.integrator.set_f_params(self.sim_param_values) self.y[0] = self.y0 t = 1 while self.integrator.successful() and self.integrator.t < tspan[-1]: self.y[t] = self.integrator.integrate(tspan[t]) t += 1 for i, obs in enumerate(self.observables): self.yobs_view[:, i] = \ (self.y[:, obs.species] * obs.coefficients).sum(1) if view: y_out = self.y.view() yobs_out = self.yobs.view() for a in y_out, yobs_out: a.flags.writeable = False else: y_out = self.y.copy() yobs_out = self.yobs.copy() return (y_out, yobs_out) """, 4)) return output.getvalue()