;+
; NAME:
;       EIS_DESPIKE
;
; PURPOSE:
;       EIS_DESPIKE is part of the SOLAR-B EIS analysis software . It is used 
;	for de-spiking, i.e. to remove cosmic ray spikes from the pixel 
;	data. 
;
; CATEGORY:
;       Hansteen/Wikstol EIS data analysis SW
;
; CALLING SEQUENCE:
;       eis_despike, wd_in, wd_despike
;
; INPUTS:
;       WD_IN:  line window data to remove cosmic rays from.
;	    	Line window data should be in the EIS format [nlabmda,
;	    	nslit,nexp]
;
;       NEXP_PRP  Number of exposures per raster position. If greater than 1
;                 then clean_exposure will be used for cleaning. Otherwise
;                 new_spike will be used. If NEXP_PRP not specified then
;                 new_spike will be used.
;
; KEYWORD PARAMETERS:
;	NO_NEIGHBOURS: EIS_DESPIKE sets by default the keyword "neighbours" 
;                      in NEW_SPIKE.PRO and CLEAN_EXPOSURE. This can be 
;                      switched off using no_neighbours.
;
;	NO_FILL: Same as above for keyword "fill". 
;
;	INFO: Display number of flagged pixels.
;
;   	SWTCH:  Output mask for bad (altered) pixels.
;
;       CLEAN_EXP:  If set, then force clean_exposure to be used for
;                   the cleaning instead of new_spike.
;
;       * Other keyword parameters can also be passed to clean_exposure and 
;       new_spike, see headers in these routines for more details.
;
; OUTPUTS:
;	WD_DESPIKE  De-spiked line window data, that may be saved by another
;                   program.
;
; CALLS:
;	NEW_SPIKE: SSW routine to remove cosmic rays.
;       EIS_DATA__READ and eis_data methods
;
; RESTRICTIONS:
;	Assumes wd_in in the standard EIS format [nlambda, nslit, nexp]
;
;	Cosmic ray removal is not a straightforward thing to do. There is 
;	always the chance that real solar feature could be removed, or 
;	CR his ignored. See documentation for "new_spike.pro" for
;	more.
;
; PROGRAMMING NOTES:
;       This routine calls new_spike.pro and clean_exposure.pro, which
;       were developed for the SOHO/CDS mission. The former routine
;       requires a 3D array as input, whereas the latter works on 2D
;       arrays. By default the routine uses new_spike for data-sets
;       with three or more exposures, and clean_exposure otherwise. In
;       addition, if nexp_prp is greater than 1, then clean_exposure
;       is used irrespective of the number of exposures. 
;
; MODIFICATION HISTORY:
;       16-Aug-2006: Oivind Wikstol. Version 1.0
;       21-Feb-2007: Harry Warren, modified to work with 1 or 2 exposures 
;                                  (clean_exposure)
;       15-Mar-2007: Ignacio Ugarte, added SWTCH keyword to MAIN and 
;                                  NO_NEIGHBOUR to CLEAN_EXPOSURE.
;       21-Mar-2007: Harry Warren, Added check of exposure times, and use of
;                                  _extra
;       11-Oct-2007: Harry Warren, Added explict no_neighbours keyword and 
;                                  iteration
;       19-Oct-2007: Harry Warren, Fixed exposure couting bug
;        7-Feb-2008: Peter Young,  Replaced expt input with nexp_prp;
;                                  implemented /no_neighbours keyword
;                                  in call to clean_exposure.
;       17-Dec-2019: Peter Young,  Added /clean_exp keyword; expanded
;                                  header. 

; $Id: eis_despike.pro,v 1.6 2008/02/07 17:55:48 gardini Exp $
;
pro eis_despike, wd_in, wd_despike, nexp_prp, swtch = swtch, $
                 no_neighbours=no_neighbours, n_iter=n_iter, _extra=ex, $
                 clean_exp=clean_exp

  neighbours = abs(keyword_set(no_neighbours) - 1)
  fill = abs(keyword_set(no_fill) - 1)
  if not(keyword_set(n_iter)) then n_iter = 1

  sz = size(wd_in)
  nlam = sz[1]
  nslit = sz[2]
  if sz[0] eq 3 then nexp = sz[3] else nexp = 1

  ;; --- rasters with small number of exposures or different exposure times won't work with new_spike

  IF n_elements(nexp_prp) EQ 0 THEN nexp_prp=1

  if (nexp lt 3) or (nexp_prp GT 1) OR keyword_set(clean_exp) then BEGIN
    print,'%EIS_DESPIKE: using clean_exposure...'
    wd_despike = wd_in
    swtch = make_array(size=sz)
    for j=0,nexp-1 do begin
      wd_despike[*,*,j] = clean_exposure(wd_in[*,*,j],swtch=swtch_out, $
                                        _extra=ex,no_neighbour=no_neighbours)
      swtch[*,*,j] = swtch_out
    endfor
    if keyword_set(info) then begin
      ind=WHERE(swtch EQ 1)
      IF ind(0) NE -1 THEN $
          PRINT,'     Pixels flagged: ',STRTRIM(N_ELEMENTS(ind)) ELSE $
          PRINT,'     No pixels flagged'
    endif
  endif else begin
    print,'%EIS_DESPIKE: using new_spike...'
    wd    = transpose(wd_in, [0,2,1])
    wd_sz = size(wd)
    swtch = make_array(size=wd_sz,/int,value=0)
    for n=0,n_iter-1 do begin
      new_spike, wd, wd_out, swtch = swtch_n, neighbours=neighbours, $
                 fill=fill, _extra=ex
      wd    = wd_out
      swtch = swtch + swtch_n
    endfor
  ;; --- reform back to EIS format
    wd_despike = transpose(wd_out, [0,2,1])
    swtch = transpose(swtch, [0,2,1])
  endelse

return
end
