Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSACSolver simulates the telegraph model incorrectly #918

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<img src="https://raw.githubusercontent.com/StochSS/GillesPy2/develop/.graphics/gillespy2-logo.png">
</p>

GillesPy2 is a Python 3 package for stochastic simulation of biochemical systems. It offers an object-oriented approach for creating mathematical models of biological systems, as well as a variety of methods for performing time simulation of those models. The methods include the [Gillespie direct method (SSA)](https://en.wikipedia.org/wiki/Gillespie_algorithm), several variant stochastic simulation methods including [tau-Leaping](https://en.wikipedia.org/wiki/Tau-leaping), and numerical integration of ODEs. The solvers support a variety of user environments, with optimized code for C++, [Cython](https://cython.org), and [NumPy](https://numpy.org). GillesPy2 also supports [SBML](https://en.wikipedia.org/wiki/SBML).
GillesPy2 is a Python 3 package for stochastic simulation of biochemical systems. It offers an object-oriented approach for creating mathematical models of biological systems, as well as a variety of methods for performing time simulation of those models. The methods include the [Gillespie direct method (SSA)](https://en.wikipedia.org/wiki/Gillespie_algorithm), several variant stochastic simulation methods including [tau-Leaping](https://en.wikipedia.org/wiki/Tau-leaping), and numerical integration of ODEs. The solvers support a variety of user environments, with optimized code for C++, and [NumPy](https://numpy.org). GillesPy2 also supports [SBML](https://en.wikipedia.org/wiki/SBML).

<table><tr><td><b>
<img width="20%" align="right" src="https://raw.githubusercontent.com/StochSS/GillesPy2/develop/.graphics/stochss-logo.png">
Expand Down
12 changes: 11 additions & 1 deletion gillespy2/solvers/cpp/c_base/ssa_cpp_solver/SSASolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ namespace Gillespy
double cumulative_sum = rng() * propensity_sum / rng.max();
simulation->current_time += -log(rng() * 1.0 / rng.max()) / propensity_sum;

// Output timestep results
while (entry_count < simulation->number_timesteps && simulation->timeline[entry_count] <= simulation->current_time)
{
if (interrupted)
{
break;
}
simulation->output_buffer_range(std::cout, entry_count++);
}

// Fire reaction
for (unsigned int potential_reaction = 0; potential_reaction < ((simulation->model)->number_reactions); potential_reaction++)
{
cumulative_sum -= propensity_values[potential_reaction];
Expand Down Expand Up @@ -119,7 +130,6 @@ namespace Gillespy
{
break;
}

simulation->output_buffer_range(std::cout, entry_count++);
}
}
Expand Down
75 changes: 71 additions & 4 deletions test/example_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -634,9 +634,76 @@ def create_opioid():
return model


def create_telegraph_model():
"""Creates a stochastic model for the dichotomous Markov process OFF <-> ON"""

# Intialize the Model with a name of your choosing.
model = gillespy2.Model(name="on_off")

"""
Variables (GillesPy2.Species) can be anything that participates in or is produced by a reaction channel.

- name: A user defined name for the species.
- initial_value: A value/population count of species at start of simulation.
"""
ON = gillespy2.Species(name="ON", initial_value=0)
OFF = gillespy2.Species(name="OFF", initial_value=1)

# Add the Variables to the Model.
model.add_species([ON, OFF])

"""
Parameters are constant values relevant to the system, such as reaction kinetic rates.

- name: A user defined name for reference.
- expression: Some constant value.
"""
kon = gillespy2.Parameter(name="kon", expression=0.1)
koff = gillespy2.Parameter(name="koff", expression=1.0)

# Add the Parameters to the Model.
model.add_parameter([kon, koff])

"""
Reactions are the reaction channels which cause the system to change over time.

- name: A user defined name for the reaction.
- reactants: A dictionary with participant reactants as keys, and consumed per reaction as value.
- products: A dictionary with reaction products as keys, and number formed per reaction as value.
- rate: A parameter rate constant to be applied to the propensity of this reaction firing.
- propensity_function: Can be used instead of rate in order to declare a custom propensity function in string format.
"""
r1 = gillespy2.Reaction(
name="on",
reactants={'OFF': 1},
products= {'ON': 1},
rate='kon'
)

r2 = gillespy2.Reaction(
name="off",
reactants={'ON': 1},
products= {'OFF': 1},
rate='koff'
)


# Add the Reactions to the Model.
model.add_reaction([r1, r2])

# Define the timespan of the model.
tspan = gillespy2.TimeSpan.linspace(t=100, num_points=100)

# Set the timespan of the Model.
model.timespan(tspan)
return model



__all__ = [
'create_trichloroethylene', 'create_lac_operon', 'create_schlogl', 'create_michaelis_menten',
'create_decay', 'create_decay_no_tspan', 'create_tyson_2_state_oscillator', 'create_oregonator',
'create_vilar_oscillator', 'create_dimerization', 'create_degradation', 'create_robust_model',
'create_multi_firing_event', 'create_toggle_switch'
'create_trichloroethylene', 'create_lac_operon', 'create_schlogl',
'create_michaelis_menten', 'create_decay', 'create_decay_no_tspan',
'create_tyson_2_state_oscillator', 'create_oregonator', 'create_vilar_oscillator',
'create_dimerization', 'create_degradation', 'create_robust_model',
'create_multi_firing_event', 'create_toggle_switch','create_telegraph_model',
]
58 changes: 30 additions & 28 deletions test/run_integration_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,36 +61,38 @@
import test_hybrid_negative_state
import test_run_output
import test_hybrid_event_round
import test_telegraph_model

modules = [
test_empty_model,
test_build_engine,
test_c_solvers,
test_model,
test_ode_solver,
test_ode_c_solver,
test_tau_leaping_c_solver,
test_tau_leaping_solver,
test_tau_hybrid_c_solver,
test_hybrid_solver,
test_simple_model,
test_ssa_c_solver,
test_variable_solvers,
test_pause_resume,
test_SBML,
test_StochML,
test_example_models,
test_all_solvers,
test_sys_init,
test_results,
test_propensity_parser,
test_check_cpp_support,
test_jsonify,
test_notebooks,
test_c_decode,
test_run_output,
test_hybrid_negative_state,
test_hybrid_event_round,
# test_empty_model,
# test_build_engine,
# test_c_solvers,
# test_model,
# test_ode_solver,
# test_ode_c_solver,
# test_tau_leaping_c_solver,
# test_tau_leaping_solver,
# test_tau_hybrid_c_solver,
# test_hybrid_solver,
# test_simple_model,
# test_ssa_c_solver,
# test_variable_solvers,
# test_pause_resume,
# test_SBML,
# test_StochML,
# test_example_models,
# test_all_solvers,
# test_sys_init,
# test_results,
# test_propensity_parser,
# test_check_cpp_support,
# test_jsonify,
# test_notebooks,
# test_c_decode,
# test_run_output,
# test_hybrid_negative_state,
# test_hybrid_event_round,
test_telegraph_model,
]

for module in modules:
Expand Down
51 changes: 51 additions & 0 deletions test/test_telegraph_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# GillesPy2 is a modeling toolkit for biochemical simulation.
# Copyright (C) 2019-2022 GillesPy2 developers.

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import unittest
import gillespy2
from example_models import create_telegraph_model
from gillespy2.core import Model, Species, Reaction, Parameter
from gillespy2.core.gillespyError import *
import os
import numpy as np


class TestTelegraphModel(unittest.TestCase):

def test_telegraph_model(self):
model = create_telegraph_model()
solvers = [
gillespy2.solvers.CLESolver,
gillespy2.solvers.NumPySSASolver,
gillespy2.solvers.ODECSolver,
gillespy2.solvers.ODESolver,
gillespy2.solvers.SSACSolver,
gillespy2.solvers.TauHybridCSolver,
gillespy2.solvers.TauHybridSolver,
gillespy2.solvers.TauLeapingCSolver,
gillespy2.solvers.TauLeapingSolver,
]
for solver in solvers:
with self.subTest(solver=solver.name):
results = model.run(solver=solver)
a = np.sum(results['ON'])/len(results['ON'])
b = np.sum(results['OFF'])/len(results['OFF'])
self.assertTrue( a < b)



if __name__ == '__main__':
unittest.main()