Skip to content

Commit

Permalink
Merge pull request #395 from GillesPy2/develop
Browse files Browse the repository at this point in the history
Release 1.5.1
  • Loading branch information
seanebum authored Jul 7, 2020
2 parents 5cc9810 + 722636a commit 09428bb
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 79 deletions.
3 changes: 1 addition & 2 deletions gillespy2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
"""

import sys
if (sys.version_info < (3,0)):
if sys.version_info < (3, 0):
raise Exception("GillesPy2 only works in Python 3.0 and higher")
from .__version__ import __version__, __title__, __description__, __url__
from .__version__ import __author__, __email__
from .__version__ import __license__, __copyright__


from gillespy2.solvers import *
from gillespy2.core import *
import gillespy2.sbml
Expand Down
2 changes: 1 addition & 1 deletion gillespy2/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# @website https://github.com/GillesPy2/GillesPy2
# =============================================================================

__version__ = '1.5.0'
__version__ = '1.5.1'
__title__ = 'GillesPy2'
__description__ = 'Python interface for Gillespie-style biochemical simulations'
__url__ = 'https://github.com/GillesPy2/GillesPy2'
Expand Down
31 changes: 22 additions & 9 deletions gillespy2/core/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ def get_element(self, ename):
return 'Element not found!'


def get_best_solver(self, precompile=True):
def get_best_solver(self, cpp_test = True):
"""
Finds best solver for the users simulation. Currently, AssignmentRules, RateRules, FunctionDefinitions,
Events, and Species with a dynamic, or continuous population must use the TauHybridSolver.
Expand Down Expand Up @@ -732,14 +732,18 @@ def get_best_solver(self, precompile=True):
raise ModelError('TauHybridSolver is the only solver currently that supports '
'AssignmentRules, RateRules, FunctionDefinitions, or Events. '
'Please install Numpy.')
from gillespy2.solvers.utilities.solverutils import check_cpp_support
cpp_test = check_cpp_support()

if cpp_test is False and can_use_numpy and not hybrid_check:
from gillespy2 import NumPySSASolver
return NumPySSASolver

else:
if precompile:
from gillespy2.solvers.cpp.variable_ssa_c_solver import VariableSSACSolver
return VariableSSACSolver
from gillespy2.solvers.auto import SSASolver
return SSASolver
from gillespy2 import VariableSSACSolver
return VariableSSACSolver

def run(self, solver=None, timeout=0, t=None, show_labels=True, **solver_args):
def run(self, solver=None, timeout=0, t=None, show_labels=True, cpp_support=False, **solver_args):
"""
Function calling simulation of the model. There are a number of
parameters to be set here.
Expand Down Expand Up @@ -768,16 +772,25 @@ def run(self, solver=None, timeout=0, t=None, show_labels=True, **solver_args):

if not show_labels:
from gillespy2.core import log
log.warning('show_labels = False is deprecated. Future releases of GillesPy2 may not support this feature.')

log.warning('show_labels = False is deprecated. Future releases '
'of GillesPy2 may not support this feature.')
if t is None:
t = self.tspan[-1]

if solver is None:
solver = self.get_best_solver()

try:
solver_results, rc = solver.run(model=self, t=t, increment=self.tspan[-1] - self.tspan[-2],
timeout=timeout, **solver_args)
except Exception as e:
if cpp_support is False:
if not isinstance(solver, str):
if solver.name == 'SSACSolver' or solver.name == 'VariableSSACSolver':
from gillespy2.core import log
log.warning("Please install/configure 'g++' and 'make' on your"
" system, to ensure that GillesPy2 C solvers will"
" run properly.")
raise SimulationError(
"argument 'solver={}' to run() failed. Reason Given: {}".format(solver, e))

Expand Down
9 changes: 7 additions & 2 deletions gillespy2/solvers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from gillespy2.core.gillespyError import ExecutionError
from .cpp import *
from .numpy import *

__all__ = cpp.__all__ + numpy.__all__

__all__ = ["SSACSolver", "VariableSSACSolver", "NumPySSASolver", "ODESolver", "TauHybridSolver", "TauLeapingSolver"]

if not __all__:
raise ExecutionError("Your computer does not contain the minimum require"
"ments for running simulations using GillesPy2."
" Please install NumPy, or configure the C++ 'g++' "
"compiler on your machine.")
2 changes: 0 additions & 2 deletions gillespy2/solvers/auto/__init__.py

This file was deleted.

32 changes: 0 additions & 32 deletions gillespy2/solvers/auto/ssa_solver.py

This file was deleted.

15 changes: 1 addition & 14 deletions gillespy2/solvers/cpp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,5 @@
from gillespy2.solvers.cpp.variable_ssa_c_solver import VariableSSACSolver
from gillespy2.core import log

def check_cpp_support():
from gillespy2.solvers.cpp.example_models import Example
try:
model = Example()
results = model.run(solver=SSACSolver)
return True
except Exception as e:
log.warn('Unable to use C++ optimized SSA: {0}. The performance of ' \
'this package can be significantly increased if you install/configure GCC on ' \
'this machine.'.format(e))
return False

can_use_cpp = check_cpp_support()

__all__ = ['SSACSolver','VariableSSACSolver'] if can_use_cpp else []
__all__ = ['SSACSolver', 'VariableSSACSolver']
23 changes: 15 additions & 8 deletions gillespy2/solvers/numpy/ssa_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ def run(self, model, t=20, number_of_trajectories=1, increment=0.05, seed=None,

if timeout is not None and timeout <= 0:
timeout = None

if len(kwargs) > 0:
for key in kwargs:
log.warning('Unsupported keyword argument to {0} solver: {1}'.format(self.name, key))
Expand All @@ -77,13 +76,14 @@ def run(self, model, t=20, number_of_trajectories=1, increment=0.05, seed=None,

# curr_time and curr_state are list of len 1 so that __run receives reference
if resume is not None:
curr_time = [resume['time'][-1]]
total_time = [resume['time'][-1]]
else:
curr_time = [0]
total_time = [0]

curr_state = [None]
live_grapher = [None]

sim_thread = Thread(target=self.___run, args=(model, curr_state, curr_time, timeline, trajectory_base,
sim_thread = Thread(target=self.___run, args=(model, curr_state, total_time, timeline, trajectory_base,
live_grapher,), kwargs={'t': t, 'number_of_trajectories':
number_of_trajectories,
'increment': increment,
Expand All @@ -105,7 +105,7 @@ def run(self, model, t=20, number_of_trajectories=1, increment=0.05, seed=None,
live_output_options,resume = resumeTest)
display_timer = gillespy2.core.liveGraphing.RepeatTimer(live_output_options['interval'],
live_grapher[0].display, args=(curr_state,
curr_time,
total_time,
trajectory_base,)
)
display_timer.start()
Expand All @@ -126,19 +126,19 @@ def run(self, model, t=20, number_of_trajectories=1, increment=0.05, seed=None,

return self.result, self.rc

def ___run(self, model, curr_state, curr_time, timeline, trajectory_base, live_grapher, t=20,
def ___run(self, model, curr_state, total_time, timeline, trajectory_base, live_grapher, t=20,
number_of_trajectories=1, increment=0.05, seed=None, debug=False, show_labels=True, resume=None,
timeout=None):

try:
self.__run(model, curr_state, curr_time, timeline, trajectory_base, live_grapher, t, number_of_trajectories,
self.__run(model, curr_state, total_time, timeline, trajectory_base, live_grapher, t, number_of_trajectories,
increment, seed, debug, show_labels, resume, timeout)
except Exception as e:
self.has_raised_exception = e
self.result = []
return [], -1

def __run(self, model, curr_state, curr_time, timeline, trajectory_base, live_grapher, t=20,
def __run(self, model, curr_state, total_time, timeline, trajectory_base, live_grapher, t=20,
number_of_trajectories=1, increment=0.05, seed=None, debug=False, show_labels=True,
resume=None, timeout=None):

Expand Down Expand Up @@ -191,6 +191,7 @@ def __run(self, model, curr_state, curr_time, timeline, trajectory_base, live_gr
# begin simulating each trajectory
simulation_data = []
for trajectory_num in range(number_of_trajectories):
total_time[0] = 0
if self.stop_event.is_set():
self.rc = 33
break
Expand All @@ -206,6 +207,11 @@ def __run(self, model, curr_state, curr_time, timeline, trajectory_base, live_gr
trajectory = trajectory_base[trajectory_num]
entry_count = 1
curr_state[0] = {}
# curr_time and curr_state are list of len 1 so that __run receives reference
if resume is not None:
curr_time = [resume['time'][-1]]
else:
curr_time = [0]

for spec in model.listOfSpecies:
if resume is not None:
Expand Down Expand Up @@ -242,6 +248,7 @@ def __run(self, model, curr_state, curr_time, timeline, trajectory_base, live_gr

cumulative_sum = random.uniform(0, propensity_sum)
curr_time[0] += -math.log(random.random()) / propensity_sum
total_time[0] += -math.log(random.random()) / propensity_sum
if debug:
print('cumulative sum: ', cumulative_sum)
print('entry count: ', entry_count)
Expand Down
21 changes: 12 additions & 9 deletions gillespy2/solvers/numpy/tau_leaping_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,17 +129,16 @@ def run(self, model, t=20, number_of_trajectories=1, increment=0.05, seed=None,
trajectory_base, tempSpecies = nputils.numpy_trajectory_base_initialization(model, number_of_trajectories,
timeline, species, resume=resume
)

# curr_time and curr_state are list of len 1 so that __run receives reference
if resume is not None:
curr_time = [resume['time'][-1]]
total_time = [resume['time'][-1]]
else:
curr_time = [0]
total_time = [0]

curr_state = [None]
live_grapher = [None]

sim_thread = Thread(target=self.___run, args=(model, curr_state, curr_time, timeline, trajectory_base,
sim_thread = Thread(target=self.___run, args=(model, curr_state, total_time, timeline, trajectory_base,
live_grapher,), kwargs={'t': t,
'number_of_trajectories':
number_of_trajectories,
Expand All @@ -161,7 +160,7 @@ def run(self, model, t=20, number_of_trajectories=1, increment=0.05, seed=None,
live_grapher[0] = liveGraphing.LiveDisplayer(model, timeline, number_of_trajectories,
live_output_options, resume=resumeTest)
display_timer = liveGraphing.RepeatTimer(live_output_options['interval'], live_grapher[0].display,
args=(curr_state, curr_time, trajectory_base,))
args=(curr_state, total_time, trajectory_base,))
display_timer.start()

sim_thread.join(timeout=timeout)
Expand All @@ -181,20 +180,20 @@ def run(self, model, t=20, number_of_trajectories=1, increment=0.05, seed=None,
raise self.has_raised_exception
return self.result, self.rc

def ___run(self, model, curr_state,curr_time, timeline, trajectory_base, live_grapher, t=20,
def ___run(self, model, curr_state,total_time, timeline, trajectory_base, live_grapher, t=20,
number_of_trajectories=1, increment=0.05, seed=None, debug=False, profile=False, show_labels=True,
timeout=None, resume=None, tau_tol=0.03, **kwargs):

try:
self.__run(model, curr_state, curr_time, timeline, trajectory_base, live_grapher, t, number_of_trajectories,
self.__run(model, curr_state, total_time, timeline, trajectory_base, live_grapher, t, number_of_trajectories,
increment, seed, debug, profile, timeout, resume, tau_tol, **kwargs)

except Exception as e:
self.has_raised_exception = e
self.result = []
return [], -1

def __run(self, model, curr_state, curr_time, timeline, trajectory_base, live_grapher, t=20,
def __run(self, model, curr_state, total_time, timeline, trajectory_base, live_grapher, t=20,
number_of_trajectories=1, increment=0.05, seed=None, debug=False, profile=False, timeout=None,
resume=None, tau_tol=0.03, **kwargs):

Expand Down Expand Up @@ -240,10 +239,13 @@ def __run(self, model, curr_state, curr_time, timeline, trajectory_base, live_gr
start_state = [0] * (len(model.listOfReactions) + len(model.listOfRateRules))
propensities = {}
curr_state[0] = {}

if resume is not None:
save_time = curr_time[0]
save_time = total_time[0]
curr_time = [save_time]
else:
save_time = 0
curr_time = [0]

curr_state[0]['vol'] = model.volume
data = { 'time': timeline}
Expand Down Expand Up @@ -345,6 +347,7 @@ def __run(self, model, curr_state, curr_time, timeline, trajectory_base, live_gr
start_state = prev_start_state.copy()
curr_state[0] = prev_curr_state.copy()
curr_time[0] = prev_curr_time
total_time[0] = prev_curr_time
tau_step = tau_step / 2
steps_rejected += 1
if debug:
Expand Down
16 changes: 16 additions & 0 deletions gillespy2/solvers/utilities/solverutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,5 +282,21 @@ def dependency_grapher(model, reactions):

return dependent_rxns

"""
Below is a utility that checks whether or not users can use C++ solvers.
"""

def check_cpp_support():
from gillespy2.solvers.cpp.example_models import Example
from gillespy2 import SSACSolver
try:
model = Example()
results = model.run(solver=SSACSolver, cpp_support=True)
return True
except Exception as e:
log.warn('Unable to use C++ optimized SSA: {0}. The performance of ' \
'this package can be significantly increased if you install/configure GCC on ' \
'this machine.'.format(e))
return False


0 comments on commit 09428bb

Please sign in to comment.