From 4408fe95b084ef87a808413d2d00d510e4d04d8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Tue, 13 Oct 2026 15:00:45 +0200 Subject: [PATCH] Fixed failing tests due to updated bindings (#420) - New python bindings return a (1,n_bytes) array instead of a 1d array - Flatten on python side before transform --- RELEASE.md | 7 +++++++ python/aare/transform.py | 4 ++-- python/tests/test_Transformation.py | 31 +++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index adb8405a..907c2668 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -12,6 +12,13 @@ wheels. - added ``NDView::sub_view(index)`` operator returns a subview at index along dimension 0 +### Bugfixes: + +- Fixed ``Matterhorn10Transform`` with 4 bit dynamic range and + ``Mythen302Transform`` failing with ``Expected 1D array, got 2D`` on frames + read through ``CtbRawFile``. The transforms now flatten the frame before + calling the decoders. + ## 2026.9.30 ### New Features: diff --git a/python/aare/transform.py b/python/aare/transform.py index 6d14231f..7739d69e 100644 --- a/python/aare/transform.py +++ b/python/aare/transform.py @@ -135,7 +135,7 @@ class Matterhorn10Transform: elif self.dynamic_range == 8: return np.take(data.view(np.uint8), self.pixel_map).reshape(self.num_counters, Matterhorn10.nRows, Matterhorn10.nCols) else: #dynamic range 4 - return np.take(_aare.expand4to8bit(data.view(np.uint8)), self.pixel_map).reshape(self.num_counters, Matterhorn10.nRows, Matterhorn10.nCols) + return np.take(_aare.expand4to8bit(data.view(np.uint8).reshape(-1)), self.pixel_map).reshape(self.num_counters, Matterhorn10.nRows, Matterhorn10.nCols) class Mythen302Transform: """ @@ -169,7 +169,7 @@ class Mythen302Transform: image : np.ndarray uint32 array of size 64, 3 """ - res = _aare.decode_my302(data, self.offset) + res = _aare.decode_my302(data.reshape(-1), self.offset) res = res.reshape( Mythen302Transform._n_channels, Mythen302Transform._n_counters ) diff --git a/python/tests/test_Transformation.py b/python/tests/test_Transformation.py index 0d91c10a..dad7d409 100644 --- a/python/tests/test_Transformation.py +++ b/python/tests/test_Transformation.py @@ -56,3 +56,34 @@ def test_matterhorn10_16bit_4counters(test_data_path): expected_data = np.tile(np.arange(255, -1, -1,dtype=np.uint16), (4, 256, 1)) # TODO: endianess issue ? assert np.all(frames == expected_data) + + +def test_matterhorn10_4bit_accepts_2d_frame(): + """CtbRawFile.read_frame returns a (1, n_bytes) array; the 4 bit path must accept it""" + n_bytes = (transform.Matterhorn10.nRows * transform.Matterhorn10.nCols * 4) // 8 + data = (np.arange(n_bytes) % 256).astype(np.uint8).reshape(1, n_bytes) + t = transform.Matterhorn10Transform(dynamic_range=4, num_counters=1) + + frames = t(data) + + assert frames.shape == (1, 256, 256) + assert frames.dtype == np.uint8 + + flat = data.reshape(-1) + nibbles = np.stack([flat & 0x0F, flat >> 4], axis=-1).reshape(-1) + expected = np.take(nibbles, t.pixel_map).reshape(1, 256, 256) + assert np.array_equal(frames, expected) + + +def test_mythen302_accepts_2d_frame(): + """CtbRawFile.read_frame returns a (1, n_bytes) array; Mythen302Transform must accept it""" + n_bytes = 64 * 3 * 3 + 2 # two extra bytes for the 4 bit offset + rng = np.random.default_rng(0) + data = rng.integers(0, 256, size=(1, n_bytes), dtype=np.uint8) + t = transform.Mythen302Transform(offset=4) + + res = t(data) + + assert res.shape == (64, 3) + assert res.dtype == np.uint32 + assert np.array_equal(res, t(data.reshape(-1)))