diff --git a/process_bigraph/__init__.py b/process_bigraph/__init__.py index a3c439b..479b0ca 100644 --- a/process_bigraph/__init__.py +++ b/process_bigraph/__init__.py @@ -1,12 +1,13 @@ import pprint -from bigraph_schema.registry import deep_merge, default from process_bigraph.processes import register_processes from process_bigraph.composite import Process, Step, Composite, ProcessTypes, interval_time_precision +from process_bigraph.process_types import process_types_registry pretty = pprint.PrettyPrinter(indent=2) + def pp(x): """Print ``x`` in a pretty format.""" pretty.pprint(x) @@ -40,9 +41,12 @@ def register_types(core): 'rates': 'map[float]', 'species': 'map[float]'}) - core = register_processes( - core) + core = register_processes(core) return core +# Make the core process types +process_types_core = ProcessTypes() +process_types_core = register_types(process_types_core) +process_types_registry.register('core', process_types_core) diff --git a/process_bigraph/composite.py b/process_bigraph/composite.py index fe496e6..c18f0d3 100644 --- a/process_bigraph/composite.py +++ b/process_bigraph/composite.py @@ -11,7 +11,9 @@ from typing import Dict from bigraph_schema import Edge, TypeSystem, get_path, set_path, deep_merge, is_schema_key, strip_schema_keys, Registry, hierarchy_depth, visit_method +from sympy.testing.pytest import RaisesContext +from process_bigraph.process_types import process_types_registry from process_bigraph.protocols import local_lookup, local_lookup_module @@ -96,7 +98,7 @@ def serialize_process(schema, value, core): return process -def deserialize_process(schema, encoded, core): +def deserialize_process(schema, encoded, core_type='core', core=None): """Deserialize a process from a serialized state. This function is used by the type system to deserialize a process. @@ -123,6 +125,9 @@ def deserialize_process(schema, encoded, core): if 'instance' in deserialized: instantiate = type(deserialized['instance']) else: + if core is None: + Exception('core not found') + process_lookup = core.protocol_registry.access(protocol) if not process_lookup: raise Exception(f'protocol "{protocol}" not implemented') @@ -146,9 +151,10 @@ def deserialize_process(schema, encoded, core): 'interval')) if not 'instance' in deserialized: - process = instantiate( - config, - core=core) + # assign the process a core and initialize + # TODO -- how do we assign core to process...? + instantiate.core = core + process = instantiate(config) deserialized['instance'] = process @@ -187,7 +193,8 @@ def deserialize_step(schema, encoded, core): deserialized.get('config', {})) if not 'instance' in deserialized: - process = instantiate(config, core=core) + instantiate.core = core + process = instantiate(config) deserialized['instance'] = process deserialized['config'] = config @@ -345,13 +352,11 @@ class Step(Edge): """ # TODO: support trigger every time as well as dependency trigger config_schema = {} + core = None - - def __init__(self, config=None, core=None): - if core is None: - raise Exception('must provide a core') - - self.core = core + def __init__(self, config=None, core_type='core'): + if not self.core: + self.core = process_types_registry.access(core_type) if config is None: config = {} @@ -393,12 +398,11 @@ class can provide a ``defaults`` class variable to specify the also contain the following special keys (TODO): """ config_schema = {} + core = None - def __init__(self, config=None, core=None): - if core is None: - raise Exception('must provide a core') - - self.core = core + def __init__(self, config=None, core_type='core'): + if not self.core: + self.core = process_types_registry.access(core_type) if config is None: config = {} @@ -408,6 +412,9 @@ def __init__(self, config=None, core=None): # if key not in self.config_schema: # raise Exception(f'config key {key} not in config_schema for {self.__class__.__name__}') + if self.core is None: + raise Exception(f'core {core_type} not found') + # fill in defaults for config self.config = self.core.fill( self.config_schema, @@ -747,19 +754,18 @@ class Composite(Process): @classmethod - def load(cls, path, core=None): + def load(cls, path, core_type='core'): with open(path) as data: document = json.load(data) composite = cls( - document, - core=core) + document, core_type=core_type) return composite - def __init__(self, config=None, core=None): - super().__init__(config, core) + def __init__(self, config=None, core_type='core'): + super().__init__(config, core_type=core_type) # insert global_time into schema if not present initial_composition = self.config.get('composition', {}) diff --git a/process_bigraph/experiments/growth_division.py b/process_bigraph/experiments/growth_division.py index 634c508..b072cb6 100644 --- a/process_bigraph/experiments/growth_division.py +++ b/process_bigraph/experiments/growth_division.py @@ -7,8 +7,8 @@ class Grow(Process): 'rate': 'float'} - def __init__(self, config, core=None): - super().__init__(config, core) + def __init__(self, config): + super().__init__(config) def inputs(self): @@ -41,8 +41,8 @@ class Divide(Step): '_default': 2}} - def __init__(self, config, core=None): - super().__init__(config, core) + def __init__(self, config): + super().__init__(config) def inputs(self): diff --git a/process_bigraph/experiments/minimal_gillespie.py b/process_bigraph/experiments/minimal_gillespie.py index a81f2d4..4752bef 100644 --- a/process_bigraph/experiments/minimal_gillespie.py +++ b/process_bigraph/experiments/minimal_gillespie.py @@ -87,8 +87,8 @@ class GillespieEvent(Process): '_default': '1e-1'}} - def __init__(self, config=None, core=None): - super().__init__(config, core) + def __init__(self, config=None): + super().__init__(config) self.stoichiometry = np.array([[0, 1], [0, -1]]) diff --git a/process_bigraph/process_types.py b/process_bigraph/process_types.py index f2abe43..b7bb4b0 100644 --- a/process_bigraph/process_types.py +++ b/process_bigraph/process_types.py @@ -5,6 +5,10 @@ import copy from bigraph_schema import Edge, deep_merge, visit_method +from bigraph_schema.registry import Registry + + +process_types_registry = Registry() def apply_process(schema, current, update, core): diff --git a/process_bigraph/processes/__init__.py b/process_bigraph/processes/__init__.py index e6b3983..d078a77 100644 --- a/process_bigraph/processes/__init__.py +++ b/process_bigraph/processes/__init__.py @@ -1,6 +1,5 @@ from process_bigraph.processes.parameter_scan import ToySystem, ODE, RunProcess, ParameterScan from process_bigraph.experiments.growth_division import Grow, Divide -from process_bigraph.experiments.minimal_gillespie import GillespieInterval, GillespieEvent def register_processes(core): @@ -12,7 +11,4 @@ def register_processes(core): core.register_process('grow', Grow) core.register_process('divide', Divide) - core.register_process('GillespieInterval', GillespieInterval) - core.register_process('GillespieEvent', GillespieEvent) - return core diff --git a/process_bigraph/tests.py b/process_bigraph/tests.py index c5b44eb..10b1ff2 100644 --- a/process_bigraph/tests.py +++ b/process_bigraph/tests.py @@ -43,7 +43,7 @@ def update(self, state, interval): def test_default_config(core): - process = IncreaseProcess(core=core) + process = IncreaseProcess() assert process.config['rate'] == 0.1 @@ -58,7 +58,7 @@ def test_merge_collections(core): def test_process(core): - process = IncreaseProcess({'rate': 0.2}, core=core) + process = IncreaseProcess({'rate': 0.2}) interface = process.interface() state = core.fill(interface['inputs']) state = core.fill(interface['outputs']) @@ -100,7 +100,7 @@ def test_composite(core): 'interval': 1.0, 'inputs': {'level': ['value']}, 'outputs': {'level': ['value']}}, - 'value': '11.11'}}, core=core) + 'value': '11.11'}}) initial_state = {'exchange': 3.33} @@ -124,7 +124,7 @@ def test_infer(core): 'config': {'rate': '0.3'}, 'inputs': {'level': ['value']}, 'outputs': {'level': ['value']}}, - 'value': '11.11'}}, core=core) + 'value': '11.11'}}) assert composite.composition['value']['_type'] == 'float' assert composite.state['value'] == 4.4 @@ -188,7 +188,7 @@ def test_step_initialization(core): 'a': ['B'], 'b': ['C']}, 'outputs': { - 'c': ['D']}}}}, core=core) + 'c': ['D']}}}}) composite.run(0.0) assert composite.state['D'] == (13 + 21) * 21 @@ -252,8 +252,7 @@ def test_dependencies(core): 'c': ['i']}}} composite = Composite( - {'state': operation}, - core=core) + {'state': operation}) composite.run(0.0) @@ -418,9 +417,7 @@ def test_emitter(core): 'mRNA': ['mRNA'], 'interval': ['event', 'interval']}}} - gillespie = Composite( - composite_schema, - core=core) + gillespie = Composite(composite_schema) updates = gillespie.update({ 'DNA': { @@ -466,8 +463,7 @@ def test_run_process(core): 'bridge': { 'outputs': { 'results': ['A_results']}}, - 'state': state}, - core=core) + 'state': state}) results = process.update({}, 0.0) @@ -503,8 +499,7 @@ def test_nested_wires(core): 'bridge': { 'outputs': { 'results': ['A_results']}}, - 'state': state}, - core=core) + 'state': state}) results = process.update({}, 0.0) @@ -544,8 +539,7 @@ def test_parameter_scan(core): 'bridge': { 'outputs': { 'results': ['results']}}, - 'state': state}, - core=core) + 'state': state}) # TODO: make a method so we can run it directly, provide some way to get the result out # result = scan.update({}) @@ -576,8 +570,7 @@ def test_grow_divide(core): 'state': environment, 'bridge': { 'inputs': { - 'environment': ['environment']}}}, - core=core) + 'environment': ['environment']}}}) updates = composite.update({ 'environment': { @@ -700,9 +693,7 @@ def test_gillespie_composite(core): # 'mRNA': { # 'C': '21.0'}}} - gillespie = Composite( - composite_schema, - core=core) + gillespie = Composite(composite_schema) updates = gillespie.update({ 'DNA': {