Skip to content

Commit dc60504

Browse files
committed
Clean code, fix pydocstrings, add coefficient of variation, add utility to check signal input object type
1 parent 6910304 commit dc60504

File tree

2 files changed

+69
-47
lines changed

2 files changed

+69
-47
lines changed

physioqc/metrics/multimodal.py

Lines changed: 49 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
"""These functions compute RETROICOR regressors (Glover et al. 2000)."""
2-
# import file
3-
from typing import List
4-
1+
"""These functions compute various non-modality dependent signal processing metrics."""
52
import numpy as np
63
import peakdet as pk
74

8-
from .. import references
9-
from ..due import due
5+
from .utils import physio_or_numpy
106

117

128
def std(signal):
@@ -15,62 +11,74 @@ def std(signal):
1511
1612
Parameters
1713
----------
18-
std : function
19-
Calculate standard deviation across input channels.
20-
args : signal (X, n) :obj:`numpy.ndarray`
21-
ND array with signal of some human biometric data, hopefully from a living human.
22-
signal, of shape (n_channels, )
14+
signal : np.array
15+
Physiological data
2316
2417
Returns
2518
-------
2619
N-sized array :obj:`numpy.ndarray`
2720
Standard deviation of signal.
2821
"""
22+
signal = physio_or_numpy(signal)
2923
std_val = np.std(signal, axis=0)
3024
return std_val
3125

3226

27+
def mean(signal: np.array):
28+
"""
29+
Calculate mean across input channels of signal.
30+
31+
Parameters
32+
----------
33+
signal : np.array
34+
Physiological data
35+
36+
Returns
37+
-------
38+
N-sized array :obj:`numpy.ndarray`
39+
Mean of signal.
40+
"""
41+
signal = physio_or_numpy(signal)
42+
mean_val = np.mean(signal, axis=0)
43+
return mean_val
44+
45+
3346
def tSNR(signal):
3447
"""
35-
Calculate temporal signal to noise ration of signal.
48+
Calculate temporal signal to noise ratio of signal.
3649
3750
Parameters
3851
----------
39-
tSNR : function
40-
Calculate temporal signal to noise ratio.
41-
args : signal
42-
ND array with signal of some human biometric data, hopefully from a living human.
52+
signal : np.array
53+
Physiological data
4354
4455
Returns
4556
-------
4657
N-sized array :obj:`numpy.ndarray`
4758
Temporal signal to noise ratio of signal.
4859
"""
49-
me = np.mean(signal, axis=0)
50-
std = np.std(signal, axis=0)
51-
tSNR_val = me / std
60+
signal = physio_or_numpy(signal)
61+
tSNR_val = np.mean(signal, axis=0) / np.std(signal, axis=0)
5262
return tSNR_val
5363

5464

55-
def mean(signal: np.array):
65+
def CoV(signal):
5666
"""
57-
Calculate mean across input channels of signal.
67+
Calculate coefficient of variation of signal.
5868
5969
Parameters
6070
----------
61-
mean : function
62-
Calculate mean over input channels.
63-
args : signal (X, n) :obj:`numpy.ndarray`
64-
ND array with signal of some human biometric data, hopefully from a living human.
65-
signal, of shape (n_channels, )
71+
signal : np.array
72+
Physiological data
6673
6774
Returns
6875
-------
6976
N-sized array :obj:`numpy.ndarray`
70-
Mean of signal.
77+
Temporal signal to noise ratio of signal.
7178
"""
72-
mean_val = np.mean(signal, axis=0)
73-
return mean_val
79+
signal = physio_or_numpy(signal)
80+
tSNR_val = np.std(signal, axis=0) / np.mean(signal, axis=0)
81+
return tSNR_val
7482

7583

7684
def min(signal: np.array):
@@ -79,17 +87,15 @@ def min(signal: np.array):
7987
8088
Parameters
8189
----------
82-
min : function
83-
Calculate min over input channels.
84-
args : signal (X, n) :obj:`numpy.ndarray`
85-
ND array with signal of some human biometric data, hopefully from a living human.
86-
signal, of shape (n_channels, )
90+
signal : np.array
91+
Physiological data
8792
8893
Returns
8994
-------
9095
N-sized array :obj:`numpy.ndarray`
9196
min of signal.
9297
"""
98+
signal = physio_or_numpy(signal)
9399
min_val = np.min(signal, axis=0)
94100
return min_val
95101

@@ -100,23 +106,21 @@ def max(signal: np.array):
100106
101107
Parameters
102108
----------
103-
max : function
104-
Calculate max over input channels.
105-
args : signal (X, n) :obj:`numpy.ndarray`
106-
ND array with signal of some human biometric data, hopefully from a living human.
107-
signal, of shape (n_channels, )
109+
signal : np.array
110+
Physiological data
108111
109112
Returns
110113
-------
111114
N-sized array :obj:`numpy.ndarray`
112115
max of signal.
113116
"""
117+
signal = physio_or_numpy(signal)
114118
max_val = np.max(signal, axis=0)
115119
return max_val
116120

117121

118122
def iqr(signal: np.array, q_high: float = 75, q_low: float = 25):
119-
"""Calculates the Inter Quantile Range (IQR) over the input signal.
123+
"""Calculate the Inter Quantile Range (IQR) over the input signal.
120124
121125
Parameters
122126
----------
@@ -132,14 +136,15 @@ def iqr(signal: np.array, q_high: float = 75, q_low: float = 25):
132136
np.array
133137
iqr of the signal
134138
"""
139+
signal = physio_or_numpy(signal)
135140
p_high, p_low = np.percentile(signal, [q_high, q_low], axis=0)
136141
iqr_val = p_high - p_low
137142

138143
return iqr_val
139144

140145

141146
def percentile(signal: np.array, perc: float = 2):
142-
"""Calculates the percentile perc over the signal.
147+
"""Calculate the percentile perc over the signal.
143148
144149
Parameters
145150
----------
@@ -153,6 +158,7 @@ def percentile(signal: np.array, perc: float = 2):
153158
np.array
154159
percentile of the signal
155160
"""
161+
signal = physio_or_numpy(signal)
156162
perc_val = np.percentile(signal, axis=0, q=perc)
157163

158164
return perc_val
@@ -186,7 +192,7 @@ def peak_detection(
186192

187193

188194
def peak_distance(ph: pk.Physio):
189-
"""Calculates the time between peaks (first derivative of onsets).
195+
"""Calculate the time between peaks (first derivative of onsets).
190196
191197
Parameters
192198
----------
@@ -198,15 +204,14 @@ def peak_distance(ph: pk.Physio):
198204
np.array
199205
np.array of shape [npeaks, ]
200206
"""
201-
202207
# TODO Check if peaks have been estimated.
203208
diff_peak = np.diff(ph.peaks, axis=0)
204209

205210
return diff_peak
206211

207212

208213
def peak_amplitude(ph: pk.Physio):
209-
"""Returns the amplitude for each peak in the ph.Physio object (peak - trough).
214+
"""Return the amplitude for each peak in the ph.Physio object (peak - trough).
210215
211216
Parameters
212217
----------
@@ -218,7 +223,6 @@ def peak_amplitude(ph: pk.Physio):
218223
np.array
219224
np.array of shape [npeaks - 1, ]
220225
"""
221-
222226
# TODO Check if peaks have been estimated.
223227
# Assuming that peaks and troughs are aligned. Last peak has no trough.
224228
peak_amp = ph.data[ph.peaks[:-1]]

physioqc/metrics/utils.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
"""Miscellaneous utility functions for metric calculation."""
22
import logging
33

4-
import numpy as np
5-
64
LGR = logging.getLogger(__name__)
75
LGR.setLevel(logging.INFO)
86

@@ -31,3 +29,23 @@ def print_metric_call(metric, args):
3129
msg = f"{msg}\n"
3230

3331
LGR.info(msg)
32+
33+
34+
def physio_or_numpy(signal):
35+
"""
36+
Return data from a peakdet.physio.Physio object or a np.ndarray-like object.
37+
38+
Parameters
39+
----------
40+
data : peakdet.physio.Physio, np.ndarray, or list
41+
object to get data from
42+
43+
Returns
44+
-------
45+
np.ndarray-like object
46+
Either a np.ndarray or a list
47+
"""
48+
if hasattr(signal, "history"):
49+
signal = signal.data
50+
51+
return signal

0 commit comments

Comments
 (0)