Skip to content

Commit

Permalink
Merge pull request #421 from GillesPy2/develop
Browse files Browse the repository at this point in the history
v.1.5.3
  • Loading branch information
seanebum authored Aug 7, 2020
2 parents e8d5208 + 4630d04 commit 0f1f192
Show file tree
Hide file tree
Showing 13 changed files with 202 additions and 150 deletions.
54 changes: 37 additions & 17 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,49 @@
os: linux
dist: xenial
language: python
python: "3.6"
before_script:
- "curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter"
- "chmod +x ./cc-test-reporter"
- "./cc-test-reporter before-build"
jobs:
allow_failures:
- os: windows # This should be removed once tests pass on Windows.
include:
- os: linux
dist: xenial
language: python
python: 3.6
before_script:
- "curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter"
- "chmod +x ./cc-test-reporter"
- "./cc-test-reporter before-build"
after_script:
- "coverage xml"
- "if [[ \"$TRAVIS_TEST_RESULT\" == 0 ]]; then ./cc-test-reporter after-build -t coverage.py --exit-code $TRAVIS_TEST_RESULT; fi"
- os: linux
dist: bionic
language: python
python: 3.6
- os: osx
osx_image: xcode9.4 # Python 3.6.5 running on macOS 10.13
language: shell # 'language: python' is an error on Travis CI macOS
- os: windows
language: shell # 'language: python' is an error on Travis CI Windows
before_install:
- choco install python --version 3.6.0
- choco install make
- python -m pip install --upgrade pip
env: PATH=/c/Python36:/c/Python36/Scripts:$PATH
install:
- pip3 install -r requirements.txt
- pip3 install python-libsbml
- pip3 install cython
- pip3 install coverage
- pip3 install --upgrade pip
- pip3 install -r requirements.txt
- pip3 install python-libsbml
- pip3 install cython
- pip3 install coverage
script:
- "coverage run --source=gillespy2 --omit=gillespy2/solvers/stochkit/* test/run_tests.py -m develop"
after_script:
- "coverage xml"
- "if [[ \"$TRAVIS_TEST_RESULT\" == 0 ]]; then ./cc-test-reporter after-build -t coverage.py --exit-code $TRAVIS_TEST_RESULT; fi"
- "coverage run --source=gillespy2 --omit=gillespy2/solvers/stochkit/* test/run_tests.py -m develop"
deploy:
# API token stored in env var PYPI_PASSWORD on Travis CI
provider: pypi
distributions: sdist bdist_wheel
edge: true # opt in to dpl v2
user: __token__
on:
condition: $TRAVIS_DIST = xenial
repo: GillesPy2/GillesPy2
branch: main
tags: true

56 changes: 43 additions & 13 deletions examples/AdvancedFeatures/hybrid_continuous_species.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 @@ -5,7 +5,7 @@
# @website https://github.com/GillesPy2/GillesPy2
# =============================================================================

__version__ = '1.5.2'
__version__ = '1.5.3'
__title__ = 'GillesPy2'
__description__ = 'Python interface for Gillespie-style biochemical simulations'
__url__ = 'https://github.com/GillesPy2/GillesPy2'
Expand Down
5 changes: 5 additions & 0 deletions gillespy2/core/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,11 @@ def add_rate_rule(self, rate_rules):
raise ModelError('Invalid Rate Rule. Expression must be a non-empty string value')
if rate_rules.variable == None:
raise ModelError('A GillesPy2 Rate Rule must be associated with a valid variable')
if isinstance(rate_rules.variable, str):
v = rate_rules.variable
if v not in self.listOfSpecies and v not in self.listOfParameters:
raise ModelError(
'Invalid variable entered for Rate Rule: {}'.format(rate_rules.name))

self.listOfRateRules[rate_rules.name] = rate_rules
sanitized_rate_rule = RateRule(name='RR{}'.format(len(self._listOfRateRules)))
Expand Down
10 changes: 7 additions & 3 deletions gillespy2/solvers/cpp/c_base/makefile
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
CC=g++
CFLAGS=-c -std=c++14 -Wall -O3
SIMFLAGS = -std=c++14 -Wall -O3
SIMFLAGS = -L. -std=c++14 -Wall -O3
DEPS = model.h ssa.h
OBJ = model.o ssa.o
.PHONY: all

all: UserSimulation

%.o: %.cpp $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)

UserSimulation: $(OBJ)
$(CC) UserSimulation.cpp $(SIMFLAGS) -o $@ $^
UserSimulation.o:
$(CC) -c -o UserSimulation.o UserSimulation.cpp $(CFLAGS)

UserSimulation: $(OBJ) UserSimulation.o
$(CC) -o UserSimulation $(OBJ) UserSimulation.o $(SIMFLAGS)

cleanSimulation:
rm -f UserSimulation
Expand Down
33 changes: 11 additions & 22 deletions gillespy2/solvers/cpp/c_base/model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,27 +82,16 @@ namespace Gillespy{
return os;
}

void Simulation :: output_results_buffer(std :: ostream& os){
double temp;
unsigned char* temp_byte = reinterpret_cast<unsigned char*>(&temp);
for(unsigned int i = 0; i < number_timesteps; i++){
temp = timeline[i];
for(unsigned int byte_i = 0; byte_i < sizeof(double); byte_i++){
os << temp_byte[byte_i];
}
for(unsigned int trajectory = 0; trajectory < number_trajectories; trajectory++){
for(unsigned int j = 0; j < model -> number_species; j++){
temp = trajectories[trajectory][i][j];
for(unsigned int byte_i = 0; byte_i < sizeof(double); byte_i++){
os << temp_byte[byte_i];
}
}
}
void Simulation :: output_results_buffer(std::ostream& os){
for (int i = 0 ; i < number_trajectories; i++){
for (int j = 0; j<number_timesteps;j++){
os<<timeline[j]<<',';
for (int k = 0; k<model->number_species; k++){
os<<trajectories[i][j][k]<<',';
}
}
}
os<<(int)current_time;
}
temp = current_time;
temp_byte = reinterpret_cast<unsigned char*>(&temp);
for (unsigned int byte_i=0; byte_i < sizeof(double); byte_i++){
os << temp_byte[byte_i];
}
}

}
8 changes: 5 additions & 3 deletions gillespy2/solvers/cpp/c_base/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <string>
#include <vector>
#include <iostream>
#include <math.h>
#include <cmath>

namespace Gillespy{

Expand All @@ -24,12 +24,13 @@ namespace Gillespy{

//Represents a model of reactions and species
struct Model{
void update_affected_reactions();

unsigned int number_species;
std :: unique_ptr<Species[]> species;
unsigned int number_reactions;
std :: unique_ptr<Reaction[]> reactions;
Model(std :: vector<std :: string> species_names, std :: vector<unsigned int> species_populations, std :: vector<std :: string> reaction_names);
void update_affected_reactions();
};

//Interface class to represent container for propensity functions
Expand All @@ -43,6 +44,8 @@ namespace Gillespy{
//Represents simulation return data
struct Simulation{
Model* model;
~Simulation();

double* timeline;
double end_time;
double current_time;
Expand All @@ -53,7 +56,6 @@ namespace Gillespy{
unsigned int*** trajectories;
IPropensityFunction *propensity_function;
Simulation(Model* model, unsigned int number_trajectories, unsigned int number_timesteps, double end_time, IPropensityFunction* propensity_function, int random_seed, double current_time);
~Simulation();
friend std :: ostream& operator<<(std :: ostream& os, const Simulation& simulation);
void output_results_buffer(std :: ostream& os);
};
Expand Down
33 changes: 20 additions & 13 deletions gillespy2/solvers/cpp/ssa_c_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

GILLESPY_PATH = os.path.dirname(inspect.getfile(gillespy2))
GILLESPY_C_DIRECTORY = os.path.join(GILLESPY_PATH, 'solvers/cpp/c_base')

MAKE_FILE = os.path.dirname(os.path.abspath(__file__))+'/c_base/makefile'

def _write_constants(outfile, model, reactions, species, parameter_mappings, resume):
"""
Expand Down Expand Up @@ -135,16 +135,21 @@ def __compile(self):
if self.resume[0].model != self.model:
raise gillespyError.ModelError('When resuming, one must not alter the model being resumed.')
else:
built = subprocess.run(["make", "-C", self.output_directory, 'UserSimulation'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
else:
try:
cleaned = subprocess.run(["make", "-C", self.output_directory, 'cleanSimulation'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
built = subprocess.run(["make", "-C", self.output_directory, 'UserSimulation'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except KeyboardInterrupt:
log.warning("Solver has been interrupted during compile time, unexpected behavior may occur.")
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
else:
try:
cleaned = subprocess.run(
["make", "-C", self.output_directory, '-f', MAKE_FILE,
'cleanSimulation'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
built = subprocess.run(
["make", "-C", self.output_directory, '-f', MAKE_FILE,
'UserSimulation'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
except KeyboardInterrupt:
log.warning(
"Solver has been interrupted during compile time, unexpected behavior may occur.")

if built.returncode == 0:
self.__compiled = True
Expand Down Expand Up @@ -233,14 +238,16 @@ def run(self=None, model=None, t=20, number_of_trajectories=1, timeout=0,
pause = True
return_code = 33

# Parse/return results.
# Decode from byte, split by comma into array
stdout = stdout.decode('utf-8').split(',')
# Parse/return results

if return_code in [0, 33]:
trajectory_base, timeStopped = cutils._parse_binary_output(stdout, number_of_trajectories,
number_timesteps, len(model.listOfSpecies),
number_timesteps, len(model.listOfSpecies), stdout,
pause=pause)
if model.tspan[2] - model.tspan[1] == 1:
timeStopped = int(timeStopped)

# Format results
self.simulation_data = []
for trajectory in range(number_of_trajectories):
Expand Down
29 changes: 19 additions & 10 deletions gillespy2/solvers/cpp/variable_ssa_c_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

GILLESPY_PATH = os.path.dirname(inspect.getfile(gillespy2))
GILLESPY_C_DIRECTORY = os.path.join(GILLESPY_PATH, 'solvers/cpp/c_base')
MAKE_FILE = os.path.dirname(os.path.abspath(__file__))+'/c_base/makefile'


def _write_variables(outfile, model, reactions, species, parameters, parameter_mappings, resume=None):
Expand Down Expand Up @@ -149,16 +150,22 @@ def __compile(self):
if self.resume[0].model != self.model:
raise gillespyError.ModelError('When resuming, one must not alter the model being resumed.')
else:
built = subprocess.run(["make", "-C", self.output_directory, 'UserSimulation'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
built = subprocess.run(
["make", "-C", self.output_directory, 'UserSimulation'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
else:
try:
cleaned = subprocess.run(["make", "-C", self.output_directory, 'cleanSimulation'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
built = subprocess.run(["make", "-C", self.output_directory, 'UserSimulation'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
cleaned = subprocess.run(
["make", "-C", self.output_directory, '-f', MAKE_FILE,
'cleanSimulation'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
built = subprocess.run(
["make", "-C", self.output_directory, '-f', MAKE_FILE,
'UserSimulation'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
except KeyboardInterrupt:
log.warning("Solver has been interrupted during compile time, unexpected behavior may occur.")
log.warning(
"Solver has been interrupted during compile time, unexpected behavior may occur.")

if built.returncode == 0:
self.__compiled = True
Expand Down Expand Up @@ -290,12 +297,14 @@ def run(self=None, model=None, t=20, number_of_trajectories=1, timeout=0,
stdout, stderr = simulation.communicate()
pause = True
return_code = 33

# Decode from byte, split by comma into array
stdout = stdout.decode('utf-8').split(',')
# Parse/return results.

if return_code in [0, 33]:
trajectory_base, timeStopped = cutils._parse_binary_output(stdout, number_of_trajectories,
number_timesteps,
len(model.listOfSpecies), pause=pause)
number_timesteps, len(model.listOfSpecies),
stdout, pause=pause)
if model.tspan[2] - model.tspan[1] == 1:
timeStopped = int(timeStopped)

Expand Down
Loading

0 comments on commit 0f1f192

Please sign in to comment.