;+
; NAME:
;	  IRIS_CALIB_SPECTRUM
;
; PURPOSE:
;	  Absolute radiometric calibration of an IRIS spectrum. By default the
;   spectrum will be returned in cgs units erg cm^-2 s^-1 sr^-1 Å^-1.
;
; CATEGORY:
;   Data analysis
;	
; CALLING SEQUENCE:
;   EBDETECT, Inputspectrum, Wavelength
;
; INPUTS:
;   Inputspectrum - The input spectrum as obtained from an IRIS SG file. Should
;                   be a 1D array.
;   Wavelength    - The wavelength array. Should be a 1D array with as many
;                   elements as Inputspectrum.
;
; OPTIONAL INPUTS:
;
; KEYWORD PARAMETERS:
;   TIME          - Date and time of the observation. Should be supplied with
;                   DATE_OBS value from the IRIS SG file header. Format
;                   '2014-10-25T05:17:13.730'. Defaults to date and time when
;                   function is called.
;   BINXY         - Spatial binning factor with which the spectra were recorded.
;                   Defaults to 1.
;   BINL          - Wavelength binning factor with which the spectra were
;                   recorded. Defaults to 1.
;   T_EXP         - Exposure time in seconds. Defaults to 1.
;   /A_EFF_ONLY   - Return the spectrum corrected for effective area only (so no
;                   absolute radiometric calibration). Defaults to not set.
;   /I_NU         - Return the spectrum in frequency units, i.e., Hz^-1. Can be
;                   combined with /SI flag. Defaults to not set.
;   /SI           - Return the spectrum in SI units, W m^-2 s^-1 sr^-1 nm^-1.
;                   Can be combined with /I_NU flag, in which case the units
;                   will be W m^-2 s^-1 sr^-1 Hz^-1. Defaults to not set.
;   /VERBOSE      - Print out status messages. Defaults to not set.
;   /DEBUG        - Stop before returning from the function. Defaults to not
;                   set.
;
; OUTPUTS:
;   1D array with radiometric calibrated spectrum.
;
; OPTIONAL OUTPUTS:
;
; COMMON BLOCKS:
;
; SIDE EFFECTS:
;
; RESTRICTIONS:
;   Requires SSWIDL and the following function:
;   Functions: IRIS_GET_RESPONSE()
;
; PROCEDURE:
;
; EXAMPLE:
;   calib_spectrum = IRIS_CALIB_SPECTRUM(Inputspectrum, Wavelength)
;
; MODIFICATION HISTORY:
;   2015 Mar Gregal Vissers: First version
;   2016 Nov GV: Extensive overhaul adding BINXY, BINL, I_NU and SI
;                 options.
;   2017 Oct A. Sainz Dalda: 'factor' keyword introduced to recover the
;            calibration factor. 
;   2019 May A. Sainz Dalda: 'dn2photon' keyword introduced to recover the
;            dn2photon factor. 
;   2019 June A. Sainz Dalda: 'Ephoton' keyword introduced to recover the
;            Ephoton factor. 
;   $Id$
;-
;
FUNCTION IRIS_CALIB_SPECTRUM, Inputspectrum, Wavelength, TIME=time, $
  A_EFF_ONLY=a_eff_only, VERBOSE=verbose, BINXY=binxy, BINL=binl, $
  T_EXP=t_exp, I_NU=i_nu, DEBUG=debug, SI=si, $
  factor = factor, dn2photon = dn2photon, Ephoton = Ephoton   

  IF (N_PARAMS() LT 2) THEN BEGIN
    MESSAGE, 'Syntax: calib_spectrum = IRIS_CALIB_SPECTRUM(Inputspectrum, '+$
      'Wavelength [, TIME=time] [, BINXY=binxy] [, BINL=binl] [, T_EXP=texp] '+$
      '[, /A_EFF_ONLY] [, /I_NU] [, /SI] [, /VERBOSE] [, /DEBUG])', /INFO
    RETURN,-1
  ENDIF

  ; Process input keywords
  IF (N_ELEMENTS(TIME) EQ 1) THEN $
    ;resp = IRIS_GET_RESPONSE(time, VERSION='003') $
    resp = IRIS_GET_RESPONSE(time) $
  ELSE $
    ;resp = IRIS_GET_RESPONSE(VERSION='003') 
    resp = IRIS_GET_RESPONSE() 
  IF (N_ELEMENTS(BINXY) NE 1) THEN $
    binxy = 1.
  IF (N_ELEMENTS(BINL) NE 1) THEN $
    binl = 1.
  IF (N_ELEMENTS(T_EXP) NE 1) THEN $
    t_exp = 1.
  

  ; Get necessary wavelength range
  nm = (MAX(Wavelength,/NAN) LT 1000)
  resp.lambda *= 10^(FLOAT(~KEYWORD_SET(NM)))
  wavelength_cm = Wavelength / 10^FLOAT(8-KEYWORD_SET(NM))
  
  IF KEYWORD_SET(VERBOSE) THEN $
    MESSAGE, 'Input wavelength range: '+STRTRIM(Wavelength[0],2)+'-'+$
      STRTRIM(Wavelength[-1],2)+' '+(['A','nm'])[nm], /INFO

  lambda_avail_fuv = resp.lambda[WHERE(resp.area_sg[*,0] NE 0)]
  lambda_avail_nuv = resp.lambda[WHERE(resp.area_sg[*,1] NE 0)]

  ; Wavelength within FUV or NUV?
  idx = ((Wavelength[0] GE lambda_avail_nuv[0]) AND $
        (Wavelength[-1] LE lambda_avail_nuv[-1]))
 
  cond_fuv = where((Wavelength lt max(lambda_avail_fuv) and Wavelength gt min(lambda_avail_fuv)) eq 1)
  cond_nuv = where((Wavelength lt max(lambda_avail_nuv) and Wavelength gt min(lambda_avail_nuv)) eq 1)
 
  print, 'Conditional values FUV, NUV...' , cond_fuv[0], cond_nuv[0]

  if cond_fuv[0] ne -1 and cond_nuv[0] eq -1 then idx = 0
  if cond_fuv[0] eq -1 and cond_nuv[0] ne -1 then idx = 1
  if cond_fuv[0] eq -1 and cond_nuv[0] eq -1 then begin
     print, 'Wavelength values are not available in the response calibration wavelength'
     stop
  endif 

  IF KEYWORD_SET(VERBOSE) THEN $
    MESSAGE, 'Using '+(['FUV','NUV'])[idx]+' response',/INFO

  a_eff_sel = INTERPOL(resp.area_sg[*,idx], resp.lambda, Wavelength)
  IF KEYWORD_SET(VERBOSE) THEN $
    MESSAGE, 'Selected effective area statistics: (min,mean,max)=('+$
      STRTRIM(MIN(a_eff_sel,/NAN),2)+','+$
      STRTRIM(MEAN(a_eff_sel,/NAN),2)+','+$ 
      STRTRIM(MAX(a_eff_sel,/NAN),2)+')',/INFO

  ; Alwasy divide by the effective area
  ;outputspectrum = Inputspectrum / a_eff_sel 
  outputspectrum = Inputspectrum ;;;;      / a_eff_sel  Term included in FACTOR Mod. 20170613 ASD
  IF NOT KEYWORD_SET(A_EFF_ONLY) THEN BEGIN
    h = 6.62606885D-27  ; erg s
    c = 2.99792458D10   ; cm/s
    w_slit = !PI/(180.*3600.*3.)
    pix_xy = binxy * w_slit/2.
    CASE idx OF
      0:  BEGIN
            ; FUV1=1331.56-1358.40, FUV2=1390.00-1406.79
            IF (Wavelength[-1] LT 1370.) THEN $
              pix_l = 0.0129 $
            ELSE $
              pix_l = 0.0127
          END
      1:  pix_l = 0.02546  ; Å/pix
    ENDCASE
    pix_l *= binl 
    numerator = h * c / wavelength_cm  * resp.dn2phot_sg[idx]
    ;denominator = a_eff_sel * pix_xy * pix_l * t_exp * w_slit
    denominator = a_eff_sel * pix_xy * pix_l * t_exp * w_slit  ;;; a_eff_sel  Term included in FACTOR Mod. 20170613 ASD
    ; print, a_eff_sel ;, pix_xy, pix_l, t_exp, w_slit ;, denominator
    ; print, a_eff_sel, pix_xy, pix_l, t_exp, w_slit ;, denominator
    factor = numerator / denominator
    dn2photon = resp.dn2phot_sg[idx]
    Ephoton =  h * c / wavelength_cm

    ;outputspectrum *= factor
    ;IF KEYWORD_SET(I_NU) THEN outputspectrum *= Wavelength * Wavelength / 3.E18
    ;IF KEYWORD_SET(SI) THEN outputspectrum *= 1.E-3
    ; FACTOR Mod. 20170613 ASD
    IF KEYWORD_SET(I_NU) THEN factor *= Wavelength * Wavelength / 3.E18
    IF KEYWORD_SET(SI) THEN factor *= 1.E-3
    outputspectrum *= factor
    ; FACTOR Mod. 20170613 ASD

    IF KEYWORD_SET(VERBOSE) THEN $
      MESSAGE, 'Spectrum converted by: (min,mean,max)=('+$
        STRTRIM(MIN(factor,/NAN),2)+','+$
        STRTRIM(MEAN(factor,/NAN),2)+','+$ 
        STRTRIM(MAX(factor,/NAN),2)+')',/INFO
  ENDIF

  IF KEYWORD_SET(DEBUG) THEN STOP
  RETURN, outputspectrum
END

