ezmsg-sigproc 1.6.0__tar.gz → 1.7.0__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.
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/PKG-INFO +1 -1
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/__version__.py +2 -2
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/decimate.py +28 -4
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/downsample.py +16 -7
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_decimate.py +7 -6
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_downsample.py +14 -12
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/uv.lock +1 -1
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/.github/workflows/python-publish-ezmsg-sigproc.yml +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/.github/workflows/python-tests.yml +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/.gitignore +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/.pre-commit-config.yaml +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/LICENSE.txt +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/README.md +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/pyproject.toml +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/__init__.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/activation.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/affinetransform.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/aggregate.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/bandpower.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/base.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/butterworthfilter.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/cheby.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/ewmfilter.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/filter.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/filterbank.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/math/__init__.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/math/abs.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/math/clip.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/math/difference.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/math/invert.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/math/log.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/math/scale.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/messages.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/sampler.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/scaler.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/signalinjector.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/slicer.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/spectral.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/spectrogram.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/spectrum.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/synth.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/wavelets.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/src/ezmsg/sigproc/window.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/conftest.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/helpers/__init__.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/helpers/util.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/resources/xform.csv +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_activation.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_affine_transform.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_aggregate.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_bandpower.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_butter.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_butterworth.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_filter_system.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_filterbank.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_math.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_sampler.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_scaler.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_slicer.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_spectrogram.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_spectrum.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_synth.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_wavelets.py +0 -0
- {ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/tests/test_window.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: ezmsg-sigproc
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.0
|
|
4
4
|
Summary: Timeseries signal processing implementations in ezmsg
|
|
5
5
|
Author-email: Griffin Milsap <griffin.milsap@gmail.com>, Preston Peranich <pperanich@gmail.com>, Chadwick Boulay <chadwick.boulay@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -1,8 +1,31 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
1
3
|
import ezmsg.core as ez
|
|
2
4
|
from ezmsg.util.messages.axisarray import AxisArray
|
|
3
5
|
|
|
4
6
|
from .cheby import ChebyshevFilter, ChebyshevFilterSettings
|
|
5
7
|
from .downsample import Downsample, DownsampleSettings
|
|
8
|
+
from .filter import FilterCoefsMultiType
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ChebyForDecimate(ChebyshevFilter):
|
|
12
|
+
"""
|
|
13
|
+
A :obj:`ChebyshevFilter` node with a design filter method that additionally accepts a target sampling rate,
|
|
14
|
+
and if the target rate cannot be achieved it returns None, else it returns the filter coefficients.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def design_filter(
|
|
18
|
+
self,
|
|
19
|
+
) -> typing.Callable[[float], FilterCoefsMultiType | None]:
|
|
20
|
+
def cheby_opt_design_fun(fs: float) -> FilterCoefsMultiType | None:
|
|
21
|
+
if fs is None:
|
|
22
|
+
return None
|
|
23
|
+
ds_factor = int(fs / (2.5 * self.SETTINGS.Wn))
|
|
24
|
+
if ds_factor < 2:
|
|
25
|
+
return None
|
|
26
|
+
partial_fun = super(ChebyForDecimate, self).design_filter()
|
|
27
|
+
return partial_fun(fs)
|
|
28
|
+
return cheby_opt_design_fun
|
|
6
29
|
|
|
7
30
|
|
|
8
31
|
class Decimate(ez.Collection):
|
|
@@ -16,17 +39,18 @@ class Decimate(ez.Collection):
|
|
|
16
39
|
INPUT_SIGNAL = ez.InputStream(AxisArray)
|
|
17
40
|
OUTPUT_SIGNAL = ez.OutputStream(AxisArray)
|
|
18
41
|
|
|
19
|
-
FILTER =
|
|
42
|
+
FILTER = ChebyForDecimate()
|
|
20
43
|
DOWNSAMPLE = Downsample()
|
|
21
44
|
|
|
22
45
|
def configure(self) -> None:
|
|
46
|
+
|
|
23
47
|
cheby_settings = ChebyshevFilterSettings(
|
|
24
|
-
order=8
|
|
48
|
+
order=8,
|
|
25
49
|
ripple_tol=0.05,
|
|
26
|
-
Wn=0.
|
|
50
|
+
Wn=0.4 * self.SETTINGS.target_rate,
|
|
27
51
|
btype="lowpass",
|
|
28
52
|
axis=self.SETTINGS.axis,
|
|
29
|
-
wn_hz=
|
|
53
|
+
wn_hz=True,
|
|
30
54
|
)
|
|
31
55
|
self.FILTER.apply_settings(cheby_settings)
|
|
32
56
|
self.DOWNSAMPLE.apply_settings(self.SETTINGS)
|
|
@@ -14,7 +14,7 @@ from .base import GenAxisArray
|
|
|
14
14
|
|
|
15
15
|
@consumer
|
|
16
16
|
def downsample(
|
|
17
|
-
axis: str | None = None,
|
|
17
|
+
axis: str | None = None, target_rate: float | None = None
|
|
18
18
|
) -> typing.Generator[AxisArray, AxisArray, None]:
|
|
19
19
|
"""
|
|
20
20
|
Construct a generator that yields a downsampled version of the data .send() to it.
|
|
@@ -26,7 +26,8 @@ def downsample(
|
|
|
26
26
|
Args:
|
|
27
27
|
axis: The name of the axis along which to downsample.
|
|
28
28
|
Note: The axis must exist in the message .axes and be of type AxisArray.LinearAxis.
|
|
29
|
-
|
|
29
|
+
target_rate: Desired rate after downsampling. The actual rate will be the nearest integer factor of the
|
|
30
|
+
input rate that is the same or higher than the target rate.
|
|
30
31
|
|
|
31
32
|
Returns:
|
|
32
33
|
A primed generator object ready to receive an :obj:`AxisArray` via `.send(axis_array)`
|
|
@@ -37,10 +38,8 @@ def downsample(
|
|
|
37
38
|
"""
|
|
38
39
|
msg_out = AxisArray(np.array([]), dims=[""])
|
|
39
40
|
|
|
40
|
-
if factor < 1:
|
|
41
|
-
raise ValueError("Downsample factor must be at least 1 (no downsampling)")
|
|
42
|
-
|
|
43
41
|
# state variables
|
|
42
|
+
factor: int = 0 # The integer downsampling factor. It will be determined based on the target rate.
|
|
44
43
|
s_idx: int = 0 # Index of the next msg's first sample into the virtual rotating ds_factor counter.
|
|
45
44
|
|
|
46
45
|
check_input = {"gain": None, "key": None}
|
|
@@ -62,6 +61,16 @@ def downsample(
|
|
|
62
61
|
check_input["key"] = msg_in.key
|
|
63
62
|
# Reset state variables
|
|
64
63
|
s_idx = 0
|
|
64
|
+
if target_rate is None:
|
|
65
|
+
factor = 1
|
|
66
|
+
else:
|
|
67
|
+
factor = int(1 / (axis_info.gain * target_rate))
|
|
68
|
+
if factor < 1:
|
|
69
|
+
ez.logger.warning(
|
|
70
|
+
f"Target rate {target_rate} cannot be achieved with input rate of {1/axis_info.gain}."
|
|
71
|
+
"Setting factor to 1."
|
|
72
|
+
)
|
|
73
|
+
factor = 1
|
|
65
74
|
|
|
66
75
|
n_samples = msg_in.data.shape[axis_idx]
|
|
67
76
|
samples = np.arange(s_idx, s_idx + n_samples) % factor
|
|
@@ -97,7 +106,7 @@ class DownsampleSettings(ez.Settings):
|
|
|
97
106
|
"""
|
|
98
107
|
|
|
99
108
|
axis: str | None = None
|
|
100
|
-
|
|
109
|
+
target_rate: float | None = None
|
|
101
110
|
|
|
102
111
|
|
|
103
112
|
class Downsample(GenAxisArray):
|
|
@@ -107,5 +116,5 @@ class Downsample(GenAxisArray):
|
|
|
107
116
|
|
|
108
117
|
def construct_generator(self):
|
|
109
118
|
self.STATE.gen = downsample(
|
|
110
|
-
axis=self.SETTINGS.axis,
|
|
119
|
+
axis=self.SETTINGS.axis, target_rate=self.SETTINGS.target_rate
|
|
111
120
|
)
|
|
@@ -13,8 +13,8 @@ from ezmsg.sigproc.synth import EEGSynth
|
|
|
13
13
|
from util import get_test_fn
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
@pytest.mark.parametrize("
|
|
17
|
-
def test_decimate_system(
|
|
16
|
+
@pytest.mark.parametrize("target_rate", [100.0, 500.0])
|
|
17
|
+
def test_decimate_system(target_rate: float):
|
|
18
18
|
test_filename = get_test_fn()
|
|
19
19
|
test_filename_raw = test_filename.parent / (
|
|
20
20
|
test_filename.stem + "raw" + test_filename.suffix
|
|
@@ -27,7 +27,7 @@ def test_decimate_system(factor: float):
|
|
|
27
27
|
|
|
28
28
|
comps = {
|
|
29
29
|
"SRC": EEGSynth(n_time=n_time, fs=fs, n_ch=n_ch, alpha_freq=10.5),
|
|
30
|
-
"DECIMATE": Decimate(axis="time",
|
|
30
|
+
"DECIMATE": Decimate(axis="time", target_rate=target_rate),
|
|
31
31
|
"LOGRAW": MessageLogger(output=test_filename_raw),
|
|
32
32
|
"LOGFILT": MessageLogger(output=test_filename),
|
|
33
33
|
"TERM": TerminateOnTotal(n_total),
|
|
@@ -47,13 +47,14 @@ def test_decimate_system(factor: float):
|
|
|
47
47
|
inputs = AxisArray.concatenate(*inputs, dim="time")
|
|
48
48
|
outputs = AxisArray.concatenate(*messages, dim="time")
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
expected_factor: int = int(fs // target_rate)
|
|
51
|
+
if expected_factor == 1:
|
|
51
52
|
expected = inputs.data
|
|
52
53
|
else:
|
|
53
|
-
b, a = scipy.signal.cheby1(8, 0.05, 0.8 /
|
|
54
|
+
b, a = scipy.signal.cheby1(8, 0.05, 0.8 / expected_factor)
|
|
54
55
|
b, a = scipy.signal.normalize(b, a)
|
|
55
56
|
zi = scipy.signal.lfilter_zi(b, a)[:, None]
|
|
56
57
|
antialiased, _ = scipy.signal.lfilter(b, a, inputs.data, axis=0, zi=zi)
|
|
57
|
-
expected = antialiased[:: int(
|
|
58
|
+
expected = antialiased[:: int(expected_factor)]
|
|
58
59
|
|
|
59
60
|
assert np.allclose(outputs.data, expected)
|
|
@@ -20,8 +20,8 @@ from ezmsg.util.debuglog import DebugLog
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
@pytest.mark.parametrize("block_size", [1, 5, 10, 20])
|
|
23
|
-
@pytest.mark.parametrize("
|
|
24
|
-
def test_downsample_core(block_size: int,
|
|
23
|
+
@pytest.mark.parametrize("target_rate", [19.0, 9.5, 6.3])
|
|
24
|
+
def test_downsample_core(block_size: int, target_rate: float):
|
|
25
25
|
in_fs = 19.0
|
|
26
26
|
test_dur = 4.0
|
|
27
27
|
n_channels = 2
|
|
@@ -60,7 +60,7 @@ def test_downsample_core(block_size: int, factor: int):
|
|
|
60
60
|
in_msgs = list(msg_generator())
|
|
61
61
|
backup = [copy.deepcopy(msg) for msg in in_msgs]
|
|
62
62
|
|
|
63
|
-
proc = downsample(axis="time",
|
|
63
|
+
proc = downsample(axis="time", target_rate=target_rate)
|
|
64
64
|
out_msgs = []
|
|
65
65
|
for msg in in_msgs:
|
|
66
66
|
res = proc.send(msg)
|
|
@@ -70,18 +70,19 @@ def test_downsample_core(block_size: int, factor: int):
|
|
|
70
70
|
assert_messages_equal(in_msgs, backup)
|
|
71
71
|
|
|
72
72
|
# Assert correctness of gain
|
|
73
|
-
|
|
73
|
+
expected_factor: int = int(in_fs // target_rate)
|
|
74
|
+
assert all(msg.axes["time"].gain == expected_factor / in_fs for msg in out_msgs)
|
|
74
75
|
|
|
75
76
|
# Assert messages have the correct timestamps
|
|
76
77
|
expected_offsets = (
|
|
77
|
-
np.cumsum([0] + [_.data.shape[0] for _ in out_msgs]) *
|
|
78
|
+
np.cumsum([0] + [_.data.shape[0] for _ in out_msgs]) * expected_factor / in_fs
|
|
78
79
|
)
|
|
79
80
|
actual_offsets = np.array([_.axes["time"].offset for _ in out_msgs])
|
|
80
81
|
assert np.allclose(actual_offsets, expected_offsets[:-1])
|
|
81
82
|
|
|
82
83
|
# Compare returned values to expected values.
|
|
83
84
|
allres_msg = AxisArray.concatenate(*out_msgs, dim="time")
|
|
84
|
-
assert np.array_equal(allres_msg.data, sig[::
|
|
85
|
+
assert np.array_equal(allres_msg.data, sig[::expected_factor])
|
|
85
86
|
|
|
86
87
|
|
|
87
88
|
class DownsampleSystemSettings(ez.Settings):
|
|
@@ -130,8 +131,8 @@ class DownsampleSystem(ez.Collection):
|
|
|
130
131
|
|
|
131
132
|
|
|
132
133
|
@pytest.mark.parametrize("block_size", [10])
|
|
133
|
-
@pytest.mark.parametrize("
|
|
134
|
-
def test_downsample_system(block_size: int,
|
|
134
|
+
@pytest.mark.parametrize("target_rate", [6.3])
|
|
135
|
+
def test_downsample_system(block_size: int, target_rate: float, test_name: str | None = None):
|
|
135
136
|
in_fs = 19.0
|
|
136
137
|
num_msgs = int(4.0 / (block_size / in_fs)) # Ensure 4 seconds of data
|
|
137
138
|
|
|
@@ -145,7 +146,7 @@ def test_downsample_system(block_size: int, factor: int, test_name: str | None =
|
|
|
145
146
|
fs=in_fs,
|
|
146
147
|
dispatch_rate=20.0,
|
|
147
148
|
),
|
|
148
|
-
down_settings=DownsampleSettings(
|
|
149
|
+
down_settings=DownsampleSettings(target_rate=target_rate),
|
|
149
150
|
log_settings=MessageLoggerSettings(output=test_filename),
|
|
150
151
|
term_settings=TerminateTestSettings(time=1.0),
|
|
151
152
|
)
|
|
@@ -159,7 +160,8 @@ def test_downsample_system(block_size: int, factor: int, test_name: str | None =
|
|
|
159
160
|
ez.logger.info(f"Analyzing recording of { len( messages ) } messages...")
|
|
160
161
|
|
|
161
162
|
# Check fs
|
|
162
|
-
|
|
163
|
+
expected_factor: int = int(in_fs // target_rate)
|
|
164
|
+
out_fs = in_fs / expected_factor
|
|
163
165
|
assert np.allclose(
|
|
164
166
|
np.array([1 / msg.axes["time"].gain for msg in messages]),
|
|
165
167
|
np.ones(
|
|
@@ -173,7 +175,7 @@ def test_downsample_system(block_size: int, factor: int, test_name: str | None =
|
|
|
173
175
|
# Check data
|
|
174
176
|
time_ax_idx = messages[0].get_axis_idx("time")
|
|
175
177
|
data = np.concatenate([_.data for _ in messages], axis=time_ax_idx)
|
|
176
|
-
expected_data = np.arange(data.shape[time_ax_idx]) *
|
|
178
|
+
expected_data = np.arange(data.shape[time_ax_idx]) * expected_factor
|
|
177
179
|
assert np.array_equal(data, expected_data[:, None])
|
|
178
180
|
|
|
179
181
|
# Grab first sample from each message. We will use their values to get the offsets.
|
|
@@ -185,7 +187,7 @@ def test_downsample_system(block_size: int, factor: int, test_name: str | None =
|
|
|
185
187
|
|
|
186
188
|
# Check offsets
|
|
187
189
|
first_samps = np.concatenate(first_samps, axis=time_ax_idx)
|
|
188
|
-
expected_offsets = first_samps.squeeze() / out_fs /
|
|
190
|
+
expected_offsets = first_samps.squeeze() / out_fs / expected_factor
|
|
189
191
|
assert np.allclose(
|
|
190
192
|
np.array([msg.axes["time"].offset for msg in messages]), expected_offsets
|
|
191
193
|
)
|
{ezmsg_sigproc-1.6.0 → ezmsg_sigproc-1.7.0}/.github/workflows/python-publish-ezmsg-sigproc.yml
RENAMED
|
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
|