Esempio n. 1
0
def test_real_to_complex(verbose):
  fft = fftpack.real_to_complex(6)
  vd = flex.double(fft.m_real())
  vc = flex.complex_double(fft.n_complex())
  for i in xrange(fft.n_real()):
    vd[i] = 1.*i
  for i in xrange(fft.n_complex()):
    vc[i] = complex(vd[2*i], vd[2*i+1])
  vdt = fft.forward(vd)
  vct = fft.forward(vc)
  for t in (vdt, vct):
    assert t.origin() == (0,)
    assert t.all()[0] == fft.n_complex()
    assert t.focus()[0] == fft.n_complex()
  if (verbose): show_rseq(vd, fft.m_real())
  assert_complex_eq_real(vc, vd)
  vdt = fft.backward(vd)
  vct = fft.backward(vc)
  for t in (vdt, vct):
    assert t.origin() == (0,)
    assert t.all()[0] == fft.m_real()
    assert t.focus()[0] == fft.n_real()
  if (verbose): show_rseq(vd, fft.n_real())
  assert_complex_eq_real(vc, vd)

  """ The backward fft computes
  y_k = sum_{n=0}^15 x_n e^{i 2pi n/16 k}
      = sum_{n=0}^7 2 Re( x_n e^{i 2pi n/16 k} ) + x_8 cos{i k pi}
  because of the assumed Hermitian condition x_{16-i} = x_i^* (=> x_8 real).
  Only x_0, ..., x_8 need to be stored.
  """
  fft = fftpack.real_to_complex(16)
  assert fft.n_complex() == 9
  x = flex.complex_double(fft.n_complex(), 0)
  x[4] = 1 + 1.j
  y = fft.backward(x)
  for i in xrange(0, fft.n_real(), 4):
    assert tuple(y[i:i+4]) == (2, -2, -2, 2)

  x = flex.complex_double(fft.n_complex(), 0)
  x[2] = 1 + 1.j
  y = fft.backward(x)
  for i in xrange(0, fft.n_real(), 8):
    assert tuple(y[i:i+3]) == (2, 0, -2)
    assert approx_equal(y[i+3], -2*math.sqrt(2))
    assert tuple(y[i+4:i+7]) == (-2, 0, 2)
    assert approx_equal(y[i+7], 2*math.sqrt(2))

  x = flex.complex_double(fft.n_complex(), 0)
  x[8] = 1.
  y = fft.backward(x)
  for i in xrange(0, fft.n_real(), 2):
    assert tuple(y[i:i+2]) == (1, -1)
Esempio n. 2
0
def test_real_to_complex(verbose):
    fft = fftpack.real_to_complex(6)
    vd = flex.double(fft.m_real())
    vc = flex.complex_double(fft.n_complex())
    for i in range(fft.n_real()):
        vd[i] = 1. * i
    for i in range(fft.n_complex()):
        vc[i] = complex(vd[2 * i], vd[2 * i + 1])
    vdt = fft.forward(vd)
    vct = fft.forward(vc)
    for t in (vdt, vct):
        assert t.origin() == (0, )
        assert t.all()[0] == fft.n_complex()
        assert t.focus()[0] == fft.n_complex()
    if (verbose): show_rseq(vd, fft.m_real())
    assert_complex_eq_real(vc, vd)
    vdt = fft.backward(vd)
    vct = fft.backward(vc)
    for t in (vdt, vct):
        assert t.origin() == (0, )
        assert t.all()[0] == fft.m_real()
        assert t.focus()[0] == fft.n_real()
    if (verbose): show_rseq(vd, fft.n_real())
    assert_complex_eq_real(vc, vd)
    """ The backward fft computes
  y_k = sum_{n=0}^15 x_n e^{i 2pi n/16 k}
      = sum_{n=0}^7 2 Re( x_n e^{i 2pi n/16 k} ) + x_8 cos{i k pi}
  because of the assumed Hermitian condition x_{16-i} = x_i^* (=> x_8 real).
  Only x_0, ..., x_8 need to be stored.
  """
    fft = fftpack.real_to_complex(16)
    assert fft.n_complex() == 9
    x = flex.complex_double(fft.n_complex(), 0)
    x[4] = 1 + 1.j
    y = fft.backward(x)
    for i in range(0, fft.n_real(), 4):
        assert tuple(y[i:i + 4]) == (2, -2, -2, 2)

    x = flex.complex_double(fft.n_complex(), 0)
    x[2] = 1 + 1.j
    y = fft.backward(x)
    for i in range(0, fft.n_real(), 8):
        assert tuple(y[i:i + 3]) == (2, 0, -2)
        assert approx_equal(y[i + 3], -2 * math.sqrt(2))
        assert tuple(y[i + 4:i + 7]) == (-2, 0, 2)
        assert approx_equal(y[i + 7], 2 * math.sqrt(2))

    x = flex.complex_double(fft.n_complex(), 0)
    x[8] = 1.
    y = fft.backward(x)
    for i in range(0, fft.n_real(), 2):
        assert tuple(y[i:i + 2]) == (1, -1)
Esempio n. 3
0
def kernapply(x, k, circular=False):
  """Convolve a sequence x with a Kernel k"""

  x = flex.double(x).deep_copy()
  lenx = len(x)
  w = flex.double(lenx, 0.0)
  w.set_selected(flex.size_t_range(k.m + 1), k.coef)
  sel = lenx -1 - flex.size_t_range(k.m)
  w.set_selected(sel, k.coef[1:])

  # do convolution in the Fourier domain
  fft = fftpack.real_to_complex(lenx)
  n = fft.n_real()
  m = fft.m_real()
  x.extend(flex.double(m-n, 0.))
  w.extend(flex.double(m-n, 0.))
  conv = fft.forward(x) * fft.forward(w)

  # extend result by the reverse conjugate, omitting the DC offset and Nyquist
  # frequencies. If fft.n_real() is odd there is no Nyquist term.
  end = fft.n_complex() - (fft.n_real() + 1) % 2
  conv.extend(flex.conj(conv[1:end]).reversed())

  # transform back, take real part and scale
  fft = fftpack.complex_to_complex(len(conv))
  result = fft.backward(conv).parts()[0] / n

  if circular:
    return result
  else:
    return result[(k.m):(lenx-k.m)]
Esempio n. 4
0
def exercise_real_to_complex_padding_area():
    mt = flex.mersenne_twister(seed=1)
    for n_real in range(1, 101):
        fft = fftpack.real_to_complex(n_real)
        assert fft.n_real() == n_real
        assert fft.n_complex() == n_real // 2 + 1
        assert fft.m_real() == fft.n_complex() * 2
        m_real = fft.m_real()
        z = mt.random_double(
            size=m_real) * 2 - 1  # non-zero values in padded area
        c = z.deep_copy()
        fft.forward(c)
        if (n_real % 2 == 0):
            assert approx_equal(c[-1],
                                0)  # imaginary part of last complex value
        r = c.deep_copy()
        fft.backward(r)
        r *= (1 / n_real)
        assert approx_equal(r[:n_real], z[:n_real])
        if (n_real % 2 == 0):
            assert approx_equal(r[n_real:], [0, 0])
            q = c.deep_copy()
            q[-1] = 123  # random imaginary part (which should be zero)
            fft.backward(q)
            q *= (1 / n_real)
            assert approx_equal(q, r)  # obtain zeros in padded area anyway
Esempio n. 5
0
def exercise_real_to_complex():
  print "real_to_complex"
  for n in xrange(1,256+1):
    fft = fftpack.real_to_complex(n)
    dp = flex.random_double(size=n)*2-1
    dp.resize(flex.grid(fft.m_real()).set_focus(n))
    dw = dp.deep_copy()
    cw = fftw3tbx.real_to_complex_in_place(dw)
    cp = fft.forward(dp)
    assert flex.max(flex.abs(cw-cp)) < 1.e-6
    rw = fftw3tbx.complex_to_real_in_place(cw, n)
    rp = fft.backward(cp)
    assert flex.max(flex.abs(rw[:n]-rp[:n])) < 1.e-6
  for n,n_repeats in [(2400,500), (19200,250)]:
    fft = fftpack.real_to_complex(n)
    print "  factors of %d:" % n, list(fft.factors())
    print "  repeats:", n_repeats
    d0 = flex.random_double(size=n)*2-1
    d0.resize(flex.grid(fft.m_real()).set_focus(n))
    #
    t0 = time.time()
    for i_trial in xrange(n_repeats):
      d = d0.deep_copy()
    overhead = time.time()-t0
    print "    overhead: %.2f seconds" % overhead
    #
    t0 = time.time()
    for i_trial in xrange(n_repeats):
      d = d0.deep_copy()
      c = fftw3tbx.real_to_complex_in_place(data=d)
      fftw3tbx.complex_to_real_in_place(data=c, n=n)
    print "    fftw:     %.2f seconds" % (time.time()-t0-overhead)
    #
    t0 = time.time()
    for i_trial in xrange(n_repeats):
      d = d0.deep_copy()
      c = fftpack.real_to_complex(n).forward(d)
      fftpack.real_to_complex(n).backward(c)
    print "    fftpack:  %.2f seconds" % (time.time()-t0-overhead)
    sys.stdout.flush()
Esempio n. 6
0
def fft(d):
  from scitbx import fftpack
  f = fftpack.real_to_complex(d.size())
  _d = flex.double(f.m_real(), 0.0)
  for j in range(d.size()):
    _d[j] = d[j]
  t = f.forward(_d)
  p = flex.abs(t) ** 2

  # remove the DC component
  p[0] = 0.0

  return p
Esempio n. 7
0
def fourier_filter(x, y, cutoff_frequency):
  assert cutoff_frequency < len(y)
  from scitbx import fftpack
  fft = fftpack.real_to_complex(len(y))
  n = fft.n_real()
  m = fft.m_real()
  y_tr = y.deep_copy()
  y_tr.extend(flex.double(m-n, 0))
  fft.forward(y_tr)
  for i in range(cutoff_frequency, m):
    y_tr[i] = 0
  fft.backward(y_tr)
  y_tr = y_tr[:n]
  scale = 1 / fft.n_real()
  y_tr *= scale
  return x, y_tr[:n]
Esempio n. 8
0
def test_comprehensive_rc_1d(max_transform_size):
    for n in range(1, max_transform_size + 1):
        fft = fftpack.real_to_complex(n)
        m = fft.m_real()
        v_in = flex.double()
        for i in range(n):
            v_in.append(random.random())
        for i in range(n, m):
            v_in.append(999)
        v_tr = v_in.deep_copy()
        fft.forward(v_tr)
        fft.backward(v_tr)
        compare_vectors(n, n, v_in, v_tr)
        v_in[n] = v_in[1]
        v_in[1] = 0
        if (n % 2 == 0): v_in[n + 1] = 0
        v_tr = v_in.deep_copy()
        fft.backward(v_tr)
        fft.forward(v_tr)
        compare_vectors(n, m, v_in, v_tr)
Esempio n. 9
0
def test_comprehensive_rc_1d(max_transform_size):
  for n in xrange(1,max_transform_size+1):
    fft = fftpack.real_to_complex(n)
    m = fft.m_real()
    v_in = flex.double()
    for i in xrange(n):
      v_in.append(random.random())
    for i in xrange(n, m):
      v_in.append(999)
    v_tr = v_in.deep_copy()
    fft.forward(v_tr)
    fft.backward(v_tr)
    compare_vectors(n, n, v_in, v_tr)
    v_in[n] = v_in[1]
    v_in[1] = 0
    if (n % 2 == 0): v_in[n+1] = 0
    v_tr = v_in.deep_copy()
    fft.backward(v_tr)
    fft.forward(v_tr)
    compare_vectors(n, m, v_in, v_tr)
Esempio n. 10
0
def exercise_real_to_complex_padding_area():
  mt = flex.mersenne_twister(seed=1)
  for n_real in xrange(1,101):
    fft = fftpack.real_to_complex(n_real)
    assert fft.n_real() == n_real
    assert fft.n_complex() == n_real // 2 + 1
    assert fft.m_real() == fft.n_complex() * 2
    m_real = fft.m_real()
    z = mt.random_double(size=m_real)*2-1 # non-zero values in padded area
    c = z.deep_copy()
    fft.forward(c)
    if (n_real % 2 == 0):
      assert approx_equal(c[-1], 0) # imaginary part of last complex value
    r = c.deep_copy()
    fft.backward(r)
    r *= (1/n_real)
    assert approx_equal(r[:n_real], z[:n_real])
    if (n_real % 2 == 0):
      assert approx_equal(r[n_real:], [0,0])
      q = c.deep_copy()
      q[-1] = 123 # random imaginary part (which should be zero)
      fft.backward(q)
      q *= (1/n_real)
      assert approx_equal(q, r) # obtain zeros in padded area anyway
Esempio n. 11
0
  def __init__(self, x, spans=None, demean=True, detrend=True):

    # Ensure x is copied as it will be changed in-place
    x = flex.double(x).deep_copy()
    n = len(x)

    if detrend:
      t = flex.size_t_range(n).as_double() + 1 - (n + 1)/2
      inv_sumt2 = 1./t.dot(t)
      x = x - flex.mean(x) - x.dot(t) * t * inv_sumt2
    elif demean:
      x -= flex.mean(x)

    # determine frequencies
    stop = ((n - (n % 2)) // 2) + 1
    self.freq = flex.double([i / n for i in range(1, stop)])

    fft = fftpack.real_to_complex(n)
    n = fft.n_real()
    m = fft.m_real()
    x.extend(flex.double(m-n, 0.))
    xf = fft.forward(x)

    # get abs length of complex and normalise by n to get the raw periodogram
    spec = flex.norm(xf) / n

    if spans is None:
      # if not doing smoothing, the spectrum is just the raw periodogram with
      # the uninteresting DC offset removed
      self.spec = spec[1:]
      return

    # for smoothing replace the DC offset term and extend the rest of the
    # sequence by its reverse conjugate, omitting the Nyquist term if it is
    # present
    spec[0] = spec[1]
    end = fft.n_complex() - (fft.n_real() + 1) % 2
    spec.extend(spec[1:end].reversed())

    try:
      # multiple integer spans
      nspans = len(spans)
      m = int(spans[0]) // 2
      multiple = True
    except TypeError:
      # single integer span
      m = int(spans) // 2
      multiple = False

    # construct smoothing kernel
    k = Kernel('modified.daniell', m)

    if multiple:
      for i in range(1, nspans):
        # construct kernel for convolution
        m1 = int(spans[i]) // 2
        k1 = Kernel('modified.daniell', m1)

        # expand coefficients of k to full kernel and zero pad for smoothing
        x1 = flex.double(k1.m, 0.0)
        x1.extend(k.coef.reversed())
        x1.extend(k.coef[1:])
        x1.extend(flex.double(k1.m, 0.0))

        # convolve kernels
        coef = kernapply(x1, k1, circular=True)
        m = len(coef)//2
        coef = coef[m:(len(coef))]
        k = Kernel(coef=coef)

    # apply smoothing kernel
    spec = kernapply(spec, k, circular=True)
    self.spec = spec[1:fft.n_complex()]

    return