Skip to content

Commit bbdf7eb

Browse files
authored
Merge pull request #860 from rgommers/waveletpacketnd-followup
BUG: fix indexing in `reconstruct` method of 1-D/2-D wavelet packet
2 parents 6031ddf + b3b650c commit bbdf7eb

2 files changed

Lines changed: 58 additions & 2 deletions

File tree

pywt/_wavelet_packets.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,9 @@ def _reconstruct(self, update):
675675
)
676676
else:
677677
rec = idwtn(coeffs, self.wavelet, self.mode, axes=self.axes)
678+
if self._data_shape is not None and (
679+
rec.shape != self._data_shape):
680+
rec = rec[tuple([slice(sz) for sz in self._data_shape])]
678681
if update:
679682
self.data = rec
680683
return rec
@@ -741,7 +744,7 @@ def reconstruct(self, update=True):
741744
if self.has_any_subnode:
742745
data = super().reconstruct(update)
743746
if self.data_size is not None and (data.shape != self.data_size):
744-
data = data[[slice(sz) for sz in self.data_size]]
747+
data = data[tuple(slice(sz) for sz in self.data_size)]
745748
if update:
746749
self.data = data
747750
return data
@@ -867,7 +870,7 @@ def reconstruct(self, update=True):
867870
if self.has_any_subnode:
868871
data = super().reconstruct(update)
869872
if self.data_size is not None and (data.shape != self.data_size):
870-
data = data[[slice(sz) for sz in self.data_size]]
873+
data = data[tuple(slice(sz) for sz in self.data_size)]
871874
if update:
872875
self.data = data
873876
return data

pywt/tests/test_wpnd.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,56 @@ def test_wavelet_packet_axes():
168168
# must have non-duplicate axes
169169
assert_raises(ValueError, pywt.WaveletPacketND, data=x, wavelet='db1',
170170
axes=(0, 0))
171+
172+
173+
def test_wavelet_packet_odd_shape():
174+
# the reconstruction has to be trimmed back to the original shape when a
175+
# transformed axis has an odd length
176+
x = np.arange(2 * 2 * 3, dtype=np.float64).reshape(2, 2, 3)
177+
wp = pywt.WaveletPacketND(data=x, wavelet='haar', mode='symmetric',
178+
axes=(0, 1, 2))
179+
wp.get_level(1)
180+
r = wp.reconstruct(update=False)
181+
assert_equal(r.shape, x.shape)
182+
assert_allclose(r, x, atol=1e-12, rtol=1e-12)
183+
184+
rstate = np.random.RandomState(0)
185+
y = rstate.standard_normal((9, 11))
186+
for level in [1, 2, 3]:
187+
wp = pywt.WaveletPacketND(data=y, wavelet='haar', mode='symmetric')
188+
wp.get_level(level)
189+
r = wp.reconstruct(update=False)
190+
assert_equal(r.shape, y.shape)
191+
assert_allclose(r, y, rtol=1e-12)
192+
193+
# only some of the axes transformed
194+
z = rstate.standard_normal((3, 5, 7))
195+
wp = pywt.WaveletPacketND(data=z, wavelet='haar', mode='symmetric',
196+
axes=(1, 2))
197+
wp.get_level(1)
198+
assert_allclose(wp.reconstruct(update=False), z, rtol=1e-12)
199+
200+
# reconstructing again after an update gives the same result
201+
wp = pywt.WaveletPacketND(data=y, wavelet='haar', mode='symmetric')
202+
wp.get_level(2)
203+
assert_allclose(wp.reconstruct(update=True), y, rtol=1e-12)
204+
assert_allclose(wp.reconstruct(update=True), y, rtol=1e-12)
205+
206+
207+
def test_wavelet_packet_odd_shape_subnode():
208+
# a subnode reconstructs to the shape of its own coefficients, so an
209+
# update does not grow the data stored in the node
210+
rstate = np.random.RandomState(0)
211+
y = rstate.standard_normal((9, 11))
212+
wp = pywt.WaveletPacketND(data=y, wavelet='haar', mode='symmetric')
213+
wp.get_level(2)
214+
215+
shape = wp['aa'].data.shape
216+
assert_equal(wp['aa'].reconstruct(update=False).shape, shape)
217+
wp['aa'].reconstruct(update=True)
218+
assert_equal(wp['aa'].data.shape, shape)
219+
220+
# WaveletPacket2D already behaves this way
221+
wp2 = pywt.WaveletPacket2D(data=y, wavelet='haar', mode='symmetric')
222+
wp2.get_level(2)
223+
assert_equal(wp2['a'].reconstruct(update=False).shape, shape)

0 commit comments

Comments
 (0)