ezmsg-sigproc 1.4.2__py3-none-any.whl → 1.6.0__py3-none-any.whl
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/__version__.py +2 -2
- ezmsg/sigproc/activation.py +2 -2
- ezmsg/sigproc/affinetransform.py +13 -13
- ezmsg/sigproc/aggregate.py +49 -28
- ezmsg/sigproc/bandpower.py +2 -2
- ezmsg/sigproc/butterworthfilter.py +89 -90
- ezmsg/sigproc/cheby.py +119 -0
- ezmsg/sigproc/decimate.py +11 -15
- ezmsg/sigproc/downsample.py +8 -4
- ezmsg/sigproc/ewmfilter.py +9 -5
- ezmsg/sigproc/filter.py +82 -115
- ezmsg/sigproc/filterbank.py +5 -5
- ezmsg/sigproc/math/abs.py +1 -1
- ezmsg/sigproc/math/clip.py +1 -1
- ezmsg/sigproc/math/difference.py +1 -1
- ezmsg/sigproc/math/invert.py +1 -1
- ezmsg/sigproc/math/log.py +1 -1
- ezmsg/sigproc/math/scale.py +1 -1
- ezmsg/sigproc/messages.py +2 -3
- ezmsg/sigproc/sampler.py +16 -15
- ezmsg/sigproc/scaler.py +153 -35
- ezmsg/sigproc/signalinjector.py +7 -7
- ezmsg/sigproc/slicer.py +34 -14
- ezmsg/sigproc/spectrogram.py +6 -6
- ezmsg/sigproc/spectrum.py +18 -14
- ezmsg/sigproc/synth.py +43 -27
- ezmsg/sigproc/wavelets.py +42 -17
- ezmsg/sigproc/window.py +14 -13
- {ezmsg_sigproc-1.4.2.dist-info → ezmsg_sigproc-1.6.0.dist-info}/METADATA +4 -5
- ezmsg_sigproc-1.6.0.dist-info/RECORD +36 -0
- {ezmsg_sigproc-1.4.2.dist-info → ezmsg_sigproc-1.6.0.dist-info}/WHEEL +1 -1
- ezmsg_sigproc-1.4.2.dist-info/RECORD +0 -35
- {ezmsg_sigproc-1.4.2.dist-info → ezmsg_sigproc-1.6.0.dist-info}/licenses/LICENSE.txt +0 -0
ezmsg/sigproc/synth.py
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
from dataclasses import
|
|
2
|
+
from dataclasses import field
|
|
3
3
|
import time
|
|
4
|
-
|
|
4
|
+
import typing
|
|
5
5
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
import ezmsg.core as ez
|
|
8
8
|
from ezmsg.util.generator import consumer
|
|
9
9
|
from ezmsg.util.messages.axisarray import AxisArray
|
|
10
|
+
from ezmsg.util.messages.util import replace
|
|
10
11
|
|
|
11
12
|
from .butterworthfilter import ButterworthFilter, ButterworthFilterSettings
|
|
12
13
|
from .base import GenAxisArray
|
|
13
14
|
|
|
14
15
|
|
|
15
|
-
def clock(dispatch_rate:
|
|
16
|
+
def clock(dispatch_rate: float | None) -> typing.Generator[ez.Flag, None, None]:
|
|
16
17
|
"""
|
|
17
18
|
Construct a generator that yields events at a specified rate.
|
|
18
19
|
|
|
@@ -32,7 +33,7 @@ def clock(dispatch_rate: Optional[float]) -> Generator[ez.Flag, None, None]:
|
|
|
32
33
|
yield ez.Flag()
|
|
33
34
|
|
|
34
35
|
|
|
35
|
-
async def aclock(dispatch_rate:
|
|
36
|
+
async def aclock(dispatch_rate: float | None) -> typing.AsyncGenerator[ez.Flag, None]:
|
|
36
37
|
"""
|
|
37
38
|
``asyncio`` version of :obj:`clock`.
|
|
38
39
|
|
|
@@ -53,12 +54,12 @@ class ClockSettings(ez.Settings):
|
|
|
53
54
|
"""Settings for :obj:`Clock`. See :obj:`clock` for parameter description."""
|
|
54
55
|
|
|
55
56
|
# Message dispatch rate (Hz), or None (fast as possible)
|
|
56
|
-
dispatch_rate:
|
|
57
|
+
dispatch_rate: float | None
|
|
57
58
|
|
|
58
59
|
|
|
59
60
|
class ClockState(ez.State):
|
|
60
61
|
cur_settings: ClockSettings
|
|
61
|
-
gen: AsyncGenerator
|
|
62
|
+
gen: typing.AsyncGenerator
|
|
62
63
|
|
|
63
64
|
|
|
64
65
|
class Clock(ez.Unit):
|
|
@@ -83,7 +84,7 @@ class Clock(ez.Unit):
|
|
|
83
84
|
self.construct_generator()
|
|
84
85
|
|
|
85
86
|
@ez.publisher(OUTPUT_CLOCK)
|
|
86
|
-
async def generate(self) -> AsyncGenerator:
|
|
87
|
+
async def generate(self) -> typing.AsyncGenerator:
|
|
87
88
|
while True:
|
|
88
89
|
out = await self.STATE.gen.__anext__()
|
|
89
90
|
if out:
|
|
@@ -93,11 +94,11 @@ class Clock(ez.Unit):
|
|
|
93
94
|
# COUNTER - Generate incrementing integer. fs and dispatch_rate parameters combine to give many options. #
|
|
94
95
|
async def acounter(
|
|
95
96
|
n_time: int,
|
|
96
|
-
fs:
|
|
97
|
+
fs: float | None,
|
|
97
98
|
n_ch: int = 1,
|
|
98
|
-
dispatch_rate:
|
|
99
|
-
mod:
|
|
100
|
-
) -> AsyncGenerator[AxisArray, None]:
|
|
99
|
+
dispatch_rate: float | str | None = None,
|
|
100
|
+
mod: int | None = None,
|
|
101
|
+
) -> typing.AsyncGenerator[AxisArray, None]:
|
|
101
102
|
"""
|
|
102
103
|
Construct an asynchronous generator to generate AxisArray objects at a specified rate
|
|
103
104
|
and with the specified sampling rate.
|
|
@@ -138,6 +139,17 @@ async def acounter(
|
|
|
138
139
|
|
|
139
140
|
n_sent: int = 0 # It is convenient to know how many samples we have sent.
|
|
140
141
|
clock_zero: float = time.time() # time associated with first sample
|
|
142
|
+
template = AxisArray(
|
|
143
|
+
data=np.array([[]]),
|
|
144
|
+
dims=["time", "ch"],
|
|
145
|
+
axes={
|
|
146
|
+
"time": AxisArray.TimeAxis(fs=fs),
|
|
147
|
+
"ch": AxisArray.CoordinateAxis(
|
|
148
|
+
data=np.array([f"Ch{_}" for _ in range(n_ch)]), dims=["ch"]
|
|
149
|
+
),
|
|
150
|
+
},
|
|
151
|
+
key="acounter",
|
|
152
|
+
)
|
|
141
153
|
|
|
142
154
|
while True:
|
|
143
155
|
# 1. Sleep, if necessary, until we are at the end of the current block
|
|
@@ -167,10 +179,13 @@ async def acounter(
|
|
|
167
179
|
# offset += clock_zero # ??
|
|
168
180
|
|
|
169
181
|
# 4. yield output
|
|
170
|
-
yield
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
axes={
|
|
182
|
+
yield replace(
|
|
183
|
+
template,
|
|
184
|
+
data=block_samp,
|
|
185
|
+
axes={
|
|
186
|
+
"time": replace(template.axes["time"], offset=offset),
|
|
187
|
+
"ch": template.axes["ch"],
|
|
188
|
+
},
|
|
174
189
|
)
|
|
175
190
|
|
|
176
191
|
# 5. Update state for next iteration (after next yield)
|
|
@@ -192,14 +207,14 @@ class CounterSettings(ez.Settings):
|
|
|
192
207
|
# Message dispatch rate (Hz), 'realtime', 'ext_clock', or None (fast as possible)
|
|
193
208
|
# Note: if dispatch_rate is a float then time offsets will be synthetic and the
|
|
194
209
|
# system will run faster or slower than wall clock time.
|
|
195
|
-
dispatch_rate:
|
|
210
|
+
dispatch_rate: float | str | None = None
|
|
196
211
|
|
|
197
212
|
# If set to an integer, counter will rollover
|
|
198
|
-
mod:
|
|
213
|
+
mod: int | None = None
|
|
199
214
|
|
|
200
215
|
|
|
201
216
|
class CounterState(ez.State):
|
|
202
|
-
gen: AsyncGenerator[AxisArray,
|
|
217
|
+
gen: typing.AsyncGenerator[AxisArray, ez.Flag | None]
|
|
203
218
|
cur_settings: CounterSettings
|
|
204
219
|
new_generator: asyncio.Event
|
|
205
220
|
|
|
@@ -248,7 +263,7 @@ class Counter(ez.Unit):
|
|
|
248
263
|
yield self.OUTPUT_SIGNAL, out
|
|
249
264
|
|
|
250
265
|
@ez.publisher(OUTPUT_SIGNAL)
|
|
251
|
-
async def run_generator(self) -> AsyncGenerator:
|
|
266
|
+
async def run_generator(self) -> typing.AsyncGenerator:
|
|
252
267
|
while True:
|
|
253
268
|
await self.STATE.new_generator.wait()
|
|
254
269
|
self.STATE.new_generator.clear()
|
|
@@ -263,16 +278,17 @@ class Counter(ez.Unit):
|
|
|
263
278
|
|
|
264
279
|
@consumer
|
|
265
280
|
def sin(
|
|
266
|
-
axis:
|
|
281
|
+
axis: str | None = "time",
|
|
267
282
|
freq: float = 1.0,
|
|
268
283
|
amp: float = 1.0,
|
|
269
284
|
phase: float = 0.0,
|
|
270
|
-
) -> Generator[AxisArray, AxisArray, None]:
|
|
285
|
+
) -> typing.Generator[AxisArray, AxisArray, None]:
|
|
271
286
|
"""
|
|
272
287
|
Construct a generator of sinusoidal waveforms in AxisArray objects.
|
|
273
288
|
|
|
274
289
|
Args:
|
|
275
290
|
axis: The name of the axis over which the sinusoid passes.
|
|
291
|
+
Note: The axis must exist in the msg.axes and be of type AxisArray.LinearAxis.
|
|
276
292
|
freq: The frequency of the sinusoid, in Hz.
|
|
277
293
|
amp: The amplitude of the sinusoid.
|
|
278
294
|
phase: The initial phase of the sinusoid, in radians.
|
|
@@ -304,7 +320,7 @@ class SinGeneratorSettings(ez.Settings):
|
|
|
304
320
|
See :obj:`sin` for parameter descriptions.
|
|
305
321
|
"""
|
|
306
322
|
|
|
307
|
-
time_axis:
|
|
323
|
+
time_axis: str | None = "time"
|
|
308
324
|
freq: float = 1.0 # Oscillation frequency in Hz
|
|
309
325
|
amp: float = 1.0 # Amplitude
|
|
310
326
|
phase: float = 0.0 # Phase offset (in radians)
|
|
@@ -338,7 +354,7 @@ class OscillatorSettings(ez.Settings):
|
|
|
338
354
|
n_ch: int = 1
|
|
339
355
|
"""Number of channels to output per block"""
|
|
340
356
|
|
|
341
|
-
dispatch_rate:
|
|
357
|
+
dispatch_rate: float | str | None = None
|
|
342
358
|
"""(Hz) | 'realtime' | 'ext_clock'"""
|
|
343
359
|
|
|
344
360
|
freq: float = 1.0
|
|
@@ -420,7 +436,7 @@ class RandomGenerator(ez.Unit):
|
|
|
420
436
|
|
|
421
437
|
@ez.subscriber(INPUT_SIGNAL)
|
|
422
438
|
@ez.publisher(OUTPUT_SIGNAL)
|
|
423
|
-
async def generate(self, msg: AxisArray) -> AsyncGenerator:
|
|
439
|
+
async def generate(self, msg: AxisArray) -> typing.AsyncGenerator:
|
|
424
440
|
random_data = np.random.normal(
|
|
425
441
|
size=msg.shape, loc=self.SETTINGS.loc, scale=self.SETTINGS.scale
|
|
426
442
|
)
|
|
@@ -436,7 +452,7 @@ class NoiseSettings(ez.Settings):
|
|
|
436
452
|
n_time: int # Number of samples to output per block
|
|
437
453
|
fs: float # Sampling rate of signal output in Hz
|
|
438
454
|
n_ch: int = 1 # Number of channels to output
|
|
439
|
-
dispatch_rate:
|
|
455
|
+
dispatch_rate: float | str | None = None
|
|
440
456
|
"""(Hz), 'realtime', or 'ext_clock'"""
|
|
441
457
|
loc: float = 0.0 # DC offset
|
|
442
458
|
scale: float = 1.0 # Scale (in standard deviations)
|
|
@@ -538,12 +554,12 @@ class Add(ez.Unit):
|
|
|
538
554
|
self.STATE.queue_b.put_nowait(msg)
|
|
539
555
|
|
|
540
556
|
@ez.publisher(OUTPUT_SIGNAL)
|
|
541
|
-
async def output(self) -> AsyncGenerator:
|
|
557
|
+
async def output(self) -> typing.AsyncGenerator:
|
|
542
558
|
while True:
|
|
543
559
|
a = await self.STATE.queue_a.get()
|
|
544
560
|
b = await self.STATE.queue_b.get()
|
|
545
561
|
|
|
546
|
-
yield
|
|
562
|
+
yield self.OUTPUT_SIGNAL, replace(a, data=a.data + b.data)
|
|
547
563
|
|
|
548
564
|
|
|
549
565
|
class EEGSynthSettings(ez.Settings):
|
ezmsg/sigproc/wavelets.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from dataclasses import replace
|
|
2
1
|
import typing
|
|
3
2
|
|
|
4
3
|
import numpy as np
|
|
@@ -6,6 +5,7 @@ import numpy.typing as npt
|
|
|
6
5
|
import pywt
|
|
7
6
|
import ezmsg.core as ez
|
|
8
7
|
from ezmsg.util.messages.axisarray import AxisArray
|
|
8
|
+
from ezmsg.util.messages.util import replace
|
|
9
9
|
from ezmsg.util.generator import consumer
|
|
10
10
|
|
|
11
11
|
from .base import GenAxisArray
|
|
@@ -14,43 +14,61 @@ from .filterbank import filterbank, FilterbankMode, MinPhaseMode
|
|
|
14
14
|
|
|
15
15
|
@consumer
|
|
16
16
|
def cwt(
|
|
17
|
-
|
|
18
|
-
wavelet:
|
|
17
|
+
frequencies: list | tuple | npt.NDArray | None,
|
|
18
|
+
wavelet: str | pywt.ContinuousWavelet | pywt.Wavelet,
|
|
19
19
|
min_phase: MinPhaseMode = MinPhaseMode.NONE,
|
|
20
20
|
axis: str = "time",
|
|
21
|
+
scales: list | tuple | npt.NDArray | None = None,
|
|
21
22
|
) -> typing.Generator[AxisArray, AxisArray, None]:
|
|
22
23
|
"""
|
|
23
24
|
Perform a continuous wavelet transform.
|
|
24
25
|
The function is equivalent to the :obj:`pywt.cwt` function, but is designed to work with streaming data.
|
|
25
26
|
|
|
26
27
|
Args:
|
|
27
|
-
|
|
28
|
+
frequencies: The wavelet frequencies to use in Hz. If `None` provided then the scales will be used.
|
|
29
|
+
Note: frequencies will be sorted from smallest to largest.
|
|
28
30
|
wavelet: Wavelet object or name of wavelet to use.
|
|
29
31
|
min_phase: See filterbank MinPhaseMode for details.
|
|
30
32
|
axis: The target axis for operation. Note that this will be moved to the -1th dimension
|
|
31
33
|
because fft and matrix multiplication is much faster on the last axis.
|
|
34
|
+
This axis must be in the msg.axes and it must be of type AxisArray.LinearAxis.
|
|
35
|
+
scales: The scales to use. If None, the scales will be calculated from the frequencies.
|
|
36
|
+
Note: Scales will be sorted from largest to smallest.
|
|
37
|
+
Note: Use of scales is deprecated in favor of frequencies. Convert scales to frequencies using
|
|
38
|
+
`pywt.scale2frequency(wavelet, scales, precision=10) * fs` where fs is the sampling frequency.
|
|
32
39
|
|
|
33
40
|
Returns:
|
|
34
41
|
A primed Generator object that expects an :obj:`AxisArray` via `.send(axis_array)` of continuous data
|
|
35
42
|
and yields an :obj:`AxisArray` with a continuous wavelet transform in its data.
|
|
36
43
|
"""
|
|
37
|
-
|
|
44
|
+
precision = 10
|
|
45
|
+
msg_out: AxisArray | None = None
|
|
38
46
|
|
|
39
47
|
# Check parameters
|
|
40
|
-
scales
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
if frequencies is None and scales is None:
|
|
49
|
+
raise ValueError("Either frequencies or scales must be provided.")
|
|
50
|
+
if frequencies is not None and scales is not None:
|
|
51
|
+
raise ValueError("Only one of frequencies or scales can be provided.")
|
|
52
|
+
if scales is not None:
|
|
53
|
+
scales = np.sort(scales)[::-1]
|
|
54
|
+
assert np.all(scales > 0), "scales must be positive."
|
|
55
|
+
assert scales.ndim == 1, "scales must be a 1D list, tuple, or array."
|
|
56
|
+
|
|
43
57
|
if not isinstance(wavelet, (pywt.ContinuousWavelet, pywt.Wavelet)):
|
|
44
58
|
wavelet = pywt.DiscreteContinuousWavelet(wavelet)
|
|
45
|
-
|
|
59
|
+
|
|
60
|
+
if frequencies is not None:
|
|
61
|
+
frequencies = np.sort(frequencies)
|
|
62
|
+
assert np.all(frequencies > 0), "frequencies must be positive."
|
|
63
|
+
assert frequencies.ndim == 1, "frequencies must be a 1D list, tuple, or array."
|
|
46
64
|
|
|
47
65
|
# State variables
|
|
48
|
-
neg_rt_scales
|
|
66
|
+
neg_rt_scales: npt.NDArray | None = None
|
|
49
67
|
int_psi, wave_xvec = pywt.integrate_wavelet(wavelet, precision=precision)
|
|
50
68
|
int_psi = np.conj(int_psi) if wavelet.complex_cwt else int_psi
|
|
51
|
-
template:
|
|
52
|
-
fbgen: typing.
|
|
53
|
-
last_conv_samp:
|
|
69
|
+
template: AxisArray | None = None
|
|
70
|
+
fbgen: typing.Generator[AxisArray, AxisArray, None] | None = None
|
|
71
|
+
last_conv_samp: npt.NDArray | None = None
|
|
54
72
|
|
|
55
73
|
# Reset if input changed
|
|
56
74
|
check_input = {
|
|
@@ -76,6 +94,12 @@ def cwt(
|
|
|
76
94
|
check_input["shape"] = in_shape
|
|
77
95
|
check_input["key"] = msg_in.key
|
|
78
96
|
|
|
97
|
+
if frequencies is not None:
|
|
98
|
+
scales = pywt.frequency2scale(
|
|
99
|
+
wavelet, frequencies * msg_in.axes[axis].gain, precision=precision
|
|
100
|
+
)
|
|
101
|
+
neg_rt_scales = -np.sqrt(scales)[:, None]
|
|
102
|
+
|
|
79
103
|
# convert int_psi, wave_xvec to the same precision as the data
|
|
80
104
|
dt_data = msg_in.data.dtype # _check_dtype(msg_in.data)
|
|
81
105
|
dt_cplx = np.result_type(dt_data, np.complex64)
|
|
@@ -103,7 +127,6 @@ def cwt(
|
|
|
103
127
|
pywt.scale2frequency(wavelet, scales, precision)
|
|
104
128
|
/ msg_in.axes[axis].gain
|
|
105
129
|
)
|
|
106
|
-
fstep = (freqs[1] - freqs[0]) if len(freqs) > 1 else 1.0
|
|
107
130
|
# Create output template
|
|
108
131
|
dummy_shape = in_shape + (len(scales), 0)
|
|
109
132
|
template = AxisArray(
|
|
@@ -113,7 +136,9 @@ def cwt(
|
|
|
113
136
|
dims=msg_in.dims[:ax_idx] + msg_in.dims[ax_idx + 1 :] + ["freq", axis],
|
|
114
137
|
axes={
|
|
115
138
|
**msg_in.axes,
|
|
116
|
-
"freq": AxisArray.
|
|
139
|
+
"freq": AxisArray.CoordinateAxis(
|
|
140
|
+
unit="Hz", data=freqs, dims=["freq"]
|
|
141
|
+
),
|
|
117
142
|
},
|
|
118
143
|
key=msg_in.key,
|
|
119
144
|
)
|
|
@@ -147,8 +172,8 @@ class CWTSettings(ez.Settings):
|
|
|
147
172
|
See :obj:`cwt` for argument details.
|
|
148
173
|
"""
|
|
149
174
|
|
|
150
|
-
scales:
|
|
151
|
-
wavelet:
|
|
175
|
+
scales: list | tuple | npt.NDArray
|
|
176
|
+
wavelet: str | pywt.ContinuousWavelet | pywt.Wavelet
|
|
152
177
|
min_phase: MinPhaseMode = MinPhaseMode.NONE
|
|
153
178
|
axis: str = "time"
|
|
154
179
|
|
ezmsg/sigproc/window.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from dataclasses import replace
|
|
2
1
|
import traceback
|
|
3
2
|
import typing
|
|
4
3
|
|
|
@@ -9,6 +8,7 @@ from ezmsg.util.messages.axisarray import (
|
|
|
9
8
|
AxisArray,
|
|
10
9
|
slice_along_axis,
|
|
11
10
|
sliding_win_oneaxis,
|
|
11
|
+
replace,
|
|
12
12
|
)
|
|
13
13
|
from ezmsg.util.generator import consumer
|
|
14
14
|
|
|
@@ -17,10 +17,10 @@ from .base import GenAxisArray
|
|
|
17
17
|
|
|
18
18
|
@consumer
|
|
19
19
|
def windowing(
|
|
20
|
-
axis:
|
|
20
|
+
axis: str | None = None,
|
|
21
21
|
newaxis: str = "win",
|
|
22
|
-
window_dur:
|
|
23
|
-
window_shift:
|
|
22
|
+
window_dur: float | None = None,
|
|
23
|
+
window_shift: float | None = None,
|
|
24
24
|
zero_pad_until: str = "input",
|
|
25
25
|
) -> typing.Generator[AxisArray, AxisArray, None]:
|
|
26
26
|
"""
|
|
@@ -31,6 +31,7 @@ def windowing(
|
|
|
31
31
|
Args:
|
|
32
32
|
axis: The axis along which to segment windows.
|
|
33
33
|
If None, defaults to the first dimension of the first seen AxisArray.
|
|
34
|
+
Note: The windowed axis must be an AxisArray.LinearAxis, not an AxisArray.CoordinateAxis.
|
|
34
35
|
newaxis: New axis on which windows are delimited, immediately
|
|
35
36
|
preceding the target windowed axis. The data length along newaxis may be 0 if
|
|
36
37
|
this most recent push did not provide enough data for a new window.
|
|
@@ -71,15 +72,15 @@ def windowing(
|
|
|
71
72
|
msg_out = AxisArray(np.array([]), dims=[""])
|
|
72
73
|
|
|
73
74
|
# State variables
|
|
74
|
-
buffer:
|
|
75
|
-
window_samples:
|
|
76
|
-
window_shift_samples:
|
|
75
|
+
buffer: npt.NDArray | None = None
|
|
76
|
+
window_samples: int | None = None
|
|
77
|
+
window_shift_samples: int | None = None
|
|
77
78
|
# Number of incoming samples to ignore. Only relevant when shift > window.:
|
|
78
79
|
shift_deficit: int = 0
|
|
79
80
|
b_1to1 = window_shift is None
|
|
80
81
|
newaxis_warned: bool = b_1to1
|
|
81
|
-
out_newaxis:
|
|
82
|
-
out_dims:
|
|
82
|
+
out_newaxis: AxisArray.LinearAxis | None = None
|
|
83
|
+
out_dims: list[str] | None = None
|
|
83
84
|
|
|
84
85
|
check_inputs = {"samp_shape": None, "fs": None, "key": None}
|
|
85
86
|
|
|
@@ -215,10 +216,10 @@ def windowing(
|
|
|
215
216
|
|
|
216
217
|
|
|
217
218
|
class WindowSettings(ez.Settings):
|
|
218
|
-
axis:
|
|
219
|
-
newaxis:
|
|
220
|
-
window_dur:
|
|
221
|
-
window_shift:
|
|
219
|
+
axis: str | None = None
|
|
220
|
+
newaxis: str | None = None # new axis for output. No new axes if None
|
|
221
|
+
window_dur: float | None = None # Sec. passthrough if None
|
|
222
|
+
window_shift: float | None = None # Sec. Use "1:1 mode" if None
|
|
222
223
|
zero_pad_until: str = "full" # "full", "shift", "input", "none"
|
|
223
224
|
|
|
224
225
|
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: ezmsg-sigproc
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.6.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
|
-
License
|
|
7
|
-
|
|
8
|
-
Requires-
|
|
9
|
-
Requires-Dist: ezmsg>=3.5.0
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.10.15
|
|
8
|
+
Requires-Dist: ezmsg>=3.6.0
|
|
10
9
|
Requires-Dist: numpy>=1.26.0
|
|
11
10
|
Requires-Dist: pywavelets>=1.6.0
|
|
12
11
|
Requires-Dist: scipy>=1.13.1
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
ezmsg/sigproc/__init__.py,sha256=8K4IcOA3-pfzadoM6s2Sfg5460KlJUocGgyTJTJl96U,52
|
|
2
|
+
ezmsg/sigproc/__version__.py,sha256=Ry70pc5l-IBhT9gahlkNwZPp4g0CzVEWqsat9H-UASY,411
|
|
3
|
+
ezmsg/sigproc/activation.py,sha256=LM-MtaNvFvmBZ1_EPNu--4K3-wIzsb7CUQ00fvMM69g,2642
|
|
4
|
+
ezmsg/sigproc/affinetransform.py,sha256=R2P1f5JdNSpr30x8Pxoqv-J-nAasGl_UZR8o7sVqlaQ,8740
|
|
5
|
+
ezmsg/sigproc/aggregate.py,sha256=6BqAujWe7_zzGPDJz7yh4ofPzJTU5z2lrclX-IuqXDU,6235
|
|
6
|
+
ezmsg/sigproc/bandpower.py,sha256=Mx8iUU-UMWKK5sgCXvxpUSA3522rW8Jg96asrT8MdpA,2180
|
|
7
|
+
ezmsg/sigproc/base.py,sha256=vut0BLjgc0mxYRbs7tDd9XzwRFA2_GcsgXZmIYovR0Y,1248
|
|
8
|
+
ezmsg/sigproc/butterworthfilter.py,sha256=vZTY37FfLwa24bRZmeZGyO5323824wJosUrrZarb0_o,5402
|
|
9
|
+
ezmsg/sigproc/cheby.py,sha256=yds5y1fOeBE1ljyH_EreBLxqFX4UetxB_3rwz3omHyc,3394
|
|
10
|
+
ezmsg/sigproc/decimate.py,sha256=Cu2weOIKGoo_pUSpA90N47kuzcT6s7OAa1HaF7u3cY0,1286
|
|
11
|
+
ezmsg/sigproc/downsample.py,sha256=oJ0VOZ0UrLAhce2bolSom23LD8Ob-8LCOmzqkrZCJ0E,3454
|
|
12
|
+
ezmsg/sigproc/ewmfilter.py,sha256=EPlocRdKORj575VV1YUzcNsVcq-pYgdEJ7_m9WfpVnY,4795
|
|
13
|
+
ezmsg/sigproc/filter.py,sha256=n3_gColSPXe4pI-A2VDKfrdFHZgC-k4kqB8H6tnGIws,6969
|
|
14
|
+
ezmsg/sigproc/filterbank.py,sha256=pySLNGppnG6Dx9r5jQpNSyWhd9qmvj6up2udG7RMNok,12410
|
|
15
|
+
ezmsg/sigproc/messages.py,sha256=y_twVPK7TxRj8ajmuSuBuxwvLTgyv9OF7Y7v9bw1tfs,926
|
|
16
|
+
ezmsg/sigproc/sampler.py,sha256=ljZuToiC5p4Jx2cJPXJ4tOtv3nBOBGMEaz7ad7Nec8U,12735
|
|
17
|
+
ezmsg/sigproc/scaler.py,sha256=5uCgVbZHV9iCsAVnc9Pz7hKIXnaIiA9ssiTCce_QHlU,9550
|
|
18
|
+
ezmsg/sigproc/signalinjector.py,sha256=-_cln7Ljny0WWrjBV3HZhhONLEkEphsgLS30AWlxcOE,2590
|
|
19
|
+
ezmsg/sigproc/slicer.py,sha256=n6JGOkkY2ur5K1STsLQDSvFhEjT2ZLiSxmggK6qEmpc,5731
|
|
20
|
+
ezmsg/sigproc/spectral.py,sha256=_2qO6as4Nesmc9V1WW2EXNMH5pPz8aVTEcIPOi4-g2o,322
|
|
21
|
+
ezmsg/sigproc/spectrogram.py,sha256=Xc3zXKjVwG0-NLzKEsVKv253Sk50t2U1SlqEJ_ll36k,3086
|
|
22
|
+
ezmsg/sigproc/spectrum.py,sha256=ZhsWlxUiTaWc8qgNZ5NWqsU_fNmjb4V5532mNA8Bd5Y,9396
|
|
23
|
+
ezmsg/sigproc/synth.py,sha256=kobTQwAyiNZLbpJIUNxI6SOiuKm0aca2G5pSjuB4K9E,18823
|
|
24
|
+
ezmsg/sigproc/wavelets.py,sha256=bwlqyUESrOWAiI_gECbaKJj0PflnFMmuYtNridBTfNs,7955
|
|
25
|
+
ezmsg/sigproc/window.py,sha256=eIxdtni6BwDmpko6m_WJnUDO3VHb5y7jM6nU9WyzIsM,13056
|
|
26
|
+
ezmsg/sigproc/math/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
+
ezmsg/sigproc/math/abs.py,sha256=Hjnn2x8djWLUDVqvxRC4V7jOvgEtdU6CCHGpfVZ0uOY,931
|
|
28
|
+
ezmsg/sigproc/math/clip.py,sha256=UpFLP_IkrY6bo4WcIpO4Czbttg7n6hybAihOGy-3nGs,1144
|
|
29
|
+
ezmsg/sigproc/math/difference.py,sha256=I96Md2pyfCU5TSw35u1uS6FaPJRv0JpHQVhrTHv1BQ0,2196
|
|
30
|
+
ezmsg/sigproc/math/invert.py,sha256=T6PEhBCquKRJQF6LfUgqjXKSBsS_tvi4BJAqJ_5VCjw,895
|
|
31
|
+
ezmsg/sigproc/math/log.py,sha256=i-iF2WDH18RWapYwlhAsiDdhzvuJY9mDWrNtjfuiyL8,1572
|
|
32
|
+
ezmsg/sigproc/math/scale.py,sha256=lQKF02Mv9nTWfgc4OcMpQMCx993p57GSN-AADeO2fjY,1063
|
|
33
|
+
ezmsg_sigproc-1.6.0.dist-info/METADATA,sha256=-Y0s91NhAEO_KWsBo1KQKPQE4IDyU-xp51rOa8FuUAo,2343
|
|
34
|
+
ezmsg_sigproc-1.6.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
|
35
|
+
ezmsg_sigproc-1.6.0.dist-info/licenses/LICENSE.txt,sha256=seu0tKhhAMPCUgc1XpXGGaCxY1YaYvFJwqFuQZAl2go,1100
|
|
36
|
+
ezmsg_sigproc-1.6.0.dist-info/RECORD,,
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
ezmsg/sigproc/__init__.py,sha256=8K4IcOA3-pfzadoM6s2Sfg5460KlJUocGgyTJTJl96U,52
|
|
2
|
-
ezmsg/sigproc/__version__.py,sha256=tX44urJsC0QN5SJ51xsM0HeojA_8Xx7NXFEGAkYlNE4,411
|
|
3
|
-
ezmsg/sigproc/activation.py,sha256=amvVjO-1BcChgK0VQi44i7-Tmz_2FK1xb-BTC52_DO0,2642
|
|
4
|
-
ezmsg/sigproc/affinetransform.py,sha256=a5xt6LSymlV3gNSdCjWdtUoi9kOkWiYx6oeiGEIphYI,8802
|
|
5
|
-
ezmsg/sigproc/aggregate.py,sha256=Wnvz1xXDQhdVkTfVPOmhdmjgIhR_YQhioo8Dwh4BaoE,5615
|
|
6
|
-
ezmsg/sigproc/bandpower.py,sha256=QPktf3v7sojDHhwUVcK3UNPU-Dm4sf2QQw3qmYWZ1r0,2228
|
|
7
|
-
ezmsg/sigproc/base.py,sha256=vut0BLjgc0mxYRbs7tDd9XzwRFA2_GcsgXZmIYovR0Y,1248
|
|
8
|
-
ezmsg/sigproc/butterworthfilter.py,sha256=vTESZAAcQhWLI8yIMOApsGAYgjv2ekCZsTIliFjEkc8,5345
|
|
9
|
-
ezmsg/sigproc/decimate.py,sha256=zNxJXauE4Z54Yy7tpN9_oJuW0I0ppQRWhSpwb3Ri2gc,1473
|
|
10
|
-
ezmsg/sigproc/downsample.py,sha256=0TOhWkg7B9g3FDcewHINZiNuo28JyXRtgTYvZ7C8ImM,3384
|
|
11
|
-
ezmsg/sigproc/ewmfilter.py,sha256=XzTmouRa7AnPjTiI32-oumwm4ZfOl6uPPUSldExNpAs,4516
|
|
12
|
-
ezmsg/sigproc/filter.py,sha256=x3ytFowxg4O0QFQeMDFmQieV86H-6Q3Mkt3ThRIOh60,8301
|
|
13
|
-
ezmsg/sigproc/filterbank.py,sha256=Rhs7AKWy36lrMlzftEbYPXPW-FwZZ-QUCEp_QFG9mFU,12443
|
|
14
|
-
ezmsg/sigproc/messages.py,sha256=KpYCWWRD5itVAq0-Lf8qd7ErEE1A9qdm2p7O8Y4zEFA,955
|
|
15
|
-
ezmsg/sigproc/sampler.py,sha256=Zv5eq9CLpE8ui4HyZzBEqxwqBf--IbexS7zBx3qKp3w,12733
|
|
16
|
-
ezmsg/sigproc/scaler.py,sha256=2Hi4XWWvUtPOVOfIyX0Dr0cZEdbTobZOoMXKh9Vszlk,5944
|
|
17
|
-
ezmsg/sigproc/signalinjector.py,sha256=T1yvigk9WYujYqubd15UAF6hNmSqS9J7rCzaPYENoEA,2644
|
|
18
|
-
ezmsg/sigproc/slicer.py,sha256=ffawSqhO06lC5TXg_Ujg0eP2EuF98McQiUdlwxn3psI,5072
|
|
19
|
-
ezmsg/sigproc/spectral.py,sha256=_2qO6as4Nesmc9V1WW2EXNMH5pPz8aVTEcIPOi4-g2o,322
|
|
20
|
-
ezmsg/sigproc/spectrogram.py,sha256=16By4VWln7UvZ8IV_TdNAFaJDgkzvVKXWpnsoZoiW1M,3146
|
|
21
|
-
ezmsg/sigproc/spectrum.py,sha256=a75d6q6o3dAuqX6ZuFv6AfHYDOMuhA01OVCugzFMUSQ,9415
|
|
22
|
-
ezmsg/sigproc/synth.py,sha256=ygJRI9Seqhrg13lUhcA6XSpxcEr3LL1NupviSQLrC9o,18351
|
|
23
|
-
ezmsg/sigproc/wavelets.py,sha256=_3jI52NzksD1WNnHx03F2p4V2uGN_MtBbLsJGRjeyoE,6596
|
|
24
|
-
ezmsg/sigproc/window.py,sha256=A697XG2YyR9ywmzfxJIXovi6wPwDhBI9UUeShNJFKgM,13094
|
|
25
|
-
ezmsg/sigproc/math/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
|
-
ezmsg/sigproc/math/abs.py,sha256=hqS_sbLqAKSlguj3_rsfeWzOe6233tMxXfjDPg1fi2g,918
|
|
27
|
-
ezmsg/sigproc/math/clip.py,sha256=xIfc6fEfiNh7ILG3IYxcuCd5VBqmWXmDliGi_dKVJpM,1131
|
|
28
|
-
ezmsg/sigproc/math/difference.py,sha256=s3al1WzUZXsG2XYzOprRcKP-VD9J5FwYx578_SKG0vg,2183
|
|
29
|
-
ezmsg/sigproc/math/invert.py,sha256=H8df1u8OVb5TOkRC8p5EW7R17kHdLOYqXVH_axy5bkI,882
|
|
30
|
-
ezmsg/sigproc/math/log.py,sha256=oot0tT0wVvdI0UlPOqj1tQLDn_gIxf8em_b4NfJRmW0,1559
|
|
31
|
-
ezmsg/sigproc/math/scale.py,sha256=iIQuJAr5pzCiMqzi2YdzLc1agQBKBOcngdNZlLO3X_o,1050
|
|
32
|
-
ezmsg_sigproc-1.4.2.dist-info/METADATA,sha256=islU0_cvDjX0iqp202X5_eD-Qu37_9wKsBOo_cKcV8c,2376
|
|
33
|
-
ezmsg_sigproc-1.4.2.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
34
|
-
ezmsg_sigproc-1.4.2.dist-info/licenses/LICENSE.txt,sha256=seu0tKhhAMPCUgc1XpXGGaCxY1YaYvFJwqFuQZAl2go,1100
|
|
35
|
-
ezmsg_sigproc-1.4.2.dist-info/RECORD,,
|
|
File without changes
|