ap_features package#
Submodules#
ap_features.average module#
- class ap_features.average.Average(y, x, ys, xs)#
Bases:
tuple
- x#
Alias for field number 1
- xs#
Alias for field number 3
- y#
Alias for field number 0
- ys#
Alias for field number 2
- ap_features.average.average_and_interpolate(ys: Sequence[ndarray | List[float] | Sequence[float]], xs: Sequence[ndarray | List[float] | Sequence[float]] | None = None, N: int = 200) Average [source]#
Get the average of list of signals assuming that they align at the same x value
- Parameters:
ys (Array) – The signal values
xs (Array) – The x-values
N (int) – Length of output array (Default: 200)
- Returns:
Y_avg (array) – The average y values
X (array) – The new x-values
- ap_features.average.clean_data(ys: Sequence[ndarray | List[float] | Sequence[float]], xs: Sequence[ndarray | List[float] | Sequence[float]] | None) Tuple[Sequence[ndarray | List[float] | Sequence[float]], Sequence[ndarray | List[float] | Sequence[float]]] [source]#
Make sure xs and ys have the correct shapes and remove empty sub-signals
- Parameters:
ys (Sequence[Array]) – First list
xs (Optional[Sequence[Array]]) – Second list
- Returns:
(ys, xs) - cleaned version
- Return type:
Tuple[Sequence[Array], Sequence[Array]]
Note
The order you send in the array will be the same as the order it is returned. Apart from this fact, the order doesn’t matter.
- Raises:
InvalidSubSignalError – If the length of xs and ys don’t agree
InvalidSubSignalError – If the length of one of the sub-signals of xs and ys don’t agree.
- ap_features.average.create_longest_time_array(xs: Sequence[ndarray | List[float] | Sequence[float]], N: int) ndarray [source]#
Given a list of sub-signals create a new array of length N that cover all values
- Parameters:
xs (Sequence[Array]) – List of monotonic sub sub-signal
N (int) – Size of output array
- Returns:
Array that cover all values of length N
- Return type:
np.ndarray
- ap_features.average.interpolate(X: ndarray | List[float] | Sequence[float], x: ndarray | List[float] | Sequence[float], y: ndarray | List[float] | Sequence[float]) ndarray [source]#
Interpolate array
- Parameters:
X (Array) – x-coordinates at which to evaluate the interpolated values
x (Array) – x-coordinates of the data points
y (Array) – y-coordinates of the data points
- Returns:
Interpolated y-coordinates
- Return type:
np.ndarray
Note
This function will try to perform spline interpolation using scipy.interpolate.UnivariateSpline and fall back to numpy.interp in case that doesn’t work
ap_features.background module#
- class ap_features.background.Background(x, y, y_filt, corrected, background, F0, method)[source]#
Bases:
NamedTuple
- F0: float#
Alias for field number 5
- background: ndarray | List[float] | Sequence[float]#
Alias for field number 4
- corrected: ndarray | List[float] | Sequence[float]#
Alias for field number 3
- method: BackgroundCorrection#
Alias for field number 6
- x: ndarray | List[float] | Sequence[float]#
Alias for field number 0
- y: ndarray | List[float] | Sequence[float]#
Alias for field number 1
- y_filt: ndarray | List[float] | Sequence[float]#
Alias for field number 2
- class ap_features.background.BackgroundCorrection(value)[source]#
Bases:
str
,Enum
An enumeration.
- full = 'full'#
- none = 'none'#
- subtract = 'subtract'#
- class ap_features.background.BackgroundCostFunction(value)[source]#
Bases:
str
,Enum
An enumeration.
- ah = 'ah'#
- atq = 'atq'#
- sh = 'sh'#
- stq = 'stq'#
- ap_features.background.background(x: ndarray | List[float] | Sequence[float], y: ndarray | List[float] | Sequence[float], order: int = 2, threshold: float = 0.01, cost_function: BackgroundCostFunction = BackgroundCostFunction.atq, **kwargs) ndarray [source]#
Compute an estimation of the background (aka baseline) in chemical spectra. The background is estimated by a polynomial with order using a cost-function and a threshold parameter. This is a re-implementation of a MATLAB script that can be found here
- Parameters:
x (Array) – Time stamps
y (Array) – Signal
order (int, optional) – Polynomial order, by default 2
threshold (float, optional) – The threshold parameters, by default 0.01
cost_function (BackgroundCostFunction, optional) – Cost function to be minimized, by default BackgroundCostFunction.atq. The cost functions can have the following forms:
- Returns:
The estimated baseline
- Return type:
np.ndarray
Notes
The cost function can have the four following values:
sh - symmetric Huber function :
\[\begin{split}f(x) = \begin{cases} x^2, \; \text{ if } |x| < \text{threshold} \\ 2 \text{threshold} |x|-\text{threshold}^2, \; \text{otherwise} \end{cases}\end{split}\]ah - asymmetric Huber function :
\[\begin{split}f(x) = \begin{cases} x^2, \; \text{ if } x < \text{threshold} \\ 2 \text{threshold} x-\text{threshold}^2 , \; \text{otherwise} \end{cases}\end{split}\]stq - symmetric truncated quadratic :
\[\begin{split}f(x) = \begin{cases} x^2, \; \text{ if } |x| < \text{threshold} \\ \text{threshold}^2 , \; \text{otherwise} \end{cases}\end{split}\]atq - asymmetric truncated quadratic :
\[\begin{split}f(x) = \begin{cases} x^2, \; \text{ if } x < \text{threshold} \\ \text{threshold}^2 , \; \text{otherwise} \end{cases}\end{split}\]
References
[1] Mazet, V., Carteret, C., Brie, D., Idier, J. and Humbert, B., 2005. Background removal from spectra by designing and minimising a non-quadratic cost function. Chemometrics and intelligent laboratory systems, 76(2), pp.121-133.
- ap_features.background.correct_background(x: ndarray | List[float] | Sequence[float], y: ndarray | List[float] | Sequence[float], method: BackgroundCorrection, filter_kernel_size: int = 0, force_positive: bool = False, **kwargs) Background [source]#
- ap_features.background.full_background_correction(x: ndarray | List[float] | Sequence[float], y: ndarray | List[float] | Sequence[float], filter_kernel_size=0, **kwargs) Background [source]#
Perform at background correction. First estimate background \(b\), and let \(F_0 = b(0)\). The corrected background is then \(\frac{y - b}{F_0}\). Additional argument can be passed to background corrected algorithm as keyword arguments.
- Parameters:
x (Array) – Time points
y (Array) – Fluorescence amplitude
- Returns:
Namedtuple containing the corrected trace and the background.
- Return type:
ap_features.beat module#
- class ap_features.beat.Beat(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], pacing: ndarray | List[float] | Sequence[float] | None = None, y_rest: float | None = None, y_max: float | None = None, parent: Beats | None = None, backend: Backend = Backend.numba, beat_number: int | None = None)[source]#
Bases:
Trace
- apd(factor: float, use_spline: bool = True) float [source]#
The action potential duration
- Parameters:
factor (int) – Integer between 0 and 100
use_spline (bool, optional) – Use spline interpolation, by default True.
- Returns:
action potential duration
- Return type:
float
- apd_point(factor: float, use_spline: bool = True, strategy: APDPointStrategy = APDPointStrategy.big_diff_plus_one) Tuple[float, float] [source]#
Return the first and second intersection of the APD p line
- Parameters:
factor (int) – The APD
use_spline (bool, optional) – Use spline interpolation or not, by default True
- Returns:
Two points corresponding to the first and second intersection of the APD p line
- Return type:
Tuple[float, float]
- apd_points(factor: float, use_spline: bool = True) List[float] [source]#
Return all intersections of the APD p line
- Parameters:
factor (int) – The APD
use_spline (bool, optional) – Use spline interpolation or not, by default True
- Returns:
Two points corresponding to the first and second intersection of the APD p line
- Return type:
List[float]
- apd_up_xy(low, high)[source]#
Find the duration between first intersection (i.e during the upstroke) of two APD lines
- Parameters:
low (int) – First APD line (value between 0 and 100)
high (int) – Second APD line (value between 0 and 100)
- Returns:
The time between low to high
- Return type:
float
- capd(factor: float, beat_rate: float | None = None, formula: str = 'friderica', use_spline: bool = True, use_median_beat_rate: bool = False) float [source]#
Correct the given APD (or any QT measurement) for the beat rate. normally the faster the HR (or the shorter the RR interval), the shorter the QT interval, and vice versa
- Parameters:
factor (int) – Integer between 0 and 100
beat_rate (float) – The beat rate (number of beats per minute)
formula (str, optional) – Formula for computing th corrected APD, either ‘friderica’ or ‘bazett’, by default ‘friderica’,
- Returns:
The corrected APD
- Return type:
float
Notes
Friderica formula (default):
\[APD (RR)^{-1/3}\]Bazett formula:
\[APD (RR)^{-1/2}\]where \(RR\) is the R-R interval in an ECG. For an action potential this would be equivalent to the inverse of the beating frequency (or 60 divided by the beat rate)
Luo, Shen, et al. “A comparison of commonly used QT correction formulae: the effect of heart rate on the QTc of normal ECGs.” Journal of electrocardiology 37 (2004): 81-90.
- property cost_terms#
- detect_ead(sigma: float = 1, prominence_level: float = 0.07) Tuple[bool, int | None] [source]#
Detect (Early after depolarizations) EADs based on peak prominence.
- Parameters:
y (Array) – The signal that you want to detect EADs
sigma (float) – Standard deviation in the gaussian smoothing kernel Default: 1.0
prominence_level (float) – How prominent a peak should be in order to be characterized as an EAD. This value should be between 0 and 1, with a greater value being more prominent. Default: 0.07
- Returns:
bool – Flag indicating if an EAD is found or not
int or None – Index where we found the EAD. If no EAD is found then this will be None. I more than one peaks are found then only the first will be returned.
- integrate_apd(factor: float, use_spline: bool = True, normalize: bool = False) float [source]#
Compute the integral of the signals above the APD p line
- Parameters:
factor (float) – Which APD line
use_spline (bool, optional) – Use spline interpolation, by default True
normalize (bool, optional) – If true normalize signal first, so that max value is 1.0, and min value is zero before performing the computation, by default False
- Returns:
Integral above the APD p line
- Return type:
float
- maximum_relative_upstroke_velocity(upstroke_duration: int = 50, sigmoid_fit: bool = True)[source]#
Estimate maximum relative upstroke velocity
- Parameters:
upstroke_duration (int) – Duration in milliseconds of upstroke (Default: 50). This does not have to be exact up should at least be longer than the upstroke.
sigmoid_fit (bool) – If True then use a sigmoid function to fit the data of the upstroke and report the maximum derivate of the sigmoid as the maximum upstroke.
- maximum_upstroke_velocity(use_spline: bool = True, normalize: bool = False) float [source]#
Compute maximum upstroke velocity
- Parameters:
use_spline (bool, optional) – Use spline interpolation, by default True
normalize (bool, optional) – If true normalize signal first, so that max value is 1.0, and min value is zero before performing the computation, by default False
- Returns:
The maximum upstroke velocity
- Return type:
float
- property parent: Beats | None#
If the beat comes from several Beats object then this will return those Beats
- Returns:
The parent Beats
- Return type:
- peaks(prominence_level: float = 0.1) List[int] [source]#
Return the list of peak indices given a prominence level
- tau(a: float) float [source]#
Decay time. Time for the signal amplitude to go from maximum to (1 - a) * 100 % of maximum
- Parameters:
a (float) – The value for which you want to estimate the time decay
- Returns:
Decay time
- Return type:
float
- time_above_apd_line(factor: float) float [source]#
Compute the amount of time spent above APD p line
- triangulation(low: int = 30, high: int = 80, use_spline: bool = True) float [source]#
Compute the triangulation which is the last intersection of the \(\mathrm{APD} \; p_{\mathrm{high}}\) line minus the last intersection of the \(\mathrm{APD} \; p_{\mathrm{low}}\) line
- Parameters:
low (int, optional) – Lower APD value, by default 30
high (int, optional) – Higher APD value, by default 80
use_spline (bool, optional) – Use spline interpolation, by default True.
- Returns:
The triangulations
- Return type:
float
- ttp(use_pacing: bool = True) float [source]#
Computed the time to peak from pacing is triggered to maximum amplitude. Note, if pacing is not provided it will compute the time from the beginning of the trace (which might not be consistent) to the peak.
- Parameters:
use_pacing (bool, optional) – If pacing is available compute time to peak from start of packing, by default True
- Returns:
Time to peak
- Return type:
float
- upstroke(a: float) float [source]#
Compute the time from (1-a)*100 % signal amplitude to peak. For example if if a = 0.8 if will compute the time from the starting value of APD80 to the upstroke.
- Parameters:
a (float) – Fraction of signal amplitude
- Returns:
The upstroke value
- Return type:
float
- property y_max: float | None#
Return maximum value if specified, otherwise None
- property y_normalized: ndarray#
Return normalized signal
- property y_rest: float | None#
Return resting value if specified, otherwise None
- class ap_features.beat.BeatCollection(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], pacing: ndarray | List[float] | Sequence[float] | None = None, mask: ndarray | List[float] | Sequence[float] | None = None, parent: BeatSeriesCollection | None = None, backend: Backend = Backend.numba)[source]#
Bases:
Trace
- property num_traces#
- property parent: BeatSeriesCollection | None#
If the beat comes from a BeatSeries object then this will return that BeatSeries
- Returns:
The parent BeatSeries
- Return type:
BeatSeries
- class ap_features.beat.BeatSeriesCollection(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float] | None, pacing: ndarray | List[float] | Sequence[float] | None = None, backend: Backend = Backend.numba)[source]#
Bases:
Trace
- property num_beats: List[int]#
- class ap_features.beat.Beats(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], pacing: ndarray | List[float] | Sequence[float] | None = None, background_correction_method: BackgroundCorrection = BackgroundCorrection.none, zero_index: int | None = None, background_correction_kernel: int = 0, backend: Backend = Backend.numba, intervals: List[Interval] | None = None, chopping_options: Dict[str, float] | None = None, force_positive: bool = False)[source]#
Bases:
Trace
- average_beat(filters: Sequence[Filters] | None = None, N: int = 200, x: float = 1.0, apd_point: float = 50) Beat [source]#
Compute an average beat based on aligning the individual beats
- Parameters:
filters (Optional[Sequence[_filters.Filters]], optional) – A list of filters that should be used to decide which beats that should be included in the averaging, by default None
N (int, optional) – Length of output signal, by default 200. Note that the output signal will be interpolated so that it has this length. This is done because the different beats might have different lengths.
x (float, optional) – The number of standard deviations used in the filtering, by default 1.0
- Returns:
An average beat.
- Return type:
- property background: ndarray#
- property beat_rate: float#
The beat rate, i.e number of beats per minute, which is simply 60 divided by the beating frequency
- property beat_rates: List[float]#
Beat rate for all beats
- Returns:
List of beat rates
- Return type:
List[float]
- property beating_frequencies: Sequence[float]#
Get the frequency for each beat
- Returns:
List of frequencies
- Return type:
List[float]
- property beating_frequency: float#
The median frequency of all beats
- property beats: List[Beat]#
Chop signal into individual beats. You can also pass in any options that should be provided to the chopping algorithm.
- Returns:
A list of chopped beats
- Return type:
List[Beat]
- chop_data(threshold_factor=0.5, min_window=50, max_window=5000, N=None, extend_front=None, extend_end=None, ignore_pacing=False, intervals=None)[source]#
- property chopped_data: ChoppedData#
- correct_background(background_correction_method: BackgroundCorrection, copy: bool = True) Beats [source]#
- filter_beats(filters: Sequence[Filters], x: float = 1.0) List[Beat] [source]#
Get a subset of the chopped beats based on similarities in different features.
- Parameters:
filters (Sequence[_filters.Filters]) – A list of filters that should be used for filtering
x (float, optional) – How many standard deviations away from the mean the different beats should be to be included, by default 1.0
- Returns:
A list of filtered beats
- Return type:
List[Beat]
- property num_beats: int#
- property original_y: ndarray#
- property y: ndarray#
The trace
- class ap_features.beat.State(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float] | None, pacing: ndarray | List[float] | Sequence[float] | None = None, backend: Backend = Backend.numba)[source]#
Bases:
Trace
- property cost_terms#
- property num_states#
- class ap_features.beat.StateCollection(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], pacing: ndarray | List[float] | Sequence[float] | None = None, mask: ndarray | List[float] | Sequence[float] | None = None, parent: StateSeriesCollection | None = None)[source]#
Bases:
Trace
- property cost_terms#
- property mask: ndarray | List[float] | Sequence[float] | None#
- property num_states#
- property num_traces#
- property parent: StateSeriesCollection | None#
If the beat comes from a BeatSeries object then this will return that BeatSeries
- Returns:
The parent BeatSeries
- Return type:
BeatSeries
- class ap_features.beat.StateSeriesCollection(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float] | None, pacing: ndarray | List[float] | Sequence[float] | None = None, backend: Backend = Backend.numba)[source]#
Bases:
Trace
- property num_beats: List[int]#
- class ap_features.beat.Trace(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float] | None, pacing: ndarray | List[float] | Sequence[float] | None = None, backend: Backend = Backend.numba)[source]#
Bases:
object
- as_spline(k: int = 3, s: int | None = None) UnivariateSpline [source]#
Convert trace to spline
- Parameters:
k (int, optional) – Degree of the smoothing spline. Must be 1 <= k <= 5. Default is k = 3, a cubic spline, by default 3.
s (float or None, optional) – Positive smoothing factor used to choose the number of knots. If 0, spline will interpolate through all data points, by default 0
- Returns:
A spline representation of the trace
- Return type:
UnivariateSpline
- property duration: float#
The duration of the trace, i.e last time point minus the first
- ensure_time_unit(unit: str) None [source]#
Convert time to milliseconds or seconds
- Parameters:
unit (str) – A string with ‘ms’ or ‘s’
- property pacing: ndarray#
Array of pacing amplitudes. If no pacing info is available, then this will be an array of zeros with same length as the trace
- plot(fname: str = '', include_pacing: bool = False, include_background: bool = False, ylabel: str = '')[source]#
Plot the trace with matplotlib
- Parameters:
fname (str, optional) – Name of the figure to be saved. If not provided the figure will note be saved, but you can show by calling plt.show
include_pacing (bool, optional) – Whether to include pacing in the plot, by default False
include_background (bool, optional) – Whether to include the background, by default False
ylabel (str, optional) – Label on the y-axis, by default “”
- Returns:
If matplotlib is installed it will return a tuple containing the figure and the axes.
- Return type:
Tuple[plt.Figure, plt.Axes] | None
- slice(start: float, end: float, copy: bool = True) Trace [source]#
Create a slice of the original trace
- Parameters:
start (float) – Start time of slice
end (float) – End time of slice
copy (bool, optional) – If true create a copy of the original array otherwise return a slice of the original array, by default True
- Returns:
A sliced trace
- Return type:
- property t: ndarray#
The time stamps
- property time_unit: str#
The time unit ‘ms’ or ‘s’
- property y: ndarray#
The trace
- ap_features.beat.align_beats(beats: List[Beat], apd_point=50, N=200, parent=None, strategy: APDPointStrategy = APDPointStrategy.big_diff_plus_one)[source]#
- ap_features.beat.apd_slope(beats: List[Beat], factor: float, corrected_apd: bool = False) Tuple[float, float] [source]#
Compute a linear interpolation of the apd values for each beat. This is useful in order to see if there is a correlation between the APD values and the beat number. If the resulting the slope is relatively close to zero there is no such dependency.
- Parameters:
beats (List[Beat]) – List of beats
factor (float) – The apd value
corrected_apd (bool, optional) – Whether to use corrected or regular apd, by default False
- Returns:
A tuple with the (constant, slope) for the linear interpolation. The slope here can be interpreted as the change in APD per minute.
- Return type:
Tuple[float, float]
- ap_features.beat.average_beat(beats: List[Beat], N: int = 200, filters: Sequence[Filters] | None = None, x: float = 1.0, apd_point: float = 50) Beat [source]#
- ap_features.beat.chopped_data_to_beats(chopped_data: ChoppedData, parent: Beats | None = None) List[Beat] [source]#
Convert a ChoppedData object to a list of Beats
- Parameters:
chopped_data (chopping.ChoppedData) – The chopped data
parent (Optional[Beats], optional) – Parent trace, by default None
- Returns:
List of Beats
- Return type:
List[Beat]
- ap_features.beat.filter_beats(beats: List[Beat], filters: Sequence[Filters], x: float = 1.0) List[Beat] [source]#
Filter beats based of similarities of the filters
- Parameters:
beats (List[Beat]) – List of beats
filters (Sequence[_filters.Filters]) – List of filters
x (float, optional) – How many standard deviations away from the mean the different beats should be to be included, by default 1.0
- Returns:
A list of filtered beats
- Return type:
List[Beat]
- Raises:
_filters.InvalidFilter – If a filter in the list of filters is not valid.
ap_features.chopping module#
- class ap_features.chopping.ChoppedData(data, times, pacing, parameters, intervals, upstroke_times)#
Bases:
tuple
- data#
Alias for field number 0
- intervals#
Alias for field number 4
- pacing#
Alias for field number 2
- parameters#
Alias for field number 3
- times#
Alias for field number 1
- upstroke_times#
Alias for field number 5
- class ap_features.chopping.Interval(start, end)#
Bases:
tuple
- end#
Alias for field number 1
- start#
Alias for field number 0
- ap_features.chopping.check_intervals(intervals: List[Interval]) None [source]#
Check starts and ends and make sure that they are consistent
- Parameters:
starts (Array) – List of start points
ends (Array) – List of end points
- Returns:
starts, ends
- Return type:
Tuple[Array, Array]
- Raises:
EmptyChoppingError – If number of starts or ends become zero.
InvalidChoppingError – If number of starts and ends does not add up.
- ap_features.chopping.chop_data(data: ndarray | List[float] | Sequence[float], time: ndarray | List[float] | Sequence[float], **kwargs) ChoppedData [source]#
Chop data into individual beats
- Parameters:
data (Array) – The signal amplitude
time (Array) – Time stamps
- Returns:
Data chopped into individual beats
- Return type:
- ap_features.chopping.chop_data_with_pacing(data: ndarray | List[float] | Sequence[float], time: ndarray | List[float] | Sequence[float], pacing: ndarray | List[float] | Sequence[float], extend_front: float = 0, extend_end: float = 0, min_window: float = 300, max_window: float = 2000, intervals: List[Interval] | None = None, **kwargs) ChoppedData [source]#
Chop data based on pacing
- Parameters:
data (Array) – The data to be chopped
time (Array) – The time stamps for the data
pacing (Array) – The pacing amplitude
extend_front (float) – Extend the start of each sub-signal this many milliseconds before the threshold is detected. Default: 0 ms
extend_end (float) – Extend the end of each sub-signal this many milliseconds. Default 0 ms.
min_window (float) – Minimum size of chopped signal
max_window (float) – Minimum size of chopped signal
- Returns:
Named tuple with the chopped data
- Return type:
Notes
We first find where the pacing for each beat starts by finding the indices where the pacing amplitude goes form zero to something positive. Then we iterate over these indices and let the start of each beat be the start of the pacing (minus extend_front, which has a default value of zero) and the end will be the time of the beginning of the next beat (plus extend_end which is also has as default value of zero).
- ap_features.chopping.chop_data_without_pacing(data: ndarray | List[float] | Sequence[float], time: ndarray | List[float] | Sequence[float], threshold_factor: float = 0.5, min_window: float = 50, max_window: float = 5000, N: int | None = None, extend_front: float | None = None, extend_end: float | None = None, intervals: List[Interval] | None = None, **kwargs) ChoppedData [source]#
Chop data into beats
- Parameters:
data (list or array) – The data that you want to chop
time (list or array) – The time points. If none is provided time will be just the indices.
threshold_factor (float) – Thresholds for where the signal should be chopped (Default: 0.3)
extend_front (scalar) – Extend the start of each sub-signal this many milliseconds before the threshold is detected. Default: 300 ms
extend_end (scalar) – Extend the end of each sub-signal this many milliseconds. Default 60 ms.
min_window (scalar) – Length of minimum window
max_window (scalar) – Length of maximum window
N (int) – Length of output signals
- Returns:
The chopped data
- Return type:
Notes
The signals extracted from the MPS data consist of data from several beats, and in order to e.g compute properties from an average beat, we need a way to chop the signal into different beats. Suppose we have the signal \(y(t), t \in [0, T]\), where we assume that filtering and background correction have already been applied. Suppose we have \(N\) sub-signals, \(z_1, z_2, \cdots, z_N\), each representing one beat. Let \(\tau_i = [\tau_i^0, \tau_i^1], i = 1, \cdots N\) be non-empty intervals corresponding to the support of each sub-signal ( \(\tau_i = \{ t \in [0,T]: z_i(t) \neq 0 \}\)), with \(\tau_i^j < \tau_{i+1}^j \forall i\) and \(\bigcup_{i=1}^N \tau_i = [0, T]\). Note that the intersection :math:` tau_i cap tau_{i+1}` can be non-empty. The aim is now to find good candidates for \(\tau_i^j , i = 1 \cdots N, j = 0,1\). We have two different scenarios, namely with or without pacing information.
If pacing information is available we can e.g set \(\tau_i^0\) to be 30 ms before each stimulus is applied and \(\tau_i^1\) to be 60 ms before the next stimulus is applied.
If pacing information is not available then we need to estimate the beginning and end of each interval. We proceed as follows:
Choose some threshold value \(\eta\) (default \(\eta = 0.5\)), and compute \(y_{\eta}\)
Let \(h = y - y_{\eta}\), and define the set
\[\mathcal{T}_0 = \{ t : h(t) = 0 \}\]Sort the elements of \(\mathcal{T}_0\) in increasing order, i.e \(\mathcal{T}_0 = (t_1, t_2, \cdots, t_M)\), with \(t_i < t_{i+1}\).
Select a minimum duration of a beat \(\nu\) (default \(\nu = 50\) ms) and define the set
\[\mathcal{T}_1 = \{t_i \in \mathcal{T}_0 : t_{i+1} - t_i > \eta \}\]to be be the subset of \(\mathcal{T}_0\) where the difference between to subsequent time stamps are greater than \(\eta\).
Let \(\delta > 0\) (default \(\delta\) = 0.1 ms), and set
\[\begin{split}\{\tilde{\tau_1}^0, \tilde{\tau_2}^0, \cdots,\tilde{\tau_N}^0\} := \{ t \in \mathcal{T}_1 : h(t + \delta) > 0 \} \\ \{\tilde{\tau_1}^1, \tilde{\tau_2}^1, \cdots,\tilde{\tau_N}^1\} := \{ t \in \mathcal{T}_1 : h(t + \delta) < 0 \} \\\end{split}\]Note that we need to also make sure that all beats have a start and an end.
Extend each sub-signal at the beginning and end, i,e if \(a,b \geq 0\), define
\[\begin{split}\tau_i^0 = \tilde{\tau_i}^0 - a \\ \tau_i^1 = \tilde{\tau_i}^1 + b\end{split}\]
- ap_features.chopping.chop_intervals(data: ndarray | List[float] | Sequence[float], time: ndarray | List[float] | Sequence[float], intervals: List[Interval], pacing: ndarray | List[float] | Sequence[float] | None = None, N: int | None = None, max_window: float = 2000, min_window: float = 50) Tuple[List[ndarray | List[float] | Sequence[float]], List[ndarray | List[float] | Sequence[float]], List[ndarray | List[float] | Sequence[float]]] [source]#
Chop the data based on starts and ends
- Parameters:
data (Array) – The signal amplitude
time (Array) – The time stamps
intervals (List[Interval]) – List of intervals with start and ends
pacing (Optional[Array], optional) – Pacing amplitude, by default None
N (Optional[int], optional) – Number of points in each chopped signal, by default None. If this is different from None then each signal will be interpolated so that it has N points
max_window (float, optional) – Maximum allowed size of a chopped signal, by default 2000
min_window (float, optional) – Minimum allowed size of a chopped signal, by default 50
- Returns:
Chopped data, times, pacing
- Return type:
Tuple[List[Array], List[Array], List[Array]]
- ap_features.chopping.create_intervals(starts: ndarray | List[float] | Sequence[float], ends: ndarray | List[float] | Sequence[float]) List[Interval] [source]#
- ap_features.chopping.cutoff_final_interval(intervals: List[Interval], end_time: float) List[Interval] [source]#
- ap_features.chopping.filter_start_ends_in_chopping(starts: ndarray | List[float] | Sequence[float], ends: ndarray | List[float] | Sequence[float], extend_front: float | None = None, extend_end: float | None = None) List[Interval] [source]#
Adjust start and ends based on extend_front and extent_end
- Parameters:
starts (Array) – The start points
ends (Array) – The end points
extend_front (Optional[float], optional) – How much you want to extent the front. If not provided it will try to use the half distance between the minimum start and end, by default None
extend_end (Optional[float], optional) – How much you want to extend the end. If not provided it will try to use the half distance between the minimum start and end, by default None
- Returns:
List of the filtered intervals
- Return type:
List[Interval]
- Raises:
EmptyChoppingError – If number of starts or ends become zero.
InvalidChoppingError – If any of the intervals have a start value that is higher than the end value.
- ap_features.chopping.find_pacing_indices(pacing: ndarray | List[float] | Sequence[float]) ndarray [source]#
Return indices of where the pacing array changes from a low to a high values
- Parameters:
pacing (list or np.ndarray) – The array with pacing amplitude
- Returns:
List of indices where the pacing is triggered
- Return type:
np.ndarray
- ap_features.chopping.find_start_and_ends(time: ndarray | List[float] | Sequence[float], data: ndarray | List[float] | Sequence[float], threshold_factor: float, min_window: float, extend_front: float | None, extend_end: float | None) Tuple[List[Interval], ndarray | List[float] | Sequence[float]] [source]#
Find the starts and ends of a signal.
- Parameters:
time (Array) – Array of time stamps
data (Array) – Signal amplitude
threshold_factor (float) – Threshold for where to chop
min_window (float) – Length of minimum chopped signal
extend_front (Optional[float]) – How many ms the signal should be extended at the front
extend_end (Optional[float]) – How many ms the signal should be extended at the end
- Returns:
(starts, ends) for interval, and upstroke times
- Return type:
Tuple[List[Interval], Array]
- Raises:
EmptyChoppingError – If starts or ends is or become zero
- ap_features.chopping.find_start_end_index(time_stamps: ndarray | List[float] | Sequence[float], start: float, end: float) Tuple[int, int] [source]#
- ap_features.chopping.get_extend_value(extend: float | None, intervals: List[Interval], default: float) float [source]#
- ap_features.chopping.locate_chop_points(time: ndarray | List[float] | Sequence[float], data: ndarray | List[float] | Sequence[float], threshold_factor: float, min_window: float = 50, eps: float | None = None) Tuple[ndarray | List[float] | Sequence[float], ndarray | List[float] | Sequence[float], ndarray | List[float] | Sequence[float]] [source]#
Find the points where to chop
- Parameters:
time (Array) – Time stamps
data (Array) – The signal amplitude
threshold_factor (float) – The threshold for where to chop
min_window (float, optional) – Minimum allow size of signal in ms, by default 50
eps (float, optional) – Perturbation use to find the sign of the signal derivative, by default 0.1
- Returns:
starts, ends, zeros
- Return type:
Tuple[Array, Array, Array]
- ap_features.chopping.pacing_to_start_ends(time: ndarray | List[float] | Sequence[float], pacing: ndarray | List[float] | Sequence[float], extend_front: float, extend_end: float, add_final: bool = True) Tuple[List[Interval], ndarray | List[float] | Sequence[float]] [source]#
Convert an array of pacing amplitudes to start and end points
- Parameters:
time (Array) – Time stamps
pacing (Array) – Array of pacing amplitudes
extend_front (float) – How many ms you want to extend the array in front
extend_end (float) – How many ms you want to extend the array at the end
add_final (bool, optional) – Whether you want to add a final end point for the last index, by default True
- Returns:
(starts, ends) for interval, and upstroke times
- Return type:
Tuple[List[Interval], Array]
ap_features.features module#
- class ap_features.features.APDCoords(x1, x2, y1, y2, yth)#
Bases:
tuple
- x1#
Alias for field number 0
- x2#
Alias for field number 1
- y1#
Alias for field number 2
- y2#
Alias for field number 3
- yth#
Alias for field number 4
- class ap_features.features.APDPointStrategy(value)[source]#
Bases:
str
,Enum
An enumeration.
- big_diff_last = 'big_diff_last'#
- big_diff_plus_one = 'big_diff_plus_one'#
- first_last = 'first_last'#
- class ap_features.features.Upstroke(index, value, upstroke, dt, x0, sigmoid, time_APD20_to_APD80)#
Bases:
tuple
- dt#
Alias for field number 3
- index#
Alias for field number 0
- sigmoid#
Alias for field number 5
- time_APD20_to_APD80#
Alias for field number 6
- upstroke#
Alias for field number 2
- value#
Alias for field number 1
- x0#
Alias for field number 4
- ap_features.features.all_cost_terms(arr: ndarray, t: ndarray, mask: ndarray | None = None, backend: Backend = Backend.numba, normalize_time: bool = True) ndarray [source]#
- ap_features.features.apd(factor: float, V: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], v_r: float | None = None, v_max: float | None = None, use_spline: bool = True, backend: Backend = Backend.python) float [source]#
Return the action potential duration at the given factor repolarization, so that factor = 0 would be zero, and factor = 1 given the time from triggering to potential is down to resting potential.
- Parameters:
factor (int) – The APD factor between 0 and 100
V (Array) – The signal
t (Array) – The time stamps
v_r (Optional[float], optional) – The resting value, by default None. If None the minimum value is chosen
v_max (Optional[float], optional) – The maximum value, by default None. If None the maximum value is chosen
use_spline (bool, optional) – Use spline interpolation, by default True. Only applicable for python Backend.
backend (utils.Backend, optional) – Which backend to use by default Backend.python. Choices, ‘python’, ‘numba’
- Returns:
float – The action potential duration
.. Note:: – If the signal has more intersection than two with the APX_X line, then the first and second occurrence will be used.
- Raises:
ValueError – If factor is outside the range of (0, 100)
ValueError – If shape of x and y does not match
RunTimeError – In unable to compute APD
Notes
If the signal represent voltage, we would like to compute the action potential duration at a given factor of the signal. Formally, Let \(p \in (0, 100)\), and define
\[y_p = \tilde{y} - \left(1- \frac{p}{100} \right).\]Now let \(\mathcal{T}\) denote the set of solutions of \(y_p = 0\), i.e
\[y_p(t) = 0, \;\; \forall t \in \mathcal{T}\]Then there are three different scenarios; \(\mathcal{T}\) contains one, two or more than two elements. Note that \(\mathcal{T}\) cannot be empty (because of the intermediate value theorem). The only valid scenario is the case when \(\mathcal{T}\) contains two (or more) elements. In this case we define
\[\mathrm{APD} \; p = \max \mathcal{T} - \min \mathcal{T}\]for \(p < 0.5\) and
\[\mathrm{APD} \; p = \min \mathcal{T} / \min \mathcal{T} - \min \mathcal{T}\]
- ap_features.features.apd_coords(factor: float, V: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], v_r: float | None = None, v_max: float | None = None, use_spline=True) APDCoords [source]#
- Return the coordinates of the start and stop
of the APD, and not the duration itself
- Parameters:
factor (int) – The APD factor between 0 and 100.
V (Array) – The signal
t (Array) – The time stamps
v_r (Optional[float], optional) – The resting value, by default None. If None the minimum value is chosen
v_max (Optional[float], optional) – The maximum value, by default None. If None the maximum value is chosen
use_spline (bool, optional) – Use spline interpolation, by default True. Only applicable for python Backend.
- Returns:
APD coordinates
- Return type:
- ap_features.features.apd_point(factor: float, V: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], v_r: float | None = None, v_max: float | None = None, use_spline=True, strategy: APDPointStrategy = APDPointStrategy.big_diff_plus_one) Tuple[float, float] [source]#
Returns exactly two intersections of the APD p line.
- Parameters:
factor (int) – The APD line
V (np.ndarray) – The signal
t (np.ndarray) – The time stamps
v_r (Optional[float], optional) – The resting value, by default None. If None the minimum value is chosen
v_max (Optional[float], optional) – The maximum value, by default None. If None the maximum value is chosen
use_spline (bool, optional) – Use spline interpolation or not, by default True
strategy (APDPointStrategy) – Strategy for picking two apd points, either
first_last
,big_diff_plus_one
orbig_diff_last
, by defaultbig_diff_plus_one
- Returns:
Two points corresponding to the first and second intersection of the APD p line
- Return type:
Tuple[float, float]
- Raises:
RuntimeError – If spline interpolation fails
Notes
Different strategies are used based on the number of intersections. If only two intersections are used, we are done, while if there are fewer then the same value will be returned for both the start and end. If no intersections are found the value 0 will be used. If more than two intersections are found then the neighboring intersections with the largest gap will be returned.
- ap_features.features.apd_points(factor: float, V: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], v_r: float | None = None, v_max: float | None = None, use_spline: bool = True) List[float] [source]#
Returns the indices of all the intersections of the APD p line
- Parameters:
factor (int) – The APD line
V (np.ndarray) – The signal
t (np.ndarray) – The time stamps
v_r (Optional[float], optional) – The resting value, by default None. If None the minimum value is chosen
v_max (Optional[float], optional) – The maximum value, by default None. If None the maximum value is chosen
use_spline (bool, optional) – Use spline interpolation or not, by default True
- Returns:
All indices of points intersecting the APD p line
- Return type:
List[float]
- Raises:
RuntimeError – If spline interpolation fails
- ap_features.features.apd_up_xy(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], low: int, high: int, backend: Backend = Backend.python) float [source]#
Find the duration between first intersection (i.e during the upstroke) of two APD lines
- Parameters:
t (np.ndarray) – Time values
y (np.ndarray) – The trace
low (int) – First APD line (value between 0 and 100)
high (int) – Second APD line (value between 0 and 100)
backend (utils.Backend, optional) – Which backend to use by default Backend.python. Choices, ‘python’, ‘numba’
- Returns:
The time between low to high
- Return type:
float
- ap_features.features.beating_frequency(times: List[ndarray | List[float] | Sequence[float]], unit: str = 'ms') float [source]#
Returns the approximate beating frequency in Hz by finding the average duration of each beat
- Parameters:
times (List[Array]) – Time stamps of all beats
unit (str, optional) – Unit of time, by default “ms”
- Returns:
Beating frequency in Hz
- Return type:
float
- ap_features.features.beating_frequency_from_apd_line(y: ndarray, time: ndarray, unit: str = 'ms') Sequence[float] [source]#
Returns the beating frequency in Hz by using the intersection of the APD50 line
- Parameters:
signals (List[Array]) – The signal values for each beat
times (List[Array]) – The time stamps of all beats
unit (str, optional) – Unit of time, by default “ms”
- Returns:
Beating frequency in Hz for each beat
- Return type:
List[float]
- ap_features.features.beating_frequency_from_peaks(signals: List[ndarray | List[float] | Sequence[float]], times: List[ndarray | List[float] | Sequence[float]], unit: str = 'ms') Sequence[float] [source]#
Returns the beating frequency in Hz by using the peak values of the signals in each beat
- Parameters:
signals (List[Array]) – The signal values for each beat
times (List[Array]) – The time stamps of all beats
unit (str, optional) – Unit of time, by default “ms”
- Returns:
Beating frequency in Hz for each beat
- Return type:
List[float]
- ap_features.features.corrected_apd(apd: float, beat_rate: float, formula: str = 'friderica')[source]#
Correct the given APD (or any QT measurement) for the beat rate. normally the faster the HR (or the shorter the RR interval), the shorter the QT interval, and vice versa
- Parameters:
apd (float) – The action potential duration
beat_rate (float) – The beat rate (number of beats per minute)
formula (str, optional) – Formula for computing th corrected APD, either ‘friderica’ or ‘bazett’, by default ‘friderica’,
- Returns:
The corrected APD
- Return type:
float
Notes
Friderica formula (default):
\[APD (RR)^{-1/3}\]Bazett formula:
\[APD (RR)^{-1/2}\]where \(RR\) is the R-R interval in an ECG. For an action potential this would be equivalent to the inverse of the beating frequency (or 60 divided by the beat rate)
Luo, Shen, et al. “A comparison of commonly used QT correction formulae: the effect of heart rate on the QTc of normal ECGs.” Journal of electrocardiology 37 (2004): 81-90.
- ap_features.features.cost_terms(v: ndarray | List[float] | Sequence[float], ca: ndarray | List[float] | Sequence[float], t_v: ndarray | List[float] | Sequence[float], t_ca: ndarray | List[float] | Sequence[float], backend: Backend = Backend.numba) ndarray [source]#
- ap_features.features.cost_terms_trace(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], backend: Backend = Backend.numba) ndarray [source]#
- ap_features.features.detect_ead(y: ndarray | List[float] | Sequence[float], sigma: float = 1, prominence_level: float = 0.07) Tuple[bool, int | None] [source]#
Detect (Early after depolarizations) EADs based on peak prominence.
- Parameters:
y (Array) – The signal that you want to detect EADs
sigma (float) – Standard deviation in the gaussian smoothing kernel Default: 1.0
prominence_level (float) – How prominent a peak should be in order to be characterized as an EAD. This value should be between 0 and 1, with a greater value being more prominent. Default: 0.07
- Returns:
bool – Flag indicating if an EAD is found or not
int or None – Index where we found the EAD. If no EAD is found then this will be None. I more than one peaks are found then only the first will be returned.
Notes
Given a signal \(y\) we want to determine wether we have an EAD present in the signal. EADs are abnormal depolarizations happening after the upstroke in an action potential.
We assume that an EAD occurs between the maximum value of the signal (i.e the peak) and the next minimum value (i.e when the signal is at rest)
To remove noisy patterns we first smooth the signal with a gaussian filter. Then we take out only the part of the signal that is between its maximum and the next minimum values. Then we find the peaks with a Topographic Prominence greater than the given prominence level
- ap_features.features.find_upstroke_values(t: ndarray, y: ndarray, upstroke_duration: int = 50, normalize: bool = True) ndarray [source]#
- ap_features.features.integrate_apd(y, t=None, factor=30, use_spline=True, normalize=False)[source]#
Compute the integral of the signals above the APD p line
- Parameters:
y (array) – The signal
t (array) – The time points
factor (float) – Which APD line, by default 0.3
use_spline (bool) – Use spline interpolation (Default : True)
normalize (bool) – If true normalize signal first, so that max value is 1.0, and min value is zero before performing the computation.
- Returns:
integral – The integral above the line defined by the APD p line.
- Return type:
float
Notes
This feature represents the integral of the signal above the horizontal line defined by \(\mathrm{APD} p\). First let
\[y_p = \tilde{y} - \left(1- \frac{p}{100} \right),\]and let \(t_1\) and \(t_2\) be the two solutions solving \(y_p(t_i) = 0, i=1,2\) (assume that we have 2 solutions only). The integral we are seeking can now be computed as follows:
\[\mathrm{Int} \; p = \int_{t_1}^{t_2} \left[ y - y(t_1) \right] \mathrm{d}t\]
- ap_features.features.max_relative_upstroke_velocity(t: ndarray, y: ndarray, upstroke_duration: int = 50, sigmoid_fit: bool = True) Upstroke [source]#
Estimate maximum relative upstroke velocity
- Parameters:
t (np.ndarray) – Time values
y (np.ndarray) – The trace
upstroke_duration (int) – Duration in milliseconds of upstroke (Default: 50). This does not have to be exact up should at least be longer than the upstroke.
sigmoid_fit (bool) – If True then use a sigmoid function to fit the data of the upstroke and report the maximum derivate of the sigmoid as the maximum upstroke.
Notes
Brief outline of current algorithm: 1. Interpolate data to have time resolution of 1 ms. 2. Find first intersection with ADP50 line 3. Select 25 ms before and after the point found in 2 4. Normalize the 50 ms (upstroke_duration) from 3 so that we have a max and min value of 1 and 0 respectively. If sigmoid fit is True Fit the normalize trace to a sigmoid function and compte the maximum derivate of the sigmoid else: 5. Compute the successive differences in amplitude (i.e delta y) and report the maximum value of these
- ap_features.features.maximum_upstroke_velocity(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float] | None = None, use_spline: bool = True, normalize: bool = False) float [source]#
Compute maximum upstroke velocity
- Parameters:
y (array) – The signal
t (array) – The time points
use_spline (bool) – Use spline interpolation (Default : True)
normalize (bool) – If true normalize signal first, so that max value is 1.0, and min value is zero before performing the computation.
- Returns:
The maximum upstroke velocity
- Return type:
float
Notes
If \(y\) is the voltage, this feature corresponds to the maximum upstroke velocity. In the case when \(y\) is a continuous signal, i.e a 5th order spline interpolant of the data, then we can simply find the roots of the second derivative, and evaluate the derivative at that point, i.e
\[\max \frac{\mathrm{d}y}{\mathrm{d}t} = \frac{\mathrm{d}y}{\mathrm{d}t} (t^*),\]where
\[\frac{\mathrm{d}^2y}{\mathrm{d}^2t}(t^*) = 0.\]If we decide to use the discrete version of the signal then the above each derivative is approximated using a forward difference, i.e
\[\frac{\mathrm{d}y}{\mathrm{d}t}(t_i) \approx \frac{y_{i+1}-y_i}{t_{i+1} - t_i}.\]
- ap_features.features.tau(x: ndarray | List[float] | Sequence[float], y: ndarray | List[float] | Sequence[float], a: float = 0.75, backend: Backend = Backend.python) float [source]#
Decay time. Time for the signal amplitude to go from maximum to (1 - a) * 100 % of maximum
- Parameters:
x (Array) – The time stamps
y (Array) – The signal
a (float, optional) – The value for which you want to estimate the time decay, by default 0.75. If the value is larger than 1.0 it will be divided by 100
backend (utils.Backend, optional) – Which backend to use by default Backend.python. Choices, ‘python’, ‘numba’
- Returns:
Decay time
- Return type:
float
- ap_features.features.time_above_apd_line(V: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], factor: float, v_r: float | None = None, v_max: float | None = None) float [source]#
Compute the amount of time spent above APD p line
- Parameters:
V (Array) – Signal
t (Array) – Time stamps
factor (float) – The p in APD line
v_r (Optional[float], optional) – Resting value, by default None
v_max (Optional[float], optional) – Maximum value, by default None
- Returns:
Total time spent above the APD p line
- Return type:
float
- ap_features.features.time_to_peak(y: ndarray | List[float] | Sequence[float], x: ndarray | List[float] | Sequence[float], pacing: ndarray | List[float] | Sequence[float] | None = None, backend: Backend = Backend.python) float [source]#
Computed the time to peak from pacing is triggered to maximum amplitude. Note, if pacing is not provided it will compute the time from the beginning of the trace (which might not be consistent) to the peak.
- Parameters:
y (Array) – The signal
x (Array) – The time stamps
pacing (Optional[Array], optional) – The pacing amplitude, by default None
backend (utils.Backend, optional) – Which backend to use by default Backend.python. Choices, ‘python’, ‘numba’
- Returns:
Time to peak
- Return type:
float
- ap_features.features.triangulation(V: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], low: int = 30, high: int = 80, v_r: float | None = None, v_max: float | None = None, use_spline: bool = True, backend: Backend = Backend.python) float [source]#
Compute the triangulation which is the last intersection of the \(\mathrm{APD} \; p_{\mathrm{high}}\) line minus the last intersection of the \(\mathrm{APD} \; p_{\mathrm{low}}\) line
- Parameters:
V (Array) – The signal
t (Array) – The time stamps
low (int, optional) – Lower APD value, by default 30
high (int, optional) – Higher APD value, by default 80
v_r (Optional[float], optional) – The resting value, by default None. If None the minimum value is chosen
v_max (Optional[float], optional) – The maximum value, by default None. If None the maximum value is chosen
use_spline (bool, optional) – Use spline interpolation, by default True. Only applicable for python Backend.
backend (utils.Backend, optional) – Which backend to use by default Backend.python. Choices, ‘python’, ‘numba’
- Returns:
The triangulation
- Return type:
float
- ap_features.features.upstroke(x: ndarray | List[float] | Sequence[float], y: ndarray | List[float] | Sequence[float], a: float = 0.8, backend: Backend = Backend.python) float [source]#
Compute the time from (1-a)*100 % signal amplitude to peak. For example if if a = 0.8 if will compute the time from the starting value of APD80 to the upstroke.
- Parameters:
x (Array) – The time stamps
y (Array) – The signal
a (float, optional) – Fraction of signal amplitude, by default 0.8. If the value is larger than 1.0 it will be divided by 100
backend (utils.Backend, optional) – Which backend to use by default Backend.python. Choices, ‘python’, ‘numba’
- Returns:
The upstroke value
- Return type:
float
- Raises:
ValueError – If a is outside the range of (0, 1)
ap_features.filters module#
- class ap_features.filters.Filters(value)[source]#
Bases:
str
,Enum
An enumeration.
- apd30 = 'apd30'#
- apd50 = 'apd50'#
- apd70 = 'apd70'#
- apd80 = 'apd80'#
- apd90 = 'apd90'#
- length = 'length'#
- time_to_peak = 'time_to_peak'#
- ap_features.filters.filt(y: ndarray | List[float] | Sequence[float], kernel_size: int = 3)[source]#
Filer signal using a median filter. Default kernel_size is 3
- ap_features.filters.filter_signals(data: Sequence[ndarray | List[float] | Sequence[float]] | Dict[Any, ndarray | List[float] | Sequence[float]], x: float = 1, center='mean') Sequence[int] [source]#
- ap_features.filters.find_spike_points(pacing, spike_duration: int = 7) List[int] [source]#
Remove spikes from signal due to pacing.
We assume that there is a spike starting at the time of pacing and the spike disappears after some duration. These points will be deleted from the signal
- Parameters:
pacing (array) – The pacing amplitude of same length as y
spike_duration (int) – Duration of the spikes
- Returns:
A list of indices containing the spikes
- Return type:
np.ndarray
- ap_features.filters.remove_points(x: ndarray | List[float] | Sequence[float], y: ndarray | List[float] | Sequence[float], t_start: float, t_end: float, normalize: bool = True) Tuple[ndarray | List[float] | Sequence[float], ndarray | List[float] | Sequence[float]] [source]#
Remove points in x and y between start and end. Also make sure that the new x starts a zero if normalize = True
- ap_features.filters.within_x_std(arr: ndarray | List[float] | Sequence[float], x: float = 1.0, center='mean') Sequence[int] [source]#
Get the indices in the array that are within x standard deviations from the center value
- Parameters:
arr (Array) – The array with values
x (float, optional) – Number of standard deviations, by default 1.0
center (str, optional) – Center value, Either “mean” or “median”, by default “mean”
- Returns:
Indices of the values that are within x standard deviations from the center value
- Return type:
Sequence[int]
ap_features.plot module#
- ap_features.plot.plot_beat(beat: Trace, include_pacing: bool = False, include_background: bool = False, ylabel: str = '', fname: str = '')[source]#
- ap_features.plot.plot_beats(beats: List[Beat], ylabel: str = '', align: bool = False, fname: str = '')[source]#
- ap_features.plot.plot_beats_from_beat(trace: Beats, ylabel: str = '', align: bool = False, fname: str = '')[source]#
- ap_features.plot.poincare(trace: Beats, apds: List[int], fname: str = '')[source]#
Create poincare plots for given APDs
- Parameters:
trace (beat.Beats) – The trace
apds (list) – List of APDs to be used, e.g [30, 50, 80] will plot the APS30, APD50 and APD80.
fname (str) – Path to filename to save the figure. If not provided plot will be showed and not saved
Notes
For more info see <http://doi.org/10.1371/journal.pcbi.1003202>
- Returns:
A dictionary with the key being the \(x\) in APD:math:x and the value begin the points being plotted.
- Return type:
dict
- ap_features.plot.poincare_from_beats(beats: List[Beat], apds: List[int], fname: str = '')[source]#
Create poincare plots for given APDs
- Parameters:
beats (List[_beat.Beat]) – List of beats
apds (list) – List of APDs to be used, e.g [30, 50, 80] will plot the APS30, APD50 and APD80.
fname (str) – Path to filename to save the figure. If not provided plot will be showed and not saved
Notes
For more info see <http://doi.org/10.1371/journal.pcbi.1003202>
- Returns:
A dictionary with the key being the \(x\) in APD:math:x and the value begin the points being plotted.
- Return type:
dict
ap_features.testing module#
- ap_features.testing.fitzhugh_nagumo(t, x, a=-0.3, b=1.4, tau=20.0, Iext=0.23)[source]#
Time derivative of the Fitzhugh-Nagumo neural model. Parameters
- Parameters:
t (float) – Time (not used)
x (np.ndarray) – State of size 2 - (Membrane potential, Recovery variable)
a (float) – Parameter in the model, by default -0.3
b (float) – Parameter in the model, by default 1.4
tau (float) – Time scale, by default 20.0
Iext (float) – Constant stimulus current, by default 0.23
- Returns:
dx/dt - size 2
- Return type:
np.ndarray
ap_features.utils module#
- class ap_features.utils.Backend(value)[source]#
Bases:
str
,Enum
An enumeration.
- numba = 'numba'#
- python = 'python'#
- ap_features.utils.find_pacing_period(pacing_data, pacing_amp=5)[source]#
Find period of pacing in pacing data
- Parameters:
pacing_data (array) – The pacing data
pacing_amp (float) – The stimulus amplitude
- ap_features.utils.intersection(data: Sequence[Sequence[int]] | Dict[Any, Sequence[int]]) Sequence[int] [source]#
Get intersection of all values in a dictionary or a list of lists
- Parameters:
data (Union[Sequence[Sequence[int]], Dict[str, Sequence[int]]]) – Input data
- Returns:
The intersection
- Return type:
Sequence[int]
- ap_features.utils.normalize_signal(V, v_r: float | None = None, v_max: float | None = None)[source]#
Normalize signal to have maximum value 1 and zero being the value equal to v_r (resting value). If v_r is not provided the minimum value in V will be used as v_r
- Parameters:
V (array) – The signal
v_r (Optional[float], optional) – The resting value, by default None. If None the minimum value is chosen
v_max (Optional[float], optional) – The maximum value, by default None. If None the maximum value is chosen
Module contents#
- ap_features.BC#
alias of
BackgroundCorrection
- class ap_features.Backend(value)[source]#
Bases:
str
,Enum
An enumeration.
- numba = 'numba'#
- python = 'python'#
- class ap_features.Beat(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], pacing: ndarray | List[float] | Sequence[float] | None = None, y_rest: float | None = None, y_max: float | None = None, parent: Beats | None = None, backend: Backend = Backend.numba, beat_number: int | None = None)[source]#
Bases:
Trace
- apd(factor: float, use_spline: bool = True) float [source]#
The action potential duration
- Parameters:
factor (int) – Integer between 0 and 100
use_spline (bool, optional) – Use spline interpolation, by default True.
- Returns:
action potential duration
- Return type:
float
- apd_point(factor: float, use_spline: bool = True, strategy: APDPointStrategy = APDPointStrategy.big_diff_plus_one) Tuple[float, float] [source]#
Return the first and second intersection of the APD p line
- Parameters:
factor (int) – The APD
use_spline (bool, optional) – Use spline interpolation or not, by default True
- Returns:
Two points corresponding to the first and second intersection of the APD p line
- Return type:
Tuple[float, float]
- apd_points(factor: float, use_spline: bool = True) List[float] [source]#
Return all intersections of the APD p line
- Parameters:
factor (int) – The APD
use_spline (bool, optional) – Use spline interpolation or not, by default True
- Returns:
Two points corresponding to the first and second intersection of the APD p line
- Return type:
List[float]
- apd_up_xy(low, high)[source]#
Find the duration between first intersection (i.e during the upstroke) of two APD lines
- Parameters:
low (int) – First APD line (value between 0 and 100)
high (int) – Second APD line (value between 0 and 100)
- Returns:
The time between low to high
- Return type:
float
- capd(factor: float, beat_rate: float | None = None, formula: str = 'friderica', use_spline: bool = True, use_median_beat_rate: bool = False) float [source]#
Correct the given APD (or any QT measurement) for the beat rate. normally the faster the HR (or the shorter the RR interval), the shorter the QT interval, and vice versa
- Parameters:
factor (int) – Integer between 0 and 100
beat_rate (float) – The beat rate (number of beats per minute)
formula (str, optional) – Formula for computing th corrected APD, either ‘friderica’ or ‘bazett’, by default ‘friderica’,
- Returns:
The corrected APD
- Return type:
float
Notes
Friderica formula (default):
\[APD (RR)^{-1/3}\]Bazett formula:
\[APD (RR)^{-1/2}\]where \(RR\) is the R-R interval in an ECG. For an action potential this would be equivalent to the inverse of the beating frequency (or 60 divided by the beat rate)
Luo, Shen, et al. “A comparison of commonly used QT correction formulae: the effect of heart rate on the QTc of normal ECGs.” Journal of electrocardiology 37 (2004): 81-90.
- property cost_terms#
- detect_ead(sigma: float = 1, prominence_level: float = 0.07) Tuple[bool, int | None] [source]#
Detect (Early after depolarizations) EADs based on peak prominence.
- Parameters:
y (Array) – The signal that you want to detect EADs
sigma (float) – Standard deviation in the gaussian smoothing kernel Default: 1.0
prominence_level (float) – How prominent a peak should be in order to be characterized as an EAD. This value should be between 0 and 1, with a greater value being more prominent. Default: 0.07
- Returns:
bool – Flag indicating if an EAD is found or not
int or None – Index where we found the EAD. If no EAD is found then this will be None. I more than one peaks are found then only the first will be returned.
- integrate_apd(factor: float, use_spline: bool = True, normalize: bool = False) float [source]#
Compute the integral of the signals above the APD p line
- Parameters:
factor (float) – Which APD line
use_spline (bool, optional) – Use spline interpolation, by default True
normalize (bool, optional) – If true normalize signal first, so that max value is 1.0, and min value is zero before performing the computation, by default False
- Returns:
Integral above the APD p line
- Return type:
float
- maximum_relative_upstroke_velocity(upstroke_duration: int = 50, sigmoid_fit: bool = True)[source]#
Estimate maximum relative upstroke velocity
- Parameters:
upstroke_duration (int) – Duration in milliseconds of upstroke (Default: 50). This does not have to be exact up should at least be longer than the upstroke.
sigmoid_fit (bool) – If True then use a sigmoid function to fit the data of the upstroke and report the maximum derivate of the sigmoid as the maximum upstroke.
- maximum_upstroke_velocity(use_spline: bool = True, normalize: bool = False) float [source]#
Compute maximum upstroke velocity
- Parameters:
use_spline (bool, optional) – Use spline interpolation, by default True
normalize (bool, optional) – If true normalize signal first, so that max value is 1.0, and min value is zero before performing the computation, by default False
- Returns:
The maximum upstroke velocity
- Return type:
float
- property parent: Beats | None#
If the beat comes from several Beats object then this will return those Beats
- Returns:
The parent Beats
- Return type:
- peaks(prominence_level: float = 0.1) List[int] [source]#
Return the list of peak indices given a prominence level
- tau(a: float) float [source]#
Decay time. Time for the signal amplitude to go from maximum to (1 - a) * 100 % of maximum
- Parameters:
a (float) – The value for which you want to estimate the time decay
- Returns:
Decay time
- Return type:
float
- time_above_apd_line(factor: float) float [source]#
Compute the amount of time spent above APD p line
- triangulation(low: int = 30, high: int = 80, use_spline: bool = True) float [source]#
Compute the triangulation which is the last intersection of the \(\mathrm{APD} \; p_{\mathrm{high}}\) line minus the last intersection of the \(\mathrm{APD} \; p_{\mathrm{low}}\) line
- Parameters:
low (int, optional) – Lower APD value, by default 30
high (int, optional) – Higher APD value, by default 80
use_spline (bool, optional) – Use spline interpolation, by default True.
- Returns:
The triangulations
- Return type:
float
- ttp(use_pacing: bool = True) float [source]#
Computed the time to peak from pacing is triggered to maximum amplitude. Note, if pacing is not provided it will compute the time from the beginning of the trace (which might not be consistent) to the peak.
- Parameters:
use_pacing (bool, optional) – If pacing is available compute time to peak from start of packing, by default True
- Returns:
Time to peak
- Return type:
float
- upstroke(a: float) float [source]#
Compute the time from (1-a)*100 % signal amplitude to peak. For example if if a = 0.8 if will compute the time from the starting value of APD80 to the upstroke.
- Parameters:
a (float) – Fraction of signal amplitude
- Returns:
The upstroke value
- Return type:
float
- property y_max: float | None#
Return maximum value if specified, otherwise None
- property y_normalized: ndarray#
Return normalized signal
- property y_rest: float | None#
Return resting value if specified, otherwise None
- class ap_features.BeatCollection(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], pacing: ndarray | List[float] | Sequence[float] | None = None, mask: ndarray | List[float] | Sequence[float] | None = None, parent: BeatSeriesCollection | None = None, backend: Backend = Backend.numba)[source]#
Bases:
Trace
- property num_traces#
- property parent: BeatSeriesCollection | None#
If the beat comes from a BeatSeries object then this will return that BeatSeries
- Returns:
The parent BeatSeries
- Return type:
BeatSeries
- class ap_features.Beats(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], pacing: ndarray | List[float] | Sequence[float] | None = None, background_correction_method: BackgroundCorrection = BackgroundCorrection.none, zero_index: int | None = None, background_correction_kernel: int = 0, backend: Backend = Backend.numba, intervals: List[Interval] | None = None, chopping_options: Dict[str, float] | None = None, force_positive: bool = False)[source]#
Bases:
Trace
- average_beat(filters: Sequence[Filters] | None = None, N: int = 200, x: float = 1.0, apd_point: float = 50) Beat [source]#
Compute an average beat based on aligning the individual beats
- Parameters:
filters (Optional[Sequence[_filters.Filters]], optional) – A list of filters that should be used to decide which beats that should be included in the averaging, by default None
N (int, optional) – Length of output signal, by default 200. Note that the output signal will be interpolated so that it has this length. This is done because the different beats might have different lengths.
x (float, optional) – The number of standard deviations used in the filtering, by default 1.0
- Returns:
An average beat.
- Return type:
- property background: ndarray#
- property beat_rate: float#
The beat rate, i.e number of beats per minute, which is simply 60 divided by the beating frequency
- property beat_rates: List[float]#
Beat rate for all beats
- Returns:
List of beat rates
- Return type:
List[float]
- property beating_frequencies: Sequence[float]#
Get the frequency for each beat
- Returns:
List of frequencies
- Return type:
List[float]
- property beating_frequency: float#
The median frequency of all beats
- property beats: List[Beat]#
Chop signal into individual beats. You can also pass in any options that should be provided to the chopping algorithm.
- Returns:
A list of chopped beats
- Return type:
List[Beat]
- chop_data(threshold_factor=0.5, min_window=50, max_window=5000, N=None, extend_front=None, extend_end=None, ignore_pacing=False, intervals=None)[source]#
- property chopped_data: ChoppedData#
- correct_background(background_correction_method: BackgroundCorrection, copy: bool = True) Beats [source]#
- filter_beats(filters: Sequence[Filters], x: float = 1.0) List[Beat] [source]#
Get a subset of the chopped beats based on similarities in different features.
- Parameters:
filters (Sequence[_filters.Filters]) – A list of filters that should be used for filtering
x (float, optional) – How many standard deviations away from the mean the different beats should be to be included, by default 1.0
- Returns:
A list of filtered beats
- Return type:
List[Beat]
- property num_beats: int#
- property original_y: ndarray#
- property y: ndarray#
The trace
- class ap_features.State(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float] | None, pacing: ndarray | List[float] | Sequence[float] | None = None, backend: Backend = Backend.numba)[source]#
Bases:
Trace
- property cost_terms#
- property num_states#
- class ap_features.StateCollection(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], pacing: ndarray | List[float] | Sequence[float] | None = None, mask: ndarray | List[float] | Sequence[float] | None = None, parent: StateSeriesCollection | None = None)[source]#
Bases:
Trace
- property cost_terms#
- property mask: ndarray | List[float] | Sequence[float] | None#
- property num_states#
- property num_traces#
- property parent: StateSeriesCollection | None#
If the beat comes from a BeatSeries object then this will return that BeatSeries
- Returns:
The parent BeatSeries
- Return type:
BeatSeries
- class ap_features.Trace(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float] | None, pacing: ndarray | List[float] | Sequence[float] | None = None, backend: Backend = Backend.numba)[source]#
Bases:
object
- as_spline(k: int = 3, s: int | None = None) UnivariateSpline [source]#
Convert trace to spline
- Parameters:
k (int, optional) – Degree of the smoothing spline. Must be 1 <= k <= 5. Default is k = 3, a cubic spline, by default 3.
s (float or None, optional) – Positive smoothing factor used to choose the number of knots. If 0, spline will interpolate through all data points, by default 0
- Returns:
A spline representation of the trace
- Return type:
UnivariateSpline
- property duration: float#
The duration of the trace, i.e last time point minus the first
- ensure_time_unit(unit: str) None [source]#
Convert time to milliseconds or seconds
- Parameters:
unit (str) – A string with ‘ms’ or ‘s’
- property pacing: ndarray#
Array of pacing amplitudes. If no pacing info is available, then this will be an array of zeros with same length as the trace
- plot(fname: str = '', include_pacing: bool = False, include_background: bool = False, ylabel: str = '')[source]#
Plot the trace with matplotlib
- Parameters:
fname (str, optional) – Name of the figure to be saved. If not provided the figure will note be saved, but you can show by calling plt.show
include_pacing (bool, optional) – Whether to include pacing in the plot, by default False
include_background (bool, optional) – Whether to include the background, by default False
ylabel (str, optional) – Label on the y-axis, by default “”
- Returns:
If matplotlib is installed it will return a tuple containing the figure and the axes.
- Return type:
Tuple[plt.Figure, plt.Axes] | None
- slice(start: float, end: float, copy: bool = True) Trace [source]#
Create a slice of the original trace
- Parameters:
start (float) – Start time of slice
end (float) – End time of slice
copy (bool, optional) – If true create a copy of the original array otherwise return a slice of the original array, by default True
- Returns:
A sliced trace
- Return type:
- property t: ndarray#
The time stamps
- property time_unit: str#
The time unit ‘ms’ or ‘s’
- property y: ndarray#
The trace
- ap_features.all_cost_terms(arr: ndarray, t: ndarray, mask: ndarray | None = None, backend: Backend = Backend.numba, normalize_time: bool = True) ndarray [source]#
- ap_features.apd(factor: float, V: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], v_r: float | None = None, v_max: float | None = None, use_spline: bool = True, backend: Backend = Backend.python) float [source]#
Return the action potential duration at the given factor repolarization, so that factor = 0 would be zero, and factor = 1 given the time from triggering to potential is down to resting potential.
- Parameters:
factor (int) – The APD factor between 0 and 100
V (Array) – The signal
t (Array) – The time stamps
v_r (Optional[float], optional) – The resting value, by default None. If None the minimum value is chosen
v_max (Optional[float], optional) – The maximum value, by default None. If None the maximum value is chosen
use_spline (bool, optional) – Use spline interpolation, by default True. Only applicable for python Backend.
backend (utils.Backend, optional) – Which backend to use by default Backend.python. Choices, ‘python’, ‘numba’
- Returns:
float – The action potential duration
.. Note:: – If the signal has more intersection than two with the APX_X line, then the first and second occurrence will be used.
- Raises:
ValueError – If factor is outside the range of (0, 100)
ValueError – If shape of x and y does not match
RunTimeError – In unable to compute APD
Notes
If the signal represent voltage, we would like to compute the action potential duration at a given factor of the signal. Formally, Let \(p \in (0, 100)\), and define
\[y_p = \tilde{y} - \left(1- \frac{p}{100} \right).\]Now let \(\mathcal{T}\) denote the set of solutions of \(y_p = 0\), i.e
\[y_p(t) = 0, \;\; \forall t \in \mathcal{T}\]Then there are three different scenarios; \(\mathcal{T}\) contains one, two or more than two elements. Note that \(\mathcal{T}\) cannot be empty (because of the intermediate value theorem). The only valid scenario is the case when \(\mathcal{T}\) contains two (or more) elements. In this case we define
\[\mathrm{APD} \; p = \max \mathcal{T} - \min \mathcal{T}\]for \(p < 0.5\) and
\[\mathrm{APD} \; p = \min \mathcal{T} / \min \mathcal{T} - \min \mathcal{T}\]
- ap_features.apd_up_xy(y: ndarray | List[float] | Sequence[float], t: ndarray | List[float] | Sequence[float], low: int, high: int, backend: Backend = Backend.python) float [source]#
Find the duration between first intersection (i.e during the upstroke) of two APD lines
- Parameters:
t (np.ndarray) – Time values
y (np.ndarray) – The trace
low (int) – First APD line (value between 0 and 100)
high (int) – Second APD line (value between 0 and 100)
backend (utils.Backend, optional) – Which backend to use by default Backend.python. Choices, ‘python’, ‘numba’
- Returns:
The time between low to high
- Return type:
float
- ap_features.average_and_interpolate(ys: Sequence[ndarray | List[float] | Sequence[float]], xs: Sequence[ndarray | List[float] | Sequence[float]] | None = None, N: int = 200) Average [source]#
Get the average of list of signals assuming that they align at the same x value
- Parameters:
ys (Array) – The signal values
xs (Array) – The x-values
N (int) – Length of output array (Default: 200)
- Returns:
Y_avg (array) – The average y values
X (array) – The new x-values
- ap_features.cost_terms(v: ndarray | List[float] | Sequence[float], ca: ndarray | List[float] | Sequence[float], t_v: ndarray | List[float] | Sequence[float], t_ca: ndarray | List[float] | Sequence[float], backend: Backend = Backend.numba) ndarray [source]#