process-bigraph 1.4.16__tar.gz → 1.4.18__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 (46) hide show
  1. {process_bigraph-1.4.16/process_bigraph.egg-info → process_bigraph-1.4.18}/PKG-INFO +7 -2
  2. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/README.md +5 -0
  3. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/__init__.py +1 -1
  4. process_bigraph-1.4.18/process_bigraph/bundle.py +179 -0
  5. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/composite.py +172 -616
  6. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/protocols/__init__.py +0 -3
  7. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/protocols/ray.py +211 -22
  8. process_bigraph-1.4.18/process_bigraph/scheduling.py +519 -0
  9. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/types/process.py +86 -7
  10. {process_bigraph-1.4.16 → process_bigraph-1.4.18/process_bigraph.egg-info}/PKG-INFO +7 -2
  11. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph.egg-info/SOURCES.txt +1 -3
  12. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph.egg-info/requires.txt +1 -1
  13. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/pyproject.toml +5 -2
  14. process_bigraph-1.4.16/process_bigraph/bundle.py +0 -484
  15. process_bigraph-1.4.16/process_bigraph/processes/math_expression.py +0 -525
  16. process_bigraph-1.4.16/process_bigraph/protocols/socket.py +0 -2
  17. process_bigraph-1.4.16/process_bigraph/units.py +0 -25
  18. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/AUTHORS.md +0 -0
  19. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/LICENSE +0 -0
  20. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/emitter.py +0 -0
  21. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/experiments/__init__.py +0 -0
  22. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/experiments/minimal_gillespie.py +0 -0
  23. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/nextflow.py +0 -0
  24. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/plumbing.py +0 -0
  25. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/processes/__init__.py +0 -0
  26. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/processes/bigraphical_reactive_system.py +0 -0
  27. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/processes/dynamic_structure.py +0 -0
  28. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/processes/examples.py +0 -0
  29. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/processes/growth_division.py +0 -0
  30. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/processes/parameter_scan.py +0 -0
  31. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/processes/reaction.py +0 -0
  32. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/protocols/clusters/__init__.py +0 -0
  33. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/protocols/clusters/ec2_ssm.py +0 -0
  34. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/protocols/parallel.py +0 -0
  35. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/protocols/pool.py +0 -0
  36. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/protocols/rest.py +0 -0
  37. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/protocols/session.py +0 -0
  38. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/run.py +0 -0
  39. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/run_step.py +0 -0
  40. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/server/__init__.py +0 -0
  41. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/server/rest.py +0 -0
  42. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/server/start.py +0 -0
  43. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph/types/__init__.py +0 -0
  44. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph.egg-info/dependency_links.txt +0 -0
  45. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/process_bigraph.egg-info/top_level.txt +0 -0
  46. {process_bigraph-1.4.16 → process_bigraph-1.4.18}/setup.cfg +0 -0
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: process-bigraph
3
- Version: 1.4.16
3
+ Version: 1.4.18
4
4
  Summary: protocol and execution for compositional systems biology
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
7
7
  License-File: LICENSE
8
8
  License-File: AUTHORS.md
9
- Requires-Dist: bigraph-schema>=1.2.3
9
+ Requires-Dist: bigraph-schema>=1.4.2
10
10
  Requires-Dist: matplotlib
11
11
  Requires-Dist: pint>=0.24.4
12
12
  Requires-Dist: scipy>=1.8
@@ -150,6 +150,11 @@ Live test report: https://vivarium-collective.github.io/spatio-flux/report/index
150
150
  - **E. coli Whole-Cell Wiring Diagram**
151
151
  https://raw.githubusercontent.com/vivarium-collective/bigraph-viz/main/doc/_static/ecoli.png
152
152
 
153
+ - **Claude Code skills** — wrap simulators, compose `pbg-*` packages, and
154
+ scaffold process-bigraph research workspaces with the
155
+ [**pbg-superpowers**](https://github.com/vivarium-collective/pbg-superpowers)
156
+ Claude Code plugin (install with `/plugin install pbg-superpowers`).
157
+
153
158
  ---
154
159
 
155
160
  ## 📜 License
@@ -124,6 +124,11 @@ Live test report: https://vivarium-collective.github.io/spatio-flux/report/index
124
124
  - **E. coli Whole-Cell Wiring Diagram**
125
125
  https://raw.githubusercontent.com/vivarium-collective/bigraph-viz/main/doc/_static/ecoli.png
126
126
 
127
+ - **Claude Code skills** — wrap simulators, compose `pbg-*` packages, and
128
+ scaffold process-bigraph research workspaces with the
129
+ [**pbg-superpowers**](https://github.com/vivarium-collective/pbg-superpowers)
130
+ Claude Code plugin (install with `/plugin install pbg-superpowers`).
131
+
127
132
  ---
128
133
 
129
134
  ## 📜 License
@@ -3,7 +3,7 @@ from bigraph_schema import allocate_core
3
3
  from process_bigraph.composite import (
4
4
  Process, Step, Composite, TimingSummary, interval_time_precision, wire_step_layers,
5
5
  )
6
- from process_bigraph.bundle import save_bundle, load_bundle
6
+ from process_bigraph.bundle import load_bundle
7
7
  from process_bigraph.emitter import Emitter, gather_emitter_results, generate_emitter_state
8
8
  from process_bigraph.types import StepLink, ProcessLink, CompositeLink
9
9
 
@@ -0,0 +1,179 @@
1
+ """
2
+ bundle.py — Bundle loading for composite documents.
3
+
4
+ A bundle is a directory containing:
5
+ document.json — the composite document with large arrays replaced
6
+ by ``{"$bundle_ref": "arrays/<hash>.parquet"}`` markers
7
+ arrays/ — externalized arrays as Parquet files
8
+
9
+ This module provides the bundle *load* path — ``_load_array_parquet`` plus
10
+ ``resolve_refs`` / ``load_bundle``. The matching *write* primitive,
11
+ ``_save_array_parquet``, lives in ``bigraph_schema.methods.bundle`` (the layer
12
+ that owns the bundle format via ``BundleContext`` + the dispatched ``bundle``
13
+ method); the two are a format pair and must stay in sync. The save *path* is
14
+ driven by ``Composite.save_bundle`` → ``core.bundle`` + ``BundleContext``.
15
+
16
+ The format is designed to be:
17
+ - Language-independent (Parquet is readable from Python, R, Rust, Java, …)
18
+ - Self-contained (everything needed to reconstruct the composite)
19
+ - Human-inspectable (document.json is small enough to open in an editor)
20
+ """
21
+
22
+ import json
23
+ import os
24
+ from typing import Any, Dict
25
+
26
+ import numpy as np
27
+
28
+
29
+ # ---------------------------------------------------------------------------
30
+ # Constants
31
+ # ---------------------------------------------------------------------------
32
+
33
+ ARRAY_DIR = 'arrays'
34
+ DOCUMENT_FILE = 'document.json'
35
+ REF_KEY = '$bundle_ref'
36
+
37
+ # Minimum estimated JSON size (bytes) before an array gets externalized.
38
+ # 10 KB — small arrays stay inline for readability.
39
+ MIN_ARRAY_BYTES = 10_000
40
+
41
+
42
+ # ---------------------------------------------------------------------------
43
+ # Parquet array reading (the writer is bigraph_schema.methods.bundle)
44
+ # ---------------------------------------------------------------------------
45
+
46
+ def _load_array_parquet(filepath: str) -> np.ndarray:
47
+ """Load a numpy array from a Parquet file written by
48
+ ``bigraph_schema.methods.bundle._save_array_parquet`` (the format pair)."""
49
+ import pyarrow.parquet as pq
50
+
51
+ # Use ParquetFile.read() rather than pq.read_table: the latter
52
+ # auto-infers hive partition columns from the path (e.g.
53
+ # ``variant=0/seed=1/...``) and appends them to every table read,
54
+ # which both clobbers metadata and adds spurious data columns.
55
+ table = pq.ParquetFile(filepath).read()
56
+ meta = table.schema.metadata or {}
57
+
58
+ # Check for binary blob format (3D+ arrays)
59
+ col_names = table.column_names
60
+ if col_names == ['data', 'shape', 'dtype']:
61
+ shape = json.loads(table.column('shape')[0].as_py())
62
+ dtype = np.dtype(table.column('dtype')[0].as_py())
63
+ data = table.column('data')[0].as_py()
64
+ # np.frombuffer returns a read-only view; copy to make writable
65
+ return np.frombuffer(data, dtype=dtype).reshape(shape).copy()
66
+
67
+ # Check for structured array
68
+ if b'bundle_structured' in meta:
69
+ import ast
70
+ struct_meta = json.loads(meta[b'bundle_structured'].decode())
71
+ dtype = np.dtype(ast.literal_eval(struct_meta['dtype']))
72
+ subarray_fields = struct_meta.get('subarray_fields', {})
73
+
74
+ n_rows = table.num_rows
75
+ result = np.zeros(n_rows, dtype=dtype)
76
+
77
+ for name in dtype.names:
78
+ if name in subarray_fields:
79
+ # Reconstruct sub-array from flattened columns
80
+ info = subarray_fields[name]
81
+ sub_count = info['count']
82
+ sub_shape = info['shape']
83
+ cols = [table.column(f'{name}.{i}').to_numpy()
84
+ for i in range(sub_count)]
85
+ flat = np.column_stack(cols)
86
+ result[name] = flat.reshape((n_rows,) + tuple(sub_shape))
87
+ elif dtype[name].kind == 'U':
88
+ result[name] = table.column(name).to_pylist()
89
+ else:
90
+ result[name] = table.column(name).to_numpy()
91
+
92
+ return result
93
+
94
+ # Dense numeric array
95
+ dtype_str = meta.get(b'dtype', b'float64').decode()
96
+ shape_str = meta.get(b'shape', b'null').decode()
97
+ dtype = np.dtype(dtype_str)
98
+
99
+ if len(col_names) == 1:
100
+ arr = table.column('c0').to_numpy().astype(dtype)
101
+ else:
102
+ cols = [table.column(f'c{i}').to_numpy() for i in range(len(col_names))]
103
+ arr = np.column_stack(cols).astype(dtype)
104
+
105
+ if shape_str != 'null':
106
+ shape = json.loads(shape_str)
107
+ arr = arr.reshape(shape)
108
+
109
+ return arr
110
+
111
+
112
+ # ---------------------------------------------------------------------------
113
+ # Resolve $bundle_ref markers back into data
114
+ # ---------------------------------------------------------------------------
115
+
116
+ def resolve_refs(
117
+ document: Dict[str, Any],
118
+ bundle_dir: str,
119
+ as_numpy: bool = False,
120
+ ) -> Dict[str, Any]:
121
+ """Walk *document* and replace ``$bundle_ref`` markers with loaded data.
122
+
123
+ Args:
124
+ document: The document dict (from document.json).
125
+ bundle_dir: Path to the bundle directory.
126
+ as_numpy: If True, return numpy arrays directly. If False (default),
127
+ return nested Python lists (for passing to Composite constructor
128
+ which handles realize).
129
+ """
130
+
131
+ def _walk(node):
132
+ if isinstance(node, dict):
133
+ if REF_KEY in node:
134
+ ref_path = os.path.join(bundle_dir, node[REF_KEY])
135
+ arr = _load_array_parquet(ref_path)
136
+ if node.get('structured'):
137
+ # Reconstruct __structured_array__ format for
138
+ # downstream deserializers that expect it
139
+ if as_numpy:
140
+ return arr
141
+ return {
142
+ '__structured_array__': True,
143
+ 'dtype': str(arr.dtype),
144
+ 'data': [list(row) for row in arr.tolist()],
145
+ }
146
+ if as_numpy:
147
+ return arr
148
+ return arr.tolist()
149
+ return {k: _walk(v) for k, v in node.items()}
150
+ if isinstance(node, list):
151
+ return [_walk(item) for item in node]
152
+ return node
153
+
154
+ return _walk(document)
155
+
156
+
157
+ # ---------------------------------------------------------------------------
158
+ # Public API: load_bundle (the save path lives on Composite.save_bundle)
159
+ # ---------------------------------------------------------------------------
160
+
161
+ def load_bundle(
162
+ bundle_dir: str,
163
+ as_numpy: bool = False,
164
+ ) -> Dict[str, Any]:
165
+ """Load a composite document from a bundle directory.
166
+
167
+ Args:
168
+ bundle_dir: Path to the bundle directory.
169
+ as_numpy: If True, arrays are returned as numpy arrays.
170
+ If False, as nested Python lists (for Composite constructor).
171
+
172
+ Returns:
173
+ The fully resolved document dict.
174
+ """
175
+ doc_path = os.path.join(bundle_dir, DOCUMENT_FILE)
176
+ with open(doc_path, 'r') as f:
177
+ document = json.load(f)
178
+
179
+ return resolve_refs(document, bundle_dir, as_numpy=as_numpy)