Exemplo n.º 1
0
Arquivo: sc.py Projeto: slaclab/ocelot
 def potential(self, q, steps):
     hx = steps[0]
     hy = steps[1]
     hz = steps[2]
     Nx = q.shape[0]
     Ny = q.shape[1]
     Nz = q.shape[2]
     out = np.zeros((2*Nx-1, 2*Ny-1, 2*Nz-1))
     out[:Nx, :Ny, :Nz] = q
     K1 = self.sym_kernel(q.shape, steps)
     K2 = np.zeros((2*Nx-1, 2*Ny-1, 2*Nz-1))
     K2[0:Nx, 0:Ny, 0:Nz] = K1
     K2[0:Nx, 0:Ny, Nz:2*Nz-1] = K2[0:Nx, 0:Ny, Nz-1:0:-1] #z-mirror
     K2[0:Nx, Ny:2*Ny-1,:] = K2[0:Nx, Ny-1:0:-1, :]        #y-mirror
     K2[Nx:2*Nx-1, :, :] = K2[Nx-1:0:-1, :, :]             #x-mirror
     t0 = time()
     if pyfftw_flag:
         nthread = multiprocessing.cpu_count()
         K2_fft = pyfftw.builders.fftn(K2, axes=None, overwrite_input=False, planner_effort='FFTW_ESTIMATE',
                                    threads=nthread, auto_align_input=False, auto_contiguous=False, avoid_copy=True)
         out_fft = pyfftw.builders.fftn(out, axes=None, overwrite_input=False, planner_effort='FFTW_ESTIMATE',
                                       threads=nthread, auto_align_input=False, auto_contiguous=False, avoid_copy=True)
         out_ifft = pyfftw.builders.ifftn(out_fft()*K2_fft(), axes=None, overwrite_input=False, planner_effort='FFTW_ESTIMATE',
                                       threads=nthread, auto_align_input=False, auto_contiguous=False, avoid_copy=True)
         out = np.real(out_ifft())
     else:
         out = np.real(ifftn(fftn(out)*fftn(K2)))
     t1 = time()
     if self.debug: print( 'fft time:', t1-t0, ' sec')
     out[:Nx, :Ny, :Nz] = out[:Nx,:Ny,:Nz]/(4*pi*epsilon_0*hx*hy*hz)
     return out[:Nx, :Ny, :Nz]
Exemplo n.º 2
0
def convolve(arr1, arr2, dx=None, axes=None):
    """
    Performs a centred convolution of input arrays

    Parameters
    ----------
    arr1, arr2 : `numpy.ndarray`
        Arrays to be convolved. If dimensions are not equal then 1s are appended
        to the lower dimensional array. Otherwise, arrays must be broadcastable.
    dx : float > 0, list of float, or `None` , optional
        Grid spacing of input arrays. Output is scaled by
        `dx**max(arr1.ndim, arr2.ndim)`. default=`None` applies no scaling
    axes : tuple of ints or `None`, optional
        Choice of axes to convolve. default=`None` convolves all axes

    """
    if arr2.ndim > arr1.ndim:
        arr1, arr2 = arr2, arr1
        if axes is None:
            axes = range(arr2.ndim)
    arr2 = arr2.reshape(arr2.shape + (1, ) * (arr1.ndim - arr2.ndim))

    if dx is None:
        dx = 1
    elif isscalar(dx):
        dx = dx**(len(axes) if axes is not None else arr1.ndim)
    else:
        dx = prod(dx)

    arr1 = fftn(arr1, axes=axes)
    arr2 = fftn(ifftshift(arr2), axes=axes)
    out = ifftn(arr1 * arr2, axes=axes) * dx
    return require(out, requirements="CA")
Exemplo n.º 3
0
    def fftconvolve(in1, in2, mode="same", threads=1):
        """Same as above but with pyfftw added in"""
        in1 = np.asarray(in1)
        in2 = np.asarray(in2)

        if in1.ndim == in2.ndim == 0:  # scalar inputs
            return in1 * in2
        elif not in1.ndim == in2.ndim:
            raise ValueError("in1 and in2 should have the same dimensionality")
        elif in1.size == 0 or in2.size == 0:  # empty arrays
            return np.array([])

        s1 = np.array(in1.shape)
        s2 = np.array(in2.shape)
        complex_result = (np.issubdtype(in1.dtype, complex)
                          or np.issubdtype(in2.dtype, complex))
        shape = s1 + s2 - 1

        # Check that input sizes are compatible with 'valid' mode
        if sig._inputs_swap_needed(mode, s1, s2):
            # Convolution is commutative; order doesn't have any effect on output
            in1, s1, in2, s2 = in2, s2, in1, s1

        # Speed up FFT by padding to optimal size for FFTPACK
        fshape = [sig.fftpack.helper.next_fast_len(int(d)) for d in shape]
        fslice = tuple([slice(0, int(sz)) for sz in shape])
        # Pre-1.9 NumPy FFT routines are not threadsafe.  For older NumPys, make
        # sure we only call rfftn/irfftn from one thread at a time.
        if not complex_result and (sig._rfft_mt_safe
                                   or sig._rfft_lock.acquire(False)):
            try:
                sp1 = rfftn(in1, fshape, threads=threads)
                sp2 = rfftn(in2, fshape, threads=threads)
                ret = (irfftn(sp1 * sp2, fshape,
                              threads=threads)[fslice].copy())
            finally:
                if not sig._rfft_mt_safe:
                    sig._rfft_lock.release()
        else:
            # If we're here, it's either because we need a complex result, or we
            # failed to acquire _rfft_lock (meaning rfftn isn't threadsafe and
            # is already in use by another thread).  In either case, use the
            # (threadsafe but slower) SciPy complex-FFT routines instead.
            sp1 = fftn(in1, fshape, threads=threads)
            sp2 = fftn(in2, fshape, threads=threads)
            ret = ifftn(sp1 * sp2, threads=threads)[fslice].copy()
            if not complex_result:
                ret = ret.real

        if mode == "full":
            return ret
        elif mode == "same":
            return sig._centered(ret, s1)
        elif mode == "valid":
            return sig._centered(ret, s1 - s2 + 1)
        else:
            raise ValueError("Acceptable mode flags are 'valid',"
                             " 'same', or 'full'.")
Exemplo n.º 4
0
    def fftconvolve(in1, in2, mode="same", threads=1):
        """Same as above but with pyfftw added in"""
        in1 = np.asarray(in1)
        in2 = np.asarray(in2)

        if in1.ndim == in2.ndim == 0:  # scalar inputs
            return in1 * in2
        elif not in1.ndim == in2.ndim:
            raise ValueError("in1 and in2 should have the same dimensionality")
        elif in1.size == 0 or in2.size == 0:  # empty arrays
            return np.array([])

        s1 = np.array(in1.shape)
        s2 = np.array(in2.shape)
        complex_result = (np.issubdtype(in1.dtype, complex) or
                          np.issubdtype(in2.dtype, complex))
        shape = s1 + s2 - 1

        # Check that input sizes are compatible with 'valid' mode
        if sig._inputs_swap_needed(mode, s1, s2):
            # Convolution is commutative; order doesn't have any effect on output
            in1, s1, in2, s2 = in2, s2, in1, s1

        # Speed up FFT by padding to optimal size for FFTPACK
        fshape = [sig.fftpack.helper.next_fast_len(int(d)) for d in shape]
        fslice = tuple([slice(0, int(sz)) for sz in shape])
        # Pre-1.9 NumPy FFT routines are not threadsafe.  For older NumPys, make
        # sure we only call rfftn/irfftn from one thread at a time.
        if not complex_result and (sig._rfft_mt_safe or sig._rfft_lock.acquire(False)):
            try:
                sp1 = rfftn(in1, fshape, threads=threads)
                sp2 = rfftn(in2, fshape, threads=threads)
                ret = (irfftn(sp1 * sp2, fshape, threads=threads)[fslice].copy())
            finally:
                if not sig._rfft_mt_safe:
                    sig._rfft_lock.release()
        else:
            # If we're here, it's either because we need a complex result, or we
            # failed to acquire _rfft_lock (meaning rfftn isn't threadsafe and
            # is already in use by another thread).  In either case, use the
            # (threadsafe but slower) SciPy complex-FFT routines instead.
            sp1 = fftn(in1, fshape, threads=threads)
            sp2 = fftn(in2, fshape, threads=threads)
            ret = ifftn(sp1 * sp2, threads=threads)[fslice].copy()
            if not complex_result:
                ret = ret.real

        if mode == "full":
            return ret
        elif mode == "same":
            return sig._centered(ret, s1)
        elif mode == "valid":
            return sig._centered(ret, s1 - s2 + 1)
        else:
            raise ValueError("Acceptable mode flags are 'valid',"
                             " 'same', or 'full'.")
Exemplo n.º 5
0
def fourier_shell_correlation(obj,
                              ref,
                              step_size=1,
                              save_path='fsc',
                              save_mask=True):

    if not os.path.exists(save_path):
        os.makedirs(save_path)

    radius_max = int(min(obj.shape) / 2)
    f_obj = np_fftshift(fftn(obj))
    f_ref = np_fftshift(fftn(ref))
    f_prod = f_obj * np.conjugate(f_ref)
    f_obj_2 = np.real(f_obj * np.conjugate(f_obj))
    f_ref_2 = np.real(f_ref * np.conjugate(f_ref))
    radius_ls = np.arange(1, radius_max, step_size)
    fsc_ls = []
    np.save(os.path.join(save_path, 'radii.npy'), radius_ls)

    for rad in radius_ls:
        print(rad)
        if os.path.exists(
                os.path.join(save_path,
                             'mask_rad_{:04d}.tiff'.format(int(rad)))):
            mask = dxchange.read_tiff(
                os.path.join(save_path,
                             'mask_rad_{:04d}.tiff'.format(int(rad))))
        else:
            mask = generate_shell(obj.shape, rad, anti_aliasing=2)
            if save_mask:
                dxchange.write_tiff(
                    mask,
                    os.path.join(save_path,
                                 'mask_rad_{:04d}.tiff'.format(int(rad))),
                    dtype='float32',
                    overwrite=True)
        fsc = abs(np.sum(f_prod * mask))
        fsc /= np.sqrt(np.sum(f_obj_2 * mask) * np.sum(f_ref_2 * mask))
        fsc_ls.append(fsc)
        np.save(os.path.join(save_path, 'fsc.npy'), fsc_ls)

    matplotlib.rcParams['pdf.fonttype'] = 'truetype'
    fontProperties = {
        'family': 'serif',
        'serif': ['Times New Roman'],
        'weight': 'normal',
        'size': 12
    }
    plt.rc('font', **fontProperties)
    plt.plot(radius_ls.astype(float) / radius_ls[-1], fsc_ls)
    plt.xlabel('Spatial frequency (1 / Nyquist)')
    plt.ylabel('FSC')
    plt.savefig(os.path.join(save_path, 'fsc.pdf'), format='pdf')
def template_generation(imgs):
    avgimg = np.median(imgs, 0)
    avgimg_fft = fftn(avgimg)
    # Estimation of the difference for few trials in order to create a new template
    datafft = fftn(imgs, axes=(1, 2))
    mov = Parallel(n_jobs=4)(delayed(register_translation)(avgimg_fft, datafft[
        i, :, :], 100, 'fourier') for i in np.arange(len(imgs)))
    x = [element[0][0] for element in mov]
    y = [element[0][1] for element in mov]
    # Creation of the new template
    newimgs = shifts(imgs, x, y)
    # Run the algorythm to estimate registration between frames
    template = np.median(newimgs, 0)
    return template
Exemplo n.º 7
0
    def __init__(
            self,
            modulus,
            support,
            beta=0.9,
            binning=1,  # for high-energy CDI. Set to 1 for regular phase retrieval.
            gpu=False,
            random_start=True):
        self._modulus = fftshift(modulus)
        self._support = support
        self._beta = beta

        #        self._modulus_sum       = modulus.sum()
        self._support_comp = 1. - support
        if random_start:
            self._cImage = np.exp(2.j * np.pi * np.random.rand(
                binning * self._modulus.shape[0],
                binning * self._modulus.shape[1],
                self._modulus.shape[2])) * self._support
        else:
            self._cImage = 1. * support

        self._cachedImage = np.zeros(self._cImage.shape).astype(complex)
        self._cImage_fft_mod = np.absolute(fftn(self._cImage))

        self._error = []
        self._UpdateError()
        self.generateAlgoDict()

        if gpu == True:
            self.gpusolver = accelerator.Solver(self.generateGPUPackage())

        return
Exemplo n.º 8
0
def fftn(a, axes=None):
    if _use_fftw:
        from pyfftw.interfaces.numpy_fft import fftn
        _init_pyfftw()
        return fftn(a, axes=axes, **_fft_extra_args)
    else:
        return np.fft.fftn(a, axes=axes)
Exemplo n.º 9
0
def fft2d(arr2d,
          mode,
          numpy_fft=pyfftw.interfaces.numpy_fft,
          only_real=False,
          batch=False):
    '''
  we apply an alterating +1/-1 multiplicative before we go to/from Fourier space. 
  Later we apply this again to the transform.
  TODO: look into pyfftw.interfaces.numpy_fft.irfftn
  '''

    assert (arr2d.ndim == 2 and not batch) or (batch and arr2d.ndim == 3)
    n1, n2 = arr2d.shape[-2:]
    assert n1 == n2
    arr2d = neg_pos_2d(arr2d.reshape(-1, n1, n1).copy())

    if mode == 'f':
        arr2d_f = numpy_fft.fftn(arr2d, axes=(-2, -1))
        arr2d_f /= n1
    elif mode == 'i':
        arr2d_f = numpy_fft.ifftn(arr2d, axes=(-2, -1))
        arr2d_f *= n1

    if only_real: arr2d_f = arr2d_f.real

    arr2d_f = neg_pos_2d(arr2d_f.copy())
    if not batch: arr2d_f = arr2d_f.reshape(n1, n2)

    return (arr2d_f)
Exemplo n.º 10
0
def cryo_conv_vol(x, kernel_f):
    n = x.shape[0]
    n_ker = kernel_f.shape[0]

    if np.any(np.array(x.shape) != n):
        raise ValueError('Volume in `x` must be cubic')

    if np.any(np.array(kernel_f.shape) != n_ker):
        raise ValueError('Convolution kernel in `kernel_f` must be cubic')

    is_singleton = len(x.shape) == 3

    shifted_kernel_f = np.fft.ifftshift(np.fft.ifftshift(np.fft.ifftshift(kernel_f, 0), 1), 2)

    if is_singleton:
        x = numpy_fft.fftn(x, [n_ker] * 3)
    else:
        x = numpy_fft.fft(x, n=n_ker, axis=0)
        x = numpy_fft.fft(x, n=n_ker, axis=1)
        x = numpy_fft.fft(x, n=n_ker, axis=2)

    x *= shifted_kernel_f

    if is_singleton:
        x = numpy_fft.ifftn(x)
        x = x[:n, :n, :n]
    else:
        x = numpy_fft.ifft(x, axis=0)
        x = numpy_fft.ifft(x, axis=1)
        x = numpy_fft.ifft(x, axis=2)

    x = x.real
    return x
Exemplo n.º 11
0
def ufftn(inarray, dim=None):
    """N-dimensional unitary Fourier transform.

    Parameters
    ----------
    inarray : ndarray
        The array to transform.
    dim : int, optional
        The last axis along which to compute the transform. All
        axes by default.

    Returns
    -------
    outarray : ndarray (same shape than inarray)
        The unitary N-D Fourier transform of ``inarray``.

    Examples
    --------
    >>> input = np.ones((3, 3, 3))
    >>> output = ufftn(input)
    >>> np.allclose(np.sum(input) / np.sqrt(input.size), output[0, 0, 0])
    True
    >>> output.shape
    (3, 3, 3)
    """
    if dim is None:
        dim = inarray.ndim
    outarray = fftn(inarray, axes=range(-dim, 0))
    return outarray / np.sqrt(np.prod(inarray.shape[-dim:]))
def registerPP(data, template=[], size=30):
    """
    Register multiple images according to a template, if the template does not exist create one with the first SIZE images.
    """
    #size of the first bunch of time to create the template
    nt, nx, ny = data.shape
    datasmooth = gaussian_filter(data, (0, 2, 2))
    # First approximation of the template
    if len(template) == 0:
        template = template_generation(data[:size, :, :])
    template_fft = fftn(template)
    mov = Parallel(n_jobs=4)(delayed(register_translation)(
        template_fft, fftn(data[i, :, :]), 100, 'fourier')
                             for i in np.arange(nt))
    x = [element[0][0] for element in mov]
    y = [element[0][1] for element in mov]
    return x, y
Exemplo n.º 13
0
def easy_fft(data, axes=None):
    """utility method that includes fft shifting"""
    return fftshift(
        fftn(
            ifftshift(
                data, axes=axes
            ), axes=axes
        ), axes=axes)
Exemplo n.º 14
0
def removePhaseRamps( img ): #... by centering the Bragg peak in the array
    fimg = fftshift( fftn( fftshift( img ) ) )
    intens = np.absolute( fimg )**2
    maxHere = np.where( intens==intens.max() )
    for n in [ 0, 1, 2 ]:
        fimg = np.roll( fimg, fimg.shape[n]//2-maxHere[n], axis=n )
    imgout = fftshift( ifftn( fftshift( fimg ) ) )
    return imgout
Exemplo n.º 15
0
def fftdeconvolve(image, psf):
   """
   De-convolution by directly dividing the DFT... may not be numerically 
   desirable for many applications. Noise could be an issue.
   Use scipy.fftpack for now; will re-write for anfft later...
   Taken from this post on stackoverflow.com: 
   http://stackoverflow.com/questions/17473917/is-there-a-equivalent-of-scipy-signal-deconvolve-for-2d-arrays
   """
   if not _pyfftw:
      raise NotImplementedError
   image = image.astype('float')
   psf = psf.astype('float')

   # image_fft = fftpack.fftshift(fftpack.fftn(image))
   # psf_fft = fftpack.fftshift(fftpack.fftn(psf))
   image_fft = fftshift(fftn(image))
   psf_fft = fftshift(fftn(psf))
   kernel = fftshift(ifftn(ifftshift(image_fft / psf_fft)))
   return kernel
Exemplo n.º 16
0
 def __init__( self, measured_intensity, gpack ):
     self._shape = gpack[ 'array_shape' ]        
     self._modulus_measured = tf.constant( np.sqrt( measured_intensity ), dtype=tf.float32 )
     pts = self._setupDomain( gpack=gpack )
     self._setupConstants( pts )
     self._setCoherentEstimate( np.absolute( fftn( gpack[ 'cImage' ] ) )**2 )
     self._setupVariables()
     self._setupAuxiliary()
     self._updateBlurKernel()
     self._setupOptimizer( learning_rate=0.01, momentum=0.99 )
     return
Exemplo n.º 17
0
def realign_image_1d(arr, shift, angle=0):

    # if both shifts are integers, do circular shift; otherwise perform Fourier shift.
    if np.abs(np.array(shift) - np.round(shift)) < 0.01:
        temp = np.roll(arr, int(shift))
        temp = temp.astype('float32')
    else:
        temp = fourier_shift(fftn(arr), shift)
        temp = ifftn(temp)
        temp = np.abs(temp).astype('float32')
    return temp
Exemplo n.º 18
0
def cfftn(data, axes):
    """ Centered fast fourier transform, n-dimensional.

    :param data: Complex input data.
    :param axes: Axes along which to shift and transform.
    :return: Fourier transformed data.
    """
    return fft.fftshift(fft.fftn(fft.ifftshift(data, axes=axes),
                                 axes=axes,
                                 norm='ortho'),
                        axes=axes)
Exemplo n.º 19
0
 def fftw(E):
     if np.any(np.array(E.shape[2:]) > 1):
         assert(E.ndim-2 == self.data_shape.size and np.all(E.shape[2:] == self.data_shape))
         if np.all(E.shape == fft_vec_object.input_shape):
             result_array = self.__empty_word_aligned(E.shape, dtype=np.complex128)
             fft_vec_object(E, result_array)
         else:
             log.debug('Fourier Transform: Array shape not standard, falling back to default interface.')
             result_array = ft.fftn(E, axes=ft_axes)
         return result_array
     else:
         return E.copy()
Exemplo n.º 20
0
    def plan_fft(A, n=None, axis=None, norm=None, **_):
        """
        Plans an fft for repeated use. Parameters are the same as for `pyfftw`'s `fftn`
        which are, where possible, the same as the `numpy` equivalents.
        Note that some functionality is only possible when using the `pyfftw` backend.

        Parameters
        ----------
        A : `numpy.ndarray`, of dimension `d`
            Array of same shape to be input for the fft
        n : iterable or `None`, `len(n) == d`, optional
            The output shape of fft (default=`None` is same as `A.shape`)
        axis : `int`, iterable length `d`, or `None`, optional
            The axis (or axes) to transform (default=`None` is all axes)
        overwrite : `bool`, optional
            Whether the input array can be overwritten during computation
            (default=False)
        planner : {0, 1, 2, 3}, optional
            Amount of effort put into optimising Fourier transform where 0 is low
            and 3 is high (default=`1`).
        threads : `int`, `None`
            Number of threads to use (default=`None` is all threads)
        auto_align_input : `bool`, optional
            If `True` then may re-align input (default=`True`)
        auto_contiguous : `bool`, optional
            If `True` then may re-order input (default=`True`)
        avoid_copy : `bool`, optional
            If `True` then may over-write initial input (default=`False`)
        norm : {None, 'ortho'}, optional
            Indicate whether fft is normalised (default=`None`)

        Returns
        -------
        plan : function
            Returns the Fourier transform of `B`, `plan() == fftn(B)`
        B : `numpy.ndarray`, `A.shape`
            Array which should be modified inplace for fft to be computed. If
            possible, `B is A`.


        Example
        -------
        A = numpy.zeros((8,16))
        plan, B = plan_fft(A)

        B[:,:] = numpy.random.rand(8,16)
        numpy.fft.fftn(B) == plan()

        B = numpy.random.rand(8,16)
        numpy.fft.fftn(B) != plan()

        """
        return lambda: fftn(A, n, axis, norm), A
Exemplo n.º 21
0
def ftrg(fr, grid):
    """Fourier transform function fr from R space to G space.

    Args:
        fr (np.ndarray): R space function. shape == (grid.n1, grid.n2, grid.n3).
        grid (FFTGrid): FFT grid on which fr is defined.

    Returns:
        G space function.
    """
    assert fr.shape == (grid.n1, grid.n2, grid.n3)
    return (1. / grid.N) * fftn(fr)
Exemplo n.º 22
0
Arquivo: ft.py Projeto: tsaie79/pyzfs
    def forward(self, fr):
        """Fourier forward transform a function.

        Args:
            fr (np.ndarray): function in R space (3D array)

        Returns:
            function in G space (with same grid size)
        """
        assert fr.ndim == 3 and fr.shape == (self.n1, self.n2, self.n3)
        fg = (1./self.N) * fftn(fr)
        return fg
Exemplo n.º 23
0
 def potential(self, q, steps):
     hx = steps[0]
     hy = steps[1]
     hz = steps[2]
     Nx = q.shape[0]
     Ny = q.shape[1]
     Nz = q.shape[2]
     out = np.zeros((2*Nx-1, 2*Ny-1, 2*Nz-1))
     out[:Nx, :Ny, :Nz] = q
     K1 = self.sym_kernel(q.shape, steps)
     K2 = np.zeros((2*Nx-1, 2*Ny-1, 2*Nz-1))
     K2[0:Nx, 0:Ny, 0:Nz] = K1
     K2[0:Nx, 0:Ny, Nz:2*Nz-1] = K2[0:Nx, 0:Ny, Nz-1:0:-1] #z-mirror
     K2[0:Nx, Ny:2*Ny-1,:] = K2[0:Nx, Ny-1:0:-1, :]        #y-mirror
     K2[Nx:2*Nx-1, :, :] = K2[Nx-1:0:-1, :, :]             #x-mirror
     t0 = time()
     out = np.real(ifftn(fftn(out)*fftn(K2)))
     t1 = time()
     if self.debug: print( 'fft time:', t1-t0, ' sec')
     out[:Nx, :Ny, :Nz] = out[:Nx,:Ny,:Nz]/(4*pi*epsilon_0*hx*hy*hz)
     return out[:Nx, :Ny, :Nz]
Exemplo n.º 24
0
 def _initializeSupport(self, sigma=0.575):
     temp = np.log10(np.absolute(fftshift(fftn(self._modulus))))
     mask = (temp > sigma * temp.max()).astype(float)
     labeled, features = label(mask)
     support_label = list(
         dict(
             sorted(collections.Counter(labeled.ravel()).items(),
                    key=lambda item: -item[1])).keys())[1]
     self._support = np.zeros(self._arraySize)
     self._support[np.where(labeled == support_label)] = 1.
     self._support = fftshift(self._support)
     #        self.BinaryErosion( 1 )
     return
Exemplo n.º 25
0
    def __init__( self,
            modulus,
            support=None,       # if None, use default support 
            beta=0.9, 
            binning=1,          # for high-energy CDI. Set to 1 for regular phase retrieval.
            gpu=False,
            pcc=False,
            pcc_params=None,    # user-defined coherence function parameters
            random_start=True 
            ):
       
        self.BEStruct           = np.ones( ( 3, 3, 3 ) ) # default structuring element for 3D binary erosion
        self.BinaryErosion      = self.__CPUErosion__
        
        self._modulus           = fftshift( modulus )
        self._arraySize         = tuple( this*shp for this, shp in zip( [ binning, binning, 1 ], self._modulus.shape ) )
        if support is None:
            self._initializeSupport()
        else: 
            self._support = fftshift( support )

        self._support_comp      = 1. - self._support
        self._beta              = beta

        if random_start:
            self._cImage            = np.exp( 2.j * np.pi * np.random.random_sample( self._arraySize ) ) * self._support
        else:
            self._cImage            = 1. * self._support

       
        self._cachedImage       = np.zeros( self._cImage.shape ).astype( complex )
        self._cImage_fft_mod = np.absolute( fftn( self._cImage ) )

        self._error             = []

        self._UpdateError()
        self.generateAlgoDict()

        if gpu==True:
            gpack = self.generateGPUPackage( pcc=pcc, pcc_params=pcc_params )
            self.gpusolver = accelerator.Solver( gpack )

        #if pcc==True:
        #    self._pccSolver = PCSolver( np.absolute( self._modulus )**2, gpack )
        #    self._kernel_f = self._pccSolver.getBlurKernel()
        #    self._ModProject = self._ModProjectPC

        return
Exemplo n.º 26
0
 def fftw_inplace(E):
     if np.any(np.array(E.shape[2:]) > 1):
         strides_not_identical = np.any(E.strides != fftw_vec_array.strides)
         if strides_not_identical:
             log.debug('In-place Fourier Transform: strides not identical.')
             E = self.__word_align(E.copy())
         if not pyfftw.is_n_byte_aligned(E, pyfftw.simd_alignment):
             log.debug('In-place Fourier Transform: Input/Output array not %d-byte word aligned, aligning now.'
                       % pyfftw.simd_alignment)
             E = self.__word_align(E)
         assert(E.ndim-2 == self.data_shape.size and np.all(E.shape[2:] == self.data_shape))
         if np.all(E.shape == fft_vec_object.input_shape) \
                 and pyfftw.is_n_byte_aligned(E, pyfftw.simd_alignment):
             fft_vec_object(E, E)  # E should be in SIMD-word-aligned memory zone
         else:
             log.debug('Fourier Transform: Array shape not standard, falling back to default interface.')
             E = ft.fftn(E, axes=ft_axes)
     return E
Exemplo n.º 27
0
def fft3d(
    arr3d, mode, neg_pos_3d=None, numpy_fft=pyfftw.interfaces.numpy_fft, only_real=False
):
    if neg_pos_3d is None:
        neg_pos_3d = make_neg_pos_3d(arr3d)
    if arr3d.shape[0] % 4 != 0:
        neg_pos_3d *= -1

    if mode == "f":
        arr3d_f = numpy_fft.fftn(neg_pos_3d * arr3d)
        arr3d_f /= np.sqrt(np.prod(arr3d_f.shape))
    elif mode == "i":
        arr3d_f = numpy_fft.ifftn(neg_pos_3d * arr3d)
        arr3d_f *= np.sqrt(np.prod(arr3d_f.shape))

    if only_real:
        arr3d_f = arr3d_f.real

    arr3d_f *= neg_pos_3d
    return arr3d_f
Exemplo n.º 28
0
def fft2d(arr2d, mode, numpy_fft=pyfftw.interfaces.numpy_fft, only_real=True):
    '''
  we apply an alterating +1/-1 multiplicative before we go to/from Fourier space. 
  Later we apply this again to the transform.
  '''
    assert arr2d.ndim == 2
    n1, n2 = arr2d.shape
    assert n1 == n2
    arr2d = neg_pos(arr2d.copy())
    arr2d_f = numpy_fft.fftn(arr2d.reshape(-1, n1, n1), axes=(-2, -1))

    if mode == 'f':
        arr2d_f /= n1
    elif mode == 'i':
        arr2d_f *= n1

    if only_real: arr2d_f = arr2d_f.real

    arr2d_f = neg_pos(arr2d_f.reshape(n1, n1).copy())
    return (arr2d_f)
Exemplo n.º 29
0
    def DFT(fx, axes=None):
        """
        Discrete Fourier transform

        Parameters
        ----------
        fx : `numpy.ndarray`
            Array defining a function evaluated on a mesh.
        axes : `int`or list of `int` , optional
            Specification of which axes to transform. default=`None` transforms all.

        Returns
        -------
        fy : `numpy.ndarray`
            The Fourier transform of `fx` evaluated on a mesh
        """
        NDIM = fx.ndim
        if axes is None:
            axes = [NDIM + i for i in range(-ndim, 0)]
        elif not hasattr(axes, "__iter__"):
            axes = (axes, )
        axes = array(axes)
        axes.sort()

        FT = fftshift(fftn(fx, axes=axes), axes=axes)

        if NDIM != 3:
            # This is not typically a bottle-neck in <3D
            for i in axes:
                sz = [1] * NDIM
                sz[axes[i]] = -1
                FT *= exp(-xmin[i] * Y[i].reshape(sz) *
                          1j) * (dx[i] if dx[i] != 0 else 1)
        else:
            F = [
                exp(-xmin[i] * Y[i] * 1j) * (dx[i] if dx[i] != 0 else 1)
                for i in range(NDIM)
            ]
            apply_phase_3D(FT, *F)

        return FT
Exemplo n.º 30
0
Arquivo: ft.py Projeto: tsaie79/pyzfs
    def interp(self, fr, n1, n2, n3):
        """Fourier interpolate a function to a smoother grid.

        Args:
            fr: function to be interpolated
            n1, n2, n3 (int): new grid size

        Returns:
            interpolated function (3D array of size n1 by n2 by n3)
        """
        assert fr.ndim == 3 and fr.shape == (self.n1, self.n2, self.n3)
        assert n1 <= self.n1 and n2 <= self.n2 and n3 <= n3
        if (n1, n2, n3) == (self.n1, self.n2, self.n3):
            return fr
        fg = fftn(fr)
        sfg = fftshift(fg)
        newsfg = sfg[(self.n1-n1-1)//2+1:(self.n1-n1-1)//2+1+n1,
                     (self.n2-n2-1)//2+1:(self.n2-n2-1)//2+1+n2,
                     (self.n3-n3-1)//2+1:(self.n3-n3-1)//2+1+n3,
                    ]
        newfg = ifftshift(newsfg)
        newfr = (float(n1*n2*n3)/float(self.N)) * ifftn(newfg)
        return newfr
Exemplo n.º 31
0
def ft(phi):
    """Go from physical space to spectral space."""
    return fftn(phi, axes=(0,1))
Exemplo n.º 32
0
def ir2fr(imp_resp, shape, center=None, real=True):
    """Return the frequency response from impulsionnal responses

	This function make the necessary correct zero-padding, zero
	convention, correct DFT etc. to compute the frequency response
	from impulsionnal responses (IR).

	The IR array is supposed to have the origin in the middle of the
	array.

	The Fourier transform is performed on the last `len(shape)`
	dimensions.

	Parameters
	----------
	imp_resp : ndarray
	The impulsionnal responses.

	shape : tuple of int
	A tuple of integer corresponding to the target shape of the
	frequency responses, without hermitian property.

	center : tuple of int, optional
	The origin index of the impulsionnal response. The middle by
	default.

	real : boolean (optionnal, default True)
	If True, imp_resp is supposed real, the hermissian property is
	used with rfftn DFT and the output has `shape[-1] / 2 + 1`
	elements on the last axis.

	Returns
	-------
	y : ndarray
	The frequency responses of shape `shape` on the last
	`len(shape)` dimensions.

	Notes
	-----
	- For convolution, the result have to be used with unitary
	discrete Fourier transform for the signal (udftn or equivalent).
	- DFT are always peformed on last axis for efficiency.
	- Results is always C-contiguous.

	See Also
	--------
	udftn, uidftn, urdftn, uirdftn
	"""
    if len(shape) > imp_resp.ndim:
        raise ValueError("length of shape must inferior to imp_resp.ndim")

    if not center:
        center = [int(np.floor(length / 2)) for length in imp_resp.shape]

    if len(center) != len(shape):
        raise ValueError("center and shape must have the same length")

    # Place the provided IR at the beginning of the array
    irpadded = np.zeros(shape)
    irpadded[tuple([slice(0, s) for s in imp_resp.shape])] = imp_resp

    # Roll, or circshift to place the origin at 0 index, the
    # hypothesis of the DFT
    for axe, shift in enumerate(center):
        irpadded = np.roll(irpadded, -shift, imp_resp.ndim - len(shape) + axe)

    # Perform the DFT on the last axes
    if real:
        return np.ascontiguousarray(
            rfftn(irpadded,
                  axes=list(range(imp_resp.ndim - len(shape), imp_resp.ndim))))
    else:
        return np.ascontiguousarray(
            fftn(irpadded,
                 axes=list(range(imp_resp.ndim - len(shape), imp_resp.ndim))))
Exemplo n.º 33
0
def register_mean_offsets(frames2reg,
                          max_iters=-1,
                          block_frame_length=-1,
                          include_shift=False,
                          to_truncate=False,
                          float_type=numpy.dtype(float).type):
    """
        This algorithm registers the given image stack against its mean
        projection. This is done by computing translations needed to put each
        frame in alignment. Then the translation is performed and new
        translations are computed. This is repeated until no further
        improvement can be made.

        The code for translations can be found in find_mean_offsets.

        Notes:
            Adapted from code provided by Wenzhi Sun with speed improvements
            provided by Uri Dubin.

        Args:
            frames2reg(numpy.ndarray):           Image stack to register (time
                                                 is the first dimension uses
                                                 C-order tyx or tzyx).

            max_iters(int):                      Number of iterations to allow
                                                 before forcing termination if
                                                 stable point is not found yet.
                                                 Set to -1 if no limit.
                                                 (Default -1)

            block_frame_length(int):             Number of frames to work with
                                                 at a time. By default all.
                                                 (Default -1)

            include_shift(bool):                 Whether to return the shifts
                                                 used, as well. (Default False)

            to_truncate(bool):                   Whether to truncate the frames
                                                 to remove all masked portions.
                                                 (Default False)

            float_type(type):                    Type of float to use for
                                                 calculation. (Default
                                                 numpy.float64).

        Returns:
            (numpy.ndarray):                     an array containing the
                                                 translations to apply to each
                                                 frame.

        Examples:
            >>> a = numpy.zeros((5, 3, 4)); a[:,0] = 1; a[2,0] = 0; a[2,2] = 1
            >>> a
            array([[[ 1.,  1.,  1.,  1.],
                    [ 0.,  0.,  0.,  0.],
                    [ 0.,  0.,  0.,  0.]],
            <BLANKLINE>
                   [[ 1.,  1.,  1.,  1.],
                    [ 0.,  0.,  0.,  0.],
                    [ 0.,  0.,  0.,  0.]],
            <BLANKLINE>
                   [[ 0.,  0.,  0.,  0.],
                    [ 0.,  0.,  0.,  0.],
                    [ 1.,  1.,  1.,  1.]],
            <BLANKLINE>
                   [[ 1.,  1.,  1.,  1.],
                    [ 0.,  0.,  0.,  0.],
                    [ 0.,  0.,  0.,  0.]],
            <BLANKLINE>
                   [[ 1.,  1.,  1.,  1.],
                    [ 0.,  0.,  0.,  0.],
                    [ 0.,  0.,  0.,  0.]]])

            >>> register_mean_offsets(a, include_shift=True)
            (masked_array(data =
             [[[1.0 1.0 1.0 1.0]
              [0.0 0.0 0.0 0.0]
              [0.0 0.0 0.0 0.0]]
            <BLANKLINE>
             [[1.0 1.0 1.0 1.0]
              [0.0 0.0 0.0 0.0]
              [0.0 0.0 0.0 0.0]]
            <BLANKLINE>
             [[-- -- -- --]
              [0.0 0.0 0.0 0.0]
              [0.0 0.0 0.0 0.0]]
            <BLANKLINE>
             [[1.0 1.0 1.0 1.0]
              [0.0 0.0 0.0 0.0]
              [0.0 0.0 0.0 0.0]]
            <BLANKLINE>
             [[1.0 1.0 1.0 1.0]
              [0.0 0.0 0.0 0.0]
              [0.0 0.0 0.0 0.0]]],
                         mask =
             [[[False False False False]
              [False False False False]
              [False False False False]]
            <BLANKLINE>
             [[False False False False]
              [False False False False]
              [False False False False]]
            <BLANKLINE>
             [[ True  True  True  True]
              [False False False False]
              [False False False False]]
            <BLANKLINE>
             [[False False False False]
              [False False False False]
              [False False False False]]
            <BLANKLINE>
             [[False False False False]
              [False False False False]
              [False False False False]]],
                   fill_value = 0.0)
            , array([[0, 0],
                   [0, 0],
                   [1, 0],
                   [0, 0],
                   [0, 0]]))
    """

    float_type = numpy.dtype(float_type).type

    # Must be of type float and must be at least 32-bit (smallest complex type
    # uses two 32-bit floats).
    assert issubclass(float_type, numpy.floating)
    assert numpy.dtype(float_type).itemsize >= 4

    # Sadly, there is no easier way to map the two types; so, this is it.
    float_complex_mapping = {
        numpy.float32 : numpy.complex64,
        numpy.float64 : numpy.complex128,
        numpy.float128 : numpy.complex256
    }
    complex_type = float_complex_mapping[float_type]

    if block_frame_length == -1:
        block_frame_length = len(frames2reg)

    tempdir_name = ""
    temporaries_filename = ""
    if isinstance(frames2reg, h5py.Dataset):
        tempdir_name, temporaries_filename = os.path.split(
            os.path.abspath(frames2reg.file.filename)
        )

        temporaries_filename = os.path.splitext(temporaries_filename)[0]
        temporaries_filename += "_".join(
            [
                frames2reg.name.replace("/", "_"),
                "temporaries.h5"
            ]
        )
        temporaries_filename = os.path.join(
            tempdir_name,
            temporaries_filename
        )
    elif (block_frame_length != len(frames2reg)):
        tempdir_name = tempfile.mkdtemp()
        temporaries_filename = os.path.join(tempdir_name, "temporaries.h5")

    frames2reg_fft = None
    space_shift = None
    this_space_shift = None
    if tempdir_name:
        temporaries_file = h5py.File(temporaries_filename, "w")

        frames2reg_fft = temporaries_file.create_dataset(
            "frames2reg_fft", shape=frames2reg.shape, dtype=complex_type
        )
        space_shift = temporaries_file.create_dataset(
            "space_shift",
            shape=(len(frames2reg), len(frames2reg.shape)-1),
            dtype=int
        )
        this_space_shift = temporaries_file.create_dataset(
            "this_space_shift",
            shape=space_shift.shape,
            dtype=space_shift.dtype
        )
    else:
        frames2reg_fft = numpy.empty(frames2reg.shape, dtype=complex_type)
        space_shift = numpy.zeros(
            (len(frames2reg), len(frames2reg.shape)-1), dtype=int
        )
        this_space_shift = numpy.empty_like(space_shift)

    for i, j in iters.lagged_generators_zipped(
            itertools.chain(
                xrange(0, len(frames2reg), block_frame_length),
                [len(frames2reg)]
            )
    ):
        frames2reg_fft[i:j] = fft.fftn(
            frames2reg[i:j], axes=range(1, len(frames2reg.shape)))
    template_fft = numpy.empty(frames2reg.shape[1:], dtype=complex_type)

    negative_wave_vector = numpy.asarray(template_fft.shape, dtype=float_type)
    numpy.reciprocal(negative_wave_vector, out=negative_wave_vector)
    negative_wave_vector *= 2*numpy.pi
    numpy.negative(negative_wave_vector, out=negative_wave_vector)

    template_fft_indices = xnumpy.cartesian_product(
        [numpy.arange(_) for _ in template_fft.shape])

    unit_space_shift_fft = template_fft_indices * negative_wave_vector
    unit_space_shift_fft = unit_space_shift_fft.T.copy()
    unit_space_shift_fft = unit_space_shift_fft.reshape(
        (template_fft.ndim,) + template_fft.shape)

    negative_wave_vector = None
    template_fft_indices = None

    # Repeat shift calculation until there is no further adjustment.
    num_iters = 0
    squared_magnitude_delta_space_shift = 1.0
    while (squared_magnitude_delta_space_shift != 0.0):
        squared_magnitude_delta_space_shift = 0.0

        template_fft[:] = 0
        for i, j in iters.lagged_generators_zipped(
                itertools.chain(
                        xrange(0, len(frames2reg), block_frame_length),
                        [len(frames2reg)]
                )
        ):
            frames2reg_shifted_fft_ij = numpy.exp(
                1j * numpy.tensordot(
                        space_shift[i:j],
                        unit_space_shift_fft,
                        axes=[-1, 0]
                     )
            )
            frames2reg_shifted_fft_ij *= frames2reg_fft[i:j]
            template_fft += numpy.sum(frames2reg_shifted_fft_ij, axis=0)
        template_fft /= len(frames2reg)

        for i, j in iters.lagged_generators_zipped(
                itertools.chain(
                    xrange(0, len(frames2reg), block_frame_length),
                    [len(frames2reg)]
                )
        ):
            this_space_shift[i:j] = find_offsets(
                frames2reg_fft[i:j], template_fft
            )

        # Remove global shifts.
        this_space_shift_mean = numpy.zeros(
            this_space_shift.shape[1:], dtype=this_space_shift.dtype)
        for i, j in iters.lagged_generators_zipped(
                itertools.chain(
                    xrange(0, len(frames2reg), block_frame_length),
                    [len(frames2reg)]
                )
        ):
            this_space_shift_mean = this_space_shift[i:j].sum(axis=0)
        this_space_shift_mean = numpy.round(
            this_space_shift_mean.astype(float_type) / len(this_space_shift)
        ).astype(int)
        for i, j in iters.lagged_generators_zipped(
                itertools.chain(
                    xrange(0, len(frames2reg), block_frame_length),
                    [len(frames2reg)]
                )
        ):
            this_space_shift[i:j] = xnumpy.find_relative_offsets(
                this_space_shift[i:j],
                this_space_shift_mean
            )

        # Find the shortest roll possible (i.e. if it is going over halfway
        # switch direction so it will go less than half).
        # Note all indices by definition were positive semi-definite and upper
        # bounded by the shape. This change will make them bound by
        # the half shape, but with either sign.
        for i, j in iters.lagged_generators_zipped(
                itertools.chain(
                    xrange(0, len(frames2reg), block_frame_length),
                    [len(frames2reg)]
                )
        ):
            this_space_shift[i:j] = xnumpy.find_shortest_wraparound(
                this_space_shift[i:j],
                frames2reg_fft.shape[1:]
            )

        for i, j in iters.lagged_generators_zipped(
                itertools.chain(
                    xrange(0, len(frames2reg), block_frame_length),
                    [len(frames2reg)]
                )
        ):
            delta_space_shift_ij = this_space_shift[i:j] - space_shift[i:j]
            squared_magnitude_delta_space_shift += numpy.dot(
                delta_space_shift_ij, delta_space_shift_ij.T
            ).sum()

        for i, j in iters.lagged_generators_zipped(
                itertools.chain(
                    xrange(0, len(frames2reg), block_frame_length),
                    [len(frames2reg)]
                )
        ):
            space_shift[i:j] = this_space_shift[i:j]

        num_iters += 1
        logger.info(
            "Completed iteration, %i, " %
            num_iters
            + "where the L_2 norm squared of the relative shift was, %f." %
            squared_magnitude_delta_space_shift
        )
        if max_iters != -1:
            if num_iters >= max_iters:
                logger.info("Hit maximum number of iterations.")
                break

    reg_frames_shape = frames2reg.shape
    if to_truncate:
        space_shift_max = numpy.zeros(
            space_shift.shape[1:], dtype=space_shift.dtype
        )
        space_shift_min = numpy.zeros(
            space_shift.shape[1:], dtype=space_shift.dtype
        )
        for i, j in iters.lagged_generators_zipped(
                itertools.chain(
                    xrange(0, len(frames2reg), block_frame_length),
                    [len(frames2reg)]
                )
        ):
            numpy.maximum(
                space_shift_max,
                space_shift[i:j].max(axis=0),
                out=space_shift_max
            )
            numpy.minimum(
                space_shift_min,
                space_shift[i:j].min(axis=0),
                out=space_shift_min
            )
        reg_frames_shape = numpy.asarray(reg_frames_shape)
        reg_frames_shape[1:] -= space_shift_max
        reg_frames_shape[1:] += space_shift_min
        reg_frames_shape = tuple(reg_frames_shape)

        space_shift_max = tuple(space_shift_max)
        space_shift_min = space_shift_min.astype(object)
        space_shift_min[space_shift_min == 0] = None
        space_shift_min = tuple(space_shift_min)
        reg_frames_slice = tuple(
            slice(_1, _2) for _1, _2 in itertools.izip(
                space_shift_max, space_shift_min
            )
        )

    # Adjust the registered frames using the translations found.
    # Mask rolled values.
    reg_frames = None
    if tempdir_name:
        if to_truncate:
            reg_frames = temporaries_file.create_dataset(
                "reg_frames",
                shape=reg_frames_shape,
                dtype=frames2reg.dtype,
                chunks=True
            )
        else:
            reg_frames = temporaries_file.create_group("reg_frames")
            reg_frames = hdf5.serializers.HDF5MaskedDataset(
                reg_frames, shape=frames2reg.shape, dtype=frames2reg.dtype
            )
    else:
        if to_truncate:
            reg_frames = numpy.empty(reg_frames_shape, dtype=frames2reg.dtype)
        else:
            reg_frames = numpy.ma.empty_like(frames2reg)
            reg_frames.mask = numpy.ma.getmaskarray(reg_frames)
            reg_frames.set_fill_value(reg_frames.dtype.type(0))

    for i, j in iters.lagged_generators_zipped(
            itertools.chain(
                xrange(0, len(frames2reg), block_frame_length),
                [len(frames2reg)]
            )
    ):
        for k in xrange(i, j):
            if to_truncate:
                reg_frames[k] = xnumpy.roll(
                    frames2reg[k], space_shift[k])[reg_frames_slice]
            else:
                reg_frames[k] = xnumpy.roll(
                    frames2reg[k], space_shift[k], to_mask=True)

    result = None
    results_filename = ""
    if tempdir_name:
        result = results_filename
        results_filename = os.path.join(tempdir_name, "results.h5")
        results_file = h5py.File(results_filename, "w")
        if to_truncate:
            temporaries_file.copy(reg_frames.name, results_file)
        else:
            temporaries_file.copy(reg_frames.group, results_file)
        if include_shift:
            temporaries_file.copy(space_shift, results_file)
        frames2reg_fft = None
        reg_frames = None
        space_shift = None
        this_space_shift = None
        temporaries_file.close()
        os.remove(temporaries_filename)
        temporaries_filename = ""
        result = results_filename
    else:
        result = reg_frames
        if include_shift:
            result = (reg_frames, space_shift)

    if tempdir_name:
        results_file.close()
        results_file = None

    return(result)
Exemplo n.º 34
0
def ir2tf(imp_resp, shape, dim=None, is_real=True):
    """Compute the transfer function of an impulse response (IR).

    This function makes the necessary correct zero-padding, zero
    convention, correct fft2, etc... to compute the transfer function
    of IR. To use with unitary Fourier transform for the signal (ufftn
    or equivalent).

    Parameters
    ----------
    imp_resp : ndarray
        The impulse responses.
    shape : tuple of int
        A tuple of integer corresponding to the target shape of the
        transfer function.
    dim : int, optional
        The last axis along which to compute the transform. All
        axes by default.
    is_real : boolean (optional, default True)
       If True, imp_resp is supposed real and the Hermitian property
       is used with rfftn Fourier transform.

    Returns
    -------
    y : complex ndarray
       The transfer function of shape ``shape``.

    See Also
    --------
    ufftn, uifftn, urfftn, uirfftn

    Examples
    --------
    >>> np.all(np.array([[4, 0], [0, 0]]) == ir2tf(np.ones((2, 2)), (2, 2)))
    True
    >>> ir2tf(np.ones((2, 2)), (512, 512)).shape == (512, 257)
    True
    >>> ir2tf(np.ones((2, 2)), (512, 512), is_real=False).shape == (512, 512)
    True

    Notes
    -----
    The input array can be composed of multiple-dimensional IR with
    an arbitrary number of IR. The individual IR must be accessed
    through the first axes. The last ``dim`` axes contain the space
    definition.
    """
    if not dim:
        dim = imp_resp.ndim
    # Zero padding and fill
    irpadded = np.zeros(shape)
    irpadded[tuple([slice(0, s) for s in imp_resp.shape])] = imp_resp
    # Roll for zero convention of the fft to avoid the phase
    # problem. Work with odd and even size.
    for axis, axis_size in enumerate(imp_resp.shape):
        if axis >= imp_resp.ndim - dim:
            irpadded = np.roll(irpadded,
                               shift=-int(np.floor(axis_size / 2)),
                               axis=axis)
    if is_real:
        return rfftn(irpadded, axes=range(-dim, 0))
    else:
        return fftn(irpadded, axes=range(-dim, 0))
Exemplo n.º 35
0
def _register_translation(src_image, target_image, upsample_factor=1,
                          space="real"):
    """
    *****************************************
    From skimage.feature.register_translation
    *****************************************
    Efficient subpixel image translation registration by cross-correlation.
    This code gives the same precision as the FFT upsampled cross-correlation
    in a fraction of the computation time and with reduced memory requirements.
    It obtains an initial estimate of the cross-correlation peak by an FFT and
    then refines the shift estimation by upsampling the DFT only in a small
    neighborhood of that estimate by means of a matrix-multiply DFT.
    Parameters
    ----------
    src_image : ndarray
        Reference image.
    target_image : ndarray
        Image to register.  Must be same dimensionality as ``src_image``.
    upsample_factor : int, optional
        Upsampling factor. Images will be registered to within
        ``1 / upsample_factor`` of a pixel. For example
        ``upsample_factor == 20`` means the images will be registered
        within 1/20th of a pixel.  Default: 1 (no upsampling).
    space : string, one of "real" or "fourier"
        Defines how the algorithm interprets input data.  "real" means data
        will be FFT'd to compute the correlation, while "fourier" data will
        bypass FFT of input data.  Case insensitive. Default: "real".

    Returns
    -------
    shifts : ndarray
        Shift vector (in pixels) required to register ``target_image`` with
        ``src_image``.  Axis ordering is consistent with numpy (e.g. Z, Y, X)
    error : float
        Translation invariant normalized RMS error between ``src_image`` and
        ``target_image``.
    phasediff : float
        Global phase difference between the two images (should be
        zero if images are non-negative).
    References
    ----------
    .. [1] Manuel Guizar-Sicairos, Samuel T. Thurman, and James R. Fienup,
           "Efficient subpixel image registration algorithms,"
           Optics Letters 33, 156-158 (2008).
    """

    # images must be the same shape
    if src_image.shape != target_image.shape:
        raise ValueError("Error: images must be same size for "
                         "register_translation")

    # only 2D data makes sense right now
    if src_image.ndim != 2 and upsample_factor > 1:
        raise NotImplementedError("Error: register_translation only supports "
                                  "subpixel registration for 2D images")

    # assume complex data is already in Fourier space
    if space.lower() == 'fourier':
        src_freq = src_image
        target_freq = target_image
    # real data needs to be fft'd.
    elif space.lower() == 'real':
        src_image = np.array(src_image, dtype=np.complex128, copy=False)
        target_image = np.array(target_image, dtype=np.complex128, copy=False)
        src_freq = fftn(src_image)
        target_freq = fftn(target_image)
    else:
        raise ValueError("Error: register_translation only knows the \"real\" "
                         "and \"fourier\" values for the ``space`` argument.")

    # Whole-pixel shift - Compute cross-correlation by an IFFT
    shape = src_freq.shape
    image_product = src_freq * target_freq.conj()
    cross_correlation = ifftn(image_product)

    # Locate maximum
    maxima = np.unravel_index(np.argmax(np.abs(cross_correlation)),
                              cross_correlation.shape)
    midpoints = np.array([np.fix(axis_size / 2) for axis_size in shape])

    shifts = np.array(maxima, dtype=np.float64)
    shifts[shifts > midpoints] -= np.array(shape)[shifts > midpoints]

    if upsample_factor == 1:
        src_amp = np.sum(np.abs(src_freq) ** 2) / src_freq.size
        target_amp = np.sum(np.abs(target_freq) ** 2) / target_freq.size
        # CCmax = cross_correlation.max()
    # If upsampling > 1, then refine estimate with matrix multiply DFT
    else:

        # Initial shift estimate in upsampled grid
        shifts = np.round(shifts * upsample_factor) / upsample_factor
        upsampled_region_size = np.ceil(upsample_factor * 1.5)
        # Center of output array at dftshift + 1
        dftshift = np.fix(upsampled_region_size / 2.0)
        upsample_factor = np.array(upsample_factor, dtype=np.float64)
        normalization = (src_freq.size * upsample_factor ** 2)
        # Matrix multiply DFT around the current shift estimate
        sample_region_offset = dftshift - shifts * upsample_factor

        cross_correlation = _upsampled_dft(image_product.conj(),
                                           upsampled_region_size,
                                           upsample_factor,
                                           sample_region_offset).conj()

        cross_correlation /= normalization
        # Locate maximum and map back to original pixel grid
        maxima = np.array(np.unravel_index(
            np.argmax(np.abs(cross_correlation)),
            cross_correlation.shape),
            dtype=np.float64)
        maxima -= dftshift
        shifts = shifts + maxima / upsample_factor
        # CCmax = cross_correlation.max()
        src_amp = _upsampled_dft(src_freq * src_freq.conj(),
                                 1, upsample_factor)[0, 0]
        src_amp /= normalization
        target_amp = _upsampled_dft(target_freq * target_freq.conj(),
                                    1, upsample_factor)[0, 0]
        target_amp /= normalization

    # If its only one row or column the shift along that dimension has no
    # effect. We set to zero.
    for dim in range(src_freq.ndim):
        if shape[dim] == 1:
            shifts[dim] = 0

    return shifts
Exemplo n.º 36
0
import numpy as np

import pyfftw.builders
from pyfftw.interfaces.numpy_fft import fftn
r = np.random.randn(32, 32, 32)

# the following transform will fail if MKL FFT routines are being linked to
# instead of the FFTW ones.  (MKL doesn't support FFT of only 1
# dimension of a 3D array).
# see:  https://github.com/pyFFTW/pyFFTW/issues/40
fftn(r, axes=(0, ))