def setUp(self): # dx1 (t)/dt = x1 (t), x1 (0) = 1 # x1 (t) = e ^ t self.odes = ODES() self.odes.add_equation("x1", "x1") self.odes.define_initial_value("x1", 1.0) self.theta = RandomParameterList() sigma_dist = Gamma(1, 1) sigma = RandomParameter("sigma", sigma_dist) sigma.value = 1.0 self.theta.set_experimental_error(sigma)
def test_equation_parameters (self): """ Tests if the system can store equation parameters correctly. """ odes = ODES () odes.add_equation ("x1", "k * x1") odes.define_initial_value ("x1", 1.0) odes.define_parameter ("k", 2) # Solution is x1 (t) = exp (2t) t = np.linspace (0, 2, 11) y = odes.evaluate_on (t) for i in range (len (t)): analytic = math.exp (2 * t[i]) assert (abs (y["x1"][i] - analytic) / analytic < 1e-1)
def test_differentiation (self): odes = ODES () odes.add_equation ("S", "- (p1 * S)") odes.add_equation ("R", "p2 * R * S") odes.define_parameter ("p1", 2) odes.define_parameter ("p2", 4) jac_f = odes.get_system_jacobian () jac = jac_f ([0], [1, 1], args=(2, 4)) self.assertEqual (jac[0][0], -2) self.assertEqual (jac[0][1], 0) self.assertEqual (jac[1][0], 4) self.assertEqual (jac[1][1], 4)
def test_initial_status (self): """ Tests if the system starts at the initial state. """ odes = ODES () # dx1(t)/dt = x1 (t) # dx2(t)/dt = x2 (t) odes.add_equation ("x1", "x1") odes.add_equation ("x2", "x2") odes.define_initial_value ("x1", 100.0) odes.define_initial_value ("x2", 250.5) y = odes.evaluate_on ([0]) self.assertListEqual (y["x1"], [100]) self.assertListEqual (y["x2"], [250.5])
def test_when_solution_times_doesnt_start_on_zero (self): """ Tests what happens when the times asked for an evaluation do not start on zero. """ odes = ODES () # dx1 (t)/dt = x1 (t) # Solution is x1 (t) = exp (t) odes.add_equation ("x1", "x1") odes.define_initial_value ("x1", 1.0) t = np.linspace (3, 5, 12) y = odes.evaluate_on (t) for i in range (len (t)): analytic = math.exp (t[i]) assert (abs (y["x1"][i] - analytic) / analytic < 1e-1)
def test_solve_with_arbitrary_initial_state (self): """ Tests if one can solve an ODES with an arbitrary initial state set as a parameter. """ odes = ODES () # dx1 (t)/dt = x1 (t) # Solution is x1 (t) = 10 * exp (t) when x1(0) = 10 odes.add_equation ("x1", "x1") odes.define_initial_value ("x1", 1.0) t = np.linspace (0, 2, 11) initial_state = {"x1": 10.0} y = odes.evaluate_on (t, initial_state) for i in range (len (t)): analytic = 10 * math.exp (t[i]) assert (abs (y["x1"][i] - analytic) / analytic < 1e-1)
def sbml_to_odes(sbml): """ Creates an ODE model given an SBML object. Parameters: sbml: a model.SBML object. Returns an ODES object that is a system of differential equations that rules the concentration changes of the chemical species specified on the sbml model. """ odes = ODES() variables = sbml.get_species_list() for var in variables: formula = sbml.get_species_kinetic_law(var) initial_val = sbml.get_initial_concentration(var) odes.add_equation(var, formula) odes.define_initial_value(var, initial_val) params = sbml.get_all_param() for param in params: odes.define_parameter(param, params[param]) odes.name = sbml.name return odes
class TestLikelihoodFunction(unittest.TestCase): def setUp(self): # dx1 (t)/dt = x1 (t), x1 (0) = 1 # x1 (t) = e ^ t self.odes = ODES() self.odes.add_equation("x1", "x1") self.odes.define_initial_value("x1", 1.0) self.theta = RandomParameterList() sigma_dist = Gamma(1, 1) sigma = RandomParameter("sigma", sigma_dist) sigma.value = 1.0 self.theta.set_experimental_error(sigma) def __gaussian(self, mu, sigma, x): """ Calculates a point of the gaussian function. """ l = np.exp (-.5 * ((x - mu) / sigma) ** 2) * \ (1 / (sigma * np.sqrt (2 * np.pi))) return l def test_get_likelihood_point(self): """ Tests if the likelihood can return the correct value when there's only one observation. """ # x1(0) = 1.0 # D ~ Gaussian (x1(0), 1) ~ Gaussian (1, 1) # f_D (1) = e ^ -{[(0) ^ 2] / [2 * 1]} * {1 * sqrt (2pi)} ^ -1 f_D = self.__gaussian(1, 1, 1) analytic = np.log(f_D) t = [0] values = [1.0] var = "x1" experiments = [Experiment(t, values, var)] likelihood_f = LikelihoodFunction(self.odes) l = likelihood_f.get_log_likelihood(experiments, self.theta) assert (abs(analytic - l) < 1e-8) def test_get_likelihood_over_time(self): """ Tests if the likelihood can return the correct value when the observation occurs in multiple time points. """ t = [0, .25, .5, .75, 1] D = [np.exp(x) for x in t] experiments = [Experiment(t, D, "x1")] f_D = 1 for y in D: f_D *= self.__gaussian(y, 1, y) analytic = np.log(f_D) likelihood_f = LikelihoodFunction(self.odes) l = likelihood_f.get_log_likelihood(experiments, self.theta) assert (abs(analytic - l) < 1e-2) def test_get_likelihood_experiment_set(self): """ Tests if can return the likelihood of data in respect to multiple experimnets. """ t = [0, .25, .5, .75, 1] D = [np.exp(x) for x in t] experiment = Experiment(t, D, "x1") experiments = [experiment, experiment] f_D = 1 for y in D: f_D *= self.__gaussian(y, 1, y) f_D **= 2 analytic = np.log(f_D) likelihood_f = LikelihoodFunction(self.odes) l = likelihood_f.get_log_likelihood(experiments, self.theta) assert (abs(analytic - l) < 1e-2)
def test_get_system_jacobian (self): """ Tests if we can produce the jacobian of the system. """ odes = ODES () # dx1 (t)/dt = x1 (t)/2 + x2(t)/2 # dx2 (t)/dt = x1 (t)/2 + x2(t)/2 # Solution is x1 (t) = exp (t), x2 (t) = exp (t) odes.add_equation ("x1", "x1/2 + x2/2") odes.add_equation ("x2", "x1/2 + x2/2") jac_f = odes.get_system_jacobian () jac = jac_f ([0], [0, 0], args=[]) self.assertEqual (jac[0][0], .5) self.assertEqual (jac[0][1], .5) self.assertEqual (jac[1][0], .5) self.assertEqual (jac[1][1], .5) odes = ODES () odes.add_equation ("x", "x/y") odes.add_equation ("y", "1") jac_f = odes.get_system_jacobian () jac = jac_f ([0], [1, 1], args=[]) self.assertEqual (jac[0][0], 1) assert (abs (jac[0][1] + 1) < 1e-8) self.assertEqual (jac[1][0], 0) self.assertEqual (jac[1][1], 0)
def test_get_parameters (self): """ Tests if the system can return all parameters. """ odes = ODES () odes.add_equation ("x1", "k * x1") odes.define_parameter ("k", 2) odes.add_equation ("x2", "k2 * x2") odes.define_parameter ("k2", 4) params = odes.get_all_parameters () self.assertEqual (params["k"], 2) self.assertEqual (params["k2"], 4)
def test_integration (self): """ Tests if the system can be solved numerically. """ odes = ODES () # dx1 (t)/dt = x1 (t) # Solution is x1 (t) = exp (t) odes.add_equation ("x1", "x1") odes.define_initial_value ("x1", 1.0) t = np.linspace (0, 2, 11) y = odes.evaluate_on (t) for i in range (len (t)): analytic = math.exp (t[i]) assert (abs (y["x1"][i] - analytic) / analytic < 1e-1) odes = ODES () # dx1 (t)/dt = x1 (t)/2 + x2(t)/2 # dx2 (t)/dt = x1 (t)/2 + x2(t)/2 # Solution is x1 (t) = exp (t), x2 (t) = exp (t) odes.add_equation ("x1", "x1/2 + x2/2") odes.add_equation ("x2", "x1/2 + x2/2") odes.define_initial_value ("x1", 1.0) odes.define_initial_value ("x2", 1.0) y = odes.evaluate_on (t) for i in range (len (t)): analytic = math.exp (t[i]) assert (abs (y["x1"][i] - analytic) / analytic < 1e-1) assert (abs (y["x2"][i] - analytic) / analytic < 1e-1)
def test_formulas_with_powers (self): """ Tests if the system can solve forula with powers of variables. """ odes = ODES () # dx (t)/dt = pow (x (t), 2) # Solution is 1/ (1 - t) odes.add_equation ("x", "pow (x, 2)") odes.define_initial_value ("x", 1.0) t = np.linspace (0, .9, 10) y = odes.evaluate_on (t) for i in range (len (t)): analytic = 1 / (1 - t[i]) assert (abs (y["x"][i] - analytic) / analytic < 5e-1) odes = ODES () # dx (t)/dt = x (t) ** 2 odes.add_equation ("x", "x ** 2") odes.define_initial_value ("x", 1.0) t = np.linspace (0, .9, 10) y = odes.evaluate_on (t) for i in range (len (t)): analytic = 1 / (1 - t[i]) assert (abs (y["x"][i] - analytic) / analytic < 5e-1)