Skip to content

Commit 709f3fd

Browse files
Merge pull request #21 from rzlim08/rvt
Add RVT algorithm (Birn et al. 2006)
2 parents 26211fb + 24515ca commit 709f3fd

File tree

4 files changed

+97
-0
lines changed

4 files changed

+97
-0
lines changed

phys2denoise/metrics/chest_belt.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from scipy.ndimage.filters import convolve1d
66
from scipy.signal import detrend
77
from scipy.stats import zscore
8+
from scipy.interpolate import interp1d
89

910
mpl.use("TkAgg")
1011
import matplotlib.pyplot as plt
@@ -14,6 +15,68 @@
1415
from . import utils
1516

1617

18+
def rvt(belt_ts, peaks, troughs, samplerate, lags=(0, 4, 8, 12)):
19+
"""
20+
Implement the Respiratory Variance over Time (Birn et al. 2006).
21+
22+
Procedural choices influenced by RetroTS
23+
24+
Parameters
25+
----------
26+
belt_ts: array_like
27+
respiratory belt data - samples x 1
28+
peaks: array_like
29+
peaks found by peakdet algorithm
30+
troughs: array_like
31+
troughs found by peakdet algorithm
32+
samplerate: float
33+
sample rate in hz of respiratory belt
34+
lags: tuple
35+
lags in seconds of the RVT output. Default is 0, 4, 8, 12.
36+
37+
Outputs
38+
-------
39+
rvt: array_like
40+
calculated RVT and associated lags.
41+
"""
42+
timestep = 1 / samplerate
43+
# respiration belt timing
44+
time = np.arange(0, len(belt_ts) * timestep, timestep)
45+
peak_vals = belt_ts[peaks]
46+
trough_vals = belt_ts[troughs]
47+
peak_time = time[peaks]
48+
trough_time = time[troughs]
49+
mid_peak_time = (peak_time[:-1] + peak_time[1:]) / 2
50+
period = peak_time[1:] - peak_time[:-1]
51+
# interpolate peak values over all timepoints
52+
peak_interp = interp1d(
53+
peak_time, peak_vals, bounds_error=False, fill_value="extrapolate"
54+
)(time)
55+
# interpolate trough values over all timepoints
56+
trough_interp = interp1d(
57+
trough_time, trough_vals, bounds_error=False, fill_value="extrapolate"
58+
)(time)
59+
# interpolate period over all timepoints
60+
period_interp = interp1d(
61+
mid_peak_time, period, bounds_error=False, fill_value="extrapolate"
62+
)(time)
63+
# full_rvt is (peak-trough)/period
64+
full_rvt = (peak_interp - trough_interp) / period_interp
65+
# calculate lags for RVT
66+
rvt_lags = np.zeros((len(full_rvt), len(lags)))
67+
for ind, lag in enumerate(lags):
68+
start_index = np.argmin(np.abs(time - lag))
69+
temp_rvt = np.concatenate(
70+
(
71+
np.full((start_index), full_rvt[0]),
72+
full_rvt[: len(full_rvt) - start_index],
73+
)
74+
)
75+
rvt_lags[:, ind] = temp_rvt
76+
77+
return rvt_lags
78+
79+
1780
@due.dcite(references.POWER_2018)
1881
def rpv(resp, window=6):
1982
"""Calculate respiratory pattern variability.

phys2denoise/tests/conftest.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import numpy as np
2+
import pytest
3+
4+
5+
@pytest.fixture(scope="module")
6+
def fake_phys():
7+
f = 0.3
8+
fs = 62.5 # sampling rate
9+
t = 300
10+
samples = np.arange(t * fs) / fs
11+
noise = np.random.normal(0, 0.5, len(samples))
12+
fake_phys = 10 * np.sin(2 * np.pi * f * samples) + noise
13+
return fake_phys
14+

phys2denoise/tests/test_rvt.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import peakdet
2+
from phys2denoise.metrics.chest_belt import rvt
3+
4+
5+
def test_peakdet(fake_phys):
6+
phys = peakdet.Physio(fake_phys, fs=62.5)
7+
phys = peakdet.operations.filter_physio(phys, cutoffs=3, method="lowpass")
8+
phys = peakdet.operations.peakfind_physio(phys)
9+
assert phys.troughs is not None
10+
assert phys.peaks is not None
11+
12+
13+
def test_rvt(fake_phys):
14+
phys = peakdet.Physio(fake_phys, fs=62.5)
15+
phys = peakdet.operations.filter_physio(phys, cutoffs=3, method="lowpass")
16+
phys = peakdet.operations.peakfind_physio(phys)
17+
r = rvt(phys.data, phys.peaks, phys.troughs, samplerate=phys.fs)
18+
assert r is not None
19+
assert len(r) == 18750

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ test =
4949
%(style)s
5050
pytest >=5.3
5151
pytest-cov
52+
peakdet
5253
coverage
5354
devtools =
5455
pre-commit

0 commit comments

Comments
 (0)