1 | ;************************************************************** WAVETEST |
---|
2 | ;+ |
---|
3 | ; NAME: WAVETEST |
---|
4 | ; |
---|
5 | ; PURPOSE: Example IDL program for WAVELET, using NINO3 SST dataset |
---|
6 | ; |
---|
7 | ; EXECUTION: |
---|
8 | ; |
---|
9 | ; IDL> .run wavetest |
---|
10 | ; |
---|
11 | ; |
---|
12 | ; See "http://paos.colorado.edu/research/wavelets/" |
---|
13 | ; Written January 1998 by C. Torrence |
---|
14 | ; |
---|
15 | ;- |
---|
16 | ;************************************************************** |
---|
17 | |
---|
18 | n = 504 |
---|
19 | sst = FLTARR(n) |
---|
20 | OPENR,1,'sst_nino3.dat' ; input SST time series |
---|
21 | READF,1,sst |
---|
22 | CLOSE,1 |
---|
23 | |
---|
24 | ;------------------------------------------------------ Computation |
---|
25 | |
---|
26 | ; normalize by standard deviation (not necessary, but makes it easier |
---|
27 | ; to compare with plot on Interactive Wavelet page, at |
---|
28 | ; "http://paos.colorado.edu/research/wavelets/plot/" |
---|
29 | sst = (sst - TOTAL(sst)/n) |
---|
30 | |
---|
31 | dt = 0.25 |
---|
32 | time = FINDGEN(n)*dt + 1871.0 ; construct time array |
---|
33 | xrange = [1870,2000] ; plotting range |
---|
34 | pad = 1 |
---|
35 | s0 = dt ; this says start at a scale of 3 months |
---|
36 | dj = 0.25 ; this will do 4 sub-octaves per octave |
---|
37 | j1 = 9./dj ; this says do 9 powers-of-two with dj sub-octaves each |
---|
38 | mother = 'Morlet' |
---|
39 | recon_sst = sst ; save an extra copy, so we don't erase original sst |
---|
40 | |
---|
41 | ; estimate lag-1 autocorrelation, for red-noise significance tests |
---|
42 | ; Note that we actually use the global wavelet spectrum (GWS) |
---|
43 | ; for the significance tests, but if you wanted to use red noise, |
---|
44 | ; here's how you could calculate it... |
---|
45 | lag1 = (A_CORRELATE(sst,1) + SQRT(A_CORRELATE(sst,2)))/2. |
---|
46 | |
---|
47 | ; Wavelet transform: |
---|
48 | wave = WAVELET(recon_sst,dt,PERIOD=period,SCALE=scale,S0=s0, $ |
---|
49 | PAD=pad,COI=coi,DJ=dj,J=j1,MOTHER=mother,/RECON) |
---|
50 | power = (ABS(wave))^2 ; compute wavelet power spectrum |
---|
51 | global_ws = TOTAL(power,1)/n ; global wavelet spectrum (GWS) |
---|
52 | J = N_ELEMENTS(scale) - 1 |
---|
53 | |
---|
54 | ; Significance levels, assuming the GWS as background spectrum: |
---|
55 | signif = WAVE_SIGNIF(sst,dt,scale,0, $ |
---|
56 | GWS=global_ws,SIGLVL=0.90,MOTHER=mother) |
---|
57 | signif = REBIN(TRANSPOSE(signif),n,J+1) ; expand signif --> (J+1)x(N) array |
---|
58 | signif = power/signif ; where ratio > 1, power is significant |
---|
59 | |
---|
60 | ; GWS significance levels: |
---|
61 | dof = n - scale ; the -scale corrects for padding at edges |
---|
62 | global_signif = WAVE_SIGNIF(sst,dt,scale,1, $ |
---|
63 | LAG1=0.0,DOF=dof,MOTHER=mother,CDELTA=Cdelta,PSI0=psi0) |
---|
64 | |
---|
65 | ; check total variance (Parseval's theorem) [Eqn(14)] |
---|
66 | scale_avg = REBIN(TRANSPOSE(scale),n,J+1) ; expand scale-->(J+1)x(N) array |
---|
67 | power_norm = power/scale_avg |
---|
68 | variance = (MOMENT(sst))(1) |
---|
69 | recon_variance = dj*dt/(Cdelta*n)*TOTAL(power_norm) ; [Eqn(14)] |
---|
70 | |
---|
71 | IF (N_ELEMENTS(recon_sst) GT 1) THEN BEGIN |
---|
72 | recon_variance = (MOMENT(recon_sst))(1) |
---|
73 | ; RMS of Reconstruction [Eqn(11)] |
---|
74 | rms_error = SQRT(TOTAL((sst - recon_sst)^2)/n) |
---|
75 | PRINT |
---|
76 | PRINT,' ******** RECONSTRUCTION ********' |
---|
77 | PRINT,'original variance =',variance,' degC^2' |
---|
78 | PRINT,'reconstructed var =',FLOAT(recon_variance),' degC^2' |
---|
79 | PRINT,'Ratio = ',recon_variance/variance |
---|
80 | PRINT,'root-mean-square error of reconstructed sst = ',rms_error,' degC' |
---|
81 | PRINT |
---|
82 | IF (mother EQ 'DOG') THEN BEGIN |
---|
83 | PRINT,'Note: for better reconstruction with the DOG, you need' |
---|
84 | PRINT,' to use a very small s0.' |
---|
85 | ENDIF |
---|
86 | PRINT |
---|
87 | ENDIF |
---|
88 | |
---|
89 | ; Scale-average between El Nino periods of 2--8 years |
---|
90 | avg = WHERE((scale GE 2) AND (scale LT 8)) |
---|
91 | scale_avg = dj*dt/Cdelta*TOTAL(power_norm(*,avg),2) ; [Eqn(24)] |
---|
92 | scaleavg_signif = WAVE_SIGNIF(sst,dt,scale,2, $ |
---|
93 | GWS=global_ws,SIGLVL=0.90,DOF=[2,7.9],MOTHER=mother) |
---|
94 | |
---|
95 | |
---|
96 | ;------------------------------------------------------ Plotting |
---|
97 | printfile = 1 |
---|
98 | |
---|
99 | !P.FONT = -1 |
---|
100 | !P.CHARSIZE = 1 |
---|
101 | IF (printfile) THEN BEGIN |
---|
102 | SET_PLOT,'ps' |
---|
103 | DEVICE,/PORT,/INCH,XSIZE=6.5,XOFF=1,YSIZE=6,YOFF=3,/COLOR,BITS=8 |
---|
104 | !P.FONT = 0 |
---|
105 | !P.CHARSIZE = 0.75 |
---|
106 | ENDIF ELSE WINDOW,0,XSIZE=600,YSIZE=600 |
---|
107 | !P.MULTI = 0 |
---|
108 | !X.STYLE = 1 |
---|
109 | !Y.STYLE = 1 |
---|
110 | LOADCT,39 |
---|
111 | |
---|
112 | ;--- Plot time series |
---|
113 | pos1 = [0.1,0.75,0.7,0.95] |
---|
114 | PLOT,time,sst,XRANGE=xrange, $ |
---|
115 | XTITLE='Time (year)',YTITLE='NINO3 SST (!Uo!NC)', $ |
---|
116 | TITLE='a) NINO3 Sea Surface Temperature (seasonal)', $ |
---|
117 | POSITION=pos1 |
---|
118 | IF (N_ELEMENTS(recon_sst) GT 1) THEN OPLOT,time,recon_sst,COLOR=144 |
---|
119 | XYOUTS,0.85,0.9,/NORMAL,ALIGN=0.5, $ |
---|
120 | '!5WAVELET ANALYSIS!X'+$ |
---|
121 | '!C!CC. Torrence & G.P. Compo'+$ |
---|
122 | '!C!Chttp://paos.colorado.edu/!Cresearch/wavelets/' |
---|
123 | |
---|
124 | ;--- Contour plot wavelet power spectrum |
---|
125 | yrange = [64,0.5] ; years |
---|
126 | levels = [0.5,1,2,4] |
---|
127 | colors = [64,128,208,254] |
---|
128 | period2 = FIX(ALOG(period)/ALOG(2)) ; integer powers of 2 in period |
---|
129 | ytickv = 2.^(period2(UNIQ(period2))) ; unique powers of 2 |
---|
130 | pos2 = [pos1(0),0.35,pos1(2),0.65] |
---|
131 | |
---|
132 | CONTOUR,power,time,period,/NOERASE,POSITION=pos2, $ |
---|
133 | XRANGE=xrange,YRANGE=yrange,/YTYPE, $ |
---|
134 | YTICKS=N_ELEMENTS(ytickv)-1,YTICKV=ytickv, $ |
---|
135 | LEVELS=levels,C_COLORS=colors,/FILL, $ |
---|
136 | XTITLE='Time (year)',YTITLE='Period (years)', $ |
---|
137 | TITLE='b) Wavelet Power Spectrum (contours at 0.5,1,2,4!Uo!NC!U2!N)' |
---|
138 | ; significance contour, levels at -99 (fake) and 1 (significant) |
---|
139 | CONTOUR,signif,time,period,/OVERPLOT,LEVEL=1,THICK=2, $ |
---|
140 | C_LABEL=1,C_ANNOT='90%',C_CHARSIZE=1 |
---|
141 | ; cone-of-influence, anything "below" is dubious |
---|
142 | x = [time(0),time,MAX(time)] |
---|
143 | y = [MAX(period),coi,MAX(period)] |
---|
144 | color = 4 |
---|
145 | POLYFILL,x,y,ORIEN=+45,SPACING=0.5,COLOR=color,NOCLIP=0,THICK=1 |
---|
146 | POLYFILL,x,y,ORIEN=-45,SPACING=0.5,COLOR=color,NOCLIP=0,THICK=1 |
---|
147 | PLOTS,time,coi,COLOR=color,NOCLIP=0,THICK=1 |
---|
148 | |
---|
149 | ;--- Plot global wavelet spectrum |
---|
150 | pos3 = [0.74,pos2(1),0.95,pos2(3)] |
---|
151 | blank = REPLICATE(' ',29) |
---|
152 | PLOT,global_ws,period,/NOERASE,POSITION=pos3, $ |
---|
153 | THICK=2,XSTYLE=10,YSTYLE=9, $ |
---|
154 | YRANGE=yrange,/YTYPE,YTICKLEN=-0.02, $ |
---|
155 | XTICKS=2,XMINOR=2, $ |
---|
156 | YTICKS=N_ELEMENTS(ytickv)-1,YTICKV=ytickv,YTICKNAME=blank, $ |
---|
157 | XTITLE='Power (!Uo!NC!U2!N)',TITLE='c) Global' |
---|
158 | OPLOT,global_signif,period,LINES=1 |
---|
159 | XYOUTS,1.7,60,'95%' |
---|
160 | |
---|
161 | ;--- Plot 2--8 yr scale-average time series |
---|
162 | pos4 = [pos1(0),0.05,pos1(2),0.25] |
---|
163 | PLOT,time,scale_avg,/NOERASE,POSITION=pos4, $ |
---|
164 | XRANGE=xrange,YRANGE=[0,MAX(scale_avg)*1.25],THICK=2, $ |
---|
165 | XTITLE='Time (year)',YTITLE='Avg variance (!Uo!NC!U2!N)', $ |
---|
166 | TITLE='d) 2-8 yr Scale-average Time Series' |
---|
167 | OPLOT,xrange,scaleavg_signif+[0,0],LINES=1 |
---|
168 | |
---|
169 | IF (printfile) THEN DEVICE,/CLOSE |
---|
170 | END |
---|