function hilbert_trans,x,d, analytic = a
on_error,2
y=fft(x,-1)
n=n_elements(y)
i=complex(0.0,-1.0)
if n_params(x) eq 2 then i=i*d
n2=ceil(n/2.)-1
y(0) = complex(0,0)
y(1)=y(1:n2)*i
if (n mod 2) eq 0 then y(n2+1) = complex(0,0)
n2=n-n2
y(n2)=y(n2:n-1)/i
y=float(fft(y,1))
if keyword_set(a) then y = complex(x,y)
return,y
end
function gaussian_window, l, w
if w ne 0.0 then sigma = l/(2*!PI*w) else message,'width is zero!'
g = fltarr(l)
iarr = findgen(l)
ex = (iarr - l/2)^2/(2*sigma^2)
wl = where(ex lt 25)
g(wl) = exp(-ex(wl))
g = shift(g,-l/2)
return, complex(g,0)
end
FUNCTION s_trans, ts, factor, help = help,verbose = verbose, samplingrate = samplingrate $
,maxfreq = maxfreq, minfreq = minfreq $
,freqsamplingrate = freqsamplingrate $
,power = power, abs = abs, removeedge = removeedge $
,maskedges=maskedges,example = example
if keyword_set(example) then begin
ex_len = 512
ex_time = findgen(ex_len)
ex_freq = 5
ex_ts = cos(2*!Pi*ex_freq*ex_time/ex_len)
ex_ts = cos(2*!Pi*(ex_len/5+2*ex_ts)*ex_time/ex_len)
!P.multi=[0,1,2]
plot,ex_ts,xtitle='Time (units)',title='Time Series [h(t) = cos(cos(wt))]'
s = s_trans(ex_ts,/samp, /abs)
contour,s.st,ex_time,s.freq,nlevels=14,/fill,xtitle='Time (units)', ytitle='Frequency (1/unit)',title='Amplitude of S-Transform'
return,0
!P.multi=0
endif
if keyword_set(HELP) then begin
print,"S_TRANS() HELP COMMAND"
print,"S_trans() returns a matrix if succesful or a structure if required"
print,"S_trans() returns - 1 or an error message if it fails"
print,"USAGE:: localspectra = s_trans(timeseries)
print," "
print,"Optional Parameters"
print,"width -size of time resolution"
print," -if not set, default WIDTH = 1"
print," "
print,"Keywords:
print,"\help -explains all the keywords and parameters
print,"\verbose -flags errors and size, tells time left etc.
print,"\samplingrate -if set returns array of frequency
print,"\maxfreq
print,"\minfreq
print,"\freqsamplingrate
print,"\power -returns the power spectrum
print,"\abs -returns the absolute value spectrum
print,"\removeedge -removes the edge with a 5% taper, and takes
print," -out least-squares fit parabola
return, -1
endif
CASE N_PARAMS() OF
1: begin
if n_elements(ts) eq 0 then MESSAGE, 'Invalid timeseries (check your spelling).'
factor = 1
end
2: if n_elements(factor) ne 1 then begin
factor = 1
if keyword_set(verbose)then print,'Error in second parameter. Using default values.'
endif
else: message, 'Wrong number of arguments'
endcase
if n_elements(ts) eq 0 then message, 'Invalid timeseries (check your spelling).'
time_series = ts
sz = size(time_series)
if sz(0) ne 1 then begin
if sz(1) eq 1 and sz(2) gt 1 then begin
time_series = reform(time_series)
if keyword_set(verbose)then print,'Reforming timeseries'
endif else message, 'Must enter an array of data'
endif
if keyword_set(verbose) then print
if keyword_set(verbose) then print,'Performing S transform:'
if keyword_set(removeedge) then begin
if keyword_set(verbose) then print,'Removing edges'
ind = findgen(n_elements(time_series))
r = poly_fit(ind,time_series,2,fit,yband,sigma,am)
ts_power = sqrt(total(float(time_series)^2)/n_elements(time_series))
if keyword_set(verbose) then print,'Sigma is:',sigma,'power',ts_power,'ratio',sigma/ts_power
if keyword_set(verbose) then print, 'total error',total(yband)/n_elements(yband)
time_series = time_series - fit
sh_len = n_elements(time_series)/10
if sh_len gt 1 then begin
wn = hanning(sh_len)
time_series(0:sh_len/2-1) = time_series(0:sh_len/2-1)*wn(0:sh_len/2-1)
time_series(n_elements(time_series)-sh_len/2:*) = time_series(n_elements(time_series)-sh_len/2:*)*wn(sh_len/2:*)
endif
endif
sz = size(time_series)
if sz(2) ne 6 then begin
if keyword_set(VERBOSE) then print,'Not complex data, finding analytic signal.'
time_series = (hilbert_trans(time_series,/analytic))
endif
length = n_elements(time_series)
spe_length = length/2
b = complexarr(length)
gw = complexarr(length)
h = fft(time_series,-1)
if (keyword_set(maxfreq)) then begin
if maxfreq lt 1 then maxfreq = fix(length*maxfreq)
endif
if not(keyword_set(minfreq)) then begin
if keyword_set(verbose) then print,'Minimum Frequency is 0.'
minfreq = 0
endif else begin
if minfreq gt spe_length then begin
minfreq = spe_length
print,'minfreq too large, using default value'
endif
if keyword_set(verbose) then print,strcompress('Minimum Frequency is '+string(minfreq)+'.')
endelse
if not(keyword_set(maxfreq)) then begin
if keyword_set(verbose) then print,strcompress('Maximum Frequency is '+string(spe_length)+'.')
maxfreq = spe_length
endif else begin
if maxfreq gt spe_length then begin
maxfreq = spe_length
print,'maxfreq too large, using default value'
endif
if keyword_set(verbose) then print,strcompress('Maximum Frequency is '+string(maxfreq)+'.')
endelse
if not(keyword_set(freqsamplingrate)) then begin
if keyword_set(verbose) then print,'Frequency sampling rate is 1.'
freqsamplingrate = 1
endif else if keyword_set(verbose) then print,strcompress('Frequency sampling rate is '+string(freqsamplingrate)+'.')
if freqsamplingrate eq 0 then freqsamplingrate = 1
if maxfreq lt minfreq then begin
temp = maxfreq
maxfreq = minfreq
minfreq = temp
temp = 0
print,'Switching frequency limits.'+strcompress(' Now, (minfreq = '+string(minfreq) + ') and (MAXFREQ ='+string(maxfreq)+').')
endif
if maxfreq ne minfreq then begin
if freqsamplingrate gt (maxfreq - minfreq) then begin
print,strcompress('FreqSamplingRate='+string(freqsamplingrate)+' too big, using default = 1.')
freqsamplingrate = 1
endif
endif else freqsamplingrate = 1
spe_nelements = floor((maxfreq - minfreq)/freqsamplingrate)+1
if keyword_set(verbose) then print,strcompress('The number of frequency elements is'+string(spe_nelements)+'.')
if keyword_set(abs) and keyword_set(power) then begin
print,'You are a moron! Defaulting to Local Amplitude Spectra calculation'
power = 0
endif
if keyword_set(abs) or keyword_set(power) then begin
loc = fltarr(length,spe_nelements)
phase = fltarr(length,spe_nelements)
if keyword_set(abs) then if keyword_set(verbose) then print,'Calculating Local Amplitude Spectra.' $
else if keyword_set(verbose) then print,'Calculating Local Power Spectra.'
h = shift(h,-minfreq)
if minfreq eq 0 then begin
gw = fltarr(length)
gw(0) = 1
loc(*,0) = abs(fft(h*gw,1))
endif else begin
f = float(minfreq)
width = factor * length/f
gw = gaussian_window(length,width)
b = h * gw
loc(*,0) = abs(fft(b,1))
endelse
for index = 1,spe_nelements-1 do begin
f = float(minfreq) + index*freqsamplingrate
width = factor * length/f
gw = gaussian_window(length,width)
h = shift(h,-freqsamplingrate)
b = h * gw
loc(*,index) = abs(fft(b,1))
endfor
if keyword_set(power) then loc = loc^2
endif else begin
if keyword_set(verbose) then print,'Calculating Local Complex Spectra'
loc = complexarr(length,spe_nelements)
h = shift(h,-minfreq)
if minfreq eq 0 then begin
gw = fltarr(length)
gw(0) = 1
loc(*,0) = fft(h*gw,1)
endif else begin
f = float(minfreq)
width = factor * length/f
gw = gaussian_window(length,width)
b = h * gw
loc(*,0) = fft(b,1)
endelse
for index = 1,spe_nelements-1 do begin
f = float(minfreq) + index*freqsamplingrate
width = factor * length/f
gw = gaussian_window(length,width)
h = shift(h,-freqsamplingrate)
b = h * gw
loc(*,index) = fft(b,1)
endfor
endelse
if keyword_set(maskedges) then begin
if maskedges eq 1 then maskthreshold=0.05
if maskedges gt 0 and maskedges lt 1 then maskthreshold=maskedges
if maskedges gt 1 and maskedges le 100 then maskthreshold=float(maskedges)/100. $
else maskthreshold=0.05
edgets = findgen(length)/length
st = s_trans(edgets,/abs)
mask=where(st gt maskthreshold,maskcount)
loc(mask) = 0
endif
if keyword_set(samplingrate) then begin
frequencies = (MINFREQ + findgen(spe_nelements)*freqsamplingrate)/(samplingrate*length)
time = findgen(length)*samplingrate
a = {st: loc, time: time, freq: frequencies}
return,a
endif else return, loc
end