biosim 0.0.1__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 (61) hide show
  1. biosim-0.0.1/.gitignore +25 -0
  2. biosim-0.0.1/LICENSE.txt +21 -0
  3. biosim-0.0.1/PKG-INFO +277 -0
  4. biosim-0.0.1/README.md +241 -0
  5. biosim-0.0.1/docs/PUBLIC_INTERNAL_BOUNDARY.md +20 -0
  6. biosim-0.0.1/docs/README.md +30 -0
  7. biosim-0.0.1/docs/biomodule.md +63 -0
  8. biosim-0.0.1/docs/bioworld.md +38 -0
  9. biosim-0.0.1/docs/book.md +49 -0
  10. biosim-0.0.1/docs/brain_pipeline.md +26 -0
  11. biosim-0.0.1/docs/config.md +42 -0
  12. biosim-0.0.1/docs/neuro.md +451 -0
  13. biosim-0.0.1/docs/overview.md +42 -0
  14. biosim-0.0.1/docs/plugin-development.md +178 -0
  15. biosim-0.0.1/docs/quickstart.md +89 -0
  16. biosim-0.0.1/docs/wiring.md +58 -0
  17. biosim-0.0.1/examples/README.md +43 -0
  18. biosim-0.0.1/examples/__init__.py +0 -0
  19. biosim-0.0.1/examples/basic_usage.py +33 -0
  20. biosim-0.0.1/examples/multi_module_ui_demo.py +161 -0
  21. biosim-0.0.1/examples/ui_demo.py +51 -0
  22. biosim-0.0.1/examples/visuals_demo.py +56 -0
  23. biosim-0.0.1/examples/wiring_builder_demo.py +86 -0
  24. biosim-0.0.1/examples/world_simulation.py +122 -0
  25. biosim-0.0.1/pyproject.toml +109 -0
  26. biosim-0.0.1/scripts/build_simui_frontend.sh +36 -0
  27. biosim-0.0.1/scripts/check_public_boundary.sh +19 -0
  28. biosim-0.0.1/scripts/release_pypi.sh +93 -0
  29. biosim-0.0.1/src/biosim/__about__.py +4 -0
  30. biosim-0.0.1/src/biosim/__init__.py +52 -0
  31. biosim-0.0.1/src/biosim/__main__.py +237 -0
  32. biosim-0.0.1/src/biosim/modules.py +73 -0
  33. biosim-0.0.1/src/biosim/signals.py +129 -0
  34. biosim-0.0.1/src/biosim/simui/__init__.py +18 -0
  35. biosim-0.0.1/src/biosim/simui/build.py +86 -0
  36. biosim-0.0.1/src/biosim/simui/editor_api.py +459 -0
  37. biosim-0.0.1/src/biosim/simui/graph.py +442 -0
  38. biosim-0.0.1/src/biosim/simui/interface.py +518 -0
  39. biosim-0.0.1/src/biosim/simui/registry.py +276 -0
  40. biosim-0.0.1/src/biosim/simui/runner.py +130 -0
  41. biosim-0.0.1/src/biosim/simui/static/app.css +1 -0
  42. biosim-0.0.1/src/biosim/simui/static/app.js +92 -0
  43. biosim-0.0.1/src/biosim/visuals.py +72 -0
  44. biosim-0.0.1/src/biosim/wiring.py +164 -0
  45. biosim-0.0.1/src/biosim/world.py +301 -0
  46. biosim-0.0.1/tests/__init__.py +3 -0
  47. biosim-0.0.1/tests/conftest.py +17 -0
  48. biosim-0.0.1/tests/test_api.py +5 -0
  49. biosim-0.0.1/tests/test_biomodules.py +40 -0
  50. biosim-0.0.1/tests/test_biosignals.py +116 -0
  51. biosim-0.0.1/tests/test_bioworld_flow.py +110 -0
  52. biosim-0.0.1/tests/test_errors.py +27 -0
  53. biosim-0.0.1/tests/test_listeners.py +25 -0
  54. biosim-0.0.1/tests/test_optional_deps.py +19 -0
  55. biosim-0.0.1/tests/test_ports_validation.py +150 -0
  56. biosim-0.0.1/tests/test_simui_spec.py +77 -0
  57. biosim-0.0.1/tests/test_visuals.py +148 -0
  58. biosim-0.0.1/tests/test_wiring_builder.py +70 -0
  59. biosim-0.0.1/tests/test_wiring_loader.py +65 -0
  60. biosim-0.0.1/tests/test_world_load_wiring.py +25 -0
  61. biosim-0.0.1/tests/test_world_load_wiring_yaml.py +19 -0
@@ -0,0 +1,25 @@
1
+ # Byte-compiled / cache
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ .pytest_cache/
6
+ .mypy_cache/
7
+ .ruff_cache/
8
+ .coverage
9
+ coverage.xml
10
+ htmlcov/
11
+
12
+ node_modules/
13
+ .venv/
14
+ dist/
15
+ build/
16
+ src/biosim/simui/_frontend/dist/
17
+
18
+ .DS_Store
19
+
20
+ # SimUI UI build outputs
21
+ packages/simui-ui/dist-static/
22
+
23
+ # Commit the built library artifacts so npm can install @biosim/simui-ui from a git SHA.
24
+ !packages/simui-ui/dist/
25
+ !packages/simui-ui/dist/**
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 BioSimulant
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
biosim-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,277 @@
1
+ Metadata-Version: 2.4
2
+ Name: biosim
3
+ Version: 0.0.1
4
+ Summary: Core simulation library for Biosimulant
5
+ Project-URL: Documentation, https://github.com/Biosimulant/biosim#readme
6
+ Project-URL: Issues, https://github.com/Biosimulant/biosim/issues
7
+ Project-URL: Source, https://github.com/Biosimulant/biosim
8
+ Author-email: Demi <bjaiye1@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE.txt
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: Implementation :: CPython
17
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
18
+ Requires-Python: >=3.10
19
+ Requires-Dist: numpy>=1.26
20
+ Provides-Extra: all
21
+ Requires-Dist: fastapi<1,>=0.110; extra == 'all'
22
+ Requires-Dist: pytest-cov>=4; extra == 'all'
23
+ Requires-Dist: pytest>=7; extra == 'all'
24
+ Requires-Dist: pyyaml>=6; extra == 'all'
25
+ Requires-Dist: tomli>=2; (python_version < '3.11') and extra == 'all'
26
+ Requires-Dist: uvicorn>=0.23; extra == 'all'
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest-cov>=4; extra == 'dev'
29
+ Requires-Dist: pytest>=7; extra == 'dev'
30
+ Requires-Dist: pyyaml>=6; extra == 'dev'
31
+ Requires-Dist: tomli>=2; (python_version < '3.11') and extra == 'dev'
32
+ Provides-Extra: ui
33
+ Requires-Dist: fastapi<1,>=0.110; extra == 'ui'
34
+ Requires-Dist: uvicorn>=0.23; extra == 'ui'
35
+ Description-Content-Type: text/markdown
36
+
37
+ # biosim
38
+
39
+ [![PyPI - Version](https://img.shields.io/pypi/v/biosim.svg)](https://pypi.org/project/biosim)
40
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/biosim.svg)](https://pypi.org/project/biosim)
41
+
42
+ Composable simulation runtime + UI layer for orchestrating runnable biomodules.
43
+
44
+ ---
45
+
46
+ ## Executive Summary & System Goals
47
+
48
+ ### Vision
49
+
50
+ Provide a small, stable composition layer for simulations: wire reusable components ("biomodules") into a `BioWorld`, run them with a single orchestration contract, and visualize/debug runs via a lightweight web UI (SimUI). Biomodules are self-contained Python packages that can wrap external simulators internally (SBML/NeuroML/CellML/etc.) without a separate adapter layer.
51
+
52
+ ### Core Mission
53
+
54
+ - Compose simulations from reusable, interoperable biomodules.
55
+ - Make "run + visualize + share a config" the default workflow (local-first; hosted later).
56
+ - Keep the runtime small and predictable while letting biomodules embed their own simulator/tooling.
57
+
58
+ ### Primary Users
59
+
60
+ - Developers and researchers who need composable simulation workflows and fast iteration.
61
+ - Near-term beachhead: neuroscience demos (single neuron + small E/I microcircuits) with strong visuals and reproducible configs.
62
+
63
+ ---
64
+
65
+ ## Installation
66
+
67
+ Preferred (pinned GitHub ref):
68
+
69
+ ```console
70
+ pip install "biosim @ git+https://github.com/<org>/biosim.git@<ref>"
71
+ ```
72
+
73
+ Alternative (package index):
74
+
75
+ ```console
76
+ pip install biosim
77
+ ```
78
+
79
+ ## Publishing to PyPI
80
+
81
+ This repository publishes to PyPI using GitHub Trusted Publishing.
82
+
83
+ Release workflow:
84
+
85
+ 1. Update `src/biosim/__about__.py` with a new version (example: `0.0.2`).
86
+ 2. Commit and push the version bump to `main`.
87
+ 3. Create and push a matching tag (`v0.0.2`).
88
+ 4. Verify GitHub Actions `Publish to PyPI` finishes successfully.
89
+
90
+ Manual commands:
91
+
92
+ ```bash
93
+ git add src/biosim/__about__.py
94
+ git commit -m "Bump version to 0.0.2"
95
+ git push origin main
96
+ git tag v0.0.2
97
+ git push origin v0.0.2
98
+ ```
99
+
100
+ Automation script:
101
+
102
+ ```bash
103
+ bash scripts/release_pypi.sh
104
+ ```
105
+
106
+ - This reads the version from `src/biosim/__about__.py`, requires a clean git tree, pushes `main`, then creates and pushes `v<version>`.
107
+ - You can also pass an explicit version: `bash scripts/release_pypi.sh 0.0.2`.
108
+ - Use `--no-push` to only create the local tag: `bash scripts/release_pypi.sh --no-push`.
109
+
110
+ ## Examples
111
+
112
+ - See `examples/` for quick-start scripts. Try:
113
+
114
+ ```bash
115
+ pip install -e .
116
+ python examples/basic_usage.py
117
+ ```
118
+
119
+ For advanced curated demos (neuro/ecology), wiring configs, and model-pack templates, see the companion repo:
120
+
121
+ - https://github.com/Biosimulant/models
122
+
123
+ ### Quick Start: BioWorld
124
+
125
+ Minimal usage:
126
+
127
+ ```python
128
+ import biosim
129
+ from biosim import BioSignal, SignalMetadata
130
+
131
+ class Counter(biosim.BioModule):
132
+ min_dt = 0.1
133
+
134
+ def __init__(self):
135
+ self.value = 0
136
+
137
+ def reset(self) -> None:
138
+ self.value = 0
139
+
140
+ def advance_to(self, t: float) -> None:
141
+ self.value += 1
142
+
143
+ def get_outputs(self):
144
+ source = getattr(self, "_world_name", "counter")
145
+ return {
146
+ "count": BioSignal(
147
+ source=source,
148
+ name="count",
149
+ value=self.value,
150
+ time=0.0,
151
+ metadata=SignalMetadata(units="1", description="tick counter"),
152
+ )
153
+ }
154
+
155
+ world = biosim.BioWorld()
156
+ world.add_biomodule("counter", Counter())
157
+ world.run(duration=1.0, tick_dt=0.1)
158
+ ```
159
+
160
+ ### Visuals from Modules
161
+
162
+ Modules may optionally expose web-native visuals via `visualize()`, returning a dict or list of dicts with keys `render` and `data`. The world can collect them without any transport layer:
163
+
164
+ ```python
165
+ class MyModule(biosim.BioModule):
166
+ min_dt = 0.1
167
+
168
+ def advance_to(self, t: float) -> None:
169
+ return
170
+
171
+ def get_outputs(self):
172
+ return {}
173
+
174
+ def visualize(self):
175
+ return {
176
+ "render": "timeseries",
177
+ "data": {"series": [{"name": "s", "points": [[0.0, 1.0]]}]},
178
+ }
179
+
180
+ world = biosim.BioWorld()
181
+ world.add_biomodule("module", MyModule())
182
+ world.run(duration=0.1, tick_dt=0.1)
183
+ print(world.collect_visuals()) # [{"module": "module", "visuals": [...]}]
184
+ ```
185
+
186
+ See `examples/visuals_demo.py` for a minimal end-to-end example.
187
+
188
+ ## SimUI (Python-Declared UI)
189
+
190
+ SimUI lets you build and launch a small web UI entirely from Python (similar to Gradio's ergonomics), backed by FastAPI and a prebuilt React SPA that renders visuals from JSON. The frontend uses Server-Sent Events (SSE) for real-time updates.
191
+
192
+ - User usage (no Node/npm required):
193
+ - Install UI extras: `pip install -e '.[ui]'`
194
+ - Try the demo: `python examples/ui_demo.py` then open `http://127.0.0.1:7860/ui/`.
195
+ - From your own code:
196
+
197
+ ```python
198
+ from biosim.simui import Interface, Number, Button, EventLog, VisualsPanel
199
+ world = biosim.BioWorld()
200
+ ui = Interface(
201
+ world,
202
+ controls=[Number("duration", 10), Number("tick_dt", 0.1), Button("Run")],
203
+ outputs=[EventLog(), VisualsPanel()],
204
+ )
205
+ ui.launch()
206
+ ```
207
+
208
+ - The UI provides endpoints under `/ui/api/...`:
209
+ - `GET /api/spec` – UI layout (controls, outputs, modules)
210
+ - `POST /api/run` – Start a simulation run
211
+ - `GET /api/status` – Runner status (running/paused/error)
212
+ - `GET /api/state` – Full state (status + last step + modules)
213
+ - `GET /api/events` – Buffered world events (`?since_id=&limit=`)
214
+ - `GET /api/visuals` – Collected module visuals
215
+ - `GET /api/snapshot` – Full snapshot (status + visuals + events)
216
+ - `GET /api/stream` – SSE endpoint for real-time event streaming
217
+ - `POST /api/pause` – Pause running simulation
218
+ - `POST /api/resume` – Resume paused simulation
219
+ - `POST /api/reset` – Stop, reset, and clear buffers
220
+ - **Editor sub-API** (`/api/editor/...`): visual config editor for loading, saving, validating, and applying YAML wiring configs as node graphs. Endpoints include `modules`, `current`, `config`, `apply`, `validate`, `layout`, `to-yaml`, `from-yaml`, and `files`.
221
+
222
+ Per-run resets for clean visuals
223
+ - On each `Run`, the backend clears its event buffer and calls `reset()` on modules if they implement it.
224
+ - The frontend clears visuals/events before posting `/api/run`.
225
+ - To avoid overlapping charts across runs, add `reset()` to modules that accumulate history (e.g., time series points).
226
+
227
+ - Maintainer flow (building the frontend SPA):
228
+ - Edit the React/Vite app under `src/biosim/simui/_frontend/`.
229
+ - Build via Python: `python -m biosim.simui.build` (requires Node/npm). This writes `src/biosim/simui/static/app.js`.
230
+ - Alternatively: `bash scripts/build_simui_frontend.sh`.
231
+ - Packaging includes `src/biosim/simui/static/**`, so end users never need npm.
232
+
233
+ - CI packaging (recommended): run the frontend build before `python -m build` so wheels/sdists ship the bundled assets.
234
+
235
+ Troubleshooting:
236
+ - If you see `SimUI static bundle missing at .../static/app.js`, build the frontend with `python -m biosim.simui.build` (requires Node/npm) before launching. End users installing a release wheel won't see this.
237
+
238
+ ### SimUI Design Notes
239
+ - Transport: SSE (Server-Sent Events). The SPA connects to `/api/stream` for real-time updates. Polling endpoints (`/api/status`, `/api/visuals`, `/api/events`) remain available for fallback/debugging.
240
+ - Events API: `/api/events?since_id=<int>&limit=<int>` returns `{ events, next_since_id }` where `events` are appended world events and `next_since_id` is the cursor for subsequent calls.
241
+ - VisualSpec types supported now:
242
+ - `timeseries`: `data = { "series": [{ "name": str, "points": [[x, y], ...] }, ...] }`
243
+ - `bar`: `data = { "items": [{ "label": str, "value": number }, ...] }`
244
+ - `table`: `data = { "columns": [..], "rows": [[..], ...] }` or `data = { "items": [{...}, ...] }`
245
+ - `image`: `data = { "src": str, "alt"?: str, "width"?: number, "height"?: number }`
246
+ - `scatter`: scatter plot data
247
+ - `heatmap`: matrix/heatmap data
248
+ - `graph`: placeholder renderer shows counts + JSON; richer graph lib can be added later
249
+ - `custom:<type>`: custom renderer namespace for user-defined types
250
+ - unknown types: rendered as JSON fallback
251
+ - VisualSpec may also include an optional `description` (string) for hover text or captions.
252
+
253
+ ## Terminology
254
+
255
+ Understanding the core concepts is essential for working with biosim effectively.
256
+
257
+ | Term | Description |
258
+ |------|-------------|
259
+ | **BioWorld** | Runtime container that orchestrates multi-rate biomodules, routes signals, and publishes lifecycle events. |
260
+ | **BioModule** | Pluggable unit of behavior with local state. Implements the runnable contract (`setup/reset/advance_to/...`). |
261
+ | **BioSignal** | Typed, versioned data payload exchanged between modules via named ports. |
262
+ | **WorldEvent** | Runtime events emitted by the BioWorld (`STARTED`, `TICK`, `FINISHED`, etc.). |
263
+ | **Wiring** | Module connection graph. Defined programmatically, via `WiringBuilder`, or loaded from YAML/TOML configs. |
264
+ | **VisualSpec** | JSON structure returned by `module.visualize()` with `render` type and `data` payload. |
265
+
266
+ ### Event Lifecycle
267
+
268
+ Every simulation follows this sequence:
269
+ ```
270
+ STARTED -> TICK (xN) -> FINISHED
271
+ ```
272
+
273
+ `PAUSED`, `RESUMED`, `STOPPED`, and `ERROR` may also be emitted depending on runtime control flow.
274
+
275
+ ## License
276
+
277
+ MIT. See `LICENSE.txt`.
biosim-0.0.1/README.md ADDED
@@ -0,0 +1,241 @@
1
+ # biosim
2
+
3
+ [![PyPI - Version](https://img.shields.io/pypi/v/biosim.svg)](https://pypi.org/project/biosim)
4
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/biosim.svg)](https://pypi.org/project/biosim)
5
+
6
+ Composable simulation runtime + UI layer for orchestrating runnable biomodules.
7
+
8
+ ---
9
+
10
+ ## Executive Summary & System Goals
11
+
12
+ ### Vision
13
+
14
+ Provide a small, stable composition layer for simulations: wire reusable components ("biomodules") into a `BioWorld`, run them with a single orchestration contract, and visualize/debug runs via a lightweight web UI (SimUI). Biomodules are self-contained Python packages that can wrap external simulators internally (SBML/NeuroML/CellML/etc.) without a separate adapter layer.
15
+
16
+ ### Core Mission
17
+
18
+ - Compose simulations from reusable, interoperable biomodules.
19
+ - Make "run + visualize + share a config" the default workflow (local-first; hosted later).
20
+ - Keep the runtime small and predictable while letting biomodules embed their own simulator/tooling.
21
+
22
+ ### Primary Users
23
+
24
+ - Developers and researchers who need composable simulation workflows and fast iteration.
25
+ - Near-term beachhead: neuroscience demos (single neuron + small E/I microcircuits) with strong visuals and reproducible configs.
26
+
27
+ ---
28
+
29
+ ## Installation
30
+
31
+ Preferred (pinned GitHub ref):
32
+
33
+ ```console
34
+ pip install "biosim @ git+https://github.com/<org>/biosim.git@<ref>"
35
+ ```
36
+
37
+ Alternative (package index):
38
+
39
+ ```console
40
+ pip install biosim
41
+ ```
42
+
43
+ ## Publishing to PyPI
44
+
45
+ This repository publishes to PyPI using GitHub Trusted Publishing.
46
+
47
+ Release workflow:
48
+
49
+ 1. Update `src/biosim/__about__.py` with a new version (example: `0.0.2`).
50
+ 2. Commit and push the version bump to `main`.
51
+ 3. Create and push a matching tag (`v0.0.2`).
52
+ 4. Verify GitHub Actions `Publish to PyPI` finishes successfully.
53
+
54
+ Manual commands:
55
+
56
+ ```bash
57
+ git add src/biosim/__about__.py
58
+ git commit -m "Bump version to 0.0.2"
59
+ git push origin main
60
+ git tag v0.0.2
61
+ git push origin v0.0.2
62
+ ```
63
+
64
+ Automation script:
65
+
66
+ ```bash
67
+ bash scripts/release_pypi.sh
68
+ ```
69
+
70
+ - This reads the version from `src/biosim/__about__.py`, requires a clean git tree, pushes `main`, then creates and pushes `v<version>`.
71
+ - You can also pass an explicit version: `bash scripts/release_pypi.sh 0.0.2`.
72
+ - Use `--no-push` to only create the local tag: `bash scripts/release_pypi.sh --no-push`.
73
+
74
+ ## Examples
75
+
76
+ - See `examples/` for quick-start scripts. Try:
77
+
78
+ ```bash
79
+ pip install -e .
80
+ python examples/basic_usage.py
81
+ ```
82
+
83
+ For advanced curated demos (neuro/ecology), wiring configs, and model-pack templates, see the companion repo:
84
+
85
+ - https://github.com/Biosimulant/models
86
+
87
+ ### Quick Start: BioWorld
88
+
89
+ Minimal usage:
90
+
91
+ ```python
92
+ import biosim
93
+ from biosim import BioSignal, SignalMetadata
94
+
95
+ class Counter(biosim.BioModule):
96
+ min_dt = 0.1
97
+
98
+ def __init__(self):
99
+ self.value = 0
100
+
101
+ def reset(self) -> None:
102
+ self.value = 0
103
+
104
+ def advance_to(self, t: float) -> None:
105
+ self.value += 1
106
+
107
+ def get_outputs(self):
108
+ source = getattr(self, "_world_name", "counter")
109
+ return {
110
+ "count": BioSignal(
111
+ source=source,
112
+ name="count",
113
+ value=self.value,
114
+ time=0.0,
115
+ metadata=SignalMetadata(units="1", description="tick counter"),
116
+ )
117
+ }
118
+
119
+ world = biosim.BioWorld()
120
+ world.add_biomodule("counter", Counter())
121
+ world.run(duration=1.0, tick_dt=0.1)
122
+ ```
123
+
124
+ ### Visuals from Modules
125
+
126
+ Modules may optionally expose web-native visuals via `visualize()`, returning a dict or list of dicts with keys `render` and `data`. The world can collect them without any transport layer:
127
+
128
+ ```python
129
+ class MyModule(biosim.BioModule):
130
+ min_dt = 0.1
131
+
132
+ def advance_to(self, t: float) -> None:
133
+ return
134
+
135
+ def get_outputs(self):
136
+ return {}
137
+
138
+ def visualize(self):
139
+ return {
140
+ "render": "timeseries",
141
+ "data": {"series": [{"name": "s", "points": [[0.0, 1.0]]}]},
142
+ }
143
+
144
+ world = biosim.BioWorld()
145
+ world.add_biomodule("module", MyModule())
146
+ world.run(duration=0.1, tick_dt=0.1)
147
+ print(world.collect_visuals()) # [{"module": "module", "visuals": [...]}]
148
+ ```
149
+
150
+ See `examples/visuals_demo.py` for a minimal end-to-end example.
151
+
152
+ ## SimUI (Python-Declared UI)
153
+
154
+ SimUI lets you build and launch a small web UI entirely from Python (similar to Gradio's ergonomics), backed by FastAPI and a prebuilt React SPA that renders visuals from JSON. The frontend uses Server-Sent Events (SSE) for real-time updates.
155
+
156
+ - User usage (no Node/npm required):
157
+ - Install UI extras: `pip install -e '.[ui]'`
158
+ - Try the demo: `python examples/ui_demo.py` then open `http://127.0.0.1:7860/ui/`.
159
+ - From your own code:
160
+
161
+ ```python
162
+ from biosim.simui import Interface, Number, Button, EventLog, VisualsPanel
163
+ world = biosim.BioWorld()
164
+ ui = Interface(
165
+ world,
166
+ controls=[Number("duration", 10), Number("tick_dt", 0.1), Button("Run")],
167
+ outputs=[EventLog(), VisualsPanel()],
168
+ )
169
+ ui.launch()
170
+ ```
171
+
172
+ - The UI provides endpoints under `/ui/api/...`:
173
+ - `GET /api/spec` – UI layout (controls, outputs, modules)
174
+ - `POST /api/run` – Start a simulation run
175
+ - `GET /api/status` – Runner status (running/paused/error)
176
+ - `GET /api/state` – Full state (status + last step + modules)
177
+ - `GET /api/events` – Buffered world events (`?since_id=&limit=`)
178
+ - `GET /api/visuals` – Collected module visuals
179
+ - `GET /api/snapshot` – Full snapshot (status + visuals + events)
180
+ - `GET /api/stream` – SSE endpoint for real-time event streaming
181
+ - `POST /api/pause` – Pause running simulation
182
+ - `POST /api/resume` – Resume paused simulation
183
+ - `POST /api/reset` – Stop, reset, and clear buffers
184
+ - **Editor sub-API** (`/api/editor/...`): visual config editor for loading, saving, validating, and applying YAML wiring configs as node graphs. Endpoints include `modules`, `current`, `config`, `apply`, `validate`, `layout`, `to-yaml`, `from-yaml`, and `files`.
185
+
186
+ Per-run resets for clean visuals
187
+ - On each `Run`, the backend clears its event buffer and calls `reset()` on modules if they implement it.
188
+ - The frontend clears visuals/events before posting `/api/run`.
189
+ - To avoid overlapping charts across runs, add `reset()` to modules that accumulate history (e.g., time series points).
190
+
191
+ - Maintainer flow (building the frontend SPA):
192
+ - Edit the React/Vite app under `src/biosim/simui/_frontend/`.
193
+ - Build via Python: `python -m biosim.simui.build` (requires Node/npm). This writes `src/biosim/simui/static/app.js`.
194
+ - Alternatively: `bash scripts/build_simui_frontend.sh`.
195
+ - Packaging includes `src/biosim/simui/static/**`, so end users never need npm.
196
+
197
+ - CI packaging (recommended): run the frontend build before `python -m build` so wheels/sdists ship the bundled assets.
198
+
199
+ Troubleshooting:
200
+ - If you see `SimUI static bundle missing at .../static/app.js`, build the frontend with `python -m biosim.simui.build` (requires Node/npm) before launching. End users installing a release wheel won't see this.
201
+
202
+ ### SimUI Design Notes
203
+ - Transport: SSE (Server-Sent Events). The SPA connects to `/api/stream` for real-time updates. Polling endpoints (`/api/status`, `/api/visuals`, `/api/events`) remain available for fallback/debugging.
204
+ - Events API: `/api/events?since_id=<int>&limit=<int>` returns `{ events, next_since_id }` where `events` are appended world events and `next_since_id` is the cursor for subsequent calls.
205
+ - VisualSpec types supported now:
206
+ - `timeseries`: `data = { "series": [{ "name": str, "points": [[x, y], ...] }, ...] }`
207
+ - `bar`: `data = { "items": [{ "label": str, "value": number }, ...] }`
208
+ - `table`: `data = { "columns": [..], "rows": [[..], ...] }` or `data = { "items": [{...}, ...] }`
209
+ - `image`: `data = { "src": str, "alt"?: str, "width"?: number, "height"?: number }`
210
+ - `scatter`: scatter plot data
211
+ - `heatmap`: matrix/heatmap data
212
+ - `graph`: placeholder renderer shows counts + JSON; richer graph lib can be added later
213
+ - `custom:<type>`: custom renderer namespace for user-defined types
214
+ - unknown types: rendered as JSON fallback
215
+ - VisualSpec may also include an optional `description` (string) for hover text or captions.
216
+
217
+ ## Terminology
218
+
219
+ Understanding the core concepts is essential for working with biosim effectively.
220
+
221
+ | Term | Description |
222
+ |------|-------------|
223
+ | **BioWorld** | Runtime container that orchestrates multi-rate biomodules, routes signals, and publishes lifecycle events. |
224
+ | **BioModule** | Pluggable unit of behavior with local state. Implements the runnable contract (`setup/reset/advance_to/...`). |
225
+ | **BioSignal** | Typed, versioned data payload exchanged between modules via named ports. |
226
+ | **WorldEvent** | Runtime events emitted by the BioWorld (`STARTED`, `TICK`, `FINISHED`, etc.). |
227
+ | **Wiring** | Module connection graph. Defined programmatically, via `WiringBuilder`, or loaded from YAML/TOML configs. |
228
+ | **VisualSpec** | JSON structure returned by `module.visualize()` with `render` type and `data` payload. |
229
+
230
+ ### Event Lifecycle
231
+
232
+ Every simulation follows this sequence:
233
+ ```
234
+ STARTED -> TICK (xN) -> FINISHED
235
+ ```
236
+
237
+ `PAUSED`, `RESUMED`, `STOPPED`, and `ERROR` may also be emitted depending on runtime control flow.
238
+
239
+ ## License
240
+
241
+ MIT. See `LICENSE.txt`.
@@ -0,0 +1,20 @@
1
+ # Public/Internal Boundary
2
+
3
+ `bio-sim` is a public OSS repository.
4
+
5
+ ## Allowed (public)
6
+ - Runtime/library source code
7
+ - Technical design docs and API contracts
8
+ - Testing strategy and quality docs
9
+ - Example models/templates intended for public use
10
+
11
+ ## Not allowed (internal only)
12
+ - Business cases, pricing, GTM, investor/fundraising content
13
+ - Competitive strategy and commercial forecasts
14
+ - Internal operating procedures and non-public incident reports
15
+ - Secrets, service-account keys, credentials, tokens
16
+
17
+ ## Enforcement
18
+ - CI blocks commits containing common business-sensitive terms in docs.
19
+ - CI blocks commits containing detected secrets.
20
+ - Internal planning docs are stored in `biosim-platform`.
@@ -0,0 +1,30 @@
1
+ # biosim Documentation
2
+
3
+ Welcome to the biosim documentation. This guide explains the core concepts, APIs, and practical wiring patterns for building modular biological simulations.
4
+
5
+ ## Contents
6
+
7
+ - [Overview](overview.md): high-level architecture, core concepts (BioWorld, BioModule, BioSignal, SimUI)
8
+ - [Quickstart](quickstart.md): install, run, and explore
9
+ - API:
10
+ - [BioWorld](bioworld.md): orchestrator, events, run control (pause/resume/stop), signal routing
11
+ - [BioModule](biomodule.md): module interface, lifecycle, port metadata, visualization
12
+ - [Wiring](wiring.md): WiringBuilder, `build_from_spec`, and YAML/TOML loaders
13
+ - [Configuration](config.md): how to write wiring files
14
+ - [Example: Eye → LGN → SC pipeline](brain_pipeline.md)
15
+ - [Neuro packs](neuro.md): computational neuroscience modules (Izhikevich, Hodgkin-Huxley, Poisson input, synapses, monitors) — lives in the companion [`models`](https://github.com/Biosimulant/models) repo
16
+ - [Plugin Development](plugin-development.md): creating and distributing custom biomodules
17
+
18
+ See the files in this folder for a textbook-style walkthrough with code and concrete data examples.
19
+
20
+ ## SimUI
21
+
22
+ The biosim core includes a lightweight web UI (SimUI) for running and visualizing simulations. See the [README](../README.md#simui-python-declared-ui) for:
23
+ - Python-declared interface API
24
+ - Full REST + SSE endpoint reference
25
+ - Config editor sub-API for visual wiring editing
26
+ - VisualSpec render types (timeseries, bar, table, image, scatter, heatmap, graph, custom)
27
+
28
+ ## Building a single PDF
29
+ - Requirements: `pandoc` and a LaTeX engine (e.g., TeX Live)
30
+ - Status: planned (no `scripts/build_pdf.sh` in this repo yet)
@@ -0,0 +1,63 @@
1
+ # API: BioModule
2
+
3
+ BioModule encapsulates behavior with local state. It:
4
+ - Implements a runnable contract (`setup/reset/advance_to/...`).
5
+ - Receives inputs via `set_inputs(...)` and emits outputs via `get_outputs()`.
6
+ - Optionally declares connection ports for validation via `inputs()` and `outputs()`.
7
+
8
+ Signature (selected)
9
+ ```python
10
+ class BioModule:
11
+ min_dt: float # required positive value (seconds by default), defaults to 0.0
12
+
13
+ def setup(self, config: Optional[Dict[str, Any]] = None) -> None: ...
14
+ def reset(self) -> None: ...
15
+ def advance_to(self, t: float) -> None: ... # abstract
16
+ def set_inputs(self, signals: Dict[str, BioSignal]) -> None: ...
17
+ def get_outputs(self) -> Dict[str, BioSignal]: ... # abstract
18
+ def get_state(self) -> Dict[str, Any]: ...
19
+ def next_due_time(self, now: float) -> float: ... # returns now + min_dt by default
20
+ def inputs(self) -> Set[str]: ...
21
+ def outputs(self) -> Set[str]: ...
22
+ def input_schemas(self) -> Dict[str, Any]: ... # optional, for future tooling
23
+ def output_schemas(self) -> Dict[str, Any]: ... # optional, for future tooling
24
+ def visualize(self) -> Optional[VisualSpec | List[VisualSpec]]: ...
25
+ ```
26
+
27
+ Notes:
28
+ - `advance_to` and `get_outputs` are abstract (must be implemented).
29
+ - `setup` receives an optional config dict (per-module section from the world config), not the BioWorld instance.
30
+ - `next_due_time` returns `float` (not Optional); default implementation is `now + min_dt`.
31
+ - `input_schemas`/`output_schemas` return port-name-to-schema mappings; currently unused but reserved for future validation.
32
+ - `visualize` returns a VisualSpec dict or list of dicts for browser rendering (see README VisualSpec types).
33
+
34
+ Example with local state
35
+ ```python
36
+ class Eye(biosim.BioModule):
37
+ min_dt = 0.01
38
+
39
+ def __init__(self):
40
+ self.photons_seen = 0
41
+
42
+ def outputs(self):
43
+ return {"visual_stream"}
44
+
45
+ def advance_to(self, t: float) -> None:
46
+ self.photons_seen += 1
47
+
48
+ def get_outputs(self):
49
+ source = getattr(self, "_world_name", "eye")
50
+ return {
51
+ "visual_stream": biosim.BioSignal(
52
+ source=source,
53
+ name="visual_stream",
54
+ value={"count": self.photons_seen},
55
+ time=0.0,
56
+ metadata=biosim.SignalMetadata(units="1"),
57
+ )
58
+ }
59
+ ```
60
+
61
+ Typical values at runtime
62
+ - `t` -> current world time (float)
63
+ - `self.photons_seen` after two ticks -> `2`