feature: Simulator Scenarios + Clinical Validation: SOFA/GCS
This commit is contained in:
@@ -48,150 +48,7 @@ public static class DataSeeder
|
||||
};
|
||||
db.Encounters.AddRange(encounter1, encounter2);
|
||||
|
||||
// Four alert thresholds
|
||||
var thresholds = new List<AlertThreshold>
|
||||
{
|
||||
new() {
|
||||
Id = Guid.NewGuid(), ObservationCode = "HEART_RATE", DisplayName = "Heart Rate",
|
||||
Unit = "bpm", CriticalLow = 30, WarningLow = 50, WarningHigh = 100, CriticalHigh = 150,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new() {
|
||||
Id = Guid.NewGuid(), ObservationCode = "TEMP_C", DisplayName = "Body Temperature",
|
||||
Unit = "°C", CriticalLow = 35.0m, WarningLow = 36.0m, WarningHigh = 38.3m, CriticalHigh = 40.0m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new() {
|
||||
Id = Guid.NewGuid(), ObservationCode = "POTASSIUM_MEQ_L", DisplayName = "Serum Potassium",
|
||||
Unit = "mEq/L", CriticalLow = 2.5m, WarningLow = 3.5m, WarningHigh = 5.0m, CriticalHigh = 6.5m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new() {
|
||||
Id = Guid.NewGuid(), ObservationCode = "SPO2", DisplayName = "Oxygen Saturation",
|
||||
Unit = "%", CriticalLow = 88, WarningLow = 92, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "RESP_RATE",
|
||||
DisplayName = "Respiratory Rate", Unit = "breaths/min",
|
||||
CriticalLow = null, WarningLow = 12m, WarningHigh = 20m, CriticalHigh = 30m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "WBC_K_UL",
|
||||
DisplayName = "White Blood Cell Count", Unit = "k/µL",
|
||||
CriticalLow = 2.0m, WarningLow = 4.0m, WarningHigh = 12.0m, CriticalHigh = 20.0m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "SYSTOLIC_BP",
|
||||
DisplayName = "Systolic Blood Pressure", Unit = "mmHg",
|
||||
CriticalLow = 70m, WarningLow = 90m, WarningHigh = 160m, CriticalHigh = 180m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "DIASTOLIC_BP",
|
||||
DisplayName = "Diastolic Blood Pressure", Unit = "mmHg",
|
||||
CriticalLow = 40m, WarningLow = 60m, WarningHigh = 90m, CriticalHigh = 110m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "LACTATE_MMOL_L",
|
||||
DisplayName = "Serum Lactate", Unit = "mmol/L",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = 2.0m, CriticalHigh = 4.0m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "AVPU",
|
||||
DisplayName = "AVPU Consciousness Level", Unit = "score",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = null, CriticalHigh = 2m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "SUPPLEMENTAL_O2",
|
||||
DisplayName = "Supplemental Oxygen", Unit = "flag",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "GLUCOSE_MG_DL",
|
||||
DisplayName = "Blood Glucose", Unit = "mg/dL",
|
||||
CriticalLow = 40m, WarningLow = 70m, WarningHigh = 180m, CriticalHigh = 400m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
// GCS components — registered for ingestion; thresholds are null (alerting is on computed total in GcsDetector)
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "GCS_EYE",
|
||||
DisplayName = "GCS Eye Response", Unit = "score",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "GCS_VERBAL",
|
||||
DisplayName = "GCS Verbal Response", Unit = "score",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "GCS_MOTOR",
|
||||
DisplayName = "GCS Motor Response", Unit = "score",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "PAO2_MMHG",
|
||||
DisplayName = "Partial Pressure O2 (Arterial)", Unit = "mmHg",
|
||||
CriticalLow = 60m, WarningLow = 80m, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "FIO2_PCT",
|
||||
DisplayName = "Fraction of Inspired O2", Unit = "%",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "PLATELET_K_UL",
|
||||
DisplayName = "Platelet Count", Unit = "k/µL",
|
||||
CriticalLow = 20m, WarningLow = 50m, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "BILIRUBIN_MG_DL",
|
||||
DisplayName = "Total Bilirubin", Unit = "mg/dL",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = 2.0m, CriticalHigh = 6.0m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "CREATININE_MG_DL",
|
||||
DisplayName = "Serum Creatinine", Unit = "mg/dL",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = 2.0m, CriticalHigh = 3.5m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "URINE_OUTPUT_ML_H",
|
||||
DisplayName = "Urine Output", Unit = "mL/h",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
};
|
||||
var thresholds = BuildDefaultThresholds();
|
||||
db.AlertThresholds.AddRange(thresholds);
|
||||
|
||||
// Observations spanning normal, warning, and critical ranges for encounter1
|
||||
@@ -235,8 +92,163 @@ public static class DataSeeder
|
||||
db.Observations.AddRange(observations);
|
||||
|
||||
await db.SaveChangesAsync();
|
||||
await CacheThresholdsAsync(redis, thresholds);
|
||||
}
|
||||
|
||||
// Populate Redis cache with the seeded thresholds
|
||||
public static async Task SeedThresholdsOnlyAsync(AppDbContext db, IConnectionMultiplexer redis)
|
||||
{
|
||||
var thresholds = BuildDefaultThresholds();
|
||||
db.AlertThresholds.AddRange(thresholds);
|
||||
await db.SaveChangesAsync();
|
||||
await CacheThresholdsAsync(redis, thresholds);
|
||||
}
|
||||
|
||||
public static List<AlertThreshold> BuildDefaultThresholds() => new()
|
||||
{
|
||||
new() {
|
||||
Id = Guid.NewGuid(), ObservationCode = "HEART_RATE", DisplayName = "Heart Rate",
|
||||
Unit = "bpm", CriticalLow = 30, WarningLow = 50, WarningHigh = 100, CriticalHigh = 150,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new() {
|
||||
Id = Guid.NewGuid(), ObservationCode = "TEMP_C", DisplayName = "Body Temperature",
|
||||
Unit = "°C", CriticalLow = 35.0m, WarningLow = 36.0m, WarningHigh = 38.3m, CriticalHigh = 40.0m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new() {
|
||||
Id = Guid.NewGuid(), ObservationCode = "POTASSIUM_MEQ_L", DisplayName = "Serum Potassium",
|
||||
Unit = "mEq/L", CriticalLow = 2.5m, WarningLow = 3.5m, WarningHigh = 5.0m, CriticalHigh = 6.5m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new() {
|
||||
Id = Guid.NewGuid(), ObservationCode = "SPO2", DisplayName = "Oxygen Saturation",
|
||||
Unit = "%", CriticalLow = 88, WarningLow = 92, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "RESP_RATE",
|
||||
DisplayName = "Respiratory Rate", Unit = "breaths/min",
|
||||
CriticalLow = null, WarningLow = 12m, WarningHigh = 20m, CriticalHigh = 30m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "WBC_K_UL",
|
||||
DisplayName = "White Blood Cell Count", Unit = "k/µL",
|
||||
CriticalLow = 2.0m, WarningLow = 4.0m, WarningHigh = 12.0m, CriticalHigh = 20.0m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "SYSTOLIC_BP",
|
||||
DisplayName = "Systolic Blood Pressure", Unit = "mmHg",
|
||||
CriticalLow = 70m, WarningLow = 90m, WarningHigh = 160m, CriticalHigh = 180m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "DIASTOLIC_BP",
|
||||
DisplayName = "Diastolic Blood Pressure", Unit = "mmHg",
|
||||
CriticalLow = 40m, WarningLow = 60m, WarningHigh = 90m, CriticalHigh = 110m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "LACTATE_MMOL_L",
|
||||
DisplayName = "Serum Lactate", Unit = "mmol/L",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = 2.0m, CriticalHigh = 4.0m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "AVPU",
|
||||
DisplayName = "AVPU Consciousness Level", Unit = "score",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = null, CriticalHigh = 2m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "SUPPLEMENTAL_O2",
|
||||
DisplayName = "Supplemental Oxygen", Unit = "flag",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "GLUCOSE_MG_DL",
|
||||
DisplayName = "Blood Glucose", Unit = "mg/dL",
|
||||
CriticalLow = 40m, WarningLow = 70m, WarningHigh = 180m, CriticalHigh = 400m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "GCS_EYE",
|
||||
DisplayName = "GCS Eye Response", Unit = "score",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "GCS_VERBAL",
|
||||
DisplayName = "GCS Verbal Response", Unit = "score",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "GCS_MOTOR",
|
||||
DisplayName = "GCS Motor Response", Unit = "score",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "PAO2_MMHG",
|
||||
DisplayName = "Partial Pressure O2 (Arterial)", Unit = "mmHg",
|
||||
CriticalLow = 60m, WarningLow = 80m, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "FIO2_PCT",
|
||||
DisplayName = "Fraction of Inspired O2", Unit = "%",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "PLATELET_K_UL",
|
||||
DisplayName = "Platelet Count", Unit = "k/µL",
|
||||
CriticalLow = 20m, WarningLow = 50m, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "BILIRUBIN_MG_DL",
|
||||
DisplayName = "Total Bilirubin", Unit = "mg/dL",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = 2.0m, CriticalHigh = 6.0m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "CREATININE_MG_DL",
|
||||
DisplayName = "Serum Creatinine", Unit = "mg/dL",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = 2.0m, CriticalHigh = 3.5m,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
new AlertThreshold
|
||||
{
|
||||
Id = Guid.NewGuid(), ObservationCode = "URINE_OUTPUT_ML_H",
|
||||
DisplayName = "Urine Output", Unit = "mL/h",
|
||||
CriticalLow = null, WarningLow = null, WarningHigh = null, CriticalHigh = null,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
},
|
||||
};
|
||||
|
||||
private static async Task CacheThresholdsAsync(
|
||||
IConnectionMultiplexer redis, IEnumerable<AlertThreshold> thresholds)
|
||||
{
|
||||
var cache = redis.GetDatabase();
|
||||
foreach (var t in thresholds)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user