Exemplo n.º 1
0
 def inc(self, inc):
     if inc is None:
         _tau, tau = self.kernel.effective_support()
         xyzrange = 8 * self.sigma
         L1 = 10
         inc = max(48, (L1 * xyzrange / (tau * self.hs)).max())
         inc = 2 ** nextpow2(inc)
     # pylint: disable=attribute-defined-outside-init
     self._inc = inc
Exemplo n.º 2
0
def test_nextpow2():
    assert_equal(nextpow2(10), 4)
    assert_equal(nextpow2(np.arange(5)), 3)
Exemplo n.º 3
0
    def tocovdata(self, timeseries):
        '''
        Return auto covariance function from data.

        Return
        -------
        R : CovData1D object
            with attributes:
            data : ACF vector length L+1
            args : time lags  length L+1
            sigma : estimated large lag standard deviation of the estimate
                     assuming x is a Gaussian process:
                     if R(k)=0 for all lags k>q then an approximation
                     of the variance for large samples due to Bartlett
                     var(R(k))=1/N*(R(0)^2+2*R(1)^2+2*R(2)^2+ ..+2*R(q)^2)
                     for  k>q and where  N=length(x). Special case is
                     white noise where it equals R(0)^2/N for k>0
            norm : bool
                If false indicating that R is not normalized

         Example:
         --------
         >>> import wafo.data
         >>> import wafo.objects as wo
         >>> x = wafo.data.sea()
         >>> ts = wo.mat2timeseries(x)
         >>> acf = ts.tocovdata(150)
         >>> h = acf.plot()
        '''
        lag = self.lag
        window = self.window
        detrend = self.detrend

        try:
            x = timeseries.data.flatten('F')
            dt = timeseries.sampling_period()
        except Exception:
            x = timeseries[:, 1:].flatten('F')
            dt = sampling_period(timeseries[:, 0])
        if not (self.dt is None):
            dt = self.dt

        if not (self.tr is None):
            x = self.tr.dat2gauss(x)

        n = len(x)
        indnan = np.isnan(x)
        if any(indnan):
            x = x - x[1 - indnan].mean()
            Ncens = n - indnan.sum()
            x[indnan] = 0.
        else:
            Ncens = n
            x = x - x.mean()
        if hasattr(detrend, '__call__'):
            x = detrend(x)

        nfft = 2 ** nextpow2(n)
        Rper = abs(fft(x, nfft)) ** 2 / Ncens  # Raw periodogram
        R = np.real(fft(Rper)) / nfft  # ifft = fft/nfft since Rper is real!

        if self.flag.startswith('unbiased'):
            # unbiased result, i.e. divide by n-abs(lag)
            R = R[:Ncens] * Ncens / np.arange(Ncens, 1, -1)

        if self.norm:
            R = R / R[0]

        if lag is None:
            lag = self._estimate_lag(R, Ncens)
        lag = min(lag, n - 2)
        if isinstance(window, str) or type(window) is tuple:
            win = get_window(window, 2 * lag - 1)
        else:
            win = np.asarray(window)
        R[:lag] = R[:lag] * win[lag - 1::]
        R[lag] = 0
        lags = slice(0, lag + 1)
        t = np.linspace(0, lag * dt, lag + 1)
        acf = CovData1D(R[lags], t)
        acf.sigma = np.sqrt(np.r_[0, R[0] ** 2,
                            R[0] ** 2 + 2 * np.cumsum(R[1:] ** 2)] / Ncens)
        acf.children = [PlotData(-2. * acf.sigma[lags], t),
                        PlotData(2. * acf.sigma[lags], t)]
        acf.plot_args_children = ['r:']
        acf.norm = self.norm
        return acf
Exemplo n.º 4
0
def test_nextpow2():
    assert nextpow2(10) == 4
    assert nextpow2(np.arange(5)) == 3
Exemplo n.º 5
0
    def sim(self, ns=None, cases=1, dt=None, iseed=None, derivative=False):
        '''
        Simulates a Gaussian process and its derivative from ACF

        Parameters
        ----------
        ns : scalar
            number of simulated points.  (default length(S)-1=n-1).
                     If ns>n-1 it is assummed that R(k)=0 for all k>n-1
        cases : scalar
            number of replicates (default=1)
        dt : scalar
            step in grid (default dt is defined by the Nyquist freq)
        iseed : int or state
            starting state/seed number for the random number generator
            (default none is set)
        derivative : bool
            if true : return derivative of simulated signal as well
            otherwise

        Returns
        -------
        xs    = a cases+1 column matrix  ( t,X1(t) X2(t) ...).
        xsder = a cases+1 column matrix  ( t,X1'(t) X2'(t) ...).

        Details
        -------
        Performs a fast and exact simulation of stationary zero mean
        Gaussian process through circulant embedding of the covariance matrix.

        If the ACF has a non-empty field .tr, then the transformation is
        applied to the simulated data, the result is a simulation of a
        transformed Gaussian process.

        Note: The simulation may give high frequency ripple when used with a
                small dt.

        Example:
        >>> import wafo.spectrum.models as sm
        >>> Sj = sm.Jonswap()
        >>> S = Sj.tospecdata()   #Make spec
        >>> R = S.tocovdata()
        >>> x = R.sim(ns=1000,dt=0.2)

        See also
        --------
        spec2sdat, gaus2dat

        Reference
        -----------
        C.R Dietrich and G. N. Newsam (1997)
        "Fast and exact simulation of stationary
        Gaussian process through circulant embedding
        of the Covariance matrix"
        SIAM J. SCI. COMPT. Vol 18, No 4, pp. 1088-1107
        '''

        # TODO fix it, it does not work

        # Add a nugget effect to ensure that round off errors
        # do not result in negative spectral estimates
        nugget = 0  # 10**-12

        _set_seed(iseed)
        self._is_valid_acf()
        acf = self.data.ravel()
        n = acf.size
        acf.shape = (n, 1)

        dT = self.sampling_period()

        x = zeros((ns, cases + 1))

        if derivative:
            xder = x.copy()

        # add a nugget effect to ensure that round off errors
        # do not result in negative spectral estimates
        acf[0] = acf[0] + nugget

        # Fast and exact simulation of simulation of stationary
        # Gaussian process throug circulant embedding of the
        # Covariance matrix
        floatinfo = finfo(float)
        if (abs(acf[-1]) > floatinfo.eps):  # assuming acf(n+1)==0
            m2 = 2 * n - 1
            nfft = 2 ** nextpow2(max(m2, 2 * ns))
            acf = r_[acf, zeros((nfft - m2, 1)), acf[-1:0:-1, :]]
            # warnings,warn('I am now assuming that ACF(k)=0 for k>MAXLAG.')
        else:  # ACF(n)==0
            m2 = 2 * n - 2
            nfft = 2 ** nextpow2(max(m2, 2 * ns))
            acf = r_[acf, zeros((nfft - m2, 1)), acf[n - 1:1:-1, :]]

        # m2=2*n-2
        S = fft(acf, nfft, axis=0).real  # periodogram

        I = S.argmax()
        k = flatnonzero(S < 0)
        if k.size > 0:
            _msg = '''
                Not able to construct a nonnegative circulant vector from ACF.
                Apply parzen windowfunction to the ACF in order to avoid this.
                The returned result is now only an approximation.'''

            # truncating negative values to zero to ensure that
            # that this noise is not added to the simulated timeseries

            S[k] = 0.

            ix = flatnonzero(k > 2 * I)
            if ix.size > 0:
                # truncating all oscillating values above 2 times the peak
                # frequency to zero to ensure that
                # that high frequency noise is not added to
                # the simulated timeseries.
                ix0 = k[ix[0]]
                S[ix0:-ix0] = 0.0

        trunc = 1e-5
        maxS = S[I]
        k = flatnonzero(S[I:-I] < maxS * trunc)
        if k.size > 0:
            S[k + I] = 0.
            # truncating small values to zero to ensure that
            # that high frequency noise is not added to
            # the simulated timeseries

        cases1 = int(cases / 2)
        cases2 = int(ceil(cases / 2))
# Generate standard normal random numbers for the simulations

        # randn = np.random.randn
        epsi = randn(nfft, cases2) + 1j * randn(nfft, cases2)
        Ssqr = sqrt(S / (nfft))  # sqrt(S(wn)*dw )
        ephat = epsi * Ssqr  # [:,np.newaxis]
        y = fft(ephat, nfft, axis=0)
        x[:, 1:cases + 1] = hstack((y[2:ns + 2, 0:cases2].real,
                                    y[2:ns + 2, 0:cases1].imag))

        x[:, 0] = linspace(0, (ns - 1) * dT, ns)  # (0:dT:(dT*(np-1)))'

        if derivative:
            Ssqr = Ssqr * \
                r_[0:(nfft / 2 + 1), -(nfft / 2 - 1):0] * 2 * pi / nfft / dT
            ephat = epsi * Ssqr  # [:,newaxis]
            y = fft(ephat, nfft, axis=0)
            xder[:, 1:(cases + 1)] = hstack((y[2:ns + 2, 0:cases2].imag -
                                            y[2:ns + 2, 0:cases1].real))
            xder[:, 0] = x[:, 0]

        if self.tr is not None:
            print('   Transforming data.')
            g = self.tr
            if derivative:
                for ix in range(cases):
                    tmp = g.gauss2dat(x[:, ix + 1], xder[:, ix + 1])
                    x[:, ix + 1] = tmp[0]
                    xder[:, ix + 1] = tmp[1]
            else:
                for ix in range(cases):
                    x[:, ix + 1] = g.gauss2dat(x[:, ix + 1])

        if derivative:
            return x, xder
        else:
            return x
Exemplo n.º 6
0
    def tospecdata(self, rate=None, method='fft', nugget=0.0, trunc=1e-5,
                   fast=True):
        '''
        Computes spectral density from the auto covariance function

        Parameters
        ----------
        rate = scalar, int
            1,2,4,8...2^r, interpolation rate for f (default 1)
        method : string
            interpolation method 'stineman', 'linear', 'cubic', 'fft'
        nugget : scalar, real
            nugget effect to ensure that round off errors do not result in
            negative spectral estimates. Good choice might be 10^-12.
        trunc : scalar, real
            truncates all spectral values where S/max(S) < trunc
                      0 <= trunc <1   This is to ensure that high frequency
                      noise is not added to the spectrum.  (default 1e-5)
        fast : bool
             if True : zero-pad to obtain power of 2 length ACF (default)
             otherwise  no zero-padding of ACF, slower but more accurate.

        Returns
        --------
        S : SpecData1D object
            spectral density

         NB! This routine requires that the covariance is evenly spaced
             starting from zero lag. Currently only capable of 1D matrices.

        Example:
        >>> import wafo.spectrum.models as sm
        >>> import numpy as np
        >>> import scipy.signal as st
        >>> import pylab
        >>> L = 129
        >>> t = np.linspace(0,75,L)
        >>> R = np.zeros(L)
        >>> win = st.parzen(41)
        >>> R[0:21] = win[20:41]
        >>> R0 = CovData1D(R,t)
        >>> S0 = R0.tospecdata()

        >>> Sj = sm.Jonswap()
        >>> S = Sj.tospecdata()
        >>> R2 = S.tocovdata()
        >>> S1 = R2.tospecdata()
        >>> abs(S1.data-S.data).max()

        >>> S1.plot('r-')
        >>> S.plot('b:')
        >>> pylab.show()

        >>> all(abs(S1.data-S.data)<1e-4)

        See also
        --------
        spec2cov
        datastructures
        '''

        dt = self.sampling_period()
        # dt = time-step between data points.

        acf, unused_ti = atleast_1d(self.data, self.args)

        if self.lagtype in 't':
            spectype = 'freq'
            ftype = 'w'
        else:
            spectype = 'k1d'
            ftype = 'k'

        if rate is None:
            rate = 1  # interpolation rate
        else:
            rate = 2 ** nextpow2(rate)  # make sure rate is a power of 2

        # add a nugget effect to ensure that round off errors
        # do not result in negative spectral estimates
        acf[0] = acf[0] + nugget
        n = acf.size
        # embedding a circulant vector and Fourier transform

        nfft = 2 ** nextpow2(2 * n - 2) if fast else 2 * n - 2

        if method == 'fft':
            nfft *= rate

        nf = nfft / 2  # number of frequencies
        acf = r_[acf, zeros(nfft - 2 * n + 2), acf[n - 2:0:-1]]

        Rper = (fft(acf, nfft).real).clip(0)  # periodogram
        RperMax = Rper.max()
        Rper = where(Rper < trunc * RperMax, 0, Rper)

        S = abs(Rper[0:(nf + 1)]) * dt / pi
        w = linspace(0, pi / dt, nf + 1)
        So = _wafospec.SpecData1D(S, w, type=spectype, freqtype=ftype)
        So.tr = self.tr
        So.h = self.h
        So.norm = self.norm

        if method != 'fft' and rate > 1:
            So.args = linspace(0, pi / dt, nf * rate)
            if method == 'stineman':
                So.data = stineman_interp(So.args, w, S)
            else:
                intfun = interpolate.interp1d(w, S, kind=method)
                So.data = intfun(So.args)
            So.data = So.data.clip(0)  # clip negative values to 0
        return So
Exemplo n.º 7
0
    def tocovdata(self, timeseries):
        """
        Return auto covariance function from data.

        Return
        -------
        acf : CovData1D object
            with attributes:
            data : ACF vector length L+1
            args : time lags  length L+1
            sigma : estimated large lag standard deviation of the estimate
                    assuming x is a Gaussian process:
                    if acf[k]=0 for all lags k>q then an approximation
                    of the variance for large samples due to Bartlett
                     var(acf[k])=1/N*(acf[0]**2+2*acf[1]**2+2*acf[2]**2+ ..+2*acf[q]**2)
                     for  k>q and where  N=length(x). Special case is
                     white noise where it equals acf[0]**2/N for k>0
            norm : bool
                If false indicating that auto_cov is not normalized

         Example:
         --------
         >>> import wafo.data
         >>> import wafo.objects as wo
         >>> x = wafo.data.sea()
         >>> ts = wo.mat2timeseries(x)
         >>> acf = ts.tocovdata(150)

         h = acf.plot()
        """
        lag = self.lag
        window = self.window
        detrend = self.detrend

        try:
            x = timeseries.data.flatten('F')
            dt = timeseries.sampling_period()
        except Exception:
            x = timeseries[:, 1:].flatten('F')
            dt = sampling_period(timeseries[:, 0])
        if self.dt is not None:
            dt = self.dt

        if self.tr is not None:
            x = self.tr.dat2gauss(x)

        n = len(x)
        indnan = np.isnan(x)
        if any(indnan):
            x = x - x[1 - indnan].mean()
            Ncens = n - indnan.sum()
            x[indnan] = 0.
        else:
            Ncens = n
            x = x - x.mean()
        if hasattr(detrend, '__call__'):
            x = detrend(x)

        nfft = 2 ** nextpow2(n)
        raw_periodogram = abs(fft(x, nfft)) ** 2 / Ncens
        # ifft = fft/nfft since raw_periodogram is real!
        auto_cov = np.real(fft(raw_periodogram)) / nfft

        if self.flag.startswith('unbiased'):
            # unbiased result, i.e. divide by n-abs(lag)
            auto_cov = auto_cov[:Ncens] * Ncens / np.arange(Ncens, 1, -1)

        if self.norm:
            auto_cov = auto_cov / auto_cov[0]

        if lag is None:
            lag = self._estimate_lag(auto_cov, Ncens)
        lag = min(lag, n - 2)
        if isinstance(window, str) or type(window) is tuple:
            win = get_window(window, 2 * lag - 1)
        else:
            win = np.asarray(window)
        auto_cov[:lag] = auto_cov[:lag] * win[lag - 1::]
        auto_cov[lag] = 0
        lags = slice(0, lag + 1)
        t = np.linspace(0, lag * dt, lag + 1)
        acf = CovData1D(auto_cov[lags], t)
        acf.sigma = np.sqrt(np.r_[0, auto_cov[0] ** 2,
                            auto_cov[0] ** 2 + 2 * np.cumsum(auto_cov[1:] ** 2)] / Ncens)
        acf.children = [PlotData(-2. * acf.sigma[lags], t),
                        PlotData(2. * acf.sigma[lags], t)]
        acf.plot_args_children = ['r:']
        acf.norm = self.norm
        return acf
Exemplo n.º 8
0
def test_nextpow2():
    assert_equal(nextpow2(10), 4)
    assert_equal(nextpow2(np.arange(5)), 3)
Exemplo n.º 9
0
    def sim(self, ns=None, cases=1, dt=None, iseed=None, derivative=False):
        '''
        Simulates a Gaussian process and its derivative from ACF

        Parameters
        ----------
        ns : scalar
            number of simulated points.  (default length(S)-1=n-1).
                     If ns>n-1 it is assummed that R(k)=0 for all k>n-1
        cases : scalar
            number of replicates (default=1)
        dt : scalar
            step in grid (default dt is defined by the Nyquist freq)
        iseed : int or state
            starting state/seed number for the random number generator
            (default none is set)
        derivative : bool
            if true : return derivative of simulated signal as well
            otherwise

        Returns
        -------
        xs    = a cases+1 column matrix  ( t,X1(t) X2(t) ...).
        xsder = a cases+1 column matrix  ( t,X1'(t) X2'(t) ...).

        Details
        -------
        Performs a fast and exact simulation of stationary zero mean
        Gaussian process through circulant embedding of the covariance matrix.

        If the ACF has a non-empty field .tr, then the transformation is
        applied to the simulated data, the result is a simulation of a
        transformed Gaussian process.

        Note: The simulation may give high frequency ripple when used with a
                small dt.

        Example:
        >>> import wafo.spectrum.models as sm
        >>> Sj = sm.Jonswap()
        >>> S = Sj.tospecdata()   #Make spec
        >>> R = S.tocovdata()
        >>> x = R.sim(ns=1000,dt=0.2)

        See also
        --------
        spec2sdat, gaus2dat

        Reference
        -----------
        C.R Dietrich and G. N. Newsam (1997)
        "Fast and exact simulation of stationary
        Gaussian process through circulant embedding
        of the Covariance matrix"
        SIAM J. SCI. COMPT. Vol 18, No 4, pp. 1088-1107
        '''

        # TODO fix it, it does not work

        # Add a nugget effect to ensure that round off errors
        # do not result in negative spectral estimates
        nugget = 0  # 10**-12

        _set_seed(iseed)
        self._is_valid_acf()
        acf = self.data.ravel()
        n = acf.size
        acf.shape = (n, 1)

        dT = self.sampling_period()

        x = zeros((ns, cases + 1))

        if derivative:
            xder = x.copy()

        # add a nugget effect to ensure that round off errors
        # do not result in negative spectral estimates
        acf[0] = acf[0] + nugget

        # Fast and exact simulation of simulation of stationary
        # Gaussian process throug circulant embedding of the
        # Covariance matrix
        floatinfo = finfo(float)
        if (abs(acf[-1]) > floatinfo.eps):  # assuming acf(n+1)==0
            m2 = 2 * n - 1
            nfft = 2 ** nextpow2(max(m2, 2 * ns))
            acf = r_[acf, zeros((nfft - m2, 1)), acf[-1:0:-1, :]]
            # warnings,warn('I am now assuming that ACF(k)=0 for k>MAXLAG.')
        else:  # ACF(n)==0
            m2 = 2 * n - 2
            nfft = 2 ** nextpow2(max(m2, 2 * ns))
            acf = r_[acf, zeros((nfft - m2, 1)), acf[n - 1:1:-1, :]]

        # m2=2*n-2
        S = fft(acf, nfft, axis=0).real  # periodogram

        I = S.argmax()
        k = flatnonzero(S < 0)
        if k.size > 0:
            _msg = '''
                Not able to construct a nonnegative circulant vector from ACF.
                Apply parzen windowfunction to the ACF in order to avoid this.
                The returned result is now only an approximation.'''

            # truncating negative values to zero to ensure that
            # that this noise is not added to the simulated timeseries

            S[k] = 0.

            ix = flatnonzero(k > 2 * I)
            if ix.size > 0:
                # truncating all oscillating values above 2 times the peak
                # frequency to zero to ensure that
                # that high frequency noise is not added to
                # the simulated timeseries.
                ix0 = k[ix[0]]
                S[ix0:-ix0] = 0.0

        trunc = 1e-5
        maxS = S[I]
        k = flatnonzero(S[I:-I] < maxS * trunc)
        if k.size > 0:
            S[k + I] = 0.
            # truncating small values to zero to ensure that
            # that high frequency noise is not added to
            # the simulated timeseries

        cases1 = int(cases / 2)
        cases2 = int(ceil(cases / 2))
# Generate standard normal random numbers for the simulations

        # randn = np.random.randn
        epsi = randn(nfft, cases2) + 1j * randn(nfft, cases2)
        Ssqr = sqrt(S / (nfft))  # sqrt(S(wn)*dw )
        ephat = epsi * Ssqr  # [:,np.newaxis]
        y = fft(ephat, nfft, axis=0)
        x[:, 1:cases + 1] = hstack((y[2:ns + 2, 0:cases2].real,
                                    y[2:ns + 2, 0:cases1].imag))

        x[:, 0] = linspace(0, (ns - 1) * dT, ns)  # (0:dT:(dT*(np-1)))'

        if derivative:
            Ssqr = Ssqr * \
                r_[0:(nfft / 2 + 1), -(nfft / 2 - 1):0] * 2 * pi / nfft / dT
            ephat = epsi * Ssqr  # [:,newaxis]
            y = fft(ephat, nfft, axis=0)
            xder[:, 1:(cases + 1)] = hstack((y[2:ns + 2, 0:cases2].imag -
                                            y[2:ns + 2, 0:cases1].real))
            xder[:, 0] = x[:, 0]

        if self.tr is not None:
            print('   Transforming data.')
            g = self.tr
            if derivative:
                for ix in range(cases):
                    tmp = g.gauss2dat(x[:, ix + 1], xder[:, ix + 1])
                    x[:, ix + 1] = tmp[0]
                    xder[:, ix + 1] = tmp[1]
            else:
                for ix in range(cases):
                    x[:, ix + 1] = g.gauss2dat(x[:, ix + 1])

        if derivative:
            return x, xder
        else:
            return x
Exemplo n.º 10
0
    def tospecdata(self, rate=None, method='fft', nugget=0.0, trunc=1e-5,
                   fast=True):
        '''
        Computes spectral density from the auto covariance function

        Parameters
        ----------
        rate = scalar, int
            1,2,4,8...2^r, interpolation rate for f (default 1)
        method : string
            interpolation method 'stineman', 'linear', 'cubic', 'fft'
        nugget : scalar, real
            nugget effect to ensure that round off errors do not result in
            negative spectral estimates. Good choice might be 10^-12.
        trunc : scalar, real
            truncates all spectral values where S/max(S) < trunc
                      0 <= trunc <1   This is to ensure that high frequency
                      noise is not added to the spectrum.  (default 1e-5)
        fast : bool
             if True : zero-pad to obtain power of 2 length ACF (default)
             otherwise  no zero-padding of ACF, slower but more accurate.

        Returns
        --------
        S : SpecData1D object
            spectral density

         NB! This routine requires that the covariance is evenly spaced
             starting from zero lag. Currently only capable of 1D matrices.

        Example:
        >>> import wafo.spectrum.models as sm
        >>> import numpy as np
        >>> import scipy.signal as st
        >>> import pylab
        >>> L = 129
        >>> t = np.linspace(0,75,L)
        >>> R = np.zeros(L)
        >>> win = st.parzen(41)
        >>> R[0:21] = win[20:41]
        >>> R0 = CovData1D(R,t)
        >>> S0 = R0.tospecdata()

        >>> Sj = sm.Jonswap()
        >>> S = Sj.tospecdata()
        >>> R2 = S.tocovdata()
        >>> S1 = R2.tospecdata()
        >>> abs(S1.data-S.data).max()

        >>> S1.plot('r-')
        >>> S.plot('b:')
        >>> pylab.show()

        >>> all(abs(S1.data-S.data)<1e-4)

        See also
        --------
        spec2cov
        datastructures
        '''

        dt = self.sampling_period()
        # dt = time-step between data points.

        acf, unused_ti = atleast_1d(self.data, self.args)

        if self.lagtype in 't':
            spectype = 'freq'
            ftype = 'w'
        else:
            spectype = 'k1d'
            ftype = 'k'

        if rate is None:
            rate = 1  # interpolation rate
        else:
            rate = 2 ** nextpow2(rate)  # make sure rate is a power of 2

        # add a nugget effect to ensure that round off errors
        # do not result in negative spectral estimates
        acf[0] = acf[0] + nugget
        n = acf.size
        # embedding a circulant vector and Fourier transform

        nfft = 2 ** nextpow2(2 * n - 2) if fast else 2 * n - 2

        if method == 'fft':
            nfft *= rate

        nf = nfft / 2  # number of frequencies
        acf = r_[acf, zeros(nfft - 2 * n + 2), acf[n - 2:0:-1]]

        Rper = (fft(acf, nfft).real).clip(0)  # periodogram
        RperMax = Rper.max()
        Rper = where(Rper < trunc * RperMax, 0, Rper)

        S = abs(Rper[0:(nf + 1)]) * dt / pi
        w = linspace(0, pi / dt, nf + 1)
        So = _wafospec.SpecData1D(S, w, type=spectype, freqtype=ftype)
        So.tr = self.tr
        So.h = self.h
        So.norm = self.norm

        if method != 'fft' and rate > 1:
            So.args = linspace(0, pi / dt, nf * rate)
            if method == 'stineman':
                So.data = stineman_interp(So.args, w, S)
            else:
                intfun = interpolate.interp1d(w, S, kind=method)
                So.data = intfun(So.args)
            So.data = So.data.clip(0)  # clip negative values to 0
        return So