;+
; Project     : SOHO - CDS     
;                   
; Name        : CDS_CLEAN_EXP
;               
; Purpose     : Clean cosmic rays (based on local median) from QLDS data. 
;               
; Explanation : CDS_CLEAN_EXP applies the function CLEAN_EXPOSURE to all the
;               data in the supplied QLDS, removing cosmic rays by comparing
;               pixels with the median of the surrounding pixels in the same
;               exposure.
;
;               Unless the keyword NOFILL is set, pixels identified as cosmic
;               rays will be filled in with the local median pixel
;               values. When NOFILL is set, the cosmic rays pixels are flagged
;               as MISSING. Pixels flagged as MISSING may be saved and
;               restored (for later sessions) through the routines
;               CDS_SAVE_MISSING/CDS_READ_MISSING.
;               
;               The routine is specifically designed to work with slit
;               spectrograms, with the first dimension of the data being the
;               dispersion direction, and the second dimension along the
;               slit. The rectangular box used to calculate the local median
;               value is longer in the slit direction than in the dispersion
;               direction. The size of the median box can be set through the
;               keywords XBOX/YBOX.
;
;               The routine does a fairly good job of identifying cosmic rays
;               when comparing with cosmic rays identified by eye. The method
;               is, however, not foolproof. Both false alarms and undetected
;               cosmic rays do occur, so manual inspection is encouraged.
;
;               A pixel P is determined to be a (first approximation) cosmic
;               ray:
;
;               IF   ( P LT LIMIT AND (P - MEDIAN) GT MAX_VAR_LOW )
;                 OR ( P GE LIMIT AND (P / MEDIAN) GT MAX_FACTOR_HI )
;
;               where LIMIT, MAX_VAR_LOW and MAX_FACTOR_HI can be set through
;               keywords. They have useful default values for debiased CDS NIS
;               exposures.
;
;               Since this definition often leaves (minimally) affected pixels
;               on the borders of cosmic ray hits untouched, all pixels having
;               a (first approximation) cosmic ray neighbour to its left or
;               right, or directly above or below will be marked as cosmic
;               rays as well. This may be turned off by setting the keyword
;               NO_NEIGHBOUR, or modified by specifying the convolution KERNEL
;               that is used to flag neighbours.
;               
; Use         : CDS_CLEAN_EXP,QLDS
;    
; Inputs      : QLDS : Quicklook data structure.
;               
; Opt. Inputs : None.
;               
; Outputs     : The data in the QLDS are altered.
;               
; Opt. Outputs: None.
;               
; Keywords    : NOFILL : Set this flag to flag the cosmic ray pixels as
;                        MISSING.
;
;               NO_NEIGHBOUR : Set this flag to avoid flagging nearest
;                              neighbours (left, right, above, below) of first
;                              approximation cosmic ray pixels as cosmic rays.
;
;               XBOX/YBOX: Determines the size of the box used to calculate
;                          the local median.
;
;               LIMIT : Determines the dividing line between high/low pixels,
;                       see the algorithm description.
;
;               MAX_VAR_LOW : See the algorithm description
;
;               MAX_FACTOR_HI : See algorithm description.
;
;               KERNEL : See algorithm description.
;
; Calls       : gt_dimension(), gt_windata(), st_windata, vds_debias
;
; Common      : None.
;               
; Restrictions: The data in the QLDS should be debiased (will be done if
;               necessary) but *not* calibrated.
;
;		This routine may not work correctly with vertically binned data
;		(COMP_ID=8), and is not recommended for such data.
;               
; Side effects: None.
;               
; Category    : Utility
;               
; Prev. Hist. : None.
;
; Written     : S.V.H. Haugan, UiO, 11 December 1996
;               
; Modified    : Version 2, SVHH, 16 October 1997
;                       Checking data units more sensibly.
;               Version 3, SVHH, 5 May 1998
;                       Corrected typo causing ybox not to be propagated, and
;                       added KERNEL keyword.
;                       
; Version     : 3, 5 May 1998
;-            

PRO cds_clean_exp,qlds,nofill=nofill,no_neighbour=no_neighbour,kernel=kernel,$
       max_var_low=max_low,max_factor_hi=max_hi,$
       limit=limit,xbox=xbox,ybox=ybox
  
  if qlds.header.comp_id eq 8 then print,	$
	"WARNING:  CDS_CLEAN_EXP may not work correctly on binned data"

  dim = gt_dimension(qlds)
  
  fill = keyword_set(nofill) - 1b
  
  FOR i = 0,N_ELEMENTS(qlds.detdesc)-1 DO BEGIN
     IF qlds.detdesc(i).ixstop(0) GE 0 THEN BEGIN
        
        IF qlds.detdesc(i).units EQ 'ADC' THEN BEGIN
           MESSAGE,"Removing bias",/informational
           vds_debias,qlds
        END
        
        IF qlds.detdesc(i).units NE 'DEBIASED-ADC' THEN BEGIN 
           IF NOT exist(dummy) THEN BEGIN
              print
              print,"Cannot debias, units: "+qlds.detdesc(i).units
           END
           dummy = 1
        END ELSE BEGIN 
           missing = qlds.detdesc(i).missing
           
           catch,error
           IF error NE 0 THEN BEGIN
              catch,/cancel
              print,!err_string
              message,"Caught error in CDS_CLEAN_EXP",/continue
              IF n_elements(da) NE 0 THEN BEGIN
                 message,"Saving data",/continue
                 st_windata,qlds,i,da
                 message,"Aborting"
              END
           END
           
           da = gt_windata(qlds,i,/no_copy)
           FOR tix = 0,(dim.sdel_time-1) > 0 DO BEGIN
              FOR xix = 0,(dim.ssolar_x-1) > 0 DO BEGIN
                 sc = REFORM(da(*,xix,*,tix))
                 sc_f = clean_exposure(sc,missing=missing,fill=fill,$
                                       no_neighbour=no_neighbour,$
                                       kernel=kernel,$
                                       max_var_low=max_low,$
                                       max_factor_hi=max_hi,$
                                       limit=limit,xbox=xbox,ybox=ybox)
                 da(*,xix,*,tix) = sc_f
              END
           END
           st_windata,qlds,i,da,/no_copy
           
           catch,/cancel
        END
     END
  END
END


