ezmsg-sigproc 2.5.0__tar.gz → 2.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.
Files changed (180) hide show
  1. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/.github/workflows/docs.yml +5 -4
  2. ezmsg_sigproc-2.7.0/.github/workflows/python-publish.yml +29 -0
  3. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/.pre-commit-config.yaml +1 -2
  4. ezmsg_sigproc-2.7.0/PKG-INFO +60 -0
  5. ezmsg_sigproc-2.7.0/README.md +42 -0
  6. ezmsg_sigproc-2.7.0/docs/source/api/index.rst +11 -0
  7. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/source/conf.py +1 -0
  8. ezmsg_sigproc-2.7.0/docs/source/guides/how-tos/signalprocessing/composite.rst +6 -0
  9. ezmsg_sigproc-2.7.0/docs/source/guides/how-tos/signalprocessing/processor.rst +8 -0
  10. ezmsg_sigproc-2.7.0/docs/source/guides/how-tos/signalprocessing/stateful.rst +8 -0
  11. ezmsg_sigproc-2.7.0/docs/source/guides/how-tos/signalprocessing/unit.rst +41 -0
  12. ezmsg_sigproc-2.7.0/docs/source/guides/sigproc/architecture.rst +41 -0
  13. ezmsg_sigproc-2.7.0/docs/source/guides/sigproc/base.rst +19 -0
  14. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/source/guides/sigproc/content-sigproc.rst +1 -0
  15. ezmsg_sigproc-2.7.0/docs/source/index.md +20 -0
  16. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/pyproject.toml +20 -0
  17. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/__version__.py +2 -2
  18. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/activation.py +5 -11
  19. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/adaptive_lattice_notch.py +11 -30
  20. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/affinetransform.py +16 -42
  21. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/aggregate.py +17 -34
  22. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/bandpower.py +12 -20
  23. ezmsg_sigproc-2.7.0/src/ezmsg/sigproc/base.py +149 -0
  24. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/butterworthfilter.py +8 -16
  25. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/butterworthzerophase.py +7 -16
  26. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/cheby.py +4 -10
  27. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/combfilter.py +5 -8
  28. ezmsg_sigproc-2.7.0/src/ezmsg/sigproc/coordinatespaces.py +142 -0
  29. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/decimate.py +3 -7
  30. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/denormalize.py +6 -11
  31. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/detrend.py +3 -4
  32. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/diff.py +8 -17
  33. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/downsample.py +11 -20
  34. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/ewma.py +11 -28
  35. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/extract_axis.py +3 -4
  36. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/fbcca.py +34 -59
  37. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/filter.py +19 -45
  38. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/filterbank.py +37 -74
  39. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/filterbankdesign.py +7 -14
  40. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/fir_hilbert.py +13 -30
  41. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/fir_pmc.py +5 -10
  42. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/firfilter.py +12 -14
  43. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/gaussiansmoothing.py +5 -9
  44. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/kaiser.py +11 -15
  45. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/math/abs.py +4 -3
  46. ezmsg_sigproc-2.7.0/src/ezmsg/sigproc/math/add.py +121 -0
  47. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/math/clip.py +4 -1
  48. ezmsg_sigproc-2.7.0/src/ezmsg/sigproc/math/difference.py +137 -0
  49. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/math/invert.py +3 -3
  50. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/math/log.py +5 -6
  51. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/math/scale.py +2 -0
  52. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/messages.py +1 -2
  53. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/quantize.py +3 -6
  54. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/resample.py +17 -38
  55. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/rollingscaler.py +12 -37
  56. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/sampler.py +19 -37
  57. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/scaler.py +11 -22
  58. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/signalinjector.py +7 -18
  59. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/slicer.py +14 -34
  60. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/spectrogram.py +12 -19
  61. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/spectrum.py +17 -38
  62. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/transpose.py +12 -24
  63. ezmsg_sigproc-2.7.0/src/ezmsg/sigproc/util/asio.py +25 -0
  64. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/util/axisarray_buffer.py +12 -26
  65. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/util/buffer.py +22 -43
  66. ezmsg_sigproc-2.7.0/src/ezmsg/sigproc/util/message.py +17 -0
  67. ezmsg_sigproc-2.7.0/src/ezmsg/sigproc/util/profile.py +23 -0
  68. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/util/sparse.py +7 -15
  69. ezmsg_sigproc-2.7.0/src/ezmsg/sigproc/util/typeresolution.py +17 -0
  70. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/wavelets.py +10 -19
  71. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/window.py +29 -83
  72. ezmsg_sigproc-2.7.0/tests/helpers/synth.py +281 -0
  73. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/helpers/util.py +9 -18
  74. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/integration/bytewax/test_spectrum_bytewax.py +4 -4
  75. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/integration/bytewax/test_window_bytewax.py +3 -3
  76. ezmsg_sigproc-2.7.0/tests/integration/ezmsg/test_add_system.py +148 -0
  77. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/integration/ezmsg/test_butterworth_system.py +10 -20
  78. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/integration/ezmsg/test_butterworthzerophase_system.py +1 -1
  79. ezmsg_sigproc-2.7.0/tests/integration/ezmsg/test_coordinatespaces_system.py +226 -0
  80. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/integration/ezmsg/test_decimate_system.py +5 -8
  81. ezmsg_sigproc-2.7.0/tests/integration/ezmsg/test_difference_system.py +203 -0
  82. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/integration/ezmsg/test_downsample_system.py +10 -13
  83. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/integration/ezmsg/test_filter_system.py +9 -20
  84. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/integration/ezmsg/test_fir_hilbert_system.py +1 -1
  85. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/integration/ezmsg/test_fir_pmc_system.py +1 -1
  86. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/integration/ezmsg/test_rollingscaler_system.py +1 -1
  87. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/integration/ezmsg/test_sampler_system.py +7 -13
  88. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/integration/ezmsg/test_scaler_system.py +8 -13
  89. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/integration/ezmsg/test_spectrum_system.py +9 -10
  90. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/integration/ezmsg/test_window_system.py +10 -17
  91. ezmsg_sigproc-2.7.0/tests/test_profile.py +39 -0
  92. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/buffer/test_axisarray_buffer.py +6 -12
  93. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/buffer/test_buffer.py +2 -1
  94. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/buffer/test_buffer_overflow.py +10 -21
  95. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_activation.py +4 -9
  96. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_adaptive_lattice_notch.py +5 -17
  97. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_affine_transform.py +2 -9
  98. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_aggregate.py +20 -56
  99. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_bandpower.py +2 -2
  100. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_base.py +52 -133
  101. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_butter.py +8 -20
  102. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_butterworthzerophase.py +7 -21
  103. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_combfilter.py +9 -24
  104. ezmsg_sigproc-2.7.0/tests/unit/test_coordinatespaces.py +272 -0
  105. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_denormalize.py +7 -20
  106. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_diff.py +3 -3
  107. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_downsample.py +5 -12
  108. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_ewma.py +4 -8
  109. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_extract_axis.py +3 -5
  110. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_fbcca.py +27 -85
  111. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_filter.py +2 -1
  112. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_filterbank.py +5 -12
  113. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_filterbankdesign.py +22 -63
  114. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_fir_hilbert.py +4 -12
  115. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_firfilter.py +2 -4
  116. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_gaussian_smoothing_filter.py +6 -14
  117. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_kaiser.py +4 -10
  118. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_math.py +1 -4
  119. ezmsg_sigproc-2.7.0/tests/unit/test_math_add.py +247 -0
  120. ezmsg_sigproc-2.7.0/tests/unit/test_math_difference.py +278 -0
  121. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_quantize.py +4 -9
  122. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_resample.py +8 -22
  123. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_rollingscaler.py +5 -13
  124. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_sampler.py +9 -25
  125. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_scaler.py +4 -7
  126. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_slicer.py +5 -12
  127. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_spectrogram.py +6 -13
  128. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_spectrum.py +14 -29
  129. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_transpose.py +2 -5
  130. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_util.py +17 -51
  131. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_wavelets.py +4 -9
  132. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_window.py +11 -30
  133. ezmsg_sigproc-2.5.0/.github/workflows/python-publish-ezmsg-sigproc.yml +0 -30
  134. ezmsg_sigproc-2.5.0/PKG-INFO +0 -72
  135. ezmsg_sigproc-2.5.0/README.md +0 -55
  136. ezmsg_sigproc-2.5.0/docs/source/api/index.rst +0 -157
  137. ezmsg_sigproc-2.5.0/docs/source/guides/ProcessorsBase.md +0 -173
  138. ezmsg_sigproc-2.5.0/docs/source/guides/how-tos/signalprocessing/composite.rst +0 -4
  139. ezmsg_sigproc-2.5.0/docs/source/guides/how-tos/signalprocessing/processor.rst +0 -4
  140. ezmsg_sigproc-2.5.0/docs/source/guides/how-tos/signalprocessing/stateful.rst +0 -4
  141. ezmsg_sigproc-2.5.0/docs/source/guides/how-tos/signalprocessing/unit.rst +0 -11
  142. ezmsg_sigproc-2.5.0/docs/source/guides/sigproc/base.rst +0 -65
  143. ezmsg_sigproc-2.5.0/docs/source/index.rst +0 -82
  144. ezmsg_sigproc-2.5.0/src/ezmsg/sigproc/base.py +0 -1284
  145. ezmsg_sigproc-2.5.0/src/ezmsg/sigproc/math/difference.py +0 -73
  146. ezmsg_sigproc-2.5.0/src/ezmsg/sigproc/synth.py +0 -774
  147. ezmsg_sigproc-2.5.0/src/ezmsg/sigproc/util/asio.py +0 -156
  148. ezmsg_sigproc-2.5.0/src/ezmsg/sigproc/util/message.py +0 -31
  149. ezmsg_sigproc-2.5.0/src/ezmsg/sigproc/util/profile.py +0 -174
  150. ezmsg_sigproc-2.5.0/src/ezmsg/sigproc/util/typeresolution.py +0 -83
  151. ezmsg_sigproc-2.5.0/tests/integration/ezmsg/test_synth_system.py +0 -243
  152. ezmsg_sigproc-2.5.0/tests/test_profile.py +0 -191
  153. ezmsg_sigproc-2.5.0/tests/unit/test_synth.py +0 -150
  154. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/.github/workflows/python-tests.yml +0 -0
  155. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/.gitignore +0 -0
  156. ezmsg_sigproc-2.5.0/LICENSE.txt → ezmsg_sigproc-2.7.0/LICENSE +0 -0
  157. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/Makefile +0 -0
  158. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/make.bat +0 -0
  159. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/source/_templates/autosummary/module.rst +0 -0
  160. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/source/guides/HybridBuffer.md +0 -0
  161. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/source/guides/explanations/sigproc.rst +0 -0
  162. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/source/guides/how-tos/signalprocessing/adaptive.rst +0 -0
  163. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/source/guides/how-tos/signalprocessing/checkpoint.rst +0 -0
  164. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/source/guides/how-tos/signalprocessing/content-signalprocessing.rst +0 -0
  165. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/source/guides/how-tos/signalprocessing/standalone.rst +0 -0
  166. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/source/guides/img/HybridBufferBasic.svg +0 -0
  167. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/source/guides/img/HybridBufferOverflow.svg +0 -0
  168. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/source/guides/sigproc/processors.rst +0 -0
  169. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/source/guides/sigproc/units.rst +0 -0
  170. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/docs/source/guides/tutorials/signalprocessing.rst +0 -0
  171. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/__init__.py +0 -0
  172. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/ewmfilter.py +1 -1
  173. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/math/__init__.py +0 -0
  174. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/spectral.py +3 -3
  175. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/src/ezmsg/sigproc/util/__init__.py +0 -0
  176. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/__init__.py +0 -0
  177. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/conftest.py +1 -1
  178. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/helpers/__init__.py +0 -0
  179. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/resources/xform.csv +0 -0
  180. {ezmsg_sigproc-2.5.0 → ezmsg_sigproc-2.7.0}/tests/unit/test_fir_pmc.py +0 -0
@@ -4,11 +4,12 @@ on:
4
4
  push:
5
5
  branches:
6
6
  - main
7
- tags:
8
- - 'v*'
9
7
  pull_request:
10
8
  branches:
9
+ - main
11
10
  - dev
11
+ release:
12
+ types: [published]
12
13
  workflow_dispatch:
13
14
 
14
15
  permissions:
@@ -52,8 +53,8 @@ jobs:
52
53
  path: 'docs/build/html'
53
54
 
54
55
  deploy:
55
- # Only deploy on push to main or release tags
56
- if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
56
+ # Only deploy when a release is published
57
+ if: github.event_name == 'release'
57
58
  environment:
58
59
  name: github-pages
59
60
  url: ${{ steps.deployment.outputs.page_url }}
@@ -0,0 +1,29 @@
1
+ name: Upload Python Package
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ build:
13
+ name: build and upload release to PyPI
14
+ runs-on: ubuntu-latest
15
+ environment: "release"
16
+ permissions:
17
+ id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - name: Install uv
23
+ uses: astral-sh/setup-uv@v6
24
+
25
+ - name: Build Package
26
+ run: uv build
27
+
28
+ - name: Publish package distributions to PyPI
29
+ run: uv publish
@@ -1,7 +1,6 @@
1
1
  repos:
2
2
  - repo: https://github.com/astral-sh/ruff-pre-commit
3
- # Ruff version.
4
- rev: v0.6.7
3
+ rev: v0.8.3
5
4
  hooks:
6
5
  # Run the linter.
7
6
  - id: ruff
@@ -0,0 +1,60 @@
1
+ Metadata-Version: 2.4
2
+ Name: ezmsg-sigproc
3
+ Version: 2.7.0
4
+ Summary: Timeseries signal processing implementations in ezmsg
5
+ Author-email: Griffin Milsap <griffin.milsap@gmail.com>, Preston Peranich <pperanich@gmail.com>, Chadwick Boulay <chadwick.boulay@gmail.com>, Kyle McGraw <kmcgraw@blackrockneuro.com>
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.10.15
9
+ Requires-Dist: array-api-compat>=1.11.1
10
+ Requires-Dist: ezmsg-baseproc>=1.1.0
11
+ Requires-Dist: ezmsg>=3.6.0
12
+ Requires-Dist: numba>=0.61.0
13
+ Requires-Dist: numpy>=1.26.0
14
+ Requires-Dist: pywavelets>=1.6.0
15
+ Requires-Dist: scipy>=1.13.1
16
+ Requires-Dist: sparse>=0.15.4
17
+ Description-Content-Type: text/markdown
18
+
19
+ # ezmsg-sigproc
20
+
21
+ Signal processing primitives for the [ezmsg](https://www.ezmsg.org) message-passing framework.
22
+
23
+ ## Features
24
+
25
+ * **Filtering** - Chebyshev, comb filters, and more
26
+ * **Spectral analysis** - Spectrogram, spectrum, and wavelet transforms
27
+ * **Resampling** - Downsample, decimate, and resample operations
28
+ * **Windowing** - Sliding windows and buffering utilities
29
+ * **Math operations** - Arithmetic, log, abs, difference, and more
30
+ * **Signal generation** - Synthetic signal generators
31
+
32
+ All modules use `AxisArray` as the primary data structure for passing signals between components.
33
+
34
+ ## Installation
35
+
36
+ Install from PyPI:
37
+
38
+ ```bash
39
+ pip install ezmsg-sigproc
40
+ ```
41
+
42
+ Or install from GitHub for the latest development version:
43
+
44
+ ```bash
45
+ pip install git+https://github.com/ezmsg-org/ezmsg-sigproc.git@dev
46
+ ```
47
+
48
+ ## Documentation
49
+
50
+ Full documentation is available at [ezmsg.org](https://www.ezmsg.org).
51
+
52
+ ## Development
53
+
54
+ We use [`uv`](https://docs.astral.sh/uv/) for development.
55
+
56
+ 1. Fork and clone the repository
57
+ 2. `uv sync` to create a virtual environment and install dependencies
58
+ 3. `uv run pre-commit install` to set up linting and formatting hooks
59
+ 4. `uv run pytest tests` to run the test suite
60
+ 5. Submit a PR against the `dev` branch
@@ -0,0 +1,42 @@
1
+ # ezmsg-sigproc
2
+
3
+ Signal processing primitives for the [ezmsg](https://www.ezmsg.org) message-passing framework.
4
+
5
+ ## Features
6
+
7
+ * **Filtering** - Chebyshev, comb filters, and more
8
+ * **Spectral analysis** - Spectrogram, spectrum, and wavelet transforms
9
+ * **Resampling** - Downsample, decimate, and resample operations
10
+ * **Windowing** - Sliding windows and buffering utilities
11
+ * **Math operations** - Arithmetic, log, abs, difference, and more
12
+ * **Signal generation** - Synthetic signal generators
13
+
14
+ All modules use `AxisArray` as the primary data structure for passing signals between components.
15
+
16
+ ## Installation
17
+
18
+ Install from PyPI:
19
+
20
+ ```bash
21
+ pip install ezmsg-sigproc
22
+ ```
23
+
24
+ Or install from GitHub for the latest development version:
25
+
26
+ ```bash
27
+ pip install git+https://github.com/ezmsg-org/ezmsg-sigproc.git@dev
28
+ ```
29
+
30
+ ## Documentation
31
+
32
+ Full documentation is available at [ezmsg.org](https://www.ezmsg.org).
33
+
34
+ ## Development
35
+
36
+ We use [`uv`](https://docs.astral.sh/uv/) for development.
37
+
38
+ 1. Fork and clone the repository
39
+ 2. `uv sync` to create a virtual environment and install dependencies
40
+ 3. `uv run pre-commit install` to set up linting and formatting hooks
41
+ 4. `uv run pytest tests` to run the test suite
42
+ 5. Submit a PR against the `dev` branch
@@ -0,0 +1,11 @@
1
+ API Reference
2
+ =============
3
+
4
+ This page contains auto-generated API reference documentation.
5
+
6
+ .. autosummary::
7
+ :toctree: generated
8
+ :recursive:
9
+ :template: autosummary/module.rst
10
+
11
+ ezmsg.sigproc
@@ -72,6 +72,7 @@ intersphinx_mapping = {
72
72
  "numpy": ("https://numpy.org/doc/stable/", None),
73
73
  "scipy": ("https://scipy.org/doc/scipy/", None),
74
74
  "ezmsg": ("https://www.ezmsg.org/ezmsg/", None),
75
+ "ezmsg.baseproc": ("https://www.ezmsg.org/ezmsg-baseproc/", None),
75
76
  "ezmsg.learn": ("https://www.ezmsg.org/ezmsg-learn/", None),
76
77
  "ezmsg.event": ("https://www.ezmsg.org/ezmsg-event/", None),
77
78
  "ezmsg.lsl": ("https://www.ezmsg.org/ezmsg-lsl/", None),
@@ -0,0 +1,6 @@
1
+ How to efficiently chain multiple signal processors in ezmsg?
2
+ #############################################################
3
+
4
+ For general composite processor implementation guidance, see the `ezmsg-baseproc documentation <https://www.ezmsg.org/ezmsg-baseproc/guides/ProcessorsBase.html>`_.
5
+
6
+ (under construction)
@@ -0,0 +1,8 @@
1
+ How to write a signal processor in ezmsg?
2
+ #########################################
3
+
4
+ For general processor implementation guidance, see the `ezmsg-baseproc documentation <https://www.ezmsg.org/ezmsg-baseproc/guides/ProcessorsBase.html>`_.
5
+
6
+ For signal processing specific patterns, see the existing processors in ``ezmsg.sigproc`` as examples.
7
+
8
+ (under construction)
@@ -0,0 +1,8 @@
1
+ How to implement a stateful signal processor in ezmsg?
2
+ ######################################################
3
+
4
+ For general stateful processor implementation guidance, see the `ezmsg-baseproc documentation <https://www.ezmsg.org/ezmsg-baseproc/guides/ProcessorsBase.html>`_.
5
+
6
+ For signal processing specific patterns using stateful processors, see implementations like ``ChebyshevFilterTransformer`` and ``WindowTransformer`` as examples.
7
+
8
+ (under construction)
@@ -0,0 +1,41 @@
1
+ How to turn a signal processor into an ``ezmsg`` Unit?
2
+ ######################################################
3
+
4
+ For general guidance on converting processors to ezmsg Units, see the `ezmsg-baseproc documentation <https://www.ezmsg.org/ezmsg-baseproc/guides/ProcessorsBase.html#implementing-a-custom-ezmsg-unit>`_.
5
+
6
+ Example with Signal Processing
7
+ ------------------------------
8
+
9
+ To convert a signal processor to an ``ezmsg`` Unit:
10
+
11
+ 1. **Define the Processor**: Create a class that inherits from the appropriate base class (e.g., ``BaseTransformer``, ``BaseStatefulTransformer``).
12
+ 2. **Implement the Processing Logic**: Override the ``_process`` method to implement the signal processing logic.
13
+ 3. **Create the Unit**: Inherit from the appropriate Unit base class (e.g., ``BaseTransformerUnit``).
14
+
15
+ .. code-block:: python
16
+
17
+ import ezmsg.core as ez
18
+ from ezmsg.util.messages.axisarray import AxisArray
19
+ from ezmsg.baseproc import BaseTransformer, BaseTransformerUnit
20
+
21
+
22
+ class MyProcessorSettings(ez.Settings):
23
+ # Your settings here
24
+ pass
25
+
26
+
27
+ class MyProcessor(BaseTransformer[MyProcessorSettings, AxisArray, AxisArray]):
28
+ def _process(self, message: AxisArray) -> AxisArray:
29
+ # Your signal processing logic here
30
+ return message
31
+
32
+
33
+ class MyUnit(BaseTransformerUnit[
34
+ MyProcessorSettings,
35
+ AxisArray,
36
+ AxisArray,
37
+ MyProcessor,
38
+ ]):
39
+ SETTINGS = MyProcessorSettings
40
+
41
+ (under construction)
@@ -0,0 +1,41 @@
1
+ Architecture & Usage Patterns
2
+ =============================
3
+
4
+ This page describes the architecture of ezmsg-sigproc and different ways to use its components.
5
+
6
+ Operating Styles: Standalone vs. Pipelines
7
+ ------------------------------------------
8
+
9
+ While each processor is designed to be assembled into an ezmsg pipeline, the components are also well-suited for offline, ad-hoc analysis. You can instantiate processors directly in scripts or notebooks for quick prototyping or to validate results from other code. The companion Unit wrappers, however, are meant for assembling processors into a full ezmsg pipeline.
10
+
11
+ A fully defined ezmsg pipeline shines in online streaming scenarios where message routing, scheduling, and latency handling are crucial. Nevertheless, you can run the same pipeline offline—say, within a Jupyter notebook—if your analysis benefits from ezmsg's structured execution model.
12
+
13
+ Deciding between a standalone processor and a full pipeline comes down to the trade-off between simplicity and the operational overhead of the pipeline:
14
+
15
+ * **Standalone processors**: Low overhead, ideal for one-off or exploratory offline tasks.
16
+ * **Pipeline + Unit wrappers**: Additional setup cost but bring concurrency, standardized interfaces, and automatic message flow—useful when your offline experiment mirrors a live system or when you require fine-grained pipeline behavior.
17
+
18
+ Source Layout
19
+ -------------
20
+
21
+ All source resides under ``src/ezmsg/sigproc``, which contains:
22
+
23
+ * A suite of processors (for example, ``filter.py``, ``spectrogram.py``, ``spectrum.py``, ``sampler.py``)
24
+ * ``math/`` and ``util/`` subpackages for mathematical operations and utilities
25
+
26
+ Key Modules
27
+ ^^^^^^^^^^^
28
+
29
+ * **base.py** (via ``ezmsg.baseproc``): Defines standard protocols—Processor, Producer, Consumer, and Transformer—that enable both stateless and stateful processing chains.
30
+ * **filter.py**: Provides settings dataclasses and a stateful transformer that applies supplied coefficients to incoming data.
31
+ * **spectrogram.py**: Implements spectral analysis using a composite transformer chaining windowing, spectrum computation, and axis adjustments.
32
+
33
+ Where to Learn Next
34
+ -------------------
35
+
36
+ * Study the :doc:`base` page to master the processor architecture.
37
+ * Explore unit tests in the repository for hands-on examples of composing processors and Units.
38
+ * Review the `ezmsg framework <https://www.ezmsg.org>`_ to understand the surrounding ecosystem.
39
+ * Experiment with the code—try running processors standalone and then integrate them into a small pipeline to observe the trade-offs firsthand.
40
+
41
+ This approach equips newcomers to choose the right level of abstraction—raw processor, Unit wrapper, or full pipeline—based on the demands of their analysis or streaming application.
@@ -0,0 +1,19 @@
1
+ Base Processors
2
+ ===============
3
+
4
+ The base processor classes are provided by the ``ezmsg-baseproc`` package and re-exported from ``ezmsg.sigproc.base`` for backwards compatibility.
5
+
6
+ For detailed documentation on the base processor architecture, see the `ezmsg-baseproc documentation <https://www.ezmsg.org/ezmsg-baseproc/>`_.
7
+
8
+ .. note::
9
+ New code should import directly from ``ezmsg.baseproc`` instead of ``ezmsg.sigproc.base``.
10
+
11
+ API Reference
12
+ -------------
13
+
14
+ The following classes are re-exported from ``ezmsg.baseproc``:
15
+
16
+ .. automodule:: ezmsg.sigproc.base
17
+ :members:
18
+ :show-inheritance:
19
+ :imported-members:
@@ -17,6 +17,7 @@ This may occur when the generator receives inadequate data to produce a valid ou
17
17
  .. toctree::
18
18
  :maxdepth: 1
19
19
 
20
+ architecture
20
21
  base
21
22
  units
22
23
  processors
@@ -0,0 +1,20 @@
1
+ ```{include} ../../README.md
2
+ ```
3
+
4
+ ## Documentation
5
+
6
+ ```{toctree}
7
+ :maxdepth: 2
8
+ :caption: Contents:
9
+
10
+ guides/sigproc/content-sigproc
11
+ guides/HybridBuffer
12
+ guides/how-tos/signalprocessing/content-signalprocessing
13
+ guides/tutorials/signalprocessing
14
+ api/index
15
+ ```
16
+
17
+ ## Indices and tables
18
+
19
+ - {ref}`genindex`
20
+ - {ref}`modindex`
@@ -13,6 +13,7 @@ requires-python = ">=3.10.15"
13
13
  dynamic = ["version"]
14
14
  dependencies = [
15
15
  "array-api-compat>=1.11.1",
16
+ "ezmsg-baseproc>=1.1.0",
16
17
  "ezmsg>=3.6.0",
17
18
  "numba>=0.61.0",
18
19
  "numpy>=1.26.0",
@@ -64,5 +65,24 @@ version-file = "src/ezmsg/sigproc/__version__.py"
64
65
  packages = ["src/ezmsg"]
65
66
 
66
67
  [tool.pytest.ini_options]
68
+ asyncio_mode = "auto"
69
+ asyncio_default_fixture_loop_scope = "function"
67
70
  norecursedirs = "tests/helpers"
68
71
  addopts = "-p no:warnings"
72
+
73
+ [tool.ruff]
74
+ line-length = 120
75
+ target-version = "py310"
76
+ # Exclude auto-generated files
77
+ exclude = ["*/__version__.py"]
78
+
79
+ [tool.ruff.lint]
80
+ select = ["E", "F", "I", "W"]
81
+
82
+ [tool.ruff.lint.isort]
83
+ known-first-party = ["ezmsg.sigproc"]
84
+ known-third-party = ["ezmsg", "ezmsg.baseproc"]
85
+
86
+ [tool.uv.sources]
87
+ # Uncomment to use development version of ezmsg from git
88
+ #ezmsg = { git = "https://github.com/ezmsg-org/ezmsg.git", branch = "dev" }
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '2.5.0'
32
- __version_tuple__ = version_tuple = (2, 5, 0)
31
+ __version__ = version = '2.7.0'
32
+ __version_tuple__ = version_tuple = (2, 7, 0)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -1,10 +1,10 @@
1
- import scipy.special
2
1
  import ezmsg.core as ez
2
+ import scipy.special
3
+ from ezmsg.baseproc import BaseTransformer, BaseTransformerUnit
3
4
  from ezmsg.util.messages.axisarray import AxisArray
4
5
  from ezmsg.util.messages.util import replace
5
6
 
6
7
  from .spectral import OptionsEnum
7
- from .base import BaseTransformer, BaseTransformerUnit
8
8
 
9
9
 
10
10
  class ActivationFunction(OptionsEnum):
@@ -50,20 +50,14 @@ class ActivationTransformer(BaseTransformer[ActivationSettings, AxisArray, AxisA
50
50
  # str type handling
51
51
  function = self.settings.function.lower()
52
52
  if function not in ActivationFunction.options():
53
- raise ValueError(
54
- f"Unrecognized activation function {function}. Must be one of {ACTIVATIONS.keys()}"
55
- )
56
- function = list(ACTIVATIONS.keys())[
57
- ActivationFunction.options().index(function)
58
- ]
53
+ raise ValueError(f"Unrecognized activation function {function}. Must be one of {ACTIVATIONS.keys()}")
54
+ function = list(ACTIVATIONS.keys())[ActivationFunction.options().index(function)]
59
55
  func = ACTIVATIONS[function]
60
56
 
61
57
  return replace(message, data=func(message.data))
62
58
 
63
59
 
64
- class Activation(
65
- BaseTransformerUnit[ActivationSettings, AxisArray, AxisArray, ActivationTransformer]
66
- ):
60
+ class Activation(BaseTransformerUnit[ActivationSettings, AxisArray, AxisArray, ActivationTransformer]):
67
61
  SETTINGS = ActivationSettings
68
62
 
69
63
 
@@ -1,12 +1,11 @@
1
+ import ezmsg.core as ez
1
2
  import numpy as np
2
3
  import numpy.typing as npt
3
4
  import scipy.signal
4
- import ezmsg.core as ez
5
+ from ezmsg.baseproc import BaseStatefulTransformer, processor_state
5
6
  from ezmsg.util.messages.axisarray import AxisArray, CoordinateAxis
6
7
  from ezmsg.util.messages.util import replace
7
8
 
8
- from .base import processor_state, BaseStatefulTransformer
9
-
10
9
 
11
10
  class AdaptiveLatticeNotchFilterSettings(ez.Settings):
12
11
  """Settings for the Adaptive Lattice Notch Filter."""
@@ -76,9 +75,7 @@ class AdaptiveLatticeNotchFilterTransformer(
76
75
 
77
76
  fs = 1 / message.axes[self.settings.axis].gain
78
77
  init_f = (
79
- self.settings.init_notch_freq
80
- if self.settings.init_notch_freq is not None
81
- else 0.07178314656435313 * fs
78
+ self.settings.init_notch_freq if self.settings.init_notch_freq is not None else 0.07178314656435313 * fs
82
79
  )
83
80
  init_omega = init_f * (2 * np.pi) / fs
84
81
  init_k1 = -np.cos(init_omega)
@@ -91,9 +88,7 @@ class AdaptiveLatticeNotchFilterTransformer(
91
88
  self._state.k1 = init_k1 + np.zeros(sample_shape, dtype=float)
92
89
  self._state.freq_template = CoordinateAxis(
93
90
  data=np.zeros((0,) + sample_shape, dtype=float),
94
- dims=[self.settings.axis]
95
- + message.dims[:ax_idx]
96
- + message.dims[ax_idx + 1 :],
91
+ dims=[self.settings.axis] + message.dims[:ax_idx] + message.dims[ax_idx + 1 :],
97
92
  unit="Hz",
98
93
  )
99
94
 
@@ -147,9 +142,7 @@ class AdaptiveLatticeNotchFilterTransformer(
147
142
  for ix, k in enumerate(self._state.k1.flatten()):
148
143
  # Filter to get s_n (notch filter state)
149
144
  a_s = [1, k * gamma_plus_1, gamma]
150
- s_n[:, ix], self._state.zi[:, ix] = scipy.signal.lfilter(
151
- [1], a_s, _x[:, ix], zi=self._state.zi[:, ix]
152
- )
145
+ s_n[:, ix], self._state.zi[:, ix] = scipy.signal.lfilter([1], a_s, _x[:, ix], zi=self._state.zi[:, ix])
153
146
 
154
147
  # Apply output filter to get y_out
155
148
  b_y = [1, 2 * k, 1]
@@ -159,17 +152,11 @@ class AdaptiveLatticeNotchFilterTransformer(
159
152
  s_n_reshaped = s_n.reshape((s_n.shape[0],) + x_data.shape[1:])
160
153
  s_final = s_n_reshaped[-1] # Current s_n
161
154
  s_final_1 = s_n_reshaped[-2] # s_n_1
162
- s_final_2 = (
163
- s_n_reshaped[-3] if len(s_n_reshaped) > 2 else self._state.s_history[0]
164
- ) # s_n_2
155
+ s_final_2 = s_n_reshaped[-3] if len(s_n_reshaped) > 2 else self._state.s_history[0] # s_n_2
165
156
 
166
157
  # Update p and q using final values
167
- self._state.p = eta * self._state.p + one_minus_eta * (
168
- s_final_1 * (s_final + s_final_2)
169
- )
170
- self._state.q = eta * self._state.q + one_minus_eta * (
171
- 2 * (s_final_1 * s_final_1)
172
- )
158
+ self._state.p = eta * self._state.p + one_minus_eta * (s_final_1 * (s_final + s_final_2))
159
+ self._state.q = eta * self._state.q + one_minus_eta * (2 * (s_final_1 * s_final_1))
173
160
 
174
161
  # Update reflection coefficient
175
162
  new_k1 = -self._state.p / (self._state.q + 1e-8) # Avoid division by zero
@@ -199,17 +186,11 @@ class AdaptiveLatticeNotchFilterTransformer(
199
186
  y_out[sample_ix] = s_n + 2 * self._state.k1 * s_n_1 + s_n_2
200
187
 
201
188
  # Update filter parameters
202
- self._state.p = eta * self._state.p + one_minus_eta * (
203
- s_n_1 * (s_n + s_n_2)
204
- )
205
- self._state.q = eta * self._state.q + one_minus_eta * (
206
- 2 * (s_n_1 * s_n_1)
207
- )
189
+ self._state.p = eta * self._state.p + one_minus_eta * (s_n_1 * (s_n + s_n_2))
190
+ self._state.q = eta * self._state.q + one_minus_eta * (2 * (s_n_1 * s_n_1))
208
191
 
209
192
  # Update reflection coefficient
210
- new_k1 = -self._state.p / (
211
- self._state.q + 1e-8
212
- ) # Avoid division by zero
193
+ new_k1 = -self._state.p / (self._state.q + 1e-8) # Avoid division by zero
213
194
  new_k1 = np.clip(new_k1, -1, 1) # Clip to prevent instability
214
195
  self._state.k1 = mu * self._state.k1 + one_minus_mu * new_k1 # Smoothed
215
196
 
@@ -1,18 +1,17 @@
1
1
  import os
2
2
  from pathlib import Path
3
3
 
4
+ import ezmsg.core as ez
4
5
  import numpy as np
5
6
  import numpy.typing as npt
6
- import ezmsg.core as ez
7
- from ezmsg.util.messages.axisarray import AxisArray, AxisBase
8
- from ezmsg.util.messages.util import replace
9
-
10
- from .base import (
7
+ from ezmsg.baseproc import (
11
8
  BaseStatefulTransformer,
12
- BaseTransformerUnit,
13
9
  BaseTransformer,
10
+ BaseTransformerUnit,
14
11
  processor_state,
15
12
  )
13
+ from ezmsg.util.messages.axisarray import AxisArray, AxisBase
14
+ from ezmsg.util.messages.util import replace
16
15
 
17
16
 
18
17
  class AffineTransformSettings(ez.Settings):
@@ -38,15 +37,12 @@ class AffineTransformState:
38
37
 
39
38
 
40
39
  class AffineTransformTransformer(
41
- BaseStatefulTransformer[
42
- AffineTransformSettings, AxisArray, AxisArray, AffineTransformState
43
- ]
40
+ BaseStatefulTransformer[AffineTransformSettings, AxisArray, AxisArray, AffineTransformState]
44
41
  ):
45
42
  def __call__(self, message: AxisArray) -> AxisArray:
46
43
  # Override __call__ so we can shortcut if weights are None.
47
44
  if self.settings.weights is None or (
48
- isinstance(self.settings.weights, str)
49
- and self.settings.weights == "passthrough"
45
+ isinstance(self.settings.weights, str) and self.settings.weights == "passthrough"
50
46
  ):
51
47
  return message
52
48
  return super().__call__(message)
@@ -68,18 +64,12 @@ class AffineTransformTransformer(
68
64
  self._state.weights = weights
69
65
 
70
66
  axis = self.settings.axis or message.dims[-1]
71
- if (
72
- axis in message.axes
73
- and hasattr(message.axes[axis], "data")
74
- and weights.shape[0] != weights.shape[1]
75
- ):
67
+ if axis in message.axes and hasattr(message.axes[axis], "data") and weights.shape[0] != weights.shape[1]:
76
68
  in_labels = message.axes[axis].data
77
69
  new_labels = []
78
70
  n_in, n_out = weights.shape
79
71
  if len(in_labels) != n_in:
80
- ez.logger.warning(
81
- f"Received {len(in_labels)} for {n_in} inputs. Check upstream labels."
82
- )
72
+ ez.logger.warning(f"Received {len(in_labels)} for {n_in} inputs. Check upstream labels.")
83
73
  else:
84
74
  b_filled_outputs = np.any(weights, axis=0)
85
75
  b_used_inputs = np.any(weights, axis=1)
@@ -97,9 +87,7 @@ class AffineTransformTransformer(
97
87
  elif np.all(b_filled_outputs):
98
88
  new_labels = np.array(in_labels)[b_used_inputs]
99
89
 
100
- self._state.new_axis = replace(
101
- message.axes[axis], data=np.array(new_labels)
102
- )
90
+ self._state.new_axis = replace(message.axes[axis], data=np.array(new_labels))
103
91
 
104
92
  def _process(self, message: AxisArray) -> AxisArray:
105
93
  axis = self.settings.axis or message.dims[-1]
@@ -110,9 +98,7 @@ class AffineTransformTransformer(
110
98
  # The weights are stacked A|B where A is the transform and B is a single row
111
99
  # in the equation y = Ax + B. This supports NeuroKey's weights matrices.
112
100
  sample_shape = data.shape[:axis_idx] + (1,) + data.shape[axis_idx + 1 :]
113
- data = np.concatenate(
114
- (data, np.ones(sample_shape).astype(data.dtype)), axis=axis_idx
115
- )
101
+ data = np.concatenate((data, np.ones(sample_shape).astype(data.dtype)), axis=axis_idx)
116
102
 
117
103
  if axis_idx in [-1, len(message.dims) - 1]:
118
104
  data = np.matmul(data, self._state.weights)
@@ -128,11 +114,7 @@ class AffineTransformTransformer(
128
114
  return replace(message, **replace_kwargs)
129
115
 
130
116
 
131
- class AffineTransform(
132
- BaseTransformerUnit[
133
- AffineTransformSettings, AxisArray, AxisArray, AffineTransformTransformer
134
- ]
135
- ):
117
+ class AffineTransform(BaseTransformerUnit[AffineTransformSettings, AxisArray, AxisArray, AffineTransformTransformer]):
136
118
  SETTINGS = AffineTransformSettings
137
119
 
138
120
 
@@ -153,9 +135,7 @@ def affine_transform(
153
135
  :obj:`AffineTransformTransformer`.
154
136
  """
155
137
  return AffineTransformTransformer(
156
- AffineTransformSettings(
157
- weights=weights, axis=axis, right_multiply=right_multiply
158
- )
138
+ AffineTransformSettings(weights=weights, axis=axis, right_multiply=right_multiply)
159
139
  )
160
140
 
161
141
 
@@ -178,9 +158,7 @@ class CommonRereferenceSettings(ez.Settings):
178
158
  """Set False to exclude each channel from participating in the calculation of its reference."""
179
159
 
180
160
 
181
- class CommonRereferenceTransformer(
182
- BaseTransformer[CommonRereferenceSettings, AxisArray, AxisArray]
183
- ):
161
+ class CommonRereferenceTransformer(BaseTransformer[CommonRereferenceSettings, AxisArray, AxisArray]):
184
162
  def _process(self, message: AxisArray) -> AxisArray:
185
163
  if self.settings.mode == "passthrough":
186
164
  return message
@@ -188,9 +166,7 @@ class CommonRereferenceTransformer(
188
166
  axis = self.settings.axis or message.dims[-1]
189
167
  axis_idx = message.get_axis_idx(axis)
190
168
 
191
- func = {"mean": np.mean, "median": np.median, "passthrough": zeros_for_noop}[
192
- self.settings.mode
193
- ]
169
+ func = {"mean": np.mean, "median": np.median, "passthrough": zeros_for_noop}[self.settings.mode]
194
170
 
195
171
  ref_data = func(message.data, axis=axis_idx, keepdims=True)
196
172
 
@@ -213,9 +189,7 @@ class CommonRereferenceTransformer(
213
189
 
214
190
 
215
191
  class CommonRereference(
216
- BaseTransformerUnit[
217
- CommonRereferenceSettings, AxisArray, AxisArray, CommonRereferenceTransformer
218
- ]
192
+ BaseTransformerUnit[CommonRereferenceSettings, AxisArray, AxisArray, CommonRereferenceTransformer]
219
193
  ):
220
194
  SETTINGS = CommonRereferenceSettings
221
195