Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.2.4 #776

Merged
merged 130 commits into from
Apr 6, 2023
Merged

0.2.4 #776

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
130 commits
Select commit Hold shift + click to select a range
5831baa
bump version (0.2.4)
DominiqueMakowski Feb 9, 2023
1bedb50
remove appended zeros from last heartbeat
danibene Feb 13, 2023
44e7f39
postprocess to remove indices larger than signal indices
danibene Feb 13, 2023
3a51d42
pad last heartbeat with nan
danibene Feb 14, 2023
16bbcd4
change dataframe indexing
danibene Feb 14, 2023
c681830
fix eda sympathetic index and add test
Feb 16, 2023
cc77750
fix eda sympathetic index and add test
Feb 16, 2023
19a2abe
run test and pass
Feb 16, 2023
401b76b
fix eda findpeaks with nabian2018 method
Feb 16, 2023
2e9b437
code check pass
Feb 16, 2023
543ca40
docstrin test
Feb 16, 2023
49b7d22
Merge pull request #777 from danibene/fix/ecg_segment_extra_samples
DominiqueMakowski Feb 17, 2023
82b8685
Merge branch 'dev' into pr/783
DominiqueMakowski Feb 17, 2023
8f1b480
mnor formatting + docstrings
DominiqueMakowski Feb 17, 2023
093226b
Update ecg_segment.py
DominiqueMakowski Feb 17, 2023
b1a3e8b
[breaking]: Use full names for features of eda_sympathetic
DominiqueMakowski Feb 17, 2023
f9ea3c9
minor docstrings
DominiqueMakowski Feb 17, 2023
7682d06
fix tests
DominiqueMakowski Feb 17, 2023
0d70c07
[Feature] refactor eda_intervalrelated
DominiqueMakowski Feb 17, 2023
4e91b56
commit before fetching
Feb 17, 2023
6d64355
solve conflict
Feb 17, 2023
13e18be
fix vanhalem2020 find peaks methods
Feb 17, 2023
257934e
Add warning if < 60 s
DominiqueMakowski Feb 18, 2023
d4496e9
style
DominiqueMakowski Feb 18, 2023
36232f4
Update NEWS.rst
DominiqueMakowski Feb 18, 2023
f62d45d
maybe like that
DominiqueMakowski Feb 18, 2023
b61428d
64 sec min instead of 60
DominiqueMakowski Feb 18, 2023
b624ec1
Fixes #784 by having eda_simulate passing a random_state argument to …
Feb 18, 2023
3867054
np.max -> np.nanmax
DominiqueMakowski Feb 19, 2023
64ecbab
fix test
DominiqueMakowski Feb 19, 2023
66b0c93
add @GanshengT to contributor
DominiqueMakowski Feb 19, 2023
6eed320
fix zero crossing bugs
Feb 19, 2023
d1e6815
fix
DominiqueMakowski Feb 19, 2023
d927d93
Merge pull request #783 from GanshengT/fix_eda_scr_calculation
DominiqueMakowski Feb 19, 2023
2457bdd
add interactive plot
danibene Feb 20, 2023
a65b217
add rsp_report
danibene Feb 20, 2023
f26836d
add test_rsp_report
danibene Feb 20, 2023
d89b7f4
import rsp_report
danibene Feb 20, 2023
ce82f53
remove line renaming x axis before creating plot
danibene Feb 20, 2023
5344213
format
danibene Feb 20, 2023
70c6953
remove commented out code
danibene Feb 20, 2023
8d10861
fix parameters for test_rsp_report
danibene Feb 20, 2023
40b9f28
again fix parameters for test_rsp_report
danibene Feb 20, 2023
ce667e4
fix number of parameters for test_rsp_report
danibene Feb 20, 2023
ad452e1
only test valid peaks methods
danibene Feb 20, 2023
2616773
test specific rvt methods
danibene Feb 20, 2023
6fccd47
remove extra s from biosppy
danibene Feb 20, 2023
0fedc30
sanitize extrema in scipy method
danibene Feb 20, 2023
448fc48
fix typo
danibene Feb 20, 2023
a45f7d4
Merge pull request #786 from danibene/fix/sanitize_rsp_peaks_scipy
DominiqueMakowski Feb 20, 2023
573b70e
Merge branch 'dev' into feature/rsp_plot_interactive
danibene Feb 20, 2023
75af8b7
return a constant signal if interpolating only one value
danibene Feb 20, 2023
8656a66
generate x_new earlier in script
danibene Feb 20, 2023
64a617f
Merge pull request #787 from danibene/fix/signal_interpolate_one_value
danibene Feb 20, 2023
bcae752
Merge branch 'dev' into feature/rsp_plot_interactive
danibene Feb 20, 2023
e302427
add autocor to intervalrelated
DominiqueMakowski Feb 20, 2023
71cbb05
fix
DominiqueMakowski Feb 21, 2023
e774ddc
Update eda_intervalrelated.py
DominiqueMakowski Feb 21, 2023
3cc4d7e
Merge pull request #789 from neuropsychology/add_autocor_eda_interval…
DominiqueMakowski Feb 21, 2023
042595c
minor docs
DominiqueMakowski Feb 21, 2023
2cd95cc
update docs to rsp_process
danibene Feb 21, 2023
b6d9cce
replace _report files with general function in misc
danibene Feb 21, 2023
04dcd0e
fix typo in name of variable
danibene Feb 21, 2023
4c12c72
fix import of create report
danibene Feb 21, 2023
d1aee12
only generate figure if saving as html
danibene Feb 21, 2023
30540fa
add random state
danibene Feb 22, 2023
0e394f8
change docs example
danibene Feb 22, 2023
a442270
return fig regardless of whether plot is static
danibene Feb 22, 2023
a47b2f5
fix typo
danibene Feb 22, 2023
76731be
add option for plotting with plotly
danibene Feb 22, 2023
f08d626
add matplotlib html export
danibene Feb 22, 2023
2bcdaf9
import plotly and matplotlib
danibene Feb 22, 2023
86a2983
remove kwargs from plotting funcs
danibene Feb 22, 2023
8794e5c
let's see how the rendered docs look like with text report
DominiqueMakowski Feb 22, 2023
989c07c
Merge pull request #785 from danibene/feature/rsp_plot_interactive
DominiqueMakowski Feb 22, 2023
ef1ca6d
Merge branch 'dev' into feature/eda_plot_interactive
danibene Feb 22, 2023
4e918b6
add working plot
danibene Feb 23, 2023
60b52e7
add methods file
danibene Feb 23, 2023
76e74d3
update methods
danibene Feb 23, 2023
11dd0f6
add report option to eda_process
danibene Feb 23, 2023
db8bc5a
have interactive plot by default
danibene Feb 23, 2023
cee81d2
use rsp_peaks instead of rsp_findpeaks
danibene Feb 23, 2023
6d70fd7
generate report with interactive plot
danibene Feb 23, 2023
515db8f
add test for eda report
danibene Feb 23, 2023
7a916bd
Merge pull request #791 from danibene/fix/report_methods
danibene Feb 23, 2023
704a679
format
danibene Feb 23, 2023
0e2fbb4
style
danibene Feb 23, 2023
bd102d1
style again
danibene Feb 23, 2023
ab79c11
revise error message
danibene Feb 23, 2023
cdce879
make order more consistent
danibene Feb 23, 2023
d1c49c8
add neurokit as equivalent to highpass for eda_phasic
danibene Feb 23, 2023
03f855a
ensure that filename is a string
danibene Feb 23, 2023
9a201b0
Merge branch 'dev' into feature/eda_plot_interactive
danibene Feb 23, 2023
d3e918c
return empty text if no rate cols
danibene Feb 23, 2023
874ddb6
Merge branch 'feature/eda_plot_interactive' of https://github.com/dan…
danibene Feb 23, 2023
7c99915
iterate over peaks and half recovery separately from onset
danibene Feb 23, 2023
811dea4
Modified the approach to random number generation (also solving the i…
Feb 24, 2023
4218318
Switched the default `random_state_distort` to "spawn". A small numbe…
Feb 25, 2023
575b148
Ran tools in https://github.com/neuropsychology/NeuroKit/blob/master/…
Feb 25, 2023
2c84e22
Merge branch 'dev' into master
lciti Feb 25, 2023
029353d
Fix error in _signal_distort_artifacts introduced by previous change
Feb 25, 2023
15e6fa9
Added tests for kmeans and kmedoids (that had low coverage)
Feb 25, 2023
3152652
fix name of method_cleaning
danibene Feb 26, 2023
65e6fa6
add none option within cleaning functions
danibene Mar 2, 2023
0977a11
Fixed test_ppg_simulate_all_rng_types to test_rsp_simulate_all_rng_types
Mar 3, 2023
690299b
compute median diff between timestamps for plot
danibene Mar 7, 2023
9865dc8
compute minimum frequency based on the median difference between time…
danibene Mar 7, 2023
d973ae2
Update neurokit2/hrv/hrv_frequency.py
danibene Mar 9, 2023
58f23df
add comment with justification
danibene Mar 9, 2023
73715e2
Merge pull request #800 from danibene/fix/plot_lombscargle_uneven
danibene Mar 10, 2023
cd36c22
Renamed get_rng to check_random_state for consistency with other pack…
Mar 12, 2023
c4c86d5
Added documentation
Mar 12, 2023
6af864e
Fixed error in example
Mar 12, 2023
f72ea91
Fixed error in example
Mar 12, 2023
4d80e60
Fixed issue with kmeans test failing with older versions of sk-learn
Mar 15, 2023
e9de4fa
Fixed typo in comment
Mar 15, 2023
9e5c253
Merge pull request #793 from lciti/master
DominiqueMakowski Mar 19, 2023
b947037
Merge pull request #792 from danibene/feature/eda_plot_interactive
danibene Mar 24, 2023
0548b5e
minor docs
DominiqueMakowski Mar 26, 2023
9e0b919
add facecolor argument
visserle Mar 29, 2023
35ed696
fix eda_clean for low sampling rates (#554)
DominiqueMakowski Mar 29, 2023
4bc744a
Merge pull request #810 from the-visserd/fix_readme_facecolor
DominiqueMakowski Mar 29, 2023
1c568ff
add angular entropy
DominiqueMakowski Mar 30, 2023
b7bfcf8
Update entropy_angular.py
DominiqueMakowski Mar 30, 2023
408da03
Merge pull request #811 from neuropsychology/feature_comEDA
DominiqueMakowski Mar 30, 2023
7efba3f
Add sparsEDA
DominiqueMakowski Mar 30, 2023
96201b6
Update eda_phasic.py
DominiqueMakowski Mar 30, 2023
dbefce5
Update eda_phasic.py
DominiqueMakowski Mar 30, 2023
0d36438
mention failed test
DominiqueMakowski Apr 2, 2023
751e5ba
Merge pull request #812 from neuropsychology/feature_sparsEDA
DominiqueMakowski Apr 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Core contributors
Contributors
-------------

* `Gansheng Tan <https://github.com/GanshengT>`_ *(Washington University, USA)*
* `Hung Pham <https://github.com/hungpham2511>`_ *(Eureka Robotics, Singapore)*
* `Christopher Schölzel <https://github.com/CSchoel>`_ *(THM University of Applied Sciences, Germany)*
* `Duy Le <https://github.com/duylp>`_ *(Hubble, Singapore)*
Expand All @@ -53,7 +54,7 @@ Contributors
* `Marek Sokol <https://github.com/sokolmarek>`_ *(Faculty of Biomedical Engineering of the CTU in Prague, Czech Republic)*


Thanks also to `Gansheng Tan <https://github.com/GanshengT>`_, `Chuan-Peng Hu <https://github.com/hcp4715>`_, `@ucohen <https://github.com/ucohen>`_, `Anthony Gatti <https://github.com/gattia>`_, `Julien Lamour <https://github.com/lamourj>`_, `@renatosc <https://github.com/renatosc>`_, `Nicolas Beaudoin-Gagnon <https://github.com/Fegalf>`_ and `@rubinovitz <https://github.com/rubinovitz>`_ for their contribution in `NeuroKit 1 <https://github.com/neuropsychology/NeuroKit.py>`_.
Thanks also to `Chuan-Peng Hu <https://github.com/hcp4715>`_, `@ucohen <https://github.com/ucohen>`_, `Anthony Gatti <https://github.com/gattia>`_, `Julien Lamour <https://github.com/lamourj>`_, `@renatosc <https://github.com/renatosc>`_, `Nicolas Beaudoin-Gagnon <https://github.com/Fegalf>`_ and `@rubinovitz <https://github.com/rubinovitz>`_ for their contribution in `NeuroKit 1 <https://github.com/neuropsychology/NeuroKit.py>`_.



Expand Down
9 changes: 9 additions & 0 deletions NEWS.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
News
=====

0.2.4
-------------------
Fixes
+++++++++++++

* `eda_sympathetic()` has been reviewed: low-pass filter and resampling have been added to be in
line with the original paper
* `eda_findpeaks()` using methods proposed in nabian2018 is reviewed and improved. Differentiation
has been added before smoothing. Skin conductance response criteria have been revised based on
the original paper.



Expand Down
23 changes: 12 additions & 11 deletions docs/functions/eda.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,6 @@ Preprocessing
"""""""""""""""""""""
.. autofunction:: neurokit2.eda.eda_phasic

*eda_autocor()*
"""""""""""""""
.. autofunction:: neurokit2.eda.eda_autocor

*eda_changepoints()*
"""""""""""""""""""""
.. autofunction:: neurokit2.eda.eda_changepoints

*eda_peaks()*
"""""""""""""""""""""
.. autofunction:: neurokit2.eda.eda_peaks
Expand All @@ -47,9 +39,6 @@ Preprocessing
"""""""""""""""""""""
.. autofunction:: neurokit2.eda.eda_fixpeaks

*eda_sympathetic()*
"""""""""""""""""""""
.. autofunction:: neurokit2.eda.eda_sympathetic


Analysis
Expand All @@ -62,6 +51,18 @@ Analysis
"""""""""""""""""""""""""
.. autofunction:: neurokit2.eda.eda_intervalrelated

*eda_sympathetic()*
"""""""""""""""""""""
.. autofunction:: neurokit2.eda.eda_sympathetic

*eda_autocor()*
"""""""""""""""
.. autofunction:: neurokit2.eda.eda_autocor

*eda_changepoints()*
"""""""""""""""""""""
.. autofunction:: neurokit2.eda.eda_changepoints



Miscellaneous
Expand Down
2 changes: 1 addition & 1 deletion docs/functions/hrv.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,5 @@ Intervals

.. automodule:: neurokit2.hrv
:members:
:exclude-members: hrv, hrv_time, hrv_frequency, hrv_nonlinear, hrv_rqa, hrv_rsa
:exclude-members: hrv, hrv_time, hrv_frequency, hrv_nonlinear, hrv_rqa, hrv_rsa, intervals_process, intervals_to_peaks

2 changes: 1 addition & 1 deletion docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Then, at the top of each of your Python script, you should be able to import the

.. code-block:: console

pip install https://github.com/neuropsychology/neurokit/zipball/dev
pip install https://github.com/neuropsychology/neurokit/zipball/dev --upgrade



Expand Down
1 change: 1 addition & 0 deletions docs/readme/README_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
# Setup matplotlib with Agg to run on server
matplotlib.use("Agg")
plt.rcParams["figure.figsize"] = (10, 6.5)
plt.rcParams["savefig.facecolor"] = "white"

# =============================================================================
# Quick Example
Expand Down
2 changes: 1 addition & 1 deletion neurokit2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from .video import *

# Info
__version__ = "0.2.3"
__version__ = "0.2.4"


# Maintainer info
Expand Down
2 changes: 2 additions & 0 deletions neurokit2/complexity/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from .complexity_lyapunov import complexity_lyapunov
from .complexity_relativeroughness import complexity_relativeroughness
from .complexity_rqa import complexity_rqa
from .entropy_angular import entropy_angular
from .entropy_approximate import entropy_approximate
from .entropy_attention import entropy_attention
from .entropy_bubble import entropy_bubble
Expand Down Expand Up @@ -155,6 +156,7 @@
"complexity_dfa",
"complexity_relativeroughness",
"complexity_rqa",
"entropy_angular",
"entropy_maximum",
"entropy_shannon",
"entropy_shannon_joint",
Expand Down
147 changes: 147 additions & 0 deletions neurokit2/complexity/entropy_angular.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import scipy.stats

from .utils_complexity_embedding import complexity_embedding


def entropy_angular(signal, delay=1, dimension=2, show=False, **kwargs):
"""**Angular entropy (AngEn)**

The Angular Entropy (AngEn) is the name that we use in NeuroKit to refer to the complexity
method described in Nardelli et al. (2022), referred as comEDA due to its application to EDA
signal. The method comprises the following steps: 1) Phase space reconstruction, 2) Calculation
of the angular distances between all the pairs of points in the phase space; 3) Computation of
the probability density function (PDF) of the distances; 4) Quadratic Rényi entropy of the PDF.

Parameters
----------
signal : Union[list, np.array, pd.Series]
The signal (i.e., a time series) in the form of a vector of values.
delay : int
Time delay (often denoted *Tau* :math:`\\tau`, sometimes referred to as *lag*) in samples.
See :func:`complexity_delay` to estimate the optimal value for this parameter.
dimension : int
Embedding Dimension (*m*, sometimes referred to as *d* or *order*). See
:func:`complexity_dimension` to estimate the optimal value for this parameter.
**kwargs : optional
Other arguments.

Returns
--------
angen : float
The Angular Entropy (AngEn) of the signal.
info : dict
A dictionary containing additional information regarding the parameters used
to compute the index.

See Also
--------
entropy_renyi

Examples
----------
.. ipython:: python

import neurokit2 as nk

# Simulate a Signal with Laplace Noise
signal = nk.signal_simulate(duration=2, frequency=[5, 3], noise=0.1)

# Compute Angular Entropy
@savefig p_entropy_angular1.png scale=100%
angen, info = nk.entropy_angular(signal, delay=1, dimension=3, show=True)
@suppress
plt.close()


References
-----------
* Nardelli, M., Greco, A., Sebastiani, L., & Scilingo, E. P. (2022). ComEDA: A new tool for
stress assessment based on electrodermal activity. Computers in Biology and Medicine, 150,
106144.

"""
# Sanity checks
if isinstance(signal, (np.ndarray, pd.DataFrame)) and signal.ndim > 1:
raise ValueError(
"Multidimensional inputs (e.g., matrices or multichannel data) are not supported yet."
)

# 1. Phase space reconstruction (time-delay embeddings)
embedded = complexity_embedding(signal, delay=delay, dimension=dimension)

# 2. Angular distances between all the pairs of points in the phase space
angles = _angular_distance(embedded)

# 3. Compute the probability density function (PDF) of the upper triangular matrix
bins, pdf = _kde_sturges(angles)

# 4. Apply the quadratic Rényi entropy to the PDF
angen = -np.log2(np.sum(pdf**2))

# Normalize to the range [0, 1] by the log of the number of bins

# Note that in the paper (eq. 4 page 4) there is a minus sign, but adding it would give
# negative values, plus the linked code does not seem to do that
# https://github.com/NardelliM/ComEDA/blob/main/comEDA.m#L103
angen = angen / np.log2(len(bins))

if show is True:
# Plot the PDF as a bar chart
plt.bar(bins[:-1], pdf, width=bins[1] - bins[0], align="edge", alpha=0.5)
# Set the x-axis limits to the range of the data
plt.xlim([np.min(angles), np.max(angles)])
# Print titles
plt.suptitle(f"Angular Entropy (AngEn) = {angen:.3f}")
plt.title("Distribution of Angular Distances:")

return angen, {"bins": bins, "pdf": pdf}


def _angular_distance(m):
"""
Compute angular distances between all the pairs of points.
"""
# Get index of upper triangular to avoid double counting
idx = np.triu_indices(m.shape[0], k=1)

# compute the magnitude of each vector
magnitudes = np.linalg.norm(m, axis=1)

# compute the dot product between all pairs of vectors using np.matmul function, which is
# more efficient than np.dot for large matrices; and divide the dot product matrix by the
# product of the magnitudes to get the cosine of the angle
cos_angles = np.matmul(m, m.T)[idx] / np.outer(magnitudes, magnitudes)[idx]

# clip the cosine values to the range [-1, 1] to avoid any numerical errors and compute angles
return np.arccos(np.clip(cos_angles, -1, 1))


def _kde_sturges(x):
"""
Computes the PDF of a vector x using a kernel density estimator based on linear diffusion
processes with a Gaussian kernel. The number of bins of the PDF is chosen applying the Sturges
method.
"""
# Estimate the bandwidth
iqr = np.percentile(x, 75) - np.percentile(x, 25)
bandwidth = 0.9 * iqr / (len(x) ** 0.2)

# Compute the number of bins using the Sturges method
nbins = int(np.ceil(np.log2(len(x)) + 1))

# Compute the bin edges
bins = np.linspace(np.min(x), np.max(x), nbins + 1)

# Compute the kernel density estimate
xi = (bins[:-1] + bins[1:]) / 2
pdf = np.sum(
scipy.stats.norm.pdf((xi.reshape(-1, 1) - x.reshape(1, -1)) / bandwidth), axis=1
) / (len(x) * bandwidth)

# Normalize the PDF
pdf = pdf / np.sum(pdf)

return bins, pdf
9 changes: 4 additions & 5 deletions neurokit2/complexity/entropy_differential.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,17 @@ def entropy_differential(signal, base=2, **kwargs):
----------
signal : Union[list, np.array, pd.Series]
The signal (i.e., a time series) in the form of a vector of values.

base: float
The logarithmic base to use, defaults to ``2``, giving a unit in *bits*. Note that ``scipy.
stats.entropy()`` uses Euler's number (``np.e``) as default (the natural logarithm), giving
a measure of information expressed in *nats*.
**kwargs : optional
Other arguments passed to ``scipy.stats.differential_entropy()``.

Returns
--------
diffen : float
The Differential entropy of the signal.
base: float
The logarithmic base to use, defaults to ``2``, giving a unit in *bits*. Note that ``scipy.
stats.entropy()`` uses Euler's number (``np.e``) as default (the natural logarithm), giving
a measure of information expressed in *nats*.
info : dict
A dictionary containing additional information regarding the parameters used
to compute Differential entropy.
Expand Down
2 changes: 1 addition & 1 deletion neurokit2/complexity/entropy_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def entropy_sample(signal, delay=1, dimension=2, tolerance="sd", **kwargs):

signal = nk.signal_simulate(duration=2, frequency=5)

sampen, parameters = nk.entropy_sample(signal)
sampen, parameters = nk.entropy_sample(signal, delay=1, dimension=2)
sampen

"""
Expand Down
10 changes: 5 additions & 5 deletions neurokit2/ecg/ecg_delineate.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ def ecg_delineate(
"NeuroKit error: ecg_delineate(): 'method' should be one of 'peak'," "'cwt' or 'dwt'."
)

# Ensure that all indices are not larger than ECG signal indices
for _, value in waves.items():
if value[-1] >= len(ecg_cleaned):
value[-1] = np.nan

# Remove NaN in Peaks, Onsets, and Offsets
waves_noNA = waves.copy()
for feature in waves_noNA.keys():
Expand Down Expand Up @@ -947,11 +952,6 @@ def _ecg_delineator_peak(ecg, rpeaks=None, sampling_rate=1000):
"ECG_T_Offsets": T_offsets,
}

# Ensure that all indices are not larger than ECG signal indices
for _, value in info.items():
if value[-1] >= len(ecg):
value[-1] = np.nan

# Return info dictionary
return info

Expand Down
5 changes: 5 additions & 0 deletions neurokit2/ecg/ecg_segment.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ def ecg_segment(ecg_cleaned, rpeaks=None, sampling_rate=1000, show=False):
epochs_end=epochs_end,
)

# pad last heartbeat with nan so that segments are equal length
last_heartbeat_key = str(np.max(np.array(list(heartbeats.keys()), dtype=int)))
after_last_index = heartbeats[last_heartbeat_key]["Index"] < len(ecg_cleaned)
heartbeats[last_heartbeat_key].loc[after_last_index, "Signal"] = np.nan

if show:
heartbeats_plot = epochs_to_df(heartbeats)
heartbeats_pivoted = heartbeats_plot.pivot(index="Time", columns="Label", values="Signal")
Expand Down
Loading