ezmsg-sigproc 2.0.0__tar.gz → 2.1.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.
Files changed (100) hide show
  1. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/PKG-INFO +1 -1
  2. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/__version__.py +2 -2
  3. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/aggregate.py +21 -4
  4. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/bandpower.py +8 -2
  5. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_aggregate.py +24 -0
  6. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_bandpower.py +2 -1
  7. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/.github/workflows/python-publish-ezmsg-sigproc.yml +0 -0
  8. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/.github/workflows/python-tests.yml +0 -0
  9. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/.gitignore +0 -0
  10. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/.pre-commit-config.yaml +0 -0
  11. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/LICENSE.txt +0 -0
  12. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/README.md +0 -0
  13. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/docs/ProcessorsBase.md +0 -0
  14. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/pyproject.toml +0 -0
  15. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/__init__.py +0 -0
  16. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/activation.py +0 -0
  17. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/adaptive_lattice_notch.py +0 -0
  18. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/affinetransform.py +0 -0
  19. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/base.py +0 -0
  20. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/butterworthfilter.py +0 -0
  21. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/cheby.py +0 -0
  22. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/combfilter.py +0 -0
  23. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/decimate.py +0 -0
  24. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/detrend.py +0 -0
  25. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/diff.py +0 -0
  26. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/downsample.py +0 -0
  27. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/ewma.py +0 -0
  28. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/ewmfilter.py +0 -0
  29. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/extract_axis.py +0 -0
  30. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/filter.py +0 -0
  31. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/filterbank.py +0 -0
  32. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/math/__init__.py +0 -0
  33. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/math/abs.py +0 -0
  34. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/math/clip.py +0 -0
  35. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/math/difference.py +0 -0
  36. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/math/invert.py +0 -0
  37. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/math/log.py +0 -0
  38. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/math/scale.py +0 -0
  39. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/messages.py +0 -0
  40. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/quantize.py +0 -0
  41. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/resample.py +0 -0
  42. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/sampler.py +0 -0
  43. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/scaler.py +0 -0
  44. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/signalinjector.py +0 -0
  45. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/slicer.py +0 -0
  46. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/spectral.py +0 -0
  47. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/spectrogram.py +0 -0
  48. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/spectrum.py +0 -0
  49. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/synth.py +0 -0
  50. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/transpose.py +0 -0
  51. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/util/__init__.py +0 -0
  52. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/util/asio.py +0 -0
  53. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/util/message.py +0 -0
  54. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/util/profile.py +0 -0
  55. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/util/sparse.py +0 -0
  56. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/util/typeresolution.py +0 -0
  57. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/wavelets.py +0 -0
  58. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/src/ezmsg/sigproc/window.py +0 -0
  59. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/__init__.py +0 -0
  60. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/conftest.py +0 -0
  61. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/helpers/__init__.py +0 -0
  62. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/helpers/util.py +0 -0
  63. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/integration/bytewax/test_spectrum_bytewax.py +0 -0
  64. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/integration/bytewax/test_window_bytewax.py +0 -0
  65. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/integration/ezmsg/test_butterworth_system.py +0 -0
  66. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/integration/ezmsg/test_decimate_system.py +0 -0
  67. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/integration/ezmsg/test_downsample_system.py +0 -0
  68. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/integration/ezmsg/test_filter_system.py +0 -0
  69. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/integration/ezmsg/test_sampler_system.py +0 -0
  70. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/integration/ezmsg/test_scaler_system.py +0 -0
  71. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/integration/ezmsg/test_spectrum_system.py +0 -0
  72. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/integration/ezmsg/test_synth_system.py +0 -0
  73. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/integration/ezmsg/test_window_system.py +0 -0
  74. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/resources/xform.csv +0 -0
  75. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/test_profile.py +0 -0
  76. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_activation.py +0 -0
  77. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_adaptive_lattice_notch.py +0 -0
  78. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_affine_transform.py +0 -0
  79. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_base.py +0 -0
  80. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_butter.py +0 -0
  81. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_combfilter.py +0 -0
  82. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_diff.py +0 -0
  83. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_downsample.py +0 -0
  84. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_ewma.py +0 -0
  85. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_extract_axis.py +0 -0
  86. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_filterbank.py +0 -0
  87. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_math.py +0 -0
  88. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_quantize.py +0 -0
  89. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_resample.py +0 -0
  90. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_sampler.py +0 -0
  91. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_scaler.py +0 -0
  92. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_slicer.py +0 -0
  93. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_spectrogram.py +0 -0
  94. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_spectrum.py +0 -0
  95. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_synth.py +0 -0
  96. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_transpose.py +0 -0
  97. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_util.py +0 -0
  98. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_wavelets.py +0 -0
  99. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/tests/unit/test_window.py +0 -0
  100. {ezmsg_sigproc-2.0.0 → ezmsg_sigproc-2.1.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ezmsg-sigproc
3
- Version: 2.0.0
3
+ Version: 2.1.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-Expression: MIT
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '2.0.0'
21
- __version_tuple__ = version_tuple = (2, 0, 0)
20
+ __version__ = version = '2.1.0'
21
+ __version_tuple__ = version_tuple = (2, 1, 0)
@@ -36,6 +36,7 @@ class AggregationFunction(OptionsEnum):
36
36
  NANSUM = "nansum"
37
37
  ARGMIN = "argmin"
38
38
  ARGMAX = "argmax"
39
+ TRAPEZOID = "trapezoid"
39
40
 
40
41
 
41
42
  AGGREGATORS = {
@@ -54,6 +55,9 @@ AGGREGATORS = {
54
55
  AggregationFunction.NANSUM: np.nansum,
55
56
  AggregationFunction.ARGMIN: np.argmin,
56
57
  AggregationFunction.ARGMAX: np.argmax,
58
+ # Note: Some methods require x-coordinates and
59
+ # are handled specially in `_process`.
60
+ AggregationFunction.TRAPEZOID: np.trapezoid,
57
61
  }
58
62
 
59
63
 
@@ -144,10 +148,23 @@ class RangedAggregateTransformer(
144
148
  ax_idx = message.get_axis_idx(axis)
145
149
  agg_func = AGGREGATORS[self.settings.operation]
146
150
 
147
- out_data = [
148
- agg_func(slice_along_axis(message.data, sl, axis=ax_idx), axis=ax_idx)
149
- for sl in self._state.slices
150
- ]
151
+ if self.settings.operation in [
152
+ AggregationFunction.TRAPEZOID,
153
+ ]:
154
+ # Special handling for methods that require x-coordinates.
155
+ out_data = [
156
+ agg_func(
157
+ slice_along_axis(message.data, sl, axis=ax_idx),
158
+ x=self._state.ax_vec[sl],
159
+ axis=ax_idx,
160
+ )
161
+ for sl in self._state.slices
162
+ ]
163
+ else:
164
+ out_data = [
165
+ agg_func(slice_along_axis(message.data, sl, axis=ax_idx), axis=ax_idx)
166
+ for sl in self._state.slices
167
+ ]
151
168
 
152
169
  msg_out = replace(
153
170
  message,
@@ -36,6 +36,9 @@ class BandPowerSettings(ez.Settings):
36
36
  (min, max) tuples of band limits in Hz.
37
37
  """
38
38
 
39
+ aggregation: AggregationFunction = AggregationFunction.MEAN
40
+ """:obj:`AggregationFunction` to apply to each band."""
41
+
39
42
 
40
43
  class BandPowerTransformer(CompositeProcessor[BandPowerSettings, AxisArray, AxisArray]):
41
44
  @staticmethod
@@ -50,7 +53,7 @@ class BandPowerTransformer(CompositeProcessor[BandPowerSettings, AxisArray, Axis
50
53
  settings=RangedAggregateSettings(
51
54
  axis="freq",
52
55
  bands=settings.bands,
53
- operation=AggregationFunction.MEAN,
56
+ operation=settings.aggregation,
54
57
  )
55
58
  ),
56
59
  }
@@ -68,6 +71,7 @@ def bandpower(
68
71
  (17, 30),
69
72
  (70, 170),
70
73
  ],
74
+ aggregation: AggregationFunction = AggregationFunction.MEAN,
71
75
  ) -> BandPowerTransformer:
72
76
  """
73
77
  Calculate the average spectral power in each band.
@@ -77,6 +81,8 @@ def bandpower(
77
81
  """
78
82
  return BandPowerTransformer(
79
83
  settings=BandPowerSettings(
80
- spectrogram_settings=spectrogram_settings, bands=bands
84
+ spectrogram_settings=spectrogram_settings,
85
+ bands=bands,
86
+ aggregation=aggregation,
81
87
  )
82
88
  )
@@ -110,6 +110,30 @@ def test_arg_aggregate(agg_func: AggregationFunction):
110
110
  assert np.array_equal(out_dat, expected_dat)
111
111
 
112
112
 
113
+ def test_trapezoid():
114
+ bands = [(5.0, 20.0), (30.0, 50.0)]
115
+ in_msgs = [_ for _ in get_msg_gen()]
116
+ gen = ranged_aggregate(
117
+ axis="freq", bands=bands, operation=AggregationFunction.TRAPEZOID
118
+ )
119
+ out_msgs = [gen.send(_) for _ in in_msgs]
120
+
121
+ out_dat = AxisArray.concatenate(*out_msgs, dim="time").data
122
+
123
+ # Calculate expected data using trapezoidal integration
124
+ in_data = AxisArray.concatenate(*in_msgs, dim="time").data
125
+ targ_ax = in_msgs[0].axes["freq"]
126
+ targ_ax_vec = targ_ax.value(np.arange(in_data.shape[-1]))
127
+ expected = []
128
+ for start, stop in bands:
129
+ inds = np.logical_and(targ_ax_vec >= start, targ_ax_vec <= stop)
130
+ expected.append(np.trapezoid(in_data[..., inds], x=targ_ax_vec[inds], axis=-1))
131
+ expected = np.stack(expected, axis=-1)
132
+
133
+ assert out_dat.shape == expected.shape
134
+ assert np.allclose(out_dat, expected)
135
+
136
+
113
137
  @pytest.mark.parametrize("change_ax", ["ch", "freq"])
114
138
  def test_aggregate_handle_change(change_ax: str):
115
139
  """
@@ -2,7 +2,7 @@ import copy
2
2
 
3
3
  import numpy as np
4
4
  from ezmsg.util.messages.axisarray import AxisArray
5
- from ezmsg.sigproc.bandpower import bandpower, SpectrogramSettings
5
+ from ezmsg.sigproc.bandpower import bandpower, SpectrogramSettings, AggregationFunction
6
6
 
7
7
  from tests.helpers.util import (
8
8
  create_messages_with_periodic_signal,
@@ -45,6 +45,7 @@ def test_bandpower():
45
45
  window_shift=0.1,
46
46
  ),
47
47
  bands=bands,
48
+ aggregation=AggregationFunction.MEAN,
48
49
  )
49
50
  results = [gen.send(_) for _ in messages]
50
51
 
File without changes
File without changes
File without changes
File without changes