def psf_calc(self, psf, data_size): """Precalculate the OTF etc...""" g = resizePSF(psf, data_size) #keep track of our data shape self.height = data_size[0] self.width = data_size[1] self.depth = data_size[2] self.shape = data_size self.FTshape = [self.shape[0], self.shape[1], self.shape[2] / 2 + 1] self.g = g.astype('f4') self.g2 = 1.0 * self.g[::-1, ::-1, ::-1] #allocate memory self.H = fftw3f.create_aligned_array(self.FTshape, 'complex64') self.Ht = fftw3f.create_aligned_array(self.FTshape, 'complex64') #self.f = np.zeros(self.shape, 'f4') #self.res = np.zeros(self.shape, 'f4') #self.S = np.zeros((np.size(self.f), 3), 'f4') #self._F = fftw3f.create_aligned_array(self.FTshape, 'complex64') #self._r = fftw3f.create_aligned_array(self.shape, 'f4') #S0 = self.S[:,0] #create plans & calculate OTF and conjugate transformed OTF fftw3f.Plan(self.g, self.H, 'forward')() fftw3f.Plan(self.g2, self.Ht, 'forward')() self.Ht /= g.size self.H /= g.size
def prep(self): #allocate memory self._F = fftw3f.create_aligned_array(self.FTshape, 'complex64') self._r = fftw3f.create_aligned_array(self.shape[:-1], 'f4') #calculate plans for other ffts self._plan_r_F = fftw3f.Plan(self._r, self._F, 'forward') self._plan_F_r = fftw3f.Plan(self._F, self._r, 'backward')
def __init__(self, u, v, k=None, lamb=488, n=1.51): """A FourierPropagator object allows us evaluate the electric field at a given defocus by propagating a complex pupil distribution a given distance from the nominal focus by adding the relevant phase term to the pupil and then taking the Fourier amplitude. Parameters ========== u, v : 2d arrays of float the co-ordinates in spatial frequencies within the pupil plane lamb : float the wavelength in nm n : float the refractive index of the media Notes ===== u, v must be the same size as the eventual pupil distribution to be used. On creation, the FourierPropagator pre-calculates the phase factor to add for each u, v, co-ordinate and also pre-computes FFTW3 plans for the necessary Fourier transforms. """ if not k is None: raise DeprecationWarning('k is no longer used') #R = np.sqrt(u**2 + v**2) self.propFac = ((2 * np.pi * n / lamb) * np.sqrt(1 - np.minimum(u**2 + v**2, 1))).astype('f') #self.pfm =(self.propFac > 0).astype('f') self.pfm = (np.sqrt(u**2 + v**2) < 1).astype('f') self._F = fftw3f.create_aligned_array(u.shape, 'complex64') self._f = fftw3f.create_aligned_array(u.shape, 'complex64') #print('Creating plans for FFTs - this might take a while') #calculate plans for other ffts self._plan_f_F = fftw3f.Plan(self._f, self._F, 'forward', flags=FFTWFLAGS, nthreads=NTHREADS) self._plan_F_f = fftw3f.Plan(self._F, self._f, 'backward', flags=FFTWFLAGS, nthreads=NTHREADS) #self._plan_F_f = fftw3f.Plan(self._F, self._f, 'backward', flags = FFTWFLAGS, nthreads=NTHREADS) fftwWisdom.save_wisdom()
def prep(self): #allocate memory self._F = fftw3f.create_aligned_array(self.FTshape, 'complex64') self._r = fftw3f.create_aligned_array(self.shape, 'f4') print('Creating plans for FFTs - this might take a while') #calculate plans for other ffts self._plan_r_F = fftw3f.Plan(self._r, self._F, 'forward', flags = FFTWFLAGS, nthreads=NTHREADS) self._plan_F_r = fftw3f.Plan(self._F, self._r, 'backward', flags = FFTWFLAGS, nthreads=NTHREADS) fftwWisdom.save_wisdom() print('Done planning')
def psf_calc(self, psf, data_size): """Precalculate the OTF etc...""" g = resizePSF(psf, data_size) #keep track of our data shape self.height = data_size[0] self.width = data_size[1] self.depth = data_size[2] self.shape = data_size FTshape = [self.shape[0], self.shape[1], self.shape[2] / 2 + 1] #allocate memory self.H = fftw3f.create_aligned_array(FTshape, 'complex64') self.Ht = fftw3f.create_aligned_array(FTshape, 'complex64') self._F = fftw3f.create_aligned_array(FTshape, 'complex64') self._r = fftw3f.create_aligned_array(self.shape, 'f4') self.g = g.astype('f4') self.g2 = 1.0 * self.g[::-1, ::-1, ::-1] #S0 = self.S[:,0] #create plans & calculate OTF and conjugate transformed OTF fftw3f.Plan(self.g, self.H, 'forward')() fftw3f.Plan(self.g2, self.Ht, 'forward')() self.Ht /= g.size self.H /= g.size self.H2 = self.Ht * self.H #calculate plans for other ffts self._plan_r_F = fftw3f.Plan(self._r, self._F, 'forward', flags=FFTWFLAGS, nthreads=NTHREADS) self._plan_F_r = fftw3f.Plan(self._F, self._r, 'backward', flags=FFTWFLAGS, nthreads=NTHREADS) fftwWisdom.save_wisdom() self.lamb = None
def psf_calc(self, psf, data_size): """Precalculate the OTF etc...""" g = resizePSF(psf, data_size) #normalise g /= g[:, :, g.shape[2] / 2].sum() #keep track of our data shape self.height = data_size[0] self.width = data_size[1] self.depth = data_size[2] self.shape = data_size self.FTshape = list( self.shape[:-1] ) #[self.shape[0], self.shape[1], self.shape[2]/2 + 1] self.FTshape[-1] = self.FTshape[-1] / 2 + 1 self.g = g.astype('f4') self.g2 = 1.0 * self.g[::-1, ::-1, :] self.H = [] self.Ht = [] for i in range(self.shape[-1]): #allocate memory self.H.append( fftw3f.create_aligned_array(self.FTshape, 'complex64')) self.Ht.append( fftw3f.create_aligned_array(self.FTshape, 'complex64')) #create plans & calculate OTF and conjugate transformed OTF fftw3f.Plan(1.0 * self.g[:, :, i], self.H[i], 'forward')() fftw3f.Plan(1.0 * self.g2[:, :, i], self.Ht[i], 'forward')() self.Ht[i] /= g[:, :, i].size self.H[i] /= g[:, :, i].size
def resizePSF(psf, data_size): if not psf.shape == data_size: #Expand PSF to data size by fourier domain interpolation print('Resizing PSF to match data size') g_ = fftw3f.create_aligned_array(data_size, 'complex64') H_ = fftw3f.create_aligned_array(data_size, 'complex64') sx, sy, sz = numpy.array(data_size).astype('f') / psf.shape #print sx, sy, sz OT = fftshift(fftn( fftshift(psf))) #don't bother with FFTW here as raw PSF is small if data_size[2] > 1: pr = ndimage.zoom(OT.real, [sx, sy, sz], order=1) pi = ndimage.zoom(OT.imag, [sx, sy, sz], order=1) else: #special case for 2D pr = ndimage.zoom(OT.real.squeeze(), [sx, sy], order=1).reshape(data_size) pi = ndimage.zoom(OT.imag.squeeze(), [sx, sy], order=1).reshape(data_size) H_[:] = ifftshift(pr + 1j * pi) fftw3f.Plan(H_, g_, 'backward')() #View3D(psf) #View3D(H_) #View3D(OT) #View3D(pr) g = ifftshift(g_.real).clip( min=0) # negative values may cause instability print('PSF resizing complete') else: g = psf #View3D(psf) #View3D(fftshift(numpy.abs(H_))) #View3D(fftshift(numpy.angle(H_))) #View3D(g) return g / g.sum()