13 KiB
VigilCare Clinical Simulator -- User Guide
Welcome! The VigilCare Simulator lets you replay realistic hospital patient scenarios against the VigilCare Clinical API. You can watch a patient's vitals change over time, see alerts fire (NEWS2, SIRS/qSOFA, sepsis bundles), and observe how the system detects clinical deterioration -- all without real patients.
Think of it as a flight simulator, but for clinical decision support.
Table of Contents
- Prerequisites
- Quick Start
- Available Commands
- Understanding Scenarios
- Available Scenarios
- Controlling Replay Speed
- Reading the Output
- Creating Your Own Scenarios
- Troubleshooting
1. Prerequisites
You need two things installed:
- .NET 8 SDK -- Download from dotnet.microsoft.com
- The VigilCare API running locally -- The simulator sends data to the API, so it must be up first
Starting the API
From the project root directory, run:
docker compose up -d
dotnet run --project VigilCare.Api
The API starts on http://localhost:5270 by default.
See docker-compose-usage-and-troubleshooting.md if you have trouble with Docker.
2. Quick Start
Open a terminal in the project root and run:
dotnet run --project VigilCare.Simulator -- replay \
VigilCare.Simulator/Scenarios/List/uti-sepsis-elderly-01.json \
--speed 60 --poll
This replays a 4-hour UTI-to-sepsis progression in about 4 seconds, showing alerts as they fire.
That's it! Read on for more detail.
3. Available Commands
The simulator has four commands. All are run with dotnet run --project VigilCare.Simulator -- <command>.
replay -- Run a scenario against the API
dotnet run --project VigilCare.Simulator -- replay <scenario-file> [options]
Options:
| Option | Default | Description |
|---|---|---|
--speed <number> |
60 | How fast to run (see Speed) |
--base-url <url> |
http://localhost:5270 |
API address (change if your API runs elsewhere) |
--poll |
off | Show alerts and scores after each set of vitals |
--poll-interval <seconds> |
5 | How often to check for alerts when polling |
Example -- run the stable baseline scenario in real-time with polling:
dotnet run --project VigilCare.Simulator -- replay \
VigilCare.Simulator/Scenarios/List/stable-baseline-01.json \
--speed 1 --poll
replay-all -- Run every scenario in a folder
dotnet run --project VigilCare.Simulator -- replay-all <directory> [options]
Runs all .json scenario files in the given directory, one after another. Accepts --speed and --base-url.
Example:
dotnet run --project VigilCare.Simulator -- replay-all \
VigilCare.Simulator/Scenarios/List --speed 60
validate -- Check a scenario file for errors
dotnet run --project VigilCare.Simulator -- validate <scenario-file>
Checks that the JSON is well-formed and all fields are valid. Does not contact the API.
Example:
dotnet run --project VigilCare.Simulator -- validate \
VigilCare.Simulator/Scenarios/List/stable-baseline-01.json
dry-run -- Preview the timeline without touching the API
dotnet run --project VigilCare.Simulator -- dry-run <scenario-file>
Prints exactly what would happen (every vital sign, medication, and order) without sending anything.
Example:
dotnet run --project VigilCare.Simulator -- dry-run \
VigilCare.Simulator/Scenarios/List/cardiac-arrest-post-mi-01.json
4. Understanding Scenarios
Each scenario is a JSON file that tells a clinical story. It contains:
- Patient -- Name, date of birth, gender
- Encounter -- Department, encounter type, attending physician, room/bed
- Events -- A timeline of observations (vitals, labs), medications, and orders
Here is what a simplified scenario looks like:
{
"scenario": {
"id": "stable-baseline-01",
"name": "Stable Baseline -- Routine Inpatient Monitoring",
"description": "52-year-old female admitted for elective cholecystectomy...",
"durationMinutes": 480,
"tags": ["stable", "baseline", "control", "surgery"]
},
"patient": {
"firstName": "Linda",
"lastName": "Weston",
"dateOfBirth": "1974-02-18",
"gender": "Female"
},
"encounter": {
"department": "Surgery",
"encounterType": "Inpatient",
"attendingPhysician": "Dr. James Nakamura",
"roomBed": "SURG-204B",
"admissionReason": "Elective laparoscopic cholecystectomy"
},
"events": [
{
"offsetMinutes": 0,
"type": "observation",
"data": {
"code": "HEART_RATE",
"value": 72,
"unit": "bpm"
},
"note": "Post-op arrival, patient alert and comfortable"
},
{
"offsetMinutes": 60,
"type": "medication",
"data": {
"drugName": "acetaminophen",
"dose": 1000,
"doseUnit": "mg",
"route": "PO",
"administeredBy": "RN Davis"
}
}
]
}
The key concept is offsetMinutes -- each event happens at a certain number of minutes after the scenario starts. The simulator waits the appropriate amount of time (adjusted by your speed setting) before sending each event.
Event Types
| Type | What It Represents | Example |
|---|---|---|
observation |
A vital sign or lab result | Heart rate 110 bpm, Temperature 39.2 C |
medication |
A drug being administered | Ceftriaxone 1g IV |
order |
A clinical order being placed | "Blood cultures", "Chest X-ray" |
order_result |
Result of a prior order | "Positive for E. coli" |
Vital Sign Codes
These are the observation codes used in scenarios:
| Code | What It Measures | Unit | Normal Range |
|---|---|---|---|
HEART_RATE |
Heart rate | bpm | 51--90 |
RESP_RATE |
Respiratory rate | /min | 12--20 |
SYSTOLIC_BP |
Systolic blood pressure | mmHg | 111--219 |
DIASTOLIC_BP |
Diastolic blood pressure | mmHg | 60--90 |
TEMP_C |
Temperature | C | 36.1--38.0 |
SPO2 |
Oxygen saturation | % | 96--100 |
AVPU |
Consciousness level | score | 0 = Alert |
SUPPLEMENTAL_O2 |
On supplemental oxygen? | flag | 0 = No |
WBC_K_UL |
White blood cell count | x10^3/uL | 4.5--11.0 |
LACTATE_MMOL_L |
Serum lactate | mmol/L | 0.5--1.5 |
POTASSIUM_MEQ_L |
Potassium | mEq/L | 3.5--5.0 |
GLUCOSE_MG_DL |
Blood glucose | mg/dL | 70--140 |
5. Available Scenarios
The simulator ships with 8 scenarios covering different clinical situations:
| Scenario | Clinical Story | Duration |
|---|---|---|
| stable-baseline-01 | Post-op cholecystectomy, all vitals normal. Control case -- no alerts should fire. | 8 hours |
| uti-sepsis-elderly-01 | 78-year-old with UTI progressing to sepsis. SIRS criteria met, sepsis bundle triggered. | 4 hours |
| cardiac-arrest-post-mi-01 | Post-MI patient deteriorating into cardiogenic shock. Rapid HR/BP changes. | Varies |
| post-op-hemorrhage-01 | Surgical patient with internal bleeding. Rising HR, falling BP and SpO2. | Varies |
| respiratory-failure-asthma-01 | Asthma exacerbation progressing to respiratory failure. Falling SpO2, rising RR. | Varies |
| dka-electrolyte-01 | Diabetic ketoacidosis with potassium and glucose derangement. | Varies |
| hypothermia-elderly-01 | Elderly patient with severe hypothermia. Slow HR, dropping temperature. | Varies |
| medication-false-alarm-01 | Beta-blocker causing bradycardia. Tests whether the system correctly handles medication-induced vital changes. | 3 hours |
All scenario files are in: VigilCare.Simulator/Scenarios/List/
6. Controlling Replay Speed
The --speed option controls how fast simulated time passes:
| Speed | Meaning | A 4-hour scenario takes... |
|---|---|---|
0 |
Instant -- no waiting, all events fire immediately | < 1 second |
1 |
Real-time -- 1 simulated minute = 1 real minute | 4 hours |
10 |
10x -- 1 simulated minute = 6 real seconds | 24 minutes |
60 |
60x (default) -- 1 simulated minute = 1 real second | 4 minutes |
120 |
120x -- 1 simulated minute = 0.5 real seconds | 2 minutes |
Recommendations:
- For demos / presentations: Use
--speed 10with--pollso people can follow along - For quick testing: Use
--speed 60or--speed 0 - For the most realistic experience: Use
--speed 1(real-time, a 4-hour scenario takes 4 hours)
7. Reading the Output
When you run a replay, the simulator prints a colored timeline. Here's what to look for:
────────────────── Stable Baseline -- Routine Inpatient Monitoring ──────────────────
52-year-old female admitted for elective cholecystectomy...
Patient registered: 3fa85f64-... (MRN-12345)
Encounter opened: 7c9e6679-... (active)
[00:00] HEART_RATE 72 bpm
[00:00] RESP_RATE 14 /min
[00:00] SYSTOLIC_BP 124 mmHg
[00:00] SPO2 98 %
... waiting 60m simulated (1.0s real) ...
[01:00] HEART_RATE 74 bpm
[01:00] medication: acetaminophen 1000 mg PO
With --poll enabled, you also see clinical scoring:
[01:30] NEWS2 = 5 (Medium)
[01:30] ALERT SEPSIS_WARNING (Critical)
[01:30] SEPSIS BUNDLE InProgress (2/4 completed)
At the end, a summary table appears:
Metric Value
-----------------------------------
Scenario uti-sepsis-elderly-01
Observations sent 42
Medications sent 2
Orders placed 3
Wall-clock time 12.3s
What the Alerts Mean
| Alert | Meaning |
|---|---|
NEWS2_LOW |
NEWS2 score 1--4: Low risk, routine monitoring |
NEWS2_MEDIUM |
NEWS2 score 5--6 or single parameter score of 3: Urgent review needed |
NEWS2_HIGH |
NEWS2 score 7+: Emergency response needed |
SEPSIS_WARNING |
SIRS criteria met (2+ of: temp, HR, RR, WBC abnormal) |
QSOFA_WARNING |
qSOFA criteria met (2+ of: altered mentation, RR >= 22, SBP <= 100) |
RAPID_DETERIORATION |
Sudden significant change in vital signs |
8. Creating Your Own Scenarios
You can create new clinical scenarios by writing a JSON file. There are two ways:
Option A: Write it manually
- Copy an existing scenario from
VigilCare.Simulator/Scenarios/List/as a template - Modify the patient, encounter, and events to match your clinical story
- Make sure
offsetMinutesvalues are in ascending order - Validate it:
dotnet run --project VigilCare.Simulator -- validate ./my-scenario.json
Option B: Use AI to generate it
There is a generation prompt file at VigilCare.Simulator/Scenarios/GENERATE_PROMPT.md. You can paste its contents into ChatGPT, Claude, or another AI assistant, describe the clinical case you want, and it will generate a valid scenario JSON file for you.
Validation Rules
The simulator enforces these rules on scenario files:
- scenario.id and scenario.name are required
- encounter.department must be one of:
Icu,GeneralMedicine,Emergency,Cardiology,Surgery,Pediatrics - encounter.encounterType must be one of:
Inpatient,Outpatient,Emergency - events must be non-empty, with
offsetMinutesin ascending order - observation codes must match one of the 12 valid codes listed above
- Maximum 10 observations per time point (API batch limit)
- order_result events must reference a matching prior order (or a sepsis bundle auto-order)
Sepsis Bundle Auto-Orders
When the system detects sepsis (SIRS or qSOFA criteria met), it automatically creates four orders:
SEP-1: Blood culturesSEP-1: Serum lactateSEP-1: Broad-spectrum antibioticsSEP-1: IV fluid bolus
You do not need to create order events for these. Just add order_result events referencing them to simulate bundle completion.
9. Troubleshooting
"Connection refused" error
The API is not running. Start it first:
docker compose up -d
dotnet run --project VigilCare.Api
"scenario.json has N error(s)"
Run validate to see what's wrong:
dotnet run --project VigilCare.Simulator -- validate ./your-scenario.json
Common issues:
- Invalid department name (must match exact casing:
Icu, notICU) offsetMinutesout of order- Missing required fields (
scenario.id,scenario.name,encounter.attendingPhysician)
Medications show "skipped"
The medication tracking endpoint may not be available. This is non-fatal -- the scenario continues.
"dotnet" command not found
Install .NET 8 SDK from dotnet.microsoft.com.
I want to point the simulator at a different API
Use --base-url:
dotnet run --project VigilCare.Simulator -- replay scenario.json \
--base-url http://192.168.1.50:5270