def shift_data_subpixel(inputs): ''' rigid shift of X by ymax and xmax ''' ''' allows subpixel shifts ''' ''' ** not being used ** ''' X, ymax, xmax, pad_fft = inputs ymax = ymax.flatten() xmax = xmax.flatten() if X.ndim<3: X = X[np.newaxis,:,:] nimg, Ly0, Lx0 = X.shape if pad_fft: X = fft2(X.astype('float32'), (next_fast_len(Ly0), next_fast_len(Lx0))) else: X = fft2(X.astype('float32')) nimg, Ly, Lx = X.shape Ny = fft.ifftshift(np.arange(-np.fix(Ly/2), np.ceil(Ly/2))) Nx = fft.ifftshift(np.arange(-np.fix(Lx/2), np.ceil(Lx/2))) [Nx,Ny] = np.meshgrid(Nx,Ny) Nx = Nx.astype('float32') / Lx Ny = Ny.astype('float32') / Ly dph = Nx * np.reshape(xmax, (-1,1,1)) + Ny * np.reshape(ymax, (-1,1,1)) Y = np.real(ifft2(X * np.exp((2j * np.pi) * dph))) # crop back to original size if Ly0<Ly or Lx0<Lx: Lyhalf = int(np.floor(Ly/2)) Lxhalf = int(np.floor(Lx/2)) Y = Y[np.ix_(np.arange(0,nimg,1,int), np.arange(-np.fix(Ly0/2), np.ceil(Ly0/2),1,int) + Lyhalf, np.arange(-np.fix(Lx0/2), np.ceil(Lx0/2),1,int) + Lxhalf)] return Y
def __init__(self, backend, xv, yv, tsgf_or_TH): self.backend = backend self.xv = xv self.yv = yv self.backend.check_freespace(self.xv, self.yv) self.backend.initialize_freespace() self.h = self.backend.h self.n = self.xv.size self.spread_width = self.backend.spread_width # get the T operator self.expand_n = self.n + 2 * self.spread_width self.n_extract = self.expand_n // 2 + self.spread_width self.big_n = 2 * self.expand_n self.Big_n = 4 * self.expand_n if type(tsgf_or_TH) == np.ndarray: self.TH = tsgf_or_TH else: self.truncated_spectral_gf = lambda k, L: tsgf_or_TH( k, L, **self.backend.kernel_kwargs) self.drange = self.xv[-1] - self.xv[0] + self.h self.kv = np.fft.fftfreq(self.Big_n, self.h / (2 * np.pi)) self.kx, self.ky = np.meshgrid(self.kv, self.kv, indexing='ij') self.tsgf = self.truncated_spectral_gf(np.hypot(self.kx, self.ky), 2.5 * self.drange) w1 = np.zeros([self.Big_n, self.Big_n], dtype=float) w1[self.big_n, self.big_n] = 1.0 w2 = ifft2(fft2(w1) * self.tsgf) self.T = w2[self.expand_n:-self.expand_n, self.expand_n:-self.expand_n] self.TH = fft2(self.T) # storage for padded array self.big_op = np.zeros([self.big_n, self.big_n], dtype=float) self.big_u = np.zeros([self.big_n, self.big_n], dtype=float) # extract local ewald function from backend self.local_func = self.backend.ewald_local_freespace
def prepare_masks(refImg0, ops): refImg = refImg0.copy() if ops['1Preg']: maskSlope = ops['spatial_taper'] # slope of taper mask at the edges else: maskSlope = 3 * ops['smooth_sigma'] # slope of taper mask at the edges Ly, Lx = refImg.shape maskMul = spatial_taper(maskSlope, Ly, Lx) if ops['1Preg']: refImg = one_photon_preprocess(refImg[np.newaxis, :, :], ops).squeeze() maskOffset = refImg.mean() * (1. - maskMul) # reference image in fourier domain if ops['pad_fft']: cfRefImg = np.conj( fft2(refImg, (next_fast_len(ops['Ly']), next_fast_len(ops['Lx'])))) else: cfRefImg = np.conj(fft2(refImg)) absRef = np.absolute(cfRefImg) cfRefImg = cfRefImg / (eps0 + absRef) # gaussian filter in space fhg = gaussian_fft(ops['smooth_sigma'], cfRefImg.shape[0], cfRefImg.shape[1]) cfRefImg *= fhg maskMul = maskMul.astype('float32') maskOffset = maskOffset.astype('float32') cfRefImg = cfRefImg.astype('complex64') cfRefImg = np.reshape(cfRefImg, (1, cfRefImg.shape[0], cfRefImg.shape[1])) return maskMul, maskOffset, cfRefImg
def phasecorr_cpu(data, refAndMasks, lcorr): maskMul = refAndMasks[0] maskOffset = refAndMasks[1] cfRefImg = refAndMasks[2].squeeze() nimg = data.shape[0] ly, lx = cfRefImg.shape[-2:] lyhalf = int(np.floor(ly / 2)) lxhalf = int(np.floor(lx / 2)) # shifts and corrmax ymax = np.zeros((nimg, ), np.int32) xmax = np.zeros((nimg, ), np.int32) cmax = np.zeros((nimg, ), np.float32) X = addmultiplytype(data, maskMul, maskOffset) for t in range(X.shape[0]): fft2(X[t], overwrite_x=True) X = apply_dotnorm(X, cfRefImg) for t in np.arange(nimg): ifft2(X[t], overwrite_x=True) x00, x01, x10, x11 = my_clip(X, lcorr) cc = np.real(np.block([[x11, x10], [x01, x00]])) for t in np.arange(nimg): ymax[t], xmax[t] = np.unravel_index(np.argmax(cc[t], axis=None), (2 * lcorr + 1, 2 * lcorr + 1)) cmax[t] = cc[t, ymax[t], xmax[t]] ymax, xmax = ymax - lcorr, xmax - lcorr return ymax, xmax, cmax
def phasecorr_reference(refImg0, ops): """ computes masks and fft'ed reference image for phasecorr Parameters ---------- refImg0 : int16 reference image ops : dictionary requires 'smooth_sigma' (if ```ops['1Preg']```, need 'spatial_taper', 'spatial_hp', 'pre_smooth') Returns ------- maskMul : float32 mask that is multiplied to spatially taper frames maskOffset : float32 shifts in x from cfRefImg to data for each frame cfRefImg : complex64 reference image fft'ed and complex conjugate and multiplied by gaussian filter in the fft domain with standard deviation 'smooth_sigma' """ refImg = refImg0.copy() if '1Preg' in ops and ops['1Preg']: maskSlope = ops['spatial_taper'] # slope of taper mask at the edges else: maskSlope = 3 * ops['smooth_sigma'] # slope of taper mask at the edges Ly, Lx = refImg.shape maskMul = utils.spatial_taper(maskSlope, Ly, Lx) if ops['1Preg']: refImg = utils.one_photon_preprocess(refImg[np.newaxis, :, :], ops).squeeze() maskOffset = refImg.mean() * (1. - maskMul) # reference image in fourier domain if 'pad_fft' in ops and ops['pad_fft']: cfRefImg = np.conj(fft2(refImg, (next_fast_len(Ly), next_fast_len(Lx)))) else: cfRefImg = np.conj(fft2(refImg)) absRef = np.absolute(cfRefImg) cfRefImg = cfRefImg / (1e-5 + absRef) # gaussian filter in space fhg = utils.gaussian_fft(ops['smooth_sigma'], cfRefImg.shape[0], cfRefImg.shape[1]) cfRefImg *= fhg maskMul = maskMul.astype('float32') maskOffset = maskOffset.astype('float32') cfRefImg = cfRefImg.astype('complex64') cfRefImg = np.reshape(cfRefImg, (1, cfRefImg.shape[0], cfRefImg.shape[1])) return maskMul, maskOffset, cfRefImg
def phasecorr_cpu(data, refAndMasks, lcorr, smooth_sigma_time): """ compute phase correlation between data and reference image Parameters ---------- data : int16 array that's frames x Ly x Lx refAndMasks : list maskMul, maskOffset and cfRefImg (from prepare_refAndMasks) lcorr : int maximum shift in pixels smooth_sigma_time : float how many frames to smooth in time Returns ------- ymax : int shifts in y from cfRefImg to data for each frame xmax : int shifts in x from cfRefImg to data for each frame cmax : float maximum of phase correlation for each frame """ maskMul = refAndMasks[0] maskOffset = refAndMasks[1] cfRefImg = refAndMasks[2].squeeze() nimg = data.shape[0] ly, lx = cfRefImg.shape[-2:] lyhalf = int(np.floor(ly / 2)) lxhalf = int(np.floor(lx / 2)) # shifts and corrmax ymax = np.zeros((nimg, ), np.int32) xmax = np.zeros((nimg, ), np.int32) cmax = np.zeros((nimg, ), np.float32) X = addmultiplytype(data, maskMul, maskOffset) for t in range(X.shape[0]): fft2(X[t], overwrite_x=True) X = utils.apply_dotnorm(X, cfRefImg) for t in np.arange(nimg): ifft2(X[t], overwrite_x=True) x00, x01, x10, x11 = clip(X, lcorr) cc = np.real(np.block([[x11, x10], [x01, x00]])) if smooth_sigma_time > 0: cc = gaussian_filter1d(cc, smooth_sigma_time, axis=0) for t in np.arange(nimg): ymax[t], xmax[t] = np.unravel_index(np.argmax(cc[t], axis=None), (2 * lcorr + 1, 2 * lcorr + 1)) cmax[t] = cc[t, ymax[t], xmax[t]] ymax, xmax = ymax - lcorr, xmax - lcorr return ymax, xmax, cmax
def _delta(self, phi): phi_x = mkl_fft.ifft2(phi) self.phi_sq = mkl_fft.fft2(phi_x**2) self.phi_cube = mkl_fft.fft2(phi_x**3) np.putmask(self.phi_cube, self.dealiasing_triple, 0) np.putmask(self.phi_sq, self.dealiasing_double, 0) mu = self.a*(-phi+self.phi_cube) + self.k*self.ksq*phi birth_death = - self.u*(self.phi_sq+(self.phi_shift-self.phi_target)*phi) birth_death[0, 0] += self.u*self.phi_shift*self.phi_target*self.size**2 dphidt = -self.M1*self.ksq*mu + birth_death return dphidt
def evolve_vode(self, verbose=True): self._make_k_grid() self._make_filters() self.phi = np.zeros((self.n_batches, self.size, self.size)) small_batch = self.batch_size while small_batch > 10000: small_batch /= 10 # decrease the amount of time integration at each step r = ode(self._delta).set_integrator('vode', atol=1e-8, nsteps=small_batch) r.set_initial_value(self.phi_initial, 0) n = 0 phi = self._make_real(fft2(self.phi_initial)) for i in range(int((self.T / self.dt) / small_batch)): if r.successful(): if i % int(self.batch_size / small_batch) == 0: phi_complex = self._make_complex(phi) self.phi[n] = np.real(ifft2(phi_complex)) if verbose: print('iteration: {} mean: {}'.format( n, self._mean_bd(self.phi[n]))) n += 1 phi = r.integrate(r.t + self.dt * small_batch)
def mfft2(a, overwrite_x = False): """Computes matrix fft2 on a matrix of shape (..., n,n,4,4). This is identical to np.fft2(a, axes = (-4,-3)) Parameters ---------- a : array_like Input array (must be complex). overwrite_x : bool Specifies whether original array can be destroyed (for inplace transform) Returns ------- out : complex ndarray Result of the transformation along the (-4,-3) axes. """ a = np.asarray(a, dtype = CDTYPE) libname = DTMMConfig["fftlib"] if libname == "mkl_fft": return mkl_fft.fft2(a, axes = (-4,-3), overwrite_x = overwrite_x) elif libname == "scipy": return spfft.fft2(a, axes = (-4,-3), overwrite_x = overwrite_x) elif libname == "numpy": return npfft.fft2(a, axes = (-4,-3)) elif libname == "pyfftw": return pyfftw.interfaces.scipy_fft.fft2(a, axes = (-4,-3), overwrite_x = overwrite_x) else: #default implementation is numpy return npfft.fft2(a, axes = (-4,-3))
def fft2(data, s=None): if s == None: s = (data.shape[-2], data.shape[-1]) if HAS_MKL: data = mkl_fft.fft2(data, shape=s, axes=(-2, -1)) else: data = fft.fft2(data, s, axes=(-2, -1)) return data
def evolve(self, verbose=True, cython=True): self.phi_initial = mkl_fft.fft2(self.phi_initial) if cython: nitr = int(self.T/self.dt) self.phi = ps.evolve_sto_ps(self.phi_initial, self.a, self.k, self.u, self.phi_shift, self.phi_target, self.epsilon, self.dt, nitr, self.n_batches, self.X) else: self.naive_evolve(verbose)
def _fft2(a, overwrite_x = False): libname = CDDMConfig["fftlib"] if libname == "mkl_fft": return mkl_fft.fft2(a, overwrite_x = overwrite_x) elif libname == "scipy": return spfft.fft2(a, overwrite_x = overwrite_x) elif libname == "numpy": return np.fft.fft2(a) #force real in case input is complex else:#default implementation is numpy fft2 return np.fft.fft2(a)
def qsCat(ti,dst,path,template,n,k): dist=numpy.zeros(shape=template.shape); dist[math.floor(dist.shape[0]/2),math.floor(dist.shape[1]/2)]=1; dist=ndimage.morphology.distance_transform_edt(1-dist); unValue=numpy.unique(ti.flat); fftim = numpy.stack([fft.fft2(-1*(ti==x)) for x in unValue],axis=2); adjustedTi=numpy.ones(ti.shape)*numpy.nan; for x in range(unValue.size): adjustedTi[ti==unValue[x]]=x; return unValue[runsim((fftim ,ti.shape, dist, n, k), adjustedTi, dst, path, template, qsSampleCat).astype(int)];
def gaussian_fft(sig, Ly, Lx): ''' gaussian filter in the fft domain with std sig and size Ly,Lx ''' xx, yy = meshgrid_mean_centered(x=Lx, y=Ly) hgx = np.exp(-np.square(xx / sig) / 2) hgy = np.exp(-np.square(yy / sig) / 2) hgg = hgy * hgx hgg /= hgg.sum() fhg = np.real(fft2(fft.ifftshift(hgg))) # smoothing filter in Fourier domain return fhg
def process(data): ''' computes movement using phase correlation ''' nt, Ly, Lx = data.shape ly = int(np.floor(Ly * 0.4)) lx = int(np.floor(Lx * 0.4)) lcorr = min(ly, lx) # taper edges maskMul = spatial_taper((Ly * Lx)**0.5 * 0.01, Ly, Lx).astype(np.complex64) # spatial filter fhg = gaussian_fft(2, Ly, Lx) # shifts and corrmax ymax = np.zeros((nt - 1, ), np.int32) xmax = np.zeros((nt - 1, ), np.int32) #cmax = np.zeros((nimg,), np.float32) #maskOffset = X[1:].mean() * (1. - maskMul) # taper and fft data X = data.astype(np.float32) #data -= data.mean(axis=-1, dtype=np.uint8).mean(axis=-1, dtype=np.uint8)[:,np.newaxis,np.newaxis] X -= X.mean(axis=-1).mean(axis=-1)[:, np.newaxis, np.newaxis] X = multiplytype(X, maskMul) #X -= X.mean(axis=-1).mean(axis=-1)[:,np.newaxis,np.newaxis] for t in range(nt): fft2(X[t], overwrite_x=True) # phase correlation with previous frame X = phase_norm(X, fhg.astype(np.complex64)) Xout = X[1:] * np.conj(X[:-1]) for t in range(nt - 1): ifft2(Xout[t], overwrite_x=True) x00, x01, x10, x11 = my_clip(Xout, lcorr) cc = np.real(np.block([[x11, x10], [x01, x00]])) #cc = spatial_smooth(cc, 2) for t in range(nt - 1): ymax[t], xmax[t] = np.unravel_index(np.argmax(cc[t], axis=None), (2 * lcorr + 1, 2 * lcorr + 1)) #cmax[t] = cc[t, ymax[t], xmax[t]] ymax, xmax = ymax - lcorr, xmax - lcorr return ymax, xmax
def _rfft2(a, overwrite_x = False): libname = CDDMConfig["fftlib"] cutoff = a.shape[-1]//2 + 1 if libname == "mkl_fft": return mkl_fft.fft2(a, overwrite_x = overwrite_x)[...,0:cutoff] elif libname == "scipy": return spfft.fft2(a, overwrite_x = overwrite_x)[...,0:cutoff] elif libname == "numpy": return np.fft.rfft2(a.real) #force real in case input is complex else:#default implementation is numpy fft2 return np.fft.fft2(a)[...,0:cutoff]
def __call__(self, src, ch): self.big_op[:] = 0.0 self.big_u[:] = 0.0 self.local_func(src, ch, self.xv, self.yv, self.big_op, self.big_u, self.n_extract) big_adj = np.fft.fftshift(ifft2(fft2(self.big_op) * self.TH).real) small_u = self.big_u[self.n_extract:-self.n_extract, self.n_extract:-self.n_extract].copy() small_adj = big_adj[self.n_extract:-self.n_extract, self.n_extract:-self.n_extract].copy() np.subtract(small_u, small_adj, small_u) return small_u
def fft2c(img): shp = img.shape nimg = int(np.prod(shp[0:-2])) scale = 1 / np.sqrt(np.prod(shp[-2:])) img = np.reshape(img, (nimg, shp[-2], shp[-1])) tmp = np.empty_like(img, dtype=np.complex64) for i in range(nimg): tmp[i] = scale * np.fft.fftshift(mkl_fft.fft2(np.fft.ifftshift( img[i]))) kspace = np.reshape(tmp, shp) return kspace
def _initialize_fft(self): """ Define the two-dimensional FFT methods. """ if self.use_mkl: import mkl mkl.set_num_threads(self.nthreads) import mkl_fft self.fft = (lambda x: mkl_fft.fft2(x)) self.ifft = (lambda x: mkl_fft.ifft2(x)) else: self.fft = (lambda x: np.fft.fft2(x)) self.ifft = (lambda x: np.fft.ifft2(x))
def gaussian_fft(sig, Ly, Lx): ''' gaussian filter in the fft domain with std sig and size Ly,Lx ''' x = np.arange(0, Lx) y = np.arange(0, Ly) x = np.abs(x - x.mean()) y = np.abs(y - y.mean()) xx, yy = np.meshgrid(x, y) hgx = np.exp(-np.square(xx/sig) / 2) hgy = np.exp(-np.square(yy/sig) / 2) hgg = hgy * hgx hgg /= hgg.sum() fhg = np.real(fft2(fft.ifftshift(hgg))); # smoothing filter in Fourier domain return fhg
def qsSample(parameter,source,template): (fftim,fftim2, imSize,dist,n,k)=parameter; for r in range(1,numpy.max(numpy.array(template.shape))//2): if numpy.logical_not(numpy.isnan(source[dist<=r])).sum()>=n: break; source[dist>r]=numpy.nan; extendSource=numpy.pad(source,((0,imSize[0]-source.shape[0]),(0,imSize[1]-source.shape[1])),'constant', constant_values=numpy.nan); extendtemplate=numpy.pad(template,((0,imSize[0]-source.shape[0]),(0,imSize[1]-source.shape[1])),'constant', constant_values=0); mismatchMap=numpy.real( fft.ifft2( fftim2 * numpy.conj(fft.fft2(extendtemplate* numpy.nan_to_num(extendSource*0+1))) - 2 * fftim * numpy.conj(fft.fft2(extendtemplate* numpy.nan_to_num(extendSource))))); mismatchMap[-template.shape[0]+1:,:]=numpy.nan; mismatchMap[:,-template.shape[1]+1:]=numpy.nan; indexes=numpy.argpartition(numpy.roll(mismatchMap,tuple(x//2 for x in template.shape),(0,1)).flat,math.ceil(k)); return indexes[int(math.floor(numpy.random.uniform(k)))];
def _initialize_fft(self): """ Define the two-dimensional FFT methods. """ if self.use_mkl: import mkl mkl.set_num_threads(self.nthreads) import mkl_fft self.fft = (lambda x : mkl_fft.fft2(x)) self.ifft = (lambda x : mkl_fft.ifft2(x)) else: self.fft = (lambda x : np.fft.fft2(x)) self.ifft = (lambda x : np.fft.ifft2(x))
def fft2c(img): """ it works on last two dimensions. takes image domain data and do the fft2 to return kspace data """ shp = img.shape nimg = int(np.prod(shp[0:-2])) scale = 1 / np.sqrt(np.prod(shp[-2:])) img = np.reshape(img, (nimg, shp[-2], shp[-1])) tmp = np.empty_like(img, dtype=np.complex64) for i in range(nimg): #tmp[i]=scale*np.fft.fftshift(np.fft.fft2(np.fft.ifftshift(img[i]))) tmp[i] = scale * np.fft.fftshift(mkl_fft.fft2(np.fft.ifftshift( img[i]))) kspace = np.reshape(tmp, shp) return kspace
def fft2(x, s=None, axes=(-2, -1), overwrite_input=False, extra_info=None): return mkl_fft.fft2(x, shape=s, axes=axes, overwrite_x=overwrite_input)
def fft2(x, s=None, axes=(-2,-1), overwrite_input=False, extra_info=None): return mkl_fft.fft2(x, shape=s, axes=axes, overwrite_x=overwrite_input)
def __call__(self, src, ch): op, u = self.local_func(src, ch, self.xv, self.yv) u += ifft2(fft2(op) * self.inverse_symbol).real return u
def complex_fft2(img: np.ndarray, pad_fft: bool = False) -> np.ndarray: """Returns the complex conjugate of the fft-transformed 2D array 'img', optionally padded for speed.""" Ly, Lx = img.shape return np.conj(fft2(img, (next_fast_len(Ly), next_fast_len(Lx)))) if pad_fft else np.conj( fft2(img))
def convolve(mov: np.ndarray, img: np.ndarray) -> np.ndarray: """Returns the 3D array 'mov' convolved by a 2D array 'img'.""" return ifft2(apply_dotnorm(fft2(mov), img))
def __init__(self, gf, fs, ifs, h, spread_width, kernel_kwargs=None, funcgen_tol=1e-10, inline_core=True): """ Backend class for re-usable 'ewald' sum grid evaluation for reusability, the grid must have the same h and the ewald sum must use the same spread width gf: numba callable greens function, gf(r) fs: Fourier symbol for operator, fs(kx, ky) ifs: Inverse Fourier symbol for operator, ifs(kx, ky) h: grid spacing spread_width: width to do spreading on for Laplace, 15 gives ~7 digits 20 gives ~10 digits can't seem to do much better than that, right now kernel_kwargs: dict of arguments to be passed to gf, fs, ifs, tsgf functions funcgen_tol: tolerance for function generator representation of functions used in interior spread funciton. can't seem to beat ~10 digits overall now, so no real reason to do more than that inline_core: whether to inline the function generator functions into the compiled ewald functions (inlining may speed things up but slows compilation time, sometimes dramatically) """ self.kernel_kwargs = {} if kernel_kwargs is None else kernel_kwargs self.gf = lambda r: gf(r, **self.kernel_kwargs) self.fourier_symbol = lambda kx, ky: fs(kx, ky, **self.kernel_kwargs) self.inverse_fourier_symbol = lambda kx, ky: ifs( kx, ky, **self.kernel_kwargs) self.h = h self.spread_width = spread_width self.funcgen_tol = funcgen_tol self.inline_core = inline_core # construct mollifier self.mollifier = SlepianMollifier(2 * self.spread_width) self.ssw = self.spread_width * self.h # screened greens function _excisor_gf = lambda d: excisor(d, 0.0, self.ssw, self.mollifier ) * self.gf(d) try: self.ex_funcgen = FunctionGenerator(_excisor_gf, 0.0, self.ssw, tol=self.funcgen_tol, inline_core=self.inline_core) self.excisor_gf = self.ex_funcgen.get_base_function(check=False) except: raise Exception( 'Failed constructing FunctionGenerator function for mollifier') # construct differential operator applied to residual of screened greens function _sn = 4 * self.spread_width _sgv = np.linspace(0, 4 * self.ssw, _sn, endpoint=False) _sgx, _sgy = np.meshgrid(_sgv, _sgv, indexing='ij') _skv = np.fft.fftfreq(_sn, self.h / (2 * np.pi)) _skx, _sky = np.meshgrid(_skv, _skv, indexing='ij') _slap = self.fourier_symbol(_skx, _sky) pt = np.array([[2 * self.ssw], [2 * self.ssw]]) targ = np.row_stack([_sgx.ravel(), _sgy.ravel()]) u = gf_apply(self.gf, pt[0], pt[1], targ[0], targ[1], np.array([ 1.0, ])).reshape(_sn, _sn) u[_sn // 2, _sn // 2] = 0.0 dist = np.hypot(_sgx - 2 * self.ssw, _sgy - 2 * self.ssw) dec1 = excisor(dist, 0.0, self.ssw, self.mollifier) dec2 = excisor(dist, self.ssw, 2 * self.ssw, self.mollifier) uf = u * (1 - dec1) * dec2 self.do_ufd = ifft2(fft2(uf) * _slap).real # get an interpolater for this _ax = np.linspace(np.pi, 1.5 * np.pi, 1000) _ay = np.repeat(np.pi, _ax.size) _ar = np.linspace(0, self.ssw, _ax.size) _fh = fft2(self.do_ufd) / (_sn * _sn) out = finufft.nufft2d2(_ax, _ay, _fh, isign=1, eps=1e-15, modeord=1) self._do_ufd_interpolater = sp.interpolate.InterpolatedUnivariateSpline( _ar, out.real, k=5, bbox=[0, self.ssw], ext=1) try: self.do_ufd_funcgen = FunctionGenerator( self._do_ufd_interpolater, 0.0, self.ssw, tol=self.funcgen_tol, inline_core=self.inline_core) self.do_ufd_interpolater = self.do_ufd_funcgen.get_base_function( check=False) except: raise Exception( 'Failed constructing FunctionGenerator function for laplacian of greens function times mollifier' )
def phasecorr(data, refAndMasks, ops): """ compute phase correlations for each block Parameters ------------- data : int16 or float32, 3D array size [nimg x Ly x Lx] refAndMasks : list gaussian filter, mask offset, FFT of reference image ops : dictionary 'Ly', 'Lx', 'nblocks', 'yblock', 'xblock' <- indices of blocks ymax1 : 2D array size [nimg x nblocks], y shifts of blocks xmax1 : 2D array size [nimg x nblocks], y shifts of blocks cmax1 : 2D array size [nimg x nblocks], value of peak of phase correlation ccsm : 4D array size [nimg x nblocks x ly x lx], smoothed phase correlations """ nimg, Ly, Lx = data.shape maskMul = refAndMasks[0].squeeze() maskOffset = refAndMasks[1].squeeze() cfRefImg = refAndMasks[2].squeeze() LyMax = np.diff(np.array(ops['yblock'])) ly, lx = cfRefImg.shape[-2:] lyhalf = int(np.floor(ly / 2)) lxhalf = int(np.floor(lx / 2)) # maximum registration shift allowed maxregshift = np.round(ops['maxregshiftNR']) lcorr = int( np.minimum(maxregshift, np.floor(np.minimum(ly, lx) / 2.) - lpad)) nb = len(ops['yblock']) nblocks = ops['nblocks'] # preprocessing for 1P recordings if ops['1Preg']: X = utils.one_photon_preprocess(data.copy().astype(np.float32), ops) # shifts and corrmax ymax1 = np.zeros((nimg, nb), np.float32) cmax1 = np.zeros((nimg, nb), np.float32) xmax1 = np.zeros((nimg, nb), np.float32) cc0 = np.zeros( (nimg, nb, 2 * lcorr + 2 * lpad + 1, 2 * lcorr + 2 * lpad + 1), np.float32) ymax = np.zeros((nb, ), np.int32) xmax = np.zeros((nb, ), np.int32) Y = np.zeros((nimg, nb, ly, lx), 'int16') for n in range(nb): yind, xind = ops['yblock'][n], ops['xblock'][n] Y[:, n] = data[:, yind[0]:yind[-1], xind[0]:xind[-1]] Y = addmultiply(Y, maskMul, maskOffset) for n in range(nb): for t in range(nimg): fft2(Y[t, n], overwrite_x=True) Y = utils.apply_dotnorm(Y, cfRefImg) for n in range(nb): for t in range(nimg): ifft2(Y[t, n], overwrite_x=True) x00, x01, x10, x11 = clip(Y, lcorr + lpad) cc0 = np.real(np.block([[x11, x10], [x01, x00]])) cc0 = np.transpose(cc0, (1, 0, 2, 3)) cc0 = cc0.reshape((cc0.shape[0], -1)) cc2 = [] R = ops['NRsm'] cc2.append(cc0) for j in range(2): cc2.append(R @ cc2[j]) for j in range(len(cc2)): cc2[j] = cc2[j].reshape( (nb, nimg, 2 * lcorr + 2 * lpad + 1, 2 * lcorr + 2 * lpad + 1)) ccsm = cc2[0] for n in range(nb): snr = np.ones((nimg, ), 'float32') for j in range(len(cc2)): ism = snr < ops['snr_thresh'] if np.sum(ism) == 0: break cc = cc2[j][n, ism, :, :] if j > 0: ccsm[n, ism, :, :] = cc snr[ism] = getSNR(cc, (lcorr, lpad), ops) ccmat = np.zeros((nb, 2 * lpad + 1, 2 * lpad + 1), np.float32) for t in range(nimg): ccmat = np.zeros((nb, 2 * lpad + 1, 2 * lpad + 1), np.float32) for n in range(nb): ix = np.argmax(ccsm[n, t][lpad:-lpad, lpad:-lpad], axis=None) ym, xm = np.unravel_index(ix, (2 * lcorr + 1, 2 * lcorr + 1)) ccmat[n] = ccsm[n, t][ym:ym + 2 * lpad + 1, xm:xm + 2 * lpad + 1] ymax[n], xmax[n] = ym - lcorr, xm - lcorr ccmat = np.reshape(ccmat, (nb, -1)) ccb = np.dot(ccmat, Kmat) imax = np.argmax(ccb, axis=1) cmax = np.amax(ccb, axis=1) ymax1[t], xmax1[t] = np.unravel_index(imax, (nup, nup)) cmax1[t] = cmax mdpt = np.floor(nup / 2) ymax1[t], xmax1[t] = (ymax1[t] - mdpt) / subpixel, (xmax1[t] - mdpt) / subpixel ymax1[t], xmax1[t] = ymax1[t] + ymax, xmax1[t] + xmax #ccmat = np.reshape(ccmat, (nb, 2*lpad+1, 2*lpad+1)) return ymax1, xmax1, cmax1, ccsm
def qs(ti,dst,path,template,n,k): dist=numpy.zeros(shape=template.shape); dist[math.floor(dist.shape[0]/2),math.floor(dist.shape[1]/2)]=1; dist=ndimage.morphology.distance_transform_edt(1-dist); return runsim((fft.fft2(ti), fft.fft2(ti**2),ti.shape, dist, n, k),ti, dst,path,template,qsSample);
def mklfft(it): mkl_fft.fft2(it)