def compare_interpolated_spectrum(): fig = plt.figure(figsize=(8, 8)) ax = fig.add_subplot(111) out = fft(ifftshift(f_full)) freqs = fftfreq(len(f_full), d=0.01) # spacing, Ang sfreqs = fftshift(freqs) taper = gauss_taper(freqs, sigma=0.0496) #Ang, corresponds to 2.89 km/s at 5150A. tout = out * taper ax.plot(sfreqs, fftshift(tout)) wl_h, fl_h = np.abs(np.load("PH6.8kms_0.01ang.npy")) wl_l, fl_l = np.abs(np.load("PH2.5kms.npy")) #end edges wl_he = wl_h[200:-200] fl_he = fl_h[200:-200] interp = Sinc_w(wl_l, fl_l, a=5, window='kaiser') fl_hi = interp(wl_he) d = wl_he[1] - wl_he[0] out = fft(ifftshift(fl_hi)) freqs = fftfreq(len(out), d=d) ax.plot(fftshift(freqs), fftshift(out)) plt.show()
def FFT_Correlation(x,y): """ FFT-based correlation, much faster than numpy autocorr. x and y are row-based vectors of arbitrary lengths. This is a vectorized implementation of O(N*log(N)) flops. """ lengthx = x.shape[0] lengthy = y.shape[0] x = np.reshape(x,(1,lengthx)) y = np.reshape(y,(1,lengthy)) length = np.array([lengthx, lengthy]).min() x = x[:length] y = y[:length] fftx = fft(x, 2 * length - 1, axis=1) #pad with zeros ffty = fft(y, 2 * length - 1, axis=1) corr_xy = fft.ifft(fftx * np.conjugate(ffty), axis=1) corr_xy = np.real(fft.fftshift(corr_xy, axes=1)) #should be no imaginary part corr_yx = fft.ifft(ffty * np.conjugate(fftx), axis=1) corr_yx = np.real(fft.fftshift(corr_yx, axes=1)) corr = 0.5 * (corr_xy[:,length:] + corr_yx[:,length:]) / range(1,length)[::-1] return np.reshape(corr,corr.shape[1])
def B_ell(flat_map, component, bin_size, window=None): """ Return the binned beam function of the given flat map component, using ell bins of bin_size. If a window name is given, multiply the map component by the window function before taking the 2-D DFT. The returned beam function is the absolute value of the DFT, so it has the same units as the map component. The returned bins array contains the left edges of the bins corresponding to the returned data: for all i in range(bins.size), bins[i] <= data[i] < bins[i+1] """ ell_x, ell_y= np.meshgrid(fftshift(fftfreq(flat_map.x.size, flat_map.dx()/(2*np.pi))), fftshift(fftfreq(flat_map.y.size, flat_map.dy()/(2*np.pi)))) ell_x = ell_x.T ell_y = ell_y.T ell_r = np.sqrt(ell_x**2 + ell_y**2) ell_bins = np.arange(0, np.max(ell_r), bin_size) beam = flat_map[component] if window is not None: beam *= get_window(window, flat_map.y.size) beam *= get_window(window, flat_map.x.size)[:, np.newaxis] dft = fftshift(fft2(beam)) # Shift the indices down by 1 so that they correspond to the data # indices. These indices should always be valid indices for the # DFT data because r_ell has a lower bound at 0 and max(r_ell) # will have index ell_bins.size. bin_indices = np.digitize(ell_r.flatten(), ell_bins) - 1 binned = np.zeros(ell_bins.size) # dtype? for i in range(binned.size): binned[i] = np.sqrt(np.mean(abs(dft.flatten()[i==bin_indices])**2)) return ell_bins, binned, dft
def test_axes_keyword(self): freqs = [[ 0, 1, 2], [ 3, 4, -4], [-3, -2, -1]] shifted = [[-1, -3, -2], [ 2, 0, 1], [-4, 3, 4]] assert_array_almost_equal(fftshift(freqs, axes=(0, 1)), shifted) assert_array_almost_equal(fftshift(freqs, axes=0), fftshift(freqs, axes=(0,))) assert_array_almost_equal(ifftshift(shifted, axes=(0, 1)), freqs) assert_array_almost_equal(ifftshift(shifted, axes=0), ifftshift(shifted, axes=(0,)))
def sph_fft(x, y): dx = x[1] - x[0] q = fft.fftshift(fft.fftfreq(len(x), dx)) * 2 * np.pi f = -(4*np.pi)*fft.fftshift(np.imag(fft.fft(y*dx * x))) f /= q f[q == 0] = np.trapz(4*np.pi*y*x**2, x) return q, f
def convFFT(x,y): nx=len(x) xf=np.pad(x,(nx/2,nx/2),mode='constant') yf=np.pad(y,(nx/2,nx/2),mode='constant') xf=(fft.fft(fft.fftshift(xf))) yf=(fft.fft(fft.fftshift(yf))) return fft.fftshift(np.real((fft.ifft(xf*yf))))[nx/2:3*nx/2]
def get_spectrum_1d(data_reg,x_reg,y_reg): """Compute the 1d power spectrum. """ # remove the mean and squarize data_reg-=data_reg.mean() jpj,jpi = data_reg.shape msize = min(jpj,jpi) data_reg = data_reg[:msize-1,:msize-1] x_reg = x_reg[:msize-1,:msize-1] y_reg = y_reg[:msize-1,:msize-1] # wavenumber vector x1dreg,y1dreg = x_reg[0,:],y_reg[:,0] Ni,Nj = msize-1,msize-1 dx=npy.int(npy.ceil(x1dreg[1]-x1dreg[0])) k_max = npy.pi / dx kx = fft.fftshift(fft.fftfreq(Ni, d=1./(2.*k_max))) ky = fft.fftshift(fft.fftfreq(Nj, d=1./(2.*k_max))) kkx, kky = npy.meshgrid( ky, kx ) Kh = npy.sqrt(kkx**2 + kky**2) Nmin = min(Ni,Nj) leng = Nmin/2+1 kstep = npy.zeros(leng) kstep[0] = k_max / Nmin for ind in range(1, leng): kstep[ind] = kstep[ind-1] + 2*k_max/Nmin norm_factor = 1./( (Nj*Ni)**2 ) # tukey windowing = tapered cosine window cff_tukey = 0.25 yw=npy.linspace(0, 1, Nj) wdw_j = npy.ones(yw.shape) xw=npy.linspace(0, 1, Ni) wdw_i= npy.ones(xw.shape) first_conditioni = xw<cff_tukey/2 first_conditionj = yw<cff_tukey/2 wdw_i[first_conditioni] = 0.5 * (1 + npy.cos(2*npy.pi/cff_tukey * (xw[first_conditioni] - cff_tukey/2) )) wdw_j[first_conditionj] = 0.5 * (1 + npy.cos(2*npy.pi/cff_tukey * (yw[first_conditionj] - cff_tukey/2) )) third_conditioni = xw>=(1 - cff_tukey/2) third_conditionj = yw>=(1 - cff_tukey/2) wdw_i[third_conditioni] = 0.5 * (1 + npy.cos(2*npy.pi/cff_tukey * (xw[third_conditioni] - 1 + cff_tukey/2))) wdw_j[third_conditionj] = 0.5 * (1 + npy.cos(2*npy.pi/cff_tukey * (yw[third_conditionj] - 1 + cff_tukey/2))) wdw_ii, wdw_jj = npy.meshgrid(wdw_j, wdw_i, sparse=True) wdw = wdw_ii * wdw_jj data_reg*=wdw #2D spectrum cff = norm_factor tempconj=fft.fft2(data_reg).conj() tempamp=cff * npy.real(tempconj*fft.fft2(data_reg)) spec_2d=fft.fftshift(tempamp) #1D spectrum leng = len(kstep) spec_1d = npy.zeros(leng) krange = Kh <= kstep[0] spec_1d[0] = spec_2d[krange].sum() for ind in range(1, leng): krange = (kstep[ind-1] < Kh) & (Kh <= kstep[ind]) spec_1d[ind] = spec_2d[krange].sum() spec_1d[0] /= kstep[0] for ind in range(1, leng): spec_1d[ind] /= kstep[ind]-kstep[ind-1] return spec_1d, kstep
def gen_wedge_psf(nx, ny, nf, dx, dy, df, z, out, threads=None): u = fftshift(fftfreq(nx, dx * np.pi / 180)) v = fftshift(fftfreq(ny, dy * np.pi / 180)) e = fftshift(fftfreq(nf, df)) E = np.sqrt(Cosmo.Om0 * (1 + z) ** 3 + Cosmo.Ok0 * (1 + z) ** 2 + Cosmo.Ode0) D = Cosmo.comoving_transverse_distance(z).value H0 = Cosmo.H0.value * 1e3 c = const.c.value print(E, D, H0) kx = u * 2 * np.pi / D ky = v * 2 * np.pi / D k_perp = np.sqrt(kx ** 2 + ky[np.newaxis, ...].T ** 2) k_par = e * 2 * np.pi * H0 * f21 * E / (c * (1 + z) ** 2) arr = np.ones((nf, nx, ny), dtype='complex128') for i in range(nf): mask = (k_perp > np.abs(k_par[i]) * c * (1 + z) / (H0 * E * D)) arr[i][mask] = 0 np.save('kx.npy', kx) np.save('ky.npy', ky) np.save('kpar.npy', k_par) np.save('wedge_window.npy', arr.real) fft_arr = fftshift(fftn(ifftshift(arr))).real hdu = fits.PrimaryHDU(data=fft_arr) hdr_dict = dict(cdelt1=dx, cdelt2=dy, cdelt3=df, crpix1=nx/2, crpix2=ny/2, crpix3=nf/2, crval1=0, crval2=0, crval3=0, ctype1='RA---SIN', ctype2='DEC--SIN', ctype3='FREQ', cunit1='deg', cunit2='deg', cunit3='Hz') for k, v in hdr_dict.items(): hdu.header[k] = v hdu.writeto(out, clobber=True)
def fft_2D(R, convert=3e-5, freq_bounds=None): """ Perform a 2D FFT to transform a 3rd order response function defined in the rotating frame into a series of 2D spectra. First argument must be a MetaArray object wth ticks and rw_freq defined. Returns the FFT in another MetaArray object with ticks updated to the calculated frequencies (converted using the convert argument which defaults to cm to fs). """ # reverses frequency order to keep convention e^{+i \omega t} R_2D = fftshift(fft2(ifftshift(R, axes=(0, 2)), axes=(0, 2)), axes=(0, 2))[::-1, :, ::-1] dt = [t[1] - t[0] for t in R.ticks] freqs = [fftshift(fftfreq(R.shape[axis], dt[axis] * convert)) + R.rw_freq for axis in (0, 2)] if freq_bounds is not None: bounds = [bound_indices(ticks, freq_bounds) for ticks in freqs] freqs = [freq[bound[0]:bound[1]] for freq, bound in zip(freqs, bounds)] R_2D = R_2D[bounds[0][0]:bounds[0][1], :, bounds[1][0]:bounds[1][1]] return MetaArray(R_2D, ticks=(freqs[0], R.ticks[1], freqs[1]))
def delayTransformVisibilities(visList,df,kernel=None,wind='Blackman-Harris'): ''' ARGS: visList: nfreqxnvis complex matrix of visibilities df: float indicating channel width RETURNS: ndelayxnvis grid of delay-transformed visibilities ''' nf=visList.shape[0] if kernel is None: kernel=np.ones(nf) nv=visList.shape[1] windowGrid=np.zeros_like(visList) if wind=='Blackman-Harris': window=signal.blackmanharris(nf) elif wind=='Nithya': window=signal.blackmanharris(nf/2) window=signal.fftconvolve(window,window,mode='full') window=np.append(window,window[-1]) window/=window.max() window/=np.sqrt(np.mean(np.abs(kernel*window)**2.)) for vNum in range(nv): windowGrid[:,vNum]=window*kernel return df*fft.fftshift(fft.fft(fft.fftshift(visList*windowGrid,axes=[0]),axis=0),axes=[0])
def create_matching_kernel(source_psf, target_psf, window=None): """ Create a kernel to match 2D point spread functions (PSF) using the ratio of Fourier transforms. Parameters ---------- source_psf : 2D `~numpy.ndarray` The source PSF. The source PSF should have higher resolution (i.e. narrower) than the target PSF. ``source_psf`` and ``target_psf`` must have the same shape and pixel scale. target_psf : 2D `~numpy.ndarray` The target PSF. The target PSF should have lower resolution (i.e. broader) than the source PSF. ``source_psf`` and ``target_psf`` must have the same shape and pixel scale. window : callable, optional The window (or taper) function or callable class instance used to remove high frequency noise from the PSF matching kernel. Some examples include: * `~photutils.psf.matching.HanningWindow` * `~photutils.psf.matching.TukeyWindow` * `~photutils.psf.matching.CosineBellWindow` * `~photutils.psf.matching.SplitCosineBellWindow` * `~photutils.psf.matching.TopHatWindow` For more information on window functions and example usage, see :ref:`psf_matching`. Returns ------- kernel : 2D `~numpy.ndarray` The matching kernel to go from ``source_psf`` to ``target_psf``. The output matching kernel is normalized such that it sums to 1. """ # inputs are copied so that they are not changed when normalizing source_psf = np.copy(np.asanyarray(source_psf)) target_psf = np.copy(np.asanyarray(target_psf)) if source_psf.shape != target_psf.shape: raise ValueError('source_psf and target_psf must have the same shape ' '(i.e. registered with the same pixel scale).') # ensure input PSFs are normalized source_psf /= source_psf.sum() target_psf /= target_psf.sum() source_otf = fftshift(fft2(source_psf)) target_otf = fftshift(fft2(target_psf)) ratio = target_otf / source_otf # apply a window function in frequency space if window is not None: ratio *= window(target_psf.shape) kernel = np.real(fftshift((ifft2(ifftshift(ratio))))) return kernel / kernel.sum()
def abs_fft(self, points=None, zoom=None,write = 'off'): """ Fourier transforms the timesignal; points is the number of points to transform, if more points given than data points the rest is zero padded absfft(points=4096) """ realdata = N.array(self.the_result.y[0]) imdata = N.array(self.the_result.y[1]) data = realdata + 1j*imdata fftdata = F.fftshift(F.fft(data, points)) absfft = N.sqrt(fftdata.real**2 + fftdata.imag**2) # create our x axis n = fftdata.size self.the_result.x = F.fftshift(F.fftfreq(n, 1.0/self.sampling_rate)) self.the_result.y[0] = absfft self.the_result.y[1] = N.zeros(n) if write == 'on': return self else: if zoom is None: return self.the_result else: center, width = zoom return self.zoom(self.the_result, center, width)
def frp_to_fir(frp, fbins=None): '''Transform a fringe rate profile to a fir filter.''' frp = ifftshift(frp,axes=-1) fir = ifft(frp, axis=-1) fir = fftshift(fir, axes=-1) if fbins is not None: return fir, fftshift(fftfreq(fbins.size, fbins[1] - fbins[0])) else: return fir
def compute(self, scene: Scene): """ Compute optical irradiance map Computation proccedure: 1) convert radiance to irradiance 2) apply lens and macular transmittance 3) apply off-axis fall-off (cos4th) 4) apply optical transfert function Args: scene (pyEyeBall.Scene): instance of Scene class, containing the radiance and other scene information Examples: >>> oi = Optics() >>> oi.compute(Scene()) """ # set field of view and wavelength samples self.fov = scene.fov scene.wave = self._wave self.dist = scene.dist # compute irradiance self.photons = pi / (1 + 4 * self.f_number**2 * (1 + abs(self.magnification))**2) * scene.photons # apply ocular transmittance self.photons *= self.ocular_transmittance # apply the relative illuminant (off-axis) fall-off: cos4th function x, y = self.spatial_support s_factor = np.sqrt(self.image_distance**2 + x**2 + y**2) self.photons *= (self.image_distance / s_factor[:, :, None])**4 # apply optical transfer function of the optics for ii in range(self.wave.size): otf = fftshift(self.otf(self._wave[ii], self.frequency_support_x, self.frequency_support_y)) self.photons[:, :, ii] = np.abs(ifftshift(ifft2(otf * fft2(fftshift(self.photons[:, :, ii])))))
def plot(self, title, truth=None): kwargs = {"interpolation": "nearest", "origin": "lower", "cmap": "afmhot", "vmin": 0.0, "vmax": np.max(self.get_real_image())} if truth is not None: plt.subplot(2,2,3) plt.imshow(truth, **kwargs) plt.title("truth") plt.subplot(2,2,1) plt.imshow(self.get_real_image(), **kwargs) plt.title("{title}: scores {s1:.1f} {s2:.1f}".format(title=title, s1=self.get_score_L1(), s2=self.get_score_L2())) kwargs["vmin"] = np.log(np.percentile(self.get_data(), 1.)) kwargs["vmax"] = np.log(np.percentile(self.get_data(), 99.)) plt.subplot(2,2,4) data = np.log(self.get_data().copy()) data[np.where(self.get_ivar() <= 0)] = kwargs["vmin"] plt.imshow(fftshift(data, axes=0), **kwargs) plt.title("data") plt.subplot(2,2,2) plt.title(title) plt.imshow(np.log(fftshift(self.get_squared_norm_ft_image(), axes=0)), **kwargs)
def compacf(acfall,noiseall,Nr,dns,bstride,ti,tInd): bstride=bstride.squeeze() assert bstride.size==1 #TODO Nlag = acfall.shape[2] acf = zeros((Nr,Nlag),complex64) #NOT empty, note complex64 is single complex float spec = empty((Nr,2*Nlag-1),complex128) try: acf_noise = zeros((noiseall.shape[3],Nlag),complex64) spec_noise= zeros(2*Nlag-1,complex128) except AttributeError: acf_noise = None spec_noise= 0. for i in range(tInd[ti]-1,tInd[ti]+1): acf += (acfall[i,bstride,:,:,0] + 1j*acfall[i,bstride,:,:,1]).T if acf_noise is not None: #must be is not None acf_noise += (noiseall[i,bstride,:,:,0] + 1j*noiseall[i,bstride,:,:,1]).T acf = acf/dns/(i-(tInd[ti]-1)+1) #NOT /= if acf_noise is not None: #must be is not None acf_noise = acf_noise/dns / (i-(tInd[ti]-1)+1) #%% spectrum noise if acf_noise is not None: for i in range(Nlag): spec_noise += fftshift(fft(append(conj(acf_noise[i,1:][::-1]),acf_noise[i,:]))) spec_noise = spec_noise / Nlag #%% spectrum from ACF for i in range(Nr): spec[i,:] = fftshift(fft(append(conj(acf[i,1:][::-1]), acf[i,:])))-spec_noise return spec,acf
def acf2psd(acfall,noiseall,Nr,dns): """ acf all: Nlag x Nslantrange x real/comp """ assert acfall.ndim in (3,2) Nlag = acfall.shape[0] spec = empty((Nr,2*Nlag-1),complex128) if acfall.ndim == 3: # last dim real,cplx acf = (acfall[...,0] + 1j*acfall[...,1]).T / dns / 2. elif acfall.ndim == 2 and iscomplex(acfall[0,0]): acf = acfall / dns / 2. else: raise TypeError('is this really ACF? I expect complex 2-D matrix') try: acf_noise = (noiseall[...,0] + 1j*noiseall[...,1]).T / dns / 2. except TypeError: acf_noise= None spec_noise= 0. #%% spectrum noise if acf_noise is not None: spec_noise = zeros(2*Nlag-1,complex128) for i in range(Nlag): spec_noise += fftshift(fft(append(conj(acf_noise[i,1:][::-1]),acf_noise[i,:]))) # spec_noise = spec_noise / Nlag #%% spectrum from ACF for i in range(Nr): spec[i,:] = fftshift(fft(append(conj(acf[i,1:][::-1]), acf[i,:])))-spec_noise return spec,acf
def fft_r2g(self, fr, shift_fg=False): """ FFT of array ``fr`` given in real space. """ ndim, shape = fr.ndim, fr.shape if ndim == 1: fr = np.reshape(fr, self.shape) return self.fft_r2g(fr, shift_fg=shift_fg).flatten() elif ndim == 3: assert self.size == np.prod(shape[-3:]) fg = fftn(fr) if shift_fg: fg = fftshift(fg) elif ndim > 3: assert self.size == np.prod(shape[-3:]) axes = np.arange(ndim)[-3:] fg = fftn(fr, axes=axes) if shift_fg: fg = fftshift(fg, axes=axes) else: raise NotImplementedError("ndim < 3 are not supported") return fg / self.size
def laplacian_filter(in_file, in_mask=None, out_file=None): import numpy as np import nibabel as nb import os.path as op from math import pi from numpy.fft import fftn, ifftn, fftshift, ifftshift if out_file is None: fname, fext = op.splitext(op.basename(in_file)) if fext == '.gz': fname, _ = op.splitext(fname) out_file = op.abspath('./%s_smooth.nii.gz' % fname) im = nb.load(in_file) data = im.get_data() if in_mask is not None: mask = nb.load(in_mask).get_data() mask[mask > 0] = 1.0 mask[mask <= 0] = 0.0 data *= mask dataft = fftshift(fftn(data)) x = np.linspace(0, 2 * pi, dataft.shape[0])[:, None, None] y = np.linspace(0, 2 * pi, dataft.shape[1])[None, :, None] z = np.linspace(0, 2 * pi, dataft.shape[2])[None, None, :] lapfilt = 2.0 * np.squeeze((np.cos(x) + np.cos(y) + np.cos(z))) - 5.0 dataft *= fftshift(lapfilt) imfilt = np.real(ifftn(ifftshift(dataft))) nb.Nifti1Image(imfilt.astype(np.float32), im.get_affine(), im.get_header()).to_filename(out_file) return out_file
def _configure(infiles, z, df): conf.infiles = infiles img_hdr = fits.getheader(conf.infiles[0]) conf.nx = img_hdr['naxis1'] conf.ny = img_hdr['naxis2'] conf.nf = MWA_FREQ_EOR_ALL_80KHZ.size conf.dx = np.abs(img_hdr['cdelt1']) * np.pi / 180 conf.dy = np.abs(img_hdr['cdelt2']) * np.pi / 180 conf.df = df conf.du = 1 / (conf.nx * conf.dx) conf.dv = 1 / (conf.ny * conf.dy) conf.deta = 1 / (conf.nf * conf.df) conf.freq = MWA_FREQ_EOR_ALL_80KHZ conf.u = fftshift(fftfreq(conf.nx, conf.dx)) conf.v = fftshift(fftfreq(conf.ny, conf.dy)) conf.eta = fftshift(fftfreq(conf.nf, conf.df)) conf.z = z conf.cosmo_d = Cosmo.comoving_transverse_distance(conf.z).value conf.cosmo_e = np.sqrt(Cosmo.Om0 * (1 + conf.z) ** 3 + Cosmo.Ok0 * (1 + conf.z) ** 2 + Cosmo.Ode0) conf.cosmo_h0 = Cosmo.H0.value * 1e3 conf.cosmo_c = const.si.c.value conf.kx = conf.u * 2 * np.pi / conf.cosmo_d conf.ky = conf.v * 2 * np.pi / conf.cosmo_d conf.dkx = conf.du * 2 * np.pi / conf.cosmo_d conf.dky = conf.dv * 2 * np.pi / conf.cosmo_d conf.k_perp = np.sqrt(conf.kx ** 2 + conf.ky[np.newaxis, ...].T ** 2) conf.k_par = conf.eta * 2 * np.pi * conf.cosmo_h0 * _F21 * \ conf.cosmo_e / (conf.cosmo_c * (1 + conf.z) ** 2)
def plot_pixel_effect(): fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(8, 8)) #fig = plt.figure() #ax = fig.add_subplot(111) out = fft(ifftshift(f_full)) freqs = fftfreq(len(f_full), d=0.01) # spacing, Ang sfreqs = fftshift(freqs) taper = gauss_taper(freqs, sigma=0.0496) #Ang, corresponds to 2.89 km/s at 5150A. tout = out * taper for ax in axs[:, 0]: ax.plot(sfreqs, fftshift(tout) / tout[0]) ax.plot(sfreqs, fftshift(taper)) ax.plot(sfreqs, 0.0395 * np.sinc(0.0395 * sfreqs)) ax.plot(sfreqs, 0.0472 * np.sinc(0.0472 * sfreqs)) for ax in axs[:, 1]: ax.plot(sfreqs, 10 * np.log10(np.abs(fftshift(tout) / tout[0]))) ax.plot(sfreqs, 10 * np.log10(np.abs(fftshift(taper)))) ax.plot(sfreqs, 10 * np.log10(np.abs(0.0395 * np.sinc(0.0395 * sfreqs)))) ax.plot(sfreqs, 10 * np.log10(np.abs(0.0472 * np.sinc(0.0472 * sfreqs)))) axs[0, 0].set_ylabel("Norm amp") axs[1, 0].set_ylabel("Norm amp") axs[0, 1].set_ylabel("dB") axs[1, 1].set_ylabel("dB") for ax in axs.flatten(): ax.set_xlabel(r"cycles/$\lambda$") plt.show()
def sample_mps(self,window,temp_rate_Hz=10,zeropad=True): ''' Return samples of modulation power spectrum ''' ft, tf, sf = self._sample_modspec(window,temp_rate_Hz, zeropad=zeropad) return fftshift(abs(ft)**2), fftshift(tf), fftshift(sf)
def GetPulseSpectrum(krotov): """ """ dw = 2 * pi * fft.fftshift(fft.fftfreq(len(krotov.ControlVector), krotov.TimeGridResolution)) pulseSpectrum = fft.fftshift(fft.fft(krotov.ControlVector)) return dw, pulseSpectrum
def __build_wavenumbers__(self): k_1d = fftshift(np.array(range(0, self.num_points_x))* ((2*np.pi)/self.length_x)) l_1d = fftshift(np.array(range(0, self.num_points_y))* ((2*np.pi)/self.length_y)) self.kmax = max(k_1d) self.lmax = max(l_1d) self.k, self.l = np.meshgrid(k_1d, l_1d)
def test_kost_comp_abs(self): ft_image = fft2(self.image) ft_mask_padded = fft2(self.inert_mask_padded) ft_result = fftshift(ft_image) * fftshift(ft_mask_padded) result = ifftshift(ifft2(ft_result)) assert_array_almost_equal(abs(result), self.image)
def test_our_comp_shifted_abs(self): # Now, our computation ft_image = fft2(self.image) ft_mask = fft2(self.inert_mask, self.image.shape) ft_res_ft = fftshift(ft_image) * fftshift(ft_mask) result = ifft2(ifftshift(ft_res_ft)) assert_array_equal(abs(result), self.image)
def get_mps(t, freq, spec): "Computes the MPS of a spectrogram (idealy a log-spectrogram) or other REAL time-freq representation" mps = fftshift(fft2(spec)) amps = np.real(mps * np.conj(mps)) nf = mps.shape[0] nt = mps.shape[1] wfreq = fftshift(fftfreq(nf, d=freq[1] - freq[0])) wt = fftshift(fftfreq(nt, d=t[1] - t[0])) return wt, wfreq, mps, amps
def test_definition(self): x = [0, 1, 2, 3, 4, -4, -3, -2, -1] y = [-4, -3, -2, -1, 0, 1, 2, 3, 4] assert_array_almost_equal(fft.fftshift(x), y) assert_array_almost_equal(fft.ifftshift(y), x) x = [0, 1, 2, 3, 4, -5, -4, -3, -2, -1] y = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4] assert_array_almost_equal(fft.fftshift(x), y) assert_array_almost_equal(fft.ifftshift(y), x)
def fir_to_frp(fir,tbins=None): '''Transform a fir (time domain fr filter) to a fringe rate profile. fir: array of fringe rate profile. tbins: Corresponding time bins of filter. If None, doesnt return ffringe rates. ''' fir = ifftshift(fir, axes=-1) frp = fft(fir, axis=-1) frp = fftshift(frp, axes=-1) if tbins is not None: return frp, fftshift(fftfreq(tbins.size, tbins[1]-tbins[0])) else: return frp
def get_k(self): """ """ azisz = self.get_info('azimuth_size') azidk = self.get_info('azimuth_dk') ransz = self.get_info('range_size') randk = self.get_info('range_dk') k = (fftshift(fftfreq(azisz))*azisz*azidk, fftshift(fftfreq(ransz))*ransz*randk) return k
elementRadial = np.exp(-1 * np.power( np.log(normalizedRadius/ (centerFrequency / 0.5)),2) / (2 * np.log(sigmaF) * np.log(sigmaF)) ) theta = math.atan2(-y,x) deltaSin = math.sin(theta) * math.cos(centerAngle) - math.cos(theta) * math.sin(centerAngle) deltaCosine = math.cos(theta) * math.cos(centerAngle) + math.sin(theta) * math.sin(centerAngle) deltaTheta = abs(math.atan2(deltaSin, deltaCosine)) elementAngular = np.exp((-1 * deltaTheta * deltaTheta) / (2 * thetaStd * thetaStd)) kernel[i, j] = elementAngular * elementRadial if(kernel[i,j] < 0.001): kernel[i,j] = 0 wavelength = wavelength * wavelengthIncrement kernel = fft.fftshift(kernel) convolved = imageFFT * kernel s1 = np.array(kernel.shape) s2 = np.array(imageFFT.shape) size = s1 + s2 - 1 fsize = 2 ** np.ceil(np.log2(size)).astype(int) fslice = tuple([slice(0, int(sz)) for sz in size]) convolved = fft.ifft2(convolved)[fslice] evens = np.real(convolved) odds = np.imag(convolved)
def simul_psd_wfm(Cn2, h, seeing, L0, zenith=0., plot=False, npsflin=1, dim=1280, three_lgs_mode=False, verbose=True): """ Batch de simulation de PSF WFM MUSE avec impact de NGS. Parameters ---------- Cn2 = pondération du profil h = altitude des couches (en m) seeing = seeing @ zenith (en arcsec @ 500nm) L0 = Grande echelle (en m) zenith = (en degré) npsflin = nombre de point (lineaire) dans le champ pour l'estimation des PSF (1 = au centre, 2 = au 4 coins, 3 = 9 PSF etc ...) dim = Final dimension of the PSD """ # STEP 0 : Définition des conditions # ============================================= # Step 0.1 : turbulence # --------- Cn2 = np.array(Cn2) Cn2 /= Cn2.sum() h = np.array(h) vent = np.full_like(h, 12.5) # FIXME: currently set to IDL values for reproducability np.random.seed(12345) # arg_v = (np.random.rand(h.shape[0]) - 0.5) * np.pi # wind dir. [rad] arg_v = np.array([0.628163, -0.326497]) # from IDL # Step 0.2 : Systeme # --------- Dpup = 8. # en m (diametre du telescope) # oc = 0.14 # normalisée [de 0 --> 1] altDM = 1. # en m hsodium = 90000. # en m # lambdalgs = 0.589 # en µm lambdaref = 0.5 # en µm nact = 24. # nombre lineaire d'actionneurs nsspup = nact # nombre lineaire d'actionneurs Fsamp = 1000. # frequence d'échantillonnage [Hz] delay = 2.5 # retard en ms (lecture CCD + calcul) seplgs = 63. # separation (en rayon) des LGS [arcsec] bruitLGS2 = 1.0 # radians de phase bord a bord de sspup @ lambdalgs if three_lgs_mode: if verbose: logger.info('Using three lasers mode') poslgs = np.array([[1, 1], [-1, -1], [-1, 1]], dtype=float).T else: poslgs = np.array([[1, 1], [-1, -1], [-1, 1], [1, -1]], dtype=float).T poslgs *= seplgs # *cos(pi/4) # position sur une grille cartesienne law = "LSE" # type de lois : lse ou mmse recons_cn2 = 1 # a priori sur Cn2 => ici GLAO recons_h = altDM # a priori sur h => ici GLAO # Step 0.3 : Direction d'estimation dirperf = direction_perf(npsflin, plot=plot, lgs=poslgs) # Step 0.4 : Paremetres numériques # --------- Dimpup = 40 # Taille de la pupille en pixel pour zone de correction # coefL0 = 1 # pour gerer les "L0 numériques" # Step 0.5 : Mise en oeuvre # --------- r0ref = seeing2r01(seeing, lambdaref, zenith) # passage seeing --> r0 hz = h / np.cos(np.deg2rad(zenith)) # altitude dans la direction de visée dilat = (hsodium - hz) / hsodium # dilatation pour prendre en compte hz_lgs = hz / dilat # la LGS hz_lgs -= altDM # on prend en compte la conjugaison negative du DM # Step 0.6 : Summarize of parameters # --------- logger.debug('r0 0.5um (zenith) = %.2f', seeing2r01(seeing, lambdaref, 0)) logger.debug('r0 0.5um (line of sight) = %.2f', r0ref) logger.debug('Seeing (line of sight) = %.2f', 0.987 * 0.5 / r0ref / 4.85) logger.debug('hbarre (zenith) = %.2f', np.sum(h**(5 / 3) * Cn2)**(3 / 5)) logger.debug('hbarre (line of sight) = %.2f', np.sum(hz**(5 / 3) * Cn2)**(3 / 5)) logger.debug('vbarre = %.2f', np.sum(vent**(5 / 3) * Cn2)**(3 / 5)) # ======================================================================== # longueur physique d'un ecran de ^hase issue de la PSD # => important pour les normalisations # L = dim / Dimpup * Dpup pitch = Dpup / nact # pitch: inter-actuator distance [m] fc = 1 / (2 * pitch) # pItch frequency (1/2a) [m^{-1}] # STEP 1 : Simulation des PSF LGS (tilt inclus) # =============================================== # cube de DSP pour chaque direction d'interet - ZONE DE CORRECTION ONLY dsp = dsp4muse(Dpup, Dimpup, Dimpup * 2, Cn2, h, L0, r0ref, recons_cn2, recons_h, vent, arg_v, law, nsspup, nact, Fsamp, delay, bruitLGS2, lambdaref, poslgs, dirperf) # STEP 2: Calcul DSP fitting # =============================================== dspa = fftshift(psd_fit(dim, 2 * Dpup, r0ref, L0, fc)) dspf = np.resize(dspa, (dsp.shape[0], dim, dim)) # Finale sl = slice(dim // 2 - Dimpup, dim // 2 + Dimpup) dspf[:, sl, sl] = np.maximum(dspa[sl, sl], fftshift(dsp, axes=(1, 2))) return dspf * (lambdaref * 1000 / (2 * np.pi))**2
def plot(self,log=False,colorbar=True,title='',powerOfL=0,pngFile=None,show=True,zoomUptoL=None,\ showMask=False, yrange = None, showBinsFromFile = None,drawCirclesAtL=None,\ drawVerticalLinesAtL = None, valueRange=None, colorbarLabel=None): """ @brief Display the power spectrum """ #modLMap = self.modLMap #modLMap[np.where(modLMap ==0)] = 1. p = self.powerMap.copy() p[:] *= (self.modLMap[:] + 1.)**powerOfL p = fftshift(p) if showBinsFromFile: binLower, binUpper, binCenter = readBinningFile(showBinsFromFile) theta = np.arange(0, 2. * np.pi + 0.05, 0.05) for i in xrange(len(binLower)): x, y = binUpper[i] * np.cos(theta), binUpper[i] * np.sin(theta) pylab.plot(x, y, 'k') if drawCirclesAtL != None: for ell in drawCirclesAtL: theta = np.arange(0, 2. * np.pi + 0.05, 0.05) x, y = ell * np.cos(theta), ell * np.sin(theta) pylab.plot(x, y, 'k') if len(drawCirclesAtL) < 5: pylab.text(ell*np.cos(np.pi/4.),ell*np.sin(np.pi/4.),\ '%d'%np.int(ell),rotation=-45,horizontalalignment = 'center',\ verticalalignment='bottom',fontsize=8) if drawVerticalLinesAtL != None: for ell in drawVerticalLinesAtL: pylab.axvline(ell) if log: p = np.log10(np.abs(p)) if yrange != None: p[np.where(p < yrange[0])] = yrange[0] p[np.where(p > yrange[1])] = yrange[1] vmin = p.min() vmax = p.max() if valueRange != None: vmin = valueRange[0] vmax = valueRange[1] im = pylab.imshow(p,origin="down",extent=[np.min(self.lx),np.max(self.lx),\ np.min(self.ly),np.max(self.ly)],aspect='equal',vmin=vmin,vmax=vmax, interpolation='nearest') pylab.title(title, fontsize=8) if colorbar: cb = pylab.colorbar() if colorbarLabel != None: cb.set_label(colorbarLabel) pylab.xlabel(r'$\ell_x$', fontsize=15) pylab.ylabel(r'$\ell_y$', fontsize=15) if showMask: im2 = pylab.imshow(fftshift(self.kMask.copy()),\ origin="down",\ extent=[np.min(self.lx),\ np.max(self.lx),\ np.min(self.ly),\ np.max(self.ly)],\ aspect='equal') pylab.xlabel(r'$\ell_x$', fontsize=15) pylab.ylabel(r'$\ell_y$', fontsize=15) if colorbar: pylab.colorbar() if zoomUptoL != None: im.axes.set_xlim(-zoomUptoL, zoomUptoL) im.axes.set_ylim(-zoomUptoL, zoomUptoL) if showMask: im2.axes.set_xlim(-zoomUptoL, zoomUptoL) im2.axes.set_ylim(-zoomUptoL, zoomUptoL) if show: pylab.show() if pngFile != None: pylab.savefig(pngFile)
def compute_pspec(self, beam_correct=False, apodize_kernel=None, alpha=0.3, beta=0.0, use_pyfftw=False, threads=1, **pyfftw_kwargs): ''' Compute the 2D power spectrum. The quantity calculated here is the same as Equation 3 in Lazarian & Esquivel (2003), but the inputted arrays are not in the same form as described. We can, however, adjust for the use of normalized Centroids and the linewidth. An unnormalized centroid can be constructed by multiplying the centroid array by the moment0. Velocity dispersion is the square of the linewidth subtracted by the square of the normalized centroid. Parameters ---------- beam_correct : bool, optional If a beam object was given, divide the 2D FFT by the beam response. apodize_kernel : None or 'splitcosinebell', 'hanning', 'tukey', 'cosinebell', 'tophat' If None, no apodization kernel is applied. Otherwise, the type of apodizing kernel is given. alpha : float, optional alpha shape parameter of the apodization kernel. See `~turbustat.apodizing_kernel` for more information. beta : float, optional beta shape parameter of the apodization kernel. See `~turbustat.apodizing_kernel` for more information. use_pyfftw : bool, optional Enable to use pyfftw, if it is installed. threads : int, optional Number of threads to use in FFT when using pyfftw. pyfftw_kwargs : Passed to `~turbustat.statistics.rfft_to_fft.rfft_to_fft`. See `here <http://hgomersall.github.io/pyFFTW/pyfftw/builders/builders.html>`__ for a list of accepted kwargs. ''' if apodize_kernel is not None: apod_kernel = self.apodizing_kernel(kernel_type=apodize_kernel, alpha=alpha, beta=beta) term1_data = self.centroid * self.moment0 * apod_kernel term2_data = self.linewidth**2 + self.centroid**2 * apod_kernel mom0_data = self.moment0 * apod_kernel else: term1_data = self.centroid * self.moment0 term2_data = self.linewidth**2 + self.centroid**2 mom0_data = self.moment0 if pyfftw_kwargs.get('threads') is not None: pyfftw_kwargs.pop('threads') term1 = rfft_to_fft(term1_data, use_pyfftw=use_pyfftw, threads=threads, **pyfftw_kwargs) fft_mom0 = rfft_to_fft(mom0_data, use_pyfftw=use_pyfftw, threads=threads, **pyfftw_kwargs) # Account for normalization in the line width. term2 = np.nanmean(term2_data) mvc_fft = term1 - term2 * fft_mom0 # Shift to the center mvc_fft = fftshift(mvc_fft) if beam_correct: if not hasattr(self, '_beam'): raise AttributeError("Beam correction cannot be applied since" " no beam object was given.") beam_kern = self._beam.as_kernel(self._ang_size, y_size=self.centroid.shape[0], x_size=self.centroid.shape[1]) beam_fft = fftshift(rfft_to_fft(beam_kern.array)) self._beam_pow = np.abs(beam_fft**2) self._ps2D = np.abs(mvc_fft)**2. if beam_correct: self._ps2D /= self._beam_pow
kxymax = 1 / (2 * deltaxy) deltakxy = 1 / (xymax - xymin) kx = ky = np.arange(kxymin, kxymax, deltakxy) # not used # create 2D function f = function2D(X, Y) X0 = 0 #translation in x Y0 = 0 #translation in y f.setcenter(X0, Y0) ftype = 'square' #change ftype to choose between 'circle', 'annulus','square','gaussian','sine',deltas f.functiontype(ftype, 0.5) Z = f.data #Z are the values of the function # calculate 2D fft (translated to the center using fftshift. ifftshift is used to remove phase errors) ft = fftshift(fft2(ifftshift(Z))) # %% create figures #plot 2D function fig1 = plt.figure(figsize=(9, 9)) plt.title(f.title) #plt.title("2D function (Real part)") plt.imshow(np.real(Z), interpolation='none', cmap=cm.RdYlGn, origin='lower', extent=[xymin, xymax, xymin, xymax], vmax=np.real(Z).max(), vmin=-np.real(Z).max())
def updateNoise(self): """Updates the noise sample. Does not change any of the noise parameters but choses a new random sample given the previously set parameters. """ if not(self.noiseType in ['binary','Binary','normal','Normal','uniform','Uniform']): if (self.noiseType in ['image', 'Image']) and (self.imageComponent in ['amplitude','Amplitude']): self.noiseTex = numpy.random.uniform(0,1,int(self._size**2)) self.noiseTex = numpy.reshape(self.noiseTex,(int(self._size),int(self._size))) if self.filter in ['Butterworth','butterworth']: self.noiseTex = fftshift(self._filter(self.noiseTex)) elif self.filter in ['Gabor','gabor']: self.noiseTex = fftshift(self._gabor(self.noiseTex)) elif self.filter in ['Isotropic','isotropic']: self.noiseTex = fftshift(self._isotropic(self.noiseTex)) self.noiseTex[0][0] = 0 In = self.noiseTex * exp(1j*self.noisePh) Im = numpy.real(ifft2(In)) else: Ph = numpy.random.uniform(0,2*numpy.pi,int(self._size**2)) Ph = numpy.reshape(Ph,(int(self._size),int(self._size))) In = self.noiseTex * exp(1j*Ph) Im = numpy.real(ifft2(In)) Im = ifftshift(Im) gsd = filters.getRMScontrast(Im) factor = gsd*self.noiseClip numpy.clip(Im, -factor, factor, Im) self.tex = Im / factor elif self.noiseType in ['normal','Normal']: self.noiseTex = numpy.random.randn(int(self._sideLength[1]),int(self._sideLength[0])) / self.noiseClip elif self.noiseType in ['uniform','Uniform']: self.noiseTex = 2.0 * numpy.random.rand(int(self._sideLength[1]),int(self._sideLength[0])) - 1.0 else: numpy.random.shuffle(self.noiseTex) # pick random noise sample by shuffleing values self.noiseTex = numpy.reshape(self.noiseTex,(int(self._sideLength[1]),int(self._sideLength[0]))) if self.noiseType in ['binary','Binary','normal','Normal','uniform','Uniform']: if self.filter in ['butterworth', 'Butterworth', 'Gabor','gabor','Isotropic','isotropic']: if self.units == 'pix': if self._size[0] == self._size[1]: baseImage = imresize(self.noiseTex, (int(self._size[0]),int(self._size[1])), interp='nearest') else: msg = ('NoiseStim can only apply filters to square noise images') raise ValueError(msg) else: baseImage = imresize(self.noiseTex, (int(self._size),int(self._size)), interp='nearest') baseImage = numpy.array(baseImage).astype( numpy.float32) * 0.0078431372549019607 - 1.0 FT = fft2(baseImage) spectrum = numpy.absolute(fftshift(FT)) angle = numpy.angle(FT) if self.filter in ['butterworth','Butterworth']: spectrum = fftshift(self._filter(spectrum)) elif self.filter in ['isotropic','Isotropic']: spectrum = fftshift(self._isotropic(spectrum)) elif self.filter in ['gabor','Gabor']: spectrum = fftshift(self._gabor(spectrum)) spectrum[0][0] = 0 # set DC to zero FT = spectrum * exp(1j*angle) Im = numpy.real(ifft2(FT)) gsd = filters.getRMScontrast(Im) factor = gsd*self.noiseClip numpy.clip(Im, -factor, factor, Im) self.tex = Im / factor else: if not(self.noiseType in ['image','Image']): self.tex = self.noiseTex
flsig4 = (bpf1(data)) flsig5 = (bpf2(data)) flsig6 = (bpf3(data)) plt.title("segmented signal") plt.plot(flsig4, color='green') plt.plot(flsig5, color='blue') plt.plot(flsig6, color='red') plt.show() datafft4 = fft_plot(flsig4, "fft :: song 1 no shift") datafft5 = fft_plot(flsig5, "fft :: song 2 no shift") datafft6 = fft_plot(flsig6, "fft :: song 3 no shift") plt.title("segmented signals :: Fourier Transform") freq = fft.fftshift(fft.fftfreq(datafft4.shape[-1])) plt.plot(freq, np.abs(datafft4), color='green') plt.plot(freq, np.abs(datafft5), color='blue') plt.plot(freq, np.abs(datafft6), color='red') plt.show() flsig4 = lpf(flsig4 * w1) flsig5 = lpf(flsig5 * w2) flsig6 = lpf(flsig6 * w3) plt.title("segmented signal") plt.plot(flsig4, color='green') plt.plot(flsig5, color='blue') plt.plot(flsig6, color='red') plt.show()
def test_inverse(self): for n in [1, 4, 9, 100, 211]: x = np.random.random((n,)) assert_array_almost_equal(fft.ifftshift(fft.fftshift(x)), x)
import numpy as np from numpy import pi from numpy.fft import fft from numpy.fft import ifft from numpy.fft import fftshift from numpy.fft import ifftshift import matplotlib.pyplot as plt from skimage.data import shepp_logan_phantom from skimage.transform import resize from scipy.signal import convolve FFT = lambda x: fftshift(fft(ifftshift(x))) IFFT = lambda x: fftshift(ifft(ifftshift(x))) EPS = 1e-18 ## 4) Sptial 1D Convolution vs. Fourier Multiplication N = 100 M = 36 X = np.random.randn(N, 1) Y = np.random.randn(M, 1) if (N > M): K = int(max(64, 2**int(np.log2(2*N)))) else: K = int(max(64, 2**int(np.log2(2*M)))) X_ = np.zeros(K)
def bt_spectrum(time_series): R = xcorr(time_series, scale='biased') return N.abs(fliplr(fftshift(fft(R))))
def time_gate(ntwk, start=None, stop=None, center=None, span=None, mode='bandpass', window=('kaiser', 6), media=None, boundary='reflect', return_all=False): ''' Time-gate one-port s-parameters. The gate can be defined with start/stop times, or by center/span. all times are in units of nanoseconds. common windows are: * ('kaiser', 6) * 6 # integers are interpreted as kaiser beta-values * 'hamming' * 'boxcar' # a staightup rect If no parameters are passed this will try to auto-gate the largest peak. Parameters ------------ start : number, or None start of time gate, (ns). stop : number, or None stop of time gate (ns). center : number, or None center of time gate, (ns). If None, and span is given, the gate will be centered on the peak. span : number, or None span of time gate, (ns). If None span will be half of the distance to the second tallest peak mode: ['bandpass','bandstop'] mode of gate boundary: {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, passed to `scipy.ndimage.filters.convolve1d` window : string, float, or tuple passed to `window` arg of `scipy.signal.get_window` Notes ------ You cant gate things that are 'behind' strong reflections. This is due to the multiple reflections that occur. If `center!=0`, then the ntwk's time response is shifted to t=0, gated, then shifted back to where it was. This is done in frequency domain using `ntwk.delay()`. If the media being gated is dispersive (ie waveguide), then the gate `span` will be span at t=0, which is different. If you need to time-gate an N-port network, then you should gate each s-parameter independently. Returns -------- ntwk : Network copy of ntwk with time-gated s-parameters .. warning:: Depending on sharpness of the gate, the band edges may be inaccurate, due to properties of FFT. We do not re-normalize anything. ''' if ntwk.nports > 1: raise ValueError( 'Time-gating only works on one-ports. try taking ntwk.s11 or ntwk.s21 first' ) if start is not None and stop is not None: start *= 1e-9 stop *= 1e-9 span = abs(stop - start) center = (stop + start) / 2. else: if center is None: # they didnt provide center, so find the peak n = ntwk.s_time_mag.argmax() center = ntwk.frequency.t_ns[n] if span is None: span = detect_span(ntwk) center *= 1e-9 span *= 1e-9 start = center - span / 2. stop = center + span / 2. # find start/stop gate indecies t = ntwk.frequency.t start_idx = find_nearest_index(t, start) stop_idx = find_nearest_index(t, stop) # create window window_width = abs(stop_idx - start_idx) window = signal.get_window(window, window_width) # create the gate by padding the window with zeros gate = npy.r_[npy.zeros(start_idx), window, npy.zeros(len(t) - stop_idx)] #FFT the gate, so we have it's frequency response, aka kernel kernel = fft.ifftshift(fft.fft(fft.fftshift(gate, axes=0), axis=0)) kernel = abs(kernel).flatten() # take mag and flatten kernel = kernel / sum(kernel) # normalize kernel out = ntwk.copy() # conditionally delay ntwk, to center at t=0, this is # equivalent to gating at center. (this is probably very inefficient) if center != 0: out = out.delay(-center * 1e9, 'ns', port=0, media=media) # waste of code to handle convolve1d suck re = out.s_re[:, 0, 0] im = out.s_im[:, 0, 0] s = convolve1d(re,kernel, mode=boundary)+\ 1j*convolve1d(im,kernel, mode=boundary) out.s[:, 0, 0] = s # conditionally un-delay ntwk if center != 0: out = out.delay(center * 1e9, 'ns', port=0, media=media) if mode == 'bandstop': out = ntwk - out elif mode == 'bandpass': pass else: raise ValueError('mode should be \'bandpass\' or \'bandstop\'') if return_all: # compute the gate ntwk and add delay gate_ntwk = out.s11.copy() gate_ntwk.s = kernel gate_ntwk = gate_ntwk.delay(center * 1e9, 'ns', media=media) return {'gated_ntwk': out, 'gate': gate_ntwk} else: return out
def periodogram(time_series): Z = fliplr(fftshift(fft(time_series))) return N.abs(Z)*N.abs(Z)/time_series.size
plt.legend(["datos", "lineal"]) v2 = plt.subplot(2,1,2) v2.scatter(x1,y1) y = interp.interp1d(x1,y1, kind = "cubic") x = np.linspace(0,6,1000) v2.plot(x,y(x), c="r") plt.legend(["datos", "cubica"]) plt.savefig("interp.png") n=100 x= np.linspace(0,2*3.14,n) y = np.sin(x) +np.random.rand(n) yo = f.fftshift( f.fft(y) ) xo = f.fftshift( f.fftfreq(n) ) plt.figure() v1 =plt.subplot(4,1,1) v1.plot(xo,abs(yo),label="fourier") plt.legend() v2 =plt.subplot(4,1,2) v2.plot(x,y,label="funcion") plt.legend() yo[abs(xo) > 0.01] = 0 #delta = np.where(abs(xo) > 0) v3 =plt.subplot(4,1,3)
def _calcpr_raar(F, C_s, plan, D_s=None, rho_0=None, r_factor=None, *args, **kwargs): """_calcpr_raar(F, C_s, plan, D_s=None, rho_0=None, r_factor=None, *args, **kwargs) -> None Relaxed alternating averaged reflections algorithm Detail: A. V. Martin et al., Optics Express 20, 16650 (2012) Parameters ---------- F : numpy.2darray target modulus C_s : numpy.2darray support in real space plan : Plan / list of Plans object (Plan) plan of PR D_s : numpy.2darray (default : None) mask in reciprocal space rho_0 : numpy.2darray (default : None) initial guess of the density map r_factor : list (default : None) history of R factor args : options kwargs : options """ # Initialize if rho_0 is None: rho_0 = _init_phase(plan.shape) rho_0 *= np.max(np.abs(ifft2(F))) elif rho_0 == "phase": rho_0 = _init_phase(plan.shape) rho_0 *= np.max(np.abs(ifft2(F))) elif rho_0 == "amplitude": rho_0 = _init_phase(plan.shape) rho_0 = ifft2(F*rho_0) elif rho_0 == "auto": rho_0 = ifft2(F**2) elif rho_0 == "auto, amplitude": rho_0 = _init_phase(plan.shape) rho_0 = ifft2(F**2 * rho_0) elif rho_0 == "auto, phase": rho_0 = _init_phase(plan.shape) rho_0 = rho_0 * ifft2(F**2) if r_factor is None: r_factor = [] _F = np.abs(fftshift(F)) _D_s = D_s if D_s is not None: _D_s = fftshift(D_s) rho_i = 1.*rho_0 rho_f = np.zeros(F.shape, dtype=np.complex64) beta = plan.kwargs.get('beta') if beta is None or beta <= 0: beta = 0.85 gamma_s = plan.kwargs.get("gamma_s") if gamma_s is None or gamma_s > 0: gamma_s = - 1. / beta gamma_m = plan.kwargs.get("gamma_m") if gamma_m is None or gamma_m < 0: gamma_m = 1. / beta # Define FFT functions func = FFT_FUNC.get(plan.fft_type) ifunc = IFFT_FUNC.get(plan.fft_type) # Check use of mask and validity of the parameters updmask_use = plan.kwargs.get('updmask_use', False) updmask_N = plan.kwargs.get('updmask_N') if updmask_use is None or type(updmask_use) != bool: updmask_use = False elif updmask_N is None or type(updmask_N) != int or updmask_N <= 0: updmask_use = False ratio = plan.kwargs.get('updmask_ratio') if ratio is None or ratio <= 0: ratio = -1 _init_C_s = kwargs.get("init_C_s", None) width = 1.5 if C_s is None: C_s = _updmask(np.abs(rho_i), C_s, plan.rho_filter, width, ratio) if _init_C_s is not None and _init_C_s == True: C_s = _updmask(np.abs(rho_i), C_s, plan.rho_filter, width, ratio) # The known error function for Liu's process. err = plan.kwargs.get('err') if err is not None and type(err) not in [np.ndarray, list]: raise TypeError('"err" has an invalid type.') intensity = plan.kwargs.get('intensity') if intensity is not None and type(intensity) != bool: raise TypeError('"intensity" must be boolean.') # alpha = plan.N # d_alpha = - (plan.N-1./plan.N)/9. # updoss_N = int(plan.N/10) # _qx = np.linspace(-1., 1.-2./plan.shape[0], plan.shape[0]) # _qy = np.linspace(-1., 1.-2./plan.shape[1], plan.shape[1]) # _qxx, _qyy = np.meshgrid(_qx, _qy) # _qrr = np.sqrt(_qxx**2 + _qyy**2) # del _qxx, _qyy, _qx, _qy _num = 0 if plan.kwargs.get('num') is None else plan.kwargs.get('num') # Main loop width = 1.5 # _W = np.exp(-0.5*(_qrr / alpha)**2) for ii in range(plan.N): rho_f = func(rho_i, plan.x_gpu, plan.xf_gpu, plan.cufft_plan) # rho(n) -> G(n) r_factor.append(_calc_r_factor(rho_f, _F)) rho_f = _projection_I(rho_f, _F, plan.f_const, _D_s, err, intensity, **kwargs) # G(n) -> G'(n) A = 2. * beta * _projection_er(ifunc(rho_f, plan.x_gpu, plan.xf_gpu, plan.cufft_plan), C_s, plan.rho_const) B = (1 - 2. * beta) * ifunc(rho_f, plan.x_gpu, plan.xf_gpu, plan.cufft_plan) C = - beta * _projection_er(rho_i, C_s, plan.rho_const) rho_i = beta * rho_i + A + B + C # rho_i = _projection_hio(ifunc(rho_f, plan.x_gpu, plan.xf_gpu, plan.cufft_plan), C_s, plan.rho_const, rho_i, beta) # G'(n) -> rho(n+1) # buff = func(rho_i, plan.x_gpu, plan.xf_gpu, plan.cufft_plan) # buff = np.real(ifunc(buff, plan.x_gpu, plan.xf_gpu, plan.cufft_plan)) # take real part of density # buff = np.real(ifunc(buff*_W, plan.x_gpu, plan.xf_gpu, plan.cufft_plan)) # take real part of density # rho_i = rho_i*C_s + buff*(1-C_s) # if np.mod(ii+1, updoss_N) == 0: # alpha -= d_alpha # _W = np.exp(-0.5*(_qrr / alpha)**2) if updmask_use: if np.mod(ii+1, updmask_N) == 0 and ratio > 0: # Update the mask width = width-0.03 if width >= 1.5 else 1.5 C_s = _updmask(np.abs(rho_i), C_s, plan.rho_filter, width, ratio) if plan.kwargs.get('save') is True: _savefig(np.abs(rho_i), C_s, rho_f, r_factor, plan.pr_mode, ii+_num) plan.set(rho_i, r_factor, C_s)
def buildNoise(self): """build a new noise sample. Required to act on changes to any noise parameters or texRes. """ if self.units == 'pix': if not (self.noiseType in ['Binary','binary','Normal','normal','uniform','Uniform']): mysize = numpy.max(self.size) else: mysize = self.size sampleSize = self.noiseElementSize mysf = self.__dict__['noiseBaseSf']*mysize lowsf = self.noiseFilterLower*numpy.max(mysize) # filter can only be applied to square images anyway upsf = self.noiseFilterUpper*numpy.max(mysize) else: mysize = self.texRes pixSize = self.size/self.texRes sampleSize = self.noiseElementSize/pixSize mysf = self.size[0]*self.noiseBaseSf lowsf = self.size[0]*self.noiseFilterLower upsf = self.size[0]*self.noiseFilterUpper self._size = mysize # store for use by updateNoise() self._sf = mysf self._lowsf = lowsf self._upsf = upsf if self.noiseType in ['binary','Binary','normal','Normal','uniform','Uniform']: self._sideLength = numpy.round(mysize/sampleSize) # dummy side length for use when unpacking noise samples in updateNoise() self._sideLength.astype(int) if ((self._sideLength[0] < 2) and (self._sideLength[1] < 2)): msg=('Noise sample size ' 'must result in more than ' '1 sample per image dimension.') raise ValueError(msg) totalSamples = self._sideLength[0]*self._sideLength[1] if self.noiseType in ['binary','Binary']: self.noiseTex=numpy.append(numpy.ones(int(numpy.round(totalSamples/2.0))),-1*numpy.ones(int(numpy.round(totalSamples/2.0)))) elif self.noiseType in ['White','white','filtered','Filtered','isotropic','Isotropic','Gabor','gabor']: self.noiseTex = numpy.ones((int(mysize),int(mysize))) self.noiseTex = fftshift(self.noiseTex) elif self.noiseType in ['Image','image']: if not(self.noiseImage in ['None','none']): im = Image.open(self.noiseImage) im = im.transpose(Image.FLIP_TOP_BOTTOM) im = im.convert("L") # FORCE TO LUMINANCE im = imresize(im, (int(self._size),int(self._size)), interp='bilinear') intensity = numpy.array(im).astype( numpy.float32) * 0.0078431372549019607 - 1.0 if self.imageComponent in ['phase', 'Phase']: self.noiseTex = numpy.absolute(fftshift(fft2(intensity))) # fftshift here is undone later elif self.imageComponent in ['amplitude', 'Amplitude']: self.noisePh = numpy.angle((fft2(intensity))) # fftshift here is undone later self.noiseTex = numpy.random.uniform(0,1,int(self._size**2)) self.noiseTex = numpy.reshape(self.noiseTex,(int(self._size),int(self._size))) else: raise ValueError("Unknown value for imageComponent in noiseStim") else: self.noiseTex = numpy.ones((int(mysize),int(mysize))) # if image is 'None' will make white noise as temporary measure else: msg = ('Noise type not recognised. Valid types are Binary, Uniform, Normal,' 'White, Filtered, Gabor, Isotropic or Image') raise ValueError(msg) if not(self.noiseType in ['binary','Binary','normal','Normal','uniform','Uniform']): if (self.noiseType in ['filtered','Filtered']) or (self.filter in ['butterworth', 'Butterworth']): self.noiseTex=self._filter(self.noiseTex) elif (self.noiseType in ['Isotropic','isotropic']) or (self.filter in ['isotropic', 'Isopropic']): self.noiseTex = self._isotropic(self.noiseTex) elif (self.noiseType in ['Gabor','gabor']) or (self.filter in ['gabor', 'Gabor']): self.noiseTex = self._gabor(self.noiseTex) self.noiseTex = fftshift(self.noiseTex) self.noiseTex[0][0] = 0 # Set DC to zero self._needBuild = False # prevent noise from being re-built at next draw() unless a parameter is changed in the mean time. self.updateNoise() # now choose the initial random sample.
def blr_probe3(N, rs_rad, fs_rad1, fs_rad2): divs = 60 rs_mask = sector_mask((N, N), (N / 2, N / 2), rs_rad * N, (0, 360)) rs_mask = rs_mask / norm(rs_mask, 1) fs_mask = np.zeros_like(rs_mask, dtype=np.float32) for i in np.arange(0, divs, 3): fs_mask += sector_mask((N, N), (N / 2, N / 2), fs_rad1 * N, (360.0 / divs * i, 360.0 / divs * (i + 1))) # fs_mask1 = sector_mask((N,N),(N/2,N/2),fs_rad1*N,(0,360)) fs_mask3 = np.logical_not( sector_mask((N, N), (N / 2, N / 2), fs_rad2 * N, (0, 360))) fs_mask = (fs_mask.astype(np.int)) * fs_mask3.astype(np.int) fs_mask = fs_mask / norm(fs_mask, 1) # riplot(rs_mask) riplot(fs_mask) fs_mask = fftshift(fs_mask) phase = np.ones_like( fs_mask ) # fftshift(nd.gaussian_filter(fftshift(np.pi*np.random.uniform(size=(N,N))),2)) psi_f = fs_mask * np.exp(2j * phase) riplot(fftshift(psi_f)) for i in range(50): # print i psi = ifft2(psi_f, norm='ortho') # plotcx(psi) # applot(psi,'psi') psir = psi.real psii = psi.imag # psir = nd.gaussian_filter(psi.real,5) # psii = nd.gaussian_filter(psi.imag,5) psi = rs_mask * (psir + 1j * psii) psi = psi / norm(psi) # plotcx(psi) psi_f = fft2(psi, norm='ortho') # plotcx(psi_f) # applot(psi_f,'psi_f') # riplot(fs_mask,'fs_mask') # plotcx(fftshift(psi_f)) # psi_fangle = fftshift(nd.gaussian_filter(fftshift(np.angle(psi_f)),1)) psi_fangle = np.angle(psi_f) psi_f = fs_mask * np.exp(1j * psi_fangle) psi_f = psi_f / norm(psi_f) # plotcx(psi_f) psi = ifft2(psi_f, norm='ortho') # plotcx(psi) # applot(psi,'psi') # psir = psi.real # psii = psi.imag # psir = nd.gaussian_filter(psi.real,5) # psii = nd.gaussian_filter(psi.imag,5) # psi = rs_mask * np.exp(1j*np.angle(psi)) # psi = psi/norm(psi) # plotcx(psi) # psi_f = fft2(psi,norm='ortho') # from skimage.restoration import unwrap_phase # psi = ifft2(psi_f,norm='ortho') # plotcx(psi_f) # applot(psi) # psia = nd.gaussian_filter(np.abs(psi),5) # psip = nd.gaussian_filter(np.angle(psi),5) # psi2 = psia * np.exp(1j*psip) ## plotcx(psi2) # angles = np.digitize(np.angle(psi2),np.arange(10)*np.pi/10) * np.pi/10 # psi3 = np.abs(psi2) * np.exp(1j*angles) # plotcx(psi3) # plotcx(psi) # psi_fabs = np.abs(psi_f) # # psi_fangle = unwrap_phase(np.angle(psi_f)) # psi_fu = psi_fabs * np.exp(1j*psi_fangle) # applot(fftshift(psi_f)) return np.real(psi).astype(np.float32), np.imag(psi).astype(np.float32)
def pass_through(u, noisef): U = fftshift(fft(u), axis=-1) U = U + U - noise_f u = ifft(fftshift(U, axis=-1)) return u
def main(): from matplotlib.pyplot import semilogx, plot, show, xlim, ylim, figure, legend, subplot, bar from numpy.fft import fft, fftfreq, fftshift, ifft from numpy import log10, linspace, interp, angle, array, concatenate N = 2048 * 2 * 2 fs = 44100. Nchannels = 20 low_freq = 20. impulse = zeros(N) impulse[N / 2] = 1 f = 1000. #impulse = sin(2*pi*f*arange(0, N/fs, 1./fs)) #[ERBforward, ERBfeedback] = MakeERBFilters(fs, Nchannels, low_freq) #y = ERBFilterBank(ERBforward, ERBfeedback, impulse) BandsPerOctave = 3 Nbands = NOCTAVE * BandsPerOctave [B, A, fi, fl, fh] = octave_filters(Nbands, BandsPerOctave) y, zfs = octave_filter_bank(B, A, impulse) #print "Filter lengths without decimation" #for b, a in zip(B, A): # print len(b), len(a) response = 20. * log10(abs(fft(y))) freqScale = fftfreq(N, 1. / fs) figure() subplot(211) for i in range(0, response.shape[0]): semilogx(freqScale[0:N / 2], response[i, 0:N / 2]) xlim(fs / 2000, fs) ylim(-70, 10) subplot(212) m = 0 for f in fi: p = 10. * log10((y[m]**2).mean()) m += 1 semilogx(f, p, 'ko') Ndec = 3 fc = 0.5 # other possibilities #(bdec, adec) = ellip(Ndec, 0.05, 30, fc) #print bdec #(bdec, adec) = cheby1(Ndec, 0.05, fc) #(bdec, adec) = butter(Ndec, fc) (bdec, adec) = iirdesign(0.48, 0.50, 0.05, 70, analog=0, ftype='ellip', output='ba') #bdec = firwin(30, fc) #adec = [1.] figure() subplot(211) response = 20. * log10(abs(fft(impulse))) plot(fftshift(freqScale), fftshift(response), label="impulse") y = lfilter(bdec, adec, impulse) response = 20. * log10(abs(fft(y))) plot(fftshift(freqScale), fftshift(response), label="lowpass") ydec = y[::2].repeat(2) response = 20. * log10(abs(fft(ydec))) plot(fftshift(freqScale), fftshift(response), label="lowpass + dec2 + repeat2") ydec2 = interp(range(0, len(y)), range(0, len(y), 2), y[::2]) response = 20. * log10(abs(fft(ydec2))) plot(fftshift(freqScale), fftshift(response), label="lowpass + dec2 + interp2") ydec3 = y[::2] response = 20. * log10(abs(fft(ydec3))) freqScale2 = fftfreq(N / 2, 2. / fs) plot(freqScale2, fftshift(response), label="lowpass + dec2") legend(loc="lower left") subplot(212) plot(range(0, len(impulse)), impulse, label="impulse") plot(range(0, len(impulse)), y, label="lowpass") plot(range(0, len(impulse)), ydec, label="lowpass + dec2 + repeat2") plot(range(0, len(impulse)), ydec2, label="lowpass + dec2 + interp2") plot(range(0, len(impulse), 2), ydec3, label="lowpass + dec2") legend() [boct, aoct, fi, flow, fhigh] = octave_filters_oneoctave(Nbands, BandsPerOctave) y, dec, zfs = octave_filter_bank_decimation(bdec, adec, boct, aoct, impulse) #print "Filter lengths with decimation" #print len(bdec), len(adec) #for b, a in zip(boct, aoct): # print len(b), len(a) figure() subplot(211) for yone, d in zip(y, dec): response = 20. * log10(abs(fft(yone)) * d) freqScale = fftfreq(N / d, 1. / (fs / d)) semilogx(freqScale[0:N / (2 * d)], response[0:N / (2 * d)]) xlim(fs / 2000, fs) ylim(-70, 10) subplot(212) m = 0 for i in range(0, NOCTAVE): for f in fi: p = 10. * log10((y[m]**2).mean()) semilogx(f / dec[m], p, 'ko') m += 1 [boct, aoct, fi, flow, fhigh] = octave_filters_oneoctave(Nbands, BandsPerOctave) y1, dec, zfs = octave_filter_bank_decimation(bdec, adec, boct, aoct, impulse[0:N / 2]) y2, dec, zfs = octave_filter_bank_decimation(bdec, adec, boct, aoct, impulse[N / 2:], zis=zfs) y = [] for y1one, y2one in zip(y1, y2): y += [concatenate((y1one, y2one))] figure() subplot(211) for yone, d in zip(y, dec): response = 20. * log10(abs(fft(yone)) * d) freqScale = fftfreq(N / d, 1. / (fs / d)) semilogx(freqScale[0:N / (2 * d)], response[0:N / (2 * d)]) xlim(fs / 2000, fs) ylim(-70, 10) subplot(212) m = 0 for i in range(0, NOCTAVE): for f in fi: p = 10. * log10((y[m]**2).mean()) semilogx(f / dec[m], p, 'ko') m += 1 generate_filters_params() show()
def main(): # Read Image in grayscale and show img = cv2.imread("input.jpg", 0) cv2.imwrite("orig.png", img) # -------------------------------------------------------------------------- # Create Filter # # TODO: 3 Marks: Create sharpen filter from the lecture, but with a # Gaussian filter form the averaging instead of the mean filter. For the # Gaussian filter, use a kernel with size 31x31 with sigma 5. For the unit # impulse set the multiplier to be 2. # To get you started, here is a 1D Gaussian filter of size 31 and sigma=5 filter1D = cv2.getGaussianKernel(31, 5) kernel = TODO # -------------------------------------------------------------------------- # Filter with FFT # # -------------------------------------------------------------------------- # TODO: 1 Mark: Pad filter with zeros to have the same size as the image, # but with the filter in the center. This creates a larger filter, that # effectively does the same thing as the original image. kernel_padded = TODO # -------------------------------------------------------------------------- # Shift filter image to have origin on 0,0. This one is done for you. The # exact theory behind this was not explained in class so you may skip this # part. kernel_padded_shifted = fftshift(kernel_padded) # -------------------------------------------------------------------------- # TODO: 1 Mark: Move all signal to Fourier space (DFT). img_fft = TODO kernel_fft = TODO # -------------------------------------------------------------------------- # Display signals in Fourier Space # I put some visualization here to help debugging :-) cv2.imwrite("orig_fft.png", np.minimum(1e-5 * np.abs(fftshift(img_fft)), 1.0) * 255.) cv2.imwrite("filt_fft.png", np.minimum(1e-1 * np.abs(fftshift(kernel_fft)), 1.0) * 255.) # -------------------------------------------------------------------------- # TODO: 1 Mark: Do filtering in Fourier space img_filtered_fft = TODO # -------------------------------------------------------------------------- # TODO: 1 Mark: Bring back to Spatial domain (Inverse DFT) # TODO: 2 Marks: Throw away the imaginary part and clip between 0 and 255 # to make it a real image. img_sharpened = TODO cv2.imwrite("res_fft.png", img_sharpened.astype(np.uint8)) # -------------------------------------------------------------------------- # ---------------------------------------------------------------------- # Filter with OpenCV # TODO: 1 Mark: Use padded filter and cyclic padding (wrap) to get exact results # TOOD: 1 Mark: Clip image for display img_sharpened = TODO # -------------------------------------------------------------------------- cv2.imwrite("res_opencv.png", img_sharpened.astype(np.uint8)) cv2.waitKey(-1)
def fftRatio(convolved, kernel): nf = len(convolved) convolved_pad = np.pad(convolved, (nf / 2, nf / 2), mode='constant') kernel_pad = np.pad(kernel, (nf / 2, nf / 2), mode='constant') return fft.fftshift(fft.fft(convolved_pad) / fft.fft(kernel_pad))
[p,p] = np.shape(A0) mask = np.zeros([p,p],dtype=complex) for x in range(p): for y in range(p): u = x-p/2+1 v = y-p/2+1 try: mask[x,y] = complex(u,v)/np.sqrt(u**2+v**2) except ZeroDivisionError: mask[x,y] = 0 A = A0-A180 A_ft = fftshift(fft2(A)) #h = mat2gray(abs(A_ft)) #cv2.imshow('FFT',h) B_ft = A_ft*mask B = ifft2(ifftshift(B_ft)) B = abs(B) k = A+B*complex(0,1) k1 = abs(k) h = mat2gray(k1)*255 cv2.imwrite('hilbert.bmp',h)
#################################################################################### # Plotting the magnitude 2D-FFT on a vertical log scales shows something unexpected: # there appears to be peaks at the corners and no information at the center. # This is because the output for the ‘fft2’ function flips the frequency axes so # that low frequencies are at the ends, and the highest frequency is in the middle. fig, axis = plt.subplots(figsize=(5, 5)) _ = px.plot_utils.plot_map(axis, np.abs(fft_image_raw), cmap=plt.cm.OrRd, clim=[0, 3E+3]) axis.set_title('FFT2 of image') #################################################################################### # To correct this, use the ‘fftshift’ command. # fftshift brings the lowest frequency components of the FFT back to the center of the plot fft_image_raw = npf.fftshift(fft_image_raw) fft_abs_image_raw = np.abs(fft_image_raw) def crop_center(image, cent_size=128): return image[image.shape[0] // 2 - cent_size // 2:image.shape[0] // 2 + cent_size // 2, image.shape[1] // 2 - cent_size // 2:image.shape[1] // 2 + cent_size // 2] # After the fftshift, the FFT looks right fig, axes = plt.subplots(ncols=2, figsize=(10, 5)) for axis, img, title in zip( axes, [fft_abs_image_raw, crop_center(fft_abs_image_raw)], ['FFT after fftshift-ing', 'Zoomed view around origin']):
def vortex(mp, im, idm): """ Differential model used to compute ctrl Jacobian for vortex coronagraph. Specialized compact model used to compute the DM response matrix, aka the control Jacobian for a vortex coronagraph. Can include an apodizer, making it an apodized vortex coronagraph (AVC). Does not include unknown aberrations of the full, "truth" model. This model propagates the first-order Taylor expansion of the phase from the poke of each actuator of the deformable mirror. Parameters ---------- mp : ModelParameters Structure containing optical model parameters Returns ------- Gzdl : numpy ndarray Complex-valued, 2-D array containing the Jacobian for the specified Zernike mode, DM number, and wavelength. """ modvar = falco.config.Object() # Initialize the new structure modvar.sbpIndex = mp.jac.sbp_inds[im] modvar.zernIndex = mp.jac.zern_inds[im] wvl = mp.sbp_centers[modvar.sbpIndex] mirrorFac = 2. # Phase change is twice the DM surface height. NdmPad = int(mp.compact.NdmPad) if mp.flagRotation: NrelayFactor = 1 else: NrelayFactor = 0 # zero out the number of relays # Minimum FPM resolution for Jacobian calculations (in pixels per lambda/D) minPadFacVortex = 8 # Get FPM charge if type(mp.F3.VortexCharge) == np.ndarray: # Passing an array for mp.F3.VortexCharge with # corresponding wavelengths mp.F3.VortexCharge_lambdas # represents a chromatic vortex FPM if mp.F3.VortexCharge.size == 1: charge = mp.F3.VortexCharge else: np.interp(wvl, mp.F3.VortexCharge_lambdas, mp.F3.VortexCharge, 'linear', 'extrap') elif type(mp.F3.VortexCharge) == int or type(mp.F3.VortexCharge) == float: # single value indicates fully achromatic mask charge = mp.F3.VortexCharge else: raise TypeError( "mp.F3.VortexCharge must be an int, float, or numpy ndarray.") """Input E-fields""" Ein = np.squeeze(mp.P1.compact.E[:, :, modvar.sbpIndex]) # Apply a Zernike (in amplitude) at input pupil # Used only for Zernike sensitivity control, which requires the perfect # E-field of the differential Zernike term. if not modvar.zernIndex == 1: indsZnoll = modvar.zernIndex # Just send in 1 Zernike mode zernMat = np.squeeze( falco.zern.gen_norm_zern_maps(mp.P1.compact.Nbeam, mp.centering, indsZnoll)) zernMat = pad_crop(zernMat, mp.P1.compact.Narr) Ein = Ein*zernMat*(2*np.pi/wvl) * \ mp.jac.Zcoef[mp.jac.zerns == modvar.zernIndex] """ Masks and DM surfaces """ pupil = pad_crop(mp.P1.compact.mask, NdmPad) Ein = pad_crop(Ein, NdmPad) # Re-image the apodizer from pupil P3 back to pupil P2. if (mp.flagApod): apodReimaged = pad_crop(mp.P3.compact.mask, NdmPad) apodReimaged = fp.relay(apodReimaged, NrelayFactor * mp.Nrelay2to3, mp.centering) else: apodReimaged = np.ones((NdmPad, NdmPad)) # Compute the DM surfaces for the current DM commands if any(mp.dm_ind == 1): DM1surf = pad_crop(mp.dm1.compact.surfM, NdmPad) # DM1surf = falco.dm.gen_surf_from_act(mp.dm1, mp.dm1.compact.dx, NdmPad) else: DM1surf = np.zeros((NdmPad, NdmPad)) if any(mp.dm_ind == 2): DM2surf = pad_crop(mp.dm2.compact.surfM, NdmPad) # DM2surf = falco.dm.gen_surf_from_act(mp.dm2, mp.dm2.compact.dx, NdmPad) else: DM2surf = np.zeros((NdmPad, NdmPad)) if (mp.flagDM1stop): DM1stop = pad_crop(mp.dm1.compact.mask, NdmPad) else: DM1stop = np.ones((NdmPad, NdmPad)) if (mp.flagDM2stop): DM2stop = pad_crop(mp.dm2.compact.mask, NdmPad) else: DM2stop = np.ones((NdmPad, NdmPad)) # This block is for BMC surface error testing if (mp.flagDMwfe): if any(mp.dm_ind == 1): Edm1WFE = np.exp( 2 * np.pi * 1j / wvl * pad_crop(mp.dm1.compact.wfe, NdmPad, 'extrapval', 0)) else: Edm1WFE = np.ones((NdmPad, NdmPad)) if any(mp.dm_ind == 2): Edm2WFE = np.exp( 2 * np.pi * 1j / wvl * pad_crop(mp.dm2.compact.wfe, NdmPad, 'extrapval', 0)) else: Edm2WFE = np.ones((NdmPad, NdmPad)) else: Edm1WFE = np.ones((NdmPad, NdmPad)) Edm2WFE = np.ones((NdmPad, NdmPad)) """Propagation""" # Define pupil P1 and Propagate to pupil P2 EP1 = pupil * Ein # E-field at pupil plane P1 EP2 = fp.relay(EP1, NrelayFactor * mp.Nrelay1to2, mp.centering) # Propagate from P2 to DM1, and apply DM1 surface and aperture stop if not (abs(mp.d_P2_dm1) == 0): # E-field arriving at DM1 Edm1 = fp.ptp(EP2, mp.P2.compact.dx * NdmPad, wvl, mp.d_P2_dm1) else: Edm1 = EP2 Edm1out = Edm1 * Edm1WFE * DM1stop * np.exp( mirrorFac * 2 * np.pi * 1j * DM1surf / wvl) """ ---------- DM1 ---------- """ if idm == 1: Gzdl = np.zeros((mp.Fend.corr.Npix, mp.dm1.Nele), dtype=complex) # Array size for planes P3, F3, and P4 Nfft1 = int(2**falco.util.nextpow2( np.max( np.array([ mp.dm1.compact.NdmPad, minPadFacVortex * mp.dm1.compact.Nbox ])))) # Don't crop--but do pad if necessary. # Generate vortex FPM with fftshift already applied fftshiftVortex = fftshift( falco.mask.falco_gen_vortex_mask(charge, Nfft1)) # Two array sizes (at same resolution) of influence functions for MFT and angular spectrum NboxPad1AS = int( mp.dm1.compact.NboxAS ) # array size for FFT-AS propagations from DM1->DM2->DM1 mp.dm1.compact.xy_box_lowerLeft_AS = mp.dm1.compact.xy_box_lowerLeft - ( mp.dm1.compact.NboxAS - mp.dm1.compact.Nbox ) / 2. # Adjust the sub-array location of the influence function for the added zero padding if any(mp.dm_ind == 2): DM2surf = pad_crop(DM2surf, mp.dm1.compact.NdmPad) else: DM2surf = np.zeros((mp.dm1.compact.NdmPad, mp.dm1.compact.NdmPad)) if (mp.flagDM2stop): DM2stop = pad_crop(DM2stop, mp.dm1.compact.NdmPad) else: DM2stop = np.ones((mp.dm1.compact.NdmPad, mp.dm1.compact.NdmPad)) apodReimaged = pad_crop(apodReimaged, mp.dm1.compact.NdmPad) Edm1pad = pad_crop(Edm1out, mp.dm1.compact.NdmPad ) # Pad or crop for expected sub-array indexing Edm2WFEpad = pad_crop(Edm2WFE, mp.dm1.compact.NdmPad ) # Pad or crop for expected sub-array indexing # Propagate each actuator from DM1 through the optical system Gindex = 0 # initialize index counter for iact in mp.dm1.act_ele: # Compute only for influence functions that are not zeroed out if np.sum(np.abs(mp.dm1.compact.inf_datacube[:, :, iact])) > 1e-12: # x- and y- coordinate indices of the padded influence function in the full padded pupil x_box_AS_ind = np.arange( mp.dm1.compact.xy_box_lowerLeft_AS[0, iact], mp.dm1.compact.xy_box_lowerLeft_AS[0, iact] + NboxPad1AS, dtype=int) # x-indices in pupil arrays for the box y_box_AS_ind = np.arange( mp.dm1.compact.xy_box_lowerLeft_AS[1, iact], mp.dm1.compact.xy_box_lowerLeft_AS[1, iact] + NboxPad1AS, dtype=int) # y-indices in pupil arrays for the box indBoxAS = np.ix_(y_box_AS_ind, x_box_AS_ind) # x- and y- coordinates of the UN-padded influence function in the full padded pupil x_box = mp.dm1.compact.x_pupPad[ x_box_AS_ind] # full pupil x-coordinates of the box y_box = mp.dm1.compact.y_pupPad[ y_box_AS_ind] # full pupil y-coordinates of the box # Propagate from DM1 to DM2, and then back to P2 dEbox = (mirrorFac * 2 * np.pi * 1j / wvl) * pad_crop( (mp.dm1.VtoH.reshape(mp.dm1.Nact**2)[iact]) * np.squeeze( mp.dm1.compact.inf_datacube[:, :, iact]), NboxPad1AS ) # Pad influence function at DM1 for angular spectrum propagation. dEbox = fp.ptp( dEbox * Edm1pad[indBoxAS], mp.P2.compact.dx * NboxPad1AS, wvl, mp.d_dm1_dm2 ) # forward propagate to DM2 and apply DM2 E-field dEP2box = fp.ptp( dEbox * Edm2WFEpad[indBoxAS] * DM2stop[indBoxAS] * np.exp( mirrorFac * 2 * np.pi * 1j / wvl * DM2surf[indBoxAS]), mp.P2.compact.dx * NboxPad1AS, wvl, -1 * (mp.d_dm1_dm2 + mp.d_P2_dm1)) # back-propagate to DM1 # dEbox = fp.ptp_inf_func(dEbox*Edm1pad[np.ix_(y_box_AS_ind,x_box_AS_ind)], mp.P2.compact.dx*NboxPad1AS,wvl, mp.d_dm1_dm2, mp.dm1.dm_spacing, mp.propMethodPTP) # forward propagate to DM2 and apply DM2 E-field # dEP2box = fp.ptp_inf_func(dEbox.*Edm2WFEpad[np.ix_(y_box_AS_ind,x_box_AS_ind)]*DM2stop(y_box_AS_ind,x_box_AS_ind).*exp(mirrorFac*2*np.pi*1j/wvl*DM2surf(y_box_AS_ind,x_box_AS_ind)), mp.P2.compact.dx*NboxPad1AS,wvl,-1*(mp.d_dm1_dm2 + mp.d_P2_dm1), mp.dm1.dm_spacing, mp.propMethodPTP ) # back-propagate to DM1 # # To simulate going forward to the next pupil plane (with the apodizer) most efficiently, # First, back-propagate the apodizer (by rotating 180-degrees) to the previous pupil. # Second, negate the coordinates of the box used. dEP2boxEff = apodReimaged[ indBoxAS] * dEP2box # Apply 180deg-rotated apodizer mask. # dEP3box = np.rot90(dEP2box,k=2*mp.Nrelay2to3) # Forward propagate the cropped box by rotating 180 degrees mp.Nrelay2to3 times. # # Negate and reverse coordinate values to effectively rotate by 180 degrees. No change if 360 degree rotation. # Re-insert the window around the influence function back into the full beam array. EP2eff = np.zeros( (mp.dm1.compact.NdmPad, mp.dm1.compact.NdmPad), dtype=complex) EP2eff[indBoxAS] = dEP2boxEff # Forward propagate from P2 (effective) to P3 EP3 = fp.relay(EP2eff, NrelayFactor * mp.Nrelay2to3, mp.centering) # Pad pupil P3 for FFT EP3pad = pad_crop(EP3, Nfft1) # FFT from P3 to Fend.and apply vortex EF3 = fftshiftVortex * fft2(fftshift(EP3pad)) / Nfft1 # FFT from Vortex FPM to Lyot Plane EP4 = fftshift(fft2(EF3)) / Nfft1 EP4 = fp.relay( EP4, NrelayFactor * mp.Nrelay3to4 - 1, mp.centering) # Add more re-imaging relays if necessary if (Nfft1 > mp.P4.compact.Narr): EP4 = mp.P4.compact.croppedMask * pad_crop( EP4, mp.P4.compact.Narr ) # Crop EP4 and then apply Lyot stop else: EP4 = pad_crop( mp.P4.compact.croppedMask, Nfft1) * EP4 # Crop the Lyot stop and then apply it. pass # MFT to camera EP4 = fp.relay( EP4, NrelayFactor * mp.NrelayFend, mp.centering ) # Rotate the final image 180 degrees if necessary EFend = fp.mft_p2f(EP4, mp.fl, wvl, mp.P4.compact.dx, mp.Fend.dxi, mp.Fend.Nxi, mp.Fend.deta, mp.Fend.Neta, mp.centering) Gzdl[:, Gindex] = EFend[mp.Fend.corr.maskBool] / np.sqrt( mp.Fend.compact.I00[modvar.sbpIndex]) Gindex += 1 """ ---------- DM2 ---------- """ if idm == 2: Gzdl = np.zeros((mp.Fend.corr.Npix, mp.dm2.Nele), dtype=complex) # Array size for planes P3, F3, and P4 Nfft2 = int(2**falco.util.nextpow2( np.max( np.array([ mp.dm2.compact.NdmPad, minPadFacVortex * mp.dm2.compact.Nbox ])))) # Don't crop--but do pad if necessary. # Generate vortex FPM with fftshift already applied fftshiftVortex = fftshift( falco.mask.falco_gen_vortex_mask(charge, Nfft2)) # Two array sizes (at same resolution) of influence functions for MFT and angular spectrum NboxPad2AS = int(mp.dm2.compact.NboxAS) mp.dm2.compact.xy_box_lowerLeft_AS = mp.dm2.compact.xy_box_lowerLeft - ( NboxPad2AS - mp.dm2.compact.Nbox ) / 2 # Account for the padding of the influence function boxes apodReimaged = pad_crop(apodReimaged, mp.dm2.compact.NdmPad) DM2stopPad = pad_crop(DM2stop, mp.dm2.compact.NdmPad) Edm2WFEpad = pad_crop(Edm2WFE, mp.dm2.compact.NdmPad) # Propagate full field to DM2 before back-propagating in small boxes Edm2inc = pad_crop( fp.ptp(Edm1out, mp.compact.NdmPad * mp.P2.compact.dx, wvl, mp.d_dm1_dm2), mp.dm2.compact.NdmPad) # E-field incident upon DM2 Edm2inc = pad_crop(Edm2inc, mp.dm2.compact.NdmPad) Edm2 = DM2stopPad * Edm2WFEpad * Edm2inc * np.exp( mirrorFac * 2 * np.pi * 1j / wvl * pad_crop(DM2surf, mp.dm2.compact.NdmPad) ) # Initial E-field at DM2 including its own phase contribution # Propagate each actuator from DM2 through the rest of the optical system Gindex = 0 # initialize index counter for iact in mp.dm2.act_ele: # Only compute for acutators specified for use or for influence functions that are not zeroed out if np.sum(np.abs(mp.dm2.compact.inf_datacube[:, :, iact])) > 1e-12: # x- and y- coordinates of the padded influence function in the full padded pupil x_box_AS_ind = np.arange( mp.dm2.compact.xy_box_lowerLeft_AS[0, iact], mp.dm2.compact.xy_box_lowerLeft_AS[0, iact] + NboxPad2AS, dtype=int) # x-indices in pupil arrays for the box y_box_AS_ind = np.arange( mp.dm2.compact.xy_box_lowerLeft_AS[1, iact], mp.dm2.compact.xy_box_lowerLeft_AS[1, iact] + NboxPad2AS, dtype=int) # y-indices in pupil arrays for the box indBoxAS = np.ix_(y_box_AS_ind, x_box_AS_ind) # # x- and y- coordinates of the UN-padded influence function in the full padded pupil # x_box = mp.dm2.compact.x_pupPad[x_box_AS_ind] # full pupil x-coordinates of the box # y_box = mp.dm2.compact.y_pupPad[y_box_AS_ind] # full pupil y-coordinates of the box dEbox = (mp.dm2.VtoH.reshape(mp.dm2.Nact**2)[iact]) * ( mirrorFac * 2 * np.pi * 1j / wvl) * pad_crop( np.squeeze(mp.dm2.compact.inf_datacube[:, :, iact]), NboxPad2AS) # the padded influence function at DM2 dEP2box = fp.ptp( dEbox * Edm2[indBoxAS], mp.P2.compact.dx * NboxPad2AS, wvl, -1 * (mp.d_dm1_dm2 + mp.d_P2_dm1)) # back-propagate to pupil P2 # dEP2box = ptp_inf_func(dEbox.*Edm2(y_box_AS_ind,x_box_AS_ind), mp.P2.compact.dx*NboxPad2AS,wvl,-1*(mp.d_dm1_dm2 + mp.d_P2_dm1), mp.dm2.dm_spacing, mp.propMethodPTP); # back-propagate to pupil P2 # To simulate going forward to the next pupil plane (with the apodizer) most efficiently, # First, back-propagate the apodizer (by rotating 180-degrees) to the previous pupil. # Second, negate the coordinates of the box used. dEP2boxEff = apodReimaged[indBoxAS] * dEP2box # dEP3box = np.rot90(dEP2box,k=2*mp.Nrelay2to3) # Forward propagate the cropped box by rotating 180 degrees mp.Nrelay2to3 times. # # Negate and rotate coordinates to effectively rotate by 180 degrees. No change if 360 degree rotation. # if np.mod(mp.Nrelay2to3,2)==1: # x_box = -1*x_box[::-1] # y_box = -1*y_box[::-1] EP2eff = np.zeros( (mp.dm2.compact.NdmPad, mp.dm2.compact.NdmPad), dtype=complex) EP2eff[indBoxAS] = dEP2boxEff # Forward propagate from P2 (effective) to P3 EP3 = fp.relay(EP2eff, NrelayFactor * mp.Nrelay2to3, mp.centering) # Pad pupil P3 for FFT EP3pad = pad_crop(EP3, Nfft2) # FFT from P3 to Fend.and apply vortex EF3 = fftshiftVortex * fft2(fftshift(EP3pad)) / Nfft2 # FFT from Vortex FPM to Lyot Plane EP4 = fftshift(fft2(EF3)) / Nfft2 EP4 = fp.relay(EP4, NrelayFactor * mp.Nrelay3to4 - 1, mp.centering) if (Nfft2 > mp.P4.compact.Narr): EP4 = mp.P4.compact.croppedMask * pad_crop( EP4, mp.P4.compact.Narr) else: EP4 = pad_crop(mp.P4.compact.croppedMask, Nfft2) * EP4 # MFT to detector EP4 = fp.relay(EP4, NrelayFactor * mp.NrelayFend, mp.centering) EFend = fp.mft_p2f(EP4, mp.fl, wvl, mp.P4.compact.dx, mp.Fend.dxi, mp.Fend.Nxi, mp.Fend.deta, mp.Fend.Neta, mp.centering) Gzdl[:, Gindex] = EFend[mp.Fend.corr.maskBool] / \ np.sqrt(mp.Fend.compact.I00[modvar.sbpIndex]) Gindex += 1 return Gzdl
def noise_func_freq(self, int_fwm, sim_wind): self.noise = self.noise_func(int_fwm) noise_freq = fftshift(fft(self.noise), axes=-1) return noise_freq
def interpolate_subband(self, nfi, df, f0, full_output=False): ''' interpolates a sub-band between fMin and fMax by taking a windowed FFT at a bandwidth twice the requested bandwidth, extrapolating and interpolating the delay-transform transform, and FT-ing back. ''' change_nfi = False fMin = f0 - nfi / 2 * df if fMin < self.fAxis.min(): fMin = self.fAxis.min() change_nfi = True fMax = f0 + (nfi / 2 - 1) * df if fMax > self.fAxis.max(): fMax = self.fAxis.max() change_nfi = True if change_nfi: nfi = int(np.round(fMax / df - fMin / df)) f0 = fMin + nfi / 2 * df fAxis_interp = f0 + np.arange(-nfi / 2, nfi / 2) * df tAxis_interp = fft.fftshift(fft.fftfreq(nfi, df)) b = fMax - fMin select_max = np.min([self.fAxis.max(), f0 + b]) select_min = np.max([self.fAxis.min(), f0 - b]) selection = np.logical_and(self.fAxis >= select_min, self.fAxis <= select_max) nf = len(self.fAxis[selection]) if np.mod(nf, 2) == 1: nf += 1 maxind = np.where(selection)[0].max() if maxind < len(selection) - 1: selection[maxind + 1] = True else: minind = np.where(selection)[0].min() if minind > 0: selection[minind - 1] = True else: nf -= 2 selection[maxind] = False sub_band = self.gainFrequency[selection] sub_fAxis = self.fAxis[selection] window = signal.blackmanharris(nf) delay_band = fft.fftshift(fft.ifft(fft.fftshift(sub_band * window))) sub_tAxis = fft.fftshift( fft.fftfreq(len(sub_band), self.fAxis[1] - self.fAxis[0])) maxTime = sub_tAxis.max() minTimeExt = maxTime * 1. / 3. maxTimeExt = maxTime * 2. / 3. ext_select = np.logical_and(sub_tAxis <= maxTimeExt, sub_tAxis >= minTimeExt) ext_poly = np.polyfit(sub_tAxis[ext_select], np.log10(np.abs(delay_band[ext_select])), 1) interp_func_abs = interp.interp1d(sub_tAxis, np.log10(np.abs(delay_band))) interp_func_arg = interp.interp1d(sub_tAxis, np.angle(delay_band)) band_interp = np.zeros(nfi, dtype=complex) select_interp = np.logical_and(tAxis_interp >= 0, tAxis_interp < maxTimeExt) band_interp[select_interp] = 10**(interp_func_abs( tAxis_interp[select_interp])) * np.exp( 1j * interp_func_arg(tAxis_interp[select_interp])) select_ext = tAxis_interp >= maxTimeExt band_interp[select_ext] = 10**(tAxis_interp[select_ext] * ext_poly[0] + ext_poly[1]) #band_interp[select_ext]=0. window_interp_func = interp.interp1d( sub_fAxis, signal.blackmanharris(len(sub_band))) wFactor = 1. / ((fAxis_interp.max() - fAxis_interp.min()) / (sub_fAxis.max() - sub_fAxis.min())) if DEBUG: print(wFactor) band_interp_f = fft.fftshift(fft.fft( fft.fftshift(band_interp))) * wFactor window_corr = window_interp_func(fAxis_interp) #band_interp_f/=window_corr if full_output: return sub_tAxis, delay_band, sub_fAxis, sub_band, tAxis_interp, band_interp, fAxis_interp, band_interp_f else: return fAxis_interp, band_interp_f
def compute_pspec(self, beam_correct=False, apodize_kernel=None, alpha=0.3, beta=0.0, use_pyfftw=False, threads=1, **pyfftw_kwargs): ''' Compute the 2D power spectrum. Parameters ---------- beam_correct : bool, optional If a beam object was given, divide the 2D FFT by the beam response. apodize_kernel : None or 'splitcosinebell', 'hanning', 'tukey', 'cosinebell', 'tophat' If None, no apodization kernel is applied. Otherwise, the type of apodizing kernel is given. alpha : float, optional alpha shape parameter of the apodization kernel. See `~turbustat.apodizing_kernel` for more information. beta : float, optional beta shape parameter of the apodization kernel. See `~turbustat.apodizing_kernel` for more information. use_pyfftw : bool, optional Enable to use pyfftw, if it is installed. threads : int, optional Number of threads to use in FFT when using pyfftw. pyfftw_kwargs : Passed to `~turbustat.statistics.rfft_to_fft.rfft_to_fft`. See `here <http://hgomersall.github.io/pyFFTW/pyfftw/builders/builders.html>`__ for a list of accepted kwargs. ''' if apodize_kernel is not None: apod_kernel = self.apodizing_kernel(kernel_type=apodize_kernel, alpha=alpha, beta=beta) data = self.data * apod_kernel else: data = self.data if pyfftw_kwargs.get('threads') is not None: pyfftw_kwargs.pop('threads') fft = fftshift( rfft_to_fft(data, use_pyfftw=use_pyfftw, threads=threads, **pyfftw_kwargs)) if beam_correct: if not hasattr(self, '_beam'): raise AttributeError("Beam correction cannot be applied since" " no beam object was given.") beam_kern = self._beam.as_kernel(self._wcs.wcs.cdelt[0] * u.deg, y_size=self.data.shape[1], x_size=self.data.shape[2]) beam_fft = fftshift(rfft_to_fft(beam_kern.array)) self._beam_pow = np.abs(beam_fft**2) self._ps2D = np.power(fft, 2.).sum(axis=0) if beam_correct: self._ps2D /= self._beam_pow
def read_files(self, fileName, fileType, fMin=None, fMax=None, windowFunction=None, comment='', filterNegative=False, extrapolateBand=False, changeZ=False, z0=100, z1=100): if DEBUG: print fileType assert fileType in FILETYPES if (windowFunction is None): windowFunction = 'blackman-harris' self.windowFunction = windowFunction if (fileType == 'CST_TimeTrace' or fileType == 'Nicolas'): if fileType == 'CST_TimeTrace': [inputTrace, outputTrace, _], self.metaData = readCSTTimeTrace(fileName, comment=comment) elif fileType == 'Nicolas': [inputTrace, outputTrace] = readNicholasTimeTrace(fileName) if np.mod(len(inputTrace), 2) == 1: inputTrace = np.vstack([inputTrace[0, :], inputTrace]) inputTrace[0, 0] -= (inputTrace[2, 0] - inputTrace[1, 0]) outputTrace = np.vstack([outputTrace[0, :], outputTrace]) outputTrace[0, 0] -= (outputTrace[2, 0] - outputTrace[1, 0]) #plt.plot(inputTrace[:,0],inputTrace[:,1]) #plt.plot(outputTrace[:,0],outputTrace[:,1]) #plt.show() self.fAxis = fft.fftshift( fft.fftfreq( len(inputTrace) * 2, inputTrace[1, 0] - inputTrace[0, 0])) self.gainFrequency = fftRatio(outputTrace[:, 1], inputTrace[:, 1]) elif (fileType == 'CST_S11'): self.fAxis, self.gainFrequency, self.metaData = readCSTS11( fileName, comment=comment) elif (fileType == 'VNAHP_S11'): self.fAxis, self.gainFrequency, self.metaData = readVNAHP( fileName, comment=comment) elif (fileType == 'S11_CSV'): self.fAxis, self.gainFrequency, self.metaData = readCSV( fileName, comment=comment) elif (fileType == 'S11_S1P'): self.fAxis, self.gainFrequency, self.metaData = readS1P( fileName, comment=comment) elif (fileType == 'ANRITSU_CSV'): self.fAxis, self.gainFrequency, self.metaData = readAnritsu( fileName, comment=comment) if (fMin is None): fMin = self.fAxis.min() if (fMax is None): fMax = self.fAxis.max() if (extrapolateBand): if DEBUG: print(self.fAxis.min()) print(self.fAxis.max()) if (fMin < self.fAxis.min()): fitSelection = self.fAxis < self.fAxis.min() + .01 pReal = np.polyfit(self.fAxis[fitSelection], np.real(self.gainFrequency[fitSelection]), 1) pImag = np.polyfit(self.fAxis[fitSelection], np.imag(self.gainFrequency[fitSelection]), 1) fLow = np.arange(self.fAxis.min(), fMin, self.fAxis[0] - self.fAxis[1]) self.fAxis = np.hstack([fLow[::-1], self.fAxis]) self.gainFrequency = np.hstack([ pReal[0] * fLow[::-1] + pReal[1] + 1j * (pImag[0] * fLow[::-1] + pImag[1]), self.gainFrequency ]) #plt.plot(self.fAxis[fitSelection],np.real(self.gainFrequency[fitSelection]),ls='none',marker='o') #plt.plot(self.fAxis[fitSelection],self.fAxis[fitSelection]*pReal[0]+pReal[1],ls='--',color='r') #plt.plot(fLow[::-1],fLow[::-1]*pReal[0]+pReal[1],color='k') #plt.show() if (fMax > self.fAxis.max()): fitSelection = self.fAxis > self.fAxis.max() - .01 pReal = np.polyfit(self.fAxis[fitSelection], np.real(self.gainFrequency[fitSelection]), 1) pImag = np.polyfit(self.fAxis[fitSelection], np.imag(self.gainFrequency[fitSelection]), 1) fHigh = np.arange(self.fAxis.max(), fMax, self.fAxis[1] - self.fAxis[0]) self.fAxis = np.hstack([self.fAxis, fHigh]) self.gainFrequency = np.hstack([ self.gainFrequency, pReal[0] * fHigh + pReal[1] + 1j * (pImag[0] * fHigh + pImag[1]) ]) selection = np.logical_and(self.fAxis >= fMin, self.fAxis <= fMax) nf = len(np.where(selection)[0]) if np.mod(nf, 2) == 1: nf += 1 maxind = np.where(selection)[0].max() if maxind < len(selection) - 1: selection[maxind + 1] = True else: minind = np.where(selection)[0].min() if minind > 0: selection[minind - 1] = True else: nf -= 2 selection[maxind] = False self.fAxis = self.fAxis[selection] self.gainFrequency = self.gainFrequency[selection] if (windowFunction == 'blackman-harris'): wF = signal.blackmanharris(len(self.fAxis)) wF /= np.sqrt(np.mean(wF**2.)) else: wF = np.ones(len(self.fAxis)) self.tAxis = fft.fftshift( fft.fftfreq(len(self.fAxis), self.fAxis[1] - self.fAxis[0])) if (filterNegative): gainDelay = fft.fftshift(fft.ifft(fft.fftshift( self.gainFrequency))) gainDelay[self.tAxis < 0.] = 0. self.gainFrequency = fft.fftshift(fft.fft(fft.fftshift(gainDelay))) self.gainDelay = fft.fftshift( fft.ifft(fft.fftshift(self.gainFrequency * wF))) if changeZ: self.change_impedance(z0, z1)
def psd_to_psf(psd, pup, D, lbda, phase_static=None, samp=None, FoV=None, return_all=False): """Computation of a PSF from a residual phase PSD and a pupil shape. Programme pour prendre en compte la multi-analyse les geometries d'etoiles et la postion de la galaxie. FUNCTION psd_to_psf, dsp, pup, local_L, osamp PSD: 2D array with PSD values (in nm² per freq² at the PSF wavelength) pup: 2D array representing the pupill Samp: final PSF sampling (number of pixel in the diffraction). Min = 2 ! FoV : PSF FoV (in arcsec) lbda : PSF wavelength in m D = pupil diameter phase_static in nm """ dim = psd.shape[0] npup = pup.shape[0] sampnum = dim / npup # numerical sampling related to PSD vs pup dimension L = D * sampnum # Physical size of the PSD if dim < 2 * npup: logger.info("the PSD horizon must be at least two time larger than " "the pupil diameter") # from PSD to structure function convnm = 2 * np.pi / (lbda * 1e9) # nm to rad bg = ifft2(fftshift(psd * convnm**2)) * (psd.size / L**2) # creation of the structure function Dphi = 2 * (bg[0, 0].real - bg.real) Dphi = fftshift(Dphi) # Extraction of the pupil part of the structure function sampin = samp if samp is not None else sampnum if samp < 2: logger.info('PSF should be at least nyquist sampled') # even dimension of the num psd dimnum = int(np.fix(dim * (sampin / sampnum) / 2)) * 2 sampout = dimnum / npup # real sampling if samp <= sampnum: ns = sampout * npup / 2 sl = slice(int(dim / 2 - ns), int(dim / 2 + ns)) Dphi2 = Dphi[sl, sl] else: Dphi2 = np.zeros(dimnum, dimnum) + (Dphi[0, 0] + Dphi[dim - 1, dim - 1] + Dphi[0, dim - 1] + Dphi[dim - 1, 0]) / 4 sl = slice(int(dimnum / 2 - dim / 2), int(dimnum / 2 + dim / 2)) Dphi2[sl, sl] = Dphi logger.warning('Sampling > Dim DSP / Dim pup => extrapolation !!! ' 'We recommmend to increase the PSD size') logger.debug( 'input sampling: %.2f, output sampling: %.2f, max num sampling: %.2f', sampin, sampout, sampnum) # increasing the FoV PSF means oversampling the pupil FoVnum = (lbda / (sampnum * D)) * dim / (4.85 * 1.e-6) if FoV is None: FoV = FoVnum overFoV = FoV / FoVnum if not np.allclose(FoV, FoVnum): dimover = int(np.fix(dimnum * overFoV / 2)) * 2 xxover = np.arange(dimover) / dimover * dimnum Dphi2 = np.maximum(interpolate(Dphi2, xxover, method='cubic'), 0) npupover = int(np.fix(npup * overFoV / 2)) * 2 xxpupover = np.arange(npupover) / npupover * npup pupover = np.maximum(interpolate(pup, xxpupover, method='cubic'), 0) else: dimover = dimnum npupover = npup pupover = pup if phase_static is not None: npups = phase_static.shape[0] if npups != npup: logger.info( "pup and static phase must have the same number of pixels") if not np.allclose(FoV, FoVnum): phase_static = np.maximum( interpolate(phase_static, xxpupover, method='cubic'), 0) logger.debug('input FoV: %.2f, output FoV: %.2f, Num FoV: %.2f', FoV, FoVnum * dimover / dimnum, FoVnum) if FoV > 2 * FoVnum: logger.warning(': Potential alisiang issue .. I recommend to create ' 'initial PSD and pupil with a larger numbert of pixel') # creation of a diff limited OTF (pupil autocorrelation) tab = np.zeros((dimover, dimover), dtype=complex) if phase_static is not None: pupover = pupover * np.exp(1j * phase_static * 2 * np.pi / lbda) tab[:npupover, :npupover] = pupover dlFTO = fft2(np.abs(ifft2(tab))**2) dlFTO = fftshift(np.abs(dlFTO) / pup.sum()) # creation of A OTF (aoFTO = np.exp(-Dphi2 / 2)) Dphi2 *= -0.5 np.exp(Dphi2, out=Dphi2) # Computation of final OTF sysFTO = fftshift(Dphi2 * dlFTO) # Computation of final PSF sysPSF = np.real(fftshift(ifft2(sysFTO))) sysPSF /= sysPSF.sum() # normalisation to 1 if return_all: FoV = FoVnum * dimover / dim return sysPSF, sampout, FoV else: return sysPSF
import cv2 import numpy as np import matplotlib from matplotlib import pyplot as plt from numpy.fft import fftshift, ifftshift, fftn, ifftn matplotlib.rcParams['font.size'] = 8.0 np.random.seed(19680801) img = cv2.imread('p2.jpg', 0) dim = range(img.ndim) k = fftshift(fftn(ifftshift(img, axes=dim), s=None, axes=dim), axes=dim) k /= np.sqrt(np.prod(np.take(img.shape, dim))) k = np.real(k) magnitude_spectrum = 20 * np.log(np.abs(k) + 1) images = [] fig, axs = plt.subplots(1, 2) for j in range(2): axs[j].set_yticklabels([]) axs[j].set_xticklabels([]) data = [img, magnitude_spectrum] images.append(axs[0].imshow(data[0], cmap='gray')) axs[0].set_title('Input Image') images.append(axs[1].imshow(data[1], cmap='gray'))
def _calcpr_er(F, C_s, plan, D_s=None, rho_0=None, r_factor=None, *args, **kwargs): """_calcpr_er(F, C_s, plan, D_s=None, rho_0=None, r_factor=None, *args, **kwargs) -> None Error reduction algorithm Detail: J. R. Fienup, Appl. Opt. 21, 2758 (1982) Parameters ---------- F : numpy.2darray target modulus C_s : numpy.2darray support in real space plan : Plan / list of Plans object (Plan) plan of PR D_s : numpy.2darray (default : None) mask in reciprocal space rho_0 : numpy.2darray (default : None) initial guess of the density map r_factor : list (default : None) history of R factor args : options kwargs : options """ # Initialize if rho_0 is None: rho_0 = _init_phase(plan.shape) rho_0 *= np.max(np.abs(ifft2(F))) elif rho_0 == "phase": rho_0 = _init_phase(plan.shape) rho_0 *= np.max(np.abs(ifft2(F))) elif rho_0 == "amplitude": rho_0 = _init_phase(plan.shape) rho_0 = ifft2(F * rho_0) elif rho_0 == "auto": rho_0 = ifft2(F**2) elif rho_0 == "auto, amplitude": rho_0 = _init_phase(plan.shape) rho_0 = ifft2(F**2 * rho_0) elif rho_0 == "auto, phase": rho_0 = _init_phase(plan.shape) rho_0 = rho_0 * ifft2(F**2) if r_factor is None: r_factor = [] _F = np.abs(fftshift(F)) _D_s = D_s if D_s is not None: _D_s = fftshift(D_s) rho_i = 1.*rho_0 rho_f = np.zeros(F.shape, dtype=np.complex64) # Define FFT functions func = FFT_FUNC.get(plan.fft_type) ifunc = IFFT_FUNC.get(plan.fft_type) # Check use of mask and validity of the parameters updmask_use = plan.kwargs.get('updmask_use', False) updmask_N = plan.kwargs.get('updmask_N') if updmask_use is None or type(updmask_use) != bool: updmask_use = False elif updmask_N is None or type(updmask_N) != int or updmask_N <= 0: updmask_use = False ratio = plan.kwargs.get('updmask_ratio') if ratio is None or ratio <= 0: ratio = -1 _init_C_s = kwargs.get("init_C_s", None) width = 1.5 if C_s is None: C_s = _updmask(np.abs(rho_i), C_s, plan.rho_filter, width, ratio) if _init_C_s is not None and _init_C_s == True: C_s = _updmask(np.abs(rho_i), C_s, plan.rho_filter, width, ratio) # The known error function for Liu's process. err = plan.kwargs.get('err') if err is not None and type(err) not in [np.ndarray, list]: raise TypeError('"err" has an invalid type.') intensity = plan.kwargs.get('intensity') if intensity is not None and type(intensity) != bool: raise TypeError('"intensity" must be boolean.') _num = 0 if plan.kwargs.get('num') is None else plan.kwargs.get('num') # Main loop for ii in range(plan.N): rho_f = func(rho_i, plan.x_gpu, plan.xf_gpu, plan.cufft_plan) # rho(n) -> G(n) r_factor.append(_calc_r_factor(rho_f, _F)) rho_f = _projection_I(rho_f, _F, plan.f_const, _D_s, err, intensity, **kwargs) # G(n) -> G'(n) rho_i = _projection_er(ifunc(rho_f, plan.x_gpu, plan.xf_gpu, plan.cufft_plan), C_s, plan.rho_const) # G'(n) -> rho(n+1) if updmask_use: if np.mod(ii+1, updmask_N) == 0 and ratio > 0: # Update the mask width = width-0.03 if width >= 1.5 else 1.5 C_s = _updmask(np.abs(rho_i), C_s, plan.rho_filter, width, ratio) if plan.kwargs.get('save') is True: _savefig(np.abs(rho_i), C_s, rho_f, r_factor, plan.pr_mode, ii+_num) plan.set(rho_i, r_factor, C_s)