def test_dwt_coeff_len(): x = np.array([3, 7, 1, 1, -2, 5, 4, 6]) w = pywt.Wavelet("sym3") ln_modes = [pywt.dwt_coeff_len(len(x), w.dec_len, mode) for mode in pywt.Modes.modes] assert_allclose(ln_modes, [6, 6, 6, 6, 6, 6, 4]) ln_modes = [pywt.dwt_coeff_len(len(x), w, mode) for mode in pywt.Modes.modes] assert_allclose(ln_modes, [6, 6, 6, 6, 6, 6, 4])
def compose_wvlt_from_vec(pin, imshape, wavelet='db4', mode='symmetric'): #currently limited to square geometry w = pywt.Wavelet(wavelet) Nl = pywt.dwt_max_level(max(imshape), w.dec_len) levlens = [pywt.dwt_coeff_len(max(imshape), w.dec_len, mode=mode)] for j in range(1, Nl): levlens.append(pywt.dwt_coeff_len(levlens[-1], w.dec_len, mode=mode)) levlens.append(levlens[-1]) levlens = levlens[::-1] p_wvlt = [ reshape(array(pin[0:levlens[0]**2], float), (levlens[0], levlens[0])) ] celem = levlens[0]**2 for j in range(1, Nl + 1): t1 = reshape(array(pin[celem:celem + levlens[j]**2], float), (levlens[j], levlens[j])) celem += levlens[j]**2 t2 = reshape(array(pin[celem:celem + levlens[j]**2], float), (levlens[j], levlens[j])) celem += levlens[j]**2 t3 = reshape(array(pin[celem:celem + levlens[j]**2], float), (levlens[j], levlens[j])) celem += levlens[j]**2 p_wvlt.append((t1, t2, t3)) return p_wvlt
def test_dwt_coeff_len(): x = np.array([3, 7, 1, 1, -2, 5, 4, 6]) w = pywt.Wavelet('sym3') ln = pywt.dwt_coeff_len(data_len=len(x), filter_len=w.dec_len, mode='sym') assert_(ln == 6) ln_modes = [pywt.dwt_coeff_len(len(x), w.dec_len, mode) for mode in pywt.MODES.modes] assert_allclose(ln_modes, [6, 6, 6, 6, 6, 4])
def test_dwt_coeff_len(): x = np.array([3, 7, 1, 1, -2, 5, 4, 6]) w = pywt.Wavelet('sym3') ln_modes = [pywt.dwt_coeff_len(len(x), w.dec_len, mode) for mode in pywt.Modes.modes] assert_allclose(ln_modes, [6, 6, 6, 6, 6, 4]) ln_modes = [pywt.dwt_coeff_len(len(x), w, mode) for mode in pywt.Modes.modes] assert_allclose(ln_modes, [6, 6, 6, 6, 6, 4])
def test_dwt_coeff_len(): x = np.array([3, 7, 1, 1, -2, 5, 4, 6]) w = pywt.Wavelet('sym3') ln = pywt.dwt_coeff_len(data_len=len(x), filter_len=w.dec_len, mode='sym') assert_(ln == 6) ln_modes = [ pywt.dwt_coeff_len(len(x), w.dec_len, mode) for mode in pywt.MODES.modes ] assert_allclose(ln_modes, [6, 6, 6, 6, 6, 4])
def test_dwt_coeff_len(): x = np.array([3, 7, 1, 1, -2, 5, 4, 6]) w = pywt.Wavelet('sym3') ln_modes = [pywt.dwt_coeff_len(len(x), w.dec_len, mode) for mode in pywt.Modes.modes] expected_result = [6, ] * len(pywt.Modes.modes) expected_result[pywt.Modes.modes.index('periodization')] = 4 assert_allclose(ln_modes, expected_result) ln_modes = [pywt.dwt_coeff_len(len(x), w, mode) for mode in pywt.Modes.modes] assert_allclose(ln_modes, expected_result)
def full_coeff_len(datalen, filtlen, mode): max_level = pywt.dwt_max_level(datalen, filtlen) total_len = 0 for i in xrange(max_level): datalen = pywt.dwt_coeff_len(datalen, filtlen, mode) total_len += datalen return total_len + datalen
def __init__(self, depth, init_wavelet, scales, p_drop=0.5): super().__init__() print("wavelet dropout:", p_drop) self.scales = scales self.wavelet = init_wavelet self.mode = "zero" self.coefficient_len_lst = [depth] for _ in range(scales): self.coefficient_len_lst.append( pywt.dwt_coeff_len( self.coefficient_len_lst[-1], init_wavelet.dec_lo.shape[-1], self.mode, )) self.coefficient_len_lst = self.coefficient_len_lst[1:] self.coefficient_len_lst.append(self.coefficient_len_lst[-1]) wave_depth = np.sum(self.coefficient_len_lst) self.depth = depth self.diag_vec_s = Parameter( torch.from_numpy(np.ones(depth, np.float32))) self.diag_vec_g = Parameter( torch.from_numpy(np.ones(wave_depth, np.float32))) self.diag_vec_b = Parameter( torch.from_numpy(np.ones(depth, np.float32))) perm = np.random.permutation(np.eye(wave_depth, dtype=np.float32)) self.perm = Parameter(torch.from_numpy(perm), requires_grad=False) self.drop_s = torch.nn.Dropout(p=p_drop) self.drop_g = torch.nn.Dropout(p=p_drop) self.drop_b = torch.nn.Dropout(p=p_drop)
def func_IDWT(I_W, level=LEVEL, wavelet=BIOR, mode=MODE): ''' 小波逆变换,将输入的小波参数,根据小波变换等级,小波类型,变换模式将小波参数逆变换为原图像 IDWT I_W : numpy array level : wavelet level wavelet : wavelet type mode : wavelet mode ''' width = I_W.shape[0] height = I_W.shape[0] S = [-1] * level current_size = width for i in range(level): current_size = pywt.dwt_coeff_len(current_size, pywt.Wavelet(BIOR), MODE) S[i] = current_size S.reverse() for current_size in S: # current_size = S[i] LL = I_W[0:current_size, 0:current_size] LH = I_W[0:current_size, current_size:2 * current_size] HL = I_W[current_size:2 * current_size, 0:current_size] HH = I_W[current_size:2 * current_size, current_size:2 * current_size] coeffs = [LL, [LH, HL, HH]] I_W[0:2 * current_size, 0:2 * current_size] = pywt.idwt2(coeffs, wavelet, MODE) return I_W
def compose_vec_from_wvlt(p_wvlt,imshape,wavelet='db4',mode='symmetric'): #currently limited to square geometry w=pywt.Wavelet(wavelet) Nl=pywt.dwt_max_level(max(imshape),w.dec_len) levlens=[pywt.dwt_coeff_len(max(imshape),w.dec_len,mode=mode)] for j in range(1,Nl): levlens.append( pywt.dwt_coeff_len(levlens[-1],w.dec_len,mode=mode) ) levlens.append(levlens[-1]) levlens=levlens[::-1] Na=sum(levlens) ret_arr = empty( (Na*Na,),float) ret_arr[0:levlens[0]**2] = ravel(p_wvlt[0]) celem=levlens[0]**2 for j in range(1,Nl+1): for k in range(3): ret_arr[celem:celem+levlens[j]**2]=ravel(p_wvlt[j][k]) celem+=levlens[j]**2 return ret_arr
def compose_vec_from_wvlt(p_wvlt, imshape, wavelet='db4', mode='symmetric'): #currently limited to square geometry w = pywt.Wavelet(wavelet) Nl = pywt.dwt_max_level(max(imshape), w.dec_len) levlens = [pywt.dwt_coeff_len(max(imshape), w.dec_len, mode=mode)] for j in range(1, Nl): levlens.append(pywt.dwt_coeff_len(levlens[-1], w.dec_len, mode=mode)) levlens.append(levlens[-1]) levlens = levlens[::-1] Na = sum(levlens) ret_arr = empty((Na * Na, ), float) ret_arr[0:levlens[0]**2] = ravel(p_wvlt[0]) celem = levlens[0]**2 for j in range(1, Nl + 1): for k in range(3): ret_arr[celem:celem + levlens[j]**2] = ravel(p_wvlt[j][k]) celem += levlens[j]**2 return ret_arr
def full_coeff_len(datalen, filtlen, mode): max_level = wt.dwt_max_level(datalen, filtlen) total_len = 0 for i in xrange(max_level): datalen = wt.dwt_coeff_len(datalen, filtlen, mode) total_len += datalen return total_len + datalen
def compose_wvlt_from_vec(pin,imshape,wavelet='db4',mode='symmetric'): #currently limited to square geometry w=pywt.Wavelet(wavelet) Nl=pywt.dwt_max_level(max(imshape),w.dec_len) levlens=[pywt.dwt_coeff_len(max(imshape),w.dec_len,mode=mode)] for j in range(1,Nl): levlens.append( pywt.dwt_coeff_len(levlens[-1],w.dec_len,mode=mode) ) levlens.append(levlens[-1]) levlens=levlens[::-1] p_wvlt=[reshape(array(pin[0:levlens[0]**2],float),(levlens[0],levlens[0]))] celem=levlens[0]**2 for j in range(1,Nl+1): t1=reshape(array(pin[celem:celem+levlens[j]**2],float),(levlens[j],levlens[j])) celem+=levlens[j]**2 t2=reshape(array(pin[celem:celem+levlens[j]**2],float),(levlens[j],levlens[j])) celem+=levlens[j]**2 t3=reshape(array(pin[celem:celem+levlens[j]**2],float),(levlens[j],levlens[j])) celem+=levlens[j]**2 p_wvlt.append( (t1,t2,t3) ) return p_wvlt
def compute_coeff_no(self, init_length): """ Compute the number of resulting wavelet coefficients. @param init_length: length of the input signal vector. """ lengths = [init_length] for J in range(self.scales): lengths.append( pywt.dwt_coeff_len(lengths[-1], self.dec_lo.shape[-1], self.mode)) lengths.append(lengths[-1]) return lengths[1:]
def wavelet_BSS(data): raw = data tp,channels = raw.shape wv = pywt.Wavelet('dmey') reduced_tp = int(pywt.dwt_coeff_len(data_len=tp, filter_len=wv.dec_len, mode='symmetric')) WT = np.zeros((reduced_tp,channels-1)) #coeff = np.zeros((22)) #coeffcients from wavelet transformation coeff = np.zeros((reduced_tp,channels-1)) for c in range(channels-1): #exclude the markers A,B = wavelet_trans(raw[:,c],wv) WT[:,c] = A #coeff[c] = B coeff[:,c] = B n=19 #general neurology techniques say to keep as many channels as possible #Essentially, remove the noisiest channel #The remaining channels will be cleaned # Z = WT #Define source space as wavelet data ica = FastICA(n_components = n-1,whiten=True) #use all components but one Z_ = ica.fit_transform(Z) #Estimated Source Space A_ = ica.mixing_ #Retrieve estimated mixing matrix with reduced dimension W_p = np.linalg.pinv(A_) #forced inverse of modified mixing matrix is the unmixing matrix #X_filt = np.matmul(Z_,A_) ####create cleaned stack with outlier_detection#### weights = np.zeros((reduced_tp,Z_.shape[1])) stacks = np.zeros((reduced_tp,Z_.shape[1])) for c_ in range(Z_.shape[1]): inp = Z_[:,c_] weights[:,c_],stacks[:,c_] = outlier_detection(inp) stacks = robust_referencing(stacks,weights) cleaned_Z_ = stacks.reshape((Z_.shape[0],Z_.shape[1])) inv_cleaned_Z_ = ica.inverse_transform(cleaned_Z_) inv_wavelet_cleaned_ica = np.zeros((tp,channels-1)) for c in range(channels-1): #exclude the markers cA = inv_cleaned_Z_[:,c] cD = coeff[:,c] inv_data = inverse_wavelet(cA,cD) inv_wavelet_cleaned_ica[:,c] = inv_data return inv_wavelet_cleaned_ica;
def quad_afb2d(x, cols, rows, mode='zero', split=True, stride=2): """ Does a single level 2d wavelet decomposition of an input. Does separate row and column filtering by two calls to :py:func:`pytorch_wavelets.dwt.lowlevel.afb1d` Inputs: x (torch.Tensor): Input to decompose filts (list of ndarray or torch.Tensor): If a list of tensors has been given, this function assumes they are in the right form (the form returned by :py:func:`~pytorch_wavelets.dwt.lowlevel.prep_filt_afb2d`). Otherwise, this function will prepare the filters to be of the right form by calling :py:func:`~pytorch_wavelets.dwt.lowlevel.prep_filt_afb2d`. mode (str): 'zero', 'symmetric', 'reflect' or 'periodization'. Which padding to use. If periodization, the output size will be half the input size. Otherwise, the output size will be slightly larger than half. """ x = x / 2 C = x.shape[1] cols = torch.cat([cols] * C, dim=0) rows = torch.cat([rows] * C, dim=0) if mode == 'per' or mode == 'periodization': # Do column filtering L = cols.shape[2] L2 = L // 2 if x.shape[2] % 2 == 1: x = torch.cat((x, x[:, :, -1:]), dim=2) N2 = x.shape[2] // 2 x = roll(x, -L2, dim=2) pad = (L - 1, 0) lohi = F.conv2d(x, cols, padding=pad, stride=(stride, 1), groups=C) lohi[:, :, :L2] = lohi[:, :, :L2] + lohi[:, :, N2:N2 + L2] lohi = lohi[:, :, :N2] # Do row filtering L = rows.shape[3] L2 = L // 2 if lohi.shape[3] % 2 == 1: lohi = torch.cat((lohi, lohi[:, :, :, -1:]), dim=3) N2 = x.shape[3] // 2 lohi = roll(lohi, -L2, dim=3) pad = (0, L - 1) w = F.conv2d(lohi, rows, padding=pad, stride=(1, stride), groups=8 * C) w[:, :, :, :L2] = w[:, :, :, :L2] + w[:, :, :, N2:N2 + L2] w = w[:, :, :, :N2] elif mode == 'zero': # Do column filtering N = x.shape[2] L = cols.shape[2] outsize = pywt.dwt_coeff_len(N, L, mode='zero') p = 2 * (outsize - 1) - N + L # Sadly, pytorch only allows for same padding before and after, if # we need to do more padding after for odd length signals, have to # prepad if p % 2 == 1: x = F.pad(x, (0, 0, 0, 1)) pad = (p // 2, 0) # Calculate the high and lowpass lohi = F.conv2d(x, cols, padding=pad, stride=(stride, 1), groups=C) # Do row filtering N = lohi.shape[3] L = rows.shape[3] outsize = pywt.dwt_coeff_len(N, L, mode='zero') p = 2 * (outsize - 1) - N + L if p % 2 == 1: lohi = F.pad(lohi, (0, 1, 0, 0)) pad = (0, p // 2) w = F.conv2d(lohi, rows, padding=pad, stride=(1, stride), groups=8 * C) elif mode == 'symmetric' or mode == 'reflect': # Do column filtering N = x.shape[2] L = cols.shape[2] outsize = pywt.dwt_coeff_len(N, L, mode=mode) p = 2 * (outsize - 1) - N + L x = mypad(x, pad=(0, 0, p // 2, (p + 1) // 2), mode=mode) lohi = F.conv2d(x, cols, stride=(stride, 1), groups=C) # Do row filtering N = lohi.shape[3] L = rows.shape[3] outsize = pywt.dwt_coeff_len(N, L, mode=mode) p = 2 * (outsize - 1) - N + L lohi = mypad(lohi, pad=(p // 2, (p + 1) // 2, 0, 0), mode=mode) w = F.conv2d(lohi, rows, stride=(1, stride), groups=8 * C) else: raise ValueError("Unkown pad type: {}".format(mode)) y = w.view((w.shape[0], C, 4, 4, w.shape[-2], w.shape[-1])) yl = y[:, :, :, 0] yh = y[:, :, :, 1:] deg75r, deg105i = pm(yh[:, :, 0, 0], yh[:, :, 3, 0]) deg105r, deg75i = pm(yh[:, :, 1, 0], yh[:, :, 2, 0]) deg15r, deg165i = pm(yh[:, :, 0, 1], yh[:, :, 3, 1]) deg165r, deg15i = pm(yh[:, :, 1, 1], yh[:, :, 2, 1]) deg135r, deg45i = pm(yh[:, :, 0, 2], yh[:, :, 3, 2]) deg45r, deg135i = pm(yh[:, :, 1, 2], yh[:, :, 2, 2]) yhr = torch.stack((deg15r, deg45r, deg75r, deg105r, deg135r, deg165r), dim=1) yhi = torch.stack((deg15i, deg45i, deg75i, deg105i, deg135i, deg165i), dim=1) yh = torch.stack((yhr, yhi), dim=-1) yl_rowa = torch.stack((yl[:, :, 1], yl[:, :, 0]), dim=-1) yl_rowb = torch.stack((yl[:, :, 3], yl[:, :, 2]), dim=-1) yl_rowa = yl_rowa.view(yl.shape[0], C, yl.shape[-2], yl.shape[-1] * 2) yl_rowb = yl_rowb.view(yl.shape[0], C, yl.shape[-2], yl.shape[-1] * 2) z = torch.stack((yl_rowb, yl_rowa), dim=-2) yl = z.view(yl.shape[0], C, yl.shape[-2] * 2, yl.shape[-1] * 2) return yl.contiguous(), yh
def quad_afb2d_nonsep(x, filts, mode='zero'): """ Does a 1 level 2d wavelet decomposition of an input. Doesn't do separate row and column filtering. Inputs: x (torch.Tensor): Input to decompose filts (list or torch.Tensor): If a list is given, should be the low and highpass filter banks. If a tensor is given, it should be of the form created by :py:func:`pytorch_wavelets.dwt.lowlevel.prep_filt_afb2d_nonsep` mode (str): 'zero', 'symmetric', 'reflect' or 'periodization'. Which padding to use. If periodization, the output size will be half the input size. Otherwise, the output size will be slightly larger than half. """ C = x.shape[1] Ny = x.shape[2] Nx = x.shape[3] # Check the filter inputs f = torch.cat([filts] * C, dim=0) Ly = f.shape[2] Lx = f.shape[3] if mode == 'periodization' or mode == 'per': if x.shape[2] % 2 == 1: x = torch.cat((x, x[:, :, -1:]), dim=2) Ny += 1 if x.shape[3] % 2 == 1: x = torch.cat((x, x[:, :, :, -1:]), dim=3) Nx += 1 pad = (Ly - 1, Lx - 1) stride = (2, 2) x = roll(roll(x, -Ly // 2, dim=2), -Lx // 2, dim=3) y = F.conv2d(x, f, padding=pad, stride=stride, groups=C) y[:, :, :Ly // 2] += y[:, :, Ny // 2:Ny // 2 + Ly // 2] y[:, :, :, :Lx // 2] += y[:, :, :, Nx // 2:Nx // 2 + Lx // 2] y = y[:, :, :Ny // 2, :Nx // 2] elif mode == 'zero' or mode == 'symmetric' or mode == 'reflect': # Calculate the pad size out1 = pywt.dwt_coeff_len(Ny, Ly, mode=mode) out2 = pywt.dwt_coeff_len(Nx, Lx, mode=mode) p1 = 2 * (out1 - 1) - Ny + Ly p2 = 2 * (out2 - 1) - Nx + Lx if mode == 'zero': # Sadly, pytorch only allows for same padding before and after, if # we need to do more padding after for odd length signals, have to # prepad if p1 % 2 == 1 and p2 % 2 == 1: x = F.pad(x, (0, 1, 0, 1)) elif p1 % 2 == 1: x = F.pad(x, (0, 0, 0, 1)) elif p2 % 2 == 1: x = F.pad(x, (0, 1, 0, 0)) # Calculate the high and lowpass y = F.conv2d(x, f, padding=(p1 // 2, p2 // 2), stride=2, groups=C) elif mode == 'symmetric' or mode == 'reflect': pad = (p2 // 2, (p2 + 1) // 2, p1 // 2, (p1 + 1) // 2) x = mypad(x, pad=pad, mode=mode) y = F.conv2d(x, f, stride=2, groups=C) else: raise ValueError("Unkown pad type: {}".format(mode)) y = y.reshape((y.shape[0], C, 4, y.shape[-2], y.shape[-1])) yl = y[:, :, 0].contiguous() yh = y[:, :, 1:].contiguous() return yl, yh
haar = pywt.Wavelet('haar') db = pywt.Wavelet('db2') # returns [decomposition, reconstruction] x [low, high] # reconstruction seem to be the ones i'm familiar with haar.filter_bank scale_vals, wavelet_vals, x_vals = haar.wavefun() plt.plot(x_vals, scale_vals) plt.show() plt.plot(x_vals, wavelet_vals) plt.show() # length of the coefficients print pywt.dwt_coeff_len(x.shape[0], haar, "sym") print pywt.dwt_coeff_len(8, 2, "sym") # Maximum useful level of decomposition for # This is currently logged as a bug print pywt.dwt_max_level(x.shape[0], haar.dec_len) coeffs3 = pywt.wavedec(x, haar, mode='sym', level=3) # Let's see if I can recover the c(1) = (0, 2) coeffs2 = pywt.wavedec(x, haar, mode='sym', level=2) decimated = coeffs[0] # http://wavelets.pybytes.com/wavelet/db2/ scale_vals, wavelet_vals, x_vals = db.wavefun() plt.plot(x_vals, scale_vals)
def afb1d(x, h0, h1, mode='zero', dim=-1): """ 1D analysis filter bank (along one dimension only) of an image Inputs: x (tensor): 4D input with the last two dimensions the spatial input h0 (tensor): 4D input for the lowpass filter. Should have shape (1, 1, h, 1) or (1, 1, 1, w) h1 (tensor): 4D input for the highpass filter. Should have shape (1, 1, h, 1) or (1, 1, 1, w) mode (str): padding method dim (int) - dimension of filtering. d=2 is for a vertical filter (called column filtering but filters across the rows). d=3 is for a horizontal filter, (called row filtering but filters across the columns). Returns: lohi: lowpass and highpass subbands concatenated along the channel dimension """ C = x.shape[1] # Convert the dim to positive d = dim % 4 s = (2, 1) if d == 2 else (1, 2) N = x.shape[d] # If h0, h1 are not tensors, make them. If they are, then assume that they # are in the right order if not isinstance(h0, torch.Tensor): h0 = torch.tensor(np.copy(np.array(h0).ravel()[::-1]), dtype=torch.float, device=x.device) if not isinstance(h1, torch.Tensor): h1 = torch.tensor(np.copy(np.array(h1).ravel()[::-1]), dtype=torch.float, device=x.device) L = h0.numel() L2 = L // 2 shape = [1, 1, 1, 1] shape[d] = L # If h aren't in the right shape, make them so if h0.shape != tuple(shape): h0 = h0.reshape(*shape) if h1.shape != tuple(shape): h1 = h1.reshape(*shape) h = torch.cat([h0, h1] * C, dim=0) if mode == 'per' or mode == 'periodization': if x.shape[dim] % 2 == 1: if d == 2: x = torch.cat((x, x[:, :, -1:]), dim=2) else: x = torch.cat((x, x[:, :, :, -1:]), dim=3) N += 1 x = roll(x, -L2, dim=d) pad = (L - 1, 0) if d == 2 else (0, L - 1) lohi = F.conv2d(x, h, padding=pad, stride=s, groups=C) N2 = N // 2 if d == 2: lohi[:, :, :L2] = lohi[:, :, :L2] + lohi[:, :, N2:N2 + L2] lohi = lohi[:, :, :N2] else: lohi[:, :, :, :L2] = lohi[:, :, :, :L2] + lohi[:, :, :, N2:N2 + L2] lohi = lohi[:, :, :, :N2] else: # Calculate the pad size outsize = pywt.dwt_coeff_len(N, L, mode=mode) p = 2 * (outsize - 1) - N + L if mode == 'zero': # Sadly, pytorch only allows for same padding before and after, if # we need to do more padding after for odd length signals, have to # prepad if p % 2 == 1: pad = (0, 0, 0, 1) if d == 2 else (0, 1, 0, 0) x = F.pad(x, pad) pad = (p // 2, 0) if d == 2 else (0, p // 2) # Calculate the high and lowpass lohi = F.conv2d(x, h, padding=pad, stride=s, groups=C) elif mode == 'symmetric' or mode == 'reflect' or mode == 'periodic': pad = (0, 0, p // 2, (p + 1) // 2) if d == 2 else (p // 2, (p + 1) // 2, 0, 0) x = mypad(x, pad=pad, mode=mode) lohi = F.conv2d(x, h, stride=s, groups=C) else: raise ValueError("Unkown pad type: {}".format(mode)) return lohi
def coeff_size_list(shape, nscales, wbasis, mode): """Construct a size list from given wavelet coefficients. Related to 1D, 2D and 3D multidimensional wavelet transforms that utilize `PyWavelets <http://www.pybytes.com/pywavelets/>`_. Parameters ---------- shape : `tuple` Number of pixels/voxels in the image. Its length must be 1, 2 or 3. nscales : `int` Number of scales in the multidimensional wavelet transform. This parameter is checked against the maximum number of scales returned by ``pywt.dwt_max_level``. For more information see the `PyWavelets documentation on the maximum level of scales <http://www.pybytes.com/pywavelets/ref/\ dwt-discrete-wavelet-transform.html#maximum-decomposition-level\ -dwt-max-level>`_. wbasis : ``pywt.Wavelet`` Selected wavelet basis. For more information see the `PyWavelets documentation on wavelet bases <http://www.pybytes.com/pywavelets/ref/wavelets.html>`_. mode : `str` Signal extention mode. Possible extension modes are 'zpd': zero-padding -- signal is extended by adding zero samples 'cpd': constant padding -- border values are replicated 'sym': symmetric padding -- signal extension by mirroring samples 'ppd': periodic padding -- signal is trated as a periodic one 'sp1': smooth padding -- signal is extended according to the first derivatives calculated on the edges (straight line) 'per': periodization -- like periodic-padding but gives the smallest possible number of decomposition coefficients. Returns ------- size_list : `list` A list containing the sizes of the wavelet (approximation and detail) coefficients at different scaling levels: ``size_list[0]`` = size of approximation coefficients at the coarsest level ``size_list[1]`` = size of the detail coefficients at the coarsest level ... ``size_list[N]`` = size of the detail coefficients at the finest level ``size_list[N+1]`` = size of the original image ``N`` = number of scaling levels = nscales """ if len(shape) not in (1, 2, 3): raise ValueError('shape must have length 1, 2 or 3, got {}.' ''.format(len(shape))) max_level = pywt.dwt_max_level(shape[0], filter_len=wbasis.dec_len) if nscales > max_level: raise ValueError('Too many scaling levels, got {}, maximum useful' ' level is {}' ''.format(nscales, max_level)) # dwt_coeff_len calculates the number of coefficients at the next # scaling level given the input size, the length of the filter and # the applied mode. # We use this in the following way (per dimension): # - length[0] = original data length # - length[n+1] = dwt_coeff_len(length[n], ...) # - until n = nscales size_list = [shape] for scale in range(nscales): shp = tuple(pywt.dwt_coeff_len(n, filter_len=wbasis.dec_len, mode=mode) for n in size_list[scale]) size_list.append(shp) # Add a duplicate of the last entry for the approximation coefficients size_list.append(size_list[-1]) # We created the list in reversed order compared to what pywt expects size_list.reverse() return size_list
def pywt_coeff_shapes(shape, wavelet, nlevels, mode): """Return a list of coefficient shapes in the specified transform. The wavelet transform specified by ``wavelet``, ``nlevels`` and ``mode`` produces a sequence of approximation and detail coefficients. This function computes the shape of those coefficient arrays and returns them as a list. Parameters ---------- shape : sequence Shape of an input to the transform. wavelet : string or `pywt.Wavelet` Specification of the wavelet to be used in the transform. If a string is given, it is converted to a `pywt.Wavelet`. Use `pywt.wavelist` to get a list of available wavelets. nlevels : positive int Number of scaling levels to be used in the decomposition. The maximum number of levels can be calculated with `pywt.dwt_max_level`. mode : string, optional PyWavelets style signal extension mode. See `signal extension modes`_ for available options. Returns ------- shapes : list The shapes of the approximation and detail coefficients at different scaling levels in the following order: ``[shape_aN, shape_DN, ..., shape_D1]`` Here, ``shape_aN`` is the shape of the N-th level approximation coefficient array, and ``shape_Di`` is the shape of all i-th level detail coefficients. See Also -------- pywt.dwt_coeff_len : function used to determine coefficient sizes at each scaling level Examples -------- Determine the coefficient shapes for 2 scaling levels in 3 dimensions with zero-padding. Approximation coefficient shape comes first, then the level-2 detail coefficient and last the level-1 detail coefficient: >>> pywt_coeff_shapes(shape=(16, 17, 18), wavelet='db2', nlevels=2, ... mode='zero') [(6, 6, 6), (6, 6, 6), (9, 10, 10)] References ---------- .. _signal extension modes: https://pywavelets.readthedocs.io/en/latest/ref/signal-extension-\ modes.html """ shape = tuple(shape) if any(int(s) != s for s in shape): raise ValueError('`shape` may only contain integers, got {}' ''.format(shape)) wavelet = pywt_wavelet(wavelet) nlevels, nlevels_in = int(nlevels), nlevels if nlevels_in != nlevels: raise ValueError('`nlevels` must be integer, got {}' ''.format(nlevels_in)) # TODO: adapt for axes for i, n in enumerate(shape): max_levels = pywt.dwt_max_level(n, wavelet.dec_len) if max_levels == 0: raise ValueError('in axis {}: data size {} too small for ' 'transform, results in maximal `nlevels` of 0' ''.format(i, n)) if not 0 < nlevels <= max_levels: raise ValueError('in axis {}: `nlevels` must satisfy 0 < nlevels ' '<= {}, got {}' ''.format(i, max_levels, nlevels)) mode, mode_in = str(mode).lower(), mode if mode not in PYWT_SUPPORTED_MODES: raise ValueError("mode '{}' not understood".format(mode_in)) # Use pywt.dwt_coeff_len to determine the coefficient lengths at each # scale recursively. Start with the image shape and use the last created # shape for the next step. shape_list = [shape] for _ in range(nlevels): shape = tuple( pywt.dwt_coeff_len(n, filter_len=wavelet.dec_len, mode=mode) for n in shape_list[-1]) shape_list.append(shape) # Add a duplicate of the last entry for the approximation coefficients shape_list.append(shape_list[-1]) # We created the list in reversed order, reverse it. Remove also the # superfluous image shape at the end. shape_list.reverse() shape_list.pop() return shape_list
# Multilevel decomposition using from pywt import wavedec cA2, cD2, cD1 = wavedec([1, 2, 3, 4, 3, 2, 1], "db1", level=2) print(cA2) print(cD2) print(cD1) print() # Partial Discrete Wavelet Transform data decomposition # Similar to pywt.dwt, but computes only one set of coefficients. # Useful when you need only approximation or only details at the given level. coeffs = pywt.downcoef(part="a", data=[1, 2, 3, 4, 3, 2, 1], wavelet="db1", level=2) print(coeffs) print() # Maximum decomposition level w = pywt.Wavelet("sym5") l = pywt.dwt_max_level(data_len=1000, filter_len=w.dec_len) print(l) l = pywt.dwt_max_level(data_len=1000, filter_len=w) print(l) print() # Result coefficients length l = pywt.dwt_coeff_len(data_len=1000, filter_len=w, mode="per") print(l)
def discrete_wavelet_transform_example(): x = [3, 7, 1, 1, -2, 5, 4, 6] cA, cD = pywt.dwt(x, 'db2') # Approximation and detail coefficients. print('Approximation coefficients =', cA) print('Detail coefficients =', cD) print('Single level reconstruction of signal =', pywt.idwt(cA, cD, 'db2')) #-------------------- # Pass a Wavelet object instead of the wavelet name and specify signal extension mode (the default is symmetric) for the border effect handling w = pywt.Wavelet('sym3') # the output coefficients arrays length depends not only on the input data length but also on the :class:Wavelet type (particularly on its filters length that are used in the transformation). # If you expected that the output length would be a half of the input data length, well, that's the trade-off that allows for the perfect reconstruction… cA, cD = pywt.dwt(x, wavelet=w, mode='constant') print('Approximation coefficients =', cA) print('Detail coefficients =', cD) # To find out what will be the output data size use the dwt_coeff_len() function. print( 'Length of coefficients =', int( pywt.dwt_coeff_len(data_len=len(x), filter_len=w.dec_len, mode='symmetric'))) print('Length of coefficients =', int(pywt.dwt_coeff_len(len(x), w, 'symmetric'))) print('Length of coefficients =', len(cA)) # The periodization (periodization) mode is slightly different from the others. # It's aim when doing the DWT transform is to output coefficients arrays that are half of the length of the input data. # Knowing that, you should never mix the periodization mode with other modes when doing DWT and IDWT. # Otherwise, it will produce invalid results. cA, cD = pywt.dwt(x, wavelet=w, mode='periodization') print('Single level reconstruction of signal =', pywt.idwt(cA, cD, 'sym3', 'symmetric')) # Invalid mode. print('Single level reconstruction of signal =', pywt.idwt(cA, cD, 'sym3', 'periodization')) # Passing None as one of the coefficient arrays parameters is similar to passing a zero-filled array. print('Single level reconstruction of signal =', pywt.idwt([1, 2, 0, 1], None, 'db2', 'symmetric')) print('Single level reconstruction of signal =', pywt.idwt([1, 2, 0, 1], [0, 0, 0, 0], 'db2', 'symmetric')) print('Single level reconstruction of signal =', pywt.idwt(None, [1, 2, 0, 1], 'db2', 'symmetric')) print('Single level reconstruction of signal =', pywt.idwt([0, 0, 0, 0], [1, 2, 0, 1], 'db2', 'symmetric')) # Only one argument at a time can be None. try: print('Single level reconstruction of signal =', pywt.idwt(None, None, 'db2', 'symmetric')) except ValueError as ex: print('Invalid coefficient parameter.') # When doing the IDWT transform, usually the coefficient arrays must have the same size. try: pywt.idwt([1, 2, 3, 4, 5], [1, 2, 3, 4], 'db2', 'symmetric') except ValueError as ex: print('Invalid size of coefficients arrays.') # Not every coefficient array can be used in IDWT. try: pywt.idwt([1, 2, 4], [4, 1, 3], 'db4', 'symmetric') except ValueError as ex: print('Invalid coefficient arrays length.') print('Coefficient length =', int(pywt.dwt_coeff_len(1, pywt.Wavelet('db4').dec_len, 'symmetric')))
>>> w = pywt.Wavelet('sym3') >>> cA, cD = pywt.dwt(x, wavelet=w, mode='cpd') >>> print cA [ 4.38354585 3.80302657 7.31813271 -0.58565539 4.09727044 7.81994027] >>> print cD [-1.33068221 -2.78795192 -3.16825651 -0.67715519 -0.09722957 -0.07045258] 注意这里输出的系数数组长度不只跟输入数据的长度有关,还和Wavelet类型有关(特别是它所使用的滤波器长度)。 如果想查看输出数据的长度可以使用dwt_coeff_len()函数: >>> pywt.dwt_coeff_len(data_len=len(x), filter_len=w.dec_len, mode='sym') 6 >>> pywt.dwt_coeff_len(len(x), w, 'sym') 6 >>> len(cA) 6 dwt_coeff_len()函数的第三个参数是mode。 >>> pywt.MODES.modes ['zpd', 'cpd', 'sym', 'ppd', 'sp1', 'per'] >>> [pywt.dwt_coeff_len(len(x), w.dec_len, mode) for mode in pywt.MODES.modes] [6, 6, 6, 6, 6, 4]
def pywt_coeff_shapes(shape, wavelet, nlevels, mode): """Return a list of coefficient shapes in the specified transform. The wavelet transform specified by ``wavelet``, ``nlevels`` and ``mode`` produces a sequence of approximation and detail coefficients. This function computes the shape of those coefficient arrays and returns them as a list. Parameters ---------- shape : sequence Shape of an input to the transform. wavelet : string or `pywt.Wavelet` Specification of the wavelet to be used in the transform. If a string is given, it is converted to a `pywt.Wavelet`. Use `pywt.wavelist` to get a list of available wavelets. nlevels : positive int Number of scaling levels to be used in the decomposition. The maximum number of levels can be calculated with `pywt.dwt_max_level`. mode : string, optional PyWavelets style signal extension mode. See `signal extension modes`_ for available options. Returns ------- shapes : list The shapes of the approximation and detail coefficients at different scaling levels in the following order: ``[shape_aN, shape_DN, ..., shape_D1]`` Here, ``shape_aN`` is the shape of the N-th level approximation coefficient array, and ``shape_Di`` is the shape of all i-th level detail coefficients. See Also -------- pywt.dwt_coeff_len : function used to determine coefficient sizes at each scaling level Examples -------- Determine the coefficient shapes for 2 scaling levels in 3 dimensions with zero-padding. Approximation coefficient shape comes first, then the level-2 detail coefficient and last the level-1 detail coefficient: >>> pywt_coeff_shapes(shape=(16, 17, 18), wavelet='db2', nlevels=2, ... mode='zero') [(6, 6, 6), (6, 6, 6), (9, 10, 10)] References ---------- .. _signal extension modes: https://pywavelets.readthedocs.io/en/latest/ref/signal-extension-\ modes.html """ shape = tuple(shape) if any(int(s) != s for s in shape): raise ValueError('`shape` may only contain integers, got {}' ''.format(shape)) wavelet = pywt_wavelet(wavelet) nlevels, nlevels_in = int(nlevels), nlevels if nlevels_in != nlevels: raise ValueError('`nlevels` must be integer, got {}' ''.format(nlevels_in)) # TODO: adapt for axes for i, n in enumerate(shape): max_levels = pywt.dwt_max_level(n, wavelet.dec_len) if max_levels == 0: raise ValueError('in axis {}: data size {} too small for ' 'transform, results in maximal `nlevels` of 0' ''.format(i, n)) if not 0 < nlevels <= max_levels: raise ValueError('in axis {}: `nlevels` must satisfy 0 < nlevels ' '<= {}, got {}' ''.format(i, max_levels, nlevels)) mode, mode_in = str(mode).lower(), mode if mode not in PYWT_SUPPORTED_MODES: raise ValueError("mode '{}' not understood".format(mode_in)) # Use pywt.dwt_coeff_len to determine the coefficient lengths at each # scale recursively. Start with the image shape and use the last created # shape for the next step. shape_list = [shape] for _ in range(nlevels): shape = tuple(pywt.dwt_coeff_len(n, filter_len=wavelet.dec_len, mode=mode) for n in shape_list[-1]) shape_list.append(shape) # Add a duplicate of the last entry for the approximation coefficients shape_list.append(shape_list[-1]) # We created the list in reversed order, reverse it. Remove also the # superfluous image shape at the end. shape_list.reverse() shape_list.pop() return shape_list
def coeff_len(self, input_length): return pywt.dwt_coeff_len(input_length, self.dec_lo.shape[0], self.mode)