def test_jumps_centered_on_current_theta(self): """ Tests if, when using suitable jump distribution, the proposed values are centered on the current theta. """ n = 10 N = 1000 theta_values = np.ones(n) / 3.2 theta = RandomParameterList() for p_val in theta_values: gamma = Gamma(2, 1) rand_par = RandomParameter('p', gamma) rand_par.value = p_val theta.append(rand_par) class JumpMock(AcceptingRateAMCMC): def __init__(self, theta): n = theta.get_size() self._jump_S = [0.001 for x in range(n)] mocked_mh = JumpMock(theta) mean_jump = np.zeros(n) for i in range(N): jump = mocked_mh.propose_jump(theta) mean_jump += jump.get_values() mean_jump /= N assert all(abs(mean_jump - theta_values) < 1e-1)
def test_iterator (self): """ Tests if we can iterate through parameters. """ p1 = RandomParameter ('p1', Gamma (2, 2)) p2 = RandomParameter ('p2', Gamma (2, 2)) theta = RandomParameterList () theta.append (p1) theta.append (p2) for p in theta: assert (p.name == "p1" or p.name == "p2")
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_idexing (self): """ Tests if one can access a parameter with an index. """ p1 = RandomParameter ('p1', Gamma (2, 2)) p2 = RandomParameter ('p2', Gamma (3, 2)) p1.value = 1 p2.value = 2 theta = RandomParameterList () theta.append (p1) theta.append (p2) self.assertEqual (theta[0].name, 'p1') self.assertEqual (theta[1].name, 'p2')
def test_get_values (self): """ Tests if we can get only the values of the parameters. """ p1 = RandomParameter ('p1', Gamma (2, 2)) p2 = RandomParameter ('p2', Gamma (3, 2)) p1.value = 1 p2.value = 2 theta = RandomParameterList () theta.append (p1) theta.append (p2) values = theta.get_values () self.assertEqual (values[0], 1) self.assertEqual (values[1], 2)
def test_get_copy (self): """ Tests if an object can produce a copy of itself. """ p1 = RandomParameter ('p1', Gamma (2, 2)) p2 = RandomParameter ('p2', Gamma (2, 2)) theta = RandomParameterList () theta.append (p1) theta.append (p2) copy = theta.get_copy () self.assertEqual (copy.get_size (), 2) for p in copy: assert (p.name == "p1" or p.name == "p2") p1.name = "new_name" for p in copy: assert (p.name != "new_name")
def test_get_last_sampled (self): """ Tests if one can get the last N sampled parameters. """ n = 10 N = 20 theta = RandomParameterList () for i in range (n): gamma = Gamma (2, 2) rand_par = RandomParameter ('p', gamma) theta.append (rand_par) mocked_mh = MHFullMock (theta) mocked_mh.start_sample_from_prior () mocked_mh.get_sample (2 * N) sample = mocked_mh.get_last_sampled (N)[0] assert (len (sample) > N * .25)
def test_acceptance_ratio (self): """ Tests if the acceptance ratio converges to 0.5 when the mh ratio in a jump proposal is always 0.5. """ n = 10 N = 3000 theta = RandomParameterList () for i in range (n): gamma = Gamma (2, 2) rand_par = RandomParameter ('p', gamma) theta.append (rand_par) mocked_mh = MHFullMock (theta) mocked_mh.start_sample_from_prior () mocked_mh.get_sample (N) acceptance_ratio = mocked_mh.get_acceptance_ratio () assert (abs (acceptance_ratio - .5) < 1e-1)
def test_manual_jump (self): """ Tests if one can perform a manual jump. """ n = 10 theta = RandomParameterList () for i in range (n): gamma = Gamma (2, 2) rand_par = RandomParameter ('p', gamma) theta.append (rand_par) mocked_mh = MHLikelihoodMock (theta) mocked_mh.start_sample_from_prior () mocked_mh.manual_jump (theta, 1) sample = mocked_mh.get_last_sampled (2)[0] last_theta = sample[-1] theta_vals = np.array (theta.get_values ()) last_theta_vals = np.array (last_theta.get_values ()) assert all (theta_vals == last_theta_vals)
def test_append (self): """ Tests if one can append a parameter to the list. """ p = RandomParameter ('', Gamma (2, 2)) theta = RandomParameterList () theta.append (p) theta.append (p) theta.append (p) self.assertEqual (theta.get_size (), 3)
def test_get_experimental_error (self): """ Tests if we can have an experimental error on the list of random parameters. """ p1 = RandomParameter ('p1', Gamma (2, 2)) p2 = RandomParameter ('p2', Gamma (3, 2)) p1.value = 1 p2.value = 2 sigma = RandomParameter ('sigma', Gamma (2, .1)) sigma.value = 123 theta = RandomParameterList () theta.append (p1) theta.set_experimental_error (sigma) theta.append (p2) self.assertEqual (theta.get_experimental_error (), 123)
def test_jumps_centered_on_current_theta (self): """ Tests if, when using suitable jump distribution, the proposed values are centered on the current theta. """ n = 10 N = 1000 theta_values = np.ones (n) / 3.2 theta = RandomParameterList () for p_val in theta_values: gamma = Gamma (2, 1) rand_par = RandomParameter ('p', gamma) rand_par.value = p_val theta.append (rand_par) mocked_mh = MHJumpMock (theta) mean_jump = np.zeros (n) for i in range (N): jump = mocked_mh.propose_jump (theta) mean_jump += jump.get_values () mean_jump /= N assert all (abs (mean_jump - theta_values) < 1e-1)
def test_sample_start (self): """ Tests if the start sample is centered on the mean of the prior distribution. """ n = 10 N = 1000 theta = RandomParameterList () for i in range (n): gamma = Gamma (2, 0.15) rand_par = RandomParameter ('p', gamma) theta.append (rand_par) start_mean = np.zeros (n) analytical_mean = np.ones (n) * 0.3 for i in range (N): mocked_mh = MHLikelihoodMock (theta) mocked_mh.start_sample_from_prior () sample = mocked_mh.get_last_sampled (1)[0] t = sample[0] start_mean += t.get_values () start_mean /= N assert all (abs (start_mean - analytical_mean) < 1e-1)
def create_starting_sample (self): my_artificial_sample = [] log_likelihoods = [] sample_mean = [0.05, 0.1, 0.2, .3] S = np.eye (4) / 5 mu = np.log (np.array (sample_mean)) - S.diagonal () / 2 my_sample_dist = MultivariateLognormal (mu, S) for i in range (50): theta = RandomParameterList () values = my_sample_dist.rvs () for v in values[:-1]: p = RandomParameter ('p', Gamma (2, 2)) p.value = v theta.append (p) exp_error = RandomParameter ('sigma', Gamma (2, 2)) theta.set_experimental_error (exp_error) log_likelihoods.append (1) my_artificial_sample.append (theta) return (my_artificial_sample, log_likelihoods)
def test_get_iterator (self): """ Tests if we can get an iterator of the object. """ p1 = RandomParameter ('p1', Gamma (2, 2)) p2 = RandomParameter ('p2', Gamma (3, 2)) sigma = RandomParameter ('sigma', Gamma (2, .1)) p1.value = 1 p2.value = 2 sigma.value = 123 theta = RandomParameterList () theta.append (p1) theta.append (p2) theta.set_experimental_error (sigma) my_iterator = iter (theta) it_1 = next (my_iterator) assert (it_1.name == 'p1') it_2 = next (my_iterator) assert (it_2.name == 'p2') it_3 = next (my_iterator) assert (it_3.name == 'sigma')
def define_sbml_params_priors(sbml, filename): """ Defined the prior distribution for all reaction parameters of an SBML model. Parameters sbml: an SBML object, with the model of interest. filename: a file path that contains the definition of all model parameters priors. Returns a RandomParameterList object that has the prior definition of all parameters of the SBML object, in the same order as they are seen on SBML.get_all_param (). """ default_priors = read_priors_file(filename) priors = RandomParameterList() original_names = [] for param in sbml.get_all_param(): original_name = sbml.get_original_param_name(param) original_names.append(original_name) param_prior = None for prior_p in default_priors.get_model_parameters(): if original_name == prior_p.name: param_prior = prior_p.copy() param_prior.name = param break if param_prior == None: raise ValueError ("Could not find a prior for " + \ original_name + " in priors defined in " + filename) priors.append(param_prior) for prior in default_priors.get_model_parameters(): if prior.name not in original_names: warnings.warn ("Prior of " + prior.name + " do not " + \ "correspond to any of the model parameters.") sigma_p = default_priors.get_experimental_error_distribution() priors.set_experimental_error(sigma_p) return priors
def read_priors_file(filename): """ Reads a priors definition file. Parameters filename: the path of the priors file. Returns a RandomParameterList object, containing all defined parameters and its prior distributions and also some experimental error. """ tree = etree.parse(filename) root = tree.getroot() if clean_tag(root) != "priors": print("Wrong experiment data syntax. Root tag should be " + "<dataset>") return None priors = RandomParameterList() for children in root.getchildren(): attribs = children.attrib if clean_tag(children) == "prior": name = attribs["name"] a = float(attribs["a"]) b = float(attribs["b"]) dist_type = attribs["distribution"] dist = __create_distribution(dist_type, [a, b]) priors.append(RandomParameter(name, dist)) elif clean_tag(children) == "experimental_error": name = attribs["name"] a = float(attribs["a"]) b = float(attribs["b"]) gamma = Gamma(a, b) priors.set_experimental_error(RandomParameter(name, gamma)) else: print("Warning: unindentified prior definition on " + filename) return priors
def test_samples_target (self): """ With a controlled target distribution, tests if the MH successfully generates a sample from the target. """ n = 10 N = 5000 theta = RandomParameterList () for i in range (n): gamma = Gamma (1, 1) p = RandomParameter ('p', gamma) theta.append (p) class MHMultivariateLognormalTargetMock (MetropolisHastings): def __init__ (self, theta): super ().__init__ (theta, verbose=False) n = theta.get_size () mu = np.ones (n) Sigma = np.eye (n) / 10 self.target_distribution = MultivariateLognormal (mu, Sigma) def _calc_log_likelihood (self, t): t_values = t.get_values () l = self.target_distribution.pdf (t_values) return np.log (l) def _create_jump_dist (self, theta_t): n = theta_t.get_size () S = np.eye (n) / 100 variances = S.diagonal () theta_values = np.array (theta_t.get_values ()) mu = np.log (theta_values) - variances / 2 return MultivariateLognormal (mu, S) def _calc_mh_ratio (self, new_t, new_l, old_t, old_l): J_gv_new = self._create_jump_dist (new_t) J_gv_old = self._create_jump_dist (old_t) p_old_gv_new = J_gv_new.pdf (old_t.get_values ()) p_new_gv_old = J_gv_old.pdf (new_t.get_values ()) l_ratio = np.exp (new_l - old_l) r = (l_ratio) * (p_old_gv_new / p_new_gv_old) return r mocked_mh = MHMultivariateLognormalTargetMock (theta) mocked_mh.start_sample_from_prior () mocked_mh.get_sample (N)[0] # let's throw away the first 10% of samples sample = mocked_mh.get_last_sampled (int (N * .9))[0] mu = np.ones (n) S = np.eye (n) / 10 analytic_mean = np.exp (mu + S.diagonal () / 2) sample_mean = np.zeros (n) for t in sample: sample_mean += t.get_values () sample_mean /= len (sample) diff = analytic_mean - sample_mean diff_norm2 = np.sqrt (diff.dot (diff)) assert (diff_norm2 < 1)
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)