Skill Tracer
Skills › Scientific Agent Skills › neurokit2 › ppg.md

ppg.md

197 lines · skills/neurokit2/references/ppg.md at 5f2bc03

Open on GitHub
1# Photoplethysmography
2
3Checked **2026-10-01** against NeuroKit2 0.2.13 stable runtime/source,
4the official PPG API, 0.2.13 release notes, and measurement guidance.
5

Photoplethysmography

Checked 2026-10-01 against NeuroKit2 0.2.13 stable runtime/source, the official PPG API, 0.2.13 release notes, and measurement guidance.

Raw lines 1 to 5
6## Acquisition contract
7
8Record sensor mode (reflectance/transmission), wavelength(s), anatomical site,
9attachment/contact pressure, device/firmware, raw unit/range, ambient-light handling,
10sampling rate, clock, temperature/perfusion, activity/posture, and motion/accelerometer
11channels. Validate across representative skin pigmentation, anatomy, age, vascular
12state, motion, and intended population.
14PPG is optical blood-volume-pulse measurement, not cardiac electrical activity.
15Pulse timing and morphology depend on site and vascular/transit dynamics.

Acquisition contract

Record sensor mode (reflectance/transmission), wavelength(s), anatomical site, attachment/contact pressure, device/firmware, raw unit/range, ambient-light handling, sampling rate, clock, temperature/perfusion, activity/posture, and motion/accelerometer channels. Validate across representative skin pigmentation, anatomy, age, vascular state, motion, and intended population.

PPG is optical blood-volume-pulse measurement, not cardiac electrical activity. Pulse timing and morphology depend on site and vascular/transit dynamics.

Raw lines 6 to 16
17## Stable high-level pipeline
19```python
20signals, info = nk.ppg_process(
21 ppg,
22 sampling_rate=100,
23 method="elgendi",
24 method_quality="templatematch",
26```
28Pinned 0.2.13 default columns:
30```text
31PPG_Raw, PPG_Clean, PPG_Rate, PPG_Quality, PPG_Peaks
32```
34`info` contained `PPG_Peaks`, `sampling_rate`, and peak/correction method metadata.
35The live doc's older codebook can omit `PPG_Quality`; stable runtime/source includes it.

Stable high-level pipeline

signals, info = nk.ppg_process(
    ppg,
    sampling_rate=100,
    method="elgendi",
    method_quality="templatematch",
)

Pinned 0.2.13 default columns:

PPG_Raw, PPG_Clean, PPG_Rate, PPG_Quality, PPG_Peaks

info contained PPG_Peaks, sampling_rate, and peak/correction method metadata. The live doc's older codebook can omit PPG_Quality; stable runtime/source includes it.

Raw lines 17 to 36
37## Cleaning and peak methods
39For explicit selection:
41```python
42clean = nk.ppg_clean(
43 ppg,
44 sampling_rate=100,
45 method="elgendi",
47markers, peak_info = nk.ppg_peaks(
48 clean,
49 sampling_rate=100,
50 method="elgendi",
51 correct_artifacts=False,
53```
55Stable cleaning methods include:
57- `elgendi`;
58- `nabian2018` (can use expected heart rate);
59- `langevin2021`;
60- `goda2024`; and
61- `none`.
63Stable peak methods include:
65- `elgendi`;
66- `bishop` (peaks plus pulse onsets);
67- `charlton` (MSPTDfast v2; peaks plus onsets); and
68- `charlton2024` (superseded v1).
70Method-dependent extra outputs are a primary reason not to hard-code one schema.
71Validate peak/onset performance against labeled data at the actual site, rate,
72perfusion, motion, and population.
74`correct_artifacts=True` uses the cardiac peak-correction path. Retain raw/corrected
75peaks and correction categories; correction cannot repair a low-quality optical
76waveform.

Cleaning and peak methods

For explicit selection:

clean = nk.ppg_clean(
    ppg,
    sampling_rate=100,
    method="elgendi",
)
markers, peak_info = nk.ppg_peaks(
    clean,
    sampling_rate=100,
    method="elgendi",
    correct_artifacts=False,
)

Stable cleaning methods include:

  • elgendi;
  • nabian2018 (can use expected heart rate);
  • langevin2021;
  • goda2024; and
  • none.

Stable peak methods include:

  • elgendi;
  • bishop (peaks plus pulse onsets);
  • charlton (MSPTDfast v2; peaks plus onsets); and
  • charlton2024 (superseded v1).

Method-dependent extra outputs are a primary reason not to hard-code one schema. Validate peak/onset performance against labeled data at the actual site, rate, perfusion, motion, and population.

correct_artifacts=True uses the cardiac peak-correction path. Retain raw/corrected peaks and correction categories; correction cannot repair a low-quality optical waveform.

Raw lines 37 to 77
78## Quality outputs added/expanded in 0.2.13
80```python
81quality = nk.ppg_quality(
82 clean,
83 peaks=peak_info["PPG_Peaks"],
84 sampling_rate=100,
85 method="templatematch",
87```
89Stable quality methods and scales differ:
91- `templatematch`: continuous similarity, typically 0–1;
92- `dissimilarity`: unbounded, where zero is highest similarity;
93- `ho2025`/interval-consistency path: binary interval quality;
94- `skewness`, `kurtosis`, `entropy`: unbounded windowed metrics;
95- `perfusion`: AC peak-to-peak / absolute raw DC mean × 100; requires raw PPG and
96 is not bounded at 100 in the implementation; and
97- `relative_power`: 0–1, requires raw PPG, and defaults to 60 s windows.
99No threshold is universal across these outputs. Name the method and direction/scale.
100For perfusion, a near-zero DC denominator can explode the ratio; exactly zero returns
101zero in the implementation. Neither outcome establishes poor/good sensor quality.
102The docstring's advertised 0–100 range is not enforced by stable source/runtime.
103Short signals can be invalid for a method's default window. `ppg_process()` passes
104peak indices—not the whole info dict—to quality estimation.
106Quality relative to an average pulse does not prove physiological accuracy: repeated
107motion-corrupted beats can be morphologically consistent. Combine morphology, motion,
108contact/perfusion, missingness, detector agreement, and endpoint-specific validation.

Quality outputs added/expanded in 0.2.13

quality = nk.ppg_quality(
    clean,
    peaks=peak_info["PPG_Peaks"],
    sampling_rate=100,
    method="templatematch",
)

Stable quality methods and scales differ:

  • templatematch: continuous similarity, typically 0–1;
  • dissimilarity: unbounded, where zero is highest similarity;
  • ho2025/interval-consistency path: binary interval quality;
  • skewness, kurtosis, entropy: unbounded windowed metrics;
  • perfusion: AC peak-to-peak / absolute raw DC mean × 100; requires raw PPG and is not bounded at 100 in the implementation; and
  • relative_power: 0–1, requires raw PPG, and defaults to 60 s windows.

No threshold is universal across these outputs. Name the method and direction/scale. For perfusion, a near-zero DC denominator can explode the ratio; exactly zero returns zero in the implementation. Neither outcome establishes poor/good sensor quality. The docstring's advertised 0–100 range is not enforced by stable source/runtime. Short signals can be invalid for a method's default window. ppg_process() passes peak indices—not the whole info dict—to quality estimation.

Quality relative to an average pulse does not prove physiological accuracy: repeated motion-corrupted beats can be morphologically consistent. Combine morphology, motion, contact/perfusion, missingness, detector agreement, and endpoint-specific validation.

Raw lines 78 to 109
110## Sampling and preprocessing
112Sampling requirements depend on endpoint:
114- pulse rate needs less bandwidth than morphology, onset timing, or derivatives;
115- wrist wearables commonly use lower rates than laboratory finger systems;
116- resampling cannot recover missing onset precision or a dicrotic feature; and
117- a nominal rate does not establish clock accuracy or anti-alias filtering.
119Do not prescribe one universal minimum. Validate rate and filters for the exact
120detector/feature and report native/processed rates. Process at native rate before
121multimodal alignment when possible.
123Motion, contact pressure, ambient light, vasoconstriction, temperature, pigmentation,
124site, and clipping can all change amplitude/morphology. Preserve a quality/artifact
125mask and accelerometry where available. Avoid interpolating through corrupted pulses.

Sampling and preprocessing

Sampling requirements depend on endpoint:

  • pulse rate needs less bandwidth than morphology, onset timing, or derivatives;
  • wrist wearables commonly use lower rates than laboratory finger systems;
  • resampling cannot recover missing onset precision or a dicrotic feature; and
  • a nominal rate does not establish clock accuracy or anti-alias filtering.

Do not prescribe one universal minimum. Validate rate and filters for the exact detector/feature and report native/processed rates. Process at native rate before multimodal alignment when possible.

Motion, contact pressure, ambient light, vasoconstriction, temperature, pigmentation, site, and clipping can all change amplitude/morphology. Preserve a quality/artifact mask and accelerometry where available. Avoid interpolating through corrupted pulses.

Raw lines 110 to 126
127## PPG-derived variability is PRV
129```python
130prv = nk.hrv_time(peak_info, sampling_rate=100)
131```
133NeuroKit2 accepts PPG peaks in HRV functions, but interpretation remains pulse-rate
134variability. PRV contains pre-ejection and pulse-transit variability and can differ
135from ECG HRV by site, posture, respiration, activity, temperature, and vascular state.
137For an HRV-equivalence claim:
1391. acquire synchronized ECG and PPG;
1402. validate pulse/beat matching and lag/drift;
1413. prespecify agreement metrics and acceptable error for each HRV endpoint;
1424. test rest, task/activity, motion, and relevant populations/sites; and
1435. report PRV terminology when equivalence is not established.
145Do not infer ECG morphology, rhythm diagnosis, oxygen saturation, blood pressure, or
146arterial stiffness from this basic PPG pipeline.

PPG-derived variability is PRV

prv = nk.hrv_time(peak_info, sampling_rate=100)

NeuroKit2 accepts PPG peaks in HRV functions, but interpretation remains pulse-rate variability. PRV contains pre-ejection and pulse-transit variability and can differ from ECG HRV by site, posture, respiration, activity, temperature, and vascular state.

For an HRV-equivalence claim:

  1. acquire synchronized ECG and PPG;
  2. validate pulse/beat matching and lag/drift;
  3. prespecify agreement metrics and acceptable error for each HRV endpoint;
  4. test rest, task/activity, motion, and relevant populations/sites; and
  5. report PRV terminology when equivalence is not established.

Do not infer ECG morphology, rhythm diagnosis, oxygen saturation, blood pressure, or arterial stiffness from this basic PPG pipeline.

Raw lines 127 to 147
148## Event and interval analysis
150```python
151epochs = nk.epochs_create(
152 signals,
153 events,
154 sampling_rate=100,
155 epochs_start=-1,
156 epochs_end=10,
157 baseline_correction=False,
159event_features = nk.ppg_eventrelated(epochs)
160interval_features = nk.ppg_intervalrelated(signals, sampling_rate=100)
161```
163Documented event fields include baseline/min/max/mean/SD rate, times, and polynomial
164trend coefficients. Interval output includes mean rate and HRV-family columns.
165Availability depends on input columns, duration, and release; inspect runtime output.

Event and interval analysis

epochs = nk.epochs_create(
    signals,
    events,
    sampling_rate=100,
    epochs_start=-1,
    epochs_end=10,
    baseline_correction=False,
)
event_features = nk.ppg_eventrelated(epochs)
interval_features = nk.ppg_intervalrelated(signals, sampling_rate=100)

Documented event fields include baseline/min/max/mean/SD rate, times, and polynomial trend coefficients. Interval output includes mean rate and HRV-family columns. Availability depends on input columns, duration, and release; inspect runtime output.

Raw lines 148 to 166
167## Pulse morphology
169`ppg_segment()` returns a dict of pulse epochs. Morphology comparisons require:
171- consistent site, attachment, pressure, wavelength, and polarity;
172- validated onsets/peaks and quality masks;
173- appropriate baseline/amplitude normalization;
174- sufficient sampling/bandwidth;
175- control of heart rate and vascular state; and
176- endpoint-specific evidence.
178A dicrotic feature in a processed waveform does not by itself validate aortic valve
179timing or arterial stiffness.

Pulse morphology

ppg_segment() returns a dict of pulse epochs. Morphology comparisons require:

  • consistent site, attachment, pressure, wavelength, and polarity;
  • validated onsets/peaks and quality masks;
  • appropriate baseline/amplitude normalization;
  • sufficient sampling/bandwidth;
  • control of heart rate and vascular state; and
  • endpoint-specific evidence.

A dicrotic feature in a processed waveform does not by itself validate aortic valve timing or arterial stiffness.

Raw lines 167 to 180
181## Interpretation boundary
183Use these tools for research and education. They are not validated here for arrhythmia,
184oxygen saturation, blood pressure, disease detection, remote patient monitoring,
185alarms, or wearable medical-device validation.

Interpretation boundary

Use these tools for research and education. They are not validated here for arrhythmia, oxygen saturation, blood pressure, disease detection, remote patient monitoring, alarms, or wearable medical-device validation.

Raw lines 181 to 186
187## Sources checked 2026-10-01
189- [Official PPG API](https://neuropsychology.github.io/NeuroKit/functions/ppg.html)
190- [Stable v0.2.13 PPG source](https://github.com/neuropsychology/NeuroKit/tree/v0.2.13/neurokit2/ppg)
191- [NeuroKit2 0.2.13 release](https://github.com/neuropsychology/NeuroKit/releases/tag/v0.2.13)
192- [Charlton et al. (2023), wearable PPG roadmap](https://doi.org/10.1088/1361-6579/acead2)
193- [Allen (2007), PPG measurement review](https://doi.org/10.1088/0967-3334/28/3/R01)
194- [Quigley et al. (2024), ECG/PPG and HRV guidance](https://doi.org/10.1111/psyp.14604)
195- [Yuda et al. (2020), PRV site differences](https://pmc.ncbi.nlm.nih.gov/articles/PMC7035641/)
197- [Stable `ppg_quality.py` implementation](https://github.com/neuropsychology/NeuroKit/blob/v0.2.13/neurokit2/ppg/ppg_quality.py)