Skip to content

Commit 8ba538e

Browse files
author
LegrandNico
committed
Documentation
1 parent 084d870 commit 8ba538e

33 files changed

+777
-417
lines changed

README.rst

Lines changed: 102 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,17 @@
3333

3434
================
3535

36-
**Systole** is an open-source Python package providing simple tools to record and analyze, cardiac signals for psychophysiology.
37-
In particular, the package provides tools to pre-process, analyze, and synchronize cardiac data from psychophysiology research.
38-
This includes tools for data epoching, heart-rate variability, and synchronizing stimulus presentation with different cardiac phases via psychopy.
36+
**Systole** is an open-source Python package implementing simple tools for working with cardiac signals for
37+
psychophysiology research. In particular, the package provides tools to pre-process, visualize, and analyze cardiac data.
38+
This includes tools for data epoching, artefact detection, artefact correction, evoked heart-rate analyses, heart-rate
39+
variability analyses, circular statistical approaches to analysing cardiac cycles, and synchronising stimulus
40+
presentation with different cardiac phases via the psychopy.
41+
3942

4043
The documentation can be found under the following `link <https://systole-docs.github.io/>`_.
4144

4245
Installation
43-
============
46+
++++++++++++
4447

4548
Systole can be installed using pip:
4649

@@ -53,98 +56,131 @@ The following packages are required to use Systole:
5356
* `Numpy <https://numpy.org/>`_ (>=1.15)
5457
* `SciPy <https://www.scipy.org/>`_ (>=1.3.0)
5558
* `Pandas <https://pandas.pydata.org/>`_ (>=0.24)
56-
* `Matplotlib <https://matplotlib.org/>`_ (>=3.0.2)
57-
* `Seaborn <https://seaborn.pydata.org/>`_ (>=0.9.0)
5859
* `Numba <http://numba.pydata.org/>`_ (>=0.51.2)
60+
* `Seaborn <https://seaborn.pydata.org/>`_ (>=0.9.0)
5961

60-
Interactive plotting functions and reports generation will also require the following packages to be installed:
61-
62+
Required when using `Matplotlib` plotting backend:
63+
* `Matplotlib <https://matplotlib.org/>`_ (>=3.0.2)
64+
Required when using `Bokeh` plotting backend:
6265
* `Bokeh <https://docs.bokeh.org/en/latest/index.html#>`_ (>=2.3.3)
6366

64-
Tutorial
65-
========
6667

67-
For an overview of all the recording functionalities, you can refer to the following examples:
68-
69-
* Recording
70-
* Artefacts detection and artefacts correction
71-
* Heart rate variability
68+
Tutorials
69+
=========
7270

7371
For an introduction to Systole and cardiac signal analysis, you can refer to the following tutorial:
7472

75-
* Introduction to cardiac signal analysis - |Colab badge| - `Jupyter Book <https://legrandnico.github.io/Notebooks/IntroductionCardiacSignalAnalysis.html>`_
73+
1. Cardiac signal analysis - |Colab badge 1|
74+
2. Detecting cardiac cycles - |Colab badge 2|
75+
3. Detecting and correcting artefats - |Colab badge 3|
76+
4. Heart rate variability - |Colab badge 4|
77+
5. Instantaneous and evoked heart rate - |Colab badge 5|
7678

77-
.. |Colab badge| image:: https://colab.research.google.com/assets/colab-badge.svg
78-
:target: https://colab.research.google.com/github/LegrandNico/Notebooks/blob/main/IntroductionCardiacSignalAnalysis.ipynb
79+
.. |Colab badge 1| image:: https://colab.research.google.com/assets/colab-badge.svg
80+
:target: https://colab.research.google.com/github/embodied-computation-group/systole/blob/dev/source/notebooks/1-PhysiologicalSignals.ipynb
7981

80-
Recording
81-
=========
82+
.. |Colab badge 2| image:: https://colab.research.google.com/assets/colab-badge.svg
83+
:target: https://colab.research.google.com/github/embodied-computation-group/systole/blob/dev/source/notebooks/2-DetectingCycles.ipynb
8284

83-
Systole natively supports recording of physiological signals from the following setups:
84-
* `Nonin 3012LP Xpod USB pulse oximeter <https://www.nonin.com/products/xpod/>`_ together with the `Nonin 8000SM 'soft-clip' fingertip sensors <https://www.nonin.com/products/8000s/>`_ (USB).
85-
* Remote Data Access (RDA) via BrainVision Recorder together with `Brain product ExG amplifier <https://www.brainproducts.com/>`_ (Ethernet).
85+
.. |Colab badge 3| image:: https://colab.research.google.com/assets/colab-badge.svg
86+
:target: https://colab.research.google.com/github/embodied-computation-group/systole/blob/dev/source/notebooks/3-DetectingAndCorrectingArtefacts.ipynb
87+
88+
.. |Colab badge 4| image:: https://colab.research.google.com/assets/colab-badge.svg
89+
:target: https://colab.research.google.com/github/embodied-computation-group/systole/blob/dev/source/notebooks/4-HeartRateVariability.ipynb
8690

87-
Artefact correction
88-
===================
91+
.. |Colab badge 5| image:: https://colab.research.google.com/assets/colab-badge.svg
92+
:target: https://colab.research.google.com/github/embodied-computation-group/systole/blob/dev/source/notebooks/5-InstantaneousHeartRate.ipynb
8993

90-
Systole implements systolic peak detection inspired by van Gent et al. (2019) and the artefact rejection method recently proposed by Lipponen & Tarvainen (2019).
94+
95+
Getting started
96+
+++++++++++++++
9197

9298
.. code-block:: python
9399
94-
from systole import simulate_rr
95-
from systole.plots import plot_subspaces
100+
from systole import import_dataset1
96101
97-
rr = simulate_rr()
98-
plot_subspaces(rr)
102+
# Import ECg recording
103+
signal = import_dataset1(modalities=['ECG']).ecg.to_numpy()
99104
100-
.. figure:: https://github.com/embodied-computation-group/systole/raw/master/Images/subspaces.png
101-
:align: center
102105
103-
Interactive visualization
104-
=========================
106+
Signal extraction and interactive plotting
107+
==========================================
108+
The package integrates a set of functions for interactive or non interactive data visualization based on `Matplotlib <https://matplotlib.org/>`_ and `Bokeh <https://docs.bokeh.org/en/latest/index.html#>`_.
105109

106-
Systole integrates a set of functions for interactive data visualization based on `Bokeh <https://docs.bokeh.org/en/latest/index.html#>`_.
110+
.. code-block:: python
107111
108-
.. figure:: https://github.com/embodied-computation-group/systole/raw/master/Images/systole.gif
109-
:align: center
112+
from systole.plots plot_raw
110113
111-
Heartrate variability
112-
======================
114+
plot_raw(signal[60000 : 120000], modality="ecg", backend="bokeh",
115+
show_heart_rate=True, show_artefacts=True, figsize=300)
113116
114117
.. raw:: html
115-
:file: source/images/hrv.html
118+
:file: source/images/raw.html
116119

117-
.. figure:: source/images/hrv.png
118120

119-
Systole supports basic time-domain, frequency-domain and non-linear extraction indices.
121+
Artefacts detection and rejection
122+
=================================
123+
Artefacts can be detected and corrected in the RR interval time series or the peaks vector following the algorythm proposed by Lipponen & Tarvainen (2019).
120124

121-
All time-domain and non-linear indices have been tested against Kubios HVR 2.2 (<https://www.kubios.com>). The frequency-domain indices can slightly differ. We recommend to always check your results against another software.
125+
.. code-block:: python
126+
127+
from systole.detection import ecg_peaks
128+
from systole.plots plot_subspaces
129+
130+
# R peaks detection
131+
signal, peaks = ecg_peaks(signal, method='pan-tompkins', sfreq=1000)
132+
133+
plot_subspaces(peaks, input_type="peaks", backend="bokeh")
134+
135+
.. raw:: html
136+
:file: source/images/subspaces.html
137+
138+
Instantaneous and evoked heart rate
139+
===================================
140+
141+
142+
Heart rate variability analysis
143+
===============================
144+
Systole implemetns basic time-domain, frequency-domain and non-linear HRV indices.
122145

123146
.. code-block:: python
124147
125-
from systole.plots import plot_frequency
148+
from bokeh.layouts import row
149+
from systole.plots plot_frequency, plot_pointcare
126150
127-
plot_psd(rr)
151+
row(
152+
plot_frequency(peaks, input_type="peaks", backend="bokeh", figsize=(600, 400)),
153+
plot_pointcare(peaks, input_type="peaks", backend="bokeh", figsize=(400, 400)),
154+
)
155+
156+
.. raw:: html
157+
:file: source/images/hrv.html
158+
159+
160+
Online systolic peak detection, cardiac-stimulus synchrony, and cardiac circular analysis
161+
=========================================================================================
162+
163+
Systole natively supports recording of physiological signals from the following setups:
164+
- `Nonin 3012LP Xpod USB pulse oximeter <https://www.nonin.com/products/xpod/>`_ together with the `Nonin 8000SM 'soft-clip' fingertip sensors <https://www.nonin.com/products/8000s/>`_ (USB).
165+
- Remote Data Access (RDA) via BrainVision Recorder together with `Brain product ExG amplifier <https://www.brainproducts.com/>`_ (Ethernet).
128166

129-
.. figure:: https://github.com/embodied-computation-group/systole/raw/master/Images/psd.png
130-
:align: center
131167

132168
Development
133-
===========
169+
+++++++++++
134170

135171
This module was created and is maintained by Nicolas Legrand and Micah Allen (ECG group, https://the-ecg.org/). If you want to contribute, feel free to contact one of the developers, open an issue or submit a pull request.
136172

137173
This program is provided with NO WARRANTY OF ANY KIND.
138174

139175
Contributors
140-
============
176+
++++++++++++
141177

142178
- Jan C. Brammer ([email protected])
143179
- Gidon Levakov ([email protected])
144180
- Peter Doggart ([email protected])
145181

146182
Acknowledgements
147-
================
183+
++++++++++++++++
148184

149185
This software and the ECG are supported by a Lundbeckfonden Fellowship (R272-2017-4345), and the AIAS-COFUND II fellowship programme that is supported by the Marie Skłodowska-Curie actions under the European Union’s Horizon 2020 (Grant agreement no 754513), and the Aarhus University Research Foundation.
150186

@@ -158,4 +194,19 @@ Systole was largely inspired by pre-existing toolboxes dedicated to heartrate va
158194

159195
* ECG-detector: https://github.com/berndporr/py-ecg-detectors
160196

161-
* Pingouin: https://pingouin-stats.org/
197+
* Pingouin: https://pingouin-stats.org/
198+
199+
* NeuroKit2: https://github.com/neuropsychology/NeuroKit
200+
201+
================
202+
203+
|AU| |lundbeck| |lab|
204+
205+
.. |AU| image:: https://github.com/embodied-computation-group/systole/raw/dev/Images/au_clinisk_logo.png
206+
:width: 100%
207+
208+
.. |lundbeck| image:: https://github.com/embodied-computation-group/systole/raw/dev/Images/lundbeckfonden_logo.png
209+
:width: 10%
210+
211+
.. |lab| image:: https://github.com/embodied-computation-group/systole/raw/dev/Images/LabLogo.png
212+
:width: 20%

examples/Artefacts/README.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Artefacts
2+
+++++++++
File renamed without changes.
File renamed without changes.

examples/README.rst

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,4 @@
33
Example gallery
44
===============
55

6-
This section demonstrates some of the basic functionality of **systole**.
7-
If you want to see the tutorials in action, you can also click on the link below and navigate to the ``tutorials/`` folder to launch one of the interactive Jupyter notebooks.
8-
9-
.. contents:: Contents
10-
:local:
11-
:depth: 3
6+
This section demonstrates some of the basic functionality of **systole**.

examples/Recording/README.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Recording
2+
+++++++++
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
"""
2+
Recording PPG signal
3+
====================
4+
5+
The py:class:systole.recording.Oximeter class can be used to read incoming PPG signal
6+
from `Nonin 3012LP Xpod USB pulse oximeter
7+
<https://www.nonin.com/products/xpod/>`_ together with the `Nonin 8000SM 'soft-clip'
8+
fingertip sensors <https://www.nonin.com/products/8000s/>`_. This function can easily
9+
be integrated with other stimulus presentation software lie `PsychoPy
10+
<https://www.psychopy.org/>`_ to record cardiac activity during psychological
11+
experiments, or to synchronize stimulus delivery around cardiac phases (e.g. systole or
12+
diastole).
13+
14+
"""
15+
16+
# Author: Nicolas Legrand <[email protected]>
17+
# Licence: GPL v3
18+
19+
20+
#%%
21+
# Recording PPG singal
22+
# --------------------
23+
24+
from systole.recording import Oximeter
25+
from systole import serialSim
26+
#%%
27+
# Recording and plotting your first PPG time-series only require a few lines of code:
28+
# First, open a serial port. Note that here we are using Systole's PPG simulation
29+
# function so the example can run without any device plugged on the computer for the
30+
# demonstration. If you want to connect to an actual Nonin pulse oximeter, you simply
31+
# have to provide the port reference it is plugged in (see commented lines below).
32+
33+
ser = serialSim() # Simulate a device
34+
35+
# Use a USB device
36+
#import serial
37+
#ser = serial.Serial("COM4") # Use this line for USB recording
38+
39+
#%%
40+
# Once the reference of the port created, you can create a recording instance,
41+
# initialize it and read some incoming signal in just one line of code.
42+
43+
oxi = Oximeter(serial=ser).setup().read(duration=10)
44+
45+
#%% The recording instance also interface with systole's plotting module so the signal
46+
# can be directly plotted using built-in functions.
47+
oxi.plot_raw(show_heart_rate=True, figsize=(13, 8))
48+
49+
#%%
50+
# Interfacing with PsychoPy
51+
# -------------------------
52+
# One nice feature provided by Systole is that it can run the recording of PPG signal
53+
# together with other Python scripts like Psychopy, which can be used to build
54+
# psychological experiments. There are two ways for interfacing with other scripts, it
55+
# can be done either in a serial or in a (pseudo-) parallel way.
56+
57+
# - The ``read()`` method will record for a predefined amount of time
58+
# (specified by the ``duration`` parameter, in seconds). This 'serial mode'
59+
# is the easiest and most robust method, but it does not allow the execution
60+
# of other instructions in the meantime.
61+
62+
# Code 1 {}
63+
oxi.read(duration=10)
64+
# Code 2 {}
65+
66+
# - The ``readInWaiting()`` method will only read the bytes temporally stored
67+
# in the USB buffer. For the Nonin device, this represents up to 10 seconds of
68+
# recording (this procedure should be executed at least one time every 10
69+
# seconds for a continuous recording). When inserted into a while loop, it can
70+
# record PPG signal almost in parallel with other commands.
71+
72+
import time
73+
tstart = time.time()
74+
while time.time() - tstart < 10:
75+
oxi.readInWaiting()
76+
# Insert code here {...}
77+
78+
#%%
79+
# Online detection
80+
# ----------------
81+
# The recording instance is also detecting heartbeats automatically in the background,
82+
# and this information can be accessed in real-time to deliver stimuli time-locked to
83+
# specific cardiac phases. Note that the delay between the actual heartbeat and the
84+
# execution of computer code (here the `print` command in the example below) can be
85+
# important. Also, it is important to note that the systolic peak detected in the PPG
86+
# signal is delayed relative to the R peaks observed in the ECG signal.
87+
88+
# Create an Oxymeter instance and initialize recording
89+
oxi = Oximeter(serial=ser, sfreq=75, add_channels=4).setup()
90+
91+
# Online peak detection - run for 10 seconds
92+
tstart = time.time()
93+
while time.time() - tstart < 10:
94+
while oxi.serial.inWaiting() >= 5:
95+
paquet = list(oxi.serial.read(5))
96+
oxi.add_paquet(paquet[2]) # Add new data point
97+
if oxi.peaks[-1] == 1:
98+
print("Heartbeat detected")

0 commit comments

Comments
 (0)