Exemplo n.º 1
0
    def test_direction_property(self):
        '''Test to see if the direction property returns the correct thing
        '''
        self.assertEqual(self.fft.direction, 'FFTW_FORWARD')

        new_fft = FFTW(self.input_array,
                       self.output_array,
                       direction='FFTW_BACKWARD')

        self.assertEqual(new_fft.direction, 'FFTW_BACKWARD')
Exemplo n.º 2
0
    def test_ortho_property(self):
        '''ortho property defaults to False
        '''
        self.assertEqual(self.fft.ortho, False)

        newfft = FFTW(self.input_array,
                      self.output_array,
                      ortho=True,
                      normalise_idft=False)
        self.assertEqual(newfft.ortho, True)
Exemplo n.º 3
0
    def setUp(self):

        self.input_array = empty_aligned((256, 512), dtype='complex128', n=16)
        self.output_array = empty_aligned((256, 512), dtype='complex128', n=16)

        self.fft = FFTW(self.input_array, self.output_array)

        self.input_array[:] = (
            numpy.random.randn(*self.input_array.shape) +
            1j * numpy.random.randn(*self.input_array.shape))
Exemplo n.º 4
0
    def test_call_with_normalisation_default(self):
        _input_array = empty_aligned((256, 512), dtype='complex128', n=16)

        ifft = FFTW(self.output_array, _input_array, direction='FFTW_BACKWARD')

        self.fft()
        ifft()

        # Scaling is performed by default
        self.assertTrue(numpy.allclose(self.input_array, _input_array))
Exemplo n.º 5
0
    def test_extra_dimension_fail(self):
        in_shape = self.input_shapes['2d']
        _out_shape = self.output_shapes['2d']
        out_shape = (2, _out_shape[0], _out_shape[1])

        axes = (1, )
        a, b = self.create_test_arrays(in_shape, out_shape)

        with self.assertRaisesRegex(ValueError, 'Invalid shapes'):
            FFTW(a, b, direction=self.direction)
Exemplo n.º 6
0
    def test_call_with_ortho_off(self):
        _input_array = empty_aligned((256, 512), dtype='complex128', n=16)

        ifft = FFTW(self.output_array, _input_array, direction='FFTW_BACKWARD')

        self.fft(ortho=False)
        ifft(ortho=False)

        # Scaling by normalise_idft is performed by default
        self.assertTrue(numpy.allclose(self.input_array, _input_array))
Exemplo n.º 7
0
    def test_missized_nonfft_axes_fail(self):
        in_shape = self.input_shapes['3d']
        _out_shape = self.output_shapes['3d']
        out_shape = (_out_shape[0], _out_shape[1] + 1, _out_shape[2])

        axes = (2, )
        a, b = self.create_test_arrays(in_shape, out_shape)

        with self.assertRaisesRegex(ValueError, 'Invalid shapes'):
            FFTW(a, b, direction=self.direction)
Exemplo n.º 8
0
    def test_default_args(self):
        in_shape = self.input_shapes['2d']
        out_shape = self.output_shapes['2d']

        a, b = self.create_test_arrays(in_shape, out_shape)

        # default args should fail for backwards transforms
        # (as the default is FFTW_FORWARD)
        with self.assertRaisesRegex(ValueError, 'Invalid direction'):
            FFTW(a, b)
Exemplo n.º 9
0
    def test_default_args(self):
        in_shape = self.input_shapes['2d']
        out_shape = self.output_shapes['2d']

        a, b = self.create_test_arrays(in_shape, out_shape)

        fft = FFTW(a, b)
        fft.execute()
        ref_b = self.reference_fftn(a, axes=(-1, ))
        self.assertTrue(numpy.allclose(b, ref_b, rtol=1e-2, atol=1e-3))
Exemplo n.º 10
0
    def test_axes_property(self):
        '''Test to see if the axes property returns the correct thing
        '''
        self.assertEqual(self.fft.axes, (1,))

        new_fft = FFTW(self.input_array, self.output_array, axes=(-1, -2))
        self.assertEqual(new_fft.axes, (1, 0))

        new_fft = FFTW(self.input_array, self.output_array, axes=(-2, -1))
        self.assertEqual(new_fft.axes, (0, 1))

        new_fft = FFTW(self.input_array, self.output_array, axes=(1, 0))
        self.assertEqual(new_fft.axes, (1, 0))

        new_fft = FFTW(self.input_array, self.output_array, axes=(1,))
        self.assertEqual(new_fft.axes, (1,))

        new_fft = FFTW(self.input_array, self.output_array, axes=(0,))
        self.assertEqual(new_fft.axes, (0,))
Exemplo n.º 11
0
    def test_call_with_normalisation_off(self):
        _input_array = empty_aligned((256, 512), dtype='complex128', n=16)

        ifft = FFTW(self.output_array, _input_array, direction='FFTW_BACKWARD')

        self.fft(normalise_idft=True)  # Shouldn't make any difference
        ifft(normalise_idft=False)

        _input_array /= ifft.N

        self.assertTrue(numpy.allclose(self.input_array, _input_array))
Exemplo n.º 12
0
    def test_output_dtype(self):
        '''Test to see if the output_dtype property returns the correct thing
        '''
        self.assertEqual(self.fft.output_dtype, self.output_array.dtype)

        new_input_array = numpy.complex64(self.input_array)
        new_output_array = numpy.complex64(self.output_array)

        new_fft = FFTW(new_input_array, new_output_array)

        self.assertEqual(new_fft.output_dtype, new_output_array.dtype)
Exemplo n.º 13
0
    def test_output_strides(self):
        '''Test to see if the output_shape property returns the correct thing
        '''
        self.assertEqual(self.fft.output_shape, self.output_array.shape)

        new_input_array = self.output_array[::2, ::4]
        new_output_array = self.output_array[::2, ::4]

        new_fft = FFTW(new_input_array, new_output_array)

        self.assertEqual(new_fft.output_shape, new_output_array.shape)
Exemplo n.º 14
0
 def test_failure(self):
     for dtype, npdtype in zip(
         ['32', '64', 'ld'], [np.complex64, np.complex128, np.clongdouble]):
         if dtype == 'ld' and np.dtype(np.clongdouble) == np.dtype(
                 np.complex128):
             # skip this test on systems where clongdouble is complex128
             continue
         if dtype not in _supported_types:
             a = empty_aligned((1, 1024), npdtype, n=16)
             b = empty_aligned(a.shape, dtype=a.dtype, n=16)
             msg = "Rebuild pyFFTW with support for %s precision!" % _all_types_human_readable[
                 dtype]
             with self.assertRaisesRegex(NotImplementedError, msg):
                 FFTW(a, b)
Exemplo n.º 15
0
    def test_call_with_copy_with_missized_array_error(self):
        '''Force an input copy with a missized array.
        '''
        shape = list(self.input_array.shape + (2, ))
        shape[0] += 1

        input_array = byte_align(numpy.random.randn(*shape) +
                                 1j * numpy.random.randn(*shape),
                                 n=16)

        fft = FFTW(self.input_array, self.output_array)

        self.assertRaisesRegex(ValueError, 'Invalid input shape', self.fft,
                               **{'input_array': input_array[:, :, 0]})
Exemplo n.º 16
0
    def test_planning_time_limit(self):
        in_shape = self.input_shapes['1d']
        out_shape = self.output_shapes['1d']

        axes = (0, )
        a, b = self.create_test_arrays(in_shape, out_shape)

        # run this a few times
        runs = 10
        t1 = time.time()
        for n in range(runs):
            forget_wisdom()
            fft = FFTW(a, b, axes=axes)

        unlimited_time = (time.time() - t1) / runs

        time_limit = (unlimited_time) / 8

        # Now do it again but with an upper limit on the time
        t1 = time.time()
        for n in range(runs):
            forget_wisdom()
            fft = FFTW(a, b, axes=axes, planning_timelimit=time_limit)

        limited_time = (time.time() - t1) / runs

        import sys
        if sys.platform == 'win32':
            # Give a 6x margin on windows. The timers are low
            # precision and FFTW seems to take longer anyway.
            # Also, we need to allow for processor contention which
            # Appveyor seems prone to.
            self.assertTrue(limited_time < time_limit * 6)
        else:
            # Otherwise have a 2x margin
            self.assertTrue(limited_time < time_limit * 2)
Exemplo n.º 17
0
    def test_call_with_normalisation_precision(self):
        '''The normalisation should use a double precision scaling.
        '''
        # Should be the case for double inputs...
        _input_array = empty_aligned((256, 512), dtype='complex128', n=16)

        ifft = FFTW(self.output_array, _input_array, direction='FFTW_BACKWARD')

        ref_output = ifft(normalise_idft=False).copy() / numpy.float64(ifft.N)
        test_output = ifft(normalise_idft=True).copy()

        self.assertTrue(numpy.alltrue(ref_output == test_output))

        # ... and single inputs.
        _input_array = empty_aligned((256, 512), dtype='complex64', n=16)

        ifft = FFTW(numpy.array(self.output_array, _input_array.dtype),
                    _input_array,
                    direction='FFTW_BACKWARD')

        ref_output = ifft(normalise_idft=False).copy() / numpy.float64(ifft.N)
        test_output = ifft(normalise_idft=True).copy()

        self.assertTrue(numpy.alltrue(ref_output == test_output))
Exemplo n.º 18
0
    def test_call_with_auto_input_alignment(self):
        '''Test the class call with a keyword input update.
        '''
        input_array = (numpy.random.randn(*self.input_array.shape) +
                       1j * numpy.random.randn(*self.input_array.shape))

        output_array = self.fft(
            input_array=byte_align(input_array.copy(), n=16)).copy()

        # Offset by one from 16 byte aligned to guarantee it's not
        # 16 byte aligned
        a = input_array
        a__ = empty_aligned(numpy.prod(a.shape) * a.itemsize + 1,
                            dtype='int8',
                            n=16)

        a_ = a__[1:].view(dtype=a.dtype).reshape(*a.shape)
        a_[:] = a

        # Just confirm that a usual update will fail
        self.assertRaisesRegex(ValueError, 'Invalid input alignment',
                               self.fft.update_arrays,
                               *(a_, self.output_array))

        self.fft(a_, self.output_array)

        self.assertTrue(numpy.alltrue(output_array == self.output_array))

        # now try with a single byte offset and SIMD off
        ar, ai = numpy.float32(numpy.random.randn(2, 257))
        a = ar[1:] + 1j * ai[1:]

        b = a.copy()

        a_size = len(a.ravel()) * a.itemsize

        update_array = numpy.frombuffer(numpy.zeros(a_size + 1,
                                                    dtype='int8')[1:].data,
                                        dtype=a.dtype).reshape(a.shape)

        fft = FFTW(a, b, flags=('FFTW_UNALIGNED', ))
        # Confirm that a usual update will fail (it's not on the
        # byte boundary)
        self.assertRaisesRegex(ValueError, 'Invalid input alignment',
                               fft.update_arrays, *(update_array, b))

        fft(update_array, b)
Exemplo n.º 19
0
def psd(buf_in, buf_out):
    """
    Perform discrete fourier transforms using the FFTW library and use it to
    get the power spectral density. FFTW optimizes
    the fft algorithm based on the size of the arrays, with SIMD parallelized
    commands. This optimization requires initialization, so this is a factory
    function that returns a numba gufunc that performs the FFT. FFTW works on
    fixed memory buffers, so you must tell it what memory to use ahead of time.
    When using this with ProcessingChain, to ensure the correct buffers are used
    call ProcessingChain.get_variable('var_name') to give it the internal memory
    buffer directly (with raw_to_dsp, you can just give it the name and it will
    automatically happen!). The possible dtypes for the input/outputs are:
    - complex64 (size n) -> float32/float (size n) 
    - complex128 (size n) -> float64/double (size n)
    - complex256/clongdouble (size n) -> float128/longdouble (size n)
    - float32/float (size n) -> float32/float (size n/2+1)
    - float64/double (size n) -> float64/double (size n/2+1)
    - float128/longdouble (size n) -> float128/longdouble (size n/2+1)
    """

    # build intermediate array for the dft, which will be abs'd to get the PSD
    buf_dft = np.ndarray(
        buf_out.shape, np.dtype('complex' + str(buf_out.dtype.itemsize * 16)))
    try:
        dft_fun = FFTW(buf_in, buf_dft, axes=(-1, ), direction='FFTW_FORWARD')
    except ValueError:
        raise ValueError("""Incompatible array types/shapes. Allowed:
        - complex64 (size n) -> float32/float (size n) 
        - complex128 (size n) -> float64/double (size n)
        - complex256/clongdouble (size n) -> float128/longdouble (size n)
        - float32/float (size n) -> float32/float (size n/2+1)
        - float64/double (size n) -> float64/double (size n/2+1)
        - float128/longdouble (size n) -> float128/longdouble (size n/2+1)""")

    typesig = 'void(' + str(buf_in.dtype) + '[:, :], ' + str(
        buf_out.dtype) + '[:, :])'
    sizesig = '(m, n)->(m, n)' if buf_in.shape == buf_out.shape else '(m, n),(m, l)'

    @guvectorize([typesig], sizesig, forceobj=True)
    def psd(wf_in, psd_out):
        dft_fun(wf_in, buf_dft)
        np.abs(buf_dft, psd_out)

    return psd
Exemplo n.º 20
0
def inv_dft(buf_in, buf_out):
    """
    Perform inverse discrete fourier transforms using FFTW. FFTW optimizes
    the fft algorithm based on the size of the arrays, with SIMD parallelized
    commands. This optimization requires initialization, so this is a factory
    function that returns a numba gufunc that performs the FFT. FFTW works on
    fixed memory buffers, so you must tell it what memory to use ahead of time.
    When using this with ProcessingChain, to ensure the correct buffers are used
    call ProcessingChain.get_variable('var_name') to give it the internal memory
    buffer directly (with raw_to_dsp, you can just give it the name and it will
    automatically happen!). The possible dtypes for the input/outputs are:
    - complex64 (size n/2+1) -> float32/float (size n) 
    - complex128 (size n/2+1) -> float64/double (size n)
    - complex256/clongdouble (size n/2+1) -> float128/longdouble (size n)
    - complex64 (size n) -> complex64 (size n)
    - complex128 (size n) -> complex128 (size n)
    - complex256/clongdouble (size n) -> complex256/clongdouble (size n)
    """

    try:
        idft_fun = FFTW(buf_in,
                        buf_out,
                        axes=(-1, ),
                        direction='FFTW_BACKWARD')
    except ValueError:
        raise ValueError("""Incompatible array types/shapes. Allowed:
        - complex64 (size n/2+1) -> float32/float (size n) 
        - complex128 (size n/2+1) -> float64/double (size n)
        - complex256/clongdouble (size n/2+1) -> float128/longdouble (size n)
        - complex64 (size n) -> complex64 (size n)
        - complex128 (size n) -> complex128 (size n)
        - complex256/clongdouble (size n) -> complex256/clongdouble (size n)"""
                         )

    typesig = 'void(' + str(buf_in.dtype) + '[:, :], ' + str(
        buf_out.dtype) + '[:, :])'
    sizesig = '(m, n)->(m, n)' if buf_in.shape == buf_out.shape else '(m, n),(m, l)'

    @guvectorize([typesig], sizesig, forceobj=True)
    def inv_dft(wf_in, dft_out):
        idft_fun(wf_in, dft_out)

    return inv_dft
Exemplo n.º 21
0
    def test_call_with_different_striding(self):
        '''Test the input update with different strides to internal array.
        '''
        shape = self.input_array.shape + (2, )

        input_array = byte_align(numpy.random.randn(*shape) +
                                 1j * numpy.random.randn(*shape),
                                 n=16)

        fft = FFTW(input_array[:, :, 0], self.output_array)

        test_output_array = fft().copy()

        new_input_array = byte_align(input_array[:, :, 0].copy(), n=16)

        new_output = fft(new_input_array).copy()

        # Test the test!
        self.assertTrue(
            new_input_array.strides != input_array[:, :, 0].strides)

        self.assertTrue(numpy.alltrue(test_output_array == new_output))
Exemplo n.º 22
0
def cryo_epsdr(vol, samples_idx, max_d):
    p = vol.shape[0]
    k = vol.shape[2]
    i, j = np.meshgrid(np.arange(max_d + 1), np.arange(max_d + 1))
    dists = np.square(i) + np.square(j)
    dsquare = np.sort(np.unique(dists[np.where(dists <= max_d**2)]))

    corrs = np.zeros(len(dsquare))
    corr_count = np.zeros(len(dsquare))
    x = np.sqrt(dsquare)

    dist_map = np.zeros(dists.shape)
    for i in range(max_d + 1):
        for j in range(max_d + 1):
            d = i**2 + j**2
            if d <= max_d**2:
                idx, _ = bsearch(dsquare, d - 1e-13, d + 1e-13)
                dist_map[i, j] = idx

    dist_map = dist_map.astype('int') - 1
    valid_dists = np.where(dist_map != -1)

    mask = np.zeros((p, p))
    mask[samples_idx] = 1
    tmp = np.zeros((2 * p + 1, 2 * p + 1))
    tmp[:p, :p] = mask
    ftmp = fft2(tmp)
    c = ifft2(ftmp * np.conj(ftmp))
    c = c[:max_d + 1, :max_d + 1]
    c = np.round(c.real).astype('int')

    r = np.zeros(len(corrs))

    # optimized version
    vol = vol.transpose((2, 0, 1)).copy()
    input_fft2 = np.zeros((2 * p + 1, 2 * p + 1), dtype='complex128')
    output_fft2 = np.zeros((2 * p + 1, 2 * p + 1), dtype='complex128')
    input_ifft2 = np.zeros((2 * p + 1, 2 * p + 1), dtype='complex128')
    output_ifft2 = np.zeros((2 * p + 1, 2 * p + 1), dtype='complex128')
    flags = ('FFTW_MEASURE', 'FFTW_UNALIGNED')
    a_fft2 = FFTW(input_fft2,
                  output_fft2,
                  axes=(0, 1),
                  direction='FFTW_FORWARD',
                  flags=flags)
    a_ifft2 = FFTW(input_ifft2,
                   output_ifft2,
                   axes=(0, 1),
                   direction='FFTW_BACKWARD',
                   flags=flags)
    sum_s = np.zeros(output_ifft2.shape, output_ifft2.dtype)
    sum_c = c * vol.shape[0]
    for i in range(k):
        proj = vol[i]

        input_fft2[samples_idx] = proj[samples_idx]
        a_fft2()
        np.multiply(output_fft2, np.conj(output_fft2), out=input_ifft2)
        a_ifft2()
        sum_s += output_ifft2

    for curr_dist in zip(valid_dists[0], valid_dists[1]):
        dmidx = dist_map[curr_dist]
        corrs[dmidx] += sum_s[curr_dist].real
        corr_count[dmidx] += sum_c[curr_dist]

    idx = np.where(corr_count != 0)[0]
    r[idx] += corrs[idx] / corr_count[idx]
    cnt = corr_count[idx]

    idx = np.where(corr_count == 0)[0]
    r[idx] = 0
    x[idx] = 0
    return r, x, cnt
Exemplo n.º 23
0
    def test_differing_aligned_arrays_update(self):
        '''Test to see if the alignment code is working as expected
        '''

        # Start by creating arrays that are only on various byte
        # alignments (4, 16 and 32)
        _input_array = empty_aligned(len(self.input_array.ravel())*2+5,
                                     dtype='float32', n=32)
        _output_array = empty_aligned(len(self.output_array.ravel())*2+5,
                                      dtype='float32', n=32)

        _input_array[:] = 0
        _output_array[:] = 0

        input_array_4 = (
                numpy.frombuffer(_input_array[1:-4].data, dtype='complex64')
                .reshape(self.input_array.shape))
        output_array_4 = (
                numpy.frombuffer(_output_array[1:-4].data, dtype='complex64')
                .reshape(self.output_array.shape))

        input_array_16 = (
                numpy.frombuffer(_input_array[4:-1].data, dtype='complex64')
                .reshape(self.input_array.shape))
        output_array_16 = (
                numpy.frombuffer(_output_array[4:-1].data, dtype='complex64')
                .reshape(self.output_array.shape))

        input_array_32 = (
                numpy.frombuffer(_input_array[:-5].data, dtype='complex64')
                .reshape(self.input_array.shape))
        output_array_32 = (
                numpy.frombuffer(_output_array[:-5].data, dtype='complex64')
                .reshape(self.output_array.shape))

        input_arrays = {4: input_array_4,
                16: input_array_16,
                32: input_array_32}

        output_arrays = {4: output_array_4,
                16: output_array_16,
                32: output_array_32}

        alignments = (4, 16, 32)

        # Test the arrays are aligned on 4 bytes...
        self.assertTrue(is_byte_aligned(input_arrays[4], n=4))
        self.assertTrue(is_byte_aligned(output_arrays[4], n=4))

        # ...and on 16...
        self.assertFalse(is_byte_aligned(input_arrays[4], n=16))
        self.assertFalse(is_byte_aligned(output_arrays[4], n=16))
        self.assertTrue(is_byte_aligned(input_arrays[16], n=16))
        self.assertTrue(is_byte_aligned(output_arrays[16], n=16))

        # ...and on 32...
        self.assertFalse(is_byte_aligned(input_arrays[16], n=32))
        self.assertFalse(is_byte_aligned(output_arrays[16], n=32))
        self.assertTrue(is_byte_aligned(input_arrays[32], n=32))
        self.assertTrue(is_byte_aligned(output_arrays[32], n=32))

        if len(pyfftw.pyfftw._valid_simd_alignments) > 0:
            max_align = pyfftw.pyfftw._valid_simd_alignments[0]
        else:
            max_align = simd_alignment

        for in_align in alignments:
            for out_align in alignments:
                expected_align = min(in_align, out_align, max_align)
                fft = FFTW(input_arrays[in_align], output_arrays[out_align])

                self.assertTrue(fft.input_alignment == expected_align)
                self.assertTrue(fft.output_alignment == expected_align)

                for update_align in alignments:

                    if update_align < expected_align:
                        # This should fail (not aligned properly)
                        self.assertRaisesRegex(ValueError,
                                'Invalid input alignment',
                                fft.update_arrays,
                                input_arrays[update_align],
                                output_arrays[out_align])

                        self.assertRaisesRegex(ValueError,
                                'Invalid output alignment',
                                fft.update_arrays,
                                input_arrays[in_align],
                                output_arrays[update_align])

                    else:
                        # This should work (and not segfault!)
                        fft.update_arrays(input_arrays[update_align],
                                output_arrays[out_align])
                        fft.update_arrays(input_arrays[in_align],
                                output_arrays[update_align])
                        fft.execute()
Exemplo n.º 24
0
def cryo_epsdr(image, samples_idx, max_d):
    """
    Estimate the 1D isotropic autocorrelation of an image. The samples to use
    are given in samples_idx. The correlation is computed up to a maximal
    distance of max_d.

    Parameters
    ----------
    image : numpy.ndarray
        square pxp image.
    samples_idx : tuple
        pixel indices to use for autocorrelation estimation.
    max_d : int
        Correlations are computed up to a maximal distance of max_d pixels.
        Default p-1.

    Returns
    -------
    r : numpy.ndarray
        1D vector with samples of the isotropic autocorrelation function.
    x : numpy.ndarray
        Distaces at which the samples of the autocorrelation function are
        given. A vector of the same length as R.
    cnt : numpy.ndarray
        Number of autocorrelation samples available for each distance.

    """
    p = image.shape[0]
    
    # Generate all possible squared distances. For a vertical shift i and 
    # horizontal shift j, dists(i,j) contains the corresponding isotropic 
    # correlation distance i^2+j^2. dsquare is then the set of all possible 
    # squared distances, that is, all distances that can be generated by 
    # integer steps in the horizontal and vertical directions.
    i = np.array([[x for x in range(max_d + 1)] for x in range(max_d + 1)])
    dists = i ** 2 + i.transpose() ** 2
    dsquare = np.sort(np.unique(dists[np.where(dists <= max_d ** 2)]))
    x = dsquare ** 0.5 # Distances at which the correlations are computed.
    
    # Create a distance map whose value at the index (i,j) is the index in the
    # array dsquare whose value is i^2+j^2. Pairs (i,j) that correspond to
    # distances that are larger than max_d are indicated by (-1).   
    dist_map = distmap(max_d, dsquare, dists.shape)
    valid_dists = np.where(dist_map != -1)

    # Compute the number of terms in the expression sum_{j}x(j)x(j+d) for each
    # distance d. As the correlation is two-dimensioanl, we compute for each
    # sum of the form  R(k1,k2)=sum_{i,j} X_{i,j} X_{i+k1,j+k2}, how many 
    # summands are in the in it for each (k1,k2). This is done by setting the
    # participating image samples to 1 and computing autocorrelation again.
    mask = np.zeros((p, p))
    mask[samples_idx] = 1
    tmp = np.zeros((2 * p + 1, 2 * p + 1))
    tmp[:p, :p] = mask
    ftmp = fft2(tmp)
    c = ifft2(ftmp * np.conj(ftmp))
    c = c[:max_d + 1, :max_d + 1]
    c = np.round(c.real).astype('int') 

    r = np.zeros(len(dsquare)) # r(i) is the value of the ACF at distance x(i)
    
    # Compute non-periodic autocorrelation of masked image with itself (mask
    # all pixels that are not used to autocorrelation estimation).
    input_fft2 = np.zeros((2 * p + 1, 2 * p + 1), dtype='complex128')
    output_fft2 = np.zeros((2 * p + 1, 2 * p + 1), dtype='complex128')
    input_ifft2 = np.zeros((2 * p + 1, 2 * p + 1), dtype='complex128')
    output_ifft2 = np.zeros((2 * p + 1, 2 * p + 1), dtype='complex128')
    flags = ('FFTW_MEASURE', 'FFTW_UNALIGNED')
    a_fft2 = FFTW(input_fft2, output_fft2, axes=(0, 1), direction='FFTW_FORWARD', flags=flags)
    a_ifft2 = FFTW(input_ifft2, output_ifft2, axes=(0, 1), direction='FFTW_BACKWARD', flags=flags)
    sum_c = c
    
    input_fft2[samples_idx] = image[samples_idx]
    a_fft2()
    np.multiply(output_fft2, np.conj(output_fft2), out=input_ifft2)
    a_ifft2()
    sum_s = output_ifft2
    
    # Accumulate all autocorrelation values R(k1,k2) such that k1^2+k2^2=const 
    # (all autocorrelations of a certain distance).
    # corrs(i) contains the sum of all products of the form x(j)x(j+d), where
    # d=sqrt(dsquare(i)).
    # corr_count is the number of pairs x(j)x(j+d) for each d.
    corr_count, corrs = accumelate_corrs(len(dsquare), valid_dists, dist_map, sum_c, sum_s)

    # Remove zero correlation sums (distances for which we had no samples at 
    # that distance)
    idx = np.where(corr_count != 0)[0]
    r[idx] += corrs[idx] / corr_count[idx]
    cnt = corr_count[idx]
    idx = np.where(corr_count == 0)[0]
    r[idx] = 0
    x[idx] = 0
    return r, x, cnt
Exemplo n.º 25
0
    def __init__(self,
                 nfft,
                 D=1,
                 analysis_window=None,
                 synthesis_window=None,
                 transform='numpy',
                 axis=0,
                 bits=32):

        self.nfft = nfft
        self.D = D
        self.axis = axis

        if bits == 32:
            time_dtype = 'float32'
            freq_dtype = 'complex64'
        elif bits == 64:
            time_dtype = 'float64'
            freq_dtype = 'complex128'
        else:
            raise ValueError("Invalid number of bits. Must be 32 or 64.")

        if axis == 0:
            self.x = np.squeeze(np.zeros((self.nfft, self.D),
                                         dtype=time_dtype))
            self.X = np.squeeze(
                np.zeros((self.nfft // 2 + 1, self.D), dtype=freq_dtype))
        elif axis == 1:
            self.x = np.squeeze(np.zeros((self.D, self.nfft),
                                         dtype=time_dtype))
            self.X = np.squeeze(
                np.zeros((self.D, self.nfft // 2 + 1), dtype=freq_dtype))
        else:
            raise ValueError("Invalid 'axis' option. Must be 0 or 1.")

        if analysis_window is not None:
            if axis == 0 and D > 1:
                self.analysis_window = analysis_window[:, np.newaxis].astype(
                    time_dtype)
            else:
                self.analysis_window = analysis_window.astype(time_dtype)
        else:
            self.analysis_window = None

        if synthesis_window is not None:
            if axis == 0 and D > 1:
                self.synthesis_window = synthesis_window[:, np.newaxis].astype(
                    time_dtype)
            else:
                self.synthesis_window = synthesis_window.astype(time_dtype)
        else:
            self.synthesis_window = None

        if transform == 'fftw':
            if pyfftw_available:
                from pyfftw import empty_aligned, FFTW
                self.transform = transform
                # allocate input (real) and output for pyfftw
                if self.D == 1:
                    self.a = empty_aligned(self.nfft, dtype=time_dtype)
                    self.b = empty_aligned(self.nfft // 2 + 1,
                                           dtype=freq_dtype)
                    self._forward = FFTW(self.a, self.b)
                    self._backward = FFTW(self.b,
                                          self.a,
                                          direction='FFTW_BACKWARD')
                else:
                    if axis == 0:
                        self.a = empty_aligned([self.nfft, self.D],
                                               dtype=time_dtype)
                        self.b = empty_aligned([self.nfft // 2 + 1, self.D],
                                               dtype=freq_dtype)
                    elif axis == 1:
                        self.a = empty_aligned([self.D, self.nfft],
                                               dtype=time_dtype)
                        self.b = empty_aligned([self.D, self.nfft // 2 + 1],
                                               dtype=freq_dtype)
                    self._forward = FFTW(self.a, self.b, axes=(self.axis, ))
                    self._backward = FFTW(self.b,
                                          self.a,
                                          axes=(self.axis, ),
                                          direction='FFTW_BACKWARD')
            else:
                warnings.warn(
                    "Could not import pyfftw wrapper for fftw functions. Using numpy's rfft instead."
                )
                self.transform = 'numpy'
        elif transform == 'mkl':
            if mkl_available:
                import mkl_fft
                self.transform = 'mkl'
            else:
                warnings.warn(
                    "Could not import mkl wrapper. Using numpy's rfft instead."
                )
                self.transform = 'numpy'
        else:
            self.transform = 'numpy'
Exemplo n.º 26
0
 def generate_wisdom(self):
     for each_dtype in _supported_nptypes_complex:
         n = 16
         a = empty_aligned((1, 1024), each_dtype, n=n)
         b = empty_aligned(a.shape, dtype=a.dtype, n=n)
         fft = FFTW(a, b)
Exemplo n.º 27
0
 def do_fft(self, inputa):
   outputa = np.zeros(self.fft_size, dtype=complex)
   fft_plan = FFTW(inputa, outputa, direction='FFTW_FORWARD')
   #fft_plan = FFTW.Plan(inputa, outputa, direction='forward', flags=['estimate'])
   fft_plan.execute()
   return (np.log10(np.abs(outputa)) * 20)[:self.fft_size/2]
Exemplo n.º 28
0
    def run_validate_fft(self,
                         a,
                         b,
                         axes,
                         fft=None,
                         ifft=None,
                         force_unaligned_data=False,
                         create_array_copies=True,
                         threads=1,
                         flags=('FFTW_ESTIMATE', )):
        ''' Run a validation of the FFTW routines for the passed pair
        of arrays, a and b, and the axes argument.

        a and b are assumed to be the same shape (but not necessarily
        the same layout in memory).

        fft and ifft, if passed, should be instantiated FFTW objects.

        If force_unaligned_data is True, the flag FFTW_UNALIGNED
        will be passed to the fftw routines.

        The threads argument runs the validation with multiple threads.

        flags is passed to the creation of the FFTW object.
        '''

        if create_array_copies:
            # Don't corrupt the original mutable arrays
            a = a.copy()
            b = b.copy()

        a_orig = a.copy()

        flags = list(flags)

        if force_unaligned_data:
            flags.append('FFTW_UNALIGNED')

        if fft == None:
            fft = FFTW(a,
                       b,
                       axes=axes,
                       direction='FFTW_FORWARD',
                       flags=flags,
                       threads=threads)
        else:
            fft.update_arrays(a, b)

        if ifft == None:
            ifft = FFTW(b,
                        a,
                        axes=axes,
                        direction='FFTW_BACKWARD',
                        flags=flags,
                        threads=threads)
        else:
            ifft.update_arrays(b, a)

        a[:] = a_orig

        # Test the forward FFT by comparing it to the result from numpy.fft
        fft.execute()
        ref_b = self.reference_fftn(a, axes=axes)

        # This is actually quite a poor relative error, but it still
        # sometimes fails. I assume that numpy.fft has different internals
        # to fftw.
        self.assertTrue(numpy.allclose(b, ref_b, rtol=1e-2, atol=1e-3))

        # Test the inverse FFT by comparing the result to the starting
        # value (which is scaled as per FFTW being unnormalised).
        ifft.execute()
        # The scaling is the product of the lengths of the fft along
        # the axes along which the fft is taken.
        scaling = numpy.prod(numpy.array(a.shape)[list(axes)])

        self.assertEqual(ifft.N, scaling)
        self.assertEqual(fft.N, scaling)

        self.assertTrue(
            numpy.allclose(a / scaling, a_orig, rtol=1e-2, atol=1e-3))
        return fft, ifft
Exemplo n.º 29
0
    def __init__(
        self,
        nfft,
        D=1,
        analysis_window=None,
        synthesis_window=None,
        transform="numpy",
        axis=0,
        precision="double",
        bits=None,
    ):

        self.nfft = nfft
        self.D = D
        self.axis = axis

        if bits is not None and precision is not None:
            warnings.warn(
                'Deprecated keyword "bits" ignored in favor of new keyword "precision"',
                DeprecationWarning,
            )
        elif bits is not None and precision is None:
            warnings.warn(
                'Keyword "bits" is deprecated and has been replaced by "precision"'
            )
            if bits == 32:
                precision = "single"
            elif bits == 64:
                precision = "double"

        if (
            precision == np.float32
            or precision == np.complex64
            or precision == "single"
        ):
            time_dtype = np.float32
            freq_dtype = np.complex64
        else:
            time_dtype = np.float64
            freq_dtype = np.complex128

        if axis == 0:
            self.x = np.squeeze(np.zeros((self.nfft, self.D), dtype=time_dtype))
            self.X = np.squeeze(
                np.zeros((self.nfft // 2 + 1, self.D), dtype=freq_dtype)
            )
        elif axis == 1:
            self.x = np.squeeze(np.zeros((self.D, self.nfft), dtype=time_dtype))
            self.X = np.squeeze(
                np.zeros((self.D, self.nfft // 2 + 1), dtype=freq_dtype)
            )
        else:
            raise ValueError("Invalid 'axis' option. Must be 0 or 1.")

        if analysis_window is not None:
            if axis == 0 and D > 1:
                self.analysis_window = analysis_window[:, np.newaxis].astype(time_dtype)
            else:
                self.analysis_window = analysis_window.astype(time_dtype)
        else:
            self.analysis_window = None

        if synthesis_window is not None:
            if axis == 0 and D > 1:
                self.synthesis_window = synthesis_window[:, np.newaxis].astype(
                    time_dtype
                )
            else:
                self.synthesis_window = synthesis_window.astype(time_dtype)
        else:
            self.synthesis_window = None

        if transform == "fftw":
            if pyfftw_available:
                from pyfftw import empty_aligned, FFTW

                self.transform = transform
                # allocate input (real) and output for pyfftw
                if self.D == 1:
                    self.a = empty_aligned(self.nfft, dtype=time_dtype)
                    self.b = empty_aligned(self.nfft // 2 + 1, dtype=freq_dtype)
                    self._forward = FFTW(self.a, self.b)
                    self._backward = FFTW(self.b, self.a, direction="FFTW_BACKWARD")
                else:
                    if axis == 0:
                        self.a = empty_aligned([self.nfft, self.D], dtype=time_dtype)
                        self.b = empty_aligned(
                            [self.nfft // 2 + 1, self.D], dtype=freq_dtype
                        )
                    elif axis == 1:
                        self.a = empty_aligned([self.D, self.nfft], dtype=time_dtype)
                        self.b = empty_aligned(
                            [self.D, self.nfft // 2 + 1], dtype=freq_dtype
                        )
                    self._forward = FFTW(self.a, self.b, axes=(self.axis,))
                    self._backward = FFTW(
                        self.b, self.a, axes=(self.axis,), direction="FFTW_BACKWARD"
                    )
            else:
                warnings.warn(
                    "Could not import pyfftw wrapper for fftw functions. Using numpy's rfft instead."
                )
                self.transform = "numpy"
        elif transform == "mkl":
            if mkl_available:
                import mkl_fft

                self.transform = "mkl"
            else:
                warnings.warn(
                    "Could not import mkl wrapper. Using numpy's rfft instead."
                )
                self.transform = "numpy"
        else:
            self.transform = "numpy"