anasim-simulator 1.0__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.
- anasim_simulator-1.0/LICENSE +21 -0
- anasim_simulator-1.0/PKG-INFO +135 -0
- anasim_simulator-1.0/README.md +97 -0
- anasim_simulator-1.0/anasim/__init__.py +3 -0
- anasim_simulator-1.0/anasim/__main__.py +4 -0
- anasim_simulator-1.0/anasim/cli.py +107 -0
- anasim_simulator-1.0/anasim/core/__init__.py +0 -0
- anasim_simulator-1.0/anasim/core/constants.py +151 -0
- anasim_simulator-1.0/anasim/core/drug_api.py +371 -0
- anasim_simulator-1.0/anasim/core/engine.py +924 -0
- anasim_simulator-1.0/anasim/core/enums.py +11 -0
- anasim_simulator-1.0/anasim/core/initialization.py +396 -0
- anasim_simulator-1.0/anasim/core/metrics.py +66 -0
- anasim_simulator-1.0/anasim/core/monitors.py +311 -0
- anasim_simulator-1.0/anasim/core/projection.py +355 -0
- anasim_simulator-1.0/anasim/core/recorder.py +67 -0
- anasim_simulator-1.0/anasim/core/runtime.py +737 -0
- anasim_simulator-1.0/anasim/core/state.py +208 -0
- anasim_simulator-1.0/anasim/core/tci.py +303 -0
- anasim_simulator-1.0/anasim/core/units.py +75 -0
- anasim_simulator-1.0/anasim/core/utils.py +67 -0
- anasim_simulator-1.0/anasim/machine/circuit.py +90 -0
- anasim_simulator-1.0/anasim/machine/ventilator.py +146 -0
- anasim_simulator-1.0/anasim/machine/volatile.py +40 -0
- anasim_simulator-1.0/anasim/monitors/__init__.py +0 -0
- anasim_simulator-1.0/anasim/monitors/alarms.py +88 -0
- anasim_simulator-1.0/anasim/monitors/capno.py +200 -0
- anasim_simulator-1.0/anasim/monitors/ecg.py +126 -0
- anasim_simulator-1.0/anasim/monitors/nibp.py +99 -0
- anasim_simulator-1.0/anasim/monitors/spo2.py +75 -0
- anasim_simulator-1.0/anasim/patient/__init__.py +0 -0
- anasim_simulator-1.0/anasim/patient/patient.py +118 -0
- anasim_simulator-1.0/anasim/patient/pd/__init__.py +10 -0
- anasim_simulator-1.0/anasim/patient/pd/anesthesia.py +268 -0
- anasim_simulator-1.0/anasim/patient/pd/nmba.py +142 -0
- anasim_simulator-1.0/anasim/patient/pk_models.py +1343 -0
- anasim_simulator-1.0/anasim/patient/volatile_pk.py +150 -0
- anasim_simulator-1.0/anasim/physiology/disturbances.py +91 -0
- anasim_simulator-1.0/anasim/physiology/hemo_config.py +185 -0
- anasim_simulator-1.0/anasim/physiology/hemo_types.py +37 -0
- anasim_simulator-1.0/anasim/physiology/hemodynamics.py +1313 -0
- anasim_simulator-1.0/anasim/physiology/resp_mech.py +383 -0
- anasim_simulator-1.0/anasim/physiology/respiration.py +557 -0
- anasim_simulator-1.0/anasim/ui/__init__.py +0 -0
- anasim_simulator-1.0/anasim/ui/config_dialog.py +341 -0
- anasim_simulator-1.0/anasim/ui/controls_widget.py +1118 -0
- anasim_simulator-1.0/anasim/ui/main_window.py +375 -0
- anasim_simulator-1.0/anasim/ui/monitor_widget.py +537 -0
- anasim_simulator-1.0/anasim/ui/scenarios/__init__.py +25 -0
- anasim_simulator-1.0/anasim/ui/scenarios/anaphylaxis.py +88 -0
- anasim_simulator-1.0/anasim/ui/scenarios/base.py +313 -0
- anasim_simulator-1.0/anasim/ui/scenarios/emergence.py +184 -0
- anasim_simulator-1.0/anasim/ui/scenarios/hemorrhage.py +128 -0
- anasim_simulator-1.0/anasim/ui/scenarios/induction.py +292 -0
- anasim_simulator-1.0/anasim/ui/scenarios/sepsis.py +121 -0
- anasim_simulator-1.0/anasim/ui/styles.py +552 -0
- anasim_simulator-1.0/anasim/ui/tutorial_overlay.py +179 -0
- anasim_simulator-1.0/anasim_simulator.egg-info/PKG-INFO +135 -0
- anasim_simulator-1.0/anasim_simulator.egg-info/SOURCES.txt +85 -0
- anasim_simulator-1.0/anasim_simulator.egg-info/dependency_links.txt +1 -0
- anasim_simulator-1.0/anasim_simulator.egg-info/entry_points.txt +2 -0
- anasim_simulator-1.0/anasim_simulator.egg-info/requires.txt +10 -0
- anasim_simulator-1.0/anasim_simulator.egg-info/top_level.txt +1 -0
- anasim_simulator-1.0/pyproject.toml +67 -0
- anasim_simulator-1.0/setup.cfg +4 -0
- anasim_simulator-1.0/tests/test_adaptive_dt.py +43 -0
- anasim_simulator-1.0/tests/test_airway_complications.py +67 -0
- anasim_simulator-1.0/tests/test_clinical_scenarios.py +165 -0
- anasim_simulator-1.0/tests/test_clinical_timing.py +406 -0
- anasim_simulator-1.0/tests/test_components.py +78 -0
- anasim_simulator-1.0/tests/test_death_detector.py +81 -0
- anasim_simulator-1.0/tests/test_drug_units.py +34 -0
- anasim_simulator-1.0/tests/test_engine_integration.py +282 -0
- anasim_simulator-1.0/tests/test_hemodynamics.py +379 -0
- anasim_simulator-1.0/tests/test_long_duration.py +120 -0
- anasim_simulator-1.0/tests/test_machine_circuit.py +133 -0
- anasim_simulator-1.0/tests/test_n2o_effects.py +38 -0
- anasim_simulator-1.0/tests/test_nibp_capno.py +279 -0
- anasim_simulator-1.0/tests/test_pharmacology.py +504 -0
- anasim_simulator-1.0/tests/test_respiration.py +363 -0
- anasim_simulator-1.0/tests/test_shivering.py +26 -0
- anasim_simulator-1.0/tests/test_state_semantics.py +477 -0
- anasim_simulator-1.0/tests/test_tci_accuracy.py +217 -0
- anasim_simulator-1.0/tests/test_temperature.py +54 -0
- anasim_simulator-1.0/tests/test_ui.py +80 -0
- anasim_simulator-1.0/tests/test_ventilator.py +371 -0
- anasim_simulator-1.0/tests/test_volatile_pk.py +163 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Robert Chen
|
|
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,135 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: anasim-simulator
|
|
3
|
+
Version: 1.0
|
|
4
|
+
Summary: Real-time anesthesia and physiology simulator for medical education
|
|
5
|
+
Author-email: Robert Chen <robert.chen@icahn.mssm.edu>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/robchiral/AnaSim
|
|
8
|
+
Project-URL: Changelog, https://github.com/robchiral/AnaSim/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Documentation, https://github.com/robchiral/AnaSim#readme
|
|
10
|
+
Project-URL: Issues, https://github.com/robchiral/AnaSim/issues
|
|
11
|
+
Project-URL: Releases, https://github.com/robchiral/AnaSim/releases
|
|
12
|
+
Project-URL: Source, https://github.com/robchiral/AnaSim
|
|
13
|
+
Keywords: anesthesia,medical education,physiology,pharmacokinetics,simulation
|
|
14
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
15
|
+
Classifier: Intended Audience :: Education
|
|
16
|
+
Classifier: Intended Audience :: Healthcare Industry
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Education
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
24
|
+
Classifier: Operating System :: OS Independent
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: numpy
|
|
29
|
+
Requires-Dist: PySide6
|
|
30
|
+
Requires-Dist: pyqtgraph
|
|
31
|
+
Requires-Dist: scipy
|
|
32
|
+
Requires-Dist: pandas
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: build; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest; extra == "dev"
|
|
36
|
+
Requires-Dist: twine; extra == "dev"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# AnaSim
|
|
40
|
+
|
|
41
|
+
Real-time anesthesia and physiology simulation for medical education.
|
|
42
|
+
|
|
43
|
+
[](https://github.com/robchiral/AnaSim/actions/workflows/ci.yml)
|
|
44
|
+
[](https://www.python.org/downloads/)
|
|
45
|
+
[](https://github.com/robchiral/AnaSim/blob/main/LICENSE)
|
|
46
|
+
|
|
47
|
+

|
|
48
|
+
|
|
49
|
+
> [!WARNING]
|
|
50
|
+
> **For educational use only**
|
|
51
|
+
>
|
|
52
|
+
> AnaSim is not a medical device. Do not use it for clinical care or patient-specific
|
|
53
|
+
> prediction.
|
|
54
|
+
|
|
55
|
+
## Installation
|
|
56
|
+
|
|
57
|
+
AnaSim requires Python 3.10 or newer. Install the published package in a virtual
|
|
58
|
+
environment:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
python3 -m venv .venv
|
|
62
|
+
source .venv/bin/activate
|
|
63
|
+
python -m pip install anasim-simulator
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
On Windows, activate the environment with `.venv\Scripts\activate`.
|
|
67
|
+
|
|
68
|
+
The package is distributed as `anasim-simulator`; the command and Python import
|
|
69
|
+
are `anasim`.
|
|
70
|
+
|
|
71
|
+
## Quick start
|
|
72
|
+
|
|
73
|
+
Launch the interactive operating-room monitor:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
anasim
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Run a headless simulation:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
anasim --mode headless --duration 10
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
See the [CLI guide](https://github.com/robchiral/AnaSim/blob/main/docs/CLI_USAGE.md)
|
|
86
|
+
for configuration files, recording, and additional examples.
|
|
87
|
+
|
|
88
|
+
## Features
|
|
89
|
+
|
|
90
|
+
- Cardiovascular and respiratory physiology responding to drugs, ventilation,
|
|
91
|
+
fluids, and surgical stimulation
|
|
92
|
+
- PK/PD models for propofol, remifentanil, sevoflurane, rocuronium, and
|
|
93
|
+
vasoactive agents
|
|
94
|
+
- VCV, PCV, PSV, CPAP, and manual bag-mask ventilation
|
|
95
|
+
- ECG, pulse oximetry, capnography, NIBP, and depth-of-anesthesia monitoring
|
|
96
|
+
- Guided induction, hemorrhage, anaphylaxis, septic shock, and emergence scenarios
|
|
97
|
+
- Headless execution and CSV recording for reproducible teaching exercises
|
|
98
|
+
|
|
99
|
+
## Model scope and calibration
|
|
100
|
+
|
|
101
|
+
AnaSim uses published models where they behave coherently in the integrated
|
|
102
|
+
simulation and documents calibrated deviations where literal parameters produce
|
|
103
|
+
implausible managed intraoperative states. See the
|
|
104
|
+
[model references and deviations](https://github.com/robchiral/AnaSim/blob/main/docs/REFERENCES.md)
|
|
105
|
+
for citations and details.
|
|
106
|
+
|
|
107
|
+
Examples of calibration choices and deliberate deviations:
|
|
108
|
+
|
|
109
|
+
- hemodynamics uses plasma propofol/remifentanil concentrations in line with Su et al. 2023, while CNS depth, tolerance, BIS, and respiratory depression use effect-site concentrations
|
|
110
|
+
- rocuronium spontaneous recovery uses a faster runtime `ke0` than pure literature modeling so recovery timing stays in the clinical range
|
|
111
|
+
- maintenance startup adds visible norepinephrine support only when the selected anesthetic state would otherwise begin below MAP 65 mmHg
|
|
112
|
+
|
|
113
|
+
AnaSim currently accepts adult patients aged 18–70 years. The upper bound avoids unsupported extrapolation of the strongly age-dependent Su et al. hemodynamic term beyond the population used to develop and illustrate that model.
|
|
114
|
+
|
|
115
|
+
## Development
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
git clone https://github.com/robchiral/AnaSim.git
|
|
119
|
+
cd AnaSim
|
|
120
|
+
python3 -m venv .venv
|
|
121
|
+
source .venv/bin/activate
|
|
122
|
+
python -m pip install -e ".[dev]"
|
|
123
|
+
QT_QPA_PLATFORM=offscreen python -m pytest -q
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
See the [contribution guide](https://github.com/robchiral/AnaSim/blob/main/CONTRIBUTING.md)
|
|
127
|
+
and [changelog](https://github.com/robchiral/AnaSim/blob/main/CHANGELOG.md).
|
|
128
|
+
|
|
129
|
+
Initial TIVA implementations were derived from
|
|
130
|
+
[Python Anesthesia Simulator](https://github.com/AnesthesiaSimulation/Python_Anesthesia_Simulator).
|
|
131
|
+
|
|
132
|
+
## License
|
|
133
|
+
|
|
134
|
+
AnaSim is released under the
|
|
135
|
+
[MIT License](https://github.com/robchiral/AnaSim/blob/main/LICENSE).
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# AnaSim
|
|
2
|
+
|
|
3
|
+
Real-time anesthesia and physiology simulation for medical education.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/robchiral/AnaSim/actions/workflows/ci.yml)
|
|
6
|
+
[](https://www.python.org/downloads/)
|
|
7
|
+
[](https://github.com/robchiral/AnaSim/blob/main/LICENSE)
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
> [!WARNING]
|
|
12
|
+
> **For educational use only**
|
|
13
|
+
>
|
|
14
|
+
> AnaSim is not a medical device. Do not use it for clinical care or patient-specific
|
|
15
|
+
> prediction.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
AnaSim requires Python 3.10 or newer. Install the published package in a virtual
|
|
20
|
+
environment:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
python3 -m venv .venv
|
|
24
|
+
source .venv/bin/activate
|
|
25
|
+
python -m pip install anasim-simulator
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
On Windows, activate the environment with `.venv\Scripts\activate`.
|
|
29
|
+
|
|
30
|
+
The package is distributed as `anasim-simulator`; the command and Python import
|
|
31
|
+
are `anasim`.
|
|
32
|
+
|
|
33
|
+
## Quick start
|
|
34
|
+
|
|
35
|
+
Launch the interactive operating-room monitor:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
anasim
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Run a headless simulation:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
anasim --mode headless --duration 10
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
See the [CLI guide](https://github.com/robchiral/AnaSim/blob/main/docs/CLI_USAGE.md)
|
|
48
|
+
for configuration files, recording, and additional examples.
|
|
49
|
+
|
|
50
|
+
## Features
|
|
51
|
+
|
|
52
|
+
- Cardiovascular and respiratory physiology responding to drugs, ventilation,
|
|
53
|
+
fluids, and surgical stimulation
|
|
54
|
+
- PK/PD models for propofol, remifentanil, sevoflurane, rocuronium, and
|
|
55
|
+
vasoactive agents
|
|
56
|
+
- VCV, PCV, PSV, CPAP, and manual bag-mask ventilation
|
|
57
|
+
- ECG, pulse oximetry, capnography, NIBP, and depth-of-anesthesia monitoring
|
|
58
|
+
- Guided induction, hemorrhage, anaphylaxis, septic shock, and emergence scenarios
|
|
59
|
+
- Headless execution and CSV recording for reproducible teaching exercises
|
|
60
|
+
|
|
61
|
+
## Model scope and calibration
|
|
62
|
+
|
|
63
|
+
AnaSim uses published models where they behave coherently in the integrated
|
|
64
|
+
simulation and documents calibrated deviations where literal parameters produce
|
|
65
|
+
implausible managed intraoperative states. See the
|
|
66
|
+
[model references and deviations](https://github.com/robchiral/AnaSim/blob/main/docs/REFERENCES.md)
|
|
67
|
+
for citations and details.
|
|
68
|
+
|
|
69
|
+
Examples of calibration choices and deliberate deviations:
|
|
70
|
+
|
|
71
|
+
- hemodynamics uses plasma propofol/remifentanil concentrations in line with Su et al. 2023, while CNS depth, tolerance, BIS, and respiratory depression use effect-site concentrations
|
|
72
|
+
- rocuronium spontaneous recovery uses a faster runtime `ke0` than pure literature modeling so recovery timing stays in the clinical range
|
|
73
|
+
- maintenance startup adds visible norepinephrine support only when the selected anesthetic state would otherwise begin below MAP 65 mmHg
|
|
74
|
+
|
|
75
|
+
AnaSim currently accepts adult patients aged 18–70 years. The upper bound avoids unsupported extrapolation of the strongly age-dependent Su et al. hemodynamic term beyond the population used to develop and illustrate that model.
|
|
76
|
+
|
|
77
|
+
## Development
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
git clone https://github.com/robchiral/AnaSim.git
|
|
81
|
+
cd AnaSim
|
|
82
|
+
python3 -m venv .venv
|
|
83
|
+
source .venv/bin/activate
|
|
84
|
+
python -m pip install -e ".[dev]"
|
|
85
|
+
QT_QPA_PLATFORM=offscreen python -m pytest -q
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
See the [contribution guide](https://github.com/robchiral/AnaSim/blob/main/CONTRIBUTING.md)
|
|
89
|
+
and [changelog](https://github.com/robchiral/AnaSim/blob/main/CHANGELOG.md).
|
|
90
|
+
|
|
91
|
+
Initial TIVA implementations were derived from
|
|
92
|
+
[Python Anesthesia Simulator](https://github.com/AnesthesiaSimulation/Python_Anesthesia_Simulator).
|
|
93
|
+
|
|
94
|
+
## License
|
|
95
|
+
|
|
96
|
+
AnaSim is released under the
|
|
97
|
+
[MIT License](https://github.com/robchiral/AnaSim/blob/main/LICENSE).
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import json
|
|
3
|
+
import sys
|
|
4
|
+
import time
|
|
5
|
+
from dataclasses import fields
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from anasim.core.engine import SimulationEngine, SimulationConfig
|
|
9
|
+
from anasim.patient.patient import Patient
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
PATIENT_CONFIG_FIELDS = {
|
|
13
|
+
field.name for field in fields(Patient)
|
|
14
|
+
if field.name not in {"lbm", "bmi", "bsa"}
|
|
15
|
+
}
|
|
16
|
+
SIMULATION_CONFIG_FIELDS = {field.name for field in fields(SimulationConfig)}
|
|
17
|
+
CONFIG_FIELDS = PATIENT_CONFIG_FIELDS | SIMULATION_CONFIG_FIELDS
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def build_models_from_config(config_data: dict) -> tuple[Patient, SimulationConfig]:
|
|
21
|
+
"""Build typed inputs and reject misspelled or obsolete keys."""
|
|
22
|
+
unknown = set(config_data) - CONFIG_FIELDS
|
|
23
|
+
if unknown:
|
|
24
|
+
names = ", ".join(sorted(unknown))
|
|
25
|
+
raise ValueError(f"Unknown configuration key(s): {names}")
|
|
26
|
+
|
|
27
|
+
patient_kwargs = {
|
|
28
|
+
key: value for key, value in config_data.items()
|
|
29
|
+
if key in PATIENT_CONFIG_FIELDS
|
|
30
|
+
}
|
|
31
|
+
simulation_kwargs = {
|
|
32
|
+
key: value for key, value in config_data.items()
|
|
33
|
+
if key in SIMULATION_CONFIG_FIELDS
|
|
34
|
+
}
|
|
35
|
+
return Patient(**patient_kwargs), SimulationConfig(**simulation_kwargs)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def run_headless(args):
|
|
39
|
+
"""Run simulation in headless mode."""
|
|
40
|
+
print(f"Starting Headless Simulation (Duration: {args.duration}s)...")
|
|
41
|
+
|
|
42
|
+
# Simple default config or load from file
|
|
43
|
+
config_data = {}
|
|
44
|
+
if args.config:
|
|
45
|
+
try:
|
|
46
|
+
config_data = json.loads(Path(args.config).read_text())
|
|
47
|
+
except (OSError, json.JSONDecodeError) as e:
|
|
48
|
+
print(f"Error loading config: {e}")
|
|
49
|
+
raise SystemExit(1) from e
|
|
50
|
+
try:
|
|
51
|
+
patient, sim_config = build_models_from_config(config_data)
|
|
52
|
+
except ValueError as e:
|
|
53
|
+
print(f"Error loading config: {e}")
|
|
54
|
+
raise SystemExit(1) from e
|
|
55
|
+
|
|
56
|
+
engine = SimulationEngine(patient, sim_config)
|
|
57
|
+
if args.record:
|
|
58
|
+
engine.start_recording(output_dir=args.record_dir, sample_interval_sec=args.record_interval)
|
|
59
|
+
engine.start()
|
|
60
|
+
|
|
61
|
+
# Run loop
|
|
62
|
+
start_real = time.perf_counter()
|
|
63
|
+
steps = int(args.duration / sim_config.dt)
|
|
64
|
+
|
|
65
|
+
for i in range(steps):
|
|
66
|
+
engine.step(sim_config.dt)
|
|
67
|
+
if i % 100 == 0:
|
|
68
|
+
state = engine.get_latest_state()
|
|
69
|
+
hr = state.display_value("hr")
|
|
70
|
+
map_val = state.display_value("map")
|
|
71
|
+
spo2 = state.display_value("spo2")
|
|
72
|
+
print(f"Time: {state.time:.2f}s | HR: {hr:.1f} | MAP: {map_val:.1f} | SpO2: {spo2:.1f}")
|
|
73
|
+
|
|
74
|
+
end_real = time.perf_counter()
|
|
75
|
+
print(f"Simulation completed in {end_real - start_real:.2f}s real time.")
|
|
76
|
+
|
|
77
|
+
def run_ui():
|
|
78
|
+
"""Run simulation with UI."""
|
|
79
|
+
from PySide6.QtWidgets import QApplication
|
|
80
|
+
from anasim.ui.main_window import MainWindow
|
|
81
|
+
|
|
82
|
+
app = QApplication.instance()
|
|
83
|
+
if app is None:
|
|
84
|
+
app = QApplication(sys.argv)
|
|
85
|
+
|
|
86
|
+
window = MainWindow()
|
|
87
|
+
window.show()
|
|
88
|
+
sys.exit(app.exec())
|
|
89
|
+
|
|
90
|
+
def main():
|
|
91
|
+
parser = argparse.ArgumentParser(description="AnaSim - Anesthesia Simulator")
|
|
92
|
+
parser.add_argument("--mode", choices=["ui", "headless"], default="ui", help="Run mode (default: ui)")
|
|
93
|
+
parser.add_argument("--duration", type=float, default=10.0, help="Duration for headless mode in seconds")
|
|
94
|
+
parser.add_argument("--config", type=str, help="Path to JSON configuration file")
|
|
95
|
+
parser.add_argument("--record", action="store_true", help="Enable CSV recording (headless only)")
|
|
96
|
+
parser.add_argument("--record-dir", type=str, default="recordings", help="Output directory for recordings")
|
|
97
|
+
parser.add_argument("--record-interval", type=float, default=1.0, help="Sample interval in seconds for CSV")
|
|
98
|
+
|
|
99
|
+
args = parser.parse_args()
|
|
100
|
+
|
|
101
|
+
if args.mode == "headless":
|
|
102
|
+
run_headless(args)
|
|
103
|
+
else:
|
|
104
|
+
run_ui()
|
|
105
|
+
|
|
106
|
+
if __name__ == "__main__":
|
|
107
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Physiological and Numerical Constants for AnaSim.
|
|
3
|
+
|
|
4
|
+
This module centralizes magic numbers used throughout the simulation.
|
|
5
|
+
|
|
6
|
+
NOTE: Only add constants here that are ACTIVELY IMPORTED elsewhere.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
|
|
11
|
+
# Physiological bounds (used in hemodynamics.py).
|
|
12
|
+
|
|
13
|
+
# Heart Rate Bounds (bpm)
|
|
14
|
+
HR_MIN = 10.0 # Below this, functional asystole
|
|
15
|
+
HR_MAX = 220.0 # Maximum physiological HR
|
|
16
|
+
|
|
17
|
+
# Blood Pressure Bounds (mmHg) - imported but available for bounds checking
|
|
18
|
+
MAP_MAX = 200.0 # Severe hypertensive crisis
|
|
19
|
+
SBP_MAX = 260.0 # Extreme hypertension
|
|
20
|
+
DBP_MAX = 160.0 # Extreme diastolic hypertension
|
|
21
|
+
|
|
22
|
+
# Total Peripheral Resistance minimum (Wood Units)
|
|
23
|
+
TPR_MIN = 0.006 # Minimum physiologically reasonable (severe vasodilation)
|
|
24
|
+
|
|
25
|
+
# Blood Volume (mL)
|
|
26
|
+
BLOOD_VOLUME_MIN = 500.0 # Below this, effectively exsanguinated
|
|
27
|
+
|
|
28
|
+
# Respiratory constants (used in respiration.py).
|
|
29
|
+
|
|
30
|
+
# Respiratory Rate Thresholds (bpm)
|
|
31
|
+
RR_APNEA_THRESHOLD = 2.0 # Below this, complete apnea
|
|
32
|
+
RR_BRADYPNEA_THRESHOLD = 4.0 # 2-4 bpm = severe bradypnea with irregular breathing
|
|
33
|
+
|
|
34
|
+
# Tidal Volume Minimum (mL)
|
|
35
|
+
VT_MIN = 50.0 # Threshold for functional apnea
|
|
36
|
+
|
|
37
|
+
# Pharmacokinetic constants (used in utils.py hill_function).
|
|
38
|
+
|
|
39
|
+
# Epsilon for preventing division by zero in Hill functions
|
|
40
|
+
HILL_EPSILON = 1e-12
|
|
41
|
+
|
|
42
|
+
# Maximum Hill coefficient (gamma) to prevent numerical overflow
|
|
43
|
+
GAMMA_MAX = 20.0
|
|
44
|
+
|
|
45
|
+
# Concentration ratio above which Hill function returns near-saturation
|
|
46
|
+
CONCENTRATION_RATIO_SATURATION = 100.0
|
|
47
|
+
|
|
48
|
+
# TCI controller constants (used in tci.py).
|
|
49
|
+
|
|
50
|
+
# Minimum interval between target changes (seconds)
|
|
51
|
+
TCI_MIN_TARGET_CHANGE_INTERVAL = 5.0
|
|
52
|
+
|
|
53
|
+
# Maximum TCI peak time search (seconds)
|
|
54
|
+
TCI_PEAK_TIME_MAX = 600.0
|
|
55
|
+
|
|
56
|
+
# Thermoregulation constants (used in respiration.py, hemodynamics.py).
|
|
57
|
+
|
|
58
|
+
# Temperature coefficient for metabolic rate (Q10 effect)
|
|
59
|
+
# VCO2 decreases ~7% per °C below 37°C (Q10 ≈ 2.0)
|
|
60
|
+
# Reference: Sessler. Anesthesiology. 2000.
|
|
61
|
+
TEMP_METABOLIC_COEFFICIENT = 0.93
|
|
62
|
+
|
|
63
|
+
# Thermoregulation effect on TPR per degree deviation from 37°C
|
|
64
|
+
# TPR increases ~10% per °C below normal (vasoconstriction)
|
|
65
|
+
# Reference: Frank et al. JAMA. 1997.
|
|
66
|
+
TEMP_TPR_COEFFICIENT = 0.10
|
|
67
|
+
|
|
68
|
+
# Shivering model constants (used in runtime.py, respiration.py).
|
|
69
|
+
# Clinically, shivering appears near 36.5°C in awake patients and is
|
|
70
|
+
# suppressed by anesthetics/opioids; maximal shivering can raise
|
|
71
|
+
# metabolic rate ~3-5x baseline.
|
|
72
|
+
SHIVER_BASE_THRESHOLD = 36.5
|
|
73
|
+
SHIVER_DEPTH_DROP_MAX = 2.0
|
|
74
|
+
SHIVER_REMI_DROP_MAX = 0.8
|
|
75
|
+
SHIVER_DELTA_FULL = 1.5
|
|
76
|
+
SHIVER_BIS_ON = 60.0
|
|
77
|
+
SHIVER_BIS_FULL = 80.0
|
|
78
|
+
SHIVER_MAX_MULTIPLIER = 3.0
|
|
79
|
+
SHIVER_TAU_ON = 30.0
|
|
80
|
+
SHIVER_TAU_OFF = 90.0
|
|
81
|
+
|
|
82
|
+
# Apnea PaCO2 rise rates (mmHg/min) and fast-phase duration.
|
|
83
|
+
APNEA_PACO2_RISE_FAST_MMHG_MIN = 10.0
|
|
84
|
+
APNEA_PACO2_RISE_SLOW_MMHG_MIN = 3.6
|
|
85
|
+
APNEA_PACO2_RISE_FAST_DURATION_SEC = 60.0
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@dataclass(frozen=True)
|
|
89
|
+
class AirwayTuning:
|
|
90
|
+
"""Centralized airway tuning parameters."""
|
|
91
|
+
# Laryngospasm dynamics (seconds)
|
|
92
|
+
laryngospasm_tau_on: float = 1.0
|
|
93
|
+
laryngospasm_tau_off: float = 8.0
|
|
94
|
+
|
|
95
|
+
# Resistance impact (cmH2O/(L/s))
|
|
96
|
+
upper_resistance_gain: float = 40.0
|
|
97
|
+
bronch_resistance_gain: float = 20.0
|
|
98
|
+
|
|
99
|
+
# Ventilation efficiency weighting
|
|
100
|
+
vent_efficiency_bronch_weight: float = 0.5
|
|
101
|
+
vent_efficiency_upper_weight: float = 0.2
|
|
102
|
+
vent_efficiency_min: float = 0.1
|
|
103
|
+
|
|
104
|
+
# Capnography obstruction weighting
|
|
105
|
+
capno_obstruction_upper_weight: float = 1.0
|
|
106
|
+
capno_obstruction_bronch_weight: float = 0.7
|
|
107
|
+
|
|
108
|
+
# V/Q mismatch weighting
|
|
109
|
+
vq_mismatch_bronch_weight: float = 0.85
|
|
110
|
+
vq_mismatch_upper_weight: float = 0.25
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@dataclass(frozen=True)
|
|
114
|
+
class ThermalTuning:
|
|
115
|
+
"""Centralized thermal model tuning parameters."""
|
|
116
|
+
ambient_temp_c: float = 20.0
|
|
117
|
+
base_conductance_w_per_c: float = 3.0
|
|
118
|
+
anesthetic_conductance_gain: float = 0.5
|
|
119
|
+
redistribution_gain_w_per_depth: float = 50000.0
|
|
120
|
+
bair_hugger_gain_w_per_c: float = 7.0
|
|
121
|
+
metabolic_reduction_max: float = 0.2
|
|
122
|
+
depth_propofol_scale: float = 4.0
|
|
123
|
+
metabolic_temp_threshold_c: float = 0.5
|
|
124
|
+
specific_heat_j_kg_k: float = 3470.0
|
|
125
|
+
temp_min_c: float = 25.0
|
|
126
|
+
temp_max_c: float = 42.0
|
|
127
|
+
|
|
128
|
+
# Centralized tuple configurations for Engine state models
|
|
129
|
+
PK_HEMODYNAMIC_MODEL_ATTRS = (
|
|
130
|
+
("propofol", "pk_prop"),
|
|
131
|
+
("remi", "pk_remi"),
|
|
132
|
+
("nore", "pk_nore"),
|
|
133
|
+
("roc", "pk_roc"),
|
|
134
|
+
("epi", "pk_epi"),
|
|
135
|
+
("phenyl", "pk_phenyl"),
|
|
136
|
+
("vaso", "pk_vaso"),
|
|
137
|
+
("dobu", "pk_dobu"),
|
|
138
|
+
("milri", "pk_mil"),
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
BOLUS_TARGETS = (
|
|
142
|
+
("prop", "pk_prop"),
|
|
143
|
+
("remi", "pk_remi"),
|
|
144
|
+
("nore", "pk_nore"),
|
|
145
|
+
("epi", "pk_epi"),
|
|
146
|
+
("phenyl", "pk_phenyl"),
|
|
147
|
+
("vaso", "pk_vaso"),
|
|
148
|
+
("dobu", "pk_dobu"),
|
|
149
|
+
("milri", "pk_mil"),
|
|
150
|
+
("roc", "pk_roc"),
|
|
151
|
+
)
|