diff --git a/spatialpy/__init__.py b/spatialpy/__init__.py
index 5599fea0..d62ab566 100644
--- a/spatialpy/__init__.py
+++ b/spatialpy/__init__.py
@@ -22,13 +22,9 @@
import sys
if (sys.version_info < (3,0)):
raise Exception("SpatialPy 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 spatialpy.Model import *
-from spatialpy.Solver import *
-from spatialpy.Geometry import *
-from spatialpy.Domain import *
-from spatialpy.DataFunction import DataFunction
-from spatialpy.InitialCondition import *
-from spatialpy.BoundaryCondition import BoundaryCondition
-from spatialpy.VTKReader import *
-from spatialpy.cleanup import *
+from spatialpy.core import *
+from spatialpy.solvers import *
diff --git a/spatialpy/BoundaryCondition.py b/spatialpy/core/BoundaryCondition.py
similarity index 90%
rename from spatialpy/BoundaryCondition.py
rename to spatialpy/core/BoundaryCondition.py
index eaa06bf5..0077c3fc 100644
--- a/spatialpy/BoundaryCondition.py
+++ b/spatialpy/core/BoundaryCondition.py
@@ -17,7 +17,8 @@
'''
import numpy
-from spatialpy.Model import ModelError
+
+from spatialpy.core.spatialpyError import BoundaryConditionError
class BoundaryCondition():
@@ -102,9 +103,9 @@ def expression(self):
:rtype: str
"""
if( self.species is not None and self.property is not None):
- raise ModelError("Can not set both species and property")
+ raise BoundaryConditionError("Can not set both species and property")
if self.value is None:
- raise ModelError("Must set value")
+ raise BoundaryConditionError("Must set value")
cond=[]
if(self.xmin is not None): cond.append("(me->x[0] >= {0})".format(self.xmin))
if(self.xmax is not None): cond.append("(me->x[0] <= {0})".format(self.xmax))
@@ -113,14 +114,14 @@ def expression(self):
if(self.zmin is not None): cond.append("(me->x[2] >= {0})".format(self.zmin))
if(self.zmax is not None): cond.append("(me->x[2] <= {0})".format(self.zmax))
if(self.type_id is not None): cond.append("(me->type == {0})".format(int(self.type_id)))
- if(len(cond)==0): raise ModelError('need at least one condition on the BoundaryCondition')
+ if(len(cond)==0): raise BoundaryConditionError('need at least one condition on the BoundaryCondition')
bcstr = "if(" + '&&'.join(cond) + "){"
if self.species is not None:
if self.deterministic:
s_ndx = self.model.species_map[self.model.listOfSpecies[self.species]]
bcstr += "me->C[{0}] = {1};".format(s_ndx,self.value)
else:
- raise Exception("BoundaryConditions don't work for stochastic species yet")
+ raise BoundaryConditionError("BoundaryConditions don't work for stochastic species yet")
elif self.property is not None:
if(self.property == 'v'):
for i in range(3):
@@ -130,6 +131,6 @@ def expression(self):
elif(self.property == 'rho'):
bcstr+= "me->rho={0};".format(self.value)
else:
- raise Exception("Unable handle boundary condition for property '{0}'".format(self.property))
+ raise BoundaryConditionError("Unable handle boundary condition for property '{0}'".format(self.property))
bcstr+= "}"
return bcstr
diff --git a/spatialpy/DataFunction.py b/spatialpy/core/DataFunction.py
similarity index 86%
rename from spatialpy/DataFunction.py
rename to spatialpy/core/DataFunction.py
index 9f1bd51b..e6b12d39 100644
--- a/spatialpy/DataFunction.py
+++ b/spatialpy/core/DataFunction.py
@@ -15,7 +15,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
'''
-
+from spatialpy.core.spatialpyError import DataFunctionError
class DataFunction():
""" Abstract class used to constuct the data function. """
@@ -24,7 +24,7 @@ def __init__(self, name=None):
if name is not None:
self.name = name
if self.name is None:
- raise Exception("DataFunction must have a 'name'")
+ raise DataFunctionError("DataFunction must have a 'name'")
def map(self, x):
"""
@@ -39,6 +39,6 @@ def map(self, x):
:returns: value of function at this spatial location.
:rtype: float
"""
- raise Exception("DataFunction.map() must be implemented.")
+ raise DataFunctionError("DataFunction.map() must be implemented.")
diff --git a/spatialpy/Domain.py b/spatialpy/core/Domain.py
similarity index 99%
rename from spatialpy/Domain.py
rename to spatialpy/core/Domain.py
index c97a3727..40155ac2 100644
--- a/spatialpy/Domain.py
+++ b/spatialpy/core/Domain.py
@@ -22,8 +22,7 @@
import numpy
from scipy.spatial import KDTree
-from spatialpy.Result import _plotly_iterate
-
+from spatialpy.core.spatialpyError import DomainError
class Domain():
""" Domain class for SpatialPy. A domain defines points and attributes of a regional space for simulation.
@@ -360,6 +359,7 @@ def plot_types(self, width=None, height=None, colormap=None, size=5, title=None,
:param use_matplotlib: Whether or not to plot the proprties results using matplotlib.
:type use_matplotlib: bool
'''
+ from spatialpy.core.Result import _plotly_iterate
if use_matplotlib:
width = 6.4 if width in (None, "auto") else width
@@ -557,7 +557,7 @@ def read_stochss_subdomain_file(self, filename):
(ndx,type_id) = line.rstrip().split(',')
self.type[int(ndx)] = int(type_id)
except ValueError as e:
- raise ModelError(f"Could not read in subdomain file, error on line {ln}: {line}")
+ raise DomainError(f"Could not read in subdomain file, error on line {ln}: {line}")
@classmethod
@@ -751,8 +751,3 @@ def create_2D_domain(cls, xlim, ylim, nx, ny, type_id=1, mass=1.0, nu=1.0, rho=N
# return model ref
return obj
-
-
-
-class DomainError(Exception):
- pass
diff --git a/spatialpy/Geometry.py b/spatialpy/core/Geometry.py
similarity index 90%
rename from spatialpy/Geometry.py
rename to spatialpy/core/Geometry.py
index ca0b291a..3e086bc3 100644
--- a/spatialpy/Geometry.py
+++ b/spatialpy/core/Geometry.py
@@ -15,6 +15,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
'''
+from spatialpy.core.spatialpyError import GeometryError
class Geometry:
""" Geometry class provides a method for tagging parts of the spatial domain as separate parts"""
@@ -23,7 +24,7 @@ def __init__(self):
pass
def inside(self, x, on_boundary):
- raise Exception("Subclasses of spatialpy.Geometry must implement the inside() method")
+ raise GeometryError("Subclasses of spatialpy.Geometry must implement the inside() method")
class GeometryAll(Geometry):
diff --git a/spatialpy/InitialCondition.py b/spatialpy/core/InitialCondition.py
similarity index 91%
rename from spatialpy/InitialCondition.py
rename to spatialpy/core/InitialCondition.py
index c682050a..5469e171 100644
--- a/spatialpy/InitialCondition.py
+++ b/spatialpy/core/InitialCondition.py
@@ -17,7 +17,8 @@
'''
import numpy
-from spatialpy.Model import ModelError
+
+from spatialpy.core.spatialpyError import InitialConditionError
class InitialCondition():
@@ -27,7 +28,7 @@ class InitialCondition():
"""
def apply(self, model):
- raise ModelError("spatialpy.InitialCondition subclasses must implement apply()")
+ raise InitialConditionError("spatialpy.InitialCondition subclasses must implement apply()")
#TODO: implement InitialConditionFromResult()
@@ -102,7 +103,7 @@ def apply(self, model):
if model.domain.type[i] in self.types:
allowed_voxels.append(i)
nvox = len(allowed_voxels)
- if nvox==0: raise ModelError("ScatterInitialCondition has zero voxels to scatter in. Species={0} count={1} types={2}".format(self.species.name, self.count, self.types))
+ if nvox==0: raise InitialConditionError("ScatterInitialCondition has zero voxels to scatter in. Species={0} count={1} types={2}".format(self.species.name, self.count, self.types))
for mol in range(self.count):
v_ndx = numpy.random.randint(0, nvox)
vtx = allowed_voxels[v_ndx]
diff --git a/spatialpy/Model.py b/spatialpy/core/Model.py
similarity index 70%
rename from spatialpy/Model.py
rename to spatialpy/core/Model.py
index 57e33262..84919e04 100644
--- a/spatialpy/Model.py
+++ b/spatialpy/core/Model.py
@@ -18,16 +18,22 @@
#This module defines a model that simulates a discrete, stoachastic, mixed biochemical reaction network in python.
-import uuid
-from collections import OrderedDict
-from spatialpy.Solver import Solver
-from spatialpy.DataFunction import DataFunction
-from spatialpy.Domain import Domain
-from spatialpy.expression import Expression
import numpy
import scipy
import warnings
import math
+import uuid
+from collections import OrderedDict
+
+from spatialpy.core.Species import Species
+from spatialpy.core.Parameter import Parameter
+from spatialpy.core.Reaction import Reaction
+from spatialpy.core.DataFunction import DataFunction
+from spatialpy.core.Domain import Domain
+from spatialpy.solvers.Solver import Solver
+from spatialpy.solvers.build.expression import Expression
+
+from spatialpy.core.spatialpyError import *
def export_StochSS(spatialpy_model, filename=None, return_stochss_model=False):
@@ -726,294 +732,3 @@ def _apply_initial_conditions(self):
# apply initial condition functions
for ic in self.listOfInitialConditions:
ic.apply(self)
-
-
-
-
-
-class Species():
- """ Model of a biochemical species. Must be assigned a diffusion coefficent.
-
- :param name: Name of the Species
- :type name: str
- :param diffusion_coefficient: non-constant coefficient of diffusion for Species
- :type diffusion_coefficient: float
- """
-
- reserved_names = ["x", "vol","sd","data_fn","t","debug_flag","Spatialpy"]
-
-
-
- def __init__(self,name=None, diffusion_coefficient=None):
- # A species has a name (string) and an initial value (positive integer)
- if name is None:
- raise ModelError("Species must have a name")
- else:
- self.name = name
- if diffusion_coefficient is not None:
- self.diffusion_coefficient=diffusion_coefficient
- else:
- raise ModelError("Species must have a diffusion_coefficient")
-
-
- def __str__(self):
- print_string = f"{self.name}: {str(self.diffusion_coefficient)}"
- return print_string
-
-class Parameter():
- """
- Model of a rate paramter.
- A parameter can be given as a String expression (function) or directly as a scalar value.
- If given a String expression, it should be evaluable in the namespace of a parent Model.
-
- :param name: Name of the Parameter
- :type name: str
- :param expression: Mathematical expression of Parameter
- :type expression: str
- :param value: Parameter as value rather than expression.
- :type value: float
-
- """
-
- def __init__(self,name=None,expression=None):
-
- if name is None:
- raise ParameterError("name is required for a Parameter.")
- if expression is None:
- raise ParameterError("expression is required for a Parameter.")
-
- self.name = name
- self.value = None
- # We allow expression to be passed in as a non-string type. Invalid strings
- # will be caught below. It is perfectly fine to give a scalar value as the expression.
- # This can then be evaluated in an empty namespace to the scalar value.
- self.expression = str(expression)
-
- def __str__(self):
- print_string = f"{self.name}: {str(self.expression)}"
- return print_string
-
- def _evaluate(self,namespace={}):
- """ Evaluate the expression and return the (scalar) value """
- try:
- self.value = (float(eval(self.expression, namespace)))
- except Exception as err:
- message = f"Could not evaluate expression '{self.expression}': {err}."
- raise ParameterError(message) from err
-
-
-class Reaction():
- """
- Models a biochemical reaction. A reaction conatains dictionaries of species (reactants and products) \
- and parameters. The reaction's propensity function needs to be evaluable and result in a \
- non-negative scalar value in the namespace defined by the union of its Reactant, Product and \
- Parameter dictionaries. If massaction is set to true, propensity_function is not a valid argument. \
- Instead, the propensity function is constructed automatically. For mass-action, zeroth, first \
- and second order reactions are supported, attempting to used higher orders will result in an error.
-
- :param name: String that the model is referenced by
- :type name: str
- :param parameters: A list of parameter instances
- :type parameters: list(spatialpy.Model.Parameter)
- :param propensity_function: String with the expression for the reaction's propensity
- :type propensity_function: str
- :param reactants: Dictionary of {species:stoichiometry} of reaction reactants
- :type reactants: dict
- :param products: Dictionary of {species:stoichiometry} of reaction products
- :type products: dict
- :param annotation: Description of the reaction (meta)
- :type annotation: str
- :param massaction: Is the reaction of mass action type or not?
- :type massaction: bool
- :param rate: if mass action, rate is a reference to a parameter instance.
- :type rate: spatialpy.model.Parameter
-
-
- """
-
- def __init__(self, name = "", reactants = {}, products = {}, propensity_function=None, massaction=None, rate=None, annotation=None,restrict_to=None):
-
- # Metadata
- self.name = name
- self.reactants = reactants
- self.products = products
- self.propensity_function = propensity_function
- self.massaction = massaction
- self.rate = rate
- self.annotation = annotation
- if isinstance(restrict_to, int):
- self.restrict_to = [restrict_to]
- elif isinstance(restrict_to, list) or restrict_to is None:
- self.restrict_to = restrict_to
- else:
- errmsg = f"Reaction {name}: restrict_to must be an integer or list of integers."
- raise ReactionError(errmsg)
-
- def initialize(self, model):
- """ Defered object initialization, called by model.add_reaction(). """
-
- self.ode_propensity_function = self.propensity_function
-
- if self.propensity_function is None:
- if self.rate is None:
- errmsg = f"Reaction {name}: You must either set the reaction to be mass-action or specifiy a propensity function."
- raise ReactionError(errmsg)
- self.massaction = True
- else:
- if self.rate is not None:
- errmsg = f"Reaction {name}: You cannot set the propensity type to mass-action and simultaneously set a propensity function."
- raise ReactionError(errmsg)
- # If they don't give us a propensity function and do give a rate, assume mass-action.
- self.massaction = False
- self.marate = None
-
-
- reactants = self.reactants
- self.reactants = {}
- if reactants is not None:
- for r in reactants:
- rtype = type(r).__name__
- if rtype=='Species':
- self.reactants[r]=reactants[r]
- elif rtype=='str':
- if r not in model.listOfSpecies:
- raise ReactionError(f"Could not find species '{r}' in model.")
- self.reactants[model.listOfSpecies[r]] = reactants[r]
-
- products = self.products
- self.products = {}
- if products is not None:
- for p in products:
- rtype = type(p).__name__
- if rtype=='Species':
- self.products[p]=products[p]
- else:
- if p not in model.listOfSpecies:
- raise ReactionError(f"Could not find species '{p}' in model.")
- self.products[model.listOfSpecies[p]] = products[p]
-
- if self.massaction:
- self.type = "mass-action"
- rtype = type(self.rate).__name__
- if rtype == 'Parameter':
- self.marate = self.rate.name
- elif rtype == 'int' or rtype == 'float':
- self.marate = str(self.rate)
- else:
- self.marate = self.rate
- self.__create_mass_action()
- else:
- self.type = "customized"
-
-
- def __str__(self):
- print_string = f"{self.name}, Active in: {str(self.restrict_to)}"
- if len(self.reactants):
- print_string += f"\n\tReactants"
- for species, stoichiometry in self.reactants.items():
- name = species if isinstance(species, str) else species.name
- print_string += f"\n\t\t{name}: {stoichiometry}"
- if len(self.products):
- print_string += f"\n\tProducts"
- for species, stoichiometry in self.products.items():
- name = species if isinstance(species, str) else species.name
- print_string += f"\n\t\t{name}: {stoichiometry}"
- print_string += f"\n\tPropensity Function: {self.propensity_function}"
- return print_string
-
-
- def __create_mass_action(self):
- """ Create a mass action propensity function given self.reactants and a single parameter value.
-
- We support zeroth, first and second order propensities only.
- There is no theoretical justification for higher order propensities.
- Users can still create such propensities if they really want to,
- but should then use a custom propensity.
- """
- total_stoch = 0
- for r in self.reactants:
- total_stoch += self.reactants[r]
- if total_stoch > 2:
- raise ReactionError(
- """Reaction: A mass-action reaction cannot involve more than two of one species or one "
- of two species (no more than 2 total reactants).
- SpatialPy support zeroth, first and second order propensities only.
- There is no theoretical justification for higher order propensities.
- Users can still create such propensities using a 'custom propensity'.""")
- # Case EmptySet -> Y
-
- if isinstance(self.marate, str):
- propensity_function = self.marate
- ode_propensity_function = self.marate
- else:
- propensity_function = self.marate.name
- ode_propensity_function = self.marate.name
-
- # There are only three ways to get 'total_stoch==2':
- for r in self.reactants:
- # Case 1: 2X -> Y
- if self.reactants[r] == 2:
- propensity_function = ("0.5*" + propensity_function +
- "*" + r.name + "*(" + r.name + "-1)/vol")
- else:
- # Case 3: X1, X2 -> Y;
- propensity_function += "*" + r.name
- ode_propensity_function += "*" + r.name
-
- # Set the volume dependency based on order.
- order = len(self.reactants)
- if order == 2:
- propensity_function += "/vol"
- elif order == 0:
- propensity_function += "*vol"
-
- self.propensity_function = propensity_function
- self.ode_propensity_function = ode_propensity_function
-
-
- def add_reactant(self,S,stoichiometry):
- """ Add a reactant to this reaction
-
- :param s: reactant Species object
- :type s: spatialpy.Model.Species
- :param stoichiometry: Stoichiometry of this participant reactant
- :type stoichiometry: int
-
- """
- if stoichiometry <= 0:
- raise ReactionError("Reaction "+self.name+"Stoichiometry must be a positive integer.")
- self.reactants[S.name]=stoichiometry
-
- def add_product(self,S,stoichiometry):
- """ Add a product to this reaction
-
- :param s: Species object to be produced by the reaction
- :type s: spatialpy.Model.Species
- :param stoichiometry: Stoichiometry of this product.
- :type stoichiometry: int
-
- """
- self.products[S.name]=stoichiometry
-
- def annotate(self,annotation):
- """ Add an annotation to this reaction.
-
- :param annotation: Annotation note to be added to reaction
- :type annotation: str
-
- """
- self.annotation = annotation
-
-
-# Module exceptions
-class ModelError(Exception):
- pass
-
-class SpeciesError(ModelError):
- pass
-
-class ReactionError(ModelError):
- pass
-
-class ParameterError(ModelError):
- pass
diff --git a/spatialpy/core/Parameter.py b/spatialpy/core/Parameter.py
new file mode 100644
index 00000000..40099c0b
--- /dev/null
+++ b/spatialpy/core/Parameter.py
@@ -0,0 +1,64 @@
+'''
+SpatialPy is a Python 3 package for simulation of
+spatial deterministic/stochastic reaction-diffusion-advection problems
+Copyright (C) 2021 SpatialPy developers.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU GENERAL PUBLIC LICENSE Version 3 as
+published by the Free Software Foundation.
+
+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 Version 3 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
+from spatialpy.core.spatialpyError import ParameterError
+
+class Parameter():
+ """
+ Model of a rate paramter.
+ A parameter can be given as a String expression (function) or directly as a scalar value.
+ If given a String expression, it should be evaluable in the namespace of a parent Model.
+
+ :param name: Name of the Parameter
+ :type name: str
+ :param expression: Mathematical expression of Parameter
+ :type expression: str
+ :param value: Parameter as value rather than expression.
+ :type value: float
+ """
+
+ def __init__(self, name=None, expression=None):
+
+ if name is None:
+ raise ParameterError("name is required for a Parameter.")
+ if not isinstance(name, str):
+ raise ParameterError("Parameter name must be a string.")
+
+ if expression is None:
+ raise ParameterError("expression is required for a Parameter.")
+
+ self.name = name
+ self.value = None
+ # We allow expression to be passed in as a non-string type. Invalid strings
+ # will be caught below. It is perfectly fine to give a scalar value as the expression.
+ # This can then be evaluated in an empty namespace to the scalar value.
+ if isinstance(expression, (int, float)):
+ self.expression = str(expression)
+ else:
+ self.expression = expression
+
+ def __str__(self):
+ print_string = f"{self.name}: {str(self.expression)}"
+ return print_string
+
+ def _evaluate(self, namespace={}):
+ """ Evaluate the expression and return the (scalar) value """
+ try:
+ self.value = (float(eval(self.expression, namespace)))
+ except Exception as err:
+ message = f"Could not evaluate expression '{self.expression}': {err}."
+ raise ParameterError(message) from err
diff --git a/spatialpy/core/Reaction.py b/spatialpy/core/Reaction.py
new file mode 100644
index 00000000..3b31c9f8
--- /dev/null
+++ b/spatialpy/core/Reaction.py
@@ -0,0 +1,238 @@
+'''
+SpatialPy is a Python 3 package for simulation of
+spatial deterministic/stochastic reaction-diffusion-advection problems
+Copyright (C) 2021 SpatialPy developers.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU GENERAL PUBLIC LICENSE Version 3 as
+published by the Free Software Foundation.
+
+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 Version 3 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
+from spatialpy.core.Parameter import Parameter
+from spatialpy.core.spatialpyError import ReactionError
+
+class Reaction():
+ """
+ Models a biochemical reaction. A reaction conatains dictionaries of species (reactants and products) \
+ and parameters. The reaction's propensity function needs to be evaluable and result in a \
+ non-negative scalar value in the namespace defined by the union of its Reactant, Product and \
+ Parameter dictionaries. For mass-action, zeroth, first \
+ and second order reactions are supported, attempting to used higher orders will result in an error.
+
+ :param name: String that the model is referenced by
+ :type name: str
+ :param parameters: A list of parameter instances
+ :type parameters: list(spatialpy.Model.Parameter)
+ :param propensity_function: String with the expression for the reaction's propensity
+ :type propensity_function: str
+ :param reactants: Dictionary of {species:stoichiometry} of reaction reactants
+ :type reactants: dict
+ :param products: Dictionary of {species:stoichiometry} of reaction products
+ :type products: dict
+ :param annotation: Description of the reaction (meta)
+ :type annotation: str
+ :param rate: if mass action, rate is a reference to a parameter instance.
+ :type rate: spatialpy.model.Parameter
+ """
+
+ def __init__(self, name="", reactants={}, products={}, propensity_function=None, rate=None, annotation=None, restrict_to=None):
+
+ if not isinstance(name, str):
+ raise ReactionError("Reaction name must be of type str.")
+ self.name = name
+
+ if not isinstance(reactants, dict):
+ raise ReactionError("Reaction reactants must be of type dict.")
+ self.reactants = reactants
+
+ if not isinstance(products, dict):
+ raise ReactionError("Reaction products must be of type dict.")
+ self.products = products
+
+ if not (isinstance(propensity_function, (str, int, float)) or propensity_function is None):
+ raise ReactionError("Reaction propensity_function must be one of the following types: str, int, float, or None.")
+ if isinstance(propensity_function, (int, float)):
+ self.propensity_function = str(propensity_function)
+ else:
+ self.propensity_function = propensity_function
+
+ if not (isinstance(rate, (str, int, float)) or rate is None or \
+ isinstance(rate, Parameter) or type(rate).__name__ == 'Parameter'):
+ raise ReactionError("Reaction rate must be one of the following types: spatialpy.Parameter, str, int, float, or None.")
+ if isinstance(rate, (int, float)):
+ self.rate = str(rate)
+ else:
+ self.rate = rate
+
+ if isinstance(restrict_to, int):
+ self.restrict_to = [restrict_to]
+ elif isinstance(restrict_to, list) or restrict_to is None:
+ self.restrict_to = restrict_to
+ else:
+ errmsg = f"Reaction {name}: restrict_to must be an integer or list of integers."
+ raise ReactionError(errmsg)
+
+ self.annotation = annotation
+
+
+ def initialize(self, model):
+ """ Defered object initialization, called by model.add_reaction(). """
+
+ self.ode_propensity_function = self.propensity_function
+
+ if self.propensity_function is None:
+ if self.rate is None:
+ errmsg = f"Reaction {name}: You must either set the reaction to be mass-action or specifiy a propensity function."
+ raise ReactionError(errmsg)
+ self.massaction = True
+ else:
+ if self.rate is not None:
+ errmsg = f"Reaction {name}: You cannot set the propensity type to mass-action and simultaneously set a propensity function."
+ raise ReactionError(errmsg)
+ # If they don't give us a propensity function and do give a rate, assume mass-action.
+ self.massaction = False
+ self.marate = None
+
+
+ reactants = self.reactants
+ self.reactants = {}
+ if reactants is not None:
+ for r in reactants:
+ rtype = type(r).__name__
+ if rtype=='Species':
+ self.reactants[r]=reactants[r]
+ elif rtype=='str':
+ if r not in model.listOfSpecies:
+ raise ReactionError(f"Could not find species '{r}' in model.")
+ self.reactants[model.listOfSpecies[r]] = reactants[r]
+
+ products = self.products
+ self.products = {}
+ if products is not None:
+ for p in products:
+ rtype = type(p).__name__
+ if rtype=='Species':
+ self.products[p]=products[p]
+ else:
+ if p not in model.listOfSpecies:
+ raise ReactionError(f"Could not find species '{p}' in model.")
+ self.products[model.listOfSpecies[p]] = products[p]
+
+ if self.massaction:
+ self.type = "mass-action"
+ rtype = type(self.rate).__name__
+ if rtype == 'Parameter':
+ self.marate = self.rate.name
+ elif rtype == 'int' or rtype == 'float':
+ self.marate = str(self.rate)
+ else:
+ self.marate = self.rate
+ self.__create_mass_action()
+ else:
+ self.type = "customized"
+
+
+ def __str__(self):
+ print_string = f"{self.name}, Active in: {str(self.restrict_to)}"
+ if len(self.reactants):
+ print_string += f"\n\tReactants"
+ for species, stoichiometry in self.reactants.items():
+ name = species if isinstance(species, str) else species.name
+ print_string += f"\n\t\t{name}: {stoichiometry}"
+ if len(self.products):
+ print_string += f"\n\tProducts"
+ for species, stoichiometry in self.products.items():
+ name = species if isinstance(species, str) else species.name
+ print_string += f"\n\t\t{name}: {stoichiometry}"
+ print_string += f"\n\tPropensity Function: {self.propensity_function}"
+ return print_string
+
+
+ def __create_mass_action(self):
+ """ Create a mass action propensity function given self.reactants and a single parameter value.
+
+ We support zeroth, first and second order propensities only.
+ There is no theoretical justification for higher order propensities.
+ Users can still create such propensities if they really want to,
+ but should then use a custom propensity.
+ """
+ total_stoch = 0
+ for r in self.reactants:
+ total_stoch += self.reactants[r]
+ if total_stoch > 2:
+ raise ReactionError(
+ """Reaction: A mass-action reaction cannot involve more than two of one species or one "
+ of two species (no more than 2 total reactants).
+ SpatialPy support zeroth, first and second order propensities only.
+ There is no theoretical justification for higher order propensities.
+ Users can still create such propensities using a 'custom propensity'.""")
+ # Case EmptySet -> Y
+
+ if isinstance(self.marate, str):
+ propensity_function = self.marate
+ ode_propensity_function = self.marate
+ else:
+ propensity_function = self.marate.name
+ ode_propensity_function = self.marate.name
+
+ # There are only three ways to get 'total_stoch==2':
+ for r in self.reactants:
+ # Case 1: 2X -> Y
+ if self.reactants[r] == 2:
+ propensity_function = ("0.5*" + propensity_function +
+ "*" + r.name + "*(" + r.name + "-1)/vol")
+ else:
+ # Case 3: X1, X2 -> Y;
+ propensity_function += "*" + r.name
+ ode_propensity_function += "*" + r.name
+
+ # Set the volume dependency based on order.
+ order = len(self.reactants)
+ if order == 2:
+ propensity_function += "/vol"
+ elif order == 0:
+ propensity_function += "*vol"
+
+ self.propensity_function = propensity_function
+ self.ode_propensity_function = ode_propensity_function
+
+
+ def add_reactant(self,S,stoichiometry):
+ """ Add a reactant to this reaction
+
+ :param s: reactant Species object
+ :type s: spatialpy.Model.Species
+ :param stoichiometry: Stoichiometry of this participant reactant
+ :type stoichiometry: int
+
+ """
+ if stoichiometry <= 0:
+ raise ReactionError("Reaction "+self.name+"Stoichiometry must be a positive integer.")
+ self.reactants[S.name]=stoichiometry
+
+ def add_product(self,S,stoichiometry):
+ """ Add a product to this reaction
+
+ :param s: Species object to be produced by the reaction
+ :type s: spatialpy.Model.Species
+ :param stoichiometry: Stoichiometry of this product.
+ :type stoichiometry: int
+
+ """
+ self.products[S.name]=stoichiometry
+
+ def annotate(self,annotation):
+ """ Add an annotation to this reaction.
+
+ :param annotation: Annotation note to be added to reaction
+ :type annotation: str
+
+ """
+ self.annotation = annotation
diff --git a/spatialpy/Result.py b/spatialpy/core/Result.py
similarity index 99%
rename from spatialpy/Result.py
rename to spatialpy/core/Result.py
index 817c2343..5885221c 100644
--- a/spatialpy/Result.py
+++ b/spatialpy/core/Result.py
@@ -26,8 +26,9 @@
import numpy
-from spatialpy.Model import *
-from spatialpy.VTKReader import VTKReader
+from spatialpy.core.Model import *
+from spatialpy.core.VTKReader import VTKReader
+from spatialpy.core.spatialpyError import ResultError
try:
import vtk
@@ -826,7 +827,4 @@ def export_to_vtk(self, timespan, folder_name=None):
The exported data is #molecules/volume, where the volume unit is implicit from the mesh dimension.
Not currently implemented."""
# TODO
- raise Exception("Not implemented.")
-
-class ResultError(Exception):
- pass
+ raise ResultError("Not implemented.")
diff --git a/spatialpy/core/Species.py b/spatialpy/core/Species.py
new file mode 100644
index 00000000..ed07e2dc
--- /dev/null
+++ b/spatialpy/core/Species.py
@@ -0,0 +1,67 @@
+'''
+SpatialPy is a Python 3 package for simulation of
+spatial deterministic/stochastic reaction-diffusion-advection problems
+Copyright (C) 2021 SpatialPy developers.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU GENERAL PUBLIC LICENSE Version 3 as
+published by the Free Software Foundation.
+
+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 Version 3 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
+from spatialpy.core.spatialpyError import SpeciesError
+
+class Species():
+ """
+ Model of a biochemical species. Must be assigned a diffusion coefficent.
+
+ :param name: Name of the Species
+ :type name: str
+ :param diffusion_coefficient: non-constant coefficient of diffusion for Species
+ :type diffusion_coefficient: float
+ """
+
+ def __init__(self, name=None, diffusion_coefficient=None):
+ # A species has a name (string) and an initial value (positive integer)
+ if name is None:
+ raise SpeciesError("Species must have a name")
+ if not isinstance(name, str):
+ raise SpeciesError("Species name must be a string")
+
+ if diffusion_coefficient is None:
+ raise SpeciesError("Species must have a diffusion_coefficient")
+ if not isinstance(diffusion_coefficient, (float, int)):
+ raise SpeciesError("Diffusion coefficient must be a float or int.")
+ if diffusion_coefficient < 0:
+ raise SpeciesError("Diffusion coefficient must be non-negative.")
+
+ self.name = name
+ self.diffusion_coefficient = diffusion_coefficient
+
+
+ def __str__(self):
+ print_string = f"{self.name}: {str(self.diffusion_coefficient)}"
+ return print_string
+
+
+ def set_diffusion_coefficient(self, diffusion_coefficient):
+ """
+ Setter method for non-constant coefficient of diffusion for Species
+
+ :param diffusion_coefficient: Integer to set initial species population
+ :type diffusion_coefficient: float
+
+ :raises SpeciesError: If diffusion_coefficient is negative or a decimal number
+ """
+ if not isinstance(diffusion_coefficient, (float, int)):
+ raise SpeciesError("Diffusion coefficient must be a float or int.")
+ if diffusion_coefficient < 0:
+ raise SpeciesError("Diffusion coefficient must be non-negative.")
+
+ self.diffusion_coefficient = diffusion_coefficient
diff --git a/spatialpy/VTKReader.py b/spatialpy/core/VTKReader.py
similarity index 96%
rename from spatialpy/VTKReader.py
rename to spatialpy/core/VTKReader.py
index 45932770..c24bad1d 100644
--- a/spatialpy/VTKReader.py
+++ b/spatialpy/core/VTKReader.py
@@ -19,6 +19,8 @@
import numpy
import math
+from spatialpy.core.spatialpyError import VTKReaderIOError
+
class VTKReader:
"""VTKReader.py: SpatialPy minimal VTK legacy file reader."""
@@ -218,16 +220,3 @@ def readfile(self):
self.arrays = self.readarrays(fd)
#if self.debug: print("self.arrays.keys = {0}".format(self.arrays.keys()))
-
-
-class VTKReaderError(Exception):
- """Base class for exceptions in VTKReader module."""
-
- pass
-
-
-class VTKReaderIOError(VTKReaderError):
- """Exception raised for I/O errors."""
-
- def __init__(self, message):
- self.message = message
diff --git a/spatialpy/core/__init__.py b/spatialpy/core/__init__.py
new file mode 100644
index 00000000..e12ccfd5
--- /dev/null
+++ b/spatialpy/core/__init__.py
@@ -0,0 +1,43 @@
+'''
+SpatialPy is a Python 3 package for simulation of
+spatial deterministic/stochastic reaction-diffusion-advection problems
+Copyright (C) 2021 SpatialPy developers.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU GENERAL PUBLIC LICENSE Version 3 as
+published by the Free Software Foundation.
+
+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 Version 3 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
+
+import logging
+from .BoundaryCondition import *
+from .cleanup import *
+from .DataFunction import *
+from .Domain import *
+from .Geometry import *
+from .InitialCondition import *
+from .Model import *
+from .Parameter import *
+from .Reaction import *
+from .Result import *
+from .spatialpyError import *
+from .Species import *
+from .VTKReader import *
+from spatialpy.__version__ import __version__
+
+_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+_handler = logging.StreamHandler()
+_handler.setFormatter(_formatter)
+version = __version__
+log = logging.getLogger()
+log.setLevel(logging.WARNING)
+log.addHandler(_handler)
+
+__all__ = [s for s in dir() if not s.startswith('_')]
diff --git a/spatialpy/cleanup.py b/spatialpy/core/cleanup.py
similarity index 85%
rename from spatialpy/cleanup.py
rename to spatialpy/core/cleanup.py
index 66d664d8..1b966b9d 100644
--- a/spatialpy/cleanup.py
+++ b/spatialpy/core/cleanup.py
@@ -24,6 +24,8 @@ def cleanup_tempfiles():
'''
Cleanup all tempfiles in spatialpy core, build, and results.
'''
+ from spatialpy.core import log
+
cleanup_core_files()
tempdir = tempfile.gettempdir()
for file_obj in os.listdir(tempdir):
@@ -36,11 +38,13 @@ def cleanup_core_files():
'''
Cleanup all tempfiles in spatialpy core.
'''
+ from spatialpy.core import log
+
tempdir = tempfile.gettempdir()
core_dir = os.path.join(tempdir, "spatialpy_core")
if os.path.isdir(core_dir):
shutil.rmtree(core_dir)
- print(f"Spatialpy core directory was removed")
+ log.info(f"Spatialpy core directory was removed")
def cleanup_build_files(build_dir=None):
'''
@@ -49,10 +53,11 @@ def cleanup_build_files(build_dir=None):
:param build_dir: Path to the build directory to be removed. (optional)
:type build_dir: string
'''
+ from spatialpy.core import log
if build_dir is not None:
shutil.rmtree(build_dir)
- print(f"Build directory'{build_dir}' was removed")
+ log.info(f"Build directory'{build_dir}' was removed")
else:
count = 0
tempdir = tempfile.gettempdir()
@@ -61,7 +66,7 @@ def cleanup_build_files(build_dir=None):
build_dir = os.path.join(tempdir, file_obj)
shutil.rmtree(build_dir)
count += 1
- print(f"{count} build directories were removed")
+ log.info(f"{count} build directories were removed")
def cleanup_result_files(result_dir=None):
'''
@@ -70,9 +75,11 @@ def cleanup_result_files(result_dir=None):
:param result_dir: Path to the result directory to be removed. (optional)
:type result_dir: string
'''
+ from spatialpy.core import log
+
if result_dir is not None:
shutil.rmtree(result_dir)
- print(f"Result directory '{result_dir}' was removed")
+ log.info(f"Result directory '{result_dir}' was removed")
else:
count = 0
tempdir = tempfile.gettempdir()
@@ -81,4 +88,4 @@ def cleanup_result_files(result_dir=None):
result_dir = os.path.join(tempdir, file_obj)
shutil.rmtree(result_dir)
count += 1
- print(f"{count} result directories were removed")
+ log.info(f"{count} result directories were removed")
diff --git a/spatialpy/core/spatialpyError.py b/spatialpy/core/spatialpyError.py
new file mode 100644
index 00000000..2139d212
--- /dev/null
+++ b/spatialpy/core/spatialpyError.py
@@ -0,0 +1,82 @@
+'''
+SpatialPy is a Python 3 package for simulation of
+spatial deterministic/stochastic reaction-diffusion-advection problems
+Copyright (C) 2021 SpatialPy developers.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU GENERAL PUBLIC LICENSE Version 3 as
+published by the Free Software Foundation.
+
+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 Version 3 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
+
+# Base Module Expections
+class ModelError(Exception):
+ pass
+
+
+class ResultError(Exception):
+ pass
+
+
+class VTKReaderError(Exception):
+ """Base class for exceptions in VTKReader module."""
+ pass
+
+
+class SimulationError(Exception):
+ pass
+
+
+# Model Component Exceptions
+class BoundaryConditionError(ModelError):
+ pass
+
+
+class DataFunctionError(ModelError):
+ pass
+
+
+class DomainError(ModelError):
+ pass
+
+
+class GeometryError(ModelError):
+ pass
+
+
+class InitialConditionError(ModelError):
+ pass
+
+
+class ParameterError(ModelError):
+ pass
+
+
+class ReactionError(ModelError):
+ pass
+
+
+class SpeciesError(ModelError):
+ pass
+
+
+# Result Exceptions
+
+
+# VTKReader Exceptions
+class VTKReaderIOError(VTKReaderError):
+ """Exception raised for I/O errors."""
+ def __init__(self, message):
+ self.message = message
+
+
+# Simulation Exceptions
+class SimulationTimeout(SimulationError):
+ pass
diff --git a/spatialpy/Solver.py b/spatialpy/solvers/Solver.py
similarity index 98%
rename from spatialpy/Solver.py
rename to spatialpy/solvers/Solver.py
index e879f1f0..59612e8f 100644
--- a/spatialpy/Solver.py
+++ b/spatialpy/solvers/Solver.py
@@ -29,8 +29,9 @@
import re
-from spatialpy.Model import *
-from spatialpy.Result import *
+from spatialpy.core.Model import *
+from spatialpy.core.Result import *
+from spatialpy.core.spatialpyError import *
def _read_from_stdout(stdout,verbose=True):
''' Used with subprocess.Popen and threading to capture all output and print
@@ -76,7 +77,7 @@ def __init__(self, model, debug_level=0):
self.h = None # basis function width
self.SpatialPy_ROOT = os.path.dirname(
- os.path.abspath(__file__))+"/ssa_sdpd-c-simulation-engine"
+ os.path.abspath(__file__))+"/c_base/ssa_sdpd-c-simulation-engine"
self.SpatialPy_ROOTDIR = self.SpatialPy_ROOT.replace(" ","\\ ");
self.SpatialPy_ROOTINC = self.SpatialPy_ROOT.replace(" ","\\\\ ");
self.SpatialPy_ROOTPARAM = self.SpatialPy_ROOT.replace(" ","?");
@@ -314,7 +315,7 @@ def __create_propensity_file(self, file_name=None):
template = open(os.path.abspath(os.path.dirname(
- __file__)) + '/ssa_sdpd-c-simulation-engine/propensity_file_template.cpp', 'r')
+ __file__)) + '/c_base/ssa_sdpd-c-simulation-engine/propensity_file_template.cpp', 'r')
propfile = open(file_name, "w")
propfilestr = template.read()
@@ -641,11 +642,3 @@ def __create_propensity_file(self, file_name=None):
#### Write the data to the file ####
propfile.write(propfilestr)
propfile.close()
-
-
-class SimulationError(Exception):
- pass
-
-
-class SimulationTimeout(SimulationError):
- pass
diff --git a/spatialpy/solvers/__init__.py b/spatialpy/solvers/__init__.py
new file mode 100644
index 00000000..030a087b
--- /dev/null
+++ b/spatialpy/solvers/__init__.py
@@ -0,0 +1,19 @@
+'''
+SpatialPy is a Python 3 package for simulation of
+spatial deterministic/stochastic reaction-diffusion-advection problems
+Copyright (C) 2021 SpatialPy developers.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU GENERAL PUBLIC LICENSE Version 3 as
+published by the Free Software Foundation.
+
+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 Version 3 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
+
+from .Solver import *
diff --git a/spatialpy/solvers/build/__init__.py b/spatialpy/solvers/build/__init__.py
new file mode 100644
index 00000000..f0969dae
--- /dev/null
+++ b/spatialpy/solvers/build/__init__.py
@@ -0,0 +1,17 @@
+'''
+SpatialPy is a Python 3 package for simulation of
+spatial deterministic/stochastic reaction-diffusion-advection problems
+Copyright (C) 2021 SpatialPy developers.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU GENERAL PUBLIC LICENSE Version 3 as
+published by the Free Software Foundation.
+
+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 Version 3 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
diff --git a/spatialpy/expression.py b/spatialpy/solvers/build/expression.py
similarity index 95%
rename from spatialpy/expression.py
rename to spatialpy/solvers/build/expression.py
index a12dda28..4b464273 100644
--- a/spatialpy/expression.py
+++ b/spatialpy/solvers/build/expression.py
@@ -1,3 +1,21 @@
+'''
+SpatialPy is a Python 3 package for simulation of
+spatial deterministic/stochastic reaction-diffusion-advection problems
+Copyright (C) 2021 SpatialPy developers.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU GENERAL PUBLIC LICENSE Version 3 as
+published by the Free Software Foundation.
+
+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 Version 3 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
+
import ast
from typing import Union, Optional
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/build/Makefile b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/build/Makefile
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/build/Makefile
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/build/Makefile
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/Copyright.txt b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/Copyright.txt
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/Copyright.txt
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/Copyright.txt
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/License.txt b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/License.txt
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/License.txt
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/License.txt
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/Ann.sln b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/Ann.sln
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/Ann.sln
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/Ann.sln
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/Makefile b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/Makefile
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/Makefile
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/Makefile
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/ann2fig/ann2fig.vcproj b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/ann2fig/ann2fig.vcproj
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/ann2fig/ann2fig.vcproj
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/ann2fig/ann2fig.vcproj
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/dll/dll.vcproj b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/dll/dll.vcproj
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/dll/dll.vcproj
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/dll/dll.vcproj
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/sample/sample.vcproj b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/sample/sample.vcproj
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/sample/sample.vcproj
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/sample/sample.vcproj
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/test/test.vcproj b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/test/test.vcproj
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/test/test.vcproj
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/MS_Win32/test/test.vcproj
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/Make-config b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/Make-config
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/Make-config
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/Make-config
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/Makefile b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/Makefile
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/Makefile
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/Makefile
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/ReadMe.txt b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/ReadMe.txt
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/ReadMe.txt
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/ReadMe.txt
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/ann2fig/Makefile b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/ann2fig/Makefile
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/ann2fig/Makefile
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/ann2fig/Makefile
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/ann2fig/ann2fig.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/ann2fig/ann2fig.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/ann2fig/ann2fig.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/ann2fig/ann2fig.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/doc/ANNmanual.pdf b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/doc/ANNmanual.pdf
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/doc/ANNmanual.pdf
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/doc/ANNmanual.pdf
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/include/ANN/ANN.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/include/ANN/ANN.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/include/ANN/ANN.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/include/ANN/ANN.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/include/ANN/ANNperf.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/include/ANN/ANNperf.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/include/ANN/ANNperf.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/include/ANN/ANNperf.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/include/ANN/ANNx.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/include/ANN/ANNx.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/include/ANN/ANNx.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/include/ANN/ANNx.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/sample/Makefile b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/sample/Makefile
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/sample/Makefile
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/sample/Makefile
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/sample/ann_sample.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/sample/ann_sample.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/sample/ann_sample.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/sample/ann_sample.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/sample/data.pts b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/sample/data.pts
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/sample/data.pts
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/sample/data.pts
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/sample/query.pts b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/sample/query.pts
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/sample/query.pts
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/sample/query.pts
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/sample/sample.save b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/sample/sample.save
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/sample/sample.save
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/sample/sample.save
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/ANN.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/ANN.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/ANN.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/ANN.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/Makefile b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/Makefile
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/Makefile
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/Makefile
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/Makefile.spatialpy b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/Makefile.spatialpy
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/Makefile.spatialpy
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/Makefile.spatialpy
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_fix_rad_search.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_fix_rad_search.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_fix_rad_search.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_fix_rad_search.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_pr_search.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_pr_search.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_pr_search.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_pr_search.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_search.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_search.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_search.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_search.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_tree.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_tree.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_tree.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_tree.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_tree.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_tree.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_tree.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/bd_tree.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/brute.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/brute.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/brute.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/brute.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_dump.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_dump.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_dump.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_dump.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_fix_rad_search.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_fix_rad_search.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_fix_rad_search.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_fix_rad_search.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_fix_rad_search.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_fix_rad_search.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_fix_rad_search.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_fix_rad_search.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_pr_search.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_pr_search.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_pr_search.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_pr_search.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_pr_search.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_pr_search.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_pr_search.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_pr_search.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_search.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_search.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_search.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_search.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_search.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_search.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_search.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_search.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_split.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_split.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_split.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_split.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_split.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_split.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_split.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_split.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_tree.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_tree.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_tree.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_tree.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_tree.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_tree.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_tree.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_tree.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_util.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_util.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_util.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_util.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_util.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_util.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_util.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/kd_util.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/perf.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/perf.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/perf.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/perf.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/pr_queue.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/pr_queue.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/pr_queue.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/pr_queue.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/pr_queue_k.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/pr_queue_k.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/src/pr_queue_k.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/src/pr_queue_k.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/Makefile b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/Makefile
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/Makefile
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/Makefile
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/ann_test.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/ann_test.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/ann_test.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/ann_test.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/rand.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/rand.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/rand.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/rand.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/rand.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/rand.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/rand.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/rand.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test1-data.pts b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test1-data.pts
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test1-data.pts
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test1-data.pts
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test1-query.pts b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test1-query.pts
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test1-query.pts
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test1-query.pts
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test1.in b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test1.in
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test1.in
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test1.in
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test1.save b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test1.save
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test1.save
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test1.save
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test2-data.pts b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test2-data.pts
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test2-data.pts
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test2-data.pts
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test2-query.pts b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test2-query.pts
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test2-query.pts
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test2-query.pts
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test2.in b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test2.in
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test2.in
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test2.in
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test2.save b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test2.save
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/test/test2.save
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/ANN/test/test2.save
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/NRMConstant/README_NRMConstant.txt b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/NRMConstant/README_NRMConstant.txt
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/NRMConstant/README_NRMConstant.txt
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/NRMConstant/README_NRMConstant.txt
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/NRMConstant/demo_NRMConstant_v5.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/NRMConstant/demo_NRMConstant_v5.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/external/NRMConstant/demo_NRMConstant_v5.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/external/NRMConstant/demo_NRMConstant_v5.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/include/NRMConstant_v5.hpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/NRMConstant_v5.hpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/include/NRMConstant_v5.hpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/NRMConstant_v5.hpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/include/count_cores.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/count_cores.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/include/count_cores.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/count_cores.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/include/model.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/model.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/include/model.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/model.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/include/output.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/output.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/include/output.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/output.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/include/particle.hpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/particle.hpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/include/particle.hpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/particle.hpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/include/particle_system.hpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/particle_system.hpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/include/particle_system.hpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/particle_system.hpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/include/propensities.hpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/propensities.hpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/include/propensities.hpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/propensities.hpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/include/pthread_barrier.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/pthread_barrier.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/include/pthread_barrier.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/pthread_barrier.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/include/read_lammps_input_file.h b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/read_lammps_input_file.h
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/include/read_lammps_input_file.h
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/read_lammps_input_file.h
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/include/simulate.hpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/simulate.hpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/include/simulate.hpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/simulate.hpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/include/simulate_rdme.hpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/simulate_rdme.hpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/include/simulate_rdme.hpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/include/simulate_rdme.hpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/propensity_file_template.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/propensity_file_template.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/propensity_file_template.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/propensity_file_template.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/src/NRMConstant_v5.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/NRMConstant_v5.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/src/NRMConstant_v5.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/NRMConstant_v5.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/src/count_cores.c b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/count_cores.c
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/src/count_cores.c
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/count_cores.c
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/src/model.c b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/model.c
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/src/model.c
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/model.c
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/src/output.c b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/output.c
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/src/output.c
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/output.c
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/src/particle.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/particle.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/src/particle.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/particle.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/src/pthread_barrier.c b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/pthread_barrier.c
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/src/pthread_barrier.c
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/pthread_barrier.c
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/src/read_lammps_input_file.c b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/read_lammps_input_file.c
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/src/read_lammps_input_file.c
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/read_lammps_input_file.c
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/src/simulate.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/simulate.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/src/simulate.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/simulate.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/src/simulate_rdme.cpp b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/simulate_rdme.cpp
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/src/simulate_rdme.cpp
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/simulate_rdme.cpp
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/src/simulate_threads.c b/spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/simulate_threads.c
similarity index 100%
rename from spatialpy/ssa_sdpd-c-simulation-engine/src/simulate_threads.c
rename to spatialpy/solvers/c_base/ssa_sdpd-c-simulation-engine/src/simulate_threads.c
diff --git a/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/lib/.gitkeep b/spatialpy/ssa_sdpd-c-simulation-engine/external/ANN/lib/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/test/run_tests.py b/test/run_tests.py
index 5811d5ad..15c8c2b3 100755
--- a/test/run_tests.py
+++ b/test/run_tests.py
@@ -30,11 +30,17 @@
print('Running tests in develop mode. Appending repository directory to system path.')
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+ import test_species
+ import test_parameter
+ import test_reaction
import test_model
import test_solver
#import test_mincde
modules = [
+ test_species,
+ test_parameter,
+ test_reaction,
test_model,
test_solver,
#test_mincde,
diff --git a/test/test_parameter.py b/test/test_parameter.py
new file mode 100644
index 00000000..3d7299b9
--- /dev/null
+++ b/test/test_parameter.py
@@ -0,0 +1,105 @@
+'''
+SpatialPy is a Python 3 package for simulation of
+spatial deterministic/stochastic reaction-diffusion-advection problems
+Copyright (C) 2021 SpatialPy developers.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU GENERAL PUBLIC LICENSE Version 3 as
+published by the Free Software Foundation.
+
+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 Version 3 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
+import unittest
+
+import spatialpy
+from spatialpy import Parameter
+from spatialpy import ParameterError
+
+class TestParameter(unittest.TestCase):
+ '''
+ ################################################################################################
+ Unit tests for spatialpy.Parameter.
+ ################################################################################################
+ '''
+ def test_constructor(self):
+ """ Test the Parameter constructor. """
+ parameter = Parameter(name="test_parameter", expression="0.5")
+ self.assertEqual(parameter.name, "test_parameter")
+ self.assertEqual(parameter.expression, "0.5")
+
+
+ def test_constructor__no_name(self):
+ """ Test the Parameter constructor without name. """
+ with self.assertRaises(ParameterError):
+ parameter = Parameter(expression="0.5")
+
+
+ def test_constructor__name_not_str(self):
+ """ Test the Parameter constructor with non-str name. """
+ with self.assertRaises(ParameterError):
+ parameter = Parameter(name=0, expression="0.5")
+
+
+ def test_constructor__no_expression(self):
+ """ Test the Parameter constructor without expression. """
+ with self.assertRaises(ParameterError):
+ parameter = Parameter(name="test_parameter")
+
+
+ def test_constructor__int_expression(self):
+ """ Test the Parameter constructor with int expression. """
+ parameter = Parameter(name="test_parameter", expression=1)
+ self.assertEqual(parameter.expression, "1")
+
+
+ def test_constructor__float_expression(self):
+ """ Test the Parameter constructor with float expression. """
+ parameter = Parameter(name="test_parameter", expression=0.5)
+ self.assertEqual(parameter.expression, "0.5")
+
+
+ def test___str___(self):
+ """ Test Parameter.__str__ method. """
+ parameter = Parameter(name="test_parameter", expression="0.5")
+ self.assertIsInstance(str(parameter), str)
+
+
+ def test__evaluate(self):
+ """ Test Parameter._evaluate method. """
+ parameter = Parameter(name="test_parameter", expression="0.5")
+ parameter._evaluate()
+ self.assertEqual(parameter.value, 0.5)
+
+
+ def test__evaluate__parameter_in_namespace(self):
+ """ Test Parameter._evaluate method with parameter in namespace. """
+ parameter = Parameter(name="test_parameter", expression="k1 + 0.5")
+ parameter._evaluate(namespace={"k1": 3})
+ self.assertEqual(parameter.value, 3.5)
+
+
+ def test__evaluate__species_in_namespace(self):
+ """ Test Parameter._evaluate method with species in namespace. """
+ parameter = Parameter(name="test_parameter", expression="S0 + 0.5")
+ parameter._evaluate(namespace={"S0": 100})
+ self.assertEqual(parameter.value, 100.5)
+
+
+ def test__evaluate__improper_expression(self):
+ """ Test Parameter._evaluate method with invalid expression. """
+ parameter = Parameter(name="test_parameter", expression="[0.5]")
+ with self.assertRaises(ParameterError):
+ parameter._evaluate()
+
+
+ def test__evaluate__param_not_in_namespace(self):
+ """ Test Parameter._evaluate method with arg missing from namespace. """
+ parameter = Parameter(name="test_parameter", expression="k1 + 0.5")
+ with self.assertRaises(ParameterError):
+ parameter._evaluate()
diff --git a/test/test_reaction.py b/test/test_reaction.py
new file mode 100644
index 00000000..0d342849
--- /dev/null
+++ b/test/test_reaction.py
@@ -0,0 +1,168 @@
+'''
+SpatialPy is a Python 3 package for simulation of
+spatial deterministic/stochastic reaction-diffusion-advection problems
+Copyright (C) 2021 SpatialPy developers.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU GENERAL PUBLIC LICENSE Version 3 as
+published by the Free Software Foundation.
+
+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 Version 3 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
+import unittest
+
+import spatialpy
+from spatialpy import Reaction
+from spatialpy import ReactionError
+
+class TestReaction(unittest.TestCase):
+ '''
+ ################################################################################################
+ Unit tests for spatialpy.Reaction.
+ ################################################################################################
+ '''
+ def test_constructor__mass_action(self):
+ """ Test the Reaction constructor for a mass action reaction. """
+ test_reactants = {"A": 1, "B": 1}
+ test_products = {"C": 1}
+ test_rate = "k1"
+ reaction = Reaction(name="test_reaction", reactants=test_reactants, products=test_products, rate=test_rate)
+ self.assertEqual(reaction.name, "test_reaction")
+ self.assertEqual(reaction.reactants, test_reactants)
+ self.assertEqual(reaction.products, test_products)
+ self.assertEqual(reaction.rate, test_rate)
+
+
+ def test_constructor__custom_propensity(self):
+ """ Test the Reaction constructor for a custom propensity reaction. """
+ test_reactants = {"A": 1, "B": 1}
+ test_products = {"C": 1}
+ test_propensity = "k1 * A * B"
+ reaction = Reaction(
+ name="test_reaction", reactants=test_reactants, products=test_products, propensity_function=test_propensity
+ )
+ self.assertEqual(reaction.name, "test_reaction")
+ self.assertEqual(reaction.reactants, test_reactants)
+ self.assertEqual(reaction.products, test_products)
+ self.assertEqual(reaction.propensity_function, test_propensity)
+
+
+ def test_constructor__name_not_str(self):
+ """ Test the Reaction constructor with non-str name. """
+ test_reactants = {"A": 1, "B": 1}
+ test_products = {"C": 1}
+ test_rate = "k1"
+ with self.assertRaises(ReactionError):
+ reaction = Reaction(name=0, reactants=test_reactants, products=test_products, rate=test_rate)
+
+
+ def test_constructor__reactants_not_dict(self):
+ """ Test the Reaction constructor with non-dict reactants. """
+ test_reactants = [["C", 1]]
+ test_products = {"A": 1, "B": 1}
+ test_rate = "k2"
+ with self.assertRaises(ReactionError):
+ reaction = Reaction(name="test_reaction", reactants=test_reactants, products=test_products, rate=test_rate)
+
+ def test_constructor__products_not_dict(self):
+ """ Test the Reaction constructor with non-dict products. """
+ test_reactants = {"A": 1, "B": 1}
+ test_products = [["C", 1]]
+ test_rate = "k1"
+ with self.assertRaises(ReactionError):
+ reaction = Reaction(name="test_reaction", reactants=test_reactants, products=test_products, rate=test_rate)
+
+
+ def test_constructor__propensity_function_not_accepted_type(self):
+ """ Test the Reaction constructor with a propensity function that is not of the proper type. """
+ test_reactants = {"A": 1, "B": 1}
+ test_products = {"C": 1}
+ test_propensity = ["k1 * A * B"]
+ with self.assertRaises(ReactionError):
+ reaction = Reaction(
+ name="test_reaction", reactants=test_reactants, products=test_products, propensity_function=test_propensity
+ )
+
+
+ def test_constructor__int_propensity_function(self):
+ """ Test the Reaction constructor with an int propensity function. """
+ test_reactants = {"A": 1, "B": 1}
+ test_products = {"C": 1}
+ test_propensity = 20
+ reaction = Reaction(
+ name="test_reaction", reactants=test_reactants, products=test_products, propensity_function=test_propensity
+ )
+ self.assertIsInstance(reaction.propensity_function, str)
+ self.assertEqual(reaction.propensity_function, "20")
+
+
+ def test_constructor__float_propensity_function(self):
+ """ Test the Reaction constructor with a float propensity function. """
+ test_reactants = {"A": 1, "B": 1}
+ test_products = {"C": 1}
+ test_propensity = 0.5
+ reaction = Reaction(
+ name="test_reaction", reactants=test_reactants, products=test_products, propensity_function=test_propensity
+ )
+ self.assertIsInstance(reaction.propensity_function, str)
+ self.assertEqual(reaction.propensity_function, "0.5")
+
+
+ def test_constructor__rate_not_accepted_type(self):
+ """ Test the Reaction constructor with a rate that is not of the proper type. """
+ test_reactants = {"A": 1, "B": 1}
+ test_products = {"C": 1}
+ test_rate = ["k1"]
+ with self.assertRaises(ReactionError):
+ reaction = Reaction(name="test_reaction", reactants=test_reactants, products=test_products, rate=test_rate)
+
+
+ def test_constructor__int_rate(self):
+ """ Test the Reaction constructor with an int rate. """
+ test_reactants = {"A": 1, "B": 1}
+ test_products = {"C": 1}
+ test_rate = 20
+ reaction = Reaction(name="test_reaction", reactants=test_reactants, products=test_products, rate=test_rate)
+ self.assertIsInstance(reaction.rate, str)
+ self.assertEqual(reaction.rate, "20")
+
+
+ def test_constructor__float_rate(self):
+ """ Test the Reaction constructor with a float rate. """
+ test_reactants = {"A": 1, "B": 1}
+ test_products = {"C": 1}
+ test_rate = 0.5
+ reaction = Reaction(name="test_reaction", reactants=test_reactants, products=test_products, rate=test_rate)
+ self.assertIsInstance(reaction.rate, str)
+ self.assertEqual(reaction.rate, "0.5")
+
+
+ def test_constructor__restrict_to_not_accepted_type(self):
+ """ Test the Reaction constructor with a restrict_to that is not the proper type. """
+ test_reactants = {"A": 1, "B": 1}
+ test_products = {"C": 1}
+ test_rate = "k1"
+ test_restrict_to = "1"
+ with self.assertRaises(ReactionError):
+ reaction = Reaction(
+ name="test_reaction", reactants=test_reactants, products=test_products,rate=test_rate, restrict_to=test_restrict_to
+ )
+
+
+ def test_constructor__int_restrict_to(self):
+ """ Test the Reaction constructor with a int restrict_to. """
+ test_reactants = {"A": 1, "B": 1}
+ test_products = {"C": 1}
+ test_rate = "k1"
+ test_restrict_to = 1
+ reaction = Reaction(
+ name="test_reaction", reactants=test_reactants, products=test_products,rate=test_rate, restrict_to=test_restrict_to
+ )
+ self.assertIsInstance(reaction.restrict_to, list)
+ self.assertEqual(reaction.restrict_to, [1])
diff --git a/test/test_solver.py b/test/test_solver.py
index 61c23bf4..53817a09 100644
--- a/test/test_solver.py
+++ b/test/test_solver.py
@@ -25,7 +25,7 @@
import unittest
import numpy
import spatialpy
-from spatialpy.expression import Expression, ExpressionConverter
+from spatialpy.solvers.build.expression import Expression, ExpressionConverter
class diffusion_debug(spatialpy.Model):
diff --git a/test/test_species.py b/test/test_species.py
new file mode 100644
index 00000000..588c14fe
--- /dev/null
+++ b/test/test_species.py
@@ -0,0 +1,91 @@
+'''
+SpatialPy is a Python 3 package for simulation of
+spatial deterministic/stochastic reaction-diffusion-advection problems
+Copyright (C) 2021 SpatialPy developers.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU GENERAL PUBLIC LICENSE Version 3 as
+published by the Free Software Foundation.
+
+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 Version 3 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
+import unittest
+
+import spatialpy
+from spatialpy import Species
+from spatialpy import SpeciesError
+
+class TestSpecies(unittest.TestCase):
+ '''
+ ################################################################################################
+ Unit tests for spatialpy.Species.
+ ################################################################################################
+ '''
+ def test_constructor(self):
+ """ Test the Species constructor. """
+ species = Species(name="test_species", diffusion_coefficient=0)
+ self.assertEqual(species.name, "test_species")
+ self.assertEqual(species.diffusion_coefficient, 0)
+
+
+ def test_constructor__no_name(self):
+ """ Test the Species constructor without name. """
+ with self.assertRaises(SpeciesError):
+ species = Species(diffusion_coefficient=0)
+
+
+ def test_constructor__name_not_str(self):
+ """ Test the Species constructor with non-str name. """
+ with self.assertRaises(SpeciesError):
+ species = Species(name=0, diffusion_coefficient=0)
+
+
+ def test_constructor__no_diffusion_coefficient(self):
+ """ Test the Species constructor without diffusion_coefficient. """
+ with self.assertRaises(SpeciesError):
+ species = Species(name="test_species")
+
+
+ def test_constructor__negative_diffusion_coefficient(self):
+ """ Test the Species constructor with negative diffusion_coefficient. """
+ with self.assertRaises(SpeciesError):
+ species = Species(name="test_species", diffusion_coefficient=-1)
+
+
+ def test_constructor__diffusion_coefficient_not_int_or_float(self):
+ """ Test the Species constructor with non-int or non-float diffusion_coefficient. """
+ with self.assertRaises(SpeciesError):
+ species = Species(name="test_species", diffusion_coefficient="0")
+
+
+ def test___str___(self):
+ """ Test Species.__str__ method. """
+ species = Species(name="test_species", diffusion_coefficient=0)
+ self.assertIsInstance(str(species), str)
+
+
+ def test_set_diffusion_coefficient(self):
+ """ Test Species.set_diffusion_coefficient method. """
+ species = Species(name="test_species", diffusion_coefficient=0)
+ species.set_diffusion_coefficient(diffusion_coefficient=1)
+ self.assertEqual(species.diffusion_coefficient, 1)
+
+
+ def test_set_diffusion_coefficient__negative_diffusion_coefficient(self):
+ """ Test Species.set_diffusion_coefficient method with negative diffusion_coefficient. """
+ species = Species(name="test_species", diffusion_coefficient=0)
+ with self.assertRaises(SpeciesError):
+ species.set_diffusion_coefficient(diffusion_coefficient=-1)
+
+
+ def test_set_diffusion_coefficient__diffusion_coefficient_not_int_or_float(self):
+ """ Test Species.set_diffusion_coefficient method with non-int or non-float diffusion_coefficient. """
+ species = Species(name="test_species", diffusion_coefficient=0)
+ with self.assertRaises(SpeciesError):
+ species.set_diffusion_coefficient(diffusion_coefficient="1")