Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
f2292de
Added HKVisualizations
Priyankas007 Feb 6, 2025
ac9dbaa
Added health visualizations
Priyankas007 Feb 10, 2025
7d2c720
Merge branch 'main' into priyanka
Priyankas007 Feb 12, 2025
d16a297
Updated tests
Priyankas007 Feb 12, 2025
dd1aa5a
Managing pull conflicts
Priyankas007 Feb 12, 2025
3bada05
Managing commit conflicts
Priyankas007 Feb 12, 2025
bae5d19
Merge branch 'priyanka' of https://github.com/CS342/2025-NeutroFeverG…
Priyankas007 Feb 12, 2025
a9f1d89
Merge branch 'main' into priyanka
Priyankas007 Feb 12, 2025
5964595
Fixed login issues
Priyankas007 Feb 12, 2025
ee7795b
Merge branch 'priyanka' of https://github.com/CS342/2025-NeutroFeverG…
Priyankas007 Feb 12, 2025
e050cf5
Recovered visualizations
Priyankas007 Feb 12, 2025
f39feb5
Fixed build issues
Priyankas007 Feb 12, 2025
5eafb1f
Disabled mock data feature flag
Priyankas007 Feb 12, 2025
db63d88
Removed orphaned doc comment
Priyankas007 Feb 12, 2025
801aca0
Disabled orphaned_doc_comment link warning
Priyankas007 Feb 13, 2025
70f2e15
Added onboarding to scheme
Priyankas007 Feb 13, 2025
0cd97e2
Removed failing UI test
Priyankas007 Feb 13, 2025
e8ff374
Updated HKVisualiztion UI
Priyankas007 Feb 13, 2025
7d8311b
Update HKMockData
Priyankas007 Feb 13, 2025
aa6248d
Merge branch 'main' into priyanka_ui
Priyankas007 Feb 13, 2025
2d697a4
Resolved lint errors
Priyankas007 Feb 13, 2025
40260c8
Merge branch 'priyanka_ui' of https://github.com/CS342/2025-NeutroFev…
Priyankas007 Feb 13, 2025
5e31f74
Edited onboarding tests
Priyankas007 Feb 13, 2025
5e80541
Updating project file
Priyankas007 Feb 13, 2025
25b61f2
Resolving periphery issues
Priyankas007 Feb 13, 2025
554fb15
Resolved lint issues
Priyankas007 Feb 13, 2025
0e1d589
Resolved lint issues
Priyankas007 Feb 13, 2025
14df79b
Resolved lint errors
Priyankas007 Feb 13, 2025
73b6fae
Readded onboarding to scheme in hopes that it will solve my errors :')
Priyankas007 Feb 13, 2025
2209771
Removed onboarding tests
Priyankas007 Feb 14, 2025
25bb5ad
Resolving ui testing errors
Priyankas007 Feb 14, 2025
0dab389
Resolved periphery errors
Priyankas007 Feb 14, 2025
d093542
Updated bodyTemperature
Priyankas007 Feb 22, 2025
bbe9e7c
Updated dashboard
Priyankas007 Feb 22, 2025
d955655
Deleted UI tests
Priyankas007 Feb 22, 2025
5828281
Merge branch 'main' into priyanka_ui
Priyankas007 Feb 22, 2025
6418944
Resolved periphery errors
Priyankas007 Feb 22, 2025
e3e5bd4
Merge branch 'priyanka_ui' of https://github.com/CS342/2025-NeutroFev…
Priyankas007 Feb 22, 2025
92630b2
Resolved periphery error
Priyankas007 Feb 22, 2025
f87edf1
Merge branch 'main' into priyanka_ui
Priyankas007 Feb 24, 2025
b3d5f0a
Resolved periphery errors
Priyankas007 Feb 24, 2025
a873fb2
Resolved lint errors
Priyankas007 Feb 24, 2025
403f46b
Resolved periphery errors
Priyankas007 Feb 24, 2025
a3fd8fc
Resolved function arguments error
Priyankas007 Feb 24, 2025
dd1a7cb
Removed failing contributions test
Priyankas007 Feb 24, 2025
edba2ae
Resolved UI test issues
Priyankas007 Feb 24, 2025
95b60ce
Added onboarding schema
Priyankas007 Feb 24, 2025
f87a82b
Commented out all UI tests
Priyankas007 Feb 24, 2025
342d439
Merge branch 'main' into priyanka_ui
Priyankas007 Mar 10, 2025
1d29743
Updated visualizations page account settings and added as homepage
Priyankas007 Mar 10, 2025
e1eeb16
Attempting to fix account issue
Priyankas007 Mar 11, 2025
e18ac8d
Removed visualizations from folder
Priyankas007 Mar 11, 2025
8c6fca0
Debug AccountButton
Priyankas007 Mar 12, 2025
a98fe3b
Updated account
Priyankas007 Mar 12, 2025
1661aa4
Merge branch 'main' into priyanka_ui
Priyankas007 Mar 12, 2025
cb7de21
add bluetooth folder in ref
dusixian Mar 12, 2025
ccadce7
Merge branch 'main' into priyanka_ui
Priyankas007 Mar 12, 2025
33f4073
Cleaned comments
Priyankas007 Mar 12, 2025
cc35311
Merge branch 'priyanka_ui' of https://github.com/CS342/2025-NeutroFev…
Priyankas007 Mar 12, 2025
5ae642e
Update comments
Priyankas007 Mar 12, 2025
2d453a4
Updated comments
Priyankas007 Mar 12, 2025
cfc1905
Removed unused functions
Priyankas007 Mar 12, 2025
ae06d91
Removed lint ignore on flags
Priyankas007 Mar 12, 2025
d0f4d5a
Added methods to extract ANC data
Priyankas007 Mar 12, 2025
0d0bb02
Merge branch 'main' into priyanka_anc_viz
Priyankas007 Mar 12, 2025
e99b6a8
Fixed ANC updates
Priyankas007 Mar 12, 2025
3902ce4
Merge branch 'priyanka_anc_viz' of https://github.com/CS342/2025-Neut…
Priyankas007 Mar 12, 2025
eb41120
Fixed anc update functionality
Priyankas007 Mar 12, 2025
fa5431e
Fixed data reading issue
Priyankas007 Mar 12, 2025
98cf536
ANC plot updates
Priyankas007 Mar 12, 2025
a2bc829
Fix scope error
Priyankas007 Mar 12, 2025
fbdfc30
build fail fix
viraj28m Mar 12, 2025
4d2a400
linter fixes
viraj28m Mar 12, 2025
43bdc49
Merge branch 'main' into priyanka_anc_viz
Priyankas007 Mar 12, 2025
dd8ce05
Merge branch 'main' into priyanka_anc_viz
Priyankas007 Mar 13, 2025
bbaa83c
Merge branch 'main' into priyanka_anc_viz
mmervecerit Mar 14, 2025
8bc5f0c
Update HKVisualization.swift
mmervecerit Mar 14, 2025
96ebe13
Update HKVisualization.swift
mmervecerit Mar 15, 2025
5d52816
Update HKVisualizationHKTests.swift
mmervecerit Mar 15, 2025
06cabfe
Updated chart names
Priyankas007 Mar 15, 2025
0d8511d
Merge branch 'main' into priyanka_anc_viz
Priyankas007 Mar 15, 2025
7b01d0c
added mock data and edited tests
mmervecerit Mar 15, 2025
6c0f800
Update project.pbxproj
mmervecerit Mar 15, 2025
21e6911
Update project.pbxproj
mmervecerit Mar 15, 2025
818c7f6
Update NeutroFeverGuardTests.swift
mmervecerit Mar 15, 2025
bb093af
fixes for tests
mmervecerit Mar 15, 2025
2d428a3
Update NeutroFeverGuardTests.swift
mmervecerit Mar 15, 2025
1568b93
Update HKVisualization.swift
mmervecerit Mar 15, 2025
136bb10
Update HKVisualizationItem.swift
mmervecerit Mar 15, 2025
c5875cd
Update HKVisualizationTests.swift
mmervecerit Mar 15, 2025
6911443
Update HKVisualization.swift
mmervecerit Mar 15, 2025
375e86a
updated mock and neutrophil tests
mmervecerit Mar 16, 2025
b5b66d7
Update HKVisualizationTests.swift
mmervecerit Mar 16, 2025
021e06e
fix the test
mmervecerit Mar 16, 2025
3dfd14c
Update HKVisualizationTests.swift
mmervecerit Mar 16, 2025
d27b96c
Update HKVisualizationTests.swift
mmervecerit Mar 16, 2025
8153d05
Update HKVisualizationTests.swift
mmervecerit Mar 16, 2025
b587ff0
Update HKVisualizationTests.swift
mmervecerit Mar 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions NeutroFeverGuard.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,6 @@
EB5D7CF92D8108BC0046BF8E /* AccountButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9DFE8A82ABE551400428242 /* AccountButton.swift */; };
EB6FDBCE2D80133A008E9F90 /* HKVisualization.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB6FDBCB2D80133A008E9F90 /* HKVisualization.swift */; };
EB6FDBCF2D80133A008E9F90 /* HKVisualizationItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB6FDBCC2D80133A008E9F90 /* HKVisualizationItem.swift */; };
EB6FDBD02D80133A008E9F90 /* HKVisualization.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB6FDBCB2D80133A008E9F90 /* HKVisualization.swift */; };
EB6FDBD12D80133A008E9F90 /* HKVisualizationItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB6FDBCC2D80133A008E9F90 /* HKVisualizationItem.swift */; };
EBFA80652D81FBE600596C3C /* FeatureFlags.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE5DC3E29EDD7ED004B9AB4 /* FeatureFlags.swift */; };
F223937A2D5D4095006C8EB4 /* DataError.swift in Sources */ = {isa = PBXBuildFile; fileRef = F22393792D5D4092006C8EB4 /* DataError.swift */; };
F268C4562D7F928C0020026F /* SymptomManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F268C4552D7F928B0020026F /* SymptomManager.swift */; };
Expand Down Expand Up @@ -718,8 +716,6 @@
EB02C6612D5D52E90035AA89 /* NeutroFeverGuardTests.swift in Sources */,
B0DF8DFD2D7C123200581A00 /* HealthDataFetchable.swift in Sources */,
B0DF8DF72D7BFEFB00581A00 /* FeverMonitorTests.swift in Sources */,
EB6FDBD02D80133A008E9F90 /* HKVisualization.swift in Sources */,
EB6FDBD12D80133A008E9F90 /* HKVisualizationItem.swift in Sources */,
B03D0E482D7D24AA0024F2CA /* DataError.swift in Sources */,
EBFA80652D81FBE600596C3C /* FeatureFlags.swift in Sources */,
C4C8A3B32D71204200F313AE /* HelperFuncTests.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion NeutroFeverGuard/DataType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ struct BloodPressureEntry {
- Lab values: include the number associated with the lab name above
*/

struct LabEntry: Codable {
struct LabEntry: Codable, Equatable {
var date: Date
var values: [LabTestType: Double]

Expand Down
109 changes: 88 additions & 21 deletions NeutroFeverGuard/HKVisualization.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// periphery:ignore all
// swiftlint:disable all
// periphery:ignore all
// This source file is part of the NeutroFeverGuard based on the Stanford Spezi Template Application project
//
// SPDX-FileCopyrightText: 2025 Stanford University
Expand All @@ -12,7 +12,16 @@
import SpeziAccount
import SwiftUI

// Parses the raw HealthKit data.

struct HKData: Identifiable, Codable {
var id = UUID()
var date: Date
var sumValue: Double
var avgValue: Double
var minValue: Double
var maxValue: Double
}

func parseSampleQueryData(results: [HKSample], quantityTypeIDF: HKQuantityTypeIdentifier) -> [HKData] {
// Retrieve quantity value and time for each data point.

Expand Down Expand Up @@ -79,23 +88,16 @@
}
}

struct HKData: Identifiable {
var date: Date
var id = UUID()
var sumValue: Double
var avgValue: Double
var minValue: Double
var maxValue: Double
}

struct HKVisualization: View {
// swiftlint:disable closure_body_length
@Environment(LabResultsManager.self) private var labResultsManager
@State var bodyTemperatureData: [HKData] = []
@State var heartRateData: [HKData] = []
@State var oxygenSaturationData: [HKData] = []
@State var heartRateScatterData: [HKData] = []
@State var oxygenSaturationScatterData: [HKData] = []
@State var bodyTemperatureScatterData: [HKData] = []
@State var neutrophilData: [HKData] = []
@State var neutrophilScatterData: [HKData] = []

var vizList: some View {
self.readAllHKData()
Expand All @@ -106,7 +108,7 @@
data: heartRateData,
xName: "Time",
yName: "Heart Rate (bpm)",
title: "Heart Rate Over Time",
title: "Heart Rate",
threshold: 100,
scatterData: heartRateScatterData
)
Expand All @@ -121,7 +123,7 @@
data: bodyTemperatureData,
xName: "Time",
yName: "Body Temperature (°F)",
title: "Body Temperature Over Time",
title: "Body Temperature",
threshold: 99.0,
scatterData: bodyTemperatureScatterData
)
Expand All @@ -136,7 +138,7 @@
data: oxygenSaturationData,
xName: "Time",
yName: "Oxygen Saturation (%)",
title: "Oxygen Saturation Over Time",
title: "Oxygen Saturation",
threshold: 94.0,
scatterData: oxygenSaturationScatterData
)
Expand All @@ -145,6 +147,21 @@
.foregroundColor(.gray)
}
}
Section {
if !neutrophilData.isEmpty {
HKVisualizationItem(
data: neutrophilData,
xName: "Date",
yName: "Neutrophil Count",
title: "Absolute Neutrophil Count",
threshold: 500, // Adjust the threshold if necessary
scatterData: neutrophilScatterData
)
} else {
Text("No neutrophil count data available.")
.foregroundColor(.gray)
}
}
}
}

Expand All @@ -164,6 +181,8 @@
.onAppear {
// Ensure that data up-to-date when the view is activated.
self.readAllHKData(ensureUpdate: true)
labResultsManager.loadLabResults()
loadNeutrophilData() // Ensure this is called
}
.toolbar {
if account != nil {
Expand All @@ -173,6 +192,41 @@
}
}

private func loadNeutrophilData() {
if FeatureFlags.mockVizData {
loadMockDataNew()
return
}
let rawData = labResultsManager.getAllAncValues().filter {
$0.date >= Calendar.current.date(byAdding: .day, value: -7, to: Date()) ?? Date()
}

Check warning on line 202 in NeutroFeverGuard/HKVisualization.swift

View check run for this annotation

Codecov / codecov/patch

NeutroFeverGuard/HKVisualization.swift#L201-L202

Added lines #L201 - L202 were not covered by tests

// Convert to HKData for bar plot
neutrophilData = rawData.map { record in
HKData(
date: record.date,
sumValue: record.ancValue,
avgValue: record.ancValue,
minValue: record.ancValue,
maxValue: record.ancValue
)
}

Check warning on line 213 in NeutroFeverGuard/HKVisualization.swift

View check run for this annotation

Codecov / codecov/patch

NeutroFeverGuard/HKVisualization.swift#L206-L213

Added lines #L206 - L213 were not covered by tests

// Create scatter data (with some random variation to separate points)
neutrophilScatterData = rawData.map { record in
HKData(
date: record.date,
sumValue: record.ancValue + Double.random(in: -0.5...0.5), // Add slight variation for visualization
avgValue: -1.0,
minValue: -1.0,
maxValue: -1.0
)
}

Check warning on line 224 in NeutroFeverGuard/HKVisualization.swift

View check run for this annotation

Codecov / codecov/patch

NeutroFeverGuard/HKVisualization.swift#L217-L224

Added lines #L217 - L224 were not covered by tests

print("✅ Converted neutrophil data: \(neutrophilData)")
print("✅ Scatter neutrophil data: \(neutrophilScatterData)")
}

func readAllHKData(ensureUpdate: Bool = false) {
if FeatureFlags.mockVizData {
loadMockDataNew()
Expand Down Expand Up @@ -331,7 +385,8 @@
self.heartRateData = minMaxAvgStatData
self.bodyTemperatureData = minMaxAvgStatData
self.oxygenSaturationData = minMaxAvgStatData

self.neutrophilData = [HKData(date: today, sumValue: 0, avgValue: 500, minValue: 1, maxValue: 1000)]

// ✅ Heart Rate Scatter Data (60-100 bpm normal range)
self.heartRateScatterData = [
HKData(date: today, sumValue: 75, avgValue: 75, minValue: 75, maxValue: 75),
Expand All @@ -352,8 +407,24 @@
HKData(date: yesterday, sumValue: 97, avgValue: 97, minValue: 97, maxValue: 97),
HKData(date: twoDaysAgo, sumValue: 96, avgValue: 96, minValue: 96, maxValue: 96)
]

let mockNeutrophilData = [
(date: today, wbc: 1000, neutrophils: 50),
(date: yesterday, wbc: 1000, neutrophils: 5),
(date: twoDaysAgo, wbc: 1200, neutrophils: 20)
]

self.neutrophilScatterData = mockNeutrophilData.map { record in
let ancValue = (Double(record.neutrophils) / 100.0) * Double(record.wbc)
return HKData(
date: record.date,
sumValue: ancValue,
avgValue: ancValue,
minValue: ancValue,
maxValue: ancValue
)
}
}
// swiftlint:enable closure_body_length
}

func parseStat(statistics: HKStatistics, quantityTypeIDF: HKQuantityTypeIdentifier) -> HKData? {
Expand Down Expand Up @@ -392,7 +463,3 @@
return -1.0
}
}

#Preview {

}
4 changes: 0 additions & 4 deletions NeutroFeverGuard/HKVisualizationItem.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// swiftlint:disable all
// periphery:ignore all
// This source file is part of the NeutroFeverGuard based on the Stanford Spezi Template Application project
//
// SPDX-FileCopyrightText: 2025 Stanford University
Expand All @@ -12,8 +10,6 @@ import Foundation
import SwiftUI

struct HKVisualizationItem: View {
// periphery:ignore
let id = UUID()
let data: [HKData]
let xName: LocalizedStringResource
let yName: LocalizedStringResource
Expand Down
16 changes: 15 additions & 1 deletion NeutroFeverGuard/LabResultsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
loadLabResults() // Refresh lab results
}

private func loadLabResults() {
func loadLabResults() {
var results: [LabEntry] = []

do {
Expand Down Expand Up @@ -120,6 +120,20 @@
}
return (neutrophils / 100.0) * wbc
}

func getAllAncValues() -> [(date: Date, ancValue: Double)] {
var ancValues: [(date: Date, ancValue: Double)] = []

for record in labRecords {
if let neutrophils = record.values[.neutrophils],
let wbc = record.values[.whiteBloodCell] {
let ancValue = (neutrophils / 100.0) * wbc
ancValues.append((date: record.date, ancValue: ancValue))
}

Check warning on line 132 in NeutroFeverGuard/LabResultsManager.swift

View check run for this annotation

Codecov / codecov/patch

NeutroFeverGuard/LabResultsManager.swift#L128-L132

Added lines #L128 - L132 were not covered by tests
}

return ancValues
}

func getANCStatus() -> (text: String, color: Color) {
guard let ancValue = getAncValue() else {
Expand Down
21 changes: 21 additions & 0 deletions NeutroFeverGuard/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
},
"1-10" : {

},
"Absolute Neutrophil Count" : {

},
"Absolute Neutrophil Counts" : {
"localizations" : {
Expand Down Expand Up @@ -154,6 +157,9 @@
},
"Bluetooth Devices" : {

},
"Body Temperature" : {

},
"Body Temperature (°F)" : {
"localizations" : {
Expand All @@ -166,6 +172,7 @@
}
},
"Body Temperature Over Time" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
Expand Down Expand Up @@ -371,6 +378,9 @@
}
}
}
},
"Heart Rate" : {

},
"Heart Rate (bpm)" : {
"localizations" : {
Expand All @@ -383,6 +393,7 @@
}
},
"Heart Rate Over Time" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
Expand Down Expand Up @@ -639,6 +650,9 @@
}
}
}
},
"Neutrophil Count" : {

},
"Next" : {
"localizations" : {
Expand Down Expand Up @@ -691,6 +705,9 @@
},
"No medications recorded" : {

},
"No neutrophil count data available." : {

},
"No oxygen saturation data available." : {
"localizations" : {
Expand Down Expand Up @@ -748,6 +765,9 @@
},
"Other factors" : {

},
"Oxygen Saturation" : {

},
"Oxygen Saturation (%)" : {
"localizations" : {
Expand All @@ -760,6 +780,7 @@
}
},
"Oxygen Saturation Over Time" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
Expand Down
Loading