bhsim 1.0.0rc2__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.
- bhsim-1.0.0rc2/LICENSE +21 -0
- bhsim-1.0.0rc2/PKG-INFO +267 -0
- bhsim-1.0.0rc2/README.md +249 -0
- bhsim-1.0.0rc2/pyproject.toml +27 -0
- bhsim-1.0.0rc2/setup.cfg +4 -0
- bhsim-1.0.0rc2/src/bhsim/__init__.py +5 -0
- bhsim-1.0.0rc2/src/bhsim/__main__.py +4 -0
- bhsim-1.0.0rc2/src/bhsim/cli.py +26 -0
- bhsim-1.0.0rc2/src/bhsim/engine.py +589 -0
- bhsim-1.0.0rc2/src/bhsim/simulator.py +34 -0
- bhsim-1.0.0rc2/src/bhsim.egg-info/PKG-INFO +267 -0
- bhsim-1.0.0rc2/src/bhsim.egg-info/SOURCES.txt +18 -0
- bhsim-1.0.0rc2/src/bhsim.egg-info/dependency_links.txt +1 -0
- bhsim-1.0.0rc2/src/bhsim.egg-info/entry_points.txt +2 -0
- bhsim-1.0.0rc2/src/bhsim.egg-info/requires.txt +7 -0
- bhsim-1.0.0rc2/src/bhsim.egg-info/top_level.txt +1 -0
- bhsim-1.0.0rc2/tests/test_engine.py +99 -0
- bhsim-1.0.0rc2/tests/test_integrated.py +49 -0
- bhsim-1.0.0rc2/tests/test_library_api.py +14 -0
- bhsim-1.0.0rc2/tests/test_names.py +31 -0
bhsim-1.0.0rc2/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rahul Byrapuneni
|
|
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.
|
bhsim-1.0.0rc2/PKG-INFO
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bhsim
|
|
3
|
+
Version: 1.0.0rc2
|
|
4
|
+
Summary: Privacy-first synthetic behavioral health operations simulator
|
|
5
|
+
Author: Rahul Byrapuneni
|
|
6
|
+
Maintainer: Rahul Byrapuneni
|
|
7
|
+
License: MIT
|
|
8
|
+
Keywords: synthetic-data,behavioral-health,sqlite,power-bi
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Provides-Extra: dev
|
|
13
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
14
|
+
Provides-Extra: ui
|
|
15
|
+
Requires-Dist: streamlit>=1.35; extra == "ui"
|
|
16
|
+
Requires-Dist: pandas>=2.0; extra == "ui"
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# BHSim
|
|
20
|
+
|
|
21
|
+
### Synthetic behavioral health data, ready for SQL and analytics
|
|
22
|
+
|
|
23
|
+
BHSim is an open-source Python library that creates **fictional, connected behavioral health records** for SQL practice, BI dashboards, software testing, and analytics prototypes.
|
|
24
|
+
|
|
25
|
+
Instead of hand-building spreadsheets or borrowing sensitive patient data, you can generate a small SQLite database with clients, programs, staff, appointments, enrollments, and screening assessments—and start querying it right away.
|
|
26
|
+
|
|
27
|
+
**Created and maintained by Rahul Byrapuneni.**
|
|
28
|
+
|
|
29
|
+
> **Important:** BHSim generates synthetic test data, not real patient records. Its scheduling, attendance, assessment trajectories, and productivity assumptions are examples for development and learning—not clinical predictions, diagnostic advice, official reporting definitions, or billing guidance.
|
|
30
|
+
|
|
31
|
+
## What can BHSim generate?
|
|
32
|
+
|
|
33
|
+
- **Individuals:** Fictional names, dates of birth, demographic fields, and unique numeric identifiers.
|
|
34
|
+
- **Programs:** Mental health (MH), substance use (SA), and intellectual/developmental disabilities (IDD) services.
|
|
35
|
+
- **Enrollments:** Admissions, discharges, multiple concurrent programs, and re-enrollment histories.
|
|
36
|
+
- **Employees:** Staff records, program assignments, and supervisor relationships.
|
|
37
|
+
- **Visits:** Completed, no-show, canceled, rescheduled, and upcoming appointments, with scheduled and actual service times.
|
|
38
|
+
- **Productivity:** Example service-unit calculations linked to visits and program rules.
|
|
39
|
+
- **Assessments:** PHQ-9 and GAD-7 with readable question text, answer choices, responses, and total scores for complete assessments.
|
|
40
|
+
|
|
41
|
+
The records are linked through primary and foreign keys, so you can practice realistic joins without needing access to an EHR.
|
|
42
|
+
|
|
43
|
+
## Quick start
|
|
44
|
+
|
|
45
|
+
**Requirements:** Python 3.10 or newer. No database server, paid API, or patient data is needed.
|
|
46
|
+
|
|
47
|
+
BHSim is currently available from its GitHub repository. To install it directly:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python -m pip install git+https://github.com/rahulbyrapuneni/bhsim.git
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
> PyPI publication is planned, but **`pip install bhsim` is not yet the documented installation method**.
|
|
54
|
+
|
|
55
|
+
Create a file named `example.py`:
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from bhsim import BHSimulator
|
|
59
|
+
|
|
60
|
+
# ---SET UP A SYNTHETIC ORGANIZATION---
|
|
61
|
+
sim = BHSimulator(
|
|
62
|
+
clients=1000,
|
|
63
|
+
employees=80,
|
|
64
|
+
history_months=12,
|
|
65
|
+
future_days=30,
|
|
66
|
+
seed=42,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# ---GENERATE, CHECK, AND EXPORT---
|
|
70
|
+
sim.generate("behavioral_health.db")
|
|
71
|
+
print(sim.validate())
|
|
72
|
+
sim.to_csv("output")
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Run:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
python example.py
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
You'll get `behavioral_health.db` plus a folder of CSV files, one for each table. A successful validation returns a result with `"valid": true` and an empty `issues` list.
|
|
82
|
+
|
|
83
|
+
**Already have an output database?** BHSim deliberately refuses to overwrite it. Choose a new filename or move the old one before generating another dataset.
|
|
84
|
+
|
|
85
|
+
### Prefer the command line?
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python -m bhsim generate demo.db --clients 100 --seed 42
|
|
89
|
+
python -m bhsim validate demo.db
|
|
90
|
+
python -m bhsim export-csv demo.db output
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The installed `bhsim` command can be used instead of `python -m bhsim` when it is available on your PATH.
|
|
94
|
+
|
|
95
|
+
## Explore the data with SQL
|
|
96
|
+
|
|
97
|
+
You can open the generated `.db` file with a SQLite-compatible editor, including [SQLime](https://sqlime.org/), or use Python's built-in `sqlite3` library.
|
|
98
|
+
|
|
99
|
+
### Appointments by program
|
|
100
|
+
|
|
101
|
+
```sql
|
|
102
|
+
SELECT
|
|
103
|
+
p.program_code,
|
|
104
|
+
p.description AS program_name,
|
|
105
|
+
COUNT(*) AS appointments,
|
|
106
|
+
SUM(CASE WHEN v.visit_status = 'COMPLETED' THEN 1 ELSE 0 END) AS completed,
|
|
107
|
+
SUM(CASE WHEN v.visit_status = 'NO_SHOW' THEN 1 ELSE 0 END) AS no_shows
|
|
108
|
+
FROM visits AS v
|
|
109
|
+
JOIN programs AS p ON p.program_id = v.program_id
|
|
110
|
+
GROUP BY p.program_code, p.description
|
|
111
|
+
ORDER BY appointments DESC;
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### No-show rate by program
|
|
115
|
+
|
|
116
|
+
```sql
|
|
117
|
+
SELECT
|
|
118
|
+
p.program_code,
|
|
119
|
+
COUNT(*) AS eligible_appointments,
|
|
120
|
+
SUM(CASE WHEN v.visit_status = 'NO_SHOW' THEN 1 ELSE 0 END) AS no_shows,
|
|
121
|
+
ROUND(
|
|
122
|
+
100.0 * SUM(CASE WHEN v.visit_status = 'NO_SHOW' THEN 1 ELSE 0 END)
|
|
123
|
+
/ COUNT(*), 2
|
|
124
|
+
) AS no_show_pct
|
|
125
|
+
FROM visits AS v
|
|
126
|
+
JOIN programs AS p ON p.program_id = v.program_id
|
|
127
|
+
WHERE v.visit_status IN ('COMPLETED', 'NO_SHOW')
|
|
128
|
+
GROUP BY p.program_code
|
|
129
|
+
ORDER BY no_show_pct DESC;
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
This example uses **completed + no-show** visits as its denominator. Organizations may define reportable no-show measures differently.
|
|
133
|
+
|
|
134
|
+
### Individual visit history
|
|
135
|
+
|
|
136
|
+
```sql
|
|
137
|
+
SELECT
|
|
138
|
+
i.individual_id,
|
|
139
|
+
i.full_name,
|
|
140
|
+
p.program_code,
|
|
141
|
+
v.visit_status,
|
|
142
|
+
v.scheduled_start,
|
|
143
|
+
e.full_name AS employee_name
|
|
144
|
+
FROM visits AS v
|
|
145
|
+
JOIN individuals AS i ON i.individual_id = v.individual_id
|
|
146
|
+
JOIN programs AS p ON p.program_id = v.program_id
|
|
147
|
+
JOIN employees AS e ON e.employee_id = v.employee_id
|
|
148
|
+
ORDER BY v.scheduled_start DESC
|
|
149
|
+
LIMIT 20;
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Read actual assessment questions and selected answers
|
|
153
|
+
|
|
154
|
+
BHSim keeps question text and answer choices in lookup tables instead of repeating them in every response. The built-in view joins those tables for you:
|
|
155
|
+
|
|
156
|
+
```sql
|
|
157
|
+
SELECT
|
|
158
|
+
instrument_code,
|
|
159
|
+
question_text,
|
|
160
|
+
selected_answer,
|
|
161
|
+
score_value
|
|
162
|
+
FROM assessment_responses_readable
|
|
163
|
+
LIMIT 20;
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
PHQ-9 contains nine scored symptom items (complete total: **0–27**); GAD-7 contains seven (complete total: **0–21**). Incomplete assessments do not receive a complete total. Scores in BHSim are simulated screening data, **not diagnoses**.
|
|
167
|
+
|
|
168
|
+
## How the tables fit together
|
|
169
|
+
|
|
170
|
+
| Area | Tables | What they represent |
|
|
171
|
+
|---|---|---|
|
|
172
|
+
| People and programs | `individuals`, `programs`, `individual_programs` | Individuals and their enrollment episodes |
|
|
173
|
+
| Workforce | `employees`, `employee_programs`, `employee_supervision` | Staff assignments and reporting relationships |
|
|
174
|
+
| Services | `visits`, `visit_types`, `locations` | Scheduled appointments and documented services |
|
|
175
|
+
| Productivity | `productivity_rules`, `visit_productivity` | Example rules and calculated units |
|
|
176
|
+
| Assessments | `assessment_instruments`, `assessment_questions`, `answer_options`, `assessments`, `assessment_responses`, `assessment_scores` | Forms, questions, selected answers, and scored submissions |
|
|
177
|
+
| Supporting data | `simulation_metadata` | Configuration and generation metadata |
|
|
178
|
+
|
|
179
|
+
There is also an `assessment_responses_readable` **SQL view** for simpler queries.
|
|
180
|
+
|
|
181
|
+
Identifiers are numeric-looking **TEXT** values, with fixed lengths defined by entity type. They are deliberately nonsequential and are joined by ID, not by name. Names may repeat, just as they can in real records.
|
|
182
|
+
|
|
183
|
+
## Customize a run
|
|
184
|
+
|
|
185
|
+
These are the main settings available through the Python API:
|
|
186
|
+
|
|
187
|
+
| Parameter | Example | Meaning |
|
|
188
|
+
|---|---|---|
|
|
189
|
+
| `clients` | `1000` | Number of fictional individuals |
|
|
190
|
+
| `employees` | `80` | Number of fictional staff records |
|
|
191
|
+
| `history_months` | `12` | Historical period to simulate |
|
|
192
|
+
| `future_days` | `30` | Days of upcoming appointments |
|
|
193
|
+
| `reference_date` | `"2026-10-10"` | Simulation's reference date, in `YYYY-MM-DD` format |
|
|
194
|
+
| `seed` | `42` | Controls the pseudorandom sequence for reproducibility |
|
|
195
|
+
|
|
196
|
+
**What is a seed?** With the same BHSim code, settings, and seed, generation is reproducible. Change the seed to get a different fictional dataset. The number `42` has no special meaning.
|
|
197
|
+
|
|
198
|
+
Some program-specific probabilities, operating hours, and productivity assumptions are currently defined internally rather than exposed as configurable API options.
|
|
199
|
+
|
|
200
|
+
## Data checks
|
|
201
|
+
|
|
202
|
+
BHSim includes a validator for core integrity rules:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
python -m bhsim validate demo.db
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
You can also run these independent SQLite checks:
|
|
209
|
+
|
|
210
|
+
```sql
|
|
211
|
+
-- Broken foreign keys: expect no rows
|
|
212
|
+
PRAGMA foreign_key_check;
|
|
213
|
+
|
|
214
|
+
-- Completed visits without valid service timestamps: expect zero
|
|
215
|
+
SELECT COUNT(*) AS invalid_completed_visits
|
|
216
|
+
FROM visits
|
|
217
|
+
WHERE visit_status = 'COMPLETED'
|
|
218
|
+
AND (actual_start IS NULL OR actual_end IS NULL
|
|
219
|
+
OR actual_end <= actual_start);
|
|
220
|
+
|
|
221
|
+
-- Visits without a matching program enrollment: expect zero
|
|
222
|
+
SELECT COUNT(*) AS visits_outside_enrollment
|
|
223
|
+
FROM visits AS v
|
|
224
|
+
WHERE NOT EXISTS (
|
|
225
|
+
SELECT 1
|
|
226
|
+
FROM individual_programs AS ip
|
|
227
|
+
WHERE ip.individual_id = v.individual_id
|
|
228
|
+
AND ip.program_id = v.program_id
|
|
229
|
+
AND DATE(v.scheduled_start) >= DATE(ip.start_date)
|
|
230
|
+
AND (ip.end_date IS NULL OR DATE(v.scheduled_start) <= DATE(ip.end_date))
|
|
231
|
+
);
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Validation checks **consistency**, not whether the generated statistics match real healthcare populations.
|
|
235
|
+
|
|
236
|
+
## Contributing and developing locally
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
git clone https://github.com/rahulbyrapuneni/bhsim.git
|
|
240
|
+
cd bhsim
|
|
241
|
+
python -m pip install -e ".[dev]"
|
|
242
|
+
python -m pytest -q
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
The library's main code lives under `src/bhsim/`. `app.py` is an **optional Streamlit demonstration**; it is not needed for library installation or use. To run the demo, install the optional UI dependencies with `python -m pip install -e ".[ui]"`, then use `python -m streamlit run app.py`.
|
|
246
|
+
|
|
247
|
+
Contributions that improve documentation, validation, reproducibility, or realistic *synthetic* workflows are welcome. Please don't submit real patient records or other protected health information in issues, examples, or tests.
|
|
248
|
+
|
|
249
|
+
## Limitations and responsible use
|
|
250
|
+
|
|
251
|
+
- All records are fictional. BHSim does **not** access EHRs or require patient data.
|
|
252
|
+
- Generated distributions are illustrative; the library has not been validated as a model of real-world clinical outcomes, demographics, or utilization.
|
|
253
|
+
- PHQ-9 and GAD-7 are screening instruments. Simulated scores are not diagnoses, treatment recommendations, or a substitute for clinical judgment.
|
|
254
|
+
- Visit eligibility currently assumes a matching enrollment episode; un-enrolled crisis-service exceptions are not generated in this release.
|
|
255
|
+
- Scheduling checks cover completed-service conflicts, not every possible appointment-booking workflow.
|
|
256
|
+
- Productivity units use demonstration rules and should not be treated as reimbursement or billing guidance.
|
|
257
|
+
- Existing databases are not automatically migrated when the schema changes. Newer releases use `full_name` in place of the older `synthetic_name` column.
|
|
258
|
+
- Questionnaire wording and names belong to their respective instrument originators. Preserve attribution and confirm the relevant usage terms before redistributing or using the instruments clinically.
|
|
259
|
+
|
|
260
|
+
## License and author
|
|
261
|
+
|
|
262
|
+
BHSim is released under the [MIT License](LICENSE). See the repository's `LICENSE` file for its full terms. Instrument attribution and third-party rights are separate from the project's software license.
|
|
263
|
+
|
|
264
|
+
**Creator & maintainer:** [Rahul Byrapuneni](https://github.com/rahulbyrapuneni)
|
|
265
|
+
**Repository:** [github.com/rahulbyrapuneni/bhsim](https://github.com/rahulbyrapuneni/bhsim)
|
|
266
|
+
|
|
267
|
+
Developed using AI-assisted software engineering, with behavioral health domain direction and product design led by the creator.
|
bhsim-1.0.0rc2/README.md
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# BHSim
|
|
2
|
+
|
|
3
|
+
### Synthetic behavioral health data, ready for SQL and analytics
|
|
4
|
+
|
|
5
|
+
BHSim is an open-source Python library that creates **fictional, connected behavioral health records** for SQL practice, BI dashboards, software testing, and analytics prototypes.
|
|
6
|
+
|
|
7
|
+
Instead of hand-building spreadsheets or borrowing sensitive patient data, you can generate a small SQLite database with clients, programs, staff, appointments, enrollments, and screening assessments—and start querying it right away.
|
|
8
|
+
|
|
9
|
+
**Created and maintained by Rahul Byrapuneni.**
|
|
10
|
+
|
|
11
|
+
> **Important:** BHSim generates synthetic test data, not real patient records. Its scheduling, attendance, assessment trajectories, and productivity assumptions are examples for development and learning—not clinical predictions, diagnostic advice, official reporting definitions, or billing guidance.
|
|
12
|
+
|
|
13
|
+
## What can BHSim generate?
|
|
14
|
+
|
|
15
|
+
- **Individuals:** Fictional names, dates of birth, demographic fields, and unique numeric identifiers.
|
|
16
|
+
- **Programs:** Mental health (MH), substance use (SA), and intellectual/developmental disabilities (IDD) services.
|
|
17
|
+
- **Enrollments:** Admissions, discharges, multiple concurrent programs, and re-enrollment histories.
|
|
18
|
+
- **Employees:** Staff records, program assignments, and supervisor relationships.
|
|
19
|
+
- **Visits:** Completed, no-show, canceled, rescheduled, and upcoming appointments, with scheduled and actual service times.
|
|
20
|
+
- **Productivity:** Example service-unit calculations linked to visits and program rules.
|
|
21
|
+
- **Assessments:** PHQ-9 and GAD-7 with readable question text, answer choices, responses, and total scores for complete assessments.
|
|
22
|
+
|
|
23
|
+
The records are linked through primary and foreign keys, so you can practice realistic joins without needing access to an EHR.
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
**Requirements:** Python 3.10 or newer. No database server, paid API, or patient data is needed.
|
|
28
|
+
|
|
29
|
+
BHSim is currently available from its GitHub repository. To install it directly:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
python -m pip install git+https://github.com/rahulbyrapuneni/bhsim.git
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
> PyPI publication is planned, but **`pip install bhsim` is not yet the documented installation method**.
|
|
36
|
+
|
|
37
|
+
Create a file named `example.py`:
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from bhsim import BHSimulator
|
|
41
|
+
|
|
42
|
+
# ---SET UP A SYNTHETIC ORGANIZATION---
|
|
43
|
+
sim = BHSimulator(
|
|
44
|
+
clients=1000,
|
|
45
|
+
employees=80,
|
|
46
|
+
history_months=12,
|
|
47
|
+
future_days=30,
|
|
48
|
+
seed=42,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# ---GENERATE, CHECK, AND EXPORT---
|
|
52
|
+
sim.generate("behavioral_health.db")
|
|
53
|
+
print(sim.validate())
|
|
54
|
+
sim.to_csv("output")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Run:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
python example.py
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
You'll get `behavioral_health.db` plus a folder of CSV files, one for each table. A successful validation returns a result with `"valid": true` and an empty `issues` list.
|
|
64
|
+
|
|
65
|
+
**Already have an output database?** BHSim deliberately refuses to overwrite it. Choose a new filename or move the old one before generating another dataset.
|
|
66
|
+
|
|
67
|
+
### Prefer the command line?
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
python -m bhsim generate demo.db --clients 100 --seed 42
|
|
71
|
+
python -m bhsim validate demo.db
|
|
72
|
+
python -m bhsim export-csv demo.db output
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The installed `bhsim` command can be used instead of `python -m bhsim` when it is available on your PATH.
|
|
76
|
+
|
|
77
|
+
## Explore the data with SQL
|
|
78
|
+
|
|
79
|
+
You can open the generated `.db` file with a SQLite-compatible editor, including [SQLime](https://sqlime.org/), or use Python's built-in `sqlite3` library.
|
|
80
|
+
|
|
81
|
+
### Appointments by program
|
|
82
|
+
|
|
83
|
+
```sql
|
|
84
|
+
SELECT
|
|
85
|
+
p.program_code,
|
|
86
|
+
p.description AS program_name,
|
|
87
|
+
COUNT(*) AS appointments,
|
|
88
|
+
SUM(CASE WHEN v.visit_status = 'COMPLETED' THEN 1 ELSE 0 END) AS completed,
|
|
89
|
+
SUM(CASE WHEN v.visit_status = 'NO_SHOW' THEN 1 ELSE 0 END) AS no_shows
|
|
90
|
+
FROM visits AS v
|
|
91
|
+
JOIN programs AS p ON p.program_id = v.program_id
|
|
92
|
+
GROUP BY p.program_code, p.description
|
|
93
|
+
ORDER BY appointments DESC;
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### No-show rate by program
|
|
97
|
+
|
|
98
|
+
```sql
|
|
99
|
+
SELECT
|
|
100
|
+
p.program_code,
|
|
101
|
+
COUNT(*) AS eligible_appointments,
|
|
102
|
+
SUM(CASE WHEN v.visit_status = 'NO_SHOW' THEN 1 ELSE 0 END) AS no_shows,
|
|
103
|
+
ROUND(
|
|
104
|
+
100.0 * SUM(CASE WHEN v.visit_status = 'NO_SHOW' THEN 1 ELSE 0 END)
|
|
105
|
+
/ COUNT(*), 2
|
|
106
|
+
) AS no_show_pct
|
|
107
|
+
FROM visits AS v
|
|
108
|
+
JOIN programs AS p ON p.program_id = v.program_id
|
|
109
|
+
WHERE v.visit_status IN ('COMPLETED', 'NO_SHOW')
|
|
110
|
+
GROUP BY p.program_code
|
|
111
|
+
ORDER BY no_show_pct DESC;
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
This example uses **completed + no-show** visits as its denominator. Organizations may define reportable no-show measures differently.
|
|
115
|
+
|
|
116
|
+
### Individual visit history
|
|
117
|
+
|
|
118
|
+
```sql
|
|
119
|
+
SELECT
|
|
120
|
+
i.individual_id,
|
|
121
|
+
i.full_name,
|
|
122
|
+
p.program_code,
|
|
123
|
+
v.visit_status,
|
|
124
|
+
v.scheduled_start,
|
|
125
|
+
e.full_name AS employee_name
|
|
126
|
+
FROM visits AS v
|
|
127
|
+
JOIN individuals AS i ON i.individual_id = v.individual_id
|
|
128
|
+
JOIN programs AS p ON p.program_id = v.program_id
|
|
129
|
+
JOIN employees AS e ON e.employee_id = v.employee_id
|
|
130
|
+
ORDER BY v.scheduled_start DESC
|
|
131
|
+
LIMIT 20;
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Read actual assessment questions and selected answers
|
|
135
|
+
|
|
136
|
+
BHSim keeps question text and answer choices in lookup tables instead of repeating them in every response. The built-in view joins those tables for you:
|
|
137
|
+
|
|
138
|
+
```sql
|
|
139
|
+
SELECT
|
|
140
|
+
instrument_code,
|
|
141
|
+
question_text,
|
|
142
|
+
selected_answer,
|
|
143
|
+
score_value
|
|
144
|
+
FROM assessment_responses_readable
|
|
145
|
+
LIMIT 20;
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
PHQ-9 contains nine scored symptom items (complete total: **0–27**); GAD-7 contains seven (complete total: **0–21**). Incomplete assessments do not receive a complete total. Scores in BHSim are simulated screening data, **not diagnoses**.
|
|
149
|
+
|
|
150
|
+
## How the tables fit together
|
|
151
|
+
|
|
152
|
+
| Area | Tables | What they represent |
|
|
153
|
+
|---|---|---|
|
|
154
|
+
| People and programs | `individuals`, `programs`, `individual_programs` | Individuals and their enrollment episodes |
|
|
155
|
+
| Workforce | `employees`, `employee_programs`, `employee_supervision` | Staff assignments and reporting relationships |
|
|
156
|
+
| Services | `visits`, `visit_types`, `locations` | Scheduled appointments and documented services |
|
|
157
|
+
| Productivity | `productivity_rules`, `visit_productivity` | Example rules and calculated units |
|
|
158
|
+
| Assessments | `assessment_instruments`, `assessment_questions`, `answer_options`, `assessments`, `assessment_responses`, `assessment_scores` | Forms, questions, selected answers, and scored submissions |
|
|
159
|
+
| Supporting data | `simulation_metadata` | Configuration and generation metadata |
|
|
160
|
+
|
|
161
|
+
There is also an `assessment_responses_readable` **SQL view** for simpler queries.
|
|
162
|
+
|
|
163
|
+
Identifiers are numeric-looking **TEXT** values, with fixed lengths defined by entity type. They are deliberately nonsequential and are joined by ID, not by name. Names may repeat, just as they can in real records.
|
|
164
|
+
|
|
165
|
+
## Customize a run
|
|
166
|
+
|
|
167
|
+
These are the main settings available through the Python API:
|
|
168
|
+
|
|
169
|
+
| Parameter | Example | Meaning |
|
|
170
|
+
|---|---|---|
|
|
171
|
+
| `clients` | `1000` | Number of fictional individuals |
|
|
172
|
+
| `employees` | `80` | Number of fictional staff records |
|
|
173
|
+
| `history_months` | `12` | Historical period to simulate |
|
|
174
|
+
| `future_days` | `30` | Days of upcoming appointments |
|
|
175
|
+
| `reference_date` | `"2026-10-10"` | Simulation's reference date, in `YYYY-MM-DD` format |
|
|
176
|
+
| `seed` | `42` | Controls the pseudorandom sequence for reproducibility |
|
|
177
|
+
|
|
178
|
+
**What is a seed?** With the same BHSim code, settings, and seed, generation is reproducible. Change the seed to get a different fictional dataset. The number `42` has no special meaning.
|
|
179
|
+
|
|
180
|
+
Some program-specific probabilities, operating hours, and productivity assumptions are currently defined internally rather than exposed as configurable API options.
|
|
181
|
+
|
|
182
|
+
## Data checks
|
|
183
|
+
|
|
184
|
+
BHSim includes a validator for core integrity rules:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
python -m bhsim validate demo.db
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
You can also run these independent SQLite checks:
|
|
191
|
+
|
|
192
|
+
```sql
|
|
193
|
+
-- Broken foreign keys: expect no rows
|
|
194
|
+
PRAGMA foreign_key_check;
|
|
195
|
+
|
|
196
|
+
-- Completed visits without valid service timestamps: expect zero
|
|
197
|
+
SELECT COUNT(*) AS invalid_completed_visits
|
|
198
|
+
FROM visits
|
|
199
|
+
WHERE visit_status = 'COMPLETED'
|
|
200
|
+
AND (actual_start IS NULL OR actual_end IS NULL
|
|
201
|
+
OR actual_end <= actual_start);
|
|
202
|
+
|
|
203
|
+
-- Visits without a matching program enrollment: expect zero
|
|
204
|
+
SELECT COUNT(*) AS visits_outside_enrollment
|
|
205
|
+
FROM visits AS v
|
|
206
|
+
WHERE NOT EXISTS (
|
|
207
|
+
SELECT 1
|
|
208
|
+
FROM individual_programs AS ip
|
|
209
|
+
WHERE ip.individual_id = v.individual_id
|
|
210
|
+
AND ip.program_id = v.program_id
|
|
211
|
+
AND DATE(v.scheduled_start) >= DATE(ip.start_date)
|
|
212
|
+
AND (ip.end_date IS NULL OR DATE(v.scheduled_start) <= DATE(ip.end_date))
|
|
213
|
+
);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Validation checks **consistency**, not whether the generated statistics match real healthcare populations.
|
|
217
|
+
|
|
218
|
+
## Contributing and developing locally
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
git clone https://github.com/rahulbyrapuneni/bhsim.git
|
|
222
|
+
cd bhsim
|
|
223
|
+
python -m pip install -e ".[dev]"
|
|
224
|
+
python -m pytest -q
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
The library's main code lives under `src/bhsim/`. `app.py` is an **optional Streamlit demonstration**; it is not needed for library installation or use. To run the demo, install the optional UI dependencies with `python -m pip install -e ".[ui]"`, then use `python -m streamlit run app.py`.
|
|
228
|
+
|
|
229
|
+
Contributions that improve documentation, validation, reproducibility, or realistic *synthetic* workflows are welcome. Please don't submit real patient records or other protected health information in issues, examples, or tests.
|
|
230
|
+
|
|
231
|
+
## Limitations and responsible use
|
|
232
|
+
|
|
233
|
+
- All records are fictional. BHSim does **not** access EHRs or require patient data.
|
|
234
|
+
- Generated distributions are illustrative; the library has not been validated as a model of real-world clinical outcomes, demographics, or utilization.
|
|
235
|
+
- PHQ-9 and GAD-7 are screening instruments. Simulated scores are not diagnoses, treatment recommendations, or a substitute for clinical judgment.
|
|
236
|
+
- Visit eligibility currently assumes a matching enrollment episode; un-enrolled crisis-service exceptions are not generated in this release.
|
|
237
|
+
- Scheduling checks cover completed-service conflicts, not every possible appointment-booking workflow.
|
|
238
|
+
- Productivity units use demonstration rules and should not be treated as reimbursement or billing guidance.
|
|
239
|
+
- Existing databases are not automatically migrated when the schema changes. Newer releases use `full_name` in place of the older `synthetic_name` column.
|
|
240
|
+
- Questionnaire wording and names belong to their respective instrument originators. Preserve attribution and confirm the relevant usage terms before redistributing or using the instruments clinically.
|
|
241
|
+
|
|
242
|
+
## License and author
|
|
243
|
+
|
|
244
|
+
BHSim is released under the [MIT License](LICENSE). See the repository's `LICENSE` file for its full terms. Instrument attribution and third-party rights are separate from the project's software license.
|
|
245
|
+
|
|
246
|
+
**Creator & maintainer:** [Rahul Byrapuneni](https://github.com/rahulbyrapuneni)
|
|
247
|
+
**Repository:** [github.com/rahulbyrapuneni/bhsim](https://github.com/rahulbyrapuneni/bhsim)
|
|
248
|
+
|
|
249
|
+
Developed using AI-assisted software engineering, with behavioral health domain direction and product design led by the creator.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "bhsim"
|
|
7
|
+
version = "1.0.0rc2"
|
|
8
|
+
description = "Privacy-first synthetic behavioral health operations simulator"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [{name = "Rahul Byrapuneni"}]
|
|
13
|
+
maintainers = [{name = "Rahul Byrapuneni"}]
|
|
14
|
+
keywords = ["synthetic-data", "behavioral-health", "sqlite", "power-bi"]
|
|
15
|
+
|
|
16
|
+
[project.optional-dependencies]
|
|
17
|
+
dev = ["pytest>=8"]
|
|
18
|
+
ui = ["streamlit>=1.35", "pandas>=2.0"]
|
|
19
|
+
|
|
20
|
+
[project.scripts]
|
|
21
|
+
bhsim = "bhsim.cli:main"
|
|
22
|
+
|
|
23
|
+
[tool.setuptools.packages.find]
|
|
24
|
+
where = ["src"]
|
|
25
|
+
|
|
26
|
+
[tool.pytest.ini_options]
|
|
27
|
+
testpaths = ["tests"]
|
bhsim-1.0.0rc2/setup.cfg
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import json
|
|
3
|
+
from .engine import Config, generate, validate, export_csv
|
|
4
|
+
|
|
5
|
+
def main():
|
|
6
|
+
parser=argparse.ArgumentParser(description='BHSim synthetic behavioral health data generator')
|
|
7
|
+
sub=parser.add_subparsers(dest='command',required=True)
|
|
8
|
+
gen=sub.add_parser('generate')
|
|
9
|
+
gen.add_argument('path')
|
|
10
|
+
gen.add_argument('--clients',type=int,default=1000)
|
|
11
|
+
gen.add_argument('--employees',type=int,default=80)
|
|
12
|
+
gen.add_argument('--months',type=int,default=12)
|
|
13
|
+
gen.add_argument('--future-days',type=int,default=30)
|
|
14
|
+
gen.add_argument('--reference-date',default='2026-10-10')
|
|
15
|
+
gen.add_argument('--seed',type=int,default=42)
|
|
16
|
+
valid=sub.add_parser('validate');valid.add_argument('path')
|
|
17
|
+
exp=sub.add_parser('export-csv');exp.add_argument('path');exp.add_argument('directory')
|
|
18
|
+
a=parser.parse_args()
|
|
19
|
+
if a.command=='generate':
|
|
20
|
+
result=generate(a.path,Config(a.clients,a.employees,a.months,a.future_days,a.reference_date,a.seed))
|
|
21
|
+
elif a.command=='validate':result=validate(a.path)
|
|
22
|
+
else:result=export_csv(a.path,a.directory)
|
|
23
|
+
print(json.dumps(result,indent=2))
|
|
24
|
+
if a.command=='validate' and not result['valid']:raise SystemExit(1)
|
|
25
|
+
|
|
26
|
+
if __name__=='__main__': main()
|