biosimulant 0.0.10__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.
- biosimulant-0.0.10/.gitignore +22 -0
- biosimulant-0.0.10/LICENSE.txt +21 -0
- biosimulant-0.0.10/PKG-INFO +398 -0
- biosimulant-0.0.10/README.md +352 -0
- biosimulant-0.0.10/docs/PUBLIC_INTERNAL_BOUNDARY.md +20 -0
- biosimulant-0.0.10/docs/README.md +37 -0
- biosimulant-0.0.10/docs/biomodule.md +106 -0
- biosimulant-0.0.10/docs/bioworld.md +65 -0
- biosimulant-0.0.10/docs/book.md +49 -0
- biosimulant-0.0.10/docs/brain_pipeline.md +26 -0
- biosimulant-0.0.10/docs/cellml.md +123 -0
- biosimulant-0.0.10/docs/config.md +54 -0
- biosimulant-0.0.10/docs/kernel-1-5.md +68 -0
- biosimulant-0.0.10/docs/migration-1-5.md +70 -0
- biosimulant-0.0.10/docs/neuro.md +483 -0
- biosimulant-0.0.10/docs/overview.md +50 -0
- biosimulant-0.0.10/docs/packaging.md +196 -0
- biosimulant-0.0.10/docs/plugin-development.md +60 -0
- biosimulant-0.0.10/docs/quickstart.md +87 -0
- biosimulant-0.0.10/docs/releasing.md +58 -0
- biosimulant-0.0.10/docs/wiring.md +41 -0
- biosimulant-0.0.10/examples/README.md +43 -0
- biosimulant-0.0.10/examples/__init__.py +0 -0
- biosimulant-0.0.10/examples/basic_usage.py +33 -0
- biosimulant-0.0.10/examples/cellml_runtime_example.py +92 -0
- biosimulant-0.0.10/examples/data/small_decay.cellml +35 -0
- biosimulant-0.0.10/examples/multi_module_ui_demo.py +154 -0
- biosimulant-0.0.10/examples/ui_demo.py +50 -0
- biosimulant-0.0.10/examples/visuals_demo.py +55 -0
- biosimulant-0.0.10/examples/wiring_builder_demo.py +82 -0
- biosimulant-0.0.10/examples/world_simulation.py +124 -0
- biosimulant-0.0.10/pyproject.toml +130 -0
- biosimulant-0.0.10/scripts/build_simui_frontend.sh +36 -0
- biosimulant-0.0.10/scripts/check_public_boundary.sh +19 -0
- biosimulant-0.0.10/scripts/release_pypi.sh +93 -0
- biosimulant-0.0.10/scripts/snapshot_biomodule_outputs.py +318 -0
- biosimulant-0.0.10/src/biosim/__about__.py +4 -0
- biosimulant-0.0.10/src/biosim/__init__.py +100 -0
- biosimulant-0.0.10/src/biosim/__main__.py +438 -0
- biosimulant-0.0.10/src/biosim/contrib/__init__.py +9 -0
- biosimulant-0.0.10/src/biosim/contrib/cellml.py +878 -0
- biosimulant-0.0.10/src/biosim/contrib/sbml.py +660 -0
- biosimulant-0.0.10/src/biosim/modules.py +230 -0
- biosimulant-0.0.10/src/biosim/onnx.py +225 -0
- biosimulant-0.0.10/src/biosim/pack.py +1413 -0
- biosimulant-0.0.10/src/biosim/runtime/__init__.py +41 -0
- biosimulant-0.0.10/src/biosim/runtime/coercion.py +339 -0
- biosimulant-0.0.10/src/biosim/runtime/entrypoint.py +100 -0
- biosimulant-0.0.10/src/biosim/runtime/flatten.py +137 -0
- biosimulant-0.0.10/src/biosim/runtime/runtime_config.py +97 -0
- biosimulant-0.0.10/src/biosim/runtime/types.py +57 -0
- biosimulant-0.0.10/src/biosim/signals.py +940 -0
- biosimulant-0.0.10/src/biosim/simui/__init__.py +18 -0
- biosimulant-0.0.10/src/biosim/simui/build.py +86 -0
- biosimulant-0.0.10/src/biosim/simui/editor_api.py +459 -0
- biosimulant-0.0.10/src/biosim/simui/graph.py +442 -0
- biosimulant-0.0.10/src/biosim/simui/interface.py +584 -0
- biosimulant-0.0.10/src/biosim/simui/registry.py +274 -0
- biosimulant-0.0.10/src/biosim/simui/runner.py +186 -0
- biosimulant-0.0.10/src/biosim/simui/static/app.css +1 -0
- biosimulant-0.0.10/src/biosim/simui/static/app.js +63 -0
- biosimulant-0.0.10/src/biosim/visuals.py +72 -0
- biosimulant-0.0.10/src/biosim/wiring.py +175 -0
- biosimulant-0.0.10/src/biosim/world.py +555 -0
- biosimulant-0.0.10/src/biosimulant/__init__.py +52 -0
- biosimulant-0.0.10/src/biosimulant/__main__.py +19 -0
- biosimulant-0.0.10/src/biosimulant/simui/__init__.py +16 -0
- biosimulant-0.0.10/tests/__init__.py +3 -0
- biosimulant-0.0.10/tests/conftest.py +22 -0
- biosimulant-0.0.10/tests/snapshots/README.md +49 -0
- biosimulant-0.0.10/tests/snapshots/biomodule_refactor_fast.json +3146 -0
- biosimulant-0.0.10/tests/snapshots/biomodule_refactor_koo2013_integrated_amd64.json +1769 -0
- biosimulant-0.0.10/tests/test_api.py +5 -0
- biosimulant-0.0.10/tests/test_biomodules.py +68 -0
- biosimulant-0.0.10/tests/test_biosignals.py +125 -0
- biosimulant-0.0.10/tests/test_biosim_init.py +41 -0
- biosimulant-0.0.10/tests/test_biosimulant_namespace.py +70 -0
- biosimulant-0.0.10/tests/test_bioworld_flow.py +101 -0
- biosimulant-0.0.10/tests/test_cellml_contrib.py +410 -0
- biosimulant-0.0.10/tests/test_cli.py +365 -0
- biosimulant-0.0.10/tests/test_errors.py +27 -0
- biosimulant-0.0.10/tests/test_listeners.py +27 -0
- biosimulant-0.0.10/tests/test_modules_coverage.py +95 -0
- biosimulant-0.0.10/tests/test_onnx.py +100 -0
- biosimulant-0.0.10/tests/test_optional_deps.py +26 -0
- biosimulant-0.0.10/tests/test_pack.py +653 -0
- biosimulant-0.0.10/tests/test_ports_validation.py +157 -0
- biosimulant-0.0.10/tests/test_runtime_coercion.py +46 -0
- biosimulant-0.0.10/tests/test_runtime_config.py +55 -0
- biosimulant-0.0.10/tests/test_runtime_entrypoint.py +40 -0
- biosimulant-0.0.10/tests/test_runtime_flatten.py +61 -0
- biosimulant-0.0.10/tests/test_sbml_contrib.py +183 -0
- biosimulant-0.0.10/tests/test_signals_coverage.py +220 -0
- biosimulant-0.0.10/tests/test_simui_build.py +213 -0
- biosimulant-0.0.10/tests/test_simui_editor_api.py +473 -0
- biosimulant-0.0.10/tests/test_simui_graph.py +338 -0
- biosimulant-0.0.10/tests/test_simui_interface.py +648 -0
- biosimulant-0.0.10/tests/test_simui_registry.py +322 -0
- biosimulant-0.0.10/tests/test_simui_runner.py +228 -0
- biosimulant-0.0.10/tests/test_simui_spec.py +78 -0
- biosimulant-0.0.10/tests/test_visuals.py +147 -0
- biosimulant-0.0.10/tests/test_visuals_coverage.py +89 -0
- biosimulant-0.0.10/tests/test_wiring_builder.py +76 -0
- biosimulant-0.0.10/tests/test_wiring_coverage.py +218 -0
- biosimulant-0.0.10/tests/test_wiring_loader.py +62 -0
- biosimulant-0.0.10/tests/test_world_coverage.py +691 -0
- biosimulant-0.0.10/tests/test_world_load_wiring.py +24 -0
- biosimulant-0.0.10/tests/test_world_load_wiring_yaml.py +19 -0
|
@@ -0,0 +1,22 @@
|
|
|
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 (built automatically via prepare script)
|
|
21
|
+
packages/simui-ui/dist/
|
|
22
|
+
packages/simui-ui/dist-static/
|
|
@@ -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.
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: biosimulant
|
|
3
|
+
Version: 0.0.10
|
|
4
|
+
Summary: Open-source local simulation runtime and CLI 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: httpx>=0.26; extra == 'all'
|
|
23
|
+
Requires-Dist: libcellml<0.7,>=0.6.3; extra == 'all'
|
|
24
|
+
Requires-Dist: onnxruntime>=1.18; extra == 'all'
|
|
25
|
+
Requires-Dist: pytest-cov>=4; extra == 'all'
|
|
26
|
+
Requires-Dist: pytest>=7; extra == 'all'
|
|
27
|
+
Requires-Dist: pyyaml>=6; extra == 'all'
|
|
28
|
+
Requires-Dist: scipy<2,>=1.11; extra == 'all'
|
|
29
|
+
Requires-Dist: tomli>=2; (python_version < '3.11') and extra == 'all'
|
|
30
|
+
Requires-Dist: uvicorn>=0.23; extra == 'all'
|
|
31
|
+
Provides-Extra: cellml
|
|
32
|
+
Requires-Dist: libcellml<0.7,>=0.6.3; extra == 'cellml'
|
|
33
|
+
Requires-Dist: scipy<2,>=1.11; extra == 'cellml'
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: httpx>=0.26; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest-cov>=4; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
38
|
+
Requires-Dist: pyyaml>=6; extra == 'dev'
|
|
39
|
+
Requires-Dist: tomli>=2; (python_version < '3.11') and extra == 'dev'
|
|
40
|
+
Provides-Extra: ml
|
|
41
|
+
Requires-Dist: onnxruntime>=1.18; extra == 'ml'
|
|
42
|
+
Provides-Extra: ui
|
|
43
|
+
Requires-Dist: fastapi<1,>=0.110; extra == 'ui'
|
|
44
|
+
Requires-Dist: uvicorn>=0.23; extra == 'ui'
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
|
|
47
|
+
# biosimulant
|
|
48
|
+
|
|
49
|
+
[](https://pypi.org/project/biosimulant)
|
|
50
|
+
[](https://pypi.org/project/biosimulant)
|
|
51
|
+
|
|
52
|
+
Composable simulation runtime + UI layer for orchestrating runnable biomodules.
|
|
53
|
+
|
|
54
|
+
`biosimulant` is the primary package and CLI name. The existing `biosim`
|
|
55
|
+
Python import path and `python -m biosim` command remain supported for existing
|
|
56
|
+
model packages during the migration.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Executive Summary & System Goals
|
|
61
|
+
|
|
62
|
+
### Vision
|
|
63
|
+
|
|
64
|
+
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.
|
|
65
|
+
|
|
66
|
+
### Core Mission
|
|
67
|
+
|
|
68
|
+
- Compose simulations from reusable, interoperable biomodules.
|
|
69
|
+
- Make "run + visualize + share a config" the default workflow (local-first; hosted later).
|
|
70
|
+
- Keep the runtime small and predictable while letting biomodules embed their own simulator/tooling.
|
|
71
|
+
|
|
72
|
+
### Primary Users
|
|
73
|
+
|
|
74
|
+
- Developers and researchers who need composable simulation workflows and fast iteration.
|
|
75
|
+
- Near-term beachhead: neuroscience demos (single neuron + small E/I microcircuits) with strong visuals and reproducible configs.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Installation
|
|
80
|
+
|
|
81
|
+
Preferred (pinned GitHub ref):
|
|
82
|
+
|
|
83
|
+
```console
|
|
84
|
+
pip install "biosimulant @ git+https://github.com/<org>/biosim.git@<ref>"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Alternative (package index):
|
|
88
|
+
|
|
89
|
+
```console
|
|
90
|
+
pip install biosimulant
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
For the shared ONNX biomodule helpers:
|
|
94
|
+
|
|
95
|
+
```console
|
|
96
|
+
pip install "biosimulant[ml]"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Compatibility and command ownership
|
|
100
|
+
|
|
101
|
+
The `biosimulant` package still ships the `biosim` Python import path so existing
|
|
102
|
+
model packages keep working:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
import biosim
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Use `biosimulant` for new CLI examples:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
biosimulant --help
|
|
112
|
+
python -m biosimulant --help
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`python -m biosim` remains available as a compatibility command. If a machine
|
|
116
|
+
also has the Desktop/product CLI installed, `PATH` decides which `biosimulant`
|
|
117
|
+
binary runs. Use `python -m biosimulant ...` to force the Python package CLI.
|
|
118
|
+
The Python package owns local open-source workflows; Desktop/product extensions
|
|
119
|
+
own Hub, auth, cloud, app state, and managed-service workflows.
|
|
120
|
+
|
|
121
|
+
## Publishing to PyPI
|
|
122
|
+
|
|
123
|
+
See the release guide: [`docs/releasing.md`](docs/releasing.md).
|
|
124
|
+
|
|
125
|
+
## Packaging Models And Labs
|
|
126
|
+
|
|
127
|
+
`biosim` can package one model or one lab into a single archive for portability, upload, caching, and validation.
|
|
128
|
+
|
|
129
|
+
Common commands:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Build a package from a directory that contains model.yaml or lab.yaml
|
|
133
|
+
biosimulant pack build path/to/model-or-lab
|
|
134
|
+
|
|
135
|
+
# Validate an existing package file
|
|
136
|
+
biosimulant pack validate dist/local__counter-1.0.0.bsimodel
|
|
137
|
+
|
|
138
|
+
# Build a self-contained lab package (.bsilab)
|
|
139
|
+
biosimulant pack build path/to/lab
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Notes:
|
|
143
|
+
- `build` prefers `package:` and `version:` from `model.yaml` or `lab.yaml` when present.
|
|
144
|
+
- model dependencies in manifests must use exact `==` pins.
|
|
145
|
+
- lab builds are always self-contained and preserve the full runnable source tree inside the `.bsilab`.
|
|
146
|
+
- nested lab dependencies must use relative `path` refs and must already exist inside the packaged lab directory.
|
|
147
|
+
- `validate` prints human-readable success or failure output by default; add `--json` for machine-readable output.
|
|
148
|
+
|
|
149
|
+
See [`docs/packaging.md`](docs/packaging.md) for the full package layout, recommended authoring flow, and CLI examples.
|
|
150
|
+
|
|
151
|
+
## Provisional Runtime Helpers
|
|
152
|
+
|
|
153
|
+
`biosim.runtime` is the provisional public home for package interpretation helpers shared by the open-source CLI and Biosimulant platform executors. It owns entrypoint loading, typed `runtime.initial_inputs` coercion, communication-step resolution, and source-neutral lab flattening. Import these helpers from `biosim.runtime`; they are not exported from top-level `biosim` while the API settles.
|
|
154
|
+
|
|
155
|
+
## BioModule Convenience Layers
|
|
156
|
+
|
|
157
|
+
`BioModule` remains the minimal full-control runtime contract. For common model
|
|
158
|
+
adapters, `biosim` also exports opt-in helpers:
|
|
159
|
+
|
|
160
|
+
- `SignalEmitterBioModule`: output storage, source-name resolution, and raw
|
|
161
|
+
value to typed `BioSignal` wrapping.
|
|
162
|
+
- `StatefulBioModule`: fixed-step window advancement, input override storage,
|
|
163
|
+
bounded history, and output publishing hooks.
|
|
164
|
+
|
|
165
|
+
Signal helper functions are available from `biosim.signals` and top-level
|
|
166
|
+
`biosim`: `unwrap_payload`, `coerce_float`, `scalar_or_record_input`, and
|
|
167
|
+
`make_signal`.
|
|
168
|
+
|
|
169
|
+
## Examples
|
|
170
|
+
|
|
171
|
+
- See `examples/` for quick-start scripts. Try:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
pip install -e .
|
|
175
|
+
python examples/basic_usage.py
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
For advanced curated demos (neuro/ecology), wiring configs, and model-pack templates, see the companion repo:
|
|
179
|
+
|
|
180
|
+
- https://github.com/Biosimulant/models
|
|
181
|
+
|
|
182
|
+
### Quick Start: BioWorld
|
|
183
|
+
|
|
184
|
+
Minimal usage:
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
import biosim
|
|
188
|
+
from biosim import ScalarSignal, SignalSpec
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class Counter(biosim.BioModule):
|
|
192
|
+
def __init__(self):
|
|
193
|
+
self.value = 0
|
|
194
|
+
self._t = 0.0
|
|
195
|
+
|
|
196
|
+
def outputs(self):
|
|
197
|
+
return {"count": SignalSpec.scalar(dtype="int64", emitted_unit="1")}
|
|
198
|
+
|
|
199
|
+
def advance_window(self, start: float, end: float) -> None:
|
|
200
|
+
_ = start
|
|
201
|
+
self.value += 1
|
|
202
|
+
self._t = end
|
|
203
|
+
|
|
204
|
+
def get_outputs(self):
|
|
205
|
+
return {
|
|
206
|
+
"count": ScalarSignal(
|
|
207
|
+
source="counter",
|
|
208
|
+
name="count",
|
|
209
|
+
value=self.value,
|
|
210
|
+
emitted_at=self._t,
|
|
211
|
+
spec=self.outputs()["count"],
|
|
212
|
+
)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
def snapshot(self) -> dict:
|
|
216
|
+
return {"value": self.value, "t": self._t}
|
|
217
|
+
|
|
218
|
+
def restore(self, snapshot: dict) -> None:
|
|
219
|
+
self.value = int(snapshot.get("value", 0))
|
|
220
|
+
self._t = float(snapshot.get("t", 0.0))
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
world = biosim.BioWorld(communication_step=0.1)
|
|
224
|
+
world.add_biomodule("counter", Counter())
|
|
225
|
+
world.run(duration=1.0)
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Outputs produced during a communication window are committed at the end of that
|
|
229
|
+
window and become visible to downstream modules on a later communication turn.
|
|
230
|
+
For final report, export, or visualisation modules in workflow-style graphs, call
|
|
231
|
+
`world.settle(steps=1)` after `world.run(...)` to propagate final outputs without
|
|
232
|
+
advancing simulated time.
|
|
233
|
+
|
|
234
|
+
### Visuals from Modules
|
|
235
|
+
|
|
236
|
+
Modules may optionally expose visuals via `visualize()`, returning a dict or list of dicts with keys `render` and `data`. The world can collect them without any transport layer:
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
class MyModule(biosim.BioModule):
|
|
240
|
+
def advance_window(self, start: float, end: float) -> None:
|
|
241
|
+
_ = start, end
|
|
242
|
+
|
|
243
|
+
def get_outputs(self):
|
|
244
|
+
return {}
|
|
245
|
+
|
|
246
|
+
def snapshot(self) -> dict:
|
|
247
|
+
return {}
|
|
248
|
+
|
|
249
|
+
def restore(self, snapshot: dict) -> None:
|
|
250
|
+
_ = snapshot
|
|
251
|
+
|
|
252
|
+
def visualize(self):
|
|
253
|
+
return {
|
|
254
|
+
"render": "timeseries",
|
|
255
|
+
"data": {"series": [{"name": "s", "points": [[0.0, 1.0]]}]},
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
world = biosim.BioWorld(communication_step=0.1)
|
|
259
|
+
world.add_biomodule("module", MyModule())
|
|
260
|
+
world.run(duration=0.1)
|
|
261
|
+
print(world.collect_visuals()) # [{"module": "module", "visuals": [...]}]
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
If visuals are generated by a separate downstream module wired to another
|
|
265
|
+
producer's final outputs, run one or more settle turns before collecting visuals:
|
|
266
|
+
`world.run(duration=...); world.settle(1); world.collect_visuals()`.
|
|
267
|
+
|
|
268
|
+
See `examples/visuals_demo.py` for a minimal end-to-end example.
|
|
269
|
+
|
|
270
|
+
### ONNX Modules
|
|
271
|
+
|
|
272
|
+
`biosim` can host ONNX-backed modules without changing the core runtime. Install
|
|
273
|
+
the ML extras and wrap the ONNX model behind the standard `BioModule`
|
|
274
|
+
interface:
|
|
275
|
+
|
|
276
|
+
```python
|
|
277
|
+
from biosim import OnnxClassifierModule, ScalarSignal, SignalSpec
|
|
278
|
+
|
|
279
|
+
classifier = OnnxClassifierModule(
|
|
280
|
+
model_path="artifacts/model.onnx",
|
|
281
|
+
class_labels=["quiescent", "subthreshold", "spiking"],
|
|
282
|
+
input_port="state_vector",
|
|
283
|
+
probabilities_port="state_probabilities",
|
|
284
|
+
predicted_port="predicted_state",
|
|
285
|
+
input_vector_length=4,
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
classifier.set_inputs(
|
|
289
|
+
{
|
|
290
|
+
"state_vector": ScalarSignal(
|
|
291
|
+
source="adapter",
|
|
292
|
+
name="state_vector",
|
|
293
|
+
value=-64.0,
|
|
294
|
+
emitted_at=0.0,
|
|
295
|
+
spec=SignalSpec.scalar(dtype="float64"),
|
|
296
|
+
)
|
|
297
|
+
}
|
|
298
|
+
)
|
|
299
|
+
classifier.advance_window(0.0, 0.001)
|
|
300
|
+
print(classifier.get_outputs()["predicted_state"].value)
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Model packs can subclass `OnnxClassifierModule` to set model-relative
|
|
304
|
+
`model_path`, port names, and label sets while keeping the inference logic in
|
|
305
|
+
the shared library.
|
|
306
|
+
|
|
307
|
+
## SimUI (Python-Declared UI)
|
|
308
|
+
|
|
309
|
+
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.
|
|
310
|
+
|
|
311
|
+
- User usage (no Node/npm required):
|
|
312
|
+
- Install UI extras: `pip install 'biosimulant[ui]'`
|
|
313
|
+
- Try the demo: `python examples/ui_demo.py` then open `http://127.0.0.1:7860/ui/`.
|
|
314
|
+
- From your own code:
|
|
315
|
+
|
|
316
|
+
```python
|
|
317
|
+
from biosim.simui import Interface, Number, Button, EventLog, VisualsPanel
|
|
318
|
+
world = biosim.BioWorld(communication_step=0.1)
|
|
319
|
+
ui = Interface(
|
|
320
|
+
world,
|
|
321
|
+
controls=[Number("duration", 10), Button("Run")],
|
|
322
|
+
outputs=[EventLog(), VisualsPanel()],
|
|
323
|
+
)
|
|
324
|
+
ui.launch()
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
- The UI provides endpoints under `/ui/api/...`:
|
|
328
|
+
- `GET /api/spec` – UI layout (controls, outputs, modules)
|
|
329
|
+
- `POST /api/run` – Start a simulation run
|
|
330
|
+
- `GET /api/status` – Runner status (running/paused/error + optional progress fields)
|
|
331
|
+
- `GET /api/state` – Full state (status + last step + modules)
|
|
332
|
+
- `GET /api/events` – Buffered world events (`?since_id=&limit=`)
|
|
333
|
+
- `GET /api/visuals` – Collected module visuals
|
|
334
|
+
- `GET /api/snapshot` – Full snapshot (status + visuals + events)
|
|
335
|
+
- `GET /api/stream` – SSE endpoint for real-time event streaming
|
|
336
|
+
- `POST /api/pause` – Pause running simulation
|
|
337
|
+
- `POST /api/resume` – Resume paused simulation
|
|
338
|
+
- `POST /api/reset` – Stop, reset, and clear buffers
|
|
339
|
+
- **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`.
|
|
340
|
+
|
|
341
|
+
Per-run resets for clean visuals
|
|
342
|
+
- On each `Run`, the backend clears its event buffer and calls `reset()` on modules if they implement it.
|
|
343
|
+
- The frontend clears visuals/events before posting `/api/run`.
|
|
344
|
+
- To avoid overlapping charts across runs, add `reset()` to modules that accumulate history (e.g., time series points).
|
|
345
|
+
|
|
346
|
+
- Maintainer flow (building the frontend SPA):
|
|
347
|
+
- Edit the React/Vite app under `src/biosim/simui/_frontend/`.
|
|
348
|
+
- Build via Python: `python -m biosim.simui.build` (requires Node/npm). This writes `src/biosim/simui/static/app.js`.
|
|
349
|
+
- Alternatively: `bash scripts/build_simui_frontend.sh`.
|
|
350
|
+
- Packaging includes `src/biosim/simui/static/**`, so end users never need npm.
|
|
351
|
+
|
|
352
|
+
- CI packaging (recommended): run the frontend build before `python -m build` so wheels/sdists ship the bundled assets.
|
|
353
|
+
|
|
354
|
+
Troubleshooting:
|
|
355
|
+
- 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.
|
|
356
|
+
|
|
357
|
+
### SimUI Design Notes
|
|
358
|
+
- 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.
|
|
359
|
+
- Objective progress fields are based on simulation-time progress (`(sim_time - sim_start) / duration`), not wall-clock time.
|
|
360
|
+
- `/api/status` may include: `sim_time`, `sim_start`, `sim_end`, `sim_remaining`, `progress`, `progress_pct` (all optional/additive).
|
|
361
|
+
- 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.
|
|
362
|
+
- VisualSpec types supported now:
|
|
363
|
+
- `timeseries`: `data = { "series": [{ "name": str, "points": [[x, y], ...] }, ...] }`
|
|
364
|
+
- `bar`: `data = { "items": [{ "label": str, "value": number }, ...] }`
|
|
365
|
+
- `scatter`: `data = { "points": [{ "x": number, "y": number, "label"?: str, "series"?: str }, ...] }`
|
|
366
|
+
- `heatmap`: `data = { "values": [[number, ...], ...], "x_labels"?: [str, ...], "y_labels"?: [str, ...] }`
|
|
367
|
+
- `table`: `data = { "columns": [..], "rows": [[..], ...] }` or `data = { "items": [{...}, ...] }`
|
|
368
|
+
- `image`: `data = { "src": str, "alt"?: str, "width"?: number, "height"?: number }`
|
|
369
|
+
- `graph`: simple node-edge graph renderer
|
|
370
|
+
- `structure3d`: `data = { "title"?: str, "source": { "kind": "url", "url": str } | { "kind": "artifact", "artifact_id": str }, "format": "mmcif" | "pdb", "annotations"?: [{ "label": str, "value": str|number|bool }], "initial_view"?: {...} }`
|
|
371
|
+
- VisualSpec may also include an optional `description` (string) for hover text or captions.
|
|
372
|
+
- SimUI serves artifact-backed `structure3d` files through `/api/artifacts/{artifact_id}` so browser clients do not receive raw local filesystem paths.
|
|
373
|
+
|
|
374
|
+
## Terminology
|
|
375
|
+
|
|
376
|
+
Understanding the core concepts is essential for working with biosim effectively.
|
|
377
|
+
|
|
378
|
+
| Term | Description |
|
|
379
|
+
|------|-------------|
|
|
380
|
+
| **BioWorld** | Runtime container that orchestrates multi-rate biomodules, routes signals, and publishes lifecycle events. |
|
|
381
|
+
| **BioModule** | Pluggable unit of behavior with local state. Implements the runnable contract (`setup/reset/advance_to/...`). |
|
|
382
|
+
| **BioSignal** | Typed, versioned data payload exchanged between modules via named ports. |
|
|
383
|
+
| **WorldEvent** | Runtime events emitted by the BioWorld (`STARTED`, `TICK`, `FINISHED`, etc.). |
|
|
384
|
+
| **Wiring** | Module connection graph. Defined programmatically, via `WiringBuilder`, or loaded from YAML/TOML configs. |
|
|
385
|
+
| **VisualSpec** | JSON structure returned by `module.visualize()` with `render` type and `data` payload. |
|
|
386
|
+
|
|
387
|
+
### Event Lifecycle
|
|
388
|
+
|
|
389
|
+
Every simulation follows this sequence:
|
|
390
|
+
```
|
|
391
|
+
STARTED -> TICK (xN) -> FINISHED
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
`PAUSED`, `RESUMED`, `STOPPED`, and `ERROR` may also be emitted depending on runtime control flow.
|
|
395
|
+
|
|
396
|
+
## License
|
|
397
|
+
|
|
398
|
+
MIT. See `LICENSE.txt`.
|