Example #1
0
def remove_frequencies_and_save_to_csv(dtfrm, band_pass, high_pass,
                                       low_freq_limit, high_freq_limit, width,
                                       delta_t):
    [row, column] = dtfrm.shape
    frame = pd.DataFrame()

    i = 0
    while i < column:
        y = dtfrm.iloc[:, i].tolist()

        wave, scales, freqs, coi, fft, fftfreqs = wavelet.cwt(
            y, delta_t, J=width - 1, wavelet=u'mexicanhat')
        wave = select_frequencies(wave, width, band_pass, high_pass, delta_t,
                                  low_freq_limit, high_freq_limit)
        xrec = wavelet.icwt(wave, scales, delta_t, wavelet=u'mexicanhat')

        xrec = normalize(xrec)

        xrec = pd.Series(xrec)
        frame = pd.concat([frame, xrec], axis=1, ignore_index=True)

        i = i + 1

    print("Select a folder")
    path = th.ui.getdir('Select a directory to save the csv file'
                        )  # prompts user to select folder
    frame.to_csv(path + "/" + "new_dtfrm.csv")
Example #2
0
def inverse_cwt(wl, scales=None):
    # wl: [10, T]
    mother = wavelet.MexicanHat()
    dt = 0.005
    dj = 1
    s0 = dt * 2
    J = 9
    C_delta = 3.541
    if scales is None:
        scales = np.array([0.01, 0.02, 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12])
    icwt_signal = wavelet.icwt(wl, scales, dt, dj, mother) / C_delta
    return icwt_signal
Example #3
0
p = numpy.polyfit(t - t0, dat, 1)
dat_notrend = dat - numpy.polyval(p, t - t0)
std = dat_notrend.std()  # Standard deviation
var = std**2  # Variance
dat_norm = dat_notrend / std  # Normalized dataset

## Define wavelet parameters
mother = wavelet.Morlet(6)
s0 = 2 * dt  # Starting scale, in this case 2 * 0.25 years = 6 months
dj = 1 / 12  # Twelve sub-octaves per octaves
J = 7 / dj  # Seven powers of two with dj sub-octaves
alpha, _, _ = wavelet.ar1(dat)  # Lag-1 autocorrelation for red noise

wave, scales, freqs, coi, fft, fftfreqs = wavelet.cwt(dat_norm, dt, dj, s0, J,
                                                      mother)
iwave = wavelet.icwt(wave, scales, dt, dj, mother) * std

power = (numpy.abs(wave))**2
fft_power = numpy.abs(fft)**2
period = 1 / freqs

power /= scales[:, None]

signif, fft_theor = wavelet.significance(1.0,
                                         dt,
                                         scales,
                                         0,
                                         alpha,
                                         significance_level=0.95,
                                         wavelet=mother)
sig95 = numpy.ones([1, N]) * signif[:, None]
def wavelet_transform(dat, mother, s0, dj, J, dt, lims=[20, 120], t0=0):
    """
    Plot the continous wavelet transform for a given signal.

    Make sure to detrend and normalize the data before calling this funcion.

    This is a function wrapper around the pycwt simple_sample example with
    some modifications.

    ----------
    Args:
        dat (Mandatory [array like]): input signal data.

        mother (Mandatory [str]): the wavelet mother name.

        s0 (Mandatory [float]): starting scale.

        dj (Mandatory [float]): number of sub-octaves per octaves.

        j (Mandatory [float]):  powers of two with dj sub-octaves.

        dt (Mandatory [float]): same frequency in the same unit as the input.

        lims (Mandatory [list]): Period interval to integrate the local
                                 power spectrum.

        label (Mandatory [str]): the plot y-label.

        title (Mandatory [str]): the plot title.
    ----------
    Return:
        No
    """

    # also create a time array in years.
    N = dat.size
    t = np.arange(0, N) * dt + t0

    # write the following code to detrend and normalize the input data by its
    # standard deviation. Sometimes detrending is not necessary and simply
    # removing the mean value is good enough. However, if your dataset has a
    # well defined trend, such as the Mauna Loa CO\ :sub:`2` dataset available
    # in the above mentioned website, it is strongly advised to perform
    # detrending. Here, we fit a one-degree polynomial function and then
    # subtract it from the
    # original data.
    p = np.polyfit(t - t0, dat, 1)
    dat_notrend = dat - np.polyval(p, t - t0)
    std = dat_notrend.std()  # Standard deviation
    var = std**2  # Variance
    dat_norm = dat_notrend / std  # Normalized dataset
    alpha, _, _ = wavelet.ar1(dat)  # Lag-1 autocorrelation for red noise

    # the following routines perform the wavelet transform and inverse wavelet
    # transform using the parameters defined above. Since we have normalized
    # our input time-series, we multiply the inverse transform by the standard
    # deviation.
    wave, scales, freqs, coi, fft, fftfreqs = wavelet.cwt(
        dat_norm, dt, dj, s0, J, mother)
    iwave = wavelet.icwt(wave, scales, dt, dj, mother) * std

    # calculate the normalized wavelet and Fourier power spectra, as well as
    # the Fourier equivalent periods for each wavelet scale.
    power = (np.abs(wave))**2
    fft_power = np.abs(fft)**2
    period = 1 / freqs

    # inverse transform but only considering lims
    idx1 = np.argmin(np.abs(period - LIMS[0]))
    idx2 = np.argmin(np.abs(period - LIMS[1]))
    _wave = wave.copy()
    _wave[0:idx1, :] = 0
    igwave = wavelet.icwt(_wave, scales, dt, dj, mother) * std

    # could stop at this point and plot our results. However we are also
    # interested in the power spectra significance test. The power is
    # significant where the ratio ``power / sig95 > 1``.
    signif, fft_theor = wavelet.significance(1.0,
                                             dt,
                                             scales,
                                             0,
                                             alpha,
                                             significance_level=0.95,
                                             wavelet=mother)
    sig95 = np.ones([1, N]) * signif[:, None]
    sig95 = power / sig95

    # calculate the global wavelet spectrum and determine its
    # significance level.
    glbl_power = power.mean(axis=1)
    dof = N - scales  # Correction for padding at edges
    glbl_signif, tmp = wavelet.significance(var,
                                            dt,
                                            scales,
                                            1,
                                            alpha,
                                            significance_level=0.95,
                                            dof=dof,
                                            wavelet=mother)

    return t, dt, power, period, coi, sig95, iwave, igwave
Example #5
0
J = -1  # 7 / dj                     # Seven powers of two with dj sub-octaves
#  alpha = 0.0                       # Lag-1 autocorrelation for white noise
try:
    alpha, _, _ = wavelet.ar1(dat)   # Lag-1 autocorrelation for red noise
except Warning:
    # When the dataset is too short, or there is a strong trend, ar1 raises a
    # warning. In this case, we assume a white noise background spectrum.
    alpha = 1.0

mother = wavelet.Morlet(6)           # Morlet mother wavelet with m=6

# The following routines perform the wavelet transform and siginificance
# analysis for the chosen data set.
wave, scales, freqs, coi, fft, fftfreqs = wavelet.cwt(dat, ds.dt, dj, s0, J,
                                                      mother)
iwave = wavelet.icwt(wave, scales, ds.dt, dj, mother)

# Normalized wavelet and Fourier power spectra
power = (numpy.abs(wave)) ** 2
fft_power = numpy.abs(fft) ** 2
period = 1 / freqs

# Significance test. Where ratio power/sig95 > 1, power is significant.
signif, fft_theor = wavelet.significance(1.0, ds.dt, scales, 0, alpha,
                                         significance_level=slevel,
                                         wavelet=mother)
sig95 = numpy.ones([1, N]) * signif[:, None]
sig95 = power / sig95

# Power rectification as of Liu et al. (2007). TODO: confirm if significance
# test ratio should be calculated first.
Example #6
0
def main():
  
# Then, we load the dataset and define some data related parameters. In this
# case, the first 19 lines of the data file contain meta-data, that we ignore,
# since we set them manually (*i.e.* title, units).
    url = 'http://paos.colorado.edu/research/wavelets/wave_idl/nino3sst.txt'
    dat = numpy.genfromtxt(url, skip_header=19)
    title = 'NINO3 Sea Surface Temperature'
    label = 'NINO3 SST'
    units = 'degC'
    t0 = 1871.0
    dt = 0.25  # In years

#%%
    
    # We also create a time array in years.
    N = dat.size
    t = numpy.arange(0, N) * dt + t0
#%%
# We write the following code to detrend and normalize the input data by its
# standard deviation. Sometimes detrending is not necessary and simply
# removing the mean value is good enough. However, if your dataset has a well
# defined trend, such as the Mauna Loa CO\ :sub:`2` dataset available in the
# above mentioned website, it is strongly advised to perform detrending.
# Here, we fit a one-degree polynomial function and then subtract it from the
# original data.
    p = numpy.polyfit(t - t0, dat, 1)
    dat_notrend = dat - numpy.polyval(p, t - t0)
    std = dat_notrend.std()  # Standard deviation
    var = std ** 2  # Variance
    dat_norm = dat_notrend / std  # Normalized dataset
#%%   
# The next step is to define some parameters of our wavelet analysis. We
# select the mother wavelet, in this case the Morlet wavelet with
# :math:`\omega_0=6`.
    mother = wavelet.Morlet(6)
    s0 = 2 * dt  # Starting scale, in this case 2 * 0.25 years = 6 months
    dj = 1 / 12  # Twelve sub-octaves per octaves
    J = 7 / dj  # Seven powers of two with dj sub-octaves
    alpha, _, _ = wavelet.ar1(dat)  # Lag-1 autocorrelation for red noise

#%%
    
# The following routines perform the wavelet transform and inverse wavelet
# transform using the parameters defined above. Since we have normalized our
# input time-series, we multiply the inverse transform by the standard
# deviation.
    wave, scales, freqs, coi, fft, fftfreqs = wavelet.cwt(dat_norm, dt, dj, s0, J,
                                                      mother)
    iwave = wavelet.icwt(wave, scales, dt, dj, mother) * std

#%%
# We calculate the normalized wavelet and Fourier power spectra, as well as
# the Fourier equivalent periods for each wavelet scale.
    power = (numpy.abs(wave)) ** 2
    fft_power = numpy.abs(fft) ** 2
    period = 1 / freqs
    
#%%
    
    # We could stop at this point and plot our results. However we are also
    # interested in the power spectra significance test. The power is significant
    # where the ratio ``power / sig95 > 1``.
    signif, fft_theor = wavelet.significance(1.0, dt, scales, 0, alpha,
                                         significance_level=0.95,
                                         wavelet=mother)
    sig95 = numpy.ones([1, N]) * signif[:, None]
    sig95 = power / sig95

#%%
    
    # Then, we calculate the global wavelet spectrum and determine its
# significance level.
    glbl_power = power.mean(axis=1)
    dof = N - scales  # Correction for padding at edges
    glbl_signif, tmp = wavelet.significance(var, dt, scales, 1, alpha,
                                        significance_level=0.95, dof=dof,
                                        wavelet=mother)
    
#%%
    
    # We also calculate the scale average between 2 years and 8 years, and its
# significance level.
    sel = find((period >= 2) & (period < 8))
    Cdelta = mother.cdelta
    scale_avg = (scales * numpy.ones((N, 1))).transpose()
    scale_avg = power / scale_avg  # As in Torrence and Compo (1998) equation 24
    scale_avg = var * dj * dt / Cdelta * scale_avg[sel, :].sum(axis=0)
    scale_avg_signif, tmp = wavelet.significance(var, dt, scales, 2, alpha,
                                             significance_level=0.95,
                                             dof=[scales[sel[0]],
                                                  scales[sel[-1]]],
                                             wavelet=mother)

#%%
    
    # Finally, we plot our results in four different subplots containing the
# (i) original series anomaly and the inverse wavelet transform; (ii) the
# wavelet power spectrum (iii) the global wavelet and Fourier spectra ; and
# (iv) the range averaged wavelet spectrum. In all sub-plots the significance
# levels are either included as dotted lines or as filled contour lines.

# Prepare the figure
    pyplot.close('all')
    pyplot.ioff()
    figprops = dict(figsize=(11, 8), dpi=72)
    fig = pyplot.figure(**figprops)
    
#%%
    
    # First sub-plot, the original time series anomaly and inverse wavelet
# transform.
    ax = pyplot.axes([0.1, 0.75, 0.65, 0.2])
    ax.plot(t, iwave, '-', linewidth=1, color=[0.5, 0.5, 0.5])
    ax.plot(t, dat, 'k', linewidth=1.5)
    ax.set_title('a) {}'.format(title))
    ax.set_ylabel(r'{} [{}]'.format(label, units))
Example #7
0
def takewav_makefig(dd,moornum):

        if moornum==8:
            dt=1
            dat=pd.read_csv(dd,header=12,sep='\s*')
            date=unique([datetime.datetime(int(dat.ix[ii,0]),
                                               int(dat.ix[ii,1]),
                                               int(dat.ix[ii,2]),
                                               int(dat.ix[ii,3])) for ii in range(len(dat))])
            utest=array(dat.ix[:,6]/100)
            vtest=array(dat.ix[:,7]/100)
            nomd=int(nanmean(array(dat.ix[:,5])))
            dat=utest**2+vtest**2
            savetit='M1-'+str(nomd)+'m'

        else:
            dataset=xr.open_dataset(dd)
            date=dataset['TIME']
            ke=dataset['UCUR']**2+dataset['VCUR']**2
            dat=ke.values.flatten()
            dt=0.5
            nomd=int(dataset.geospatial_vertical_min)
            savetit=dataset.platform_code[-3:]+'-'+str(nomd)+'m'

        dat[isnan(dat)]=nanmean(dat)
        alpha, _, _ = wavelet.ar1(dat)  # Lag-1 autocorrelation for red noise

        N=len(dat)
        #in hours

        t = numpy.arange(0, N) * dt

        std=dat.std()
        var=std**2
        dat_norm=dat/std


        # The following routines perform the wavelet transform and inverse wavelet transform using the parameters defined above. Since we have normalized our input time-series, we multiply the inverse transform by the standard deviation.
        wave, scales, freqs, coi, fft, fftfreqs = wavelet.cwt(dat_norm,dt, dj, s0, J, mother)

        iwave = wavelet.icwt(wave, scales, dt, dj, mother) * std

        # We calculate the normalized wavelet and Fourier power spectra, as well as the Fourier equivalent periods for each wavelet scale.

        power = (numpy.abs(wave)) ** 2
        fft_power = numpy.abs(fft) ** 2
        period = 1 / freqs

        # Optionally, we could also rectify the power spectrum according to the suggestions proposed by Liu et al. (2007)[2]

        power /= scales[:, None]

        # We could stop at this point and plot our results. However we are also interested in the power spectra significance test. The power is significant where the ratio power / sig95 > 1.


        signif, fft_theor = wavelet.significance(1.0, dt, scales, 0, alpha,
                                                 significance_level=0.95,
                                                 wavelet=mother)


        sig95 = numpy.ones([1, N]) * signif[:, None]
        sig95 = power / sig95

        # Then, we calculate the global wavelet spectrum and determine its significance level.

        glbl_power = power.mean(axis=1)
        dof = N - scales  # Correction for padding at edges
        glbl_signif, tmp = wavelet.significance(var, dt, scales, 1, alpha,
                                                significance_level=0.95, dof=dof,
                                                wavelet=mother)

        # We also calculate the scale average between pmin and pmax, and its significance level.
        f,dx = pyplot.subplots(6,1,figsize=(12,12),sharex=True)
        bands=[1,2,8,16,48,128,512]
        for ii in range(len(bands)-1):
            pmin=bands[ii]
            pmax=bands[ii+1]
            sel = find((period >= pmin) & (period < pmax))
            Cdelta = mother.cdelta
            scale_avg = (scales * numpy.ones((N, 1))).transpose()
            scale_avg = power / scale_avg  # As in Torrence and Compo (1998) equation 24
            scale_avg = var * dj * dt / Cdelta * scale_avg[sel, :].sum(axis=0)
            scale_avg_signif, tmp = wavelet.significance(var, dt, scales, 2, alpha,
                                                         significance_level=0.95,
                                                         dof=[scales[sel[0]],
                                                              scales[sel[-1]]],
                                                         wavelet=mother)

            dx[ii].axhline(scale_avg_signif, color='C'+str(ii), linestyle='--', linewidth=1.)
            dx[ii].plot(date, scale_avg, '-', color='C'+str(ii), linewidth=1.5,label='{}--{} hour band'.format(pmin,pmax))
            [dx[ii].axvline(dd,color=clist[jj],linewidth=3) for jj,dd in enumerate(dlist)]
            dx[ii].legend()

        dx[0].set_title('Scale-averaged power: '+savetit)
        dx[3].set_ylabel(r'Average variance [{}]'.format(units))
        if moornum ==8:
            dx[0].set_xlim(date[0],date[-1])
        else:
            dx[0].set_xlim(date[0].values,date[-1].values)
        savefig(figdir+'ScaleSep_'+savetit+'.png',bbox_inches='tight')

        pmin=2
        pmax=24


        sel = find((period >= pmin) & (period < pmax))
        Cdelta = mother.cdelta
        scale_avg = (scales * numpy.ones((N, 1))).transpose()
        scale_avg = power / scale_avg  # As in Torrence and Compo (1998) equation 24
        scale_avg = var * dj * dt / Cdelta * scale_avg[sel, :].sum(axis=0)
        scale_avg_signif, tmp = wavelet.significance(var, dt, scales, 2, alpha,
                                                     significance_level=0.95,
                                                     dof=[scales[sel[0]],
                                                          scales[sel[-1]]],
                                                     wavelet=mother)



        figprops = dict(figsize=(11, 8), dpi=72)
        fig = pyplot.figure(**figprops)

        # First sub-plot, the original time series anomaly and inverse wavelet
        # transform.
        ax = pyplot.axes([0.1, 0.75, 0.65, 0.2])
        ax.plot(date, dat, linewidth=1.5, color=[0.5, 0.5, 0.5])
        ax.plot(date, iwave, 'k-', linewidth=1,zorder=100)
        if moornum ==8:
            ax.set_xlim(date[0],date[-1])
        else:
            ax.set_xlim(date[0].values,date[-1].values)
        # ax.set_title('a) {}'.format(title))
        ax.set_ylabel(r'{} [{}]'.format(label, units))
        # Second sub-plot, the normalized wavelet power spectrum and significance
        # level contour lines and cone of influece hatched area. Note that period
        # scale is logarithmic.

        bx = pyplot.axes([0.1, 0.37, 0.65, 0.28])
        levels = [0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16]
        bx.contourf(t, numpy.log2(period), numpy.log2(power), numpy.log2(levels),
                    extend='both', cmap=pyplot.cm.viridis)
        extent = [t.min(), t.max(), 0, max(period)]
        bx.contour(t, numpy.log2(period), sig95, [-99, 1], colors='k', linewidths=2,
                   extent=extent)
        bx.fill(numpy.concatenate([t, t[-1:] + dt, t[-1:] + dt,
                                   t[:1] - dt, t[:1] - dt]),
                numpy.concatenate([numpy.log2(coi), [1e-9], numpy.log2(period[-1:]),
                                   numpy.log2(period[-1:]), [1e-9]]),
                'k', alpha=0.3, hatch='x')
        bx.set_title('{} Wavelet Power Spectrum ({})'.format(label, mother.name))
        bx.set_ylabel('Period (hours)')
        #
        Yticks = 2 ** numpy.arange(numpy.ceil(numpy.log2(period.min())),
                                   numpy.ceil(numpy.log2(period.max())))
        bx.set_yticks(numpy.log2(Yticks))
        bx.set_yticklabels(Yticks)
        bx.set_xticklabels('')
        bx.set_xlim(t.min(),t.max())


        # Third sub-plot, the global wavelet and Fourier power spectra and theoretical
        # noise spectra. Note that period scale is logarithmic.
        cx = pyplot.axes([0.77, 0.37, 0.2, 0.28], sharey=bx)
        cx.plot(glbl_signif, numpy.log2(period), 'k--')
        cx.plot(var * fft_theor, numpy.log2(period), '--', color='#cccccc')
        cx.plot(var * fft_power, numpy.log2(1./fftfreqs), '-', color='#cccccc',
                linewidth=1.)
        cx.plot(var * glbl_power, numpy.log2(period), 'k-', linewidth=1.5)
        cx.set_title('Global Wavelet Spectrum')
        cx.set_xlabel(r'Power [({})^2]'.format(units))
        cx.set_xlim([0, glbl_power.max() + var])
        cx.set_ylim(numpy.log2([period.min(), period.max()]))
        cx.set_yticks(numpy.log2(Yticks))
        cx.set_yticklabels(Yticks)
        pyplot.setp(cx.get_yticklabels(), visible=False)

        spowdic={}
        spowdic['sig']=scale_avg_signif
        if moornum==8:
            spowdic['date']=date
        else:
            spowdic['date']=date.values
        spowdic['spow']=scale_avg

        # Fourth sub-plot, the scale averaged wavelet spectrum.
        dx = pyplot.axes([0.1, 0.07, 0.65, 0.2], sharex=ax)
        dx.axhline(scale_avg_signif, color='k', linestyle='--', linewidth=1.)
        dx.plot(date, scale_avg, 'k-', linewidth=1.5)
        dx.set_title('{}--{} hour scale-averaged power'.format(pmin,pmax))
        # [dx.axvline(dd,color=clist[ii],linewidth=3) for ii,dd in enumerate(dlist)]
        # dx.set_xlabel('Time (hours)')
        dx.set_ylabel(r'Average variance [{}]'.format(units))
        if moornum ==8:
            dx.set_xlim(date[0],date[-1])
        else:
            dx.set_xlim(date[0].values,date[-1].values)

        fig.suptitle(savetit)
        savefig(figdir+'Wavelet_'+savetit+'.png',bbox_inches='tight')

        return nomd,spowdic
Example #8
0
 def inverse(self):
     return wavelet.icwt(self.coeffs, self.scales, self.feature.dt,
                         self.feature.dj,
                         self.feature.mother) * self.feature.amplitude
Example #9
0
    def cwt(signal, t, obspy=None):
        # from __future__ import division
        import numpy
        from matplotlib import pyplot

        import pycwt as wavelet
        from pycwt.helpers import find
        signal = signal[10000:11000]
        t = t[10000:11000]
        url = 'http://paos.colorado.edu/research/wavelets/wave_idl/nino3sst.txt'
        dat = numpy.genfromtxt(url, skip_header=19)
        title = 'DICARDIA'
        label = 'DICARDIA SST'
        units = 'degC'
        t0 = 1871.0
        dt = 0.25  # In years

        N = signal.shape[0]
        print(N)
        p = numpy.polyfit(t, signal, 1)
        dat_notrend = signal - numpy.polyval(p, t)
        std = dat_notrend.std()  # Standard deviation
        var = std**2  # Variance
        dat_norm = dat_notrend / std  # Normalized dataset

        mother = wavelet.Morlet(6)
        s0 = 2 * dt  # Starting scale, in this case 2 * 0.25 years = 6 months
        dj = 1 / 12  # Twelve sub-octaves per octaves
        J = 7 / dj  # Seven powers of two with dj sub-octaves
        alpha, _, _ = wavelet.ar1(
            signal)  # Lag-1 autocorrelation for red noise

        wave, scales, freqs, coi, fft, fftfreqs = wavelet.cwt(
            dat_norm, dt, dj, s0, J, mother)
        iwave = wavelet.icwt(wave, scales, dt, dj, mother) * std

        power = (numpy.abs(wave))**2
        fft_power = numpy.abs(fft)**2
        period = 1 / freqs

        power /= scales[:, None]

        signif, fft_theor = wavelet.significance(1.0,
                                                 dt,
                                                 scales,
                                                 0,
                                                 alpha,
                                                 significance_level=0.95,
                                                 wavelet=mother)
        sig95 = numpy.ones([1, N]) * signif[:, None]
        sig95 = power / sig95

        glbl_power = power.mean(axis=1)
        dof = N - scales  # Correction for padding at edges
        glbl_signif, tmp = wavelet.significance(var,
                                                dt,
                                                scales,
                                                1,
                                                alpha,
                                                significance_level=0.95,
                                                dof=dof,
                                                wavelet=mother)
        sel = find((period >= 2) & (period < 8))
        Cdelta = mother.cdelta
        scale_avg = (scales * numpy.ones((N, 1))).transpose()
        scale_avg = power / scale_avg  # As in Torrence and Compo (1998) equation 24
        scale_avg = var * dj * dt / Cdelta * scale_avg[sel, :].sum(axis=0)
        scale_avg_signif, tmp = wavelet.significance(
            var,
            dt,
            scales,
            2,
            alpha,
            significance_level=0.95,
            dof=[scales[sel[0]], scales[sel[-1]]],
            wavelet=mother)
        # Prepare the figure
        pyplot.close('all')
        pyplot.ioff()
        figprops = dict(figsize=(11, 8), dpi=72)
        fig = pyplot.figure(**figprops)

        # First sub-plot, the original time series anomaly and inverse wavelet
        # transform.
        ax = pyplot.axes([0.1, 0.75, 0.65, 0.2])
        ax.plot(t, iwave, '-', linewidth=1, color=[0.5, 0.5, 0.5])
        ax.plot(t, signal, 'k', linewidth=1.5)
        ax.set_title('a) {}'.format(title))
        ax.set_ylabel(r'{} [{}]'.format(label, units))

        # Second sub-plot, the normalized wavelet power spectrum and significance
        # level contour lines and cone of influece hatched area. Note that period
        # scale is logarithmic.
        bx = pyplot.axes([0.1, 0.37, 0.65, 0.28], sharex=ax)
        levels = [0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16]
        bx.contourf(t,
                    numpy.log2(period),
                    numpy.log2(power),
                    numpy.log2(levels),
                    extend='both',
                    cmap=pyplot.cm.viridis)
        extent = [t.min(), t.max(), 0, max(period)]
        bx.contour(t,
                   numpy.log2(period),
                   sig95, [-99, 1],
                   colors='k',
                   linewidths=2,
                   extent=extent)
        bx.fill(numpy.concatenate(
            [t, t[-1:] + dt, t[-1:] + dt, t[:1] - dt, t[:1] - dt]),
                numpy.concatenate([
                    numpy.log2(coi), [1e-9],
                    numpy.log2(period[-1:]),
                    numpy.log2(period[-1:]), [1e-9]
                ]),
                'k',
                alpha=0.3,
                hatch='x')
        bx.set_title('b) {} Wavelet Power Spectrum ({})'.format(
            label, mother.name))
        bx.set_ylabel('Period (years)')
        #
        Yticks = 2**numpy.arange(numpy.ceil(numpy.log2(period.min())),
                                 numpy.ceil(numpy.log2(period.max())))
        bx.set_yticks(numpy.log2(Yticks))
        bx.set_yticklabels(Yticks)

        # Third sub-plot, the global wavelet and Fourier power spectra and theoretical
        # noise spectra. Note that period scale is logarithmic.
        cx = pyplot.axes([0.77, 0.37, 0.2, 0.28], sharey=bx)
        cx.plot(glbl_signif, numpy.log2(period), 'k--')
        cx.plot(var * fft_theor, numpy.log2(period), '--', color='#cccccc')
        cx.plot(var * fft_power,
                numpy.log2(1. / fftfreqs),
                '-',
                color='#cccccc',
                linewidth=1.)
        cx.plot(var * glbl_power, numpy.log2(period), 'k-', linewidth=1.5)
        cx.set_title('c) Global Wavelet Spectrum')
        cx.set_xlabel(r'Power [({})^2]'.format(units))
        cx.set_xlim([0, glbl_power.max() + var])
        cx.set_ylim(numpy.log2([period.min(), period.max()]))
        cx.set_yticks(numpy.log2(Yticks))
        cx.set_yticklabels(Yticks)
        pyplot.setp(cx.get_yticklabels(), visible=False)

        # Fourth sub-plot, the scale averaged wavelet spectrum.
        dx = pyplot.axes([0.1, 0.07, 0.65, 0.2], sharex=ax)
        dx.axhline(scale_avg_signif, color='k', linestyle='--', linewidth=1.)
        dx.plot(t, scale_avg, 'k-', linewidth=1.5)
        dx.set_title('d) {}--{} year scale-averaged power'.format(2, 8))
        dx.set_xlabel('Time (year)')
        dx.set_ylabel(r'Average variance [{}]'.format(units))
        ax.set_xlim([t.min(), t.max()])

        pyplot.show()
Example #10
0
def wtdtw_dvv(ref,
              cur,
              allfreq,
              para,
              maxLag,
              b,
              direction,
              dj=1 / 12,
              s0=-1,
              J=-1,
              wvn='morlet',
              normalize=True):
    """
    Apply dynamic time warping method to continuous wavelet transformation (CWT) of signals
    for all frequecies in an interest range

    Parameters
    --------------
    ref: The "Reference" timeseries (numpy.ndarray)
    cur: The "Current" timeseries (numpy.ndarray)
    allfreq: a boolen variable to make measurements on all frequency range or not
    maxLag: max number of points to search forward and backward. 
    b: b-value to limit strain, which is to limit the maximum velocity perturbation. See equation 11 in (Mikesell et al. 2015)
    direction: direction to accumulate errors (1=forward, -1=backward)
    dj, s0, J, sig, wvn: common parameters used in 'wavelet.wct'
    normalize: normalize the wavelet spectrum or not. Default is True
    
    RETURNS:
    ------------------
    dvv: estimated dv/v
    err: error of dv/v estimation

    Written by Congcong Yuan (30 Jun, 2019)
    """
    # common variables
    t = para['t']
    twin = para['twin']
    freq = para['freq']
    dt = para['dt']
    tmin = np.min(twin)
    tmax = np.max(twin)
    fmin = np.min(freq)
    fmax = np.max(freq)
    itvec = np.arange(
        np.int((tmin - t.min()) / dt) + 1,
        np.int((tmax - t.min()) / dt) + 1)
    tvec = t[itvec]

    # apply cwt on two traces
    cwt1, sj, freq, coi, _, _ = pycwt.cwt(cur, dt, dj, s0, J, wvn)
    cwt2, sj, freq, coi, _, _ = pycwt.cwt(ref, dt, dj, s0, J, wvn)

    # extract real values of cwt
    rcwt1, rcwt2 = np.real(cwt1), np.real(cwt2)

    # zero out cone of influence and data outside frequency band
    if (fmax > np.max(freq)) | (fmax <= fmin):
        raise ValueError('Abort: input frequency out of limits!')
    else:
        freq_indin = np.where((freq >= fmin) & (freq <= fmax))[0]

    # convert wavelet domain back to time domain (~filtering)
    if not allfreq:

        # inverse cwt to time domain
        icwt1 = pycwt.icwt(cwt1[freq_indin], sj[freq_indin], dt, dj, wvn)
        icwt2 = pycwt.icwt(cwt2[freq_indin], sj[freq_indin], dt, dj, wvn)

        # assume all time window is used
        wcwt1, wcwt2 = np.real(icwt1), np.real(icwt2)

        # Normalizes both signals, if appropriate.
        if normalize:
            ncwt1 = (wcwt1 - wcwt1.mean()) / wcwt1.std()
            ncwt2 = (wcwt2 - wcwt2.mean()) / wcwt2.std()
        else:
            ncwt1 = wcwt1
            ncwt2 = wcwt2

        # run dtw
        dv, error, dist = dtw_dvv(ncwt2[itvec], ncwt1[itvec], para, maxLag, b,
                                  direction)
        dvv, err = dv, error

        return dvv, err

    # directly take advantage of the real-valued parts of wavelet transforms
    else:
        # initialize variable
        nfreq = len(freq_indin)
        dvv, cc, cdp, err = np.zeros(nfreq,dtype=np.float32), np.zeros(nfreq,dtype=np.float32),\
            np.zeros(nfreq,dtype=np.float32),np.zeros(nfreq,dtype=np.float32)

        # loop through each freq
        for ii, ifreq in enumerate(freq_indin):

            # prepare windowed data
            wcwt1, wcwt2 = rcwt1[ifreq], rcwt2[ifreq]

            # Normalizes both signals, if appropriate.
            if normalize:
                ncwt1 = (wcwt1 - wcwt1.mean()) / wcwt1.std()
                ncwt2 = (wcwt2 - wcwt2.mean()) / wcwt2.std()
            else:
                ncwt1 = wcwt1
                ncwt2 = wcwt2

            # run dtw
            dv, error, dist = dtw_dvv(ncwt2[itvec], ncwt1[itvec], para, maxLag,
                                      b, direction)
            dvv[ii], err[ii] = dv, error

        return freq[freq_indin], dvv, err
Example #11
0
def wts_dvv(ref,
            cur,
            allfreq,
            para,
            dv_range,
            nbtrial,
            dj=1 / 12,
            s0=-1,
            J=-1,
            wvn='morlet',
            normalize=True):
    """
    Apply stretching method to continuous wavelet transformation (CWT) of signals
    for all frequecies in an interest range
    
    Parameters
    --------------
    ref: The complete "Reference" time series (numpy.ndarray)
    cur: The complete "Current" time series (numpy.ndarray)
    allfreq: a boolen variable to make measurements on all frequency range or not
    para: a dict containing freq/time info of the data matrix
    dv_range: absolute bound for the velocity variation; example: dv=0.03 for [-3,3]% of relative velocity change (float)
    nbtrial: number of stretching coefficient between dvmin and dvmax, no need to be higher than 100  (float)
    dj, s0, J, sig, wvn: common parameters used in 'wavelet.wct'
    normalize: normalize the wavelet spectrum or not. Default is True
    
    RETURNS:
    ------------------
    dvv: estimated dv/v
    err: error of dv/v estimation
    
    Written by Congcong Yuan (30 Jun, 2019)  
    """
    # common variables
    t = para['t']
    twin = para['twin']
    freq = para['freq']
    dt = para['dt']
    tmin = np.min(twin)
    tmax = np.max(twin)
    fmin = np.min(freq)
    fmax = np.max(freq)
    itvec = np.arange(
        np.int((tmin - t.min()) / dt) + 1,
        np.int((tmax - t.min()) / dt) + 1)
    tvec = t[itvec]

    # apply cwt on two traces
    cwt1, sj, freq, coi, _, _ = pycwt.cwt(cur, dt, dj, s0, J, wvn)
    cwt2, sj, freq, coi, _, _ = pycwt.cwt(ref, dt, dj, s0, J, wvn)

    # extract real values of cwt
    rcwt1, rcwt2 = np.real(cwt1), np.real(cwt2)

    # zero out data outside frequency band
    if (fmax > np.max(freq)) | (fmax <= fmin):
        raise ValueError('Abort: input frequency out of limits!')
    else:
        freq_indin = np.where((freq >= fmin) & (freq <= fmax))[0]

    # convert wavelet domain back to time domain (~filtering)
    if not allfreq:

        # inverse cwt to time domain
        icwt1 = pycwt.icwt(cwt1[freq_indin], sj[freq_indin], dt, dj, wvn)
        icwt2 = pycwt.icwt(cwt2[freq_indin], sj[freq_indin], dt, dj, wvn)

        # assume all time window is used
        wcwt1, wcwt2 = np.real(icwt1), np.real(icwt2)

        # Normalizes both signals, if appropriate.
        if normalize:
            ncwt1 = (wcwt1 - wcwt1.mean()) / wcwt1.std()
            ncwt2 = (wcwt2 - wcwt2.mean()) / wcwt2.std()
        else:
            ncwt1 = wcwt1
            ncwt2 = wcwt2

        # run stretching
        dvv, err, cc, cdp = ts_dvv(ncwt2[itvec], ncwt1[itvec], dv_range,
                                   nbtrial, para)
        return dvv, err

    # directly take advantage of the real-valued parts of wavelet transforms
    else:
        # initialize variable
        nfreq = len(freq_indin)
        dvv, cc, cdp, err = np.zeros(nfreq,dtype=np.float32), np.zeros(nfreq,dtype=np.float32),\
            np.zeros(nfreq,dtype=np.float32),np.zeros(nfreq,dtype=np.float32)

        # loop through each freq
        for ii, ifreq in enumerate(freq_indin):

            # prepare windowed data
            wcwt1, wcwt2 = rcwt1[ifreq], rcwt2[ifreq]

            # Normalizes both signals, if appropriate.
            if normalize:
                ncwt1 = (wcwt1 - wcwt1.mean()) / wcwt1.std()
                ncwt2 = (wcwt2 - wcwt2.mean()) / wcwt2.std()
            else:
                ncwt1 = wcwt1
                ncwt2 = wcwt2

            # run stretching
            dv, error, c1, c2 = ts_dvv(ncwt2[itvec], ncwt1[itvec], dv_range,
                                       nbtrial, para)
            dvv[ii], cc[ii], cdp[ii], err[ii] = dv, c1, c2, error

        return freq[freq_indin], dvv, err
Example #12
0
def plot_wavelet(t,
                 dat,
                 dt,
                 pl,
                 pr,
                 period_pltlim=None,
                 ax=None,
                 ax2=None,
                 stscale=2,
                 siglev=0.95,
                 cmap='viridis',
                 title='',
                 levels=None,
                 label='',
                 units='',
                 tunits='',
                 sav_img=False):
    import pycwt as wavelet
    from pycwt.helpers import find
    import numpy as np
    import matplotlib.pyplot as plt
    from copy import copy
    import numpy.ma as ma

    t_ = copy(t)
    t0 = t[0]
    # print(Time(t[-1:], format='plot_date').iso)
    # We also create a time array in years.
    N = dat.size
    t = np.arange(0, N) * dt + t0
    # print(Time(t[-1:], format='plot_date').iso)
    # We write the following code to detrend and normalize the input data by its
    # standard deviation. Sometimes detrending is not necessary and simply
    # removing the mean value is good enough. However, if your dataset has a well
    # defined trend, such as the Mauna Loa CO\ :sub:`2` dataset available in the
    # above mentioned website, it is strongly advised to perform detrending.
    # Here, we fit a one-degree polynomial function and then subtract it from the
    # original data.
    p = np.polyfit(t - t0, dat, 1)
    dat_notrend = dat - np.polyval(p, t - t0)
    std = dat_notrend.std()  # Standard deviation
    var = std**2  # Variance
    dat_norm = dat_notrend / std  # Normalized dataset

    # The next step is to define some parameters of our wavelet analysis. We
    # select the mother wavelet, in this case the Morlet wavelet with
    # :math:`\omega_0=6`.
    mother = wavelet.Morlet(6)
    s0 = stscale * dt  # Starting scale, in this case 2 * 0.25 years = 6 months
    dj = 1 / 12  # Twelve sub-octaves per octaves
    J = -1  # 7 / dj  # Seven powers of two with dj sub-octaves
    alpha, _, _ = wavelet.ar1(dat)  # Lag-1 autocorrelation for red noise

    # The following routines perform the wavelet transform and inverse wavelet
    # transform using the parameters defined above. Since we have normalized our
    # input time-series, we multiply the inverse transform by the standard
    # deviation.
    wave, scales, freqs, coi, fft, fftfreqs = wavelet.cwt(
        dat_norm, dt, dj, s0, J, mother)
    iwave = wavelet.icwt(wave, scales, dt, dj, mother) * std

    # We calculate the normalized wavelet and Fourier power spectra, as well as
    # the Fourier equivalent periods for each wavelet scale.
    power = (np.abs(wave))**2
    fft_power = np.abs(fft)**2
    period = 1 / freqs

    # We could stop at this point and plot our results. However we are also
    # interested in the power spectra significance test. The power is significant
    # where the ratio ``power / sig95 > 1``.
    signif, fft_theor = wavelet.significance(1.0,
                                             dt,
                                             scales,
                                             0,
                                             alpha,
                                             significance_level=siglev,
                                             wavelet=mother)
    sig95 = np.ones([1, N]) * signif[:, None]
    sig95 = power / sig95

    # Then, we calculate the global wavelet spectrum and determine its
    # significance level.
    glbl_power = power.mean(axis=1)
    dof = N - scales  # Correction for padding at edges
    glbl_signif, tmp = wavelet.significance(var,
                                            dt,
                                            scales,
                                            1,
                                            alpha,
                                            significance_level=siglev,
                                            dof=dof,
                                            wavelet=mother)

    # We also calculate the scale average between 2 years and 8 years, and its
    # significance level.
    sel = find((period >= pl) & (period < pr))
    Cdelta = mother.cdelta
    scale_avg = (scales * np.ones((N, 1))).transpose()
    scale_avg = power / scale_avg  # As in Torrence and Compo (1998) equation 24
    scale_avg = var * dj * dt / Cdelta * scale_avg[sel, :].sum(axis=0)
    scale_avg_signif, tmp = wavelet.significance(
        var,
        dt,
        scales,
        2,
        alpha,
        significance_level=siglev,
        dof=[scales[sel[0]], scales[sel[-1]]],
        wavelet=mother)

    # levels = [0.25, 0.5, 1, 2, 4, 8, 16,32]
    if levels is None:
        levels = np.linspace(0.0, 128., 256)
    # ax.contourf(t, np.log2(period), np.log2(power), np.log2(levels), extend='both', cmap=plt.cm.viridis)
    im = ax.contourf(t_,
                     np.array(period) * 24 * 60,
                     power,
                     levels,
                     extend='both',
                     cmap=cmap,
                     zorder=-20)
    # for pathcoll in im.collections:
    #     pathcoll.set_rasterized(True)
    ax.set_rasterization_zorder(-10)
    # im = ax.pcolormesh(t_, np.array(period) * 24 * 60, power,vmax=32.,vmin=0, cmap=cmap)
    # im = ax.contourf(t, np.array(period)*24*60, np.log2(power), np.log2(levels), extend='both', cmap=cmap)
    extent = [t_.min(), t_.max(), 0, max(period) * 24 * 60]
    # ax.contour(t, np.log2(period), sig95, [-99, 1], colors='k', linewidths=1, extent=extent)
    CS = ax.contour(t_,
                    np.array(period) * 24 * 60,
                    sig95 * siglev, [-99, 1.0 * siglev],
                    colors='k',
                    linewidths=1,
                    extent=extent)
    ax.clabel(CS, inline=1, fmt='%1.3f')
    ax.fill(np.concatenate(
        [t_, t_[-1:] + dt, t_[-1:] + dt, t_[:1] - dt, t_[:1] - dt]),
            np.concatenate([
                np.array(coi), [2**(1e-9)],
                np.array(period[-1:]),
                np.array(period[-1:]), [2**(1e-9)]
            ]) * 24 * 60,
            color='k',
            alpha=0.75,
            edgecolor='None',
            facecolor='k',
            hatch='x')
    # ### not Matplotlib does not display hatching when rendering to pdf. Here is a workaround.
    # ax.fill(np.concatenate([t_, t_[-1:] + dt, t_[-1:] + dt, t_[:1] - dt, t_[:1] - dt]),
    #         np.concatenate(
    #             [np.array(coi), [2 ** (1e-9)], np.array(period[-1:]), np.array(period[-1:]),
    #              [2 ** (1e-9)]]) * 24 * 60,
    #         color='None', alpha=1.0, edgecolor='k', hatch='x')
    # ax.set_title('b) {} Wavelet Power Spectrum ({})'.format(label, mother.name))
    #
    # ax.set_rasterization_zorder(20)
    # Yticks = np.arange(np.ceil(np.array(period.min()*24*60)), np.ceil(np.array(period.max()*24*60)))
    # ax.set_yticks(np.array(Yticks))
    # ax.set_yticklabels(Yticks)

    ax2.plot(glbl_signif, np.array(period) * 24 * 60, 'k--')
    # ax2.plot(var * fft_theor, np.array(period) * 24 * 60, '--', color='#cccccc')
    # ax2.plot(var * fft_power, np.array(1. / fftfreqs) * 24 * 60, '-', color='#cccccc',
    #          linewidth=1.)
    ax2.plot(var * glbl_power, np.array(period) * 24 * 60, 'k-', linewidth=1)
    mperiod = ma.masked_outside(np.array(period), period_pltlim[0],
                                period_pltlim[1])
    mpower = ma.masked_array(var * glbl_power, mask=mperiod.mask)
    # ax2.set_title('c) Global Wavelet Spectrum')
    ax2.set_xlabel(r'Power'.format(units))
    ax2.set_xlim([0, mpower.compressed().max() + var])
    # print(glbl_power)
    # ax2.set_ylim(np.array([period.min(), period.max()]))
    # ax2.set_yticks(np.array(Yticks))
    # ax2.set_yticklabels(Yticks)
    plt.setp(ax2.get_yticklabels(), visible=False)

    if period_pltlim:
        ax.set_ylim(np.array(period_pltlim) * 24 * 60)
    else:
        ax.set_ylim(np.array([period.min(), period.max()]) * 24 * 60)

    return im
def do_icwt(wave, scales, dt, dj, mother, std):
    return wavelet.icwt(wave, scales, dt, dj, mother) * std
def do_wavelet_transform(dat, dt):

    t0 = 0
    # dt = 0.25  # In years

    # We also create a time array in years.
    N = dat.size
    t = np.arange(0, N) * dt + t0
    '''
    We write the following code to detrend and normalize the input data by its
    standard deviation. Sometimes detrending is not necessary and simply
    removing the mean value is good enough. However, if your dataset has a well
    defined trend, such as the Mauna Loa CO\ :sub:`2` dataset available in the
    above mentioned website, it is strongly advised to perform detrending.
    Here, we fit a one-degree polynomial function and then subtract it from the
    original data.
    '''
    p = np.polyfit(t - t0, dat, 1)
    dat_notrend = dat - np.polyval(p, t - t0)
    std = dat_notrend.std()  # Standard deviation
    var = std**2  # Variance
    dat_norm = dat_notrend / std  # Normalized dataset

    # The next step is to define some parameters of our wavelet analysis. We
    # select the mother wavelet, in this case the Morlet wavelet with
    # :math:`\omega_0=6`.
    mother = wavelet.Morlet(6)
    s0 = 2 * dt  # Starting scale, in this case 2 * 0.25 years = 6 months
    dj = 1 / 12  # Twelve sub-octaves per octaves
    J = 7 / dj  # Seven powers of two with dj sub-octaves
    sr = pd.Series(dat)
    alpha = sr.autocorr(lag=1)  # Lag-1 autocorrelation for red noise
    '''
    The following routines perform the wavelet transform and inverse wavelet
    transform using the parameters defined above. Since we have normalized our
    input time-series, we multiply the inverse transform by the standard
    deviation.
    '''
    wave, scales, freqs, coi, fft, fftfreqs = wavelet.cwt(
        dat_norm, dt, dj, s0, J, mother)
    iwave = wavelet.icwt(wave, scales, dt, dj, mother) * std

    # We calculate the normalized wavelet and Fourier power spectra, as well as
    # the Fourier equivalent periods for each wavelet scale.
    power = (np.abs(wave))**2
    fft_power = np.abs(fft)**2
    period = 1 / freqs
    '''
    We could stop at this point and plot our results. However we are also
    interested in the power spectra significance test. The power is significant
    where the ratio ``power / sig95 > 1``.
    '''
    signif, fft_theor = wavelet.significance(1.0,
                                             dt,
                                             scales,
                                             0,
                                             alpha,
                                             significance_level=0.95,
                                             wavelet=mother)
    sig95 = np.ones([1, N]) * signif[:, None]
    sig95 = power / sig95

    # Then, we calculate the global wavelet spectrum and determine its
    # significance level.
    glbl_power = power.mean(axis=1)
    dof = N - scales  # Correction for padding at edges
    glbl_signif, tmp = wavelet.significance(var,
                                            dt,
                                            scales,
                                            1,
                                            alpha,
                                            significance_level=0.95,
                                            dof=dof,
                                            wavelet=mother)

    # We also calculate the scale average between 2 years and 8 years, and its
    # significance level.
    sel = find((period >= 2) & (period < 8))
    Cdelta = mother.cdelta
    scale_avg = (scales * np.ones((N, 1))).transpose()
    # As in Torrence and Compo (1998) equation 24
    scale_avg = power / scale_avg
    scale_avg = var * dj * dt / Cdelta * scale_avg[sel, :].sum(axis=0)
    scale_avg_signif, tmp = wavelet.significance(
        var,
        dt,
        scales,
        2,
        alpha,
        significance_level=0.95,
        dof=[scales[sel[0]], scales[sel[-1]]],
        wavelet=mother)

    return dat, t, \
        period, power, coi, wave, \
        scales, dt, dj, mother, sig95, \
        glbl_power, glbl_signif, \
        scale_avg_signif, scale_avg, \
        std, iwave, var, \
        fft_theor, fft_power, fftfreqs
Example #15
0
def get_graph_from_file(in_filepath, out_folder, out_filename):
    # Get data
    # TODO there are differents formats of file
    # TODO implement differents parsers by parameters of function
    p1 = numpy.genfromtxt(in_filepath)

    # TODO fix this shit
    dat = p1

    title = 'NINO3 Sea Surface Temperature'
    label = 'NINO3 SST'
    units = 'degC'

    # Values for calculations
    # TODO spike about args
    t0 = 12.0  # start time
    dt = 0.5  # step of differentiation - in minutes

    N = dat.size
    t = numpy.arange(0, N) * dt + t0

    p = numpy.polyfit(t - t0, dat, 1)
    dat_notrend = dat - numpy.polyval(p, t - t0)
    std = dat_notrend.std()  # Standard deviation
    var = std**2  # Variance
    dat_norm = dat_notrend / std  # Normalized dataset

    mother = wavelet.Morlet(6)
    s0 = 2 * dt  # Starting scale, in this case 2 * 0.25 years = 6 months
    dj = 1 / 12  # Twelve sub-octaves per octaves
    J = 7 / dj  # Seven powers of two with dj sub-octaves
    alpha, _, _ = wavelet.ar1(dat)  # Lag-1 autocorrelation for red noise

    wave, scales, freqs, coi, fft, fftfreqs = wavelet.cwt(
        dat_norm, dt, dj, s0, J, mother)
    iwave = wavelet.icwt(wave, scales, dt, dj, mother) * std

    power = (numpy.abs(wave))**2
    fft_power = numpy.abs(fft)**2
    period = 1 / freqs

    power /= scales[:, None]

    signif, fft_theor = wavelet.significance(1.0,
                                             dt,
                                             scales,
                                             0,
                                             alpha,
                                             significance_level=0.95,
                                             wavelet=mother)
    sig95 = numpy.ones([1, N]) * signif[:, None]
    sig95 = power / sig95

    glbl_power = power.mean(axis=1)
    dof = N - scales  # Correction for padding at edges
    glbl_signif, tmp = wavelet.significance(var,
                                            dt,
                                            scales,
                                            1,
                                            alpha,
                                            significance_level=0.95,
                                            dof=dof,
                                            wavelet=mother)

    sel = find((period >= 2) & (period < 8))
    Cdelta = mother.cdelta
    scale_avg = (scales * numpy.ones((N, 1))).transpose()
    scale_avg = power / scale_avg  # As in Torrence and Compo (1998) equation 24
    scale_avg = var * dj * dt / Cdelta * scale_avg[sel, :].sum(axis=0)
    scale_avg_signif, tmp = wavelet.significance(
        var,
        dt,
        scales,
        2,
        alpha,
        significance_level=0.95,
        dof=[scales[sel[0]], scales[sel[-1]]],
        wavelet=mother)

    # Prepare the figure
    pyplot.close('all')
    #pyplot.ioff()
    figprops = dict(dpi=144)
    fig = pyplot.figure(**figprops)

    # Second sub-plot, the normalized wavelet power spectrum and significance
    # level contour lines and cone of influece hatched area. Note that period
    # scale is logarithmic.
    bx = pyplot.axes([0.1, 0.37, 0.65, 0.28])
    levels = [0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16]
    bx.contourf(t,
                period,
                numpy.log2(power),
                numpy.log2(levels),
                extend='both',
                cmap=pyplot.cm.viridis)
    extent = [t.min(), t.max(), 0, max(period)]
    bx.contour(t,
               period,
               sig95, [-99, 1],
               colors='k',
               linewidths=2,
               extent=extent)
    bx.set_title('{} Wavelet Power Spectrum ({})'.format(label, mother.name))
    bx.set_ylabel('Period (minutes)')
    #
    #Yticks = 2 ** numpy.arange(numpy.ceil(numpy.log2(period.min())),
    #                        numpy.ceil(numpy.log2(period.max())))
    #bx.set_yticks(numpy.log2(Yticks))
    #bx.set_yticklabels(Yticks)
    bx.set_ylim([2, 20])

    # Save graph to file
    # TODO implement
    #pyplot.savefig('{}/{}.png'.format(out_folder, out_filename))
    # ----------------------------------------------
    # or show the graph
    pyplot.show()
Example #16
0
def parse_frames(image_file, sig=0.95):
    """
    
    """
    cap = cv2.VideoCapture(image_file)
    if verbose: print("Video successfully loaded")
    FRAME_COUNT = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    FPS = cap.get(cv2.CAP_PROP_FPS)
    if verbose > 1:
        FRAME_HEIGHT = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
        FRAME_WIDTH = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
        print(
            "INFO: \n Frame count: ",
            FRAME_COUNT,
            "\n",
            "FPS: ",
            FPS,
            " \n",
            "FRAME_HEIGHT: ",
            FRAME_HEIGHT,
            " \n",
            "FRAME_WIDTH: ",
            FRAME_WIDTH,
            " \n",
        )

    directory = os.getcwd(
    ) + '\\analysis\\{}_{}_{}_{}({})_{}_{}_scaled\\'.format(
        date, trial_type, name, wavelet, order, per_min, per_max)
    if not os.path.exists(directory):
        os.makedirs(directory)
    made = False
    frame_idx = 0
    idx = 0
    dropped = 0
    skip = True
    thresh = None

    df_wav = pd.DataFrame()
    df_auc = pd.DataFrame()
    df_for = pd.DataFrame()
    df_pow = pd.DataFrame()

    for i in range(FRAME_COUNT):
        a, img = cap.read()
        if a:
            frame_idx += 1

            if made == False:
                #first we need to manually determine the boundaries and angle
                res = bg.manual_format(img)
                #print(res)
                x, y, w, h, angle = res
                horizon_begin = x
                horizon_end = x + w
                vert_begin = y
                vert_end = y + h
                #scale_array = np.zeros((FRAME_COUNT, abs(horizon_begin - horizon_end)))
                #area_time = np.zeros((FRAME_COUNT))
                #df[']
                print("Now Select the Red dot")
                red_res = bg.manual_format(img, stop_sign=True)
                red_x, red_y, red_w, red_h = red_res
                box_h_begin = red_x
                box_h_end = red_x + red_w
                box_v_begin = red_y
                box_v_end = red_y + red_h
                made = True
                #dims = (vert_begin, vert_end, horizon_begin, horizon_end)

            real_time = i / FPS
            rows, cols, chs = img.shape
            M = cv2.getRotationMatrix2D((cols / 2, rows / 2), angle, 1)
            rot_img = cv2.warpAffine(img, M, (cols, rows))
            roi = rot_img[vert_begin:vert_end, horizon_begin:horizon_end, :]

            red_box = img[box_v_begin:box_v_end, box_h_begin:box_h_end, 2]
            if thresh == None:
                thresh = np.mean(red_box)
            #print(np.mean(red_box))
            percent_drop = 1 - (np.mean(red_box) / thresh)
            print(percent_drop)
            if percent_drop >= 0.18:
                #cv2.imshow("Red Image", red_box)
                #cv2.waitKey(0)
                skip = False

            if skip:
                if verbose >= 1:
                    print('Frame is skipped {} / {}'.format(
                        frame_idx, FRAME_COUNT))
                continue

            if verbose >= 1:
                print('Processing frame {} / {}'.format(
                    frame_idx, FRAME_COUNT))

            idx += 1
            begin_code, data_line = extract_frame(roi)

            #We need to detrend the data before sending it away
            N = len(data_line)
            dt = su / N
            t = np.arange(0, N) * dt
            t = t - np.mean(t)

            var, std, dat_norm = detrend(data_line)
            ###################################################################
            if wavelet == 'DOG':
                mother = cwt.DOG(order)
            elif wavelet == 'Paul':
                mother = cwt.Paul(order)
            elif wavelet == 'Morlet':
                mother = cwt.Morlet(order)
            elif wavelet == 'MexicanHat':
                mother = cwt.MexicanHat(order)

            s0 = 4 * dt
            try:
                alpha, _, _ = cwt.ar1(dat_norm)
            except:
                alpha = 0.95

            wave, scales, freqs, coi, fft, fftfreqs = cwt.cwt(
                dat_norm, dt, dj, s0, J, mother)

            iwave = cwt.icwt(
                wave, scales, dt, dj,
                mother) * std  #This is a reconstruction of the wave

            power = (np.abs(wave))**2  #This is the power spectra
            fft_power = np.abs(fft)**2  #This is the fourier power
            period = 1 / freqs  #This is the periods of the wavelet analysis in cm
            power /= scales[:,
                            None]  #This is an option suggested by Liu et. al.

            #Next we calculate the significance of the power spectra. Significane where power / sig95 > 1
            signif, fft_theor = cwt.significance(1.0,
                                                 dt,
                                                 scales,
                                                 0,
                                                 alpha,
                                                 significance_level=0.95,
                                                 wavelet=mother)
            sig95 = np.ones([1, N]) * signif[:, None]
            sig95 = power / sig95

            #This is the significance of the global wave
            glbl_power = power.mean(axis=1)
            dof = N - scales  # Correction for padding at edges
            glbl_signif, tmp = cwt.significance(var,
                                                dt,
                                                scales,
                                                1,
                                                alpha,
                                                significance_level=0.95,
                                                dof=dof,
                                                wavelet=mother)

            sel = find((period >= per_min) & (period < per_max))
            Cdelta = mother.cdelta
            scale_avg = (scales * np.ones((N, 1))).transpose()
            scale_avg = power / scale_avg  # As in Torrence and Compo (1998) equation 24
            #scale_avg = var * dj * dt / Cdelta * scale_avg[sel, :].sum(axis=0)

            #scale_array[i,:] = scale_array[i,:]/np.max(scale_array[i,:])
            #data_array[i,:] = data_array[i,:]/np.max(data_array[i,:])

            scale_avg = var * dj * dt / Cdelta * scale_avg[sel, :].sum(axis=0)
            scale_avg_signif, tmp = cwt.significance(
                var,
                dt,
                scales,
                2,
                alpha,
                significance_level=0.95,
                dof=[scales[sel[0]], scales[sel[-1]]],
                wavelet=mother)
            Yticks = 2**np.arange(np.ceil(np.log2(period.min())),
                                  np.ceil(np.log2(period.max())))

            plt.close('all')
            plt.ioff()
            figprops = dict(figsize=(11, 8), dpi=72)
            fig = plt.figure(**figprops)

            wx = plt.axes([0.77, 0.75, 0.2, 0.2])
            imz = 0
            for idxy in range(0, len(period), 10):
                wx.plot(t, mother.psi(t / period[idxy]) + imz, linewidth=1.5)
                imz += 1
            wx.xaxis.set_ticklabels([])
            #wx.set_ylim([-10,10])
            # First sub-plot, the original time series anomaly and inverse wavelet
            # transform.
            ax = plt.axes([0.1, 0.75, 0.65, 0.2])
            ax.plot(t,
                    data_line - np.mean(data_line),
                    'k',
                    label="Original Data")
            ax.plot(t,
                    iwave,
                    '-',
                    linewidth=1,
                    color=[0.5, 0.5, 0.5],
                    label="Reconstructed wave")
            ax.plot(t,
                    dat_norm,
                    '--k',
                    linewidth=1.5,
                    color=[0.5, 0.5, 0.5],
                    label="Denoised Wave")
            ax.set_title(
                'a) {:10.2f} from beginning of trial.'.format(real_time))
            ax.set_ylabel(r'{} [{}]'.format("Amplitude", unit))
            ax.legend(loc=1)
            ax.set_ylim([-200, 200])
            #If the non-serrated section, bounds are 200 -
            # Second sub-plot, the normalized wavelet power spectrum and significance
            # level contour lines and cone of influece hatched area. Note that period
            # scale is logarithmic.
            bx = plt.axes([0.1, 0.37, 0.65, 0.28], sharex=ax)
            levels = [0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16]
            cont = bx.contourf(t,
                               np.log2(period),
                               np.log2(power),
                               np.log2(levels),
                               extend='both',
                               cmap=plt.cm.viridis)
            extent = [t.min(), t.max(), 0, max(period)]
            bx.contour(t,
                       np.log2(period),
                       sig95, [-99, 1],
                       colors='k',
                       linewidths=2,
                       extent=extent)
            bx.fill(np.concatenate(
                [t, t[-1:] + dt, t[-1:] + dt, t[:1] - dt, t[:1] - dt]),
                    np.concatenate([
                        np.log2(coi), [1e-9],
                        np.log2(period[-1:]),
                        np.log2(period[-1:]), [1e-9]
                    ]),
                    'k',
                    alpha=0.3,
                    hatch='x')
            bx.set_title(
                'b) {} Octaves Wavelet Power Spectrum [{}({})]'.format(
                    octaves, mother.name, order))
            bx.set_ylabel('Period (cm)')
            #
            Yticks = 2**np.arange(np.ceil(np.log2(period.min())),
                                  np.ceil(np.log2(period.max())))
            bx.set_yticks(np.log2(Yticks))
            bx.set_yticklabels(Yticks)
            cbar = fig.colorbar(cont, ax=bx)
            # Third sub-plot, the global wavelet and Fourier power spectra and theoretical
            # noise spectra. Note that period scale is logarithmic.
            cx = plt.axes([0.77, 0.37, 0.2, 0.28], sharey=bx)
            cx.plot(glbl_signif, np.log2(period), 'k--')
            cx.plot(var * fft_theor, np.log2(period), '--', color='#cccccc')
            cx.plot(var * fft_power,
                    np.log2(1. / fftfreqs),
                    '-',
                    color='#cccccc',
                    linewidth=1.)
            cx.plot(var * glbl_power, np.log2(period), 'k-', linewidth=1.5)
            cx.set_title('c) Global Wavelet Spectrum')
            cx.set_xlabel(r'Power [({})^2]'.format(unit))
            #cx.set_xlim([0, (var*fft_theor).max()])
            plt.xscale('log')
            cx.set_ylim(np.log2([period.min(), period.max()]))
            cx.set_yticks(np.log2(Yticks))
            cx.set_yticklabels(Yticks)

            #if sig_array == []:
            yvals = np.linspace(Yticks.min(), Yticks.max(), len(period))

            plt.xscale('linear')
            plt.setp(cx.get_yticklabels(), visible=False)

            # Fourth sub-plot, the scale averaged wavelet spectrum.
            dx = plt.axes([0.1, 0.07, 0.65, 0.2], sharex=ax)
            dx.axhline(scale_avg_signif,
                       color='k',
                       linestyle='--',
                       linewidth=1.)
            dx.plot(t, scale_avg, 'k-', linewidth=1.5)
            dx.set_title('d) {}-{}cm scale-averaged power'.format(
                per_min, per_max))
            dx.set_xlabel('Distance from center(cm)')
            dx.set_ylabel(r'Average variance [{}]'.format(unit))
            #dx.set_ylim([0,500])
            ax.set_xlim([t.min(), t.max()])

            #plt.savefig(directory+'{}_analysis_frame-{}.png'.format(name, idx), bbox = 'tight')
            if verbose >= 2:
                print('*' * int((i / FRAME_COUNT) * 100))

            df_wav[real_time] = (pd.Series(dat_norm, index=t))
            df_pow[real_time] = (pd.Series(var * glbl_power,
                                           index=np.log2(period)))
            df_for[real_time] = (pd.Series(var * fft_power,
                                           index=np.log2(1. / fftfreqs)))
            df_auc[real_time] = [np.trapz(data_line)]

        else:
            print("Frame #{} has dropped".format(i))
            dropped += 1

    if verbose >= 1: print('All images saved')
    if verbose >= 1:
        print("{:10.2f} % of the frames have dropped".format(
            (dropped / FRAME_COUNT) * 100))

    #Plotting and saving tyhe

    row, cols = df_pow.shape
    time = np.arange(0, cols) / FPS

    plt.close('all')
    plt.ioff()
    plt.contourf(time, df_pow.index.tolist(), df_pow)
    plt.contour(time, df_pow.index.tolist(), df_pow)
    plt.title("Global Power over Time")
    plt.ylabel("Period[cm]")
    plt.xlabel("Time")
    cax = plt.gca()
    #plt.xscale('log')
    cax.set_ylim(np.log2([period.min(), period.max()]))
    cax.set_yticks(np.log2(Yticks))
    cax.set_yticklabels(Yticks)

    plt.savefig(directory + '{}_global_power-{}.png'.format(name, idx),
                bbox='tight')

    row, cols = df_for.shape
    time = np.arange(0, cols) / FPS
    plt.close('all')
    plt.ioff()
    plt.contourf(time, df_for.index.tolist(), df_for)
    plt.contour(time, df_for.index.tolist(), df_for)
    plt.title("Fourier Power over Time")
    plt.ylabel("Period[cm]")
    plt.xlabel("Time")
    cax = plt.gca()
    #plt.xscale('log')
    cax.set_ylim(np.log2([period.min(), period.max()]))
    cax.set_yticks(np.log2(Yticks))
    cax.set_yticklabels(Yticks)
    plt.savefig(directory + '{}_fourier_power-{}.png'.format(name, idx),
                bbox='tight')

    plt.close('all')
    plt.ioff()
    rows, cols = df_auc.shape
    time = np.arange(0, cols) / FPS
    plt.plot(time, df_auc.T)
    plt.xlabel("Time")
    plt.ylabel("Area under the curve in cm")
    plt.title("Area under the curve over time")
    plt.savefig(directory + '{}_area_under_curve-{}.png'.format(name, idx),
                bbox='tight')

    df_wav['Mean'] = df_wav.mean(axis=1)
    df_pow['Mean'] = df_pow.mean(axis=1)
    df_for['Mean'] = df_for.mean(axis=1)
    df_auc['Mean'] = df_auc.mean(axis=1)

    df_wav['Standard Deviation'] = df_wav.std(axis=1)
    df_pow['Standard Deviation'] = df_pow.std(axis=1)
    df_for['Standard Deviation'] = df_for.std(axis=1)
    df_auc['Standard Deviation'] = df_auc.std(axis=1)

    ##[Writing analysis to excel]##############################################

    print("Writing files")
    writer = pd.ExcelWriter(directory + "analysis{}.xlsx".format(trial_name))
    df_wav.to_excel(writer, "Raw Waveforms")
    df_auc.to_excel(writer, "Area Under the Curve")
    df_for.to_excel(writer, "Fourier Spectra")
    df_pow.to_excel(writer, "Global Power Spectra")
    writer.save()

    ##[Writing means to a single file]#########################################

    #filename = 'C:\\pyscripts\\wavelet_analysis\\Overall_Analysis.xlsx'
    #append_data(filename, df_pow['Mean'].values,  str(trial_name), Yticks)
    ##[Plotting mean power and foruier]########################################
    plt.close('all')
    plt.ioff()
    plt.plot(df_pow['Mean'], df_pow.index.tolist(), label="Global Power")
    plt.plot(df_for['Mean'], df_for.index.tolist(), label="Fourier Power")
    plt.title("Global Power averaged over Time")
    plt.ylabel("Period[cm]")
    plt.xlabel("Power[cm^2]")
    cax = plt.gca()
    #plt.xscale('log')
    cax.set_ylim(np.log2([period.min(), period.max()]))
    cax.set_yticks(np.log2(Yticks))
    cax.set_yticklabels(Yticks)
    plt.legend()
    plt.savefig(directory + '{}_both_{}.png'.format(name, idx), bbox='tight')

    plt.close('all')
    plt.ioff()
    plt.plot(df_pow['Mean'], df_pow.index.tolist(), label="Global Power")
    plt.title("Global Power averaged over Time")
    plt.ylabel("Period[cm]")
    plt.xlabel("Power[cm^2]")
    cax = plt.gca()
    #plt.xscale('log')
    cax.set_ylim(np.log2([period.min(), period.max()]))
    cax.set_yticks(np.log2(Yticks))
    cax.set_yticklabels(Yticks)
    plt.legend()
    plt.savefig(directory + '{}_global_power_{}.png'.format(name, idx),
                bbox='tight')

    plt.close('all')
    plt.ioff()
    plt.plot(df_for['Mean'], df_for.index.tolist(), label="Fourier Power")
    plt.title("Fourier averaged over Time")
    plt.ylabel("Period[cm]")
    plt.xlabel("Power[cm^2]")
    cax = plt.gca()
    #plt.xscale('log')
    cax.set_ylim(np.log2([period.min(), period.max()]))
    cax.set_yticks(np.log2(Yticks))
    cax.set_yticklabels(Yticks)
    plt.legend()
    plt.savefig(directory + '{}_fourier_{}.png'.format(name, idx),
                bbox='tight')

    cap.release()
    return directory
def graph_wavelet(data_xs, title, lims, font = 11, params = default_params):
    a_lims, b_lims, d_lims = lims
    plt.rcParams.update({'font.size': font})
    return_data = {}
    
    N = len(data_xs)
    dt = (2*params['per_pixel'])/N #This is how much cm each pixel equals
    t = np.arange(0, N) * dt
    t = t - np.mean(t)
    t0 = 0
    per_min = params['min_per']
    per_max = params['max_per']
    units = params['units']
    sx = params['sx']
    octaves = params['octaves']
    dj = 1/params['suboctaves'] #suboctaves
    order = params['order']
    
    var, std, dat_norm = detrend(data_xs)
    mother = cwt.DOG(order) #This is the Mother Wavelet
    s0 = sx * dt #This is the starting scale, which in out case is two pixels or 0.04cm/40um\
    J = octaves/dj #This is powers of two with dj suboctaves
    
    return_data['var'] = var
    return_data['std'] = std
    
    try:
        alpha, _, _ = cwt.ar1(dat_norm) #This calculates the Lag-1 autocorrelation for red noise
    except: 
        alpha = 0.95
            
    wave, scales, freqs, coi, fft, fftfreqs = cwt.cwt(dat_norm, dt, dj, s0, J,
                                                              mother)
    return_data['scales'] = scales
    return_data['freqs'] = freqs
    return_data['fft'] = fft
    iwave = cwt.icwt(wave, scales, dt, dj, mother) * std
        
    power = (np.abs(wave)) ** 2
    fft_power = np.abs(fft) ** 2
    period = 1 / freqs
    power /= scales[:, None] #This is an option suggested by Liu et. al.
    

    #Next we calculate the significance of the power spectra. Significane where power / sig95 > 1
    signif, fft_theor = cwt.significance(1.0, dt, scales, 0, alpha,
                                             significance_level=0.95,
                                             wavelet=mother)
    sig95 = np.ones([1, N]) * signif[:, None]
    sig95 = power / sig95
    
    glbl_power = power.mean(axis=1)
    dof = N - scales  # Correction for padding at edges
    glbl_signif, tmp = cwt.significance(var, dt, scales, 1, alpha,
                                            significance_level=0.95, dof=dof,
                                            wavelet=mother)
    
    sel = find((period >= per_min) & (period < per_max))
    Cdelta = mother.cdelta
    scale_avg = (scales * np.ones((N, 1))).transpose()
    scale_avg = power / scale_avg  # As in Torrence and Compo (1998) equation 24
    scale_avg = var * dj * dt / Cdelta * scale_avg[sel, :].sum(axis=0)
    scale_avg_signif, tmp = cwt.significance(var, dt, scales, 2, alpha,
                                                 significance_level=0.95,
                                                 dof=[scales[sel[0]],
                                                      scales[sel[-1]]],
                                                 wavelet=mother)
    
    
    # Prepare the figure
    plt.close('all')
    plt.ioff()
    figprops = dict(figsize=(11, 11), dpi=72)
    fig = plt.figure(**figprops)
    
    wx = plt.axes([0.77, 0.75, 0.2, 0.2])
    imz = 0
    for idxy in range(0,len(period), 10):
        wx.plot(t, mother.psi(t / period[idxy]) + imz, linewidth = 1.5)
        imz+=1
        wx.xaxis.set_ticklabels([])
    
    ax = plt.axes([0.1, 0.75, 0.65, 0.2])
    ax.plot(t, data_xs, 'k', linewidth=1.5)
    ax.plot(t, iwave, '-', linewidth=1, color=[0.5, 0.5, 0.5])
    ax.plot(t, dat_norm, '--', linewidth=1.5, color=[0.5, 0.5, 0.5])
    if a_lims != None:
        ax.set_ylim([-a_lims, a_lims])
    ax.set_title('a) {}'.format(title))
    ax.set_ylabel(r'Displacement [{}]'.format(units))
    #ax.set_ylim([-20,20])

    bx = plt.axes([0.1, 0.37, 0.65, 0.28], sharex=ax)
    levels = [0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16]
    bx.contourf(t, np.log2(period), np.log2(power), np.log2(levels),
                extend='both', cmap=plt.cm.viridis)
    extent = [t.min(), t.max(), 0, max(period)]
    bx.contour(t, np.log2(period), sig95, [-99, 1], colors='k', linewidths=2,
               extent=extent)
    bx.fill(np.concatenate([t, t[-1:] + dt, t[-1:] + dt,
                               t[:1] - dt, t[:1] - dt]),
            np.concatenate([np.log2(coi), [1e-9], np.log2(period[-1:]),
                               np.log2(period[-1:]), [1e-9]]),
            'k', alpha=0.3, hatch='x')
    bx.set_title('b) {} Octaves Wavelet Power Spectrum [{}({})]'.format(octaves, mother.name, order))
    bx.set_ylabel('Period (cm)')
    #
    Yticks = 2 ** np.arange(np.ceil(np.log2(period.min())),
                               np.ceil(np.log2(period.max())))
    bx.set_yticks(np.log2(Yticks))
    bx.set_yticklabels(Yticks)
    
    # Third sub-plot, the global wavelet and Fourier power spectra and theoretical
    # noise spectra. Note that period scale is logarithmic.
    cx = plt.axes([0.77, 0.37, 0.2, 0.28], sharey=bx)
    cx.plot(glbl_signif, np.log2(period), 'k--')
    cx.plot(var * fft_theor, np.log2(period), '--', color='#cccccc')
    cx.plot(var * fft_power, np.log2(1./fftfreqs), '-', color='#cccccc',
            linewidth=1.)
    
    return_data['global_power'] = var * glbl_power
    return_data['fourier_spectra'] = var * fft_power
    return_data['per'] = np.log2(period)
    return_data['amp'] = np.log2(1./fftfreqs)
    
    cx.plot(var * glbl_power, np.log2(period), 'k-', linewidth=1.5)
    cx.set_title('c) Power Spectrum')
    cx.set_xlabel(r'Power [({})^2]'.format(units))
    if b_lims != None:
        cx.set_xlim([0,b_lims])
    #cx.set_xlim([0,max(glbl_power.max(), var*fft_power.max())])
    #print(max(glbl_power.max(), var*fft_power.max()))
    cx.set_ylim(np.log2([period.min(), period.max()]))
    cx.set_yticks(np.log2(Yticks))
    cx.set_yticklabels(Yticks)
    return_data['yticks'] = Yticks
    
    plt.setp(cx.get_yticklabels(), visible=False)
    
    # Fourth sub-plot, the scale averaged wavelet spectrum.
    dx = plt.axes([0.1, 0.07, 0.65, 0.2], sharex=ax)
    dx.axhline(scale_avg_signif, color='k', linestyle='--', linewidth=1.)
    dx.plot(t, scale_avg, 'k-', linewidth=1.5)
    dx.set_title('d) {}--{} cm scale-averaged power'.format(per_min, per_max))
    dx.set_xlabel('Displacement (cm)')
    dx.set_ylabel(r'Average variance [{}]'.format(units))
    ax.set_xlim([t.min(), t.max()])
    if d_lims != None:
        dx.set_ylim([0,d_lims])
    plt.savefig("C:\pyscripts\wavelet_analysis\Calibrated Images\{}".format(title))
    return fig, return_data
Example #18
0
def simple_sample(sls):
    # Then, we load the dataset and define some data related parameters. In this
    # case, the first 19 lines of the data file contain meta-data, that we ignore,
    # since we set them manually (*i.e.* title, units).
    # url = 'http://paos.colorado.edu/research/wavelets/wave_idl/nino3sst.txt'
    # dat = numpy.genfromtxt(url, skip_header=19)

    title = 'Sentence Length'
    label = 'Zhufu Sentence Length'
    units = 'Characters'
    t0 = 1
    dt = 1  # In years
    dat = numpy.array(sls)
    # We also create a time array in years.
    N = dat.size
    t = numpy.arange(0, N) * dt + t0

    # We write the following code to detrend and normalize the input data by its
    # standard deviation. Sometimes detrending is not necessary and simply
    # removing the mean value is good enough. However, if your dataset has a well
    # defined trend, such as the Mauna Loa CO\ :sub:`2` dataset available in the
    # above mentioned website, it is strongly advised to perform detrending.
    # Here, we fit a one-degree polynomial function and then subtract it from the
    # original data.
    p = numpy.polyfit(t - t0, dat, 1)
    dat_notrend = dat - numpy.polyval(p, t - t0)
    std = dat_notrend.std()  # Standard deviation
    var = std**2  # Variance
    dat_norm = dat_notrend / std  # Normalized dataset

    # The next step is to define some parameters of our wavelet analysis. We
    # select the mother wavelet, in this case the Morlet wavelet with
    # :math:`\omega_0=6`.
    mother = wavelet.Morlet(6)
    s0 = 2 * dt  # Starting scale, in this case 2 * 0.25 years = 6 months
    dj = 1 / 12  # Twelve sub-octaves per octaves
    J = 7 / dj  # Seven powers of two with dj sub-octaves
    alpha, _, _ = wavelet.ar1(dat)  # Lag-1 autocorrelation for red noise

    # The following routines perform the wavelet transform and inverse wavelet
    # transform using the parameters defined above. Since we have normalized our
    # input time-series, we multiply the inverse transform by the standard
    # deviation.
    wave, scales, freqs, coi, fft, fftfreqs = wavelet.cwt(
        dat_norm, dt, dj, s0, J, mother)
    iwave = wavelet.icwt(wave, scales, dt, dj, mother) * std

    # We calculate the normalized wavelet and Fourier power spectra, as well as
    # the Fourier equivalent periods for each wavelet scale.
    power = (numpy.abs(wave))**2
    fft_power = numpy.abs(fft)**2
    period = 1 / freqs

    # We could stop at this point and plot our results. However we are also
    # interested in the power spectra significance test. The power is significant
    # where the ratio ``power / sig95 > 1``.
    signif, fft_theor = wavelet.significance(1.0,
                                             dt,
                                             scales,
                                             0,
                                             alpha,
                                             significance_level=0.95,
                                             wavelet=mother)
    sig95 = numpy.ones([1, N]) * signif[:, None]
    sig95 = power / sig95

    # Then, we calculate the global wavelet spectrum and determine its
    # significance level.
    glbl_power = power.mean(axis=1)
    dof = N - scales  # Correction for padding at edges
    glbl_signif, tmp = wavelet.significance(var,
                                            dt,
                                            scales,
                                            1,
                                            alpha,
                                            significance_level=0.95,
                                            dof=dof,
                                            wavelet=mother)

    # We also calculate the scale average between 2 years and 8 years, and its
    # significance level.
    sel = find((period >= 2) & (period < 8))
    Cdelta = mother.cdelta
    scale_avg = (scales * numpy.ones((N, 1))).transpose()
    scale_avg = power / scale_avg  # As in Torrence and Compo (1998) equation 24
    scale_avg = var * dj * dt / Cdelta * scale_avg[sel, :].sum(axis=0)
    scale_avg_signif, tmp = wavelet.significance(
        var,
        dt,
        scales,
        2,
        alpha,
        significance_level=0.95,
        dof=[scales[sel[0]], scales[sel[-1]]],
        wavelet=mother)

    # Finally, we plot our results in four different subplots containing the
    # (i) original series anomaly and the inverse wavelet transform; (ii) the
    # wavelet power spectrum (iii) the global wavelet and Fourier spectra ; and
    # (iv) the range averaged wavelet spectrum. In all sub-plots the significance
    # levels are either included as dotted lines or as filled contour lines.

    # Prepare the figure
    pyplot.close('all')
    pyplot.ioff()
    figprops = dict(figsize=(11, 8), dpi=72)
    fig = pyplot.figure(**figprops)

    # First sub-plot, the original time series anomaly and inverse wavelet
    # transform.
    ax = pyplot.axes([0.1, 0.75, 0.65, 0.2])
    ax.plot(t, iwave, '-', linewidth=1, color=[0.5, 0.5, 0.5])
    ax.plot(t, dat, 'k', linewidth=1.5)
    ax.set_title('a) {}'.format(title))
    ax.set_ylabel(r'{} [{}]'.format(label, units))

    # Second sub-plot, the normalized wavelet power spectrum and significance
    # level contour lines and cone of influece hatched area. Note that period
    # scale is logarithmic.
    bx = pyplot.axes([0.1, 0.37, 0.65, 0.28], sharex=ax)
    levels = [0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16]
    bx.contourf(t,
                numpy.log2(period),
                numpy.log2(power),
                numpy.log2(levels),
                extend='both',
                cmap=pyplot.cm.viridis)
    extent = [t.min(), t.max(), 0, max(period)]
    bx.contour(t,
               numpy.log2(period),
               sig95, [-99, 1],
               colors='k',
               linewidths=2,
               extent=extent)
    bx.fill(numpy.concatenate(
        [t, t[-1:] + dt, t[-1:] + dt, t[:1] - dt, t[:1] - dt]),
            numpy.concatenate([
                numpy.log2(coi), [1e-9],
                numpy.log2(period[-1:]),
                numpy.log2(period[-1:]), [1e-9]
            ]),
            'k',
            alpha=0.3,
            hatch='x')
    bx.set_title('b) {} Wavelet Power Spectrum ({})'.format(
        label, mother.name))
    bx.set_ylabel('Period (years)')
    #
    Yticks = 2**numpy.arange(numpy.ceil(numpy.log2(period.min())),
                             numpy.ceil(numpy.log2(period.max())))
    bx.set_yticks(numpy.log2(Yticks))
    bx.set_yticklabels(Yticks)

    # Third sub-plot, the global wavelet and Fourier power spectra and theoretical
    # noise spectra. Note that period scale is logarithmic.
    cx = pyplot.axes([0.77, 0.37, 0.2, 0.28], sharey=bx)
    cx.plot(glbl_signif, numpy.log2(period), 'k--')
    cx.plot(var * fft_theor, numpy.log2(period), '--', color='#cccccc')
    cx.plot(var * fft_power,
            numpy.log2(1. / fftfreqs),
            '-',
            color='#cccccc',
            linewidth=1.)
    cx.plot(var * glbl_power, numpy.log2(period), 'k-', linewidth=1.5)
    cx.set_title('c) Global Wavelet Spectrum')
    cx.set_xlabel(r'Power [({})^2]'.format(units))
    cx.set_xlim([0, glbl_power.max() + var])
    cx.set_ylim(numpy.log2([period.min(), period.max()]))
    cx.set_yticks(numpy.log2(Yticks))
    cx.set_yticklabels(Yticks)
    pyplot.setp(cx.get_yticklabels(), visible=False)

    # Third sub-plot, the global wavelet and Fourier power spectra and theoretical
    # noise spectra. Note that period scale is logarithmic.
    dx = pyplot.axes([0.1, 0.07, 0.65, 0.2])
    dx.plot(numpy.log2(fftfreqs), numpy.log2(fft_power), 'k')
    dx.plot(numpy.log2(freqs), var * fft_theor, '--', color='#cccccc')
    dx.plot(numpy.log2(1. / fftfreqs),
            var * fft_power,
            '-',
            color='#cccccc',
            linewidth=1.)
    dx.plot(fftfreqs, fft_power, 'k-', linewidth=1.5)
    dx.set_title('d) Global Wavelet Spectrum')
    dx.set_ylabel(r'Power [({})^2]'.format(units))
    dx.set_xlim([0, 2 * fftfreqs.max()])

    Yticks = 2**numpy.arange(numpy.ceil(numpy.log2(fft_power.min())),
                             numpy.ceil(numpy.log2(fft_power.max())))
    dx.set_ylim(numpy.log2([fft_power.min(), fft_power.max()]))
    dx.set_yticks(numpy.log2(Yticks))
    dx.set_yticklabels(Yticks)
    pyplot.setp(dx.get_yticklabels(), visible=False)

    pyplot.show()