updated simulator to include smoothing of simulated vitals to make more realistic

This commit is contained in:
Raika Furude 2025-11-01 15:40:19 -04:00
parent 4cd0ac3fee
commit 3509ba7578
10 changed files with 1362 additions and 1115 deletions

View File

@ -1,4 +0,0 @@
215078
215139
215153
215223

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
215078

View File

@ -3,7 +3,7 @@
> vite
VITE v7.1.10 ready in 104 ms
VITE v7.1.10 ready in 107 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose

View File

@ -1 +0,0 @@
215153

View File

@ -4,7 +4,7 @@
Port 5173 is in use, trying another one...
VITE v7.1.10 ready in 113 ms
VITE v7.1.10 ready in 107 ms
➜ Local: http://localhost:5174/
➜ Network: use --host to expose

View File

@ -1 +0,0 @@
215223

View File

@ -1 +0,0 @@
215139

View File

@ -56,61 +56,60 @@ PATIENT_PROFILES = {
"stable": PatientProfile(
name="Stable Patient",
hr_base=72,
hr_variance=5,
hr_variance=3, # Reduced from 5
spo2_base=98,
spo2_variance=1,
spo2_variance=0.5, # Reduced from 1
temp_base=36.8,
temp_variance=0.2,
temp_variance=0.1, # Reduced from 0.2
deterioration_rate=0.0,
recovery_rate=0.0,
),
"mild_anxiety": PatientProfile(
name="Mild Anxiety",
hr_base=88,
hr_variance=8,
hr_base=105,
hr_variance=5, # Reduced from 8
spo2_base=97,
spo2_variance=1,
temp_base=37.1,
temp_variance=0.3,
spo2_variance=0.5,
temp_base=37.8,
temp_variance=0.2,
deterioration_rate=0.0,
recovery_rate=0.01, # Slowly calms down
recovery_rate=0.02,
),
"deteriorating": PatientProfile(
name="Deteriorating Condition",
hr_base=85,
hr_variance=10,
spo2_base=95,
spo2_variance=2,
temp_base=37.5,
temp_variance=0.4,
deterioration_rate=0.05, # Gets worse over time
hr_base=108,
hr_variance=4, # Reduced from 10 - KEY CHANGE
spo2_base=93,
spo2_variance=1, # Reduced from 2
temp_base=38.0,
temp_variance=0.2, # Reduced from 0.4
deterioration_rate=1.5, # Smooth, steady increase
recovery_rate=0.0,
),
"critical": PatientProfile(
name="Critical Patient",
hr_base=130,
hr_variance=15,
spo2_base=88,
spo2_variance=3,
temp_base=39.2,
temp_variance=0.5,
deterioration_rate=0.02,
hr_base=145,
hr_variance=8, # Reduced from 15
spo2_base=87,
spo2_variance=2, # Reduced from 3
temp_base=39.7,
temp_variance=0.3, # Reduced from 0.5
deterioration_rate=0.2, # Slight worsening
recovery_rate=0.0,
),
"sepsis": PatientProfile(
name="Sepsis Presentation",
hr_base=115,
hr_variance=12,
spo2_base=92,
spo2_variance=2,
temp_base=38.8,
temp_variance=0.6,
deterioration_rate=0.08, # Rapid deterioration
hr_base=125,
hr_variance=8, # Reduced from 12
spo2_base=90,
spo2_variance=1, # Reduced from 2
temp_base=39.2,
temp_variance=0.3, # Reduced from 0.6
deterioration_rate=1.0,
recovery_rate=0.0,
),
}
# ============================================================================
# WRISTBAND SIMULATOR
# ============================================================================
@ -139,16 +138,21 @@ class WristbandSimulator:
# Time since condition change
self.time_elapsed = 0
# Add smoothing buffer
self.hr_history = []
self.spo2_history = []
self.temp_history = []
def _calculate_checksum(self, data: bytes) -> int:
"""Calculate 8-bit checksum"""
return sum(data[0:14]) & 0xFF
def _generate_vitals(self) -> tuple:
"""Generate realistic vital signs with progression"""
"""Generate realistic vital signs with progression and smoothing"""
self.time_elapsed += 1
# Apply deterioration/recovery over time
# Apply deterioration/recovery
if self.profile.deterioration_rate > 0:
self.current_hr += random.uniform(0, self.profile.deterioration_rate * 2)
self.current_spo2 -= random.uniform(
@ -159,7 +163,6 @@ class WristbandSimulator:
)
if self.profile.recovery_rate > 0:
# Trend back toward normal
self.current_hr += (72 - self.current_hr) * self.profile.recovery_rate
self.current_spo2 += (98 - self.current_spo2) * self.profile.recovery_rate
self.current_temp += (36.8 - self.current_temp) * self.profile.recovery_rate
@ -174,11 +177,27 @@ class WristbandSimulator:
spo2 = max(70, min(100, spo2))
temp = max(34.0, min(42.0, temp))
# Activity varies (simulates patient movement)
# Apply moving average smoothing (reduces jitter)
self.hr_history.append(hr)
self.spo2_history.append(spo2)
self.temp_history.append(temp)
# Keep last 3 readings for smoothing
if len(self.hr_history) > 3:
self.hr_history = self.hr_history[-3:]
self.spo2_history = self.spo2_history[-3:]
self.temp_history = self.temp_history[-3:]
# Use average of last 3 readings
hr_smoothed = sum(self.hr_history) / len(self.hr_history)
spo2_smoothed = sum(self.spo2_history) / len(self.spo2_history)
temp_smoothed = sum(self.temp_history) / len(self.temp_history)
# Activity varies
self.activity_level += random.gauss(0, 0.1)
self.activity_level = max(0, min(2.0, self.activity_level))
return int(hr), int(spo2), temp, self.activity_level
return int(hr_smoothed), int(spo2_smoothed), temp_smoothed, self.activity_level
def _determine_tier(self, hr: int, spo2: int, temp: float) -> tuple:
"""Determine flags based on vitals - tier determined by backend"""