function hi_correction, im, hdr,sebip_off=sebip_off,calimg_off=calimg_off,desmear_off=desmear_off, $
             CALFAC_OFF=calfac_off, exptime_off=exptime_off,cosmics=cosmics,_extra=ex,silent=silent, $
             saturation_limit=saturation_limit,nsaturated=nsaturated, BIAS_OFF=bias_off

;+
; $Id: hi_correction.pro,v 1.20 2015/02/09 14:43:14 crothers Exp $
;
; Project   : STEREO SECCHI
;
; Name      : hi_correction
;
; Purpose   : This function returns corrected images.
;
; Explanation: The default correction procedure involves; desmearing
;        the image and applying calibration. Any of these operations
;        can turned off using the keywords.
;
; Use       : IDL> cal_image = hi_correction(image,hdr,cosmics=cosmics)
;
; Inputs    : image - level 0.5 image in DN (long)
;             hdr -image header, either fits or SECCHI structure
;
; Outputs   :  cal_image - level 1 image
;              cosmics - cosmic ray scrub count from summed images
;
; Keywords  :desmear_off - set to return image without desmear, image is weighted for exptime
;            exptime_off - set to return weighted image as exposed
;            calimg_off - set to return image without vignetting
;                        (flat-field) correction
;            sebip_off - set to return image without SEB IP correction
;                        applied
;   	     calfac_off - Do not apply calibration factor (including summing correction)
;            bias_off - set to return image without bias subtraction applied (valid only for HI images
;   	    	    	not using the HI summing buffer)
;
; Common    :
;
; Calls     : SCC_FITSHDR2STRUCT, GET_CALFAC, GET_CALIMG, HI_DESMEAR
;
; Category    : Calibration
;
; Prev. Hist. : None.
;
; Written     : Steve Crothers RAL January 2007
;
; $Log: hi_correction.pro,v $
; Revision 1.20  2015/02/09 14:43:14  crothers
; capture ipsum before get_calfac and carried forward into diffuse source correction
;
; Revision 1.19  2013/11/22 17:06:53  crothers
; Updated to omit diffuse source correction if calimg is off or calfac is off
;
; Revision 1.18  2013/11/05 16:16:31  crothers
; added diffuse source correction to allow for change in solid angle off axis
;
; Revision 1.17  2013/10/28 18:28:14  nathan
; Always call get_biasmean, though it usually returns zero
;
; Revision 1.16  2013/10/17 22:23:19  nathan
; set calfac_off if calfac is 1.0
;
; Revision 1.15  2009/06/08 11:03:37  crothers
; updated saturation removal code to allow a column with a small amount of
; saturation to be allowed.
;
; Revision 1.14  2008/02/15 16:21:19  crothers
; Now uses hi_remove_saturation and hi_fill_missing to flag "bad" data
; Changed output type to float rather than double [meaningless precision]
;
; Revision 1.13  2008/01/24 11:45:33  crothers
; Moved get_calfac to after desmear to allow for side effects in the former
;
; Revision 1.12  2008/01/03 00:12:33  thompson
; *** empty log message ***
;
; Revision 1.11  2007/09/24 21:29:21  nathan
; Add _EXTRA to subpro calls to propagate /SILENT
;
; Revision 1.10  2007/09/24 20:58:44  nathan
; Added /CALFAC_OFF option to be consistent with other telescopes
;
; Revision 1.9  2007/09/04 17:02:32  crothers
; moved cosmic ray field extraction from desmear to its own routine
;
; Revision 1.8  2007/08/28 14:36:01  colaninn
; corrected comments for calimg
;
; Revision 1.7  2007/08/24 19:30:03  nathan
; updated info messages and hdr history
;
; Revision 1.6  2007/08/23 23:57:30  nathan
; added info messages
;
; Revision 1.5  2007/05/21 20:16:06  colaninn
; added silent keyword
;
; Revision 1.4  2007/05/18 11:19:58  crothers
; Added cosmics option and changed shutterless to desmear and exptime
;
; Revision 1.3  2007/04/05 12:59:58  colaninn
; problem updating history corrected
;
; Revision 1.2  2007/04/04 19:13:43  colaninn
; added sebip and calfac for IPSUM
;
; Revision 1.1  2007/01/22 19:35:08  colaninn
; new from RAL
;
;-
IF datatype(ex) EQ 'UND' THEN ex = create_struct('blank',-1)
IF keyword_set(silent) THEN ex = CREATE_STRUCT('silent',1,ex)
info="$Id: hi_correction.pro,v 1.20 2015/02/09 14:43:14 crothers Exp $"
len=strlen(info)
version='Applied '+strmid(info,5,len-10)
IF ~keyword_set(silent) THEN message,version,/inform

;--Check Header-------------------------------------------------------
IF(DATATYPE(hdr) NE 'STC') THEN hdr=SCC_FITSHDR2STRUCT(hdr)

IF (TAG_NAMES(hdr, /STRUCTURE_NAME) NE 'SECCHI_HDR_STRUCT') THEN $
MESSAGE,'ONLY SECCHI HEADER STRUCTURE ALLOWED'

IF (hdr[0].DETECTOR NE 'HI1' AND hdr[0].DETECTOR NE 'HI2') THEN $
message,'Calibration for HI DETECTOR only'
;----------------------------------------------------------------------
;hdr0=hdr
;--Add file version to header history
hdr = scc_update_history(hdr,version)

;------------------------------------------------------------------------
;
;im0=im

;--Correct for SEB IP(ON)
IF ~keyword_set(sebip_off) THEN im = SCC_SEBIP(im,hdr,ip_flag,_EXTRA=ex)
; hdr modified in sebip

;-- Bias Subtraction(ON)
IF keyword_set(bias_off) THEN biasmean = 0.0 ELSE BEGIN
  biasmean =GET_BIASMEAN(hdr,_EXTRA=ex)
  IF biasmean NE 0.0 THEN BEGIN
    hdr = SCC_UPDATE_HISTORY(hdr,'Bias Subtracted',value=biasmean)
    hdr.OFFSETCR=biasmean
; Remove bias here so following procedures behave correctly.
    im=im-biasmean    
    IF ~keyword_set(SILENT) THEN message,'Subtracted BIAS='+trim(biasmean),/info
  ENDIF
ENDELSE


; extract and correct for cosmic ray reports
cosmics=hi_cosmics(hdr,im,_EXTRA=ex)
im=hi_remove_saturation(im,hdr,saturation_limit=saturation_limit,nsaturated=nsaturated)

IF keyword_set(exptime_off) then begin
; do nothing to image

endif else if keyword_set(desmear_off) then begin
; correct for exposure weighting across the ccd
  im=im/hi_exposure_wt(hdr,silent=silent)
  if hdr.nmissing gt 0 then hi_fill_missing,im,hdr
  hdr = SCC_UPDATE_HISTORY(hdr,'Applied exposure weighting')
  hdr.bunit='DN/s'
	IF ~keyword_set(SILENT) THEN message,'Exposure Normalized to 1 Second, exposure weighting method',/info

endif else begin
;--Correct for desmear(ON)
  im=hi_desmear(im,hdr,_extra=ex)
  if hdr.nmissing gt 0 then hi_fill_missing,im,hdr
    ; hdr history updated in hi_desmear
  hdr.bunit='DN/s'
	IF ~keyword_set(SILENT) THEN message,'Exposure Normalized to 1 Second, desmearing method',/info
ENDelse

; need to capture ipsum for diffuse source correction code

ipkeep=hdr.ipsum

;--Apply calibration factor (currently summing correction only)
; DO NOT do this before hi_desmear because it can modify IPSUM!!!!
IF keyword_set(CALFAC_OFF) THEN calfac=1.0 ELSE $
calfac = GET_CALFAC(hdr,_EXTRA=ex)

diffuse=1.0

IF calfac NE 1.0 THEN BEGIN
	hdr = SCC_UPDATE_HISTORY(hdr,'Applied calibration factor',value=calfac)
	IF ~keyword_set(SILENT) THEN message,'Applied calibration factor'+string(calfac),/info
        if ~keyword_set(calimg_off) then begin
            diffuse=scc_hi_diffuse(hdr,ipsum=ipkeep)
            hdr=scc_update_history(hdr,'Applied diffuse source correction')
	    IF ~keyword_set(SILENT) THEN message,'Applied diffuse source correction',/info
        endif
ENDIF ELSE calfac_off=1

;--Correction for flat field and vignetting (ON)
IF keyword_set(calimg_off) THEN calimg = 1.0 ELSE BEGIN
  calimg = GET_CALIMG(hdr,fn,_EXTRA=ex)
  IF (size(calimg))(0) GT 1 THEN $
  hdr = SCC_UPDATE_HISTORY(hdr,'Applied Flat Field '+fn)
ENDELSE

;------------------------------------------------------------------------
;--Apply Correction
im = float(temporary(im)*calimg*calfac*diffuse)

;help,im
;----------------------------------------------------------------------

RETURN,im
END
