|
49 | 49 |
|
50 | 50 | import functools
|
51 | 51 | from numbers import Number
|
| 52 | +import sys |
52 | 53 |
|
53 | 54 | import numpy as np
|
54 | 55 |
|
@@ -210,6 +211,30 @@ def detrend_linear(y):
|
210 | 211 | return y - (b*x + a)
|
211 | 212 |
|
212 | 213 |
|
| 214 | +def _stride_windows(x, n, noverlap=0): |
| 215 | + if noverlap >= n: |
| 216 | + raise ValueError('noverlap must be less than n') |
| 217 | + if n < 1: |
| 218 | + raise ValueError('n cannot be less than 1') |
| 219 | + |
| 220 | + x = np.asarray(x) |
| 221 | + |
| 222 | + if n == 1 and noverlap == 0: |
| 223 | + return x[np.newaxis] |
| 224 | + if n > x.size: |
| 225 | + raise ValueError('n cannot be greater than the length of x') |
| 226 | + |
| 227 | + # np.lib.stride_tricks.as_strided easily leads to memory corruption for |
| 228 | + # non integer shape and strides, i.e. noverlap or n. See #3845. |
| 229 | + noverlap = int(noverlap) |
| 230 | + n = int(n) |
| 231 | + |
| 232 | + step = n - noverlap |
| 233 | + shape = (n, (x.shape[-1]-noverlap)//step) |
| 234 | + strides = (x.strides[0], step*x.strides[0]) |
| 235 | + return np.lib.stride_tricks.as_strided(x, shape=shape, strides=strides) |
| 236 | + |
| 237 | + |
213 | 238 | def _spectral_helper(x, y=None, NFFT=None, Fs=None, detrend_func=None,
|
214 | 239 | window=None, noverlap=None, pad_to=None,
|
215 | 240 | sides=None, scale_by_freq=None, mode=None):
|
@@ -304,17 +329,23 @@ def _spectral_helper(x, y=None, NFFT=None, Fs=None, detrend_func=None,
|
304 | 329 | raise ValueError(
|
305 | 330 | "The window length must match the data's first dimension")
|
306 | 331 |
|
307 |
| - result = np.lib.stride_tricks.sliding_window_view( |
308 |
| - x, NFFT, axis=0)[::NFFT - noverlap].T |
| 332 | + if sys.maxsize > 2**32: # NumPy version on 32-bit OOMs. |
| 333 | + result = np.lib.stride_tricks.sliding_window_view( |
| 334 | + x, NFFT, axis=0)[::NFFT - noverlap].T |
| 335 | + else: |
| 336 | + result = _stride_windows(x, NFFT, noverlap=noverlap) |
309 | 337 | result = detrend(result, detrend_func, axis=0)
|
310 | 338 | result = result * window.reshape((-1, 1))
|
311 | 339 | result = np.fft.fft(result, n=pad_to, axis=0)[:numFreqs, :]
|
312 | 340 | freqs = np.fft.fftfreq(pad_to, 1/Fs)[:numFreqs]
|
313 | 341 |
|
314 | 342 | if not same_data:
|
315 | 343 | # if same_data is False, mode must be 'psd'
|
316 |
| - resultY = np.lib.stride_tricks.sliding_window_view( |
317 |
| - y, NFFT, axis=0)[::NFFT - noverlap].T |
| 344 | + if sys.maxsize > 2**32: # NumPy version on 32-bit OOMs. |
| 345 | + resultY = np.lib.stride_tricks.sliding_window_view( |
| 346 | + y, NFFT, axis=0)[::NFFT - noverlap].T |
| 347 | + else: |
| 348 | + resultY = _stride_windows(y, NFFT, noverlap=noverlap) |
318 | 349 | resultY = detrend(resultY, detrend_func, axis=0)
|
319 | 350 | resultY = resultY * window.reshape((-1, 1))
|
320 | 351 | resultY = np.fft.fft(resultY, n=pad_to, axis=0)[:numFreqs, :]
|
|
0 commit comments