;+ ;FUNCTION: THM_LSP_REMOVE_SPIKES, t, xx, per, nwin=nwin, nfit=nfit ; ; NOT FOR GENERAL USE. CALLED BY THM_EFI_REMOVE_SPIKES ; ONLY FOR ISOLATED PARTICLE OR WAVE BURSTS ; NOT FOR ENTIRE ORBIT. ; ;PURPOSE: ; Remove the non-physical spiky signals in the efw data. ; ;INPUT: ; t -NEEDED. Time array ; x -NEEDED. Data ; per -NEEDED. Spin period. ; ;KEYWORD: ; nwin -OPTIONAL. Number of points in spike search window. DFLT = 16 ; spikesig -OPTIONAL. Sigma of spikes. DFLT = 5 ; sigmin -OPTIONAL. Minimun of sigma. DFLT = 0 mV/m. ; nfit -OPTIONAL. Number of points in the fit window. DFLT = 16 ; ;HISTORY: ; 2008-11-08: Created by Jianbao Tao at LASP@CU-Boulder. ; 2008-11-10: The head comment was added. ; 2009-03-30: REE. Rewrite to test epoch analysis. ; 2009-04-30: REE. Rewrite to use median smooth. ;- function thm_lsp_remove_spikes, t, xx, per, nwin=nwin, spikesig=spikesig, $ sigmin=sigmin, nfit=nfit, talk=talk, diagnose=diagnose ; CHECK KEYWORDS if not keyword_set(nwin) then nwin = 16L if not keyword_set(spikesig) then spikesig = 5.0d if n_elements(sigmin) EQ 0 then sigmin = 0.01d if not keyword_set(nfit) then nfit = 16L x = xx ; CALCULATE AVERAGE SIGNAL OVER PERIOD tt = t-t(0) dt = t(1:*)-t(*) mdt = median(dt) phs = tt/per npps = long(round(2.0d*per/mdt)) ; SET NUMBER OF POINTS PER SPIN AT ~2X DT nspins = ceil(max(phs)) ; NUMBER OF SPINS ntot = long(nspins) * long(npps) ; NUMBER OF PHASE POINTS phx = dindgen(ntot)/npps xp = interpol(x, phs, phx) xr = reform(xp, npps, nspins) xe = total(xr,2)/ nspins if keyword_set(talk) then $ plot, phx(0:npps-1), xe, xtit = 'Spin Phase (/2pi)', $ title = 'Spin-Averaged Value', ytit = 'Amplitude' ; FIND SPIKES xel = [xe(npps-nwin/2:npps-1), xe, xe(0:nwin/2-1)] xel2 = abs(xel-thm_lsp_median_smooth(xel,nwin)) sig = abs(xel2)/(stddev(xel2(nwin/2: npps-nwin/2-1))+sigmin) sdum = sig ; ISOLATE MAXIMUMS IN SIG FOR i= nwin/2-1, npps-nwin/2 DO BEGIN smax = max(sdum(i-nwin/2+1:i+nwin/2)) if sdum(i) EQ smax then sig(i)=smax else sig(i) = 0 ENDFOR sig = sig(nwin/2: npps-nwin/2-1) ppk = where(sig GE spikesig, nppk) ; CHECK PPK FOR ERRORS IF nppk EQ 0 then BEGIN print, 'NO SPIKES FOUND' IF keyword_set(talk) then BEGIN xyouts, 0.25, 0.75, 'NO SPIKES FOUND', charsize=2, /normal wait, 1.0 ENDIF return, x ENDIF IF nppk GT 4 THEN BEGIN print, 'TOO MANY SPIKES - CANNOT REMOVE' return, x ENDIF ; PEAKS tpks = ppk*per/double(npps) ipks = round(tpks/dt) iper = float(per/mdt) IF keyword_set(talk) then BEGIN oplot, phx(ppk), xe(ppk), psym=6, col = 250 xyouts, 0.25, 0.75, 'SPIKES', charsize=2, /normal wait, 0.25 ENDIF ; CALCULATE TIMES / INDECIES tel = [phx(npps-nwin/2:npps-1)-1.d, phx(0: npps+nwin/2-1)] nfit = 16 good = 0 bad = 0 ; REMOVE PEAKS FOR j = 0, n_elements(ipks)-1 DO BEGIN ; DO A PRELIMINARY FIT TO DETERMINE LIMITS xwin = xel[ppk(j)-nfit/2+nwin/2:ppk(j)+nfit/2+nwin/2] twin = tel[ppk(j)-nfit/2+nwin/2:ppk(j)+nfit/2+nwin/2] fit = gaussfit(twin, xwin, A, nterms=6, chisq=chisq, sigma=sigma) ; DIAGNOSTIC PLOT IF keyword_Set(diagnose) then BEGIN plot, twin, xwin oplot, twin, A(0)*exp( -((twin-A(1))/A(2))^2 / 2.0d) + $ poly(twin, A(3:5)) , col = 2 ENDIF A0 = A(0) A1 = A(1) A0min = 0 A0max = 0 if A0 GT 0 then A0max = 5.0*A0 else A0min = 5.0*A0 istart = float((ipks(j)-nfit/2) > 0) iend = round(istart) + nfit ispin = 0 ; NEXT LOOP WHILE iend LT n_elements(x)-1 DO BEGIN xwin = x(round(istart):iend) twin = tt(round(istart):iend) - tt(round(istart)) fit = gaussfit(twin, xwin, A, nterms=6, chisq=chisq, sigma=sigma) cent = round(A(1)/mdt) - nfit/2 ; DIAGNOSTIC PLOT if keyword_set(diagnose) then plot, twin, xwin ; FIND GOOD FITS AND REMOVE ELSE SUBTRACT TYPICAL IF (chisq LE 3) AND (abs(cent) LE 2) AND $ (A(0) GT A0min) AND (A(0) LT A0max) then BEGIN xwin = xwin - A(0)*exp( -((twin-A(1))/A(2))^2 / 2.0d) good = good + 1 ; DIAGNOSTIC PLOT IF keyword_Set(diagnose) then BEGIN oplot, twin, A(0)*exp( -((twin-A(1))/A(2))^2 / 2.0d) + poly(twin, A(3:5)) , col = 2 xyouts, 0.25, 0.75, 'GOOD FIT', charsize=2, /normal ENDIF ENDIF else BEGIN ; NOTCH A = ladfit(twin, xwin) xwin(nwin/4:3*nwin/4) = poly(twin(nwin/4:3*nwin/4), A) bad = bad + 1 ; DIAGNOSTIC PLOT IF keyword_Set(diagnose) then BEGIN oplot, twin, poly(twin, A) , col = 2 xyouts, 0.25, 0.75, 'NOTCH', charsize=2, /normal ENDIF ENDELSE ; DIAGNOSTIC PLOT IF keyword_Set(diagnose) then BEGIN oplot, twin, xwin, col=6 wait, 0.25 ENDIF ; RESET X x(round(istart):iend) = xwin istart = istart+iper; + (( (round(A(1)/mdt) - nfit/2) > (-1)) < 1); REMOVED iend = istart + nfit ispin = ispin + 1 ENDWHILE END print, good, ' SPIKES REMOVED (GOOD FITS)', bad, ' SPIKES NOTCHED (FAILED FITS)' return, x end ; DIAGNOSTICS ;plot, twin, xwin ;oplot, twin, A(0)*exp( -((twin-A(1))/A(2))^2 / 2.0d) + $ ;A(3) + A(4)*twin + A(5)*twin*twin, col=2 ;AAV1 = A0(1)*per + ispin*per - tt(round(istart)) ;oplot, twin, AAV(0)*exp( -((twin-AAV1)/AAV(2))^2 / 2.0d) + $ ;A(3) + A(4)*twin + A(5)*twin*twin, col=4 ;oplot, twin, xwin, col=6 ;print, AAV1, A(1) ;if abs(cent) GT 2 then print, 'POOR CENTER' ;if chisq GT 3 then print, 'POOR FIT' ;if A(0) LT A0min or A(0) GT A0max then print, 'POOR AMPLITUDE' ; OLD NOTCHER ;great = 0 ;AAV = fltarr(6) ; FIND GREAT FITS TO DETERMINE AAV ;IF (chisq LT 1) AND (abs(cent) LT 2) AND $ ;(A(0) GT A0min) AND (A(0) LT A0max) then BEGIN ;AAV = (AAV*great + A)/(1+great) ;great=great+1 ;ENDIF ;ENDIF else BEGIN ;AAV1 = A0(1)*per + ispin*per - tt(round(istart)) ;xwin = xwin - AAV(0)*exp( -((twin-AAV1)/AAV(2))^2 / 2.0d) ;bad = bad + 1 ;ENDELSE ; OLD PEAK FINDER ; FIND SPIKES ;slide = nwin/2 ;xel = [xe,xe] ;ppk = 0 ;FOR i = 0L, npps-1, slide DO BEGIN ; wstart = i ; wend = wstart + nwin ; win = xel[wstart: wend] ; xmed = median(win) ; xstd = stddev(win) ; xpk = max(abs(win-xmed), ipeak) ; print, xpk, xstd, xpk/xstd ; if (xpk GT (xstd*3)) AND (ipeak GT nwin/4) AND (ipeak LE 3*nwin/4) then $ ; ppk = [ppk, wstart+ipeak] ;ENDFOR ; CHECK PPK FOR ERRORS ;IF n_elements(ppk) EQ 1 then BEGIN ; print, 'NO SPIKES FOUND' ; return, x ;ENDIF ;IF n_elements(ppk) GT 5 THEN BEGIN ; print, 'TOO MANY SPIKES - CANNOT REMOVE' ; return, x ;ENDIF ; PEAKS ;ppk = ppk(1:*)