def test_models_with_different_species_are_unequal(self): """ Given models that differ by species names only, they should not be equal """ model_a = Model(species=['a', 'b'], parameters=['x', 'y'], stoichiometry_matrix=[[2, 3], [15, -1]], propensities=['a+b+x+y', 'a-b+x-y']) model_b = Model(species=['c', 'd'], parameters=['x', 'y'], stoichiometry_matrix=[[2, 3], [15, -1]], propensities=['c+d+x+y', 'c-d+x-y']) model_c = Model(species=['c', 'b'], parameters=['x', 'y'], stoichiometry_matrix=[[2, 3], [15, -1]], propensities=['c+b+x+y', 'c-b+x-y']) self.assertNotEqual(model_a, model_b) self.assertNotEqual(model_a, model_c) self.assertNotEqual(model_b, model_c) # Compare hashes as well self.assertNotEqual(hash(model_a), hash(model_b)) self.assertNotEqual(hash(model_a), hash(model_c)) self.assertNotEqual(hash(model_b), hash(model_c))
def test_initialisation_of_propensities_as_list_of_sympy_formulae(self): """ The model constructor should accept propensities as list of strings e.g. map(sympy.sympify, ['y_0+y_1', 'y_1+y_2']) and return them as sympy (column) Matrix of equations i.e. sympy.Matrix(['y_0+y_1', 'y_1+y_2']) """ answer = sympy.Matrix([['c_0*y_0*(y_0 + y_1 - 181)'], ['c_1*(-y_0 - y_1 + 301)'], ['c_2*(-y_0 - y_1 + 301)']]) # List m = Model( self.SAMPLE_VARIABLES, self.SAMPLE_CONSTANTS, map(sympy.sympify, [ 'c_0*y_0*(y_0 + y_1 - 181)', 'c_1*(-y_0 - y_1 + 301)', 'c_2*(-y_0 - y_1 + 301)' ]), self.SAMPLE_STOICHIOMETRY_MATRIX) self.assertEqual(m.propensities, answer) # Double list m = Model(self.SAMPLE_VARIABLES, self.SAMPLE_CONSTANTS, [ map(sympy.sympify, [ 'c_0*y_0*(y_0 + y_1 - 181)', 'c_1*(-y_0 - y_1 + 301)', 'c_2*(-y_0 - y_1 + 301)' ]) ], self.SAMPLE_STOICHIOMETRY_MATRIX) self.assertEqual(m.propensities, answer)
def test_initialisation_of_propensities_as_matrix(self): """ The model constructor should accept propensities as a sympy matrix e.g. sympy.Matrix(['y_0+y_1', 'y_1+y_2']) and return them as sympy (column) Matrix of equations i.e. sympy.Matrix(['y_0+y_1', 'y_1+y_2']) """ answer = to_sympy_matrix([['c_0*y_0*(y_0 + y_1 - 181)'], ['c_1*(-y_0 - y_1 + 301)'], ['c_2*(-y_0 - y_1 + 301)']]) # Column m = Model( self.SAMPLE_VARIABLES, self.SAMPLE_CONSTANTS, to_sympy_matrix([ 'c_0*y_0*(y_0 + y_1 - 181)', 'c_1*(-y_0 - y_1 + 301)', 'c_2*(-y_0 - y_1 + 301)' ]), self.SAMPLE_STOICHIOMETRY_MATRIX) self.assertEqual(m.propensities, answer) # Row matrix m = Model(self.SAMPLE_VARIABLES, self.SAMPLE_CONSTANTS, [[ 'c_0*y_0*(y_0 + y_1 - 181)', 'c_1*(-y_0 - y_1 + 301)', 'c_2*(-y_0 - y_1 + 301)' ]], self.SAMPLE_STOICHIOMETRY_MATRIX) self.assertEqual(m.propensities, answer)
def test_identical_models_have_equal_hash(self): """ Given two identical models, they should have the same hash """ model_a = Model(species=['a', 'b'], parameters=['x', 'y'], stoichiometry_matrix=[[2, 3], [15, -1]], propensities=['a+b+x+y', 'a-b+x-y']) model_b = Model(species=['a', 'b'], parameters=['x', 'y'], stoichiometry_matrix=[[2, 3], [15, -1]], propensities=['a+b+x+y', 'a-b+x-y']) self.assertEqual(hash(model_a), hash(model_b))
def test_models_with_different_constants_are_unequal(self): """ Given two models, that differ by their constants only, they should return False on == comparison. """ model_a = Model(species=['a', 'b'], parameters=['x', 'y'], stoichiometry_matrix=[[2, 3], [15, -1]], propensities=['a+b+x+y', 'a-b+x-y']) model_b = Model(species=['a', 'b'], parameters=['z', 'q'], stoichiometry_matrix=[[2, 3], [15, -1]], propensities=['a+b+z+q', 'a-b+z-q']) self.assertNotEqual(model_a, model_b) self.assertNotEqual(hash(model_a), hash(model_b))
def test_equal_models_are_equal(self): """ Given two equal models, they should return true on == comparison. """ model_a = Model(species=['a', 'b'], parameters=['x', 'y'], stoichiometry_matrix=[[2, 3], [15, -1]], propensities=['a+b+x+y', 'a-b+x-y']) model_b = Model(species=['a', 'b'], parameters=['x', 'y'], stoichiometry_matrix=[[2, 3], [15, -1]], propensities=['a+b+x+y', 'a-b+x-y']) self.assertEqual(model_a, model_b)
def test_models_with_different_stoichiometry_matrices_are_unequal(self): """ Given two models that differ only by stoichiometry_matrices, they should be returned as unequal. """ model_a = Model(species=['a', 'b'], parameters=['x', 'y'], stoichiometry_matrix=[[2, 3], [15, -1]], propensities=['a+b+x+y', 'a-b+x-y']) model_b = Model(species=['a', 'b'], parameters=['x', 'y'], stoichiometry_matrix=[[1, 2], [3, -4]], propensities=['a+b+x+y', 'a-b+x-y']) self.assertNotEqual(model_a, model_b) self.assertNotEqual(hash(model_a), hash(model_b))
def test_initialisation_of_variables_as_list_of_sympy_matrix(self): """ The model constructor should accept variables as sympy.Matrix i.e. sympy.Matrix(['y_0', 'y_1']) It should return them as sympy.symbols(['y_0', 'y_1']) :return: """ # Column m = Model(sympy.Matrix(['y_0', 'y_1']), self.SAMPLE_CONSTANTS, self.SAMPLE_PROPENSITIES, self.SAMPLE_STOICHIOMETRY_MATRIX) self.assertEqual(m.species, sympy.symbols(['y_0', 'y_1'])) # Row m = Model(sympy.Matrix([['y_0', 'y_1']]), self.SAMPLE_CONSTANTS, self.SAMPLE_PROPENSITIES, self.SAMPLE_STOICHIOMETRY_MATRIX) self.assertEqual(m.species, sympy.symbols(['y_0', 'y_1']))
def test_initialisation_of_constants_as_list_of_sympy_matrix(self): """ The model constructor should accept constants as sympy.Matrix i.e. sympy.Matrix(['c_0', 'c_1', 'c_2']) It should return them as sympy.symbols(['c_0', 'c_1', 'c_2']) :return: """ # Column m = Model(self.SAMPLE_VARIABLES, sympy.Matrix(['c_0', 'c_1', 'c_2']), self.SAMPLE_PROPENSITIES, self.SAMPLE_STOICHIOMETRY_MATRIX) self.assertEqual(m.parameters, sympy.symbols(['c_0', 'c_1', 'c_2'])) # Row m = Model(self.SAMPLE_VARIABLES, sympy.Matrix([['c_0', 'c_1', 'c_2']]), self.SAMPLE_PROPENSITIES, self.SAMPLE_STOICHIOMETRY_MATRIX) self.assertEqual(m.parameters, sympy.symbols(['c_0', 'c_1', 'c_2']))
def test_models_with_equivalent_propensities_are_equal(self): """ Given two equal models, that have different, but equivalent propensities, the == comparison should return true """ model_a = Model(species=['a', 'b'], parameters=['x', 'y'], stoichiometry_matrix=[[2, 3], [15, -1]], propensities=['a+b+x+y', 'a-b+x-y']) model_b = Model( species=['a', 'b'], parameters=['x', 'y'], stoichiometry_matrix=[[2, 3], [15, -1]], propensities=['a+b+x+y', 'a-b+x-y +2*x +x - (1/3) * x * 9']) self.assertEqual(model_a, model_b)
def test_transcription_model(self): #use simple production and degradation of mRNA and protein for testing # mRNA production rate is k1, degradation rate is g1 # protein production rate is k2, degradation rate is g2 stoichiometry_matrix = sympy.Matrix([[1, -1, 0, 0], [0, 0, 1, -1]]) propensities = to_sympy_matrix(['k1', 'g1*x', 'k2*x', 'g2*y']) species = to_sympy_matrix(['x', 'y']) correct_rhs = to_sympy_matrix( ["k1 - g1 * x", "k2 * x - g2 * y", "k1 + g1 * x - 2 * g1 * V_0_0", "k2 * V_0_0 - (g1 + g2) * V_0_1", "k2 * x + g2 * y + k2 * V_0_1 + k2 * V_0_1 - 2 * g2 * V_1_1"]) correct_lhs = to_sympy_matrix(['x','y','V_0_0', 'V_0_1', 'V_1_1']) constants = ["k1","k2","g1","g2"] model = Model(species, constants, propensities, stoichiometry_matrix) lna = LinearNoiseApproximation(model) problem = lna.run() answer_rhs = problem.right_hand_side answer_lhs = problem.left_hand_side assert_sympy_expressions_equal(correct_rhs, answer_rhs) self.assertEqual(correct_lhs, answer_lhs)
def test_initialisation_of_variables_as_list_of_strings(self): """ The model constructor should accept variables as a list of strings, i.e. ['y_0', 'y_1'] It should return them as sympy.symbols(['y_0', 'y_1']) :return: """ m = Model(['y_0', 'y_1'], self.SAMPLE_CONSTANTS, self.SAMPLE_PROPENSITIES, self.SAMPLE_STOICHIOMETRY_MATRIX) self.assertEqual(m.species, sympy.symbols(['y_0', 'y_1']))
def test_initialisation_of_constants_as_list_of_strings(self): """ The model constructor should accept constants as a list of strings, i.e. ['c_0', 'c_1', 'c_2'] It should return them as sympy.symbols(['c_0', 'c_1', 'c_2']) :return: """ m = Model(self.SAMPLE_VARIABLES, ['c_0', 'c_1', 'c_2'], self.SAMPLE_PROPENSITIES, self.SAMPLE_STOICHIOMETRY_MATRIX) self.assertEqual(m.parameters, sympy.symbols(['c_0', 'c_1', 'c_2']))
def test_initialisation_of_stoichiometry_matrix_as_list(self): """ The model constructor should accept stoichiometry_matrix as list e.g. [[-1, 1, 0], [0, 0, 1]] and return them as sympy Matrix e.g. sympy.Matrix([[-1, 1, 0], [0, 0, 1]]) """ answer = sympy.Matrix([[-1, 1, 0], [0, 0, 1]]) # List m = Model(self.SAMPLE_VARIABLES, self.SAMPLE_CONSTANTS, self.SAMPLE_PROPENSITIES, [[-1, 1, 0], [0, 0, 1]]) self.assertEqual(m.stoichiometry_matrix, answer)
def test_initialisation_of_stoichiometry_matrix_as_numpy_array(self): """ The model constructor should accept stoichiometry_matrix as a numpy matrix e.g. np.array(['y_0+y_1', 'y_1+y_2']) and return them as sympy Matrix e.g. sympy.Matrix([[-1, 1, 0], [0, 0, 1]]) """ answer = sympy.Matrix([[-1, 1, 0], [0, 0, 1]]) # Column m = Model(self.SAMPLE_VARIABLES, self.SAMPLE_CONSTANTS, self.SAMPLE_PROPENSITIES, sympy.Matrix([[-1, 1, 0], [0, 0, 1]])) assert_sympy_expressions_equal(m.stoichiometry_matrix, answer)
def read_sbml(filename): """ Read the model from a SBML file. :param filename: SBML filename to read the model from :return: A tuple, consisting of :class:`~means.core.model.Model` instance, set of parameter values, and set of initial conditions variables. """ import libsbml if not os.path.exists(filename): raise IOError('File {0!r} does not exist'.format(filename)) reader = libsbml.SBMLReader() document = reader.readSBML(filename) sbml_model = document.getModel() if not sbml_model: raise ValueError('Cannot parse SBML model from {0!r}'.format(filename)) species = sympy.symbols([s.getId() for s in sbml_model.getListOfSpecies()]) initial_conditions = [ s.getInitialConcentration() for s in sbml_model.getListOfSpecies() ] compartments = sympy.symbols( [s.getId() for s in sbml_model.getListOfCompartments()]) compartment_sizes = [ s.getSize() for s in sbml_model.getListOfCompartments() ] reactions = map(_parse_reaction, sbml_model.getListOfReactions()) # getListOfParameters is an attribute of the model for SBML Level 1&2 parameters_with_values = [(sympy.Symbol(p.getId()), p.getValue()) for p in sbml_model.getListOfParameters()] parameter_values = dict(parameters_with_values) parameters = map(lambda x: x[0], parameters_with_values) if not parameters: track_local_parameters = True parameters = set() parameter_values = {} else: track_local_parameters = False stoichiometry_matrix = np.zeros((len(species), len(reactions)), dtype=int) propensities = [] for reaction_index, reaction in enumerate(reactions): if track_local_parameters: for param, value in reaction.parameters: parameters.add(param) parameter_values[param] = value reactants = reaction.reactants products = reaction.products propensities.append(reaction.propensity) for species_index, species_id in enumerate(species): net_stoichiometry = products.get(species_id, 0) - reactants.get( species_id, 0) stoichiometry_matrix[species_index, reaction_index] = net_stoichiometry if track_local_parameters: # sympy does not allow sorting its parameter lists by default, # explicitly tell to sort by str representation sorted_parameters = sorted(parameters, key=str) else: sorted_parameters = parameters parameter_values_list = [parameter_values[p] for p in sorted_parameters] # We need to concatenate compartment names and parameters as in our framework we cannot differentiate the two compartments_and_parameters = compartments + sorted_parameters parameter_values_list = compartment_sizes + parameter_values_list model = Model(species, compartments_and_parameters, propensities, stoichiometry_matrix) return model, parameter_values_list, initial_conditions