;+ ;NAME: ; pwrspc ;PURPOSE: ; Called with times time and data quantity, PWRSPC returns a power ; spectrum power at frequencies freq. A Hanning window is applied to ; the input data, and its power is divided out of the returned ; spectrum. A straight line is subtracted from the data to ; reduce spurius power due to sawtooth behavior of a background. ; UNITS ARE (UNITS)^2 WHERE UNITS ARE THE UNITS OF quantity. freq ; is in 1/timeunits. ; THUS THE OUTPUT REPRESENTS THE MEAN SQUARED AMPLITUDE OF THE SIGNAL ; AT EACH SPECIFIC FREQUENCY. THE TOTAL (SUM) POWER UNDER THE CURVE IS ; EQUAL TO THE MEAN (OVER TIME) POWER OF THE OSCILLATION IN TIME DOMAIN. ; NOTE: IF KEYWORD notperhz IS SET, THEN POWER IS IN UNITS^2. If notset ; power is (as normal) in UNITS^2/Hz. ;CALLING SEQUENCE: ; pwrspc, time, quantity, freq, power, noline = noline, $ ; nohanning = nohanning, bin = bin, notperhz = notperhz ;INPUT: ; time = the time array ; quantity = the function for which you want to obtain a power ; spectrum ;OUTPUT: ; freq = the frequency array (units =1/time units) ; power = the power spectrum, (units of quantity)^2/frequency_units ;KEYWORDS: ; noline = if set, no straight line is subtracted ; nohanning = if set, then no hanning window is applied to the input ; bin = a binsize for binning of the data, the default is 3 ; notperhz = if set, the output units are simply the square of the ; input units ; err_msg = named variable that contains any error message that might occur ; ;$LastChangedBy$ ;$LastChangedDate$ ;$LastChangedRevision$ ;$URL$ ; ;- pro pwrspc, time, quantity, freq, power, noline = noline, $ nohanning = nohanning, bin = bin, notperhz = notperhz, $ err_msg=err_msg, _extra = _extra err_msg='' ; t = double(time)-double(time(0)) x = double(quantity) ; if keyword_set(bin) then begin binsize = bin endif else begin binsize = 3 endelse ; if not(keyword_set(noline)) then begin c=poly_fit(t,x,1,line,band,sigma,status=pf_status) case pf_status of 1: err_msg = "Singular matrix detected." 2: err_msg = "Warning: Invert detected a small pivot element." 3: err_msg = "Warning: Undefined (NaN) error estimate encountered. There are NaNs in the data." else: endcase dprint, dlevel=2, err_msg x=x-line endif ; if not(keyword_set(nohanning)) then begin window = hanning(n_elements(x)) x = x * window endif ; nt = n_elements(t) bign = nt dprint, 'bign=',bign if (bign-(bign/2l)*2l ne 0) then begin dprint,'needs an even number of data points, dropping last point...' t = t(0:nt-2) x = x(0:nt-2) bign = bign - 1 endif dprint, 'bign=',bign ; ; following Numerical recipes in Fortran, p. 421, sort of... ; dbign = double(bign) k = [0,dindgen(bign/2)+1] tres=median(t(1:n_elements(t)-1)-t(0:n_elements(t)-2)) fk = k/(bign*tres) ; xs2 = abs(fft(x,1))^2 ; pwr = dblarr(bign/2+1) pwr(0) = xs2(0)/dbign^2 pwr(1:bign/2-1) = (xs2(1:bign/2-1) + xs2(bign - dindgen(bign/2)))/dbign^2 pwr(bign/2) = xs2(bign/2)/dbign^2 ; if not keyword_set(nohanning) then begin wss = dbign*total(window^2) pwr = dbign^2*pwr/wss endif ; ; Now reduce variance by summing bin neighbors in frequency domain...except zero ; dfreq=binsize*(fk(1)-fk(0)) ; npwr = n_elements(pwr)-1 nfinal=long(npwr/binsize) iarray=lindgen(nfinal) power = dblarr(nfinal) freq = fk((iarray+0.5)*binsize+1) for i=0l,binsize-1 do begin power = power+pwr(iarray*binsize+i+1) endfor if not(keyword_set(notperhz)) then begin power = power / dfreq endif dprint, 'dfreq=',dfreq return end