ezmsg-sigproc 1.3.1__tar.gz → 1.3.3__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 (61) hide show
  1. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/PKG-INFO +2 -2
  2. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/pyproject.toml +1 -1
  3. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/__version__.py +2 -2
  4. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/affinetransform.py +3 -4
  5. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_affine_transform.py +33 -4
  6. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/uv.lock +2 -2
  7. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/.github/workflows/python-publish-ezmsg-sigproc.yml +0 -0
  8. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/.github/workflows/python-tests.yml +0 -0
  9. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/.gitignore +0 -0
  10. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/.pre-commit-config.yaml +0 -0
  11. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/LICENSE.txt +0 -0
  12. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/README.md +0 -0
  13. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/__init__.py +0 -0
  14. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/activation.py +0 -0
  15. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/aggregate.py +0 -0
  16. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/bandpower.py +0 -0
  17. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/base.py +0 -0
  18. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/butterworthfilter.py +0 -0
  19. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/decimate.py +0 -0
  20. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/downsample.py +0 -0
  21. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/ewmfilter.py +0 -0
  22. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/filter.py +0 -0
  23. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/filterbank.py +0 -0
  24. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/math/__init__.py +0 -0
  25. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/math/abs.py +0 -0
  26. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/math/clip.py +0 -0
  27. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/math/difference.py +0 -0
  28. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/math/invert.py +0 -0
  29. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/math/log.py +0 -0
  30. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/math/scale.py +0 -0
  31. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/messages.py +0 -0
  32. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/sampler.py +0 -0
  33. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/scaler.py +0 -0
  34. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/signalinjector.py +0 -0
  35. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/slicer.py +0 -0
  36. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/spectral.py +0 -0
  37. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/spectrogram.py +0 -0
  38. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/spectrum.py +0 -0
  39. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/synth.py +0 -0
  40. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/wavelets.py +0 -0
  41. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/src/ezmsg/sigproc/window.py +0 -0
  42. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/conftest.py +0 -0
  43. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/helpers/__init__.py +0 -0
  44. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/helpers/util.py +0 -0
  45. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/resources/xform.csv +0 -0
  46. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_activation.py +0 -0
  47. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_aggregate.py +0 -0
  48. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_bandpower.py +0 -0
  49. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_butter.py +0 -0
  50. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_butterworth.py +0 -0
  51. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_downsample.py +0 -0
  52. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_filterbank.py +0 -0
  53. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_math.py +0 -0
  54. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_sampler.py +0 -0
  55. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_scaler.py +0 -0
  56. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_slicer.py +0 -0
  57. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_spectrogram.py +0 -0
  58. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_spectrum.py +0 -0
  59. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_synth.py +0 -0
  60. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_wavelets.py +0 -0
  61. {ezmsg_sigproc-1.3.1 → ezmsg_sigproc-1.3.3}/tests/test_window.py +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: ezmsg-sigproc
3
- Version: 1.3.1
3
+ Version: 1.3.3
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
7
7
  License-File: LICENSE.txt
8
8
  Requires-Python: >=3.9
9
9
  Requires-Dist: ezmsg>=3.5.0
10
- Requires-Dist: numpy>=2.0.2
10
+ Requires-Dist: numpy>=1.26.0
11
11
  Requires-Dist: pywavelets>=1.6.0
12
12
  Requires-Dist: scipy>=1.13.1
13
13
  Provides-Extra: test
@@ -12,7 +12,7 @@ requires-python = ">=3.9"
12
12
  dynamic = ["version"]
13
13
  dependencies = [
14
14
  "ezmsg>=3.5.0",
15
- "numpy>=2.0.2",
15
+ "numpy>=1.26.0",
16
16
  "pywavelets>=1.6.0",
17
17
  "scipy>=1.13.1",
18
18
  ]
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.3.1'
16
- __version_tuple__ = version_tuple = (1, 3, 1)
15
+ __version__ = version = '1.3.3'
16
+ __version_tuple__ = version_tuple = (1, 3, 3)
@@ -76,16 +76,15 @@ def affine_transform(
76
76
  ):
77
77
  in_labels = msg_in.axes[axis].labels
78
78
  new_labels = []
79
- n_in = weights.shape[1 if right_multiply else 0]
80
- n_out = weights.shape[0 if right_multiply else 1]
79
+ n_in, n_out = weights.shape
81
80
  if len(in_labels) != n_in:
82
81
  # Something upstream did something it wasn't supposed to. We will drop the labels.
83
82
  ez.logger.warning(
84
83
  f"Received {len(in_labels)} for {n_in} inputs. Check upstream labels."
85
84
  )
86
85
  else:
87
- b_used_inputs = np.any(weights, axis=0 if right_multiply else 1)
88
- b_filled_outputs = np.any(weights, axis=1 if right_multiply else 0)
86
+ b_filled_outputs = np.any(weights, axis=0)
87
+ b_used_inputs = np.any(weights, axis=1)
89
88
  if np.all(b_used_inputs) and np.all(b_filled_outputs):
90
89
  # All inputs are used and all outputs are used, but n_in != n_out.
91
90
  # Mapping cannot be determined.
@@ -1,5 +1,7 @@
1
1
  import copy
2
+ from dataclasses import dataclass, field
2
3
  from pathlib import Path
4
+ import typing
3
5
 
4
6
  import numpy as np
5
7
  from ezmsg.util.messages.axisarray import AxisArray
@@ -9,11 +11,33 @@ from ezmsg.sigproc.affinetransform import affine_transform, common_rereference
9
11
  from util import assert_messages_equal
10
12
 
11
13
 
14
+ # Define a custom Axis class that has a `labels` attribute
15
+ @dataclass
16
+ class CustomAxis(AxisArray.Axis):
17
+ labels: typing.List[str] = field(default_factory=lambda: [])
18
+
19
+ @classmethod
20
+ def SpaceAxis(
21
+ cls, labels: typing.List[str]
22
+ ): # , locs: typing.Optional[npt.NDArray] = None):
23
+ return cls(unit="mm", labels=labels)
24
+
25
+
26
+ # Monkey-patch AxisArray with our customized Axis
27
+ AxisArray.Axis = CustomAxis
28
+
29
+
12
30
  def test_affine_generator():
13
31
  n_times = 13
14
32
  n_chans = 64
15
33
  in_dat = np.arange(n_times * n_chans).reshape(n_times, n_chans)
16
- msg_in = AxisArray(in_dat, dims=["time", "ch"])
34
+ msg_in = AxisArray(
35
+ data=in_dat,
36
+ dims=["time", "ch"],
37
+ axes={
38
+ "ch": AxisArray.Axis.SpaceAxis(labels=[f"ch_{i}" for i in range(n_chans)])
39
+ },
40
+ )
17
41
 
18
42
  backup = [copy.deepcopy(msg_in)]
19
43
 
@@ -25,33 +49,38 @@ def test_affine_generator():
25
49
 
26
50
  assert_messages_equal([msg_in], backup)
27
51
 
52
+ # Send again just to make sure the generator doesn't crash
53
+ _ = gen.send(msg_in)
54
+
28
55
  # Test with weights from a CSV file.
29
56
  csv_path = Path(__file__).parent / "resources" / "xform.csv"
30
57
  weights = np.loadtxt(csv_path, delimiter=",")
31
58
  expected_out = in_dat @ weights.T
32
59
  # Same result: expected_out = np.vstack([(step[None, :] * weights).sum(axis=1) for step in in_dat])
33
60
 
34
- # Send again just to make sure the generator doesn't crash
35
- _ = gen.send(msg_in)
36
-
37
61
  gen = affine_transform(weights=csv_path, axis="ch", right_multiply=False)
38
62
  msg_out = gen.send(msg_in)
39
63
  assert np.allclose(msg_out.data, expected_out)
64
+ assert len(msg_out.axes["ch"].labels) == weights.shape[0]
65
+ assert msg_out.axes["ch"].labels[:-1] == msg_in.axes["ch"].labels
40
66
 
41
67
  # Try again as str, not Path
42
68
  gen = affine_transform(weights=str(csv_path), axis="ch", right_multiply=False)
43
69
  msg_out = gen.send(msg_in)
44
70
  assert np.allclose(msg_out.data, expected_out)
71
+ assert len(msg_out.axes["ch"].labels) == weights.shape[0]
45
72
 
46
73
  # Try again as direct ndarray
47
74
  gen = affine_transform(weights=weights, axis="ch", right_multiply=False)
48
75
  msg_out = gen.send(msg_in)
49
76
  assert np.allclose(msg_out.data, expected_out)
77
+ assert len(msg_out.axes["ch"].labels) == weights.shape[0]
50
78
 
51
79
  # One more time, but we pre-transpose the weights and do not override right_multiply
52
80
  gen = affine_transform(weights=weights.T, axis="ch", right_multiply=True)
53
81
  msg_out = gen.send(msg_in)
54
82
  assert np.allclose(msg_out.data, expected_out)
83
+ assert len(msg_out.axes["ch"].labels) == weights.shape[0]
55
84
 
56
85
 
57
86
  def test_affine_passthrough():
@@ -125,7 +125,7 @@ wheels = [
125
125
 
126
126
  [[package]]
127
127
  name = "ezmsg-sigproc"
128
- version = "1.2.6.dev14+g329dc1b.d20240924"
128
+ version = "1.3.2.dev0+g021511b.d20240926"
129
129
  source = { editable = "." }
130
130
  dependencies = [
131
131
  { name = "ezmsg" },
@@ -154,7 +154,7 @@ requires-dist = [
154
154
  { name = "ezmsg", specifier = ">=3.5.0" },
155
155
  { name = "flake8", marker = "extra == 'test'", specifier = ">=7.1.1" },
156
156
  { name = "frozendict", marker = "extra == 'test'", specifier = ">=2.4.4" },
157
- { name = "numpy", specifier = ">=2.0.2" },
157
+ { name = "numpy", specifier = ">=1.26.0" },
158
158
  { name = "pytest", marker = "extra == 'test'", specifier = ">=8.3.3" },
159
159
  { name = "pytest-asyncio", marker = "extra == 'test'", specifier = ">=0.24.0" },
160
160
  { name = "pytest-cov", marker = "extra == 'test'", specifier = ">=5.0.0" },
File without changes
File without changes
File without changes