source: trunk/procs/tools_wavelets/wavelet.pro @ 2

Last change on this file since 2 was 2, checked in by post_it, 17 years ago

Initial import from ~/POST_IT/

File size: 12.2 KB
Line 
1;******************************************************************* WAVELET
2;+
3; NAME:   WAVELET
4;
5; PURPOSE:   Compute the WAVELET transform of a 1D time series.
6;       
7;
8; CALLING SEQUENCE:
9;
10;      wave = WAVELET(Y,DT)
11;
12;
13; INPUTS:
14;
15;    Y = the time series of length N.
16;
17;    DT = amount of time between each Y value, i.e. the sampling time.
18;
19;
20; OUTPUTS:
21;
22;    WAVE is the WAVELET transform of Y. This is a complex array
23;    of dimensions (N,J+1). FLOAT(WAVE) gives the WAVELET amplitude,
24;    ATAN(IMAGINARY(WAVE),FLOAT(WAVE)) gives the WAVELET phase.
25;    The WAVELET power spectrum is ABS(WAVE)^2.
26;
27;
28; OPTIONAL KEYWORD INPUTS:
29;
30;    S0 = the smallest scale of the wavelet.  Default is 2*DT.
31;
32;    DJ = the spacing between discrete scales. Default is 0.125.
33;         A smaller # will give better scale resolution, but be slower to plot.
34;
35;    J = the # of scales minus one. Scales range from S0 up to S0*2^(J*DJ),
36;        to give a total of (J+1) scales. Default is J = (LOG2(N DT/S0))/DJ.
37;
38;    MOTHER = A string giving the mother wavelet to use.
39;            Currently, 'Morlet','Paul','DOG' (derivative of Gaussian)
40;            are available. Default is 'Morlet'.
41;
42;    PARAM = optional mother wavelet parameter.
43;            For 'Morlet' this is k0 (wavenumber), default is 6.
44;            For 'Paul' this is m (order), default is 4.
45;            For 'DOG' this is m (m-th derivative), default is 2.
46;
47;    PAD = if set, then pad the time series with enough zeroes to get
48;         N up to the next higher power of 2. This prevents wraparound
49;         from the end of the time series to the beginning, and also
50;         speeds up the FFT's used to do the wavelet transform.
51;         This will not eliminate all edge effects (see COI below).
52;
53;    LAG1 = LAG 1 Autocorrelation, used for SIGNIF levels. Default is 0.0
54;
55;    SIGLVL = significance level to use. Default is 0.95
56;
57;    VERBOSE = if set, then print out info for each analyzed scale.
58;
59;    RECON = if set, then reconstruct the time series, and store in Y.
60;            Note that this will destroy the original time series,
61;            so be sure to input a dummy copy of Y.
62;
63;    FFT_THEOR = theoretical background spectrum as a function of
64;                Fourier frequency. This will be smoothed by the
65;                wavelet function and returned as a function of PERIOD.
66;
67;
68; OPTIONAL KEYWORD OUTPUTS:
69;
70;    PERIOD = the vector of "Fourier" periods (in time units) that corresponds
71;           to the SCALEs.
72;
73;    SCALE = the vector of scale indices, given by S0*2^(j*DJ), j=0...J
74;            where J+1 is the total # of scales.
75;
76;    COI = if specified, then return the Cone-of-Influence, which is a vector
77;        of N points that contains the maximum period of useful information
78;        at that particular time.
79;        Periods greater than this are subject to edge effects.
80;        This can be used to plot COI lines on a contour plot by doing:
81;            IDL>  CONTOUR,wavelet,time,period
82;            IDL>  PLOTS,time,coi,NOCLIP=0
83;
84;    YPAD = returns the padded time series that was actually used in the
85;         wavelet transform.
86;
87;    DAUGHTER = if initially set to 1, then return the daughter wavelets.
88;         This is a complex array of the same size as WAVELET. At each scale
89;         the daughter wavelet is located in the center of the array.
90;
91;    SIGNIF = output significance levels as a function of PERIOD
92;
93;    FFT_THEOR = output theoretical background spectrum (smoothed by the
94;                wavelet function), as a function of PERIOD.
95;
96;
97; [ Defunct INPUTS:
98; [   OCT = the # of octaves to analyze over.           ]
99; [         Largest scale will be S0*2^OCT.             ]
100; [         Default is (LOG2(N) - 1).                   ]
101; [   VOICE = # of voices in each octave. Default is 8. ]
102; [          Higher # gives better scale resolution,    ]
103; [          but is slower to plot.                     ]
104; ]
105;
106;----------------------------------------------------------------------------
107;
108; EXAMPLE:
109;
110;    IDL> ntime = 256
111;    IDL> y = RANDOMN(s,ntime)       ;*** create a random time series
112;    IDL> dt = 0.25
113;    IDL> time = FINDGEN(ntime)*dt   ;*** create the time index
114;    IDL>
115;    IDL> wave = WAVELET(y,dt,PERIOD=period,COI=coi,/PAD,SIGNIF=signif)
116;    IDL> nscale = N_ELEMENTS(period)
117;    IDL> LOADCT,39
118;    IDL> CONTOUR,ABS(wave)^2,time,period, $
119;       XSTYLE=1,XTITLE='Time',YTITLE='Period',TITLE='Noise Wavelet', $
120;       YRANGE=[MAX(period),MIN(period)], $   ;*** Large-->Small period
121;       /YTYPE, $                             ;*** make y-axis logarithmic
122;       NLEVELS=25,/FILL
123;    IDL>
124;    IDL> signif = REBIN(TRANSPOSE(signif),ntime,nscale)
125;    IDL> CONTOUR,ABS(wave)^2/signif,time,period, $
126;           /OVERPLOT,LEVEL=1.0,C_ANNOT='95%'
127;    IDL> PLOTS,time,coi,NOCLIP=0   ;*** anything "below" this line is dubious
128;
129;
130;----------------------------------------------------------------------------
131; Copyright (C) 1995-2004, Christopher Torrence and Gilbert P. Compo
132;
133; This software may be used, copied, or redistributed as long as it is not
134; sold and this copyright notice is reproduced on each copy made.
135; This routine is provided as is without any express or implied warranties
136; whatsoever.
137;
138; Notice: Please acknowledge the use of the above software in any publications:
139;    ``Wavelet software was provided by C. Torrence and G. Compo,
140;      and is available at URL: http://paos.colorado.edu/research/wavelets/''.
141;
142; Reference: Torrence, C. and G. P. Compo, 1998: A Practical Guide to
143;            Wavelet Analysis. <I>Bull. Amer. Meteor. Soc.</I>, 79, 61-78.
144;
145; Please send a copy of such publications to either C. Torrence or G. Compo:
146;  Dr. Christopher Torrence               Dr. Gilbert P. Compo
147;  Research Systems, Inc.                 Climate Diagnostics Center
148;  4990 Pearl East Circle                 325 Broadway R/CDC1
149;  Boulder, CO 80301, USA                 Boulder, CO 80305-3328, USA
150;  E-mail: chris[AT]rsinc[DOT]com         E-mail: compo[AT]colorado[DOT]edu
151;----------------------------------------------------------------------------
152;-
153
154FUNCTION morlet, $ ;*********************************************** MORLET
155        k0,scale,k,period,coi,dofmin,Cdelta,psi0
156
157        IF (k0 EQ -1) THEN k0 = 6d
158        n = N_ELEMENTS(k)
159        expnt = -(scale*k - k0)^2/2d*(k GT 0.)
160        dt = 2*!PI/(n*k(1))
161        norm = SQRT(2*!PI*scale/dt)*(!PI^(-0.25))   ; total energy=N   [Eqn(7)]
162        morlet = norm*EXP(expnt > (-100d))
163        morlet = morlet*(expnt GT -100)  ; avoid underflow errors
164        morlet = morlet*(k GT 0.)  ; Heaviside step function (Morlet is complex)
165        fourier_factor = (4*!PI)/(k0 + SQRT(2+k0^2)) ; Scale-->Fourier [Sec.3h]
166        period = scale*fourier_factor
167        coi = fourier_factor/SQRT(2)   ; Cone-of-influence [Sec.3g]
168        dofmin = 2   ; Degrees of freedom with no smoothing
169        Cdelta = -1
170        IF (k0 EQ 6) THEN Cdelta = 0.776 ; reconstruction factor
171        psi0 = !PI^(-0.25)
172;       PRINT,scale,n,SQRT(TOTAL(ABS(morlet)^2,/DOUBLE))
173        RETURN,morlet
174END
175
176FUNCTION paul, $ ;************************************************** PAUL
177        m,scale,k,period,coi,dofmin,Cdelta,psi0
178
179        IF (m EQ -1) THEN m = 4d
180        n = N_ELEMENTS(k)
181        expnt = -(scale*k)*(k GT 0.)
182        dt = 2d*!PI/(n*k(1))
183        norm = SQRT(2*!PI*scale/dt)*(2^m/SQRT(m*FACTORIAL(2*m-1)))
184        paul = norm*((scale*k)^m)*EXP(expnt > (-100d))*(expnt GT -100)
185        paul = paul*(k GT 0.)
186        fourier_factor = 4*!PI/(2*m+1)
187        period = scale*fourier_factor
188        coi = fourier_factor*SQRT(2)
189        dofmin = 2   ; Degrees of freedom with no smoothing
190        Cdelta = -1
191        IF (m EQ 4) THEN Cdelta = 1.132 ; reconstruction factor
192        psi0 = 2.^m*FACTORIAL(m)/SQRT(!PI*FACTORIAL(2*m))
193;       PRINT,scale,n,norm,SQRT(TOTAL(paul^2,/DOUBLE))*SQRT(n)
194        RETURN,paul
195END
196
197FUNCTION dog, $ ;*************************************************** DOG
198        m,scale,k,period,coi,dofmin,Cdelta,psi0
199
200        IF (m EQ -1) THEN m = 2
201        n = N_ELEMENTS(k)
202        expnt = -(scale*k)^2/2d
203        dt = 2d*!PI/(n*k(1))
204        norm = SQRT(2*!PI*scale/dt)*SQRT(1d/GAMMA(m+0.5))
205        I = DCOMPLEX(0,1)
206        gauss = -norm*(I^m)*(scale*k)^m*EXP(expnt > (-100d))*(expnt GT -100)
207        fourier_factor = 2*!PI*SQRT(2./(2*m+1))
208        period = scale*fourier_factor
209        coi = fourier_factor/SQRT(2)
210        dofmin = 1   ; Degrees of freedom with no smoothing
211        Cdelta = -1
212        psi0 = -1
213        IF (m EQ 2) THEN BEGIN
214                Cdelta = 3.541 ; reconstruction factor
215                psi0 = 0.867325
216        ENDIF
217        IF (m EQ 6) THEN BEGIN
218                Cdelta = 1.966 ; reconstruction factor
219                psi0 = 0.88406
220        ENDIF
221;       PRINT,scale,n,norm,SQRT(TOTAL(ABS(gauss)^2,/DOUBLE))*SQRT(n)
222        RETURN,gauss
223END
224
225
226;****************************************************************** WAVELET
227FUNCTION wavelet,y1,dt, $   ;*** required inputs
228        S0=s0,DJ=dj,J=j, $   ;*** optional inputs
229        PAD=pad,MOTHER=mother,PARAM=param, $
230        VERBOSE=verbose,NO_WAVE=no_wave,RECON=recon, $
231        LAG1=lag1,SIGLVL=siglvl,DOF=dof,GLOBAL=global, $   ;*** optional inputs
232        SCALE=scale,PERIOD=period,YPAD=ypad, $  ;*** optional outputs
233        DAUGHTER=daughter,COI=coi, $
234        SIGNIF=signif,FFT_THEOR=fft_theor, $
235        OCT=oct,VOICE=voice   ;*** defunct inputs
236       
237        ON_ERROR,2
238        r = CHECK_MATH(0,1)
239        n = N_ELEMENTS(y1)
240        n1 = n
241        base2 = FIX(ALOG(n)/ALOG(2) + 0.4999)   ; power of 2 nearest to N
242
243;....check keywords & optional inputs
244        IF (N_ELEMENTS(s0) LT 1) THEN s0 = 2.0*dt
245        IF (N_ELEMENTS(voice) EQ 1) THEN dj = 1./voice
246        IF (N_ELEMENTS(dj) LT 1) THEN dj = 1./8
247        IF (N_ELEMENTS(oct) EQ 1) THEN J = FLOAT(oct)/dj
248        IF (N_ELEMENTS(J) LT 1) THEN J=FIX((ALOG(FLOAT(n)*dt/s0)/ALOG(2))/dj)  ;[Eqn(10)]
249        IF (N_ELEMENTS(mother) LT 1) THEN mother = 'MORLET'
250        IF (N_ELEMENTS(param) LT 1) THEN param = -1
251        IF (N_ELEMENTS(siglvl) LT 1) THEN siglvl = 0.95
252        IF (N_ELEMENTS(lag1) LT 1) THEN lag1 = 0.0
253        lag1 = lag1(0)
254        verbose = KEYWORD_SET(verbose)
255        do_daughter = KEYWORD_SET(daughter)
256        do_wave = NOT KEYWORD_SET(no_wave)
257        recon = KEYWORD_SET(recon)
258        IF KEYWORD_SET(global) THEN MESSAGE, $
259                'Please use WAVE_SIGNIF for global significance tests'
260               
261;....construct time series to analyze, pad if necessary
262        ypad = y1 - TOTAL(y1)/n    ; remove mean
263        IF KEYWORD_SET(pad) THEN BEGIN   ; pad with extra zeroes, up to power of 2
264                ypad = [ypad,FLTARR(2L^(base2 + 1) - n)]
265                n = N_ELEMENTS(ypad)
266        ENDIF
267
268;....construct SCALE array & empty PERIOD & WAVE arrays
269        na = J + 1                  ; # of scales
270        scale = DINDGEN(na)*dj      ; array of j-values
271        scale = 2d0^(scale)*s0      ; array of scales  2^j   [Eqn(9)]
272        period = FLTARR(na,/NOZERO) ; empty period array (filled in below)
273        wave = COMPLEXARR(n,na,/NOZERO)  ; empty wavelet array
274        IF (do_daughter) THEN daughter = wave   ; empty daughter array
275
276;....construct wavenumber array used in transform [Eqn(5)]
277        k = (DINDGEN(n/2) + 1)*(2*!PI)/(DOUBLE(n)*dt)
278        k = [0d,k,-REVERSE(k(0:(n-1)/2 - 1))]
279
280;....compute FFT of the (padded) time series
281        yfft = FFT(ypad,-1,/DOUBLE)  ; [Eqn(3)]
282
283        IF (verbose) THEN BEGIN  ;verbose
284                PRINT
285                PRINT,mother
286                PRINT,'#points=',n1,'   s0=',s0,'   dj=',dj,'   J=',FIX(J)
287                IF (n1 NE n) THEN PRINT,'(padded with ',n-n1,' zeroes)'
288                PRINT,['j','scale','period','variance','mathflag'], $
289                        FORMAT='(/,A3,3A11,A10)'
290        ENDIF  ;verbose
291        IF (N_ELEMENTS(fft_theor) EQ n) THEN fft_theor_k = fft_theor ELSE $
292                fft_theor_k = (1-lag1^2)/(1-2*lag1*COS(k*dt)+lag1^2)  ; [Eqn(16)]
293        fft_theor = FLTARR(na)
294       
295;....loop thru each SCALE
296        FOR a1=0,na-1 DO BEGIN  ;scale
297                psi_fft=CALL_FUNCTION(mother, $
298                        param,scale(a1),k,period1,coi,dofmin,Cdelta,psi0)
299                IF (do_wave) THEN $
300                        wave(*,a1) = FFT(yfft*psi_fft,1,/DOUBLE)  ;wavelet transform[Eqn(4)]
301                period(a1) = period1   ; save period
302                fft_theor(a1) = TOTAL((ABS(psi_fft)^2)*fft_theor_k)/n
303                IF (do_daughter) THEN $
304                        daughter(*,a1) = FFT(psi_fft,1,/DOUBLE)   ; save daughter
305                IF (verbose) THEN PRINT,a1,scale(a1),period(a1), $
306                                TOTAL(ABS(wave(*,a1))^2),CHECK_MATH(0), $
307                                FORMAT='(I3,3F11.3,I6)'
308        ENDFOR  ;scale
309
310        coi = coi*[FINDGEN((n1+1)/2),REVERSE(FINDGEN(n1/2))]*dt   ; COI [Sec.3g]
311       
312        IF (do_daughter) THEN $   ; shift so DAUGHTERs are in middle of array
313                daughter = [daughter(n-n1/2:*,*),daughter(0:n1/2-1,*)]
314
315;....significance levels [Sec.4]
316        sdev = (MOMENT(y1))(1)
317        fft_theor = sdev*fft_theor  ; include time-series variance
318        dof = dofmin
319        signif = fft_theor*CHISQR_CVF(1. - siglvl,dof)/dof   ; [Eqn(18)]
320
321        IF (recon) THEN BEGIN  ; Reconstruction [Eqn(11)]
322                IF (Cdelta EQ -1) THEN BEGIN
323                        y1 = -1
324                        MESSAGE,/INFO, $
325                                'Cdelta undefined, cannot reconstruct with this wavelet'
326                ENDIF ELSE BEGIN
327                        y1=dj*SQRT(dt)/(Cdelta*psi0)*(FLOAT(wave) # (1./SQRT(scale)))
328                        y1 = y1[0:n1-1]
329                ENDELSE
330        ENDIF
331       
332        RETURN,wave(0:n1-1,*)    ; get rid of padding before returning
333
334END
Note: See TracBrowser for help on using the repository browser.