def toeplitz(c, r=None): """ Construct a Toeplitz matrix. The Toeplitz matrix has constant diagonals, with c as its first column and r as its first row. If r is not given, ``r == conjugate(c)`` is assumed. Parameters ---------- c : array_like First column of the matrix. Whatever the actual shape of `c`, it will be converted to a 1-D array. r : array_like, optional First row of the matrix. If None, ``r = conjugate(c)`` is assumed; in this case, if c[0] is real, the result is a Hermitian matrix. r[0] is ignored; the first row of the returned matrix is ``[c[0], r[1:]]``. Whatever the actual shape of `r`, it will be converted to a 1-D array. Returns ------- A : (len(c), len(r)) ndarray The Toeplitz matrix. Dtype is the same as ``(c[0] + r[0]).dtype``. See Also -------- circulant : circulant matrix hankel : Hankel matrix solve_toeplitz : Solve a Toeplitz system. Notes ----- The behavior when `c` or `r` is a scalar, or when `c` is complex and `r` is None, was changed in version 0.8.0. The behavior in previous versions was undocumented and is no longer supported. Examples -------- >>> from scipy.linalg import toeplitz >>> toeplitz([1,2,3], [1,4,5,6]) array([[1, 4, 5, 6], [2, 1, 4, 5], [3, 2, 1, 4]]) >>> toeplitz([1.0, 2+3j, 4-1j]) array([[ 1.+0.j, 2.-3.j, 4.+1.j], [ 2.+3.j, 1.+0.j, 2.-3.j], [ 4.-1.j, 2.+3.j, 1.+0.j]]) """ c = cp.asarray(c).ravel() if r is None: r = cp.conjugate() else: r = cp.asarray(r).ravel() # Form a 1D array containing a reversed c followed by r[1:] that could be # strided to give us toeplitz matrix. vals = cp.concatenate((c[::-1], r[1:])) out_shp = len(c), len(r) n = vals.strides[0] return as_strided(vals[len(c) - 1:], shape=out_shp, strides=(-n, n)).copy()
def _direct_correlate(in1, in2, mode='full', output=float, convolution=False, boundary='constant', fillvalue=0.0, shift=False): if in1.ndim != 1 and (in1.dtype.kind == 'b' or (in1.dtype.kind == 'f' and in1.dtype.itemsize < 4)): raise ValueError('unsupported type in SciPy') # Swaps inputs so smaller one is in2: # NOTE: when mode != 'valid' we can only swap with a constant-0 boundary swapped_inputs = False orig_in1_shape = in1.shape if _inputs_swap_needed(mode, in1.shape, in2.shape) or ( in2.size > in1.size and boundary == 'constant' and fillvalue == 0): in1, in2 = in2, in1 swapped_inputs = True # Due to several optimizations, the second array can only be 2 GiB if in2.nbytes >= (1 << 31): raise RuntimeError('smaller array must be 2 GiB or less, ' 'use method="fft" instead') # At this point, in1.size > in2.size # (except some cases when boundary != 'constant' or fillvalue != 0) # Figure out the output shape and the origin of the kernel if mode == 'full': out_shape = tuple(x1+x2-1 for x1, x2 in zip(in1.shape, in2.shape)) offsets = tuple(x-1 for x in in2.shape) elif mode == 'valid': out_shape = tuple(x1-x2+1 for x1, x2 in zip(in1.shape, in2.shape)) offsets = (0,) * in1.ndim else: # mode == 'same': # In correlate2d: When using "same" mode with even-length inputs, the # outputs of correlate and correlate2d differ: There is a 1-index # offset between them. # This is dealt with by using "shift" parameter. out_shape = orig_in1_shape if orig_in1_shape == in1.shape: offsets = tuple((x-shift)//2 for x in in2.shape) else: offsets = tuple((2*x2-x1-(not convolution)+shift)//2 for x1, x2 in zip(in1.shape, in2.shape)) # Check the output if not isinstance(output, cupy.ndarray): output = cupy.empty(out_shape, output) elif output.shape != out_shape: raise ValueError('out has wrong shape') # Get and run the CuPy kernel int_type = _util._get_inttype(in1) kernel = filters._get_correlate_kernel( boundary, in2.shape, int_type, offsets, fillvalue) in2 = _reverse(in2) if convolution else in2.conj() if not swapped_inputs or convolution: kernel(in1, in2, output) elif output.dtype.kind != 'c': # Avoids one array copy kernel(in1, in2, _reverse(output)) else: kernel(in1, in2, output) output = cupy.ascontiguousarray(_reverse(output)) if swapped_inputs and (mode != 'valid' or not shift): cupy.conjugate(output, out=output) return output
def FLCF(volume, template, mask=None, stdV=None, gpu=False): '''Fast local correlation function @param volume: target volume @param template: template to be searched. It can have smaller size then target volume. @param mask: template mask. If not given, a default sphere mask will be used. @param stdV: standard deviation of the target volume under mask, which do not need to be calculated again when the mask is identical. @return: the local correlation function ''' if gpu: import cupy as xp else: import numpy as xp from pytom.tompy.tools import paste_in_center from pytom.tompy.transform import rfft, irfft, fftshift from pytom.tompy.tools import create_sphere if volume.shape[0] < template.shape[0] or volume.shape[1] < template.shape[ 1] or volume.shape[2] < template.shape[2]: raise Exception('Template size is bigger than the target volume!') # generate the mask if mask is None: mask = create_sphere(template.shape) else: if template.shape[0] != mask.shape[0] and template.shape[ 1] != mask.shape[1] and template.shape[2] != mask.shape[2]: raise Exception('Template and mask sizes are not the same!') # normalize the template under mask meanT = mean_under_mask(template, mask) stdT = std_under_mask(template, mask, meanT) temp = (template - meanT) / stdT temp = temp * mask # construct both the template and the mask which has the same size as target volume tempV = temp if volume.shape[0] != temp.shape[0] or volume.shape[1] != temp.shape[ 1] or volume.shape[2] != temp.shape[2]: tempV = np.zeros(volume.shape) tempV = paste_in_center(temp, tempV) maskV = mask if volume.shape[0] != mask.shape[0] or volume.shape[1] != mask.shape[ 1] or volume.shape[2] != mask.shape[2]: maskV = np.zeros(volume.shape) maskV = paste_in_center(mask, maskV) # calculate the mean and std of volume meanV = mean_vol_under_mask(volume, maskV) stdV = std_vol_under_mask(volume, maskV, meanV) size = volume.shape fT = xp.fft.rfft(tempV) fT = xp.conjugate(fT) result = xp.fft.fftshift(xp.fft.irfft(fT * xp.fft.rfft(volume), size)) / stdV return result / np.sum(mask)
def _refineCarrier_cupy(self, band0, band1, kx_in, ky_in): band0 = cp.asarray(band0) band1 = cp.asarray(band1) pxc0 = np.int(np.round(kx_in / self._dk) + self.N // 2) pyc0 = np.int(np.round(ky_in / self._dk) + self.N // 2) otf_exclude_min_radius = self.eta / 2 otf_exclude_max_radius = 1.5 # kr = cp.sqrt(cp.asarray(self._kx) ** 2 + cp.asarray(self._ky) ** 2) kr = cp.asarray(self._kr, dtype=np.double) m = (kr < 2) otf = cp.fft.fftshift(self._tfm_cupy(kr, m) + (1 - m) * 0.0001) otf_mask = (kr > otf_exclude_min_radius) & (kr < otf_exclude_max_radius) otf_mask_for_band_common_freq = cp.fft.fftshift( otf_mask & cupyx.scipy.ndimage.shift(otf_mask, (pyc0 - (self.N // 2), pxc0 - (self.N // 2)), order=0)) band0_common = cp.fft.ifft2( cp.fft.fft2(band0) / otf * otf_mask_for_band_common_freq) band1_common = cp.fft.ifft2( cp.fft.fft2(band1) / otf * otf_mask_for_band_common_freq) band = band0_common * band1_common mag = 25 * self.N / 256 ixfz, Kx, Ky = self._zoomf_cupy(band, self.N, np.single(self._k[pxc0]), np.single(self._k[pyc0]), mag, self._dk * self.N) pyc, pxc = self._findPeak_cupy(abs(ixfz)) if self.debug: plt.figure() plt.title('Zoon Find carrier') plt.imshow(abs(ixfz.get())) kx = Kx[pxc] ky = Ky[pyc] xx = cp.arange(-self.N / 2 * self._dx, self.N / 2 * self._dx, self._dx, dtype=np.double) phase_shift_to_xpeak = cp.exp(-1j * kx * xx * 2 * pi * self.NA / self.wavelength) phase_shift_to_ypeak = cp.exp(-1j * ky * xx * 2 * pi * self.NA / self.wavelength) scaling = 1 / cp.sum(band0_common * cp.conjugate(band0_common)) cross_corr_result = cp.sum(band0_common * band1_common * cp.outer( phase_shift_to_ypeak, phase_shift_to_xpeak)) * scaling ampl = cp.abs(cross_corr_result) * 2 phase = cp.angle(cross_corr_result) return kx.get(), ky.get(), phase.get(), ampl.get()