From 6298eaf369c2761ca5f651747f31f5dd15262579 Mon Sep 17 00:00:00 2001 From: seanebum Date: Fri, 18 Feb 2022 10:31:22 -0500 Subject: [PATCH 1/3] added unit test for hybrid solvers based on multifiring event notebook --- test/example_models.py | 47 +++++++++++++++++++++++++++++++++++++- test/test_hybrid_solver.py | 15 ++++++++++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/test/example_models.py b/test/example_models.py index 1ca2349a2..1711f0dd3 100644 --- a/test/example_models.py +++ b/test/example_models.py @@ -98,7 +98,7 @@ def __init__(self, parameter_values=None): class Dimerization(Model): def __init__(self, parameter_values=None): - # First call the gillespy2.Model initializer. + # First call the Model initializer. Model.__init__(self, name="Dimerization") # Define parameters for the rates of creation and dissociation. @@ -525,6 +525,51 @@ def __init__(self, parameter_values=None): # Timespan self.timespan(np.arange(0, 20, 0.05)) +class MultiFiringEvent(Model): + """ + This is a simple example for mass-action degradation of species S. We will add two events + to demonstrate the usage of events. The first event will assign the value '0' to our species + once time passes 20, and the second event will be triggered once time crosses 30, assigning + a value of "100" to our species and changing the value of our degradation rate parameter + "k1" from .01 to .1, causing the species to decay more quickly. + """ + + def __init__(self, parameter_values=None): + + # Initialize the model. + Model.__init__(self, name="Example") + + # Species + S = Species(name='Sp', initial_value=100, mode='discrete') +# ev_time1 = Species(name='ev_time1', initial_value=20) +# ev_time2 = Species(name='ev_time2', initial_value=30) + self.add_species([S]) + + # Parameters + k1 = Parameter(name='k1', expression=0.01) + ev_time1 = Parameter(name='ev_time1', expression=20) + ev_time2 = Parameter(name='ev_time2', expression=30) + self.add_parameter([k1, ev_time1, ev_time2]) + + # Events + et = EventTrigger(expression='t>ev_time1') + ea = EventAssignment(variable=S, expression='0') + ea1 = EventAssignment(variable=ev_time1, expression='ev_time1+15') + e = Event(name='event1', trigger=et, assignments=[ea, ea1]) + + et2 = EventTrigger(expression='t>ev_time2', persistent=True) + ea2 = EventAssignment(variable=S, expression='100') + ea3 = EventAssignment(variable=k1, expression='.1') + ea4 = EventAssignment(variable=ev_time2, expression='ev_time2+15') + e2 = Event(name='event2', trigger=et2, assignments=[ea2, ea3, ea4]) + self.add_event([e, e2]) + + #Reactions + r = Reaction(name='R', reactants={S:1}, products={}, rate=k1) #Multiple reactions + self.add_reaction([r]) + + self.timespan(np.linspace(0, 60, 175)) + __all__ = ['Trichloroethylene', 'LacOperon', 'Schlogl', 'MichaelisMenten', 'ToggleSwitch', 'Example', 'Tyson2StateOscillator', 'Oregonator', 'VilarOscillator', 'Dimerization', 'RobustModel'] diff --git a/test/test_hybrid_solver.py b/test/test_hybrid_solver.py index 2248cd3b1..75c7c143c 100644 --- a/test/test_hybrid_solver.py +++ b/test/test_hybrid_solver.py @@ -15,12 +15,11 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ - import unittest import numpy as np import gillespy2 from gillespy2.core.gillespyError import * -from example_models import Example, ExampleNoTspan +from example_models import Example, ExampleNoTspan, MultiFiringEvent from gillespy2 import TauHybridSolver @@ -238,6 +237,18 @@ def test_continuous_state_values(self): self.assertGreater(result["S1"][-1], 0.0, "Reaction never fired; indicates that continuous species is being truncated") + def test_multi_firing_event(self): + model = MultiFiringEvent() + for solver in self.solvers: + with self.subTest(solver=solver.name): + res = model.run(solver=solver, seed=1) + self.assertNotEqual(res['Sp'][15], 0) + self.assertEqual(res['Sp'][25], 0) + self.assertNotEqual(res['Sp'][32], 0) + self.assertEqual(res['Sp'][40], 0) + self.assertNotEqual(res['Sp'][48], 0) + self.assertEqual(res['Sp'][55], 0) + self.assertEqual(res['Sp'][60],100) if __name__ == '__main__': unittest.main() From 2df511c441dfdb76f1e203304b57b92180c6b88e Mon Sep 17 00:00:00 2001 From: seanebum Date: Fri, 18 Feb 2022 12:07:14 -0500 Subject: [PATCH 2/3] realigned asserts to fall within subtests --- test/test_hybrid_solver.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/test_hybrid_solver.py b/test/test_hybrid_solver.py index 75c7c143c..4308d3db1 100644 --- a/test/test_hybrid_solver.py +++ b/test/test_hybrid_solver.py @@ -242,13 +242,13 @@ def test_multi_firing_event(self): for solver in self.solvers: with self.subTest(solver=solver.name): res = model.run(solver=solver, seed=1) - self.assertNotEqual(res['Sp'][15], 0) - self.assertEqual(res['Sp'][25], 0) - self.assertNotEqual(res['Sp'][32], 0) - self.assertEqual(res['Sp'][40], 0) - self.assertNotEqual(res['Sp'][48], 0) - self.assertEqual(res['Sp'][55], 0) - self.assertEqual(res['Sp'][60],100) + self.assertNotEqual(res['Sp'][15], 0) + self.assertEqual(res['Sp'][25], 0) + self.assertNotEqual(res['Sp'][32], 0) + self.assertEqual(res['Sp'][40], 0) + self.assertNotEqual(res['Sp'][48], 0) + self.assertEqual(res['Sp'][55], 0) + self.assertEqual(res['Sp'][60],100) if __name__ == '__main__': unittest.main() From 19985051b07108719c6cbb195b4c8ae32ec13aa8 Mon Sep 17 00:00:00 2001 From: seanebum Date: Fri, 18 Feb 2022 12:21:48 -0500 Subject: [PATCH 3/3] fixed time indexing of unit test to match event points --- test/example_models.py | 2 +- test/test_hybrid_solver.py | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/test/example_models.py b/test/example_models.py index 1711f0dd3..bbcec04f5 100644 --- a/test/example_models.py +++ b/test/example_models.py @@ -568,7 +568,7 @@ def __init__(self, parameter_values=None): r = Reaction(name='R', reactants={S:1}, products={}, rate=k1) #Multiple reactions self.add_reaction([r]) - self.timespan(np.linspace(0, 60, 175)) + self.timespan(np.linspace(0, 60, 181)) __all__ = ['Trichloroethylene', 'LacOperon', 'Schlogl', 'MichaelisMenten', 'ToggleSwitch', 'Example', 'Tyson2StateOscillator', 'Oregonator', diff --git a/test/test_hybrid_solver.py b/test/test_hybrid_solver.py index 4308d3db1..c0d0c5fc2 100644 --- a/test/test_hybrid_solver.py +++ b/test/test_hybrid_solver.py @@ -242,13 +242,12 @@ def test_multi_firing_event(self): for solver in self.solvers: with self.subTest(solver=solver.name): res = model.run(solver=solver, seed=1) - self.assertNotEqual(res['Sp'][15], 0) - self.assertEqual(res['Sp'][25], 0) - self.assertNotEqual(res['Sp'][32], 0) - self.assertEqual(res['Sp'][40], 0) - self.assertNotEqual(res['Sp'][48], 0) - self.assertEqual(res['Sp'][55], 0) - self.assertEqual(res['Sp'][60],100) + self.assertNotEqual(res['Sp'][45], 0) + self.assertEqual(res['Sp'][75], 0) + self.assertNotEqual(res['Sp'][96], 0) + self.assertEqual(res['Sp'][120], 0) + self.assertNotEqual(res['Sp'][144], 0) + self.assertEqual(res['Sp'][165], 0) if __name__ == '__main__': unittest.main()