process-bigraph 0.0.35__tar.gz → 0.0.37__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. {process-bigraph-0.0.35/process_bigraph.egg-info → process-bigraph-0.0.37}/PKG-INFO +1 -1
  2. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/process_bigraph/composite.py +40 -14
  3. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/process_bigraph/emitter.py +21 -20
  4. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/process_bigraph/process_types.py +8 -6
  5. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/process_bigraph/processes/parameter_scan.py +55 -43
  6. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/process_bigraph/tests.py +79 -34
  7. {process-bigraph-0.0.35 → process-bigraph-0.0.37/process_bigraph.egg-info}/PKG-INFO +1 -1
  8. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/setup.py +1 -1
  9. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/AUTHORS.md +0 -0
  10. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/LICENSE +0 -0
  11. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/README.md +0 -0
  12. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/process_bigraph/__init__.py +0 -0
  13. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/process_bigraph/experiments/__init__.py +0 -0
  14. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/process_bigraph/experiments/minimal_gillespie.py +0 -0
  15. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/process_bigraph/processes/__init__.py +0 -0
  16. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/process_bigraph/processes/growth_division.py +0 -0
  17. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/process_bigraph/protocols.py +0 -0
  18. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/process_bigraph.egg-info/SOURCES.txt +0 -0
  19. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/process_bigraph.egg-info/dependency_links.txt +0 -0
  20. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/process_bigraph.egg-info/requires.txt +0 -0
  21. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/process_bigraph.egg-info/top_level.txt +0 -0
  22. {process-bigraph-0.0.35 → process-bigraph-0.0.37}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: process-bigraph
3
- Version: 0.0.35
3
+ Version: 0.0.37
4
4
  Home-page: https://github.com/vivarium-collective/process-bigraph
5
5
  Author: Ryan Spangler, Eran Agmon
6
6
  Author-email: ryan.spangler@gmail.com, agmon.eran@gmail.com
@@ -12,7 +12,7 @@ from typing import Dict
12
12
 
13
13
  from bigraph_schema import (
14
14
  Edge, Registry,
15
- get_path, resolve_path, hierarchy_depth, deep_merge,
15
+ get_path, set_path, resolve_path, hierarchy_depth, deep_merge,
16
16
  is_schema_key, strip_schema_keys)
17
17
 
18
18
  from process_bigraph.protocols import local_lookup, local_lookup_module
@@ -482,7 +482,7 @@ class Composite(Process):
482
482
  # build the step network
483
483
  self.build_step_network()
484
484
 
485
- # self.run_steps(self.to_run)
485
+ self.run_steps(self.to_run)
486
486
 
487
487
 
488
488
  def build_step_network(self):
@@ -587,7 +587,24 @@ class Composite(Process):
587
587
  path,
588
588
  schema,
589
589
  state)
590
+ self.find_instance_paths(self.state)
590
591
 
592
+ def apply(self, update, path=None):
593
+ path = path or []
594
+ update = set_path({}, path, update)
595
+ self.state = self.core.apply(
596
+ self.composition,
597
+ self.state,
598
+ update)
599
+ self.find_instance_paths(
600
+ self.state)
601
+
602
+ def merge_schema(self, schema, path=None):
603
+ path = path or []
604
+ schema = set_path({}, path, schema)
605
+ self.composition = self.core.merge_schemas(self.composition, schema)
606
+ self.composition, self.state = self.core.generate(self.composition, self.state)
607
+ self.find_instance_paths(self.state)
591
608
 
592
609
  def process_update(
593
610
  self,
@@ -697,6 +714,20 @@ class Composite(Process):
697
714
  return full_step
698
715
 
699
716
 
717
+ def read_bridge(self, state=None):
718
+ if state is None:
719
+ state = self.state
720
+
721
+ bridge_view = self.core.view(
722
+ self.interface()['outputs'],
723
+ self.bridge['outputs'],
724
+ (),
725
+ top_schema=self.composition,
726
+ top_state=state)
727
+
728
+ return bridge_view
729
+
730
+
700
731
  def apply_updates(self, updates):
701
732
  # view_expire = False
702
733
  update_paths = []
@@ -718,15 +749,15 @@ class Composite(Process):
718
749
  self.state,
719
750
  update)
720
751
 
721
- bridge_update = self.core.view(
722
- self.interface()['outputs'],
723
- self.bridge['outputs'],
724
- (),
725
- top_schema=self.composition,
726
- top_state=update)
752
+ bridge_update = self.read_bridge(
753
+ update)
727
754
 
728
755
  if bridge_update:
729
- self.bridge_updates.append(bridge_update)
756
+ self.bridge_updates.append(
757
+ bridge_update)
758
+
759
+ self.find_instance_paths(
760
+ self.state)
730
761
 
731
762
  return update_paths
732
763
 
@@ -766,11 +797,6 @@ class Composite(Process):
766
797
 
767
798
 
768
799
  def run(self, interval, force_complete=False):
769
- # If there are steps to run, execute them
770
- if self.to_run:
771
- self.run_steps(self.to_run)
772
- self.to_run = None
773
-
774
800
  # Define the end time for the run
775
801
  end_time = self.state['global_time'] + interval
776
802
 
@@ -251,11 +251,9 @@ class RAMEmitter(Emitter):
251
251
  state=t,
252
252
  path=path)
253
253
 
254
- # element = get_path(t, path)
255
254
  result = set_path(result, path, state)
256
255
  results.append(result)
257
- # element = get_path(self.history, path)
258
- # result = set_path(result, path, element)
256
+
259
257
  else:
260
258
  results = self.history
261
259
 
@@ -363,12 +361,13 @@ def test_ram_emitter(core):
363
361
  # 'interval': 1.0,
364
362
  'inputs': {'level': ['valueB']},
365
363
  'outputs': {'level': ['valueB']}},
366
- }
367
- composite = Composite({'state': composite_spec}, core)
368
- composite = add_emitter_to_composite(composite,
369
- core,
370
- emitter_mode='all',
371
- address='local:ram-emitter')
364
+ 'emitter': emitter_from_wires({
365
+ 'time': ['global_time'],
366
+ 'valueA': ['valueA'],
367
+ 'valueB': ['valueB']})}
368
+
369
+ composite = Composite(
370
+ {'state': composite_spec}, core=core)
372
371
 
373
372
  # run the simulation
374
373
  composite.run(10)
@@ -376,15 +375,16 @@ def test_ram_emitter(core):
376
375
  # query the emitter
377
376
  results = composite.state['emitter']['instance'].query()
378
377
  assert len(results) == 11
379
- assert results[-1]['global_time'] == 10
378
+ assert results[-1]['time'] == 10
380
379
  assert 'valueA' in results[0] and 'valueB' in results[0]
381
380
  # print(results)
382
381
 
383
- composite2 = Composite({'state': composite_spec}, core)
384
- composite2 = add_emitter_to_composite(composite2,
385
- core,
386
- emitter_mode={'paths': ['valueA']},
387
- address='local:ram-emitter')
382
+ composite_spec['emitter'] = emitter_from_wires({
383
+ 'time': ['global_time'],
384
+ 'valueA': ['valueA']})
385
+
386
+ composite2 = Composite({
387
+ 'state': composite_spec}, core=core)
388
388
 
389
389
  # run the simulation
390
390
  composite2.run(10)
@@ -406,17 +406,18 @@ def test_json_emitter(core):
406
406
  'outputs': {'level': ['value']}},
407
407
  }
408
408
  composite = Composite({'state': composite_spec}, core)
409
- composite = add_emitter_to_composite(composite,
410
- core,
411
- emitter_mode='all',
412
- address='local:json-emitter')
409
+ composite = add_emitter_to_composite(
410
+ composite,
411
+ core,
412
+ emitter_mode='all',
413
+ address='local:json-emitter')
413
414
 
414
415
  # run the simulation
415
416
  composite.run(10)
416
417
 
417
418
  # query the emitter
418
419
  results = composite.state['emitter']['instance'].query()
419
- assert len(results) == 11
420
+ assert len(results) == 10
420
421
  assert results[-1]['global_time'] == 10
421
422
  print(results)
422
423
 
@@ -120,7 +120,8 @@ def deserialize_process(schema, encoded, core):
120
120
 
121
121
  protocol, address = deserialized['address'].split(':', 1)
122
122
 
123
- if 'instance' in deserialized:
123
+ existing_instance = 'instance' in deserialized and deserialized['instance']
124
+ if existing_instance:
124
125
  instantiate = type(deserialized['instance'])
125
126
  else:
126
127
  process_lookup = core.protocol_registry.access(protocol)
@@ -145,14 +146,14 @@ def deserialize_process(schema, encoded, core):
145
146
  'interval',
146
147
  'interval'))
147
148
 
148
- if not 'instance' in deserialized:
149
+ if existing_instance:
150
+ process = deserialized['instance']
151
+ else:
149
152
  process = instantiate(
150
153
  config,
151
154
  core=core)
152
155
 
153
156
  deserialized['instance'] = process
154
- else:
155
- process = deserialized['instance']
156
157
 
157
158
  # TODO: this mutating the original value directly into
158
159
  # the return value is weird (?)
@@ -189,7 +190,8 @@ def deserialize_step(schema, encoded, core):
189
190
 
190
191
  protocol, address = deserialized['address'].split(':', 1)
191
192
 
192
- if 'instance' in deserialized:
193
+ existing_instance = 'instance' in deserialized and deserialized['instance']
194
+ if existing_instance:
193
195
  instantiate = type(deserialized['instance'])
194
196
  else:
195
197
  process_lookup = core.protocol_registry.access(protocol)
@@ -204,7 +206,7 @@ def deserialize_step(schema, encoded, core):
204
206
  instantiate.config_schema,
205
207
  deserialized.get('config', {}))
206
208
 
207
- if not 'instance' in deserialized:
209
+ if not existing_instance:
208
210
  process = instantiate(config, core=core)
209
211
  deserialized['instance'] = process
210
212
 
@@ -66,6 +66,7 @@ class RunProcess(Step):
66
66
  'process_address': 'string',
67
67
  'process_config': 'tree[any]',
68
68
  'observables': 'list[path]',
69
+ 'initial_state': 'any',
69
70
  'timestep': 'float',
70
71
  'runtime': 'float'}
71
72
 
@@ -113,59 +114,68 @@ class RunProcess(Step):
113
114
  {'time': 'float'},
114
115
  **self.observables_schema)
115
116
 
116
- composite_config = {
117
+ state = copy.deepcopy(
118
+ config['initial_state'])
119
+
120
+ state['process'] = {
121
+ '_type': 'process',
122
+ 'address': self.config['process_address'],
123
+ 'config': self.config['process_config'],
124
+ 'instance': self.process,
125
+ 'interval': self.config['timestep'],
126
+ '_inputs': self.process.inputs(),
127
+ '_outputs': self.process.outputs(),
128
+ 'inputs': {
129
+ key: [key]
130
+ for key in self.process.inputs()},
131
+ 'outputs': {
132
+ key: [key]
133
+ for key in process_outputs}}
134
+
135
+ state['emitter'] = {
136
+ '_type': 'step',
137
+ '_inputs': emit_config,
138
+ 'address': 'local:ram-emitter',
139
+ 'config': {
140
+ 'emit': emit_config},
141
+ 'inputs': dict(
142
+ {'time': ['global_time']},
143
+ **self.inputs_config),
144
+ 'outputs': {}}
145
+
146
+ self.document = {
117
147
  'global_time_precision': global_time_precision,
118
- # TODO: support emitter at the composite level
119
- # they are a list of emit dicts that describe
120
- # which emitter to use and what from the composite
121
- # state will be emitted. The schema can be inferred
122
- # from the targets. ALSO: support process ports
123
- # to be targets
124
- # 'emit': [{
125
- # 'address': 'local:mongo-emitter'
126
- # 'targets': dict({'time': ['global_time']}, **{
127
- # key: [key]
128
- # for key in self.process.outputs()})}],
129
- 'state': {
130
- 'process': {
131
- '_type': 'process',
132
- 'address': self.config['process_address'],
133
- 'config': self.config['process_config'],
134
- 'instance': self.process,
135
- 'interval': self.config['timestep'],
136
- '_inputs': self.process.inputs(),
137
- '_outputs': self.process.outputs(),
138
- 'inputs': {
139
- key: [key]
140
- for key in self.process.inputs()},
141
- 'outputs': {
142
- key: [key]
143
- for key in process_outputs}},
144
- 'emitter': {
145
- '_type': 'step',
146
- '_inputs': emit_config,
147
- 'address': 'local:ram-emitter',
148
- 'config': {
149
- 'emit': emit_config},
150
- 'inputs': dict(
151
- {'time': ['global_time']},
152
- **self.inputs_config),
153
- 'outputs': {}}}}
154
-
155
- self.composite = Composite(composite_config, core=self.core)
148
+ 'state': state}
149
+
150
+ # wait to initialize until we get our first update
151
+ self.composite = None
152
+
156
153
 
157
154
  def inputs(self):
158
155
  return self.process.inputs()
159
156
 
157
+
160
158
  def outputs(self):
161
159
  return {
162
160
  'results': dict(
163
161
  {'time': 'list[float]'},
164
162
  **self.results_schema)}
165
163
 
164
+
166
165
  def update(self, inputs):
167
- # TODO: instead of the composite being a reference it is instead read through
168
- # some port and lives in the state of the simulation (??)
166
+ # TODO: instead of the composite being a reference it is
167
+ # instead read through some port and lives in
168
+ # the state of the simulation (??)
169
+
170
+ if self.composite is None:
171
+ self.document['state'] = deep_merge(
172
+ self.document['state'],
173
+ inputs)
174
+
175
+ self.composite = Composite(
176
+ self.document,
177
+ core=self.core)
178
+
169
179
  self.composite.merge(
170
180
  self.inputs(),
171
181
  inputs)
@@ -173,7 +183,8 @@ class RunProcess(Step):
173
183
  self.composite.run(
174
184
  self.config['runtime'])
175
185
 
176
- histories = gather_emitter_results(self.composite)
186
+ histories = gather_emitter_results(
187
+ self.composite)
177
188
 
178
189
  results = {
179
190
  key: timeseries_from_history(
@@ -185,7 +196,8 @@ class RunProcess(Step):
185
196
  for timeseries in results.values():
186
197
  all_results = deep_merge(all_results, timeseries)
187
198
 
188
- return {'results': all_results}
199
+ return {
200
+ 'results': all_results}
189
201
 
190
202
 
191
203
  def timeseries_from_history(history, observables):
@@ -5,8 +5,8 @@ import pytest
5
5
  import random
6
6
 
7
7
  from bigraph_schema import default
8
-
9
8
  from process_bigraph import register_types
9
+
10
10
  from process_bigraph.composite import Process, Step, Composite, merge_collections
11
11
 
12
12
  from process_bigraph.processes.growth_division import grow_divide_agent
@@ -427,18 +427,9 @@ def test_emitter(core):
427
427
  'outputs': {
428
428
  'mRNA': ['mRNA']},
429
429
  'interval': '3.0'}},
430
- 'emitter': {
431
- '_type': 'step',
432
- 'address': 'local:ram-emitter',
433
- 'inputs': {
434
- 'time': ['global_time'],
435
- 'mRNA': ['mRNA'],
436
- 'interval': ['event', 'interval']},
437
- 'config': {
438
- 'emit': {
439
- 'time': 'any',
440
- 'mRNA': 'any',
441
- 'interval': 'any'}}}}
430
+ 'emitter': emitter_from_wires({
431
+ 'mRNA': ['mRNA'],
432
+ 'interval': ['event', 'interval']})}
442
433
 
443
434
  gillespie = Composite(
444
435
  composite_schema,
@@ -466,7 +457,8 @@ def test_run_process(core):
466
457
  initial_A = 11.11
467
458
 
468
459
  state = {
469
- 'species': {'A': initial_A},
460
+ 'species': {
461
+ 'A': initial_A},
470
462
  'run': {
471
463
  '_type': 'step',
472
464
  'address': 'local:RunProcess',
@@ -480,21 +472,20 @@ def test_run_process(core):
480
472
  'observables': [['species']],
481
473
  'timestep': timestep,
482
474
  'runtime': runtime},
483
- # '_outputs': {'results': {'_emit': True}},
484
475
  'inputs': {'species': ['species']},
485
476
  'outputs': {'results': ['A_results']}}}
486
477
 
487
- process = Composite({
478
+ run = Composite({
488
479
  'bridge': {
489
480
  'outputs': {
490
481
  'results': ['A_results']}},
491
482
  'state': state},
492
483
  core=core)
493
484
 
494
- results = process.update({}, 0.0)
485
+ results = run.read_bridge()['results']
495
486
 
496
- assert results[0]['results']['time'][-1] == runtime
497
- assert results[0]['results']['species'][0]['A'] == initial_A
487
+ assert results['time'][-1] == runtime
488
+ assert results['species'][0]['A'] == initial_A
498
489
 
499
490
 
500
491
  def test_nested_wires(core):
@@ -611,8 +602,7 @@ def test_grow_divide(core):
611
602
  assert composite.state['environment']['0_0_0_0_1']['mass'] == composite.state['environment']['0_0_0_0_1']['grow_divide']['instance'].state['mass']
612
603
 
613
604
  # check recursive schema reference
614
- assert (id(composite.composition['environment']['_value']['grow_divide']) ==
615
- id(composite.composition['environment']['_value']['grow_divide']['_outputs']['environment']['_value']['grow_divide']))
605
+ assert id(composite.composition['environment'] == id(composite.composition['environment']['_value']['grow_divide']['_outputs']['environment']))
616
606
 
617
607
  composite.save('test_grow_divide_saved.json')
618
608
 
@@ -620,8 +610,7 @@ def test_grow_divide(core):
620
610
  'out/test_grow_divide_saved.json',
621
611
  core=core)
622
612
 
623
- assert (id(composite.composition['environment']['_value']['grow_divide']) ==
624
- id(composite.composition['environment']['_value']['grow_divide']['_outputs']['environment']['_value']['grow_divide']))
613
+ assert id(composite.composition['environment'] == id(composite.composition['environment']['_value']['grow_divide']['_outputs']['environment']))
625
614
 
626
615
 
627
616
  def test_gillespie_composite(core):
@@ -695,6 +684,71 @@ def test_union_tree(core):
695
684
  {'a': ['what', 'is', 'happening']})
696
685
 
697
686
 
687
+ def test_merge_schema(core):
688
+ state = {'a': 11.0}
689
+ composite = Composite({
690
+ 'state': state}, core=core)
691
+
692
+ increase_schema = {
693
+ 'increase': {
694
+ '_type': 'process',
695
+ 'address': default('string', 'local:!process_bigraph.tests.IncreaseProcess'),
696
+ 'config': default('quote', {'rate': 0.0001}),
697
+ 'inputs': default('wires', {'level': ['b']}),
698
+ 'outputs': default('wires', {'level': ['a']})}}
699
+
700
+ composite.merge(
701
+ increase_schema,
702
+ {})
703
+
704
+ # composite.merge_schema(
705
+ # increase_schema)
706
+
707
+ assert composite.composition['increase']['_type'] == 'process'
708
+ assert isinstance(composite.state['increase']['instance'], Process)
709
+
710
+ state = {
711
+ 'x': -3.33,
712
+ 'atoms': {
713
+ 'A': {
714
+ 'lll': 55}}}
715
+
716
+ composition = {
717
+ 'atoms': 'map[lll:integer]'}
718
+
719
+ merge = Composite({
720
+ 'composition': composition,
721
+ 'state': state}, core=core)
722
+
723
+ nested_increase_schema = {
724
+ 'increase': {
725
+ '_type': 'process',
726
+ 'address': default('string', 'local:!process_bigraph.tests.IncreaseProcess'),
727
+ 'config': default('quote', {'rate': 0.0001}),
728
+ 'inputs': default('wires', {'level': ['..', '..', 'b']}),
729
+ 'outputs': default('wires', {'level': ['..', '..', 'a']})}}
730
+
731
+ merge.merge(
732
+ {'atoms': {'_value': nested_increase_schema}},
733
+ {})
734
+
735
+ # TODO: do we need merge_schema if merge works for schema and state?
736
+ # merge.merge_schema(
737
+ # nested_increase_schema,
738
+ # path=['atoms', '_value'])
739
+
740
+ assert isinstance(merge.state['atoms']['A']['increase']['instance'], Process)
741
+ assert merge.composition['atoms']['_value']['increase']['_type'] == 'process'
742
+ assert ('atoms', 'A', 'increase') in merge.process_paths
743
+
744
+ merge.merge(
745
+ {},
746
+ {'atoms': {'B': {'lll': 11111}}})
747
+
748
+ assert isinstance(merge.state['atoms']['B']['increase']['instance'], Process)
749
+ assert ('atoms', 'B', 'increase') in merge.process_paths
750
+
751
+
698
752
  def test_shared_steps(core):
699
753
  initial_rate = 0.4
700
754
 
@@ -714,15 +768,6 @@ def test_shared_steps(core):
714
768
  'emitter': emitter_from_wires({
715
769
  'level': ['value']})}
716
770
 
717
- # 'emitter': {
718
- # '_type': 'step',
719
- # 'address': 'local:ram-emitter',
720
- # 'config': {
721
- # 'emit': {
722
- # 'level': 'float'}},
723
- # 'inputs': {
724
- # 'level': ['value']}}}
725
-
726
771
  shared = Composite(
727
772
  {'state': state},
728
773
  core=core)
@@ -755,11 +800,11 @@ if __name__ == '__main__':
755
800
  test_union_tree(core)
756
801
 
757
802
  test_gillespie_composite(core)
758
- test_grow_divide(core)
759
803
  test_run_process(core)
760
804
  test_nested_wires(core)
761
805
  test_parameter_scan(core)
762
806
  test_shared_steps(core)
763
807
 
764
808
  test_stochastic_deterministic_composite(core)
765
-
809
+ test_merge_schema(core)
810
+ test_grow_divide(core)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: process-bigraph
3
- Version: 0.0.35
3
+ Version: 0.0.37
4
4
  Home-page: https://github.com/vivarium-collective/process-bigraph
5
5
  Author: Ryan Spangler, Eran Agmon
6
6
  Author-email: ryan.spangler@gmail.com, agmon.eran@gmail.com
@@ -2,7 +2,7 @@ import re
2
2
  from setuptools import setup, find_packages
3
3
 
4
4
 
5
- VERSION = '0.0.35'
5
+ VERSION = '0.0.37'
6
6
 
7
7
 
8
8
  with open("README.md", "r") as readme: