Skip to content

Commit d8b620c

Browse files
authored
copy ricker wavelet from scipy which removed it from version 1.15.0 (#526)
This PR fixes issue #525
2 parents ce702cb + dd6506f commit d8b620c

File tree

1 file changed

+88
-2
lines changed

1 file changed

+88
-2
lines changed

wfdb/processing/qrs.py

+88-2
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def _mwi(self):
215215
N/A
216216
217217
"""
218-
wavelet_filter = signal.ricker(self.qrs_width, 4)
218+
wavelet_filter = ricker(self.qrs_width, 4)
219219

220220
self.sig_i = (
221221
signal.filtfilt(wavelet_filter, [1], self.sig_f, axis=0) ** 2
@@ -277,7 +277,7 @@ def _learn_init_params(self, n_calib_beats=8):
277277
qrs_amps = []
278278
noise_amps = []
279279

280-
ricker_wavelet = signal.ricker(self.qrs_radius * 2, 4).reshape(-1, 1)
280+
ricker_wavelet = ricker(self.qrs_radius * 2, 4).reshape(-1, 1)
281281

282282
# Find the local peaks of the signal.
283283
peak_inds_f = find_local_peaks(self.sig_f, self.qrs_radius)
@@ -1776,3 +1776,89 @@ def gqrs_detect(
17761776
annotations = gqrs.detect(x=d_sig, conf=conf, adc_zero=adc_zero)
17771777

17781778
return np.array([a.time for a in annotations])
1779+
1780+
1781+
# This function includes code from SciPy, which is licensed under the
1782+
# BSD 3-Clause "New" or "Revised" License.
1783+
# The original code can be found at:
1784+
# https://github.com/scipy/scipy/blob/v1.14.0/scipy/signal/_wavelets.py#L316-L359
1785+
1786+
# Copyright (c) 2001-2002 Enthought, Inc. 2003, SciPy Developers.
1787+
# All rights reserved.
1788+
1789+
# Redistribution and use in source and binary forms, with or without
1790+
# modification, are permitted provided that the following conditions
1791+
# are met:
1792+
1793+
# 1. Redistributions of source code must retain the above copyright
1794+
# notice, this list of conditions and the following disclaimer.
1795+
1796+
# 2. Redistributions in binary form must reproduce the above
1797+
# copyright notice, this list of conditions and the following
1798+
# disclaimer in the documentation and/or other materials provided
1799+
# with the distribution.
1800+
1801+
# 3. Neither the name of the copyright holder nor the names of its
1802+
# contributors may be used to endorse or promote products derived
1803+
# from this software without specific prior written permission.
1804+
1805+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1806+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1807+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1808+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1809+
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1810+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1811+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1812+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1813+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1814+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1815+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1816+
1817+
1818+
def ricker(points, a):
1819+
"""
1820+
Return a Ricker wavelet, also known as the "Mexican hat wavelet".
1821+
1822+
It models the function:
1823+
1824+
``A * (1 - (x/a)**2) * exp(-0.5*(x/a)**2)``,
1825+
1826+
where ``A = 2/(sqrt(3*a)*(pi**0.25))``.
1827+
1828+
This function is copied from the `scipy` library which
1829+
removed it from version 1.15.0.
1830+
1831+
Parameters
1832+
----------
1833+
points : int
1834+
Number of points in `vector`.
1835+
Will be centered around 0.
1836+
a : scalar
1837+
Width parameter of the wavelet.
1838+
1839+
Returns
1840+
-------
1841+
vector : (N,) ndarray
1842+
Array of length `points` in shape of ricker curve.
1843+
1844+
Examples
1845+
--------
1846+
>>> import matplotlib.pyplot as plt
1847+
1848+
>>> points = 100
1849+
>>> a = 4.0
1850+
>>> vec2 = ricker(points, a)
1851+
>>> print(len(vec2))
1852+
100
1853+
>>> plt.plot(vec2)
1854+
>>> plt.show()
1855+
1856+
"""
1857+
A = 2 / (np.sqrt(3 * a) * (np.pi**0.25))
1858+
wsq = a**2
1859+
vec = np.arange(0, points) - (points - 1.0) / 2
1860+
xsq = vec**2
1861+
mod = 1 - xsq / wsq
1862+
gauss = np.exp(-xsq / (2 * wsq))
1863+
total = A * mod * gauss
1864+
return total

0 commit comments

Comments
 (0)