;+ ; NAME: ; GTITRIM ; ; AUTHOR: ; Craig B. Markwardt, NASA/GSFC Code 662, Greenbelt, MD 20770 ; craigm@lheamail.gsfc.nasa.gov ; ; PURPOSE: ; Normalize a Good Time Interval (GTI) - no overlapping and adjoining ; ; CALLING SEQUENCE: ; NEWGTI = GTITRIM(GTI, COUNT=, MAXGAP=, MINGTI=) ; ; DESCRIPTION: ; ; A good time interval is by definition a list of intervals which ; represent "good" or acceptable portions of the real number line. ; In this library a GTI is a 2xNINTERVAL array where NINTERVAL is ; the number of intervals. ; ; The numbers in the array represent the start and stop times of ; each interval. Thus, the array [[0,10],[20,30],[40,50]] represent ; intervals ranging from 0-10, 20-30 and 40-50. Formally, this ; example GTI represents times which would satisfy the following ; expression, for each time T and interval number i: ; T GE GTI(0,i) AND T LT GTI(1,i) ; Note that the endpoint is closed on the left but open on the ; right. ; ; However, not every 2xNINTERVAL array is a valid or "normalized" ; GTI as used by this library. The array must satisfy several ; conditions: ; * time ordered (ascending) ; * no overlapping intervals ; * no adjoining intervals (intervals that start and stop at the ; same point; e.g. the point 10 in this array [[0,10],[10,20]]) ; ; A user who desires to create his or her own GTI array can proceed ; as follows. ; ; First, the array is placed in time order. This can be ; accomplished simply using the built-in function SORT. This ; statement sorts the array by start times. ; ; GTI = GTI(*, SORT(GTI(0,*))) ; ; Second, the GTITRIM function is used to fully normalize the set of ; intervals: ; ; GTI = GTITRIM(GTI) ; ; After these two procedures the GTI is considered valid and can be ; passed to the other routines of the library. Of course if the ; user can guarantee the above requirements without using GTITRIM ; then this is acceptable as well. ; ; It should be noted that this function is not constrained to ; operation only on time arrays. It should work on any ; one-dimensional quantity with intervals. ; ; INPUTS: ; ; GTI - a 2xNINTERVAL array where NINTERVAL is the number of ; intervals. GTI(*,i) represents the start and stop times of ; interval number i. The intervals must be non-overlapping ; and time-ordered (use GTITRIM to achieve this). ; ; A scalar value of zero indicates that the GTI is empty, ie, ; there are no good intervals. ; ; KEYWORDS: ; ; MAXGAP - Maximum allowable gap for merging existing good time ; intervals. Intervals with gaps smaller than MAXGAP will ; be combined into a single interval. ; Default: 0 (any gap keeps intervals separate) ; ; MINGTI - Minimum size interval. If any interval is smaller than ; MINGTI then it is discarded. ; Default: 0 (all intervals are preserved) ; ; COUNT - upon return, the number of resulting intervals. A value ; of zero indicates no good time intervals. ; ; ; RETURNS: ; ; A new GTI array containing the normalized intervals. The array is ; 2xCOUNT where COUNT is the number of resulting intervals. ; GTI(*,i) represents the start and stop times of interval number i. ; The intervals are non-overlapping and time-ordered. ; ; If COUNT is zero then the returned array is a scalar value of ; zero, indicating no good intervals were found. ; ; SEE ALSO: ; ; GTIMERGE ; ; MODIFICATION HISTORY: ; Written, CM, 1997-2001 ; Documented, CM, Apr 2001 ; Corrected bug which bypassed MIN/MAXGTI, CM, 20 Jul 2003 ; ; $Id: gtitrim.pro,v 1.7 2006/10/22 09:50:09 craigm Exp $ ; ;- ; Copyright (C) 1997-2001, 2003, Craig Markwardt ; This software is provided as is without any warranty whatsoever. ; Permission to use, copy, modify, and distribute modified or ; unmodified copies is granted, provided this copyright and disclaimer ; are included unchanged. ;- function gtitrim, gti, maxgap=maxgap, mingti=mingti, maxgti=maxgti, $ count=count, query=query if keyword_set(query) then return, 1 count = 0L ngti = n_elements(gti) if n_elements(maxgap) EQ 0 then maxgap = 0D if n_elements(mingti) EQ 0 then mingti = 0D ;; Case of empty GTI if ngti LT 2 then return, 0L ;; Case of single GTI if ngti EQ 2 then begin if gti(1) - gti(0) LT mingti then return, 0L count = 1L newgti = reform(gti, 2, 1) goto, GTI_CHECKS endif newgti = gti ngti = ngti/2 ;; Check for gaps, spaces between GTIs gaps = newgti(0,1:*) - newgti(1,*) wh = where(gaps GT maxgap, ct) if ct EQ 0 then begin ;; All of the gaps are too small newgti = reform([min(newgti), max(newgti)], 2, 1) endif else if ct GT 0 AND ct LT ngti-1 then begin ;; Remake the GTI, removing the gaps vgti = reform(make_array(2, ct+1, value=newgti(0)), 2, ct+1, /overwrite) vgti(0,0) = min(newgti) vgti(1,ct) = max(newgti) vgti(1,0:ct-1) = newgti(1,wh) vgti(0,1:ct) = newgti(0,wh+1) newgti = temporary(vgti) endif GTI_CHECKS: ;; Remove too-small GTIs dur = newgti(1,*) - newgti(0,*) wh = where(dur GE mingti, count) if count GT 0 then newgti = newgti(*,wh) else newgti = 0L if count GT 0 then newgti = reform(newgti, 2, count, /overwrite) ;; if count GT 0 AND n_elements(maxgti) GT 0 then begin maxgti1 = maxgti(0) nper = (newgti(1,*)-newgti(0,*)) / maxgti1 iper = ceil(nper) totgti = total(iper) if maxgti1 GT 0 AND totgti GT count then begin vzero = newgti(0) & vzero(0) = 0 newgti2 = make_array(2, totgti, value=vzero) j = 0L for i = 0L, count-1 do begin if iper(i) EQ 1 then begin newgti2(*,j) = newgti(*,i) endif else begin for k = 0, iper(i)-1 do $ newgti2(*,j+k) = [ newgti(0,i)+maxgti1*k, $ newgti(1,i)<(newgti(0,i)+maxgti1*(k+1))] endelse j = j + iper(i) endfor count = totgti newgti = reform(newgti2,2,totgti) endif endif return, newgti end