Skip to content

Commit 7a3d341

Browse files
committed
mths - wip
1 parent 1b5babe commit 7a3d341

1 file changed

Lines changed: 38 additions & 5 deletions

File tree

src/dsp/mths.clj

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,21 @@
2525
;;
2626
;; ### What We'll Explore
2727
;;
28-
;; In this notebook, we'll walk through a [signal processing](https://en.wikipedia.org/wiki/Signal_processing) pipeline for analyzing Camera PPG data:
28+
;; **Our goal is to extract heart rate from smartphone camera video and validate it against clinical measurements.**
29+
;;
30+
;; The MTHS dataset provides both the raw camera data (RGB signals) and ground truth heart rate measurements from medical-grade equipment. This allows us to:
31+
;;
32+
;; 1. Develop and test signal processing algorithms
33+
;; 2. Validate our extracted heart rates against the ground truth
34+
;; 3. Calibrate parameters (filter cutoffs, window sizes, etc.) for optimal accuracy
35+
;;
36+
;; In this notebook, we'll walk through the complete pipeline:
2937
;;
3038
;; 1. **Loading and visualizing** raw [RGB](https://en.wikipedia.org/wiki/RGB_color_model) signals from multiple subjects
3139
;; 2. **Signal preprocessing**: removing [DC offset](https://en.wikipedia.org/wiki/DC_bias), [bandpass filtering](https://en.wikipedia.org/wiki/Band-pass_filter) to isolate heart rate frequencies (0.5-5 Hz, corresponding to 30-300 bpm), and [standardization](https://en.wikipedia.org/wiki/Standard_score)
32-
;; 3. **Power spectrum analysis**: using windowed [FFT](https://en.wikipedia.org/wiki/Fast_Fourier_transform) to identify the dominant frequency (heart rate)
40+
;; 3. **Power spectrum analysis**: using windowed [FFT](https://en.wikipedia.org/wiki/Fast_Fourier_transform) to identify the dominant frequency
41+
;; 4. **Heart rate extraction**: finding the peak frequency and converting to bpm
42+
;; 5. **Validation**: comparing our estimates with ground truth measurements
3343
;;
3444
;; This exploration demonstrates how Clojure's ecosystem—combining tablecloth for data wrangling, dtype-next for efficient numerical computation, jdsp for signal processing, and tableplot for visualization—provides powerful tools for biomedical signal analysis.
3545

@@ -131,11 +141,26 @@
131141
;; NumPy arrays can be inspected using dtype-next:
132142

133143
(dtype/shape (raw-data [:signal 23])) ; 30Hz signal → [n-samples, 3] array
134-
(dtype/shape (raw-data [:label 23])) ; 1Hz labels → [n-samples, 2] array
144+
(dtype/shape (raw-data [:label 23])) ; 1Hz labels → [n-samples, 2] array (heart rate + SpO2)
135145

136146
;; The [sampling rate](https://en.wikipedia.org/wiki/Sampling_(signal_processing)) is 30 Hz (30 samples per second)
137147
(def sampling-rate 30)
138148

149+
;; ## Ground Truth Data
150+
;;
151+
;; Before we dive into signal processing, let's look at the ground truth labels.
152+
;; These provide the reference heart rate values we'll use to validate our algorithms.
153+
154+
(defn labels [i]
155+
(some-> [:label i]
156+
raw-data
157+
ds-tensor/tensor->dataset
158+
(tc/rename-columns [:heart-rate :spo2])))
159+
160+
;; For example, subject 23's ground truth measurements:
161+
162+
(labels 23)
163+
139164
;; Let's create a helper function to convert a subject's raw signal into a tablecloth dataset
140165
;; with properly named columns (:R, :G, :B) and a time column (:t in seconds):
141166

@@ -253,12 +278,20 @@
253278
:high-cutoff high-cutoff})
254279
:standardize stats/standardize}))
255280

256-
;; ## Power Spectrum Analysis
281+
;; ## Power Spectrum Analysis: Extracting Heart Rate
257282
;;
258-
;; To extract the heart rate from our cleaned PPG signal, we'll use **[frequency domain](https://en.wikipedia.org/wiki/Frequency_domain) analysis**.
283+
;; Now comes the key step: **extracting heart rate from the camera signal**.
284+
;;
285+
;; To do this, we'll use **[frequency domain](https://en.wikipedia.org/wiki/Frequency_domain) analysis**.
259286
;; The idea is simple: a heartbeat creates a periodic oscillation in the signal, and we can find
260287
;; the dominant frequency of that oscillation using the [Fast Fourier Transform (FFT)](https://en.wikipedia.org/wiki/Fast_Fourier_transform).
261288
;;
289+
;; Once we identify the peak frequency, we can:
290+
;;
291+
;; 1. Convert it to beats per minute (bpm)
292+
;; 2. Compare it with the ground truth heart rate
293+
;; 3. Evaluate our algorithm's accuracy
294+
;;
262295
;; ### Windowing and Overlap
263296
;;
264297
;; Rather than analyzing the entire signal at once, we'll use **[windowed analysis](https://en.wikipedia.org/wiki/Window_function)**:

0 commit comments

Comments
 (0)