Public
Edited
Apr 12, 2024
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof enrollment = Inputs.date({
label: "Enrollment date",
value: "2022-12-20"
})
Insert cell
Insert cell
viewof now = Inputs.date({
label: "Current date",
value: dayjs()
})
Insert cell
Insert cell
points = [
{
name: "Sleep",
value: d3.sum(sleepSummaryPoints, (d) => d.points),
icon: "💤"
},
{
name: "Activity",
value: d3.sum(currentWeekActivePoints, (d) => d.points),
icon: "🏃‍♀️"
}
// { name: "Rest", value: 300, icon: "" }
]
Insert cell
sleep_devices = [
...d3
.group(
currentWeekSleepRecords.filter((d) => !d.sourceName.includes("iPhone")),
(d) => d.sourceName
)
.keys()
]
Insert cell
sleepSummaryPoints = d3
.rollups(
currentWeekSleepRecords
.filter(
(d) =>
d.sourceName === sleep_device &&
d.value.includes("HKCategoryValueSleepAnalysisAsleep")
)
.map((d) => ({
...d,
offsetStartDate: d.startDate.add(12, "hours"),
sleep_minutes: (d.endDate - d.startDate) / 1000 / 60
}))
.map((d) => ({
...d,
offsetStartDay: new Date(
d.offsetStartDate.$y,
d.offsetStartDate.$M,
d.offsetStartDate.$D
)
})),
(v) => Math.round(d3.sum(v, (d) => d.sleep_minutes)),
(d) => d.offsetStartDay
)
.map((d) => ({
date: d[0],
sleep_minutes: d[1],
points: point_lookup_fun(SLEEP_LOOKUP, d[1])
}))
Insert cell
bmr_hourly = d3.median(currentWeekBasalEnergyBurned, (d) => d.value) * 4
Insert cell
currentWeekActivePoints = currentWeekActiveEnergyBurned.map((d) => ({
...d,
points: (d.value / (bmr_hourly * MET_THRESHOLD)) * MAX_POINTS_ACTIVITIES
}))
Insert cell
Plot.plot({
width: width,
y: {
grid: true,
label: "Calories"
},
x: { type: "time" },
marks: [
Plot.rect(currentWeekBasalEnergyBurned, {
y1: 0,
y2: (d) => d.value,
x1: (d) => new Date(d.aggTime), // .format("YYYY-MM-DD hh:mm"),
x2: (d) => new Date(d.aggTime.add(15, "minutes")),
// width: 100,
fill: "steelblue"
})
]
})
Insert cell
Plot.plot({
width: width,
y: {
grid: true,
label: "Calories"
},
x: { type: "time" },
marks: [
Plot.rect(currentWeekActiveEnergyBurned, {
y1: 0,
y2: (d) => d.value,
x1: (d) => new Date(d.aggTime), // .format("YYYY-MM-DD hh:mm"),
x2: (d) => new Date(d.aggTime.add(15, "minutes")),
// width: 100,
fill: "steelblue"
})
]
})
Insert cell
Plot.plot({
width: width,
y: {
grid: true,
label: "Calories"
},
marks: [
Plot.rectY(
currentWeekBasalEnergyBurned,
Plot.binX(
{ y: "sum" },
{
y: (d) => d.value,
x: (d) => d.aggTime,
thresholds: d3.utcDay,
fill: "steelblue"
}
)
)
]
})
Insert cell
Plot.plot({
width: width,
y: {
grid: true,
label: "Calories"
},
marks: [
Plot.rectY(
currentWeekActiveEnergyBurned,
Plot.binX(
{ y: "sum" },
{
y: (d) => d.value,
x: (d) => d.aggTime,
thresholds: d3.utcDay,
fill: "steelblue"
}
)
)
]
})
Insert cell
currentWeekActiveEnergyBurned = getAggByInterval(
startOfWeek,
now,
currentWeekRecordsActiveEnergyBurned
)
Insert cell
currentWeekBasalEnergyBurned = getAggByInterval(
startOfWeek,
now,
currentWeekRecordsBasalEnergyBurned
)
Insert cell
startOfWeek = dayjs(now)
.utc(true)
.subtract(dayjs(now).day() - 1, "day")
.hour(0)
.minute(0)
.millisecond(0)
Insert cell
// weekyear: d.weekYear(),
// week: d.week(),
// weekday: d.day(),
Insert cell
currentWeekRecordsActiveEnergyBurned = currentWeekRecords.filter(
(d) => d.type === "HKQuantityTypeIdentifierActiveEnergyBurned"
)
Insert cell
currentWeekRecordsBasalEnergyBurned = currentWeekRecords
.filter((d) => d.type === "HKQuantityTypeIdentifierBasalEnergyBurned")
.map((d) => ({
...d,
source: basalEnergyBurnedRanking.indexOf(d.sourceName)
}))
Insert cell
activeEnergyBurnedRanking.indexOf("Connect")
Insert cell
activeEnergyBurnedRanking
Insert cell
activeEnergyBurnedRankingDebounced = debounce(viewof activeEnergyBurnedRanking)
Insert cell
currentWeekRecords = healthjson.HealthData.Record.map((d) => ({
...d,
// value: +d.value,
// startDate: new Date(d.startDate),
startDate: dayjs(d.startDate).utc(true),
// endDate: new Date(d.endDate),
endDate: dayjs(d.endDate).utc(true),
// creationDate: new Date(d.creationDate)
creationDate: dayjs(d.creationDate).utc(true),
source: activeEnergyBurnedRankingDebounced.indexOf(d.sourceName)
})).filter(
(d) =>
true &&
[
"HKQuantityTypeIdentifierActiveEnergyBurned",
"HKQuantityTypeIdentifierBasalEnergyBurned",
"HKQuantityTypeIdentifierStepCount"
].includes(d.type) &&
d.endDate >= startOfWeek
)
Insert cell
currentWeekSleepRecords = healthjson.HealthData.Record.map((d) => ({
...d,
// value: +d.value,
// startDate: new Date(d.startDate),
startDate: dayjs(d.startDate).utc(true),
// endDate: new Date(d.endDate),
endDate: dayjs(d.endDate).utc(true),
// creationDate: new Date(d.creationDate)
creationDate: dayjs(d.creationDate).utc(true)
})).filter(
(d) =>
true &&
["HKCategoryTypeIdentifierSleepAnalysis"].includes(d.type) &&
d.endDate >= startOfWeek.subtract(1, 'day').hour(14)
)
Insert cell
historicalDataLowRes = {
return {};
}
Insert cell
historicalDataHighRes = {
return {};
}
Insert cell
healthjson
Insert cell
Insert cell
import {
ArcChart,
mini_circle_fun
} from "@andyreagan/sleep-activity-combined-arc"
Insert cell
import { getAggByInterval } from "@andyreagan/split-overlapping-time-objects"
Insert cell
import { healthjson } with { zipfile as zipfile } from "@berkeleyvis/apple-health-xml-parse"
Insert cell
import {
instructions,
SLEEP_LOOKUP,
point_lookup_fun,
MAX_POINTS,
MAX_POINTS_ACTIVITIES,
MET_THRESHOLD,
blankInput as dummyInput
} from "@berkeleyvis/analyze-your-apple-health-data"
Insert cell
import { dayjs } from "@andyreagan/dayjs-loader"
Insert cell
import { debounce } from "@mbostock/debouncing-input"
Insert cell
import { SortableList } from "@andyreagan/sortable-list"
Insert cell
Insert cell
Insert cell
platforms = ["ios", "android"]
Insert cell
Object.keys(allowed_devices)
Insert cell
Object.keys(Object.fromEntries(platforms.map((d) => [d, {}])))
Insert cell
allowed_devices_byplatform = {
var tmp = Object.fromEntries(platforms.map((d) => [d, {}]));
for (const platform in tmp) {
for (const brand in allowed_devices) {
const filtered = allowed_devices[brand].devices.filter(
(d) => d[platform]
);
if (filtered.length > 0) {
tmp[platform][allowed_devices[brand].brand] = filtered;
}
}
}
return tmp;
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more