Skip to content

Instantly share code, notes, and snippets.

@halcwb
Created March 17, 2021 08:45
Show Gist options
  • Save halcwb/49624106b8e5f702f7e051d10d9ea261 to your computer and use it in GitHub Desktop.
Save halcwb/49624106b8e5f702f7e051d10d9ea261 to your computer and use it in GitHub Desktop.
OncoSepsis
#r "nuget: SqlProvider"
#r "nuget: FSharp.Stats"
#r "nuget: Plotly.NET, 2.0.0-beta5"
#r "nuget: Informedica.Utils.Lib"
open System
open System.Text
open FSharp.Data.Sql
open FSharp.Stats
open Plotly.NET
open Informedica.Utils.Lib
Environment.CurrentDirectory <- __SOURCE_DIRECTORY__
fsi.AddPrinter<DateTime> (fun dt -> dt.ToString("dd-MM-yyyy HH:mm"))
module StringBuilder =
let builder (s : string) = StringBuilder(s)
let append (s : string) (sb : StringBuilder) = sb.Append(s)
let appendLine (s : string) (sb : StringBuilder) = sb.AppendLine(s)
let newLine = appendLine ""
let newLine2 sb =
sb
|> appendLine ""
|> appendLine ""
let appendFormat (fs : string) vs (sb : StringBuilder) = sb.AppendFormat(fs, (vs |> List.toArray))
let appendLineFormat (fs : string) vs (sb : StringBuilder) = sb.AppendFormat(fs + "\n", (vs |> List.toArray))
let replace (s1 : string) s2 (sb : StringBuilder) = sb.Replace(s1, s2)
let toString (sb : StringBuilder) = sb.ToString()
module File =
open System
open System.IO
let appendTextToFile path (s : string) =
File.AppendAllText(path, s)
[<Literal>]
let resolutionPath = __SOURCE_DIRECTORY__ + "\libs"
[<Literal>]
let connString = @"Data Source=VOXDB-PICURED01;Initial Catalog=PICURED;Persist Security Info=True;Integrated Security=SSPI;Connection Timeout=0;Command Timeout=0;"
[<Literal>]
let schemaPath = __SOURCE_DIRECTORY__ + "\schema\picured.schema"
type NumericalData =
{
Name : string
Label : string
Values : (DateTime * float) []
}
type Patient =
{
HospNum : string
BirthDate : DateTime
Gender : string
Weight : float option
AdmNo : int
AdmTime : DateTime
DisTime : DateTime
EndTime : DateTime
Data : NumericalData []
Sepsis : bool
Specialism : string
Diagnoses : string []
PIM2 : float option
PIM3 : float option
PRISMIV : float option
Outcome : string
}
let addPatientData (pat: Patient) label name values =
{ pat with
Data =
[|
{
Name = name
Label = label
Values = values
}
|]
|> Array.append pat.Data
}
type sql = SqlDataProvider<Common.DatabaseProviderTypes.MSSQLSERVER_DYNAMIC,
connString,
ResolutionPath = resolutionPath,
UseOptionTypes = true,
ContextSchemaPath = schemaPath,
CaseSensitivityChange = Common.CaseSensitivityChange.ORIGINAL>
let getPatientHospAdmissions (ctx: sql.dataContext) =
query {
for r in ctx.Dbo.DataOncoSepsis do
where (r.PatAdmNo.IsSome && r.PatBirthdate.IsSome)
distinct
select (
{|
hospnum = r.PatHospId
birthDate = r.PatBirthdate.Value
gender = r.PatSex
weight = r.PatAdmWeight
admno = r.PatAdmNo.Value
pim2 = r.PatAdmPim2
pim3 = r.PatAdmPim3
prismIV = r.PatAdmPrismIv
outcome = r.PatAdmOutcome |> Option.defaultValue ""
|}
)
}
|> Seq.toArray
|> Array.sortBy (fun x -> x.hospnum, x.admno)
let calcGCS (e : string option) (m: string option) (v: string option) =
let toInt d (s : string option) =
match s with
| None -> d
| Some s ->
s.Split('-')
|> Array.toList
|> function
| h::_ ->
h
|> Int32.TryParse
|> function
| true, i -> i
| false, _ -> 0
| _ -> d
let e = e |> toInt 5
let m = m |> toInt 6
let v = v |> toInt 4
e + m + v
let mapPatients (ctx: sql.dataContext) (pats : {| hospnum : string;
birthDate : DateTime;
gender : string option;
weight : float option;
admno : int
pim2 : float option
pim3 : float option
prismIV : float option
outcome : string |} []) =
pats
|> Array.sortBy (fun r -> r.hospnum, r.admno)
|> Array.map (fun r ->
let admTime =
query {
for x in ctx.Dbo.DataOncoSepsis do
where (x.PatHospId = r.hospnum && x.PatAdmNo.Value = r.admno)
sortBy x.PatDatetime
take 1
select x.PatDatetime
}
|> Seq.tryHead
let disTime =
query {
for x in ctx.Dbo.DataOncoSepsis do
where (x.PatHospId = r.hospnum && x.PatAdmNo.Value = r.admno)
sortByDescending x.PatDatetime
take 1
select x.PatDatetime
}
|> Seq.tryHead
let endTime = admTime |> Option.map (fun dt -> dt.AddHours(24.))
{|
hospnum = r.hospnum
birthDate = r.birthDate
gender = r.gender |> Option.defaultValue ""
weight = r.weight
admno = r.admno
admTime = admTime
disTime = disTime
endTime = endTime
pim2 = r.pim2
pim3 = r.pim3
prismIV = r.prismIV
outcome = r.outcome
|}
)
|> Array.filter (fun x -> x.admTime.IsSome && x.disTime.IsSome)
|> Array.map (fun x ->
{
HospNum = x.hospnum
BirthDate = x.birthDate
Gender = x.gender
Weight = x.weight
AdmNo = x.admno
AdmTime = x.admTime.Value
DisTime = x.disTime.Value
EndTime = x.endTime.Value
Data = [||]
Sepsis = false
Specialism = ""
Diagnoses = [||]
PIM2 = x.pim2
PIM3 = x.pim3
PRISMIV = x.prismIV
Outcome = x.outcome
}
|> fun p ->
p,
query {
for d in ctx.Dbo.DataOncoSepsis do
where (
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select d
}
|> Seq.toArray
|> fun (p, data) ->
query {
for d in data do
where (
d.MonIbpSys.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.MonIbpSys.Value)
}
|> Seq.toArray
|> addPatientData p "Systolic invasive blood pressure" "sbp", data
|> fun (p, data) ->
query {
for d in data do
where (
d.MonIbpDia.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.MonIbpDia.Value)
}
|> Seq.toArray
|> addPatientData p "Diastolic invasive blood pressure" "dbp", data
|> fun (p, data) ->
query {
for d in data do
where (
d.MonIbpMean.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.MonIbpMean.Value)
}
|> Seq.toArray
|> addPatientData p "Mean invasive blood pressure" "mbp", data
|> fun (p, data) ->
query {
for d in data do
where (
d.MonNibpSys.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.MonNibpSys.Value)
}
|> Seq.toArray
|> addPatientData p "Systolic non-invasive blood pressure" "nibps", data
|> fun (p, data) ->
query {
for d in data do
where (
d.MonNibpDia.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.MonNibpDia.Value)
}
|> Seq.toArray
|> addPatientData p "Diastolic non-invasive blood pressure" "nibpd", data
|> fun (p, data) ->
query {
for d in data do
where (
d.MonNibpMean.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.MonNibpMean.Value)
}
|> Seq.toArray
|> addPatientData p "Mean non-invasive blood pressure" "nibpm", data
|> fun (p, data) ->
query {
for d in data do
where (
d.MonRr.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.MonRr.Value)
}
|> Seq.toArray
|> addPatientData p "Respiratory rate" "rr", data
|> fun (p, data) ->
query {
for d in data do
where (
d.MonCvp.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.MonCvp.Value)
}
|> Seq.toArray
|> addPatientData p "Central venuous pressure" "cvp", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBgPo2.IsSome && d.MonIbpMean.IsSome && // arterial bg if invasive bp
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBgPo2.Value)
}
|> Seq.toArray
|> addPatientData p "Arterial pO2" "pO2", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBgSat.IsSome && d.MonIbpMean.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBgSat.Value)
}
|> Seq.toArray
|> addPatientData p "Arterial bloodgas oxygen saturation" "bgsat", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBgPo2.IsSome && d.LabBgPo2.Value <> 0. && d.MonIbpMean.IsSome &&
d.VentSetFiO2.IsSome && d.VentSetFiO2.Value <> 0. &&
d.VentMMean.IsSome && d.VentMMean.Value <> 0. &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.VentSetFiO2.Value * d.VentMMean.Value / d.LabBgPo2.Value )
}
|> Seq.toArray
|> addPatientData p "Oxygenation Index" "oi", data
|> fun (p, data) ->
query {
for d in data do
where (
d.VentSetFiO2.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.VentSetFiO2.Value / 100.)
}
|> Seq.toArray
|> addPatientData p "Ventilator FiO2 setting" "fio2", data
|> fun (p, data) ->
query {
for d in data do
where (
d.VentMMean.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.VentMMean.Value)
}
|> Seq.toArray
|> addPatientData p "Ventilator mean airway pressure" "map", data
|> fun (p, data) ->
query {
for d in data do
where (
d.MonSat.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.MonSat.Value)
}
|> Seq.toArray
|> addPatientData p "Monitor oxygen saturation" "sat", data
|> fun (p, data) ->
query {
for d in data do
where (
d.MonTemp.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.MonTemp.Value)
}
|> Seq.toArray
|> addPatientData p "Temperature" "temp", data
|> fun (p, data) ->
query {
for d in data do
where (
d.ObsFbUrine.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.ObsFbUrine.Value)
}
|> Seq.toArray
|> addPatientData p "Urine output" "urine", data
|> fun (p, data) ->
query {
for d in data do
where (
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.ObsGcsE, d.ObsGcsM, d.ObsGcsV)
}
|> Seq.toArray
|> Array.map (fun (dt, e, m, v) -> dt, calcGCS e m v |> float)
|> addPatientData p "Glascow coma score" "gcs", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlLactate.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlLactate.Value)
}
|> Seq.toArray
|> addPatientData p "Lactate" "lact", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlGluc.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlGluc.Value)
}
|> Seq.toArray
|> addPatientData p "Glucose" "gluc", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlNa.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlNa.Value)
}
|> Seq.toArray
|> addPatientData p "Sodium" "na", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlCl.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlCl.Value)
}
|> Seq.toArray
|> addPatientData p "Chloride" "cl", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBgHco3.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBgHco3.Value)
}
|> Seq.toArray
|> addPatientData p "Bicarbonate" "bic", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlCr.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlCr.Value)
}
|> Seq.toArray
|> addPatientData p "Creatinine" "creat", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlUr.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlUr.Value)
}
|> Seq.toArray
|> addPatientData p "Urea" "urea", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlLeuco.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlLeuco.Value)
}
|> Seq.toArray
|> addPatientData p "Leucocyte count" "leuco", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlNeutro.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlNeutro.Value)
}
|> Seq.toArray
|> addPatientData p "Neutrophil count" "neutro", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlHb.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlHb.Value)
}
|> Seq.toArray
|> addPatientData p "Hemoglobin" "hb", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlTr.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlTr.Value)
}
|> Seq.toArray
|> addPatientData p "Platelets" "trombo", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlAlat.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlAlat.Value)
}
|> Seq.toArray
|> addPatientData p "Alanine aminotransferase" "alat", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlAsat.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlAsat.Value)
}
|> Seq.toArray
|> addPatientData p "Aspartate aminotransferase" "asat", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlGgt.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlGgt.Value)
}
|> Seq.toArray
|> addPatientData p "Gamma-glutamyl transferase" "ggt", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlAlp.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlAlp.Value)
}
|> Seq.toArray
|> addPatientData p "Alkaline phosphatase" "alp", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlLdh.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlLdh.Value)
}
|> Seq.toArray
|> addPatientData p "LDH" "ldh", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlBilI.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlBilI.Value)
}
|> Seq.toArray
|> addPatientData p "Bilirubin" "bili", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlAlb.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlAlb.Value)
}
|> Seq.toArray
|> addPatientData p "Albumin" "alb", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlTg.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlTg.Value)
}
|> Seq.toArray
|> addPatientData p "Triglyceride" "tg", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlFibrinogen.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlFibrinogen.Value)
}
|> Seq.toArray
|> addPatientData p "Fibrinogen" "fibr", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlInr.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlInr.Value)
}
|> Seq.toArray
|> addPatientData p "INR" "inr", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlPt.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlPt.Value)
}
|> Seq.toArray
|> addPatientData p "Prothrombin time" "pt", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlCrp.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlCrp.Value)
}
|> Seq.toArray
|> addPatientData p "C Reactive Protein" "crp", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlFerritin.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlFerritin.Value)
}
|> Seq.toArray
|> addPatientData p "Ferritine" "ferri", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlIl2.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlIl2.Value)
}
|> Seq.toArray
|> addPatientData p "Soluble IL-2 receptor" "sIL2", data
|> fun (p, data) ->
query {
for d in data do
where (
d.LabBlTropo.IsSome &&
d.PatHospId = x.hospnum &&
d.PatDatetime >= x.admTime.Value &&
d.PatDatetime <= x.endTime.Value
)
select (d.PatDatetime, d.LabBlTropo.Value)
}
|> Seq.toArray
|> addPatientData p "Troponine" "tropo"
)
let getData (ctx: sql.dataContext) =
ctx
|> getPatientHospAdmissions
|> fun pats ->
let noPats = pats |> Array.map (fun p -> p.hospnum) |> Array.distinct |> Array.length
let noAdms = pats |> Array.length
printfn "No of patients: %i\nNo of admissions: %i" noPats noAdms
pats
let smoothData ns (pat: Patient) =
let window = 31
pat.Data
|> Array.filter (fun d -> ns |> Seq.exists ((=) d.Name))
|> fun xs ->
{
pat with
Data =
xs
|> Array.map (fun nd ->
{
Name = nd.Name + "_sm"
Label = nd.Label + " smoothed"
Values =
let dts = nd.Values |> Array.map fst
let vs =
nd.Values
|> Array.map snd
|> fun xs ->
if xs |> Seq.length < window then xs
else
xs
|> Signal.Filtering.savitzkyGolay window 1 0 1
Array.zip dts vs
}
)
|> Array.append pat.Data
}
let calcStats (xs : float seq) =
let xs = xs |> Seq.filter ((<>) 0.)
if xs |> Seq.isEmpty then None
else
{|
mean = xs |> Seq.mean
median = xs |> Seq.median
min = xs |> Seq.min
max = xs |> Seq.max
sd = xs |> Seq.stDev
|}
|> Some
let statsToStr n (stats: {| max: float; mean: float; median: float; min: float; sd: float |} option) =
match stats with
| None -> sprintf "%40s\tno data" n
| Some stats ->
sprintf "%40s\tmean: %8.2f\tmedian: %8.2f\tmin: %8.2f\tmax %8.2f"
n
stats.mean
stats.median
stats.min
stats.max
let report (pat : Patient) =
let wght =
if pat.Weight.IsSome then sprintf "%.1f" pat.Weight.Value
else ""
let dtToStr (dt: DateTime) = dt.ToString("dd-MM-yyyy HH:mm")
let start, stop =
pat.AdmTime |> dtToStr,
pat.DisTime |> dtToStr
let age = (pat.AdmTime - pat.BirthDate).TotalDays / 365.
StringBuilder.builder (sprintf "=== Patient: %s, admission: %i %s - %s" pat.HospNum pat.AdmNo start stop)
|> StringBuilder.appendLine "=== Demographics:"
|> StringBuilder.appendLine (sprintf "Age at PICU admission(years) : %.1f" age)
|> StringBuilder.appendLine (sprintf "Gender: %s" pat.Gender)
|> StringBuilder.appendLine (sprintf "Gewicht: %s" wght)
|> StringBuilder.appendLine "=== Data:"
|> fun sb ->
pat.Data
|> Array.sortBy (fun d -> d.Label)
|> Array.fold (fun sb d ->
let stats =
d.Values
|> Seq.map snd
|> calcStats
sb
|> StringBuilder.appendLine (stats |> statsToStr (d.Label.Trim()))
) sb
|> StringBuilder.appendLine (sprintf "Sepsis: %s" (if pat.Sepsis then "Ja" else "Nee" ))
|> StringBuilder.appendLine (sprintf "Diagnoses: %s" (pat.Diagnoses |> String.concat ", "))
|> StringBuilder.appendLine (sprintf "Outcome: %s" pat.Outcome)
|> StringBuilder.appendLine ""
|> StringBuilder.appendLine ""
|> StringBuilder.toString
let createCSV (pats : Patient[]) =
let wght pat =
if pat.Weight.IsSome then sprintf "%.1f" pat.Weight.Value
else ""
let dtToStr (dt: DateTime) = dt.ToString("dd-MM-yyyy HH:mm")
let age pat = (pat.AdmTime - pat.BirthDate).TotalDays / 365.
let headers =
pats
|> Array.head
|> fun pat ->
pat.Data
|> Array.collect (fun nd ->
[|
nd.Name + "_mean"
nd.Name + "_median"
nd.Name + "_min"
nd.Name + "_max"
|]
)
|> Array.append [|
"hospNum"
"admNo"
"start"
"stop"
"age"
"gender"
"weight"
"sepsis"
"diagns"
"outcome"
"pim2"
"pim3"
"prismIV"
|]
[|
headers
for pat in pats do
let stats =
pat.Data
|> Array.map (fun nd -> nd.Values |> Array.map snd |> calcStats)
|> Array.collect (fun st ->
match st with
| None -> [|""; ""; ""; ""|]
| Some nd ->
[|
nd.mean |> sprintf "%A"
nd.median |> sprintf "%A"
nd.min |> sprintf "%A"
nd.max |> sprintf "%A"
|]
)
stats
|> Array.append [|
pat.HospNum
pat.AdmNo |> string
pat.AdmTime |> dtToStr
pat.DisTime |> dtToStr
pat |> age |> sprintf "%A"
pat.Gender
pat |> wght
pat.Sepsis |> sprintf "%A"
pat.Diagnoses |> String.concat ";"
pat.Outcome
pat.PIM2 |> Option.map (sprintf "%A") |> Option.defaultValue ""
pat.PIM3 |> Option.map (sprintf "%A") |> Option.defaultValue ""
pat.PRISMIV |> Option.map (sprintf "%A") |> Option.defaultValue ""
|]
|]
[<Literal>]
let connString2 = @"Data Source=VOXDB-PICURED01;Initial Catalog=PICE_MRDM;Persist Security Info=True;Integrated Security=SSPI;Connection Timeout=0;Command Timeout=0;"
[<Literal>]
let schemaPath2 = __SOURCE_DIRECTORY__ + "\schema\pice.schema"
type sql2 = SqlDataProvider<Common.DatabaseProviderTypes.MSSQLSERVER_DYNAMIC,
connString2,
ResolutionPath = resolutionPath,
UseOptionTypes = true,
ContextSchemaPath = schemaPath2,
CaseSensitivityChange = Common.CaseSensitivityChange.ORIGINAL>
let addPICEData (pat: Patient) =
let ctx = sql2.GetDataContext(SelectOperations.DatabaseSide)
query {
for pd in ctx.Dbo.PimPrism2103111003 do
where (
pd.HospitalNumber.Trim() = pat.HospNum.Trim() &&
pat.AdmTime >= pd.AdmissionDate.AddDays(-1.) &&
pat.AdmTime <= pd.AdmissionDate.AddDays(1.)
)
select pd
}
|> Seq.toList
|> function
| h::[] ->
{
pat with
Sepsis =
h.Sepsis
|> Option.map (fun s -> if s = "True" then true else false)
|> Option.defaultValue false
Specialism = h.Specialism |> Option.defaultValue ""
Diagnoses =
[|
h.Diagnosis1 |> Option.defaultValue ""
h.Diagnosis2 |> Option.defaultValue ""
h.DiagnosesOther |> Option.defaultValue ""
|]
|> Array.filter (String.IsNullOrWhiteSpace >> not)
|> Array.distinct
Outcome = h.Status |> Option.defaultValue ""
}
| _ -> pat
let processPatients n =
let smd =
[
"sbp"
"dbp"
"mbp"
"cvp"
"sat"
]
let ctx = sql.GetDataContext(SelectOperations.DatabaseSide)
ctx
|> getData
|> fun d ->
if n = 0 then d
else
d |> Array.take n
|> fun d ->
printfn "going to map %i admissions" (d |> Seq.length)
d
|> Array.collect (fun d ->
printfn "now mapping %s, admission %i" d.hospnum d.admno
[| d |]
|> mapPatients ctx
|> Array.map ((smoothData smd) >> (addPICEData))
)
let saveReports n =
processPatients n
|> Array.iter (report >> (sprintf "%s") >> (File.appendTextToFile "./download/patients.txt"))
let saveCSV n =
processPatients n
|> createCSV
|> Array.map (String.concat "\t")
|> String.concat "\n"
|> File.writeTextToFile "./download/patients.csv"
let getSinglePatient n =
processPatients n
|> Array.item (n - 1)
let plotPatient pat =
do
let mbp =
pat.Data
|> Array.find (fun d -> d.Name = "mbp")
let xs =
mbp.Values
|> Array.map fst
let ys =
mbp.Values
|> Array.map snd
let ys_sm =
pat.Data
|> Array.find (fun d -> d.Name = "mbp_sm")
|> fun x -> x.Values |> Array.map snd
[
Chart.Point(xs, ys, Name="raw")
Chart.Line(xs, ys_sm, Name="smoothed")
]
|> Chart.Combine
|> Chart.withTitle ("Mean Invasive Blood Pressure")
|> Chart.withSize (1000., 800.)
|> Chart.Show
// |> Chart.SaveHtmlAs "smoothed"
let xs = ["1"; 1 ]
let pat = getSinglePatient "a"
plotPatient pat
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment