Skip to content

Commit 8a75460

Browse files
author
Nicolas Legrand
committed
- Add examples in detection docs
- Clean PPG signal data import (only keep one version)
1 parent 37d87f2 commit 8a75460

File tree

14 files changed

+80
-47
lines changed

14 files changed

+80
-47
lines changed

MANIFEST.in

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ include LICENSE
44
include requirements.txt
55

66
# Add datasets files
7-
include systole/datasets/ppg1.npy
8-
include systole/datasets/ppg2.npy
9-
include systole/datasets/ppg3.npy
10-
include systole/datasets/ppgNoisy1.npy
7+
include systole/datasets/ppg.npy
118
include systole/datasets/rr.txt
129
include systole/datasets/Task1_ECG.npy
1310
include systole/datasets/Task1_EDA.npy

systole/datasets/5minRest.npy

-265 KB
Binary file not shown.

systole/datasets/__init__.py

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
# Simulate serial inputs from ppg recording
1212
# =========================================
1313
class serialSim():
14-
"""Simulate online data cquisition using pre recorded signal and realistic
15-
recording duration.
14+
"""Simulate online data acquisition using pre recorded signal and realistic
15+
sampling rate (75 Hz).
1616
"""
1717

1818
def __init__(self, id='1'):
1919
self.sfreq = 75
20-
self.ppg = import_ppg()[0]
20+
self.ppg = import_ppg().ppg.to_numpy()
2121
self.start = time.time()
2222

2323
def inWaiting(self):
@@ -32,7 +32,7 @@ def inWaiting(self):
3232
def read(self, length):
3333

3434
if len(self.ppg) == 0:
35-
self.ppg = import_ppg()[0]
35+
self.ppg = import_ppg().ppg.to_numpy()
3636

3737
# Read 1rst item of ppg signal
3838
rec = self.ppg[:1]
@@ -48,30 +48,26 @@ def reset_input_buffer(self):
4848
print('Reset input buffer')
4949

5050

51-
def import_ppg(id='1'):
52-
"""Import PPG recording.
53-
54-
Parameters
55-
----------
56-
id : int
57-
Signal number (1 or 2).
51+
def import_ppg():
52+
"""Import a 5 minutes long PPG recording.
5853
5954
Returns
6055
-------
61-
signal : array
62-
1d array containing the PPG signal.
56+
df : :py:class:`pandas.DataFrame`
57+
Dataframe containing the PPG signale.
6358
"""
64-
signal = np.load(op.join(ddir, 'ppg' + id + '.npy'))
59+
df = pd.DataFrame({'ppg': np.load(op.join(ddir, 'ppg.npy'))})
60+
df['time'] = np.arange(0, len(df))/75
6561

66-
return signal
62+
return df
6763

6864

6965
def import_rr():
7066
"""Import PPG recording.
7167
7268
Returns
7369
-------
74-
rr : pandas DataFrame
70+
rr : :py:class:`pandas.DataFrame`
7571
Dataframe containing the RR time-serie.
7672
"""
7773
rr = pd.read_csv(op.join(ddir, 'rr.txt'))
@@ -84,7 +80,7 @@ def import_dataset():
8480
8581
Returns
8682
-------
87-
df : pandas DataFrame
83+
df : :py:class:`pandas.DataFrame`
8884
Dataframe containing the RR time-serie.
8985
9086
Notes

systole/datasets/ppg.npy

97.2 KB
Binary file not shown.

systole/datasets/ppg1.npy

-194 KB
Binary file not shown.

systole/datasets/ppg2.npy

-265 KB
Binary file not shown.

systole/datasets/ppg3.npy

-9.78 KB
Binary file not shown.

systole/datasets/ppgNoisy1.npy

-399 KB
Binary file not shown.

systole/detection.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ def oxi_peaks(x, sfreq=75, win=1, new_sfreq=1000, clipping=True,
4242
4343
.. warning :: This function will resample the signal to 1000 Hz.
4444
45+
Examples
46+
--------
47+
>>> from systole import import_ppg
48+
>>> from systole.detection import oxi_peaks
49+
>>> df = import_ppg() # Import PPG recording
50+
>>> signal, peaks = oxi_peaks(df.ppg.to_numpy())
51+
>>> print(f'{sum(peaks)} peaks detected.')
52+
4553
References
4654
----------
4755
Some of the processing steps were adapted from the HeartPy toolbox [1]:
@@ -133,6 +141,15 @@ def ecg_peaks(x, sfreq=1000, new_sfreq=1000, method='pan-tompkins',
133141
134142
.. warning :: This function will resample the signal to 1000 Hz.
135143
144+
Examples
145+
--------
146+
>>> from systole import import_dataset
147+
>>> from systole.detection import ecg_peaks
148+
>>> signal_df = import_dataset()[:20*2000]
149+
>>> signal, peaks = ecg_peaks(signal_df.ecg.to_numpy(), method='hamilton',
150+
>>> sfreq=2000, find_local=True)
151+
>>> print(f'{sum(peaks)} peaks detected.')
152+
136153
References
137154
----------
138155
Some of the processing steps were adapted from the HeartPy toolbox [1]:
@@ -233,6 +250,14 @@ def rr_artefacts(rr, c1=0.13, c2=0.17, alpha=5.2):
233250
This function will use the method proposed by Lipponen & Tarvainen (2019)
234251
to detect ectopic beats, long, shorts, missed and extra RR intervals.
235252
253+
Examples
254+
--------
255+
>>> from systole import simulate_rr
256+
>>> from systole.detection import rr_artefacts
257+
>>> rr = simulate_rr() # Simulate RR time series
258+
>>> artefacts = rr_artefacts(rr)
259+
>>> print(artefacts.keys())
260+
236261
References
237262
----------
238263
.. [1] Lipponen, J. A., & Tarvainen, M. P. (2019). A robust algorithm for
@@ -358,6 +383,21 @@ def interpolate_clipping(signal, threshold=255):
358383
clean_signal : 1d array-like
359384
Interpolated signal.
360385
386+
Examples
387+
--------
388+
.. plot::
389+
>>> import matplotlib.pyplot as plt
390+
>>> from systole import import_ppg
391+
>>> from systole.detection import interpolate_clipping
392+
>>> df = import_ppg()
393+
>>> clean_signal = interpolate_clipping(df.ppg.to_numpy(),
394+
>>> threshold=255)
395+
>>> plt.plot(df.time, clean_signal, color='#F15854')
396+
>>> plt.plot(df.time, ppg, color='#5DA5DA')
397+
>>> plt.axhline(y=255, linestyle='--', color='k')
398+
>>> plt.xlabel('Time (s)')
399+
>>> plt.ylabel('PPG level (a.u)')
400+
361401
Notes
362402
-----
363403
Correct signal segment reaching recording threshold (default is 255)

systole/hrv.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def time_domain(x):
104104
105105
Returns
106106
-------
107-
stats : Pandas DataFrame
107+
stats : :py:class:`pandas.DataFrame`
108108
Time domain summary statistics:
109109
110110
'Mean RR' : Mean of R-R intervals.
@@ -192,7 +192,7 @@ def frequency_domain(x, sfreq=5, method='welch', fbands=None):
192192
193193
Returns
194194
-------
195-
stats : pandas DataFrame
195+
stats : :py:class:`pandas.DataFrame`
196196
DataFrame of HRV parameters (frequency domain)
197197
"""
198198
# Interpolate R-R interval
@@ -271,7 +271,7 @@ def nonlinear(x):
271271
272272
Returns
273273
-------
274-
stats : pandas DataFrame
274+
stats : :py:class:`pandas.DataFrame`
275275
DataFrame of HRV parameters (frequency domain)
276276
"""
277277

0 commit comments

Comments
 (0)