def _call(self, x): """Return wavelet transform of ``x``.""" if self.impl == 'pywt': coeff_list = pywt_multi_level_decomp( x, wavelet=self.pywt_wavelet, nlevels=self.nlevels, mode=self.pywt_pad_mode) return pywt_flat_array_from_coeffs(coeff_list) else: raise RuntimeError("bad `impl` '{}'".format(self.impl))
def test_multilevel_recon_inverts_decomp(shape_setup, floating_dtype): """Test that reco is the inverse of decomp.""" wavelet, pywt_mode, nlevels, image_shape, coeff_shapes = shape_setup image = np.random.uniform(size=image_shape).astype(floating_dtype) wave_decomp = pywt_multi_level_decomp(image, wavelet, nlevels, pywt_mode) wave_recon = pywt_multi_level_recon(wave_decomp, wavelet, pywt_mode, image_shape) assert wave_recon.shape == image.shape assert all_almost_equal(wave_recon, image)
def test_explicit_example(odl_floating_dtype): """Comparison with hand-calculated wavelet transform.""" dtype = odl_floating_dtype space = odl.uniform_discr([0, 0], [1, 1], (16, 15), dtype=dtype) x = noise_array(space).reshape(space.shape) # We use a Daubechies-2 wavelet wavelet = pywt.Wavelet('db2') filter_l = np.array(wavelet.dec_lo) filter_h = np.array(wavelet.dec_hi) # Build the 2D filters filter_ll = filter_l[:, None] * filter_l[None, :] filter_lh = filter_l[:, None] * filter_h[None, :] filter_hl = filter_h[:, None] * filter_l[None, :] filter_hh = filter_h[:, None] * filter_h[None, :] # Convolve x with 2D filters (implicitly uses zero-padding) conv_ll = convolve(x, filter_ll) conv_lh = convolve(x, filter_lh) conv_hl = convolve(x, filter_hl) conv_hh = convolve(x, filter_hh) # Downsampling by factor 2, taking the odd indices, gives the wavelet # coefficients coeff_aa = conv_ll[1::2, 1::2] coeff_ad = conv_lh[1::2, 1::2] coeff_da = conv_hl[1::2, 1::2] coeff_dd = conv_hh[1::2, 1::2] # Compare with single-level wavelet trafo (zero padding) coeffs = pywt_single_level_decomp(x, wavelet='db2', mode='zero') approx, details = coeffs assert all_almost_equal(approx, coeff_aa) assert all_almost_equal(details, [coeff_ad, coeff_da, coeff_dd]) # Second level, continuing with the level 1 approximation coefficient coeff_2_aa = convolve(coeff_aa, filter_ll)[1::2, 1::2] coeff_2_ad = convolve(coeff_aa, filter_lh)[1::2, 1::2] coeff_2_da = convolve(coeff_aa, filter_hl)[1::2, 1::2] coeff_2_dd = convolve(coeff_aa, filter_hh)[1::2, 1::2] # Compare with multi-level wavelet trafo (zero padding) coeffs = pywt_multi_level_decomp(x, wavelet='db2', mode='zero', nlevels=2) approx_2, details_2, details_1 = coeffs assert all_almost_equal(approx_2, coeff_2_aa) assert all_almost_equal(details_1, [coeff_ad, coeff_da, coeff_dd]) assert all_almost_equal(details_2, [coeff_2_ad, coeff_2_da, coeff_2_dd])
def test_explicit_example(floating_dtype): """Comparison with hand-calculated wavelet transform.""" space = odl.uniform_discr([0, 0], [1, 1], (16, 15), dtype=floating_dtype) x = noise_array(space).reshape(space.shape) # We use a Daubechies-2 wavelet wavelet = pywt.Wavelet('db2') filter_l = np.array(wavelet.dec_lo) filter_h = np.array(wavelet.dec_hi) # Build the 2D filters filter_ll = filter_l[:, None] * filter_l[None, :] filter_lh = filter_l[:, None] * filter_h[None, :] filter_hl = filter_h[:, None] * filter_l[None, :] filter_hh = filter_h[:, None] * filter_h[None, :] # Convolve x with 2D filters (implicitly uses zero-padding) conv_ll = convolve(x, filter_ll) conv_lh = convolve(x, filter_lh) conv_hl = convolve(x, filter_hl) conv_hh = convolve(x, filter_hh) # Downsampling by factor 2, taking the odd indices, gives the wavelet # coefficients coeff_aa = conv_ll[1::2, 1::2] coeff_ad = conv_lh[1::2, 1::2] coeff_da = conv_hl[1::2, 1::2] coeff_dd = conv_hh[1::2, 1::2] # Compare with single-level wavelet trafo (zero padding) coeffs = pywt_single_level_decomp(x, wavelet='db2', mode='zero') approx, details = coeffs assert all_almost_equal(approx, coeff_aa) assert all_almost_equal(details, [coeff_ad, coeff_da, coeff_dd]) # Second level, continuing with the level 1 approximation coefficient coeff_2_aa = convolve(coeff_aa, filter_ll)[1::2, 1::2] coeff_2_ad = convolve(coeff_aa, filter_lh)[1::2, 1::2] coeff_2_da = convolve(coeff_aa, filter_hl)[1::2, 1::2] coeff_2_dd = convolve(coeff_aa, filter_hh)[1::2, 1::2] # Compare with multi-level wavelet trafo (zero padding) coeffs = pywt_multi_level_decomp(x, wavelet='db2', mode='zero', nlevels=2) approx_2, details_2, details_1 = coeffs assert all_almost_equal(approx_2, coeff_2_aa) assert all_almost_equal(details_1, [coeff_ad, coeff_da, coeff_dd]) assert all_almost_equal(details_2, [coeff_2_ad, coeff_2_da, coeff_2_dd])
def test_multilevel_decomp_inverts_recon(shape_setup): """Test that decomp is the inverse of recon.""" dtype = 'float64' # when fixed, use dtype fixture instead wavelet, pywt_mode, nlevels, image_shape, coeff_shapes = shape_setup if not ((ndim == 1 and wavelet == 'sym2' and pywt_mode == 'periodization') or (ndim == 1 and wavelet == 'db1' and pywt_mode in ('zero', 'periodization'))): # The reverse invertibility is not given since the wavelet # decomposition as implemented in PyWavelets, is not left-invertible. # Only some setups work by miracle. # TODO: investigate further pytest.xfail('not left-invertible') coeffs, _ = _grouped_and_flat_arrays(coeff_shapes, dtype) wave_recon = pywt_multi_level_recon(coeffs, wavelet, pywt_mode, recon_shape=image_shape) wave_decomp = pywt_multi_level_decomp(wave_recon, wavelet, nlevels, pywt_mode) assert all_almost_equal(coeffs, wave_decomp)