prpy 0.4.4__tar.gz → 0.4.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {prpy-0.4.4 → prpy-0.4.5}/PKG-INFO +2 -4
- {prpy-0.4.4 → prpy-0.4.5}/README.md +0 -2
- {prpy-0.4.4 → prpy-0.4.5}/prpy/ffmpeg/probe.py +46 -15
- {prpy-0.4.4 → prpy-0.4.5}/prpy/numpy/filters.py +9 -6
- {prpy-0.4.4 → prpy-0.4.5}/prpy.egg-info/PKG-INFO +2 -4
- prpy-0.4.5/prpy.egg-info/scm_version.json +8 -0
- {prpy-0.4.4 → prpy-0.4.5}/pyproject.toml +5 -1
- {prpy-0.4.4 → prpy-0.4.5}/tests/conftest.py +14 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_ffmpeg.py +27 -1
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_numpy_filters.py +11 -0
- prpy-0.4.4/prpy.egg-info/scm_version.json +0 -8
- {prpy-0.4.4 → prpy-0.4.5}/.gitignore +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/CONTRIBUTING.md +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/LICENSE +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/MANIFEST.in +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/__init__.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/constants.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/ffmpeg/__init__.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/ffmpeg/readwrite.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/ffmpeg/utils.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/helpers.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/numpy/__init__.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/numpy/core.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/numpy/detect.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/numpy/face.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/numpy/freq.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/numpy/image.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/numpy/image_ops.c +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/numpy/interp.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/numpy/metric.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/numpy/physio.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/numpy/rolling.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/numpy/stride_tricks.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/numpy/utils.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/tensorflow/__init__.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/tensorflow/image.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/tensorflow/loss.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/tensorflow/lr_schedule.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/tensorflow/model_saver.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/tensorflow/nan.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/tensorflow/optimizer.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/tensorflow/signal.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/torch/__init__.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/torch/loss.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/torch/lr_schedule.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/torch/model_saver.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy/torch/nan.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy.egg-info/SOURCES.txt +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy.egg-info/dependency_links.txt +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy.egg-info/requires.txt +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy.egg-info/scm_file_list.json +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/prpy.egg-info/top_level.txt +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/setup.cfg +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/setup.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_numpy_core.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_numpy_detect.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_numpy_face.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_numpy_freq.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_numpy_image.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_numpy_interp.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_numpy_metric.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_numpy_rolling.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_numpy_stride_tricks.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_numpy_utils.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_tensorflow.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_torch.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_torch_loss.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_torch_lr_schedule.py +0 -0
- {prpy-0.4.4 → prpy-0.4.5}/tests/test_torch_nan.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: prpy
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.5
|
|
4
4
|
Summary: Collection of Python utils for signal, image, and video processing
|
|
5
5
|
Author-email: Philipp Rouast <philipp@rouast.com>
|
|
6
6
|
License: MIT License
|
|
@@ -11,7 +11,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
11
11
|
Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Development Status :: 4 - Beta
|
|
13
13
|
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
-
Requires-Python:
|
|
14
|
+
Requires-Python: <3.13,>=3.10
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
License-File: LICENSE
|
|
17
17
|
Requires-Dist: numpy>=1.24
|
|
@@ -50,8 +50,6 @@ It contains subpackages for working with `numpy`, `ffmpeg`, `tensorflow`, and `t
|
|
|
50
50
|
|
|
51
51
|
General prerequisites are `python>=3.10` and `ffmpeg` installed and accessible via the `$PATH` environment variable.
|
|
52
52
|
|
|
53
|
-
- Please note: If using `numpy` or `tensorflow` options, we only support Python `<3.12` because of the dependencies.
|
|
54
|
-
|
|
55
53
|
The easiest way to install the latest version of `prpy`:
|
|
56
54
|
|
|
57
55
|
```
|
|
@@ -10,8 +10,6 @@ It contains subpackages for working with `numpy`, `ffmpeg`, `tensorflow`, and `t
|
|
|
10
10
|
|
|
11
11
|
General prerequisites are `python>=3.10` and `ffmpeg` installed and accessible via the `$PATH` environment variable.
|
|
12
12
|
|
|
13
|
-
- Please note: If using `numpy` or `tensorflow` options, we only support Python `<3.12` because of the dependencies.
|
|
14
|
-
|
|
15
13
|
The easiest way to install the latest version of `prpy`:
|
|
16
14
|
|
|
17
15
|
```
|
|
@@ -172,9 +172,18 @@ def probe_video(
|
|
|
172
172
|
|
|
173
173
|
return fps, total_frames, width, height, codec, bitrate, rotation, issues
|
|
174
174
|
|
|
175
|
+
def _parse_ffprobe_csv_floats(raw: str) -> np.ndarray:
|
|
176
|
+
"""Parse ffprobe's `-of csv=p=0` stdout (one value per line, possibly with a
|
|
177
|
+
trailing comma) into a float array."""
|
|
178
|
+
cleaned = "\n".join(line.rstrip(",") for line in raw.splitlines())
|
|
179
|
+
return np.fromstring(cleaned, dtype=float, sep="\n")
|
|
180
|
+
|
|
175
181
|
def probe_video_frame_timestamps(path: str, sanity_check: bool = False) -> list:
|
|
176
182
|
"""Probe a video file for a best effort estimate of its frame timestamps.
|
|
177
183
|
|
|
184
|
+
Tries reading each packet's pts directly and sorting (no decode needed).
|
|
185
|
+
Falls back to decoding every frame otherwise.
|
|
186
|
+
|
|
178
187
|
Args:
|
|
179
188
|
path: The path of the video.
|
|
180
189
|
sanity_check: Whether to check result against ffprobe count
|
|
@@ -184,23 +193,45 @@ def probe_video_frame_timestamps(path: str, sanity_check: bool = False) -> list:
|
|
|
184
193
|
if not os.path.exists(path):
|
|
185
194
|
raise FileNotFoundError(f"File {path} does not exist")
|
|
186
195
|
|
|
187
|
-
|
|
188
|
-
ts_cmd = [
|
|
189
|
-
"ffprobe", "-v", "error",
|
|
190
|
-
"-select_streams", "v:0",
|
|
191
|
-
"-show_entries", "frame=best_effort_timestamp_time",
|
|
192
|
-
"-of", "csv=p=0",
|
|
193
|
-
path
|
|
194
|
-
]
|
|
196
|
+
timestamps = None
|
|
195
197
|
try:
|
|
196
|
-
proc = subprocess.run(
|
|
197
|
-
|
|
198
|
+
proc = subprocess.run([
|
|
199
|
+
"ffprobe", "-v", "error",
|
|
200
|
+
"-select_streams", "v:0",
|
|
201
|
+
"-show_entries", "packet=pts_time",
|
|
202
|
+
"-of", "csv=p=0",
|
|
203
|
+
path
|
|
204
|
+
], capture_output=True, text=True, check=True)
|
|
205
|
+
lines = proc.stdout.splitlines()
|
|
206
|
+
if lines and all(line.rstrip(",") for line in lines):
|
|
207
|
+
candidate = np.sort(_parse_ffprobe_csv_floats(proc.stdout))
|
|
208
|
+
# A handful of tied pts (e.g. a GOP-boundary rounding artifact) is fine
|
|
209
|
+
# -- sorting already guarantees non-decreasing order, so the only real
|
|
210
|
+
# question is whether too many packets are tied to trust the result.
|
|
211
|
+
n_dupes = int(np.sum(np.diff(candidate) <= 0)) if candidate.size else 0
|
|
212
|
+
if candidate.size == len(lines) and n_dupes <= max(1, int(0.01 * candidate.size)):
|
|
213
|
+
timestamps = candidate
|
|
214
|
+
else:
|
|
215
|
+
logging.debug("Packet-level pts unusable (incomplete or too many duplicates); falling back.")
|
|
198
216
|
except subprocess.CalledProcessError as e:
|
|
199
|
-
logging.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
217
|
+
logging.debug("Fast packet-level probe failed, falling back: %s", e)
|
|
218
|
+
|
|
219
|
+
if timestamps is None:
|
|
220
|
+
# Fallback: decode every frame to read its best-effort timestamp.
|
|
221
|
+
ts_cmd = [
|
|
222
|
+
"ffprobe", "-v", "error",
|
|
223
|
+
"-select_streams", "v:0",
|
|
224
|
+
"-show_entries", "frame=best_effort_timestamp_time",
|
|
225
|
+
"-of", "csv=p=0",
|
|
226
|
+
path
|
|
227
|
+
]
|
|
228
|
+
try:
|
|
229
|
+
proc = subprocess.run(ts_cmd, capture_output=True, text=True, check=True)
|
|
230
|
+
raw = proc.stdout
|
|
231
|
+
except subprocess.CalledProcessError as e:
|
|
232
|
+
logging.error("ffprobe error: %s", e)
|
|
233
|
+
return []
|
|
234
|
+
timestamps = _parse_ffprobe_csv_floats(raw)
|
|
204
235
|
|
|
205
236
|
if sanity_check:
|
|
206
237
|
# Grab the frame count
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
import math
|
|
22
22
|
import numpy as np
|
|
23
23
|
from scipy import signal
|
|
24
|
+
from scipy.linalg import solveh_banded
|
|
24
25
|
from scipy.ndimage import uniform_filter1d
|
|
25
26
|
from scipy.sparse import spdiags
|
|
26
27
|
from typing import Union, Tuple
|
|
@@ -151,18 +152,20 @@ def detrend(
|
|
|
151
152
|
T = z.shape[axis]
|
|
152
153
|
if T < 3:
|
|
153
154
|
return z
|
|
154
|
-
# Identity matrix
|
|
155
|
-
I = np.identity(T)
|
|
156
155
|
# Regularization matrix
|
|
157
156
|
D2 = spdiags(
|
|
158
157
|
[np.ones(T), -2*np.ones(T), np.ones(T)],
|
|
159
|
-
[0, 1, 2], (T-2), T)
|
|
160
|
-
#
|
|
161
|
-
|
|
158
|
+
[0, 1, 2], (T-2), T)
|
|
159
|
+
# I+lambda^2*D2’*D2 is symmetric pentadiagonal, so solve it in banded form
|
|
160
|
+
DTD = (D2.T @ D2).todia()
|
|
161
|
+
ab = np.zeros((3, T))
|
|
162
|
+
ab[2] = 1. + (Lambda**2) * DTD.diagonal(0)
|
|
163
|
+
ab[1, 1:] = (Lambda**2) * DTD.diagonal(1)
|
|
164
|
+
ab[0, 2:] = (Lambda**2) * DTD.diagonal(2)
|
|
162
165
|
# Compute the detrending operation (vectorized)
|
|
163
166
|
if axis == 0:
|
|
164
167
|
z = np.transpose(z)
|
|
165
|
-
z_trend =
|
|
168
|
+
z_trend = solveh_banded(ab, z.T)
|
|
166
169
|
proc_z = (z.T - z_trend)
|
|
167
170
|
if axis == 1:
|
|
168
171
|
proc_z = np.transpose(proc_z)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: prpy
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.5
|
|
4
4
|
Summary: Collection of Python utils for signal, image, and video processing
|
|
5
5
|
Author-email: Philipp Rouast <philipp@rouast.com>
|
|
6
6
|
License: MIT License
|
|
@@ -11,7 +11,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
11
11
|
Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Development Status :: 4 - Beta
|
|
13
13
|
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
-
Requires-Python:
|
|
14
|
+
Requires-Python: <3.13,>=3.10
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
License-File: LICENSE
|
|
17
17
|
Requires-Dist: numpy>=1.24
|
|
@@ -50,8 +50,6 @@ It contains subpackages for working with `numpy`, `ffmpeg`, `tensorflow`, and `t
|
|
|
50
50
|
|
|
51
51
|
General prerequisites are `python>=3.10` and `ffmpeg` installed and accessible via the `$PATH` environment variable.
|
|
52
52
|
|
|
53
|
-
- Please note: If using `numpy` or `tensorflow` options, we only support Python `<3.12` because of the dependencies.
|
|
54
|
-
|
|
55
53
|
The easiest way to install the latest version of `prpy`:
|
|
56
54
|
|
|
57
55
|
```
|
|
@@ -15,7 +15,11 @@ authors = [
|
|
|
15
15
|
]
|
|
16
16
|
description = "Collection of Python utils for signal, image, and video processing"
|
|
17
17
|
readme = "README.md"
|
|
18
|
-
|
|
18
|
+
# Upper bound must match the newest version actually tested (main.yml's
|
|
19
|
+
# matrix) and built (release.yml's CIBW_BUILD) - keep all three in sync
|
|
20
|
+
# when adding/dropping a Python version. Without this ceiling, pip will
|
|
21
|
+
# silently attempt an untested sdist build on any newer Python.
|
|
22
|
+
requires-python = ">=3.10,<3.13"
|
|
19
23
|
keywords = ["python", "numpy", "ffmpeg", "tensorflow", "torch"]
|
|
20
24
|
license = {text = "MIT License"}
|
|
21
25
|
classifiers = [
|
|
@@ -23,6 +23,7 @@ from PIL import Image
|
|
|
23
23
|
import os
|
|
24
24
|
import pytest
|
|
25
25
|
import random as rand
|
|
26
|
+
import subprocess
|
|
26
27
|
import tempfile
|
|
27
28
|
from typing import Optional, Union
|
|
28
29
|
|
|
@@ -138,6 +139,19 @@ def sample_video_file(temp_dir):
|
|
|
138
139
|
_ffmpeg_output_to_file(stream, output_dir=temp_dir, output_file=filename, overwrite=True)
|
|
139
140
|
yield os.path.join(temp_dir, filename)
|
|
140
141
|
|
|
142
|
+
@pytest.fixture(scope='session')
|
|
143
|
+
def sample_video_file_no_bframes(temp_dir):
|
|
144
|
+
# H264 with B-frames disabled, for probe_video_frame_timestamps' fast path.
|
|
145
|
+
filename = 'test_no_bframes.mp4'
|
|
146
|
+
path = os.path.join(temp_dir, filename)
|
|
147
|
+
subprocess.run([
|
|
148
|
+
'ffmpeg', '-y', '-v', 'error',
|
|
149
|
+
'-f', 'lavfi', '-i', 'testsrc=size=320x240:rate=25:duration=2',
|
|
150
|
+
'-c:v', 'libx264', '-bf', '0', '-pix_fmt', 'yuv420p',
|
|
151
|
+
path
|
|
152
|
+
], check=True)
|
|
153
|
+
yield path
|
|
154
|
+
|
|
141
155
|
@pytest.fixture(scope='session')
|
|
142
156
|
def sample_video_data():
|
|
143
157
|
# Create sample stream
|
|
@@ -26,7 +26,7 @@ import pytest
|
|
|
26
26
|
import sys
|
|
27
27
|
sys.path.append('../prpy')
|
|
28
28
|
|
|
29
|
-
from prpy.ffmpeg.probe import probe_video
|
|
29
|
+
from prpy.ffmpeg.probe import probe_video, probe_video_frame_timestamps
|
|
30
30
|
from prpy.ffmpeg.readwrite import read_video_from_path
|
|
31
31
|
from prpy.ffmpeg.readwrite import write_video_from_path, write_video_from_numpy
|
|
32
32
|
|
|
@@ -49,6 +49,32 @@ def test_probe_video(sample_video_file):
|
|
|
49
49
|
assert r == SAMPLE_ROTATION
|
|
50
50
|
assert i == SAMPLE_ISSUES
|
|
51
51
|
|
|
52
|
+
def test_probe_video_frame_timestamps_no_bframes_uses_fast_path(sample_video_file_no_bframes, caplog):
|
|
53
|
+
with caplog.at_level("DEBUG"):
|
|
54
|
+
timestamps = probe_video_frame_timestamps(sample_video_file_no_bframes)
|
|
55
|
+
assert "falling back" not in caplog.text
|
|
56
|
+
assert len(timestamps) == 50 # 2s at 25fps
|
|
57
|
+
assert np.all(np.diff(timestamps) > 0)
|
|
58
|
+
np.testing.assert_allclose(timestamps, np.arange(50) / 25., atol=1e-3)
|
|
59
|
+
|
|
60
|
+
def test_probe_video_frame_timestamps_bframes_still_uses_fast_path(sample_video_file, caplog):
|
|
61
|
+
# sample_video_file has B-frames (libx264 defaults); sorting packet pts
|
|
62
|
+
# handles that without needing the decode fallback.
|
|
63
|
+
with caplog.at_level("DEBUG"):
|
|
64
|
+
timestamps = probe_video_frame_timestamps(sample_video_file)
|
|
65
|
+
assert "falling back" not in caplog.text
|
|
66
|
+
assert len(timestamps) == SAMPLE_FRAMES
|
|
67
|
+
assert np.all(np.diff(timestamps) > 0)
|
|
68
|
+
np.testing.assert_allclose(timestamps, np.arange(SAMPLE_FRAMES) / SAMPLE_FPS, atol=1e-3)
|
|
69
|
+
|
|
70
|
+
def test_probe_video_frame_timestamps_sanity_check(sample_video_file_no_bframes, sample_video_file):
|
|
71
|
+
assert len(probe_video_frame_timestamps(sample_video_file_no_bframes, sanity_check=True)) == 50
|
|
72
|
+
assert len(probe_video_frame_timestamps(sample_video_file, sanity_check=True)) == SAMPLE_FRAMES
|
|
73
|
+
|
|
74
|
+
def test_probe_video_frame_timestamps_missing_file():
|
|
75
|
+
with pytest.raises(FileNotFoundError):
|
|
76
|
+
probe_video_frame_timestamps("does_not_exist.mp4")
|
|
77
|
+
|
|
52
78
|
@pytest.mark.parametrize("target_fps", [25., 8.])
|
|
53
79
|
@pytest.mark.parametrize("crop", [None, (256, 94, 416, 214)])
|
|
54
80
|
@pytest.mark.parametrize("scale", [None, 30, (40, 40)])
|
|
@@ -134,6 +134,17 @@ def test_detrend():
|
|
|
134
134
|
[-.0582996, .03747831, -.27848467, .31075766, .33470214]]),
|
|
135
135
|
rtol=1e-6)
|
|
136
136
|
|
|
137
|
+
@pytest.mark.parametrize("T", [3, 4, 10, 500])
|
|
138
|
+
def test_detrend_matches_dense_solution(T):
|
|
139
|
+
rng = np.random.default_rng(T)
|
|
140
|
+
z = np.cumsum(rng.normal(size=(2, T)), axis=1)
|
|
141
|
+
D2 = np.diff(np.identity(T), n=2, axis=0)
|
|
142
|
+
A = np.identity(T) + 25. * D2.T @ D2
|
|
143
|
+
expected = z - np.linalg.solve(A, z.T).T
|
|
144
|
+
np.testing.assert_allclose(detrend(z=z, Lambda=5., axis=-1), expected, rtol=1e-8, atol=1e-10)
|
|
145
|
+
np.testing.assert_allclose(detrend(z=z.T, Lambda=5., axis=0), expected.T, rtol=1e-8, atol=1e-10)
|
|
146
|
+
np.testing.assert_allclose(detrend(z=z[0], Lambda=5.), expected[0], rtol=1e-8, atol=1e-10)
|
|
147
|
+
|
|
137
148
|
def test_detrend_frequency_response():
|
|
138
149
|
# Example from the paper
|
|
139
150
|
f_s = 4
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|