def plot_filters(bank=None, filt_opt_bank = None): if bank is None: filt_opt_bank, bank = test_filter_bank(return_bank=True) for k in range(2): print('Bank {}'.format(k)) center_psi, bw_psi, bw_phi = morlet_freq_1d(filt_opt_bank[k]) sigma0 = bank[k].meta.sigma0 sigma_psi = sigma0*np.pi/2./bw_psi sigma_phi = sigma0*np.pi/2./bw_phi J = bank[k].meta.J P = bank[k].meta.P print('J = {}, P = {}'.format(J, P)) for j in range(J)[::J//5]: f = bank[k].psi.filter[j] # f = np.concatenate([f[:len(f)//2][::-1], f[:len(f)//2]]) ifft_f = mkl_fft.ifft(f) ifft_f = np.real(ifft_f) fig, ax = plt.subplots(1, 2, figsize = (24, 4)) ax[0].plot(np.concatenate([ifft_f[-int(3*sigma_psi[-1]):], ifft_f[:int(3*sigma_psi[-1])]])) # ax[0].plot(ifft_f) ax[1].plot(f) # ax[1].plot(np.concatenate([f[:len(f)//2][::-1], f[:len(f)//2]])) fig.suptitle('Psi filter, j{} = {}'.format(k+1, j), size = 'xx-large') ax[0].set_title('Time domain') ax[1].set_title('Frequency domain') plt.show() if P > 0: f = bank[k].phi.filter[0] ifft_f = mkl_fft.ifft(f) ifft_f = np.real(ifft_f) fig, ax = plt.subplots(1, 2, figsize = (24, 4)) ax[0].plot(np.concatenate([ifft_f[-int(3*sigma_psi[-1]):], ifft_f[:int(3*sigma_psi[-1])]])) # ax[0].plot(ifft_f) ax[1].plot(f) fig.suptitle('Phi filter', size = 'xx-large') ax[0].set_title('Time domain') ax[1].set_title('Frequency domain') plt.show()
def FFT_t_2(self, A): if MKL_AVAILABLE: if global_variables.PRE_FFTSHIFT: return mkl_fft.ifft(A) else: return ifftshift(mkl_fft.ifft(fftshift(A))) else: if global_variables.PRE_FFTSHIFT: return scipy.fftpack.ifft(A) else: return ifftshift(scipy.fftpack.ifft(fftshift(A)))
def mkl_ifft1d(a): n,m = a.shape b = np.zeros((n,m),dtype=np.complex128) for i in xrange(m): b[:,i] = mkl_fft.ifft(a[:,i]+0j)/n return b
def ifft(a, overwrite_x = False): """Computes ifft on a matrix of shape (..., n). This is identical to np.ifft2(a) Parameters ---------- a : array_like Input array (must be complex). overwrite_x : bool Specifies whether original array can be destroyed (for inplace transform) Returns ------- out : complex ndarray Result of the transformation along the (-4,-3) axes. """ a = np.asarray(a, dtype = CDTYPE) libname = DTMMConfig["fftlib"] if libname == "mkl_fft": return mkl_fft.ifft(a, overwrite_x = overwrite_x) elif libname == "scipy": return spfft.ifft(a, overwrite_x = overwrite_x) elif libname == "numpy": return npfft.ifft(a) elif libname == "pyfftw": return pyfftw.interfaces.scipy_fft.ifft(a, overwrite_x = overwrite_x) else: #default implementation is numpy return npfft.ifft(a)
def test_vector3(self): "fft(ifft(x)) is identity" f1 = mkl_fft.ifft(self.xz1) f2 = mkl_fft.fft(f1) assert_(np.allclose(self.xz1,f2)) f1 = mkl_fft.ifft(self.xc1) f2 = mkl_fft.fft(f1) assert_( np.allclose(self.xc1,f2)) f1 = mkl_fft.ifft(self.xd1) f2 = mkl_fft.fft(f1) assert_( np.allclose(self.xd1,f2)) f1 = mkl_fft.ifft(self.xf1) f2 = mkl_fft.fft(f1) assert_( np.allclose(self.xf1, f2, atol = 2.0e-7))
def mifft(fh): M = fh.shape[0] NS = fh.shape[1] N = NS + 1 N2 = int(N / 2) temp = np.empty((M, N), dtype=complex) temp[:, :N2] = fh[:, :N2] temp[:, N2] = 0.0 temp[:, N2 + 1:] = fh[:, N2:] return ifft(temp)
def _ifft(a, overwrite_x=False): libname = CDDMConfig["fftlib"] if libname == "mkl_fft": return mkl_fft.ifft(a, overwrite_x=overwrite_x) elif libname == "scipy": return spfft.ifft(a, overwrite_x=overwrite_x) elif libname == "pyfftw": return fftw.scipy_fftpack.ifft(a, overwrite_x=overwrite_x) elif libname == "numpy": return np.fft.ifft(a)
def test_scale_1d_array(self): X = np.ones((8, 4, 4,), dtype='d') f1 = mkl_fft.fft(X, axis=1, forward_scale=0.25) f2 = mkl_fft.fft(X, axis=1) r_tol, a_tol = _get_rtol_atol(X) assert_allclose(4*f1, f2, rtol=r_tol, atol=a_tol) X1 = mkl_fft.ifft(f1, axis=1, forward_scale=0.25) assert_allclose(X, X1, rtol=r_tol, atol=a_tol) f3 = mkl_fft.rfft(X, axis=0, forward_scale=0.5) X2 = mkl_fft.irfft(f3, axis=0, forward_scale=0.5) assert_allclose(X, X2, rtol=r_tol, atol=a_tol)
def test_scale_1d_vector(self): X = np.ones(128, dtype='d') f1 = mkl_fft.fft(X, forward_scale=0.25) f2 = mkl_fft.fft(X) r_tol, a_tol = _get_rtol_atol(X) assert_allclose(4*f1, f2, rtol=r_tol, atol=a_tol) X1 = mkl_fft.ifft(f1, forward_scale=0.25) assert_allclose(X, X1, rtol=r_tol, atol=a_tol) f3 = mkl_fft.rfft(X, forward_scale=0.5) X2 = mkl_fft.irfft(f3, forward_scale=0.5) assert_allclose(X, X2, rtol=r_tol, atol=a_tol)
def hilbert(signal: np.ndarray) -> np.ndarray: """ hilbert(signal) calculate the analytic signal using the `Hilbert transform` (same with scipy.signal.hilbert) .. math:: S_a = S + iS_H where S_H is the hilbert transform of the signal Parameters ---------- signal : np.ndarray signal Returns ------- np.ndarray :math:'s + s_{H} i' """ @njit def _modifyfft(x: np.ndarray) -> np.ndarray: """used by the function hilbert Parameters ---------- x : np.ndarray [description] Returns ------- np.ndarray [description] """ N = x.size if N % 2 == 0: x[1:N // 2] = x[1:N // 2] * 2 x[N // 2 + 1:] = 0 else: x[1:(N + 1) // 2] = x[1:(N + 1) // 2] * 2 x[(N + 1) // 2:] = 0 return x Xf = fft(signal) Xf = _modifyfft(Xf) x = ifft(Xf) return x
def test_fft(self): n_tests = 1000 n_max = 2 d_max = 100 norm = 'ortho' inplace = True scrambled = True passed = True for i in range(n_tests): ndim = np.random.randint(1, high=n_max + 1) axis = np.random.randint(0, high=ndim) dims = np.random.randint(1, high=d_max + 1, size=(ndim)) x = np.random.normal(size=dims) + 1j * np.random.normal(size=dims) if inplace: X = x.copy() fft(X, axis=axis, norm=norm, out=X, scrambled=scrambled) else: X = fft(x, axis=axis, norm=norm, scrambled=scrambled) Y = np.fft.fft(x, axis=axis, norm=norm) x_ = ifft(X, axis=axis, norm=norm) if not np.allclose(X, Y) and not scrambled: print( ' Failed forward with ndim=%d axis=%d dims=' % (ndim, axis), dims) passed = False if not np.allclose(x, x_): print( ' Failed backward with ndim=%d axis=%d dims=' % (ndim, axis), dims) passed = False self.assertTrue(passed)
def test_fft_truncation(self): n_tests = 1000 n_max = 2 d_max = 100 norm = None inplace = False scrambled = False passed = True for i in range(n_tests): ndim = np.random.randint(1, high=n_max + 1) axis = np.random.randint(0, high=ndim) dims = np.random.randint(2, high=d_max + 1, size=(ndim)) x = np.random.normal(size=dims) + 1j * np.random.normal(size=dims) x_trunc = np.swapaxes(x, axis, -1)[..., :dims[axis] // 2] x_trunc = np.swapaxes(x_trunc, -1, axis) X = fft(x, axis=axis, n=dims[axis] // 2) Y = np.fft.fft(x, axis=axis, n=dims[axis] // 2) x_ = ifft(X, axis=axis, norm=norm) if not np.allclose(X, Y) and not scrambled: print( ' Failed forward with ndim=%d axis=%d dims=' % (ndim, axis), dims) passed = False if not np.allclose(x_trunc, x_): print( ' Failed backward with ndim=%d axis=%d dims=' % (ndim, axis), dims) passed = False self.assertTrue(passed)
def test_fft(self): n_tests = 1000 n_max = 2 d_max = 100 norm = 'ortho' inplace = True scrambled = True passed = True for i in range(n_tests): ndim = np.random.randint(1,high=n_max+1) axis = np.random.randint(0,high=ndim) dims = np.random.randint(1,high=d_max+1,size=(ndim)) x = np.random.normal(size=dims) + 1j*np.random.normal(size=dims) if inplace: X = x.copy() fft(X, axis=axis, norm=norm, out=X, scrambled=scrambled) else: X = fft(x, axis=axis, norm=norm, scrambled=scrambled) Y = np.fft.fft(x, axis=axis, norm=norm) x_ = ifft(X, axis=axis, norm=norm) if not np.allclose(X,Y) and not scrambled: print(' Failed forward with ndim=%d axis=%d dims=' % (ndim, axis), dims) passed = False if not np.allclose(x, x_): print(' Failed backward with ndim=%d axis=%d dims=' % (ndim, axis), dims) passed = False self.assertTrue(passed)
def ifft(x, n=None, axis=-1, overwrite_input=False, extra_info=None): return mkl_fft.ifft(x, n=n, axis=axis, overwrite_x=overwrite_input)
def FFT_t_shift(self, A): if MKL_AVAILABLE: return ifftshift(mkl_fft.ifft(fftshift(A))) else: return ifftshift(scipy.fftpack.ifft(fftshift(A)))
# Ensure Image can be split in blocks by 8 and split it height = height - height % block width = width - width % block hmax = height // block wmax = width // block CompIMG = np.zeros((height, width, 3)) # Process every component for kk in range(3): I = img[:height, :width, kk] MM = np.array(I, dtype=np.float32) CC = np.zeros((height, width)) for i in range(hmax): for j in range(wmax): # Splint int 8x8 blocks M = MM[block * i: block * (i + 1), block * j: block * (j + 1)] # Execute fft D = np.real(mkl_fft.fft(M)).reshape((-1, 8)) # Compress dividing by quantization matrix (most coef are zeros) C = np.round(D * Q) CC[block * i: block * (i + 1), block * j: block * (j + 1)] = C.copy() for i in range(hmax): for j in range(wmax): # Restore image with ifft CompIMG[block * i: block * (i + 1), block * j: block * (j + 1), kk] = np.real( mkl_fft.ifft(CC[block * i: block * (i + 1), block * j: block * (j + 1)])).reshape(-1, 8) # Convert image back to RGB t.saveImage(CompIMG, file + "_compressedFFT") t.showResults(file, file + "_compressedFFT")
def test_array4(self): x = self.ad3 for ax in range(x.ndim): f1 = mkl_fft.ifft(x, axis = ax) f2 = mkl_fft.fft(f1, axis = ax) assert_allclose(f2, x, atol=2e-15)
def test_matrix6(self): x = self.ad2; f1 = mkl_fft.ifft(x) f2 = mkl_fft.fft(f1) assert_allclose(x, f2, atol=1e-10)
def test_vector8(self): "ifft of real array is the same as fft of its complex cast" x = self.xd1[3:17:2] f1 = mkl_fft.ifft(x) f2 = mkl_fft.ifft(x.astype(np.complex128)) assert_(np.allclose(f1,f2))
def pfourier_multiply(fh, m): pos = int(fh.shape[1] // 2 + 1) fh[:, pos] = 0.0 oh = fft(m * ifft(fh)) oh[:, pos] = 0.0 return oh
def pifftr(fh): pos = int(fh.shape[1] // 2 + 1) fh[:, pos] = 0.0 return ifft(fh).real
def ffourier_multiply(fh, m): return fft(m * ifft(fh))
def remove_stripe(img, level, wname='db5', sigma=1.5): """ Suppress horizontal stripe in a sinogram using the Fourier-Wavelet based method by Munch et al. [2]_. Parameters ---------- img : 2d array The two-dimensional array representig the image or the sinogram to de-stripe. level : int The highest decomposition level. wname : str, optional The wavelet type. Default value is ``db5`` sigma : float, optional The damping factor in the Fourier space. Default value is ``1.5`` Returns ------- out : 2d array The resulting filtered image. References ---------- .. [2] B. Munch, P. Trtik, F. Marone, M. Stampanoni, Stripe and ring artifact removal with combined wavelet-Fourier filtering, Optics Express 17(10):8567-8591, 2009. """ nrow, ncol = img.shape # wavelet decomposition. cH = [] cV = [] cD = [] for i in range(0, level): img, (cHi, cVi, cDi) = pywt.dwt2(img, wname) cH.append(cHi) cV.append(cVi) cD.append(cDi) # FFT transform of horizontal frequency bands for i in range(0, level): # FFT fcV = fftshift(fft(cV[i], axis=0)) my, mx = fcV.shape # damping of vertical stripe information yy2 = (np.arange(-np.floor(my / 2), -np.floor(my / 2) + my))**2 damp = -np.expm1(-yy2 / (2.0 * (sigma**2))) fcV = fcV * np.tile(damp.reshape(damp.size, 1), (1, mx)) #inverse FFT cV[i] = np.real(ifft(ifftshift(fcV), axis=0)) # wavelet reconstruction for i in range(level - 1, -1, -1): img = img[0:cH[i].shape[0], 0:cH[i].shape[1]] img = pywt.idwt2((img, (cH[i], cV[i], cD[i])), wname) return img[0:nrow, 0:ncol]
def conv_sub_1d(x_fft, f, ds): ''' Input x_fft: The Fourier transform of the signals to be convolved, 2-d array N x K, where K is number of signals. f: The filter in the frequency domain (= Fourier transform of the filter). ds: The downsampling factor as a power of 2 with respect to x_fft Output y_ds: the filtered, downsampled signalm in the time domain ''' # periodize filter so that it has the correct resolution # j0 = int(np.log2(f.shape[0]/x_fft.shape[0])) # f = f.reshape((f.shape[0]//2**j0, 2**j0)).sum(axis = 1) sig_length = x_fft.shape[0] if type(f) != dict: end = len(f) f = np.concatenate([ f[:sig_length // 2], [f[sig_length // 2] / 2 + f[end - sig_length // 2] / 2], f[end - sig_length // 2 + 1:] ]) # represent filter in matrix form f = f[:, np.newaxis] + 0 * 1j # print('Inside conv_sub_1d: filter') # print(f.shape) # print(f[:10,0]) # Calculate Fourier coefficients y_fft = f * x_fft #print('Inside conv_sub_1d: y_fft') #print(y_fft.shape) # print(y_fft[:10,0]) elif f['type'] == 'fourier_truncated': coefft, start = f['coefft'], f['start'] if len(coefft) > sig_length: # filter is larger than signal, lowpass filter & periodize the former # create lowpass filter start0 = np.mod(start, f['N']) nCoeffts0 = len(coefft) if start0 + nCoeffts0 - 1 <= f['N']: rng = np.arange(start0, nCoeffts0) else: rng = np.concatenate([ np.arange(start0, f['N']), np.arange(nCoeffts0 + start0 - f['N']) ]) lowpass = np.zeros(shape=coefft.shape) lowpass[rng < sig_length // 2] = 1 lowpass[rng == sig_length // 2] = 0.5 lowpass[rng == f['N'] - sig_length // 2] = 0.5 lowpass[rng > f['N'] - sig_length // 2] = 1 coefft = (coefft * lowpass).reshape( (sig_length, len(coefft) // sig_length), order='F').sum(axis=1) nCoeffts = len(coefft) j = int(np.log2(nCoeffts / sig_length)) start = np.mod(start, x_fft.shape[0]) if start + nCoeffts <= x_fft.shape[0]: # filter support contained in one period, no wrap-around y_fft = coefft[:, np.newaxis] * x_fft[start:(nCoeffts + start), :] else: # filter support wraps around, extract both parts y_fft = coefft[:, np.newaxis] * np.concatenate([ x_fft[start:, :], x_fft[:nCoeffts + start - x_fft.shape[0], :] ]) # Calculate downsampling factor with respect to y_fft # Пока в имплементации у нас всегда y_fft.shape[0]=x_fft.shape[0] ds_factor = ds + np.log2(y_fft.shape[0] / sig_length) #print('Inside conv_sub_1d: dsj: ', ds_factor) if ds_factor > 0: y_fft = downsample_filter(y_fft, ds_factor=ds_factor) elif ds_factor < 0: # upsample, so zero-pad in Fourier # note that this only happens for fourier_truncated filters, since otherwise # filter sizes are always the same as the signal size # also, we have to do one-sided padding since otherwise we might break # continuity of Fourier transform y_fft = np.concatenate([ y_fft, np.zeros(((2**(-ds_factor) - 1) * y_fft.shape[0], y_fft.shape[1])) ]) #print('Inside conv_sub_1d; downsampled y_fft: ') #print(y_fft.shape) # print(y_fft[:4,0]) if (type(f) == dict) and (f['type'] == 'fourier_truncated') and f['recenter']: # result has been shifted in frequency so that the zero fre- # quency is actually at -filter.start+1 y_fft = np.roll(y_fft, f['start']) # Calculate inverse Fourier transform # Use .T to apply transform along columns (coefficients of 1-d signals) # Divede to the 2**(ds_factor/2) to get the same signal magnitude in time domain # after downsampling in frequency domain (CHECK TAHT WE SHOULD DEVIDE ifft NOT fft) x_filtered_ds = mkl_fft.ifft(y_fft.T).T / (2**(ds_factor / 2)) # print('Inside conv_sub_1d; x_filtered_ds: ') # print(x_filtered_ds.shape) # print(x_filtered_ds[:4,0]) return x_filtered_ds