Skip to content

Commit

Permalink
Setting up fhirstore and mock patients
Browse files Browse the repository at this point in the history
  • Loading branch information
apgupta3303 committed Feb 2, 2024
1 parent a37367b commit 18921fb
Show file tree
Hide file tree
Showing 18 changed files with 1,315,659 additions and 24 deletions.
41 changes: 22 additions & 19 deletions Intake/IntakeStandard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import Spezi
import SpeziAccount
import SpeziFirebaseAccountStorage
import SpeziFirestore
import SpeziFHIR

Check failure on line 18 in Intake/IntakeStandard.swift

View workflow job for this annotation

GitHub Actions / SwiftLint / SwiftLint

Sorted Imports Violation: Imports should be sorted (sorted_imports)
import SpeziFHIRHealthKit
import SpeziHealthKit
import SpeziMockWebService
import SpeziOnboarding
Expand All @@ -23,6 +25,11 @@ import SwiftUI


actor IntakeStandard: Standard, EnvironmentAccessible, HealthKitConstraint, OnboardingConstraint, AccountStorageConstraint {
@Dependency var fhirStore: FHIRStore

Check failure on line 28 in Intake/IntakeStandard.swift

View workflow job for this annotation

GitHub Actions / SwiftLint / SwiftLint

Type Contents Order Violation: An 'instance_property' should not be placed amongst the type content(s) 'subtype' (type_contents_order)

@MainActor var useHealthKitResources = true

Check failure on line 30 in Intake/IntakeStandard.swift

View workflow job for this annotation

GitHub Actions / SwiftLint / SwiftLint

Type Contents Order Violation: An 'instance_property' should not be placed amongst the type content(s) 'subtype' (type_contents_order)
private var samples: [HKSample] = []

Check failure on line 31 in Intake/IntakeStandard.swift

View workflow job for this annotation

GitHub Actions / SwiftLint / SwiftLint

Type Contents Order Violation: An 'instance_property' should not be placed amongst the type content(s) 'subtype' (type_contents_order)

enum IntakeStandardError: Error {
case userNotAuthenticatedYet
}
Expand Down Expand Up @@ -68,32 +75,28 @@ actor IntakeStandard: Standard, EnvironmentAccessible, HealthKitConstraint, Onbo


func add(sample: HKSample) async {
if let mockWebService {
let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted, .sortedKeys, .withoutEscapingSlashes]
let jsonRepresentation = (try? String(data: encoder.encode(sample.resource), encoding: .utf8)) ?? ""
try? await mockWebService.upload(path: "healthkit/\(sample.uuid.uuidString)", body: jsonRepresentation)
return
}

do {
try await healthKitDocument(id: sample.id).setData(from: sample.resource)
} catch {
logger.error("Could not store HealthKit sample: \(error)")
samples.append(sample)
if await useHealthKitResources {
await fhirStore.add(sample: sample)
}
}

func remove(sample: HKDeletedObject) async {
if let mockWebService {
try? await mockWebService.remove(path: "healthkit/\(sample.uuid.uuidString)")
return
samples.removeAll(where: { $0.id == sample.uuid })
if await useHealthKitResources {
await fhirStore.remove(sample: sample)
}
}

@MainActor
func loadHealthKitResources() async {
await fhirStore.removeAllResources()

do {
try await healthKitDocument(id: sample.uuid).delete()
} catch {
logger.error("Could not remove HealthKit sample: \(error)")
for sample in await samples {
await fhirStore.add(sample: sample)
}

useHealthKitResources = true
}

func add(response: ModelsR4.QuestionnaireResponse) async {
Expand Down
171 changes: 171 additions & 0 deletions Intake/Mock Data/FHIRStore+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
//
// This source file is part of the Stanford LLM on FHIR project
//
// SPDX-FileCopyrightText: 2023 Stanford University
//
// SPDX-License-Identifier: MIT
//

import ModelsR4
import SpeziFHIR
import SwiftUI


extension FHIRStore {
var llmRelevantResources: [FHIRResource] {
allergyIntolerances
+ llmConditions
+ encounters.uniqueDisplayNames
+ immunizations
+ llmMedications
+ observations.uniqueDisplayNames
+ procedures.uniqueDisplayNames
}

var allResources: [FHIRResource] {
allergyIntolerances
+ conditions
+ diagnostics
+ encounters
+ immunizations
+ medications
+ observations
+ otherResources
+ procedures
}

var patient: FHIRResource? {
otherResources
.first { resource in
guard case let .r4(resource) = resource.versionedResource,
resource is ModelsR4.Patient else {
return false
}

return true
}
}

private var llmConditions: [FHIRResource] {
conditions
.filter { resource in
guard case let .r4(resource) = resource.versionedResource,
let condition = resource as? ModelsR4.Condition else {
return false
}

return condition.clinicalStatus?.coding?.contains { coding in
guard coding.system?.value?.url == URL(string: "http://terminology.hl7.org/CodeSystem/condition-clinical"),
coding.code?.value?.string == "active" else {
return false
}

return true
} ?? false
}
}

private var llmMedications: [FHIRResource] {
func medicationRequest(resource: FHIRResource) -> MedicationRequest? {
guard case let .r4(resource) = resource.versionedResource,
let medicationRequest = resource as? ModelsR4.MedicationRequest else {
return nil
}

return medicationRequest
}

let outpatientMedications = medications
.filter { medication in
guard let medicationRequest = medicationRequest(resource: medication),
medicationRequest.category?
.contains(where: { codableconcept in
codableconcept.text?.value?.string.lowercased() == "outpatient"
})
?? false else {
return false
}

return true
}
.uniqueDisplayNames

let activeMedications = medications
.filter { medication in
guard let medicationRequest = medicationRequest(resource: medication),
medicationRequest.status == .active else {
return false
}

return true
}
.uniqueDisplayNames

return outpatientMedications + activeMedications
}

// var allResourcesFunctionCallIdentifier: [String] {
// @AppStorage(StorageKeys.resourceLimit) var resourceLimit = StorageKeys.Defaults.resourceLimit
//
// let relevantResources: [FHIRResource]
//
// if llmRelevantResources.count > resourceLimit {
// relevantResources = llmRelevantResources
// .lazy
// .filter {
// $0.date != nil
// }
// .sorted {
// $0.date ?? .distantPast < $1.date ?? .distantPast
// }
// .suffix(resourceLimit)
// } else {
// relevantResources = llmRelevantResources
// }
//
// return Array(Set(relevantResources.map { $0.functionCallIdentifier }))
// }
//
//
// func loadMockResources() {
// if FeatureFlags.testMode {
// let mockObservation = Observation(
// code: CodeableConcept(coding: [Coding(code: "1234".asFHIRStringPrimitive())]),
// id: FHIRPrimitive<FHIRString>("1234"),
// issued: FHIRPrimitive<Instant>(try? Instant(date: .now)),
// status: FHIRPrimitive(ObservationStatus.final)
// )
//
// let mockFHIRResource = FHIRResource(
// versionedResource: .r4(mockObservation),
// displayName: "Mock Resource"
// )
//
// removeAllResources()
// insert(resource: mockFHIRResource)
// }
// }
}


extension Array where Element == FHIRResource {
fileprivate var uniqueDisplayNames: [FHIRResource] {
let reducedEncounters = Dictionary(
map { ($0.displayName, $0) },
uniquingKeysWith: { first, second in
if first.date ?? .distantFuture < second.date ?? .distantPast {
return second
} else {
return first
}
}
)

return Array(reducedEncounters.values)
}


fileprivate func dateSuffix(maxLength: Int) -> [FHIRResource] {
self.lazy.sorted(by: { $0.date ?? .distantPast < $1.date ?? .distantPast }).suffix(maxLength)
}
}
118 changes: 118 additions & 0 deletions Intake/Mock Data/MockData.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
//
// This source file is part of the Stanford LLM on FHIR project
//
// SPDX-FileCopyrightText: 2023 Stanford University
//
// SPDX-License-Identifier: MIT
//

import Foundation
import class ModelsR4.Bundle
import SpeziFHIRMockPatients


extension ModelsR4.Bundle {
private static var _allen322Ferry570: ModelsR4.Bundle?
static var allen322Ferry570: ModelsR4.Bundle {
get async {
if let allen322Ferry570 = _allen322Ferry570 {
return allen322Ferry570
}

let allen322Ferry570 = await Foundation.Bundle.main.loadFHIRBundle(
withName: "Allen322_Ferry570_ad134528-56a5-35fd-c37f-466ff119c625"
)
ModelsR4.Bundle._allen322Ferry570 = allen322Ferry570
return allen322Ferry570
}
}

private static var _beatris270Bogan287: ModelsR4.Bundle?
static var beatris270Bogan287: ModelsR4.Bundle {
get async {
if let beatris270Bogan287 = _beatris270Bogan287 {
return beatris270Bogan287
}

let beatris270Bogan287 = await Foundation.Bundle.main.loadFHIRBundle(
withName: "Beatris270_Bogan287_5b3645de-a2d0-d016-0839-bab3757c4c58"
)
ModelsR4.Bundle._beatris270Bogan287 = beatris270Bogan287
return beatris270Bogan287
}
}

private static var _edythe31Morar593: ModelsR4.Bundle?
static var edythe31Morar593: ModelsR4.Bundle {
get async {
if let edythe31Morar593 = _edythe31Morar593 {
return edythe31Morar593
}

let edythe31Morar593 = await Foundation.Bundle.main.loadFHIRBundle(
withName: "Edythe31_Morar593_9c3df38a-d3b7-2198-3898-51f9153d023d"
)
ModelsR4.Bundle._edythe31Morar593 = edythe31Morar593
return edythe31Morar593
}
}

private static var _gonzalo160Duenas839: ModelsR4.Bundle?
static var gonzalo160Duenas839: ModelsR4.Bundle {
get async {
if let gonzalo160Duenas839 = _gonzalo160Duenas839 {
return gonzalo160Duenas839
}

let gonzalo160Duenas839 = await Foundation.Bundle.main.loadFHIRBundle(
withName: "Gonzalo160_Duenas839_ed70a28f-30b2-acb7-658a-8b340dadd685"
)
ModelsR4.Bundle._gonzalo160Duenas839 = gonzalo160Duenas839
return gonzalo160Duenas839
}
}

private static var _jacklyn830Veum823: ModelsR4.Bundle?
static var jacklyn830Veum823: ModelsR4.Bundle {
get async {
if let jacklyn830Veum823 = _jacklyn830Veum823 {
return jacklyn830Veum823
}

let jacklyn830Veum823 = await Foundation.Bundle.main.loadFHIRBundle(
withName: "Jacklyn830_Veum823_e0e1f21a-22a7-d166-7bb1-63f6bbce1a32"
)
ModelsR4.Bundle._jacklyn830Veum823 = jacklyn830Veum823
return jacklyn830Veum823
}
}

private static var _milton509Ortiz186: ModelsR4.Bundle?
static var milton509Ortiz186: ModelsR4.Bundle {
get async {
if let milton509Ortiz186 = _milton509Ortiz186 {
return milton509Ortiz186
}

let milton509Ortiz186 = await Foundation.Bundle.main.loadFHIRBundle(
withName: "Milton509_Ortiz186_d66b5418-06cb-fc8a-8c13-85685b6ac939"
)
ModelsR4.Bundle._milton509Ortiz186 = milton509Ortiz186
return milton509Ortiz186
}
}


static var llmOnFHIRMockPatients: [Bundle] {
get async {
await [
.allen322Ferry570,
.beatris270Bogan287,
.edythe31Morar593,
.gonzalo160Duenas839,
.jacklyn830Veum823,
.milton509Ortiz186
]
}
}
}
Loading

0 comments on commit 18921fb

Please sign in to comment.