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

Release v1.6.7 #660

Merged
merged 53 commits into from
Jan 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
4a3d8ff
Initial design for `Event` static methods
jtcooper10 Jul 31, 2021
4878386
Refactor C++ parameters to be vectorized
jtcooper10 Aug 4, 2021
afd9d97
Implement basic `Event` class in C++
jtcooper10 Aug 5, 2021
743a59c
Python-side template macros for events
jtcooper10 Aug 5, 2021
ed83291
Fix assignment ID templating
jtcooper10 Aug 5, 2021
7b9e7d2
Fix assignment ID templating
jtcooper10 Aug 5, 2021
3d678e6
Unfinished version of events for simulation loop
jtcooper10 Aug 6, 2021
a026adf
Queue for non-persistent events
jtcooper10 Aug 14, 2021
49113bb
Root-finder and updates to trigger pipeline
jtcooper10 Sep 9, 2021
1a56c10
Basic direct event trigger detection
jtcooper10 Oct 3, 2021
bcbe4d1
Basic event toggle functions for `Integrator`
jtcooper10 Nov 4, 2021
fb001d3
Trigger execution for root-finding
jtcooper10 Nov 17, 2021
ee31ca3
Bug fixes before merge
jtcooper10 Nov 18, 2021
bfe8890
Unit tests for events and bug fixes
jtcooper10 Nov 19, 2021
356aad0
Initial value templating
jtcooper10 Nov 20, 2021
7f290d8
Event trigger clean-up and initial values implementation
jtcooper10 Nov 20, 2021
bf4bdf2
Merge branch 'develop' into feature/cpp-hybrid-events
jtcooper10 Nov 20, 2021
d588e0c
Added missing numpy imports.
BryanRumsey Dec 2, 2021
29e4201
Added new example for live graphing and pause resume for c solvers.
BryanRumsey Dec 2, 2021
bd8a025
Changed version to v1.6.7
BryanRumsey Dec 2, 2021
fdd84a8
Merge pull request #658 from StochSS/live-output-example-csolvers
seanebum Dec 7, 2021
2b56cb1
Bug-fix: errant `continue`, mis-ordered initialization
jtcooper10 Dec 20, 2021
c84a9a4
Added blocks to resolve parameters at run time.
BryanRumsey Jan 5, 2022
ab62d2e
Added check for solver model. Added resolve parameter func call to O…
BryanRumsey Jan 6, 2022
2e4c3e5
Removed the model arg from GillesPySolver.get_increment. Switch the …
BryanRumsey Jan 6, 2022
510a095
Added check for solver model to CLE_solver. Added resolve parameter …
BryanRumsey Jan 6, 2022
6eb2ec9
Added check for solver model to NumPySSASolver. Added resolve parame…
BryanRumsey Jan 6, 2022
4a05abd
Added check for solver model to TauHybridSolver. Added resolve param…
BryanRumsey Jan 6, 2022
352bc26
Added check for solver model to TauLeapingSolver. Added resolve para…
BryanRumsey Jan 6, 2022
009b427
Added check for solver model to ODECSolver. Added resolve parameter …
BryanRumsey Jan 6, 2022
1825b8a
Added check for solver model to SSACSolver. Added resolve parameter …
BryanRumsey Jan 6, 2022
65cf2ca
Added check for solver model to SSACSolver. Added resolve parameter …
BryanRumsey Jan 6, 2022
9181d80
Added check for solver model to TauLeapingCSolver. Added resolve par…
BryanRumsey Jan 6, 2022
1f8196a
Fixed solver instantiation test.
BryanRumsey Jan 6, 2022
44fb39e
Added 'CSolver._set_model' helper method to fix failing test.
BryanRumsey Jan 6, 2022
572297e
Fixed loacl var ref issue.
BryanRumsey Jan 6, 2022
f9015fc
Merge branch 'develop' of github.com:StochSS/GillesPy2 into feature/c…
briandrawert Jan 7, 2022
6c77fa0
Added default names for Reactions, Rate Rules, Assignment Rules, Even…
BryanRumsey Jan 7, 2022
84f0afc
Added missing imports
BryanRumsey Jan 7, 2022
31d49af
Merge branch 'auto-gen-names' of github.com:StochSS/GillesPy2 into fe…
briandrawert Jan 7, 2022
6249b32
Merge pull request #594 from StochSS/feature/cpp-hybrid-events
briandrawert Jan 7, 2022
e633b01
Fixing hybrid continuous notebook
briandrawert Jan 7, 2022
b138187
Merge pull request #667 from StochSS/fixing_notebooks
briandrawert Jan 7, 2022
20e680c
Merge branch 'develop' into hotfix-resolve-params-at-run
briandrawert Jan 10, 2022
dbaedfb
Merge pull request #664 from StochSS/hotfix-resolve-params-at-run
seanebum Jan 10, 2022
468aab2
Removed events form the unsupported sbml features.
BryanRumsey Jan 10, 2022
08c0197
Fixing #668 ODECsolver not handling bimolecular reactions correctly
briandrawert Jan 10, 2022
7d2feee
unit test to show bug
briandrawert Jan 10, 2022
86d66cd
Fixes #675
briandrawert Jan 11, 2022
58fe061
tests do not fail locally, do on github
briandrawert Jan 11, 2022
5784c1c
Merge pull request #671 from StochSS/hybrid-c-sbml-feature
seanebum Jan 11, 2022
33153ae
Merge pull request #673 from StochSS/fix_668
BryanRumsey Jan 11, 2022
cfa3de3
Merge pull request #674 from StochSS/ode_solver_vol_issue
BryanRumsey Jan 11, 2022
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
28 changes: 12 additions & 16 deletions examples/AdvancedFeatures/hybrid_continuous_species.ipynb

Large diffs are not rendered by default.

265 changes: 265 additions & 0 deletions examples/DataVisualization/Live Output with C Solver.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion gillespy2/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
# =============================================================================


__version__ = '1.6.6'
__version__ = '1.6.7'

__title__ = 'GillesPy2'
__description__ = 'Python interface for Gillespie-style biochemical simulations'
Expand Down
7 changes: 6 additions & 1 deletion gillespy2/core/assignmentrule.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""

import uuid

from gillespy2.core.sortableobject import SortableObject
from gillespy2.core.jsonify import Jsonify

Expand All @@ -36,9 +38,12 @@ class AssignmentRule(SortableObject, Jsonify):
"""

def __init__(self, variable=None, formula=None, name=None):
if name in (None, ""):
self.name = f'ar{uuid.uuid4()}'.replace('-', '_')
else:
self.name = name
self.variable = variable
self.formula = formula
self.name = name

def __str__(self):
return self.variable + ': ' + self.formula
Expand Down
9 changes: 8 additions & 1 deletion gillespy2/core/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""

import uuid

from gillespy2.core.gillespyError import *
from gillespy2.core.jsonify import Jsonify

Expand All @@ -39,7 +41,12 @@ class EventAssignment(Jsonify):

"""

def __init__(self, variable=None, expression=None):
def __init__(self, name=None, variable=None, expression=None):

if name in (None, ""):
self.name = f'evn{uuid.uuid4()}'.replace('-', '_')
else:
self.name = name

self.variable = variable
self.expression = expression
Expand Down
7 changes: 6 additions & 1 deletion gillespy2/core/functiondefinition.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""

import uuid

from gillespy2.core.sortableobject import SortableObject
from gillespy2.core.jsonify import Jsonify

Expand All @@ -38,7 +40,10 @@ def __init__(self, name="", function=None, args=[]):
if function is None:
raise TypeError("Function string provided for FunctionDefinition cannot be None")

self.name = name
if name in (None, ""):
self.name = f'fd{uuid.uuid4()}'.replace('-', '_')
else:
self.name = name
self.function_string = function
self.args = args

Expand Down
9 changes: 3 additions & 6 deletions gillespy2/core/gillespySolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,16 @@ def get_solver_settings(self):

raise SimulationError("This abstract solver class cannot be used directly")

def get_increment(self, model, increment):
def get_increment(self, increment):
"""
Set the default increment value if it was not provided

:param model: The model on which the tspan can be found.
:type model: gillespy.Model

:param increment: The current value of increment.
:type increment: int
"""
if increment is None:
return model.tspan[-1] - model.tspan[-2]
if model.user_set_tspan:
return self.model.tspan[-1] - self.model.tspan[-2]
if self.model.user_set_tspan:
raise SimulationError(
"""
Failed while preparing to run the model. Both increment and timespan are set.
Expand Down
7 changes: 6 additions & 1 deletion gillespy2/core/raterule.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""

import uuid

from gillespy2.core.sortableobject import SortableObject
from gillespy2.core.jsonify import Jsonify

Expand All @@ -34,9 +36,12 @@ class RateRule(SortableObject, Jsonify):
"""

def __init__(self, variable=None, formula='', name=None):
if name in (None, ""):
self.name = f'rr{uuid.uuid4()}'.replace('-', '_')
else:
self.name = name
self.formula = formula
self.variable = variable
self.name = name

def __str__(self):
try:
Expand Down
5 changes: 4 additions & 1 deletion gillespy2/core/reaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ def __init__(self, name="", reactants={}, products={}, propensity_function=None,
"""

# Metadata
self.name = name
if name in (None, ""):
self.name = f'rxn{uuid.uuid4()}'.replace('-', '_')
else:
self.name = name
self.annotation = ""

# We might use this flag in the future to automatically generate
Expand Down
4 changes: 2 additions & 2 deletions gillespy2/solvers/cpp/build/build_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,14 @@ def prepare(self, model: "Union[Model, template_gen.SanitizedModel]", variable=F

# If a raw GillesPy2 model was provided, convert it to a sanitized model.
if isinstance(model, gillespy2.Model):
model = template_gen.SanitizedModel(model)
model = template_gen.SanitizedModel(model, variable=variable)
elif not isinstance(model, template_gen.SanitizedModel):
raise TypeError(f"Build engine expected gillespy2.Model or SanitizedModel type: received {type(model)}")

# Build the template and write it to the temp directory and remove the sample template_definitions header.
template_file = self.template_dir.joinpath(self.template_definitions_name)
template_file.unlink()
template_gen.write_definitions(str(template_file), model.get_template(variable=variable))
template_gen.write_definitions(str(template_file), model.get_template())
custom_definitions = model.get_options()
if custom_definitions is not None:
options_file = self.template_dir.joinpath(self.template_options_name)
Expand Down
33 changes: 23 additions & 10 deletions gillespy2/solvers/cpp/build/template_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,32 @@ class SanitizedModel:
:type model: gillespy2.Model
"""
reserved_names = {
"vol": "V",
"t": "t",
}

def __init__(self, model: Model):
def __init__(self, model: Model, variable=False):
self.model = model
self.variable = variable

self.species: "OrderedDict[str, Species]" = OrderedDict()
self.species_names = model.sanitized_species_names()
for species_name, sanitized_name in self.species_names.items():
self.species_id: "OrderedDict[str, int]" = OrderedDict()
for spec_id, spec_entry in enumerate(self.species_names.items()):
species_name, sanitized_name = spec_entry
self.species[sanitized_name] = model.get_species(species_name)
self.species_id[species_name] = spec_id

self.parameters: "OrderedDict[str, Parameter]" = OrderedDict()
self.parameter_names = model.sanitized_parameter_names()
self.parameter_names: "OrderedDict[str, str]" = OrderedDict()
self.parameter_names["vol"] = "P[0]" if variable else "C[0]"
self.parameter_id: "OrderedDict[str, int]" = OrderedDict()
for param_id, param_name in enumerate(model.listOfParameters.keys(), start=1):
if param_name not in self.parameter_names:
self.parameter_names[param_name] = f"P[{param_id}]" if variable else f"C[{param_id}]"
self.parameter_id[param_name] = param_id
for parameter_name, sanitized_name in self.parameter_names.items():
self.parameters[sanitized_name] = model.get_parameter(parameter_name) \
if parameter_name != "vol" else Parameter(name="V", expression=model.volume)
if parameter_name != "vol" else Parameter(name=sanitized_name, expression=str(model.volume))

base_namespace = {
# ORDER IS IMPORTANT HERE!
Expand Down Expand Up @@ -153,7 +162,7 @@ def use_rate_rule(self, rate_rule: "RateRule") -> "SanitizedModel":
log.warning(f"Could not sanitize rate rule formula expression: {rate_rule.formula}")
return self

def get_template(self, variable=False) -> "dict[str, str]":
def get_template(self) -> "dict[str, str]":
"""
Creates a dictionary of C++ macro definitions from the given model.
The keys of the dictionary contain the name of the macro definition.
Expand All @@ -168,7 +177,7 @@ def get_template(self, variable=False) -> "dict[str, str]":
results = dict({})

# Get definitions for variables
parameter_definitions = template_def_variables(self, variable)
parameter_definitions = template_def_variables(self, self.variable)
results.update(parameter_definitions)

# Get definitions for species
Expand Down Expand Up @@ -332,11 +341,15 @@ def template_def_variables(model: SanitizedModel, variable=False) -> "dict[str,
parameter_type = "VARIABLE" if variable else "CONSTANT"
# Parameter entries, parsed and formatted
parameter_set = []
for param_name, parameter in model.parameters.items():
parameter_set.append(f"{parameter_type}({param_name},{parameter.expression})")
for param_id, parameter in enumerate(model.parameters.values()):
parameter_set.append(f"{parameter_type}({param_id},{parameter.expression})")

return {
"GPY_PARAMETER_VALUES": " ".join(parameter_set)
"GPY_PARAMETER_VALUES": " ".join(parameter_set),
# Currently assumes all variable or all constant.
# For partially variable models, modify to compute these two separately.
"GPY_PARAMETER_NUM_VARIABLES": str(len(parameter_set)) if variable else "0",
"GPY_PARAMETER_NUM_CONSTANTS": str(len(parameter_set)) if not variable else "0",
}


Expand Down
5 changes: 5 additions & 0 deletions gillespy2/solvers/cpp/c_base/model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@

namespace Gillespy {

int Reaction::s_num_constants;
int Reaction::s_num_variables;
std::shared_ptr<double> Reaction::s_variables;
std::shared_ptr<const double> Reaction::s_constants;

template <typename PType>
Model<PType>::Model(
std::vector<std::string> species_names,
Expand Down
70 changes: 58 additions & 12 deletions gillespy2/solvers/cpp/c_base/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@

#pragma once

#include "template.h"

#include <cmath>
#include <memory>
#include <string>
#include <vector>
#include <iostream>

namespace Gillespy {
namespace Gillespy
{
typedef unsigned int ReactionId;

template <typename PType>
struct Species {
Expand All @@ -48,6 +52,59 @@ namespace Gillespy {

// List of reactions who's propensities will change when this reaction fires.
std::unique_ptr<int[]> species_change;

inline static double propensity(
ReactionId reaction_id,
double *state,
double *parameters,
const double *constants)
{
return map_propensity(reaction_id, state, parameters, constants);
}

inline static double propensity(
ReactionId reaction_id,
unsigned int *state,
double *parameters,
const double *constants)
{
return map_propensity(reaction_id, state, parameters, constants);
}

inline static double propensity(
ReactionId reaction_id,
int *state,
double *parameters,
const double *constants)
{
return map_propensity(reaction_id, state, parameters, constants);
}

inline static double propensity(ReactionId reaction_id, double *state)
{
return map_propensity(reaction_id, state, s_variables.get(), s_constants.get());
}

inline static double propensity(ReactionId reaction_id, int *state)
{
return map_propensity(reaction_id, state, s_variables.get(), s_constants.get());
}

inline static double propensity(ReactionId reaction_id, unsigned int *state)
{
return map_propensity(reaction_id, state, s_variables.get(), s_constants.get());
}

inline static void load_parameters()
{
s_variables = std::shared_ptr<double>(get_variables(&s_num_variables));
s_constants = std::shared_ptr<const double>(get_constants(&s_num_constants));
}

static int s_num_variables;
static int s_num_constants;
static std::shared_ptr<double> s_variables;
static std::shared_ptr<const double> s_constants;
};

template <typename PType>
Expand All @@ -67,15 +124,6 @@ namespace Gillespy {
);
};

class IPropensityFunction {
public:
virtual double evaluate(unsigned int reaction_number, unsigned int *state) = 0;
virtual double TauEvaluate(unsigned int reaction_number, const int *S) = 0;
virtual double ODEEvaluate(int reaction_number, const std::vector<double> &S) = 0;

virtual ~IPropensityFunction() {};
};

template <typename PType>
struct Simulation {
int random_seed;
Expand All @@ -95,8 +143,6 @@ namespace Gillespy {

Model<PType> *model;

IPropensityFunction *propensity_function;

template <class T> friend std::ostream &operator << (std::ostream &os, const Simulation<T> &simulation);

// output_results_buffer: Writes the contents of the entire simulation trajectory.
Expand Down
24 changes: 1 addition & 23 deletions gillespy2/solvers/cpp/c_base/ode_cpp_solver/ODESimulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,6 @@ unsigned int number_timesteps = 0;
double end_time = 100.0;
double increment = 0;

class PropensityFunction : public IPropensityFunction
{
public:
double evaluate(unsigned int reaction_number, unsigned int *S)
{
return 1.0;
}

double TauEvaluate(unsigned int reaction_number, const int *S)
{
return 1.0;
}

double ODEEvaluate(int reaction_number, const std::vector<double> &S)
{
return map_ode_propensity(reaction_number, S);
}
};

int main(int argc, char *argv[]) {
ArgParser parser = ArgParser(argc, argv);

Expand All @@ -72,6 +53,7 @@ int main(int argc, char *argv[]) {
number_timesteps = parser.timesteps;
increment = parser.increment;

Reaction::load_parameters();
Model<double> model(species_names, species_populations, reaction_names);
add_reactions(model);

Expand All @@ -80,15 +62,13 @@ int main(int argc, char *argv[]) {
random_seed = time(NULL);
}

IPropensityFunction *propensity_function = new PropensityFunction();
Simulation<double> simulation;

simulation.model = &model;
simulation.end_time = end_time;
simulation.random_seed = random_seed;
simulation.number_timesteps = number_timesteps;
simulation.number_trajectories = number_trajectories;
simulation.propensity_function = propensity_function;
simulation.current_time = 0.0;
simulation.output_interval = parser.output_interval;

Expand All @@ -98,7 +78,5 @@ int main(int argc, char *argv[]) {
ODESolver(&simulation, increment);
simulation.output_buffer_final(std::cout);

delete propensity_function;

return 0;
}
Loading