FUNCTION xrt_flux_ch, te, fw1, fw2, time, $
         cal = cal, index=index, vem=vem, cem=cem, electron=electron, $
         datapoint=datapoint, $
         contamination_thickness=contamination_thickness, info=info, $ 
         message=message, lambda_spectrum = lambda_spectrum, $
         te_spectrum = te_spectrum, spectrum = spectrum, $
         apac_spectrum = apac_spectrum, eff_area = eff_area, $
         hybrid=hybrid, photospheric=photospheric, spectrum_file=spectrum_file, $
         ch_version=ch_version

; =========================================================================
;+
; PROJECT:
;
;       Solar-B / XRT 
;
; NAME:
;       
;       XRT_FLUX_CH
;
; CATEGORY:
;       
;       XRT RESPONSE
;
; PURPOSE:
;       
;       Get the data number (DN) flux [sec^-1 pixel^-1]
;       when XRT observes the solar plasma at an inputed temperature (for CEM = 1 [cm^-5] in default),
;       i.e., get the XRT temperature response.
;       Covered temperature range is from 10^5.0 to 10^8.0 [K].
;
;       In default, this program use the solar spectrum
;       calculated with CHIANTI database ver. 6.0.1
;       (density: 10^9 [cm^-3], ionization equilibrium: chianti.ioneq, abundance: sun_coronal_ext.abund).
;
; CALLING SEQUENCE:
;
;       result = XRT_FLUX(te, fw1, fw2, time, [index=index], $
;                         [vem=vem], [cem=cem], [/electron], [/datapoint], $
;                         [contamination_thickness=contamination_thickness], [/info], $
;                         [lambda_spectrum = lambda_spectrum, te_spectrum = te_spectrum, spectrum = spectrum], $
;                         [/apac_spectrum], [eff_area = eff_area])
;       
; INPUTS:
;       
;       TE              - (float array) log Temperature with a range from 5.0 to 8.0.
;       FW1             - (long) Filter No. on filter wheel 1.
;       FW2             - (long) Filter No. on filter wheel 2.
;       TIME            - (string) Time when you want to calculate the XRT flux,
;                     because XRT flux influenced by contamination is a function of time.
;                     This time is used to derive the thickness of contaminant.
;                     If you directly give the contamination thickness with CONTAMINATION_THICKNESS
;                     keyword, you should omit this TIME input.
;
; KEYWORDS:
;
;		CAL             - [Optional input] If set as "cal = 1", the flux is calculated based
;					 on the calibration in Narukage et al. (2011). If "cal = 2", the flux is 
;					 calculated based on the calibration in Narukage et al. (2014), in which the thickness of
;					 of thick X-ray analysis filters (med-Be, med-Al, thick-Al and thick-Be) were updated.
;                    Default is "cal = 2" using the latest calibration result of Narukage et al. (2014).
;       INDEX           - [Optional input] (structure) If set, you can omit the inputs of FW1, FW2 and TIME.
;       VEM             - [Optional input] (float) volume emission measure [cm^-3] of solar plasma in logalithmic scale (e.g., VEM = 44. for 1e44 [cm^-3]).
;       CEM             - [Optional input] (float) column emission measure [cm^-5] of solar plasma in logalithmic scale (e.g., CEM = 26. for 1e26 [cm^-5]).
;       /ELECTRON       - [Optional] (Boolean) If set, unit of return value is [electron sec^-1 pixel^-1].
;       /DATAPOINT      - [Optional] (Boolean)
;                    If set, result is calculated at the data point of temperature and
;                    the data point is inputed into "te" parameter.
;                    The data point of temperature is from 10^5.0 to 10^8.0 [K] with 10^0.05 [K] resolution.
;       CONTAMINATION_THICKNESS - [Optional input] (float)
;                    You can directly give the contamination thickness.
;                    When you use this keyword, you should omit the input of TIME.
;       /INFO           - [Optional] (Boolean) If set, information is shown.
;       LAMBDA_SPECTRUM - [Optional input] (float array) wavelength for SPECTRUM in an unit of [A].
;       TE_SPECTRUM     - [Optional input] (float array) temperature for SPECTRUM in an unit of [log K].
;       SPECTRUM        - [Optional input] (2-dim float array, [lambda_spectrum, te_spectrum]) photon number spectrum from solar plasma in an unit of [cm^3 s^-1 sr^-1].
;                                   We recommend that
;                                     (1) The data point of wavelength is from 1 to 400 [A] with 0.1 [A] resolution.
;                                     (2) The data point of temperature is from 10^5.0 to 10^8.0 [K] with 10^0.05 [K] resolution.
;       /APAC_SPECTRUM  - [Optional] (Boolean) If set, solar spectrum calculated with APAC database is used. (in default, solar spectrum is calculated with CHIANTI database.)
;       EFF_AREA        - [Optional] (Structure) You can input the output (effective area) from MAKE_XRT_WAVE_RESP.PRO.
;	SPECTRUM_FILE   - [Optional] (scalar string) 
;              		specify the name of the solar spectrum files (with path).
;	CH_VERSION	- [Optional] (scalar string of length 4). Specify 
;			the desired version of solar spectrum files calculated with 
;			CHIANTI (Densities: 10^9 [cm^-3]). By default, the routine will 
;			use the latest version of Chianti that is available. These files
;			are stored in $SSW_IDL/XRT/idl/response/spectrum_files/. 
;			As of this writing, mid-2022 A.D., the versions of Chianti 
;			that are available for use by this routine are:
;			0601 = Version 6.0.1
;			0700 = Version 7.0.0
;			0710 = Version 7.1.0
;			0713 = Version 7.1.3
;			0800 = Version 8.0.0
;                       0901 = Version 9.0.1
;                       1000 = Version 10.0.0
;			list = List all available versions of Chianti. This will cause 
;			the routine to exit before calculating the temperature. 
;			The ionization equilibrium: chianti.ioneq.
;						The abundance: sun_coronal_1992_feldman_ext.       
;       HYBRID		- [Optional input] (boolean) Switch to use 
;			hybrid spectrum.
;       PHOTOSPHERIC    - [Optional input] (boolean) Switch to use 
;			photospheric spectrum.
;
; OUTPUTS:
;       
;       return - (float array) DN flux [DN sec^-1 pixel^-1] (for CEM = 1 [cm^-5] in default).
;
; EXAMPLES:
;      
;       Get X-ray flux [DN sec^-1 pixel^-1] observed with thin-Al-poly filter
;       at 11-Mar-2007 00:55:00 from the solar plasma (CEM=1 [cm^-5]):
;       IDL> te = 5.+findgen(61)*0.05
;       IDL> flux = xrt_flux(te, 1, 0, '11-Mar-2007 00:55:00')
;
;       Get X-ray flux [DN sec^-1 pixel^-1] with index from the solar plasma (VEM = 10^44 [cm^-3]):
;       IDL> te = 5.+findgen(61)*0.05
;       IDL> flux = xrt_flux(te, index = index, vem = 44.)
;
; COMMON BLOCKS:
;
;       none 
;
; NOTES:
;
;       filter on filter wheel 1
;         0: open
;         1: thin-Al-poly
;         2: C-poly
;         3: thin-Be
;         4: med-Be
;         5: med-Al
;
;       filter on filter wheel 2
;         0: open
;         1: thin-Al-mesh
;         2: Ti-poly
;         3: G-band (optical)
;         4: thick-Al
;         5: thick-Be
;
;       The detail of calibrated temperature response function of the Hinode/XRT is described in
;         Narukage et al. 2011, Solar Phys., 269, 169.
;         http://adsabs.harvard.edu/doi/10.1007/s11207-010-9685-2
;       and
;        Narukage et al. (2014) Solar Phys., 289, 1029.
;         http://adsabs.harvard.edu/doi/10.1007/s11207-013-0368-7
;       These two papers are the reference papers of this program.
;
; CONTACT:
;
;       Comments, feedback, and bug reports regarding this routine may be 
;       directed to this email address: 
;                noriyuki.narukage ~at~ nao.ac.jp
;       
; MODIFICATION HISTORY:
;
progver = 'v2007-May-17' ;--- (N.Narukage (ISAS/JAXA)) Written.
progver = 'v2009-Jul-27' ;--- (N.Narukage (NAOJ)) Updated to consider the contamination on focal-plane analysis filters and CCD.
progver = 'v2010-Jul-30' ;--- (N.Narukage (NAOJ)) Updated to input the solar spectrum.
;                                                 And added the option to select the APAC database.
progver = 'v2010-Aug-04' ;--- (N.Narukage (NAOJ)) Updated to input the output from MAKE_XRT_WAVE_RESP.PRO.
progver = 'v2011-Jan-31' ;--- (N.Narukage (NAOJ)) Modified the manual.
progver = 'v2011-Feb-17' ;--- (N.Narukage (NAOJ)) Added the information on the reference paper.
progver = 'v2013-Nov-04' ;--- (N.Narukage (NAOJ)) Updated to use the calibration result of Narukage et al. (2013).
;                                                 Added the keyword of "cal" to select the calibration result.
;                                                 And modified for the message from the program.
;           2014-Feb-24' ;--- (Aki Takeda (MSU)) added keywords to accept various solar_spectrum files.
;                              AkT version created to study new XRT response functions.
;                              XRT_TEEM_CH713 does not use this function for Te&EM calculation.
;           2014-Feb-27' ;--- (Aki Takeda (MSU)) added spectrum_file keywords.
;           2015-Sep-24' ;--- (Aki Takeda (MSU)) Updated to Chianti ver.8.0.
;progver = 'v2017-Jul-14' ;--- (P. R. Jibben (SAO)) Prepared routine for distribution into SolarSoft by making the default 
;						   to search for latest version of Chianti.
progver = 'v2022-Feb-25' ;--- (Lucas Guliano (SAO) Updated default to the latest version of Chianti (V10.0), still autos to most recent
;-
; =========================================================================

  ps = path_sep()
  file_prefix = get_logenv('$SSW_XRT') + ps + 'idl' + ps + 'response' + ps + 'j' + ps
  

; --- setting for message -------------------------------------------------

  if not keyword_set(message) then message = ['XRT_FLUX']

; --- read filter config data ---------------------------------------------

  config = xrt_config(cal = cal)

; --- process of option ---------------------------------------------------

  if keyword_set(index) then begin
    time = anytim(index.date_obs, /ecs)
    fw1 = index.ec_fw1
    fw2 = index.ec_fw2
  endif

; --- read solar spectrum -------------------------------------------------

  if not(keyword_set(lambda_spectrum) and keyword_set(te_spectrum) and keyword_set(spectrum)) then begin

    if keyword_set(apac_spectrum) then begin

      print, '** Assumed APAC spectrum'
      temp = get_xrt_spec_genx()

      dl = temp.wave[1] - temp.wave[0]

      lambda_spectrum = temp.wave[0:temp.WLENGTH-1.]
      te_spectrum     = temp.temp[0:temp.TLENGTH-1.]
      spectrum        = temp.spec[0:temp.WLENGTH-1., 0:temp.TLENGTH-1.] * dl

    endif else begin

     ; Code to select the latest Chianti spectrum file.

     ; switch that is used.
     listver=0B

     dir_spec = get_logenv('$SSW_XRT') + ps + 'idl' + ps + 'response' + ps + 'solar_spectrum' + ps

   ; Default spectra and settings to use. 
     spectra_ver='1000'
     sp_type='corona'
     solar_spe_file=dir_spec+'solspec_ch1000_corona_chianti.genx'

    sfiles=file_search(dir_spec,'*.genx')
    sfiles=file_basename(sfiles)
    ChVers=strmid(sfiles,10,4)
    ChVers=chVers[uniq(chVers)] 
    
    if not keyword_set(ch_version) then $
      spectra_ver=string(max(fix(ChVers)),format='(I04)')

    if keyword_set(ch_version) then begin
      verloc=where(strmatch(ChVers,ch_version,/fold_case) eq 1,count)      
      if count eq 1 then spectra_ver=ChVers[verloc[0]] else listver=1B

      if (strmatch(ch_version,'list',/fold_case) eq 1 or listver eq 1) then begin
        box_message,['Available Chianti Versions:',ChVers]
        return,ChVers
      endif
    endif

    if keyword_set(photospheric) then sp_type='photos'
    if keyword_set(hybrid) then sp_type='hybrid'
    solar_spe_file=dir_spec+'solspec_ch'+spectra_ver+'_'+sp_type+'_chianti.genx'


    if keyword_set(spectrum_file) then solar_spe_file = spectrum_file

      print,'*** Assumed spectrum file : ', file_basename(solar_spe_file)

      restgen, te_spectrum, lambda_spectrum, spectrum, file=solar_spe_file

    endelse

  endif

; --- calculate flux ------------------------------------------------------

  p = config.ccd.plate_scale ; XRT CCD plate scale [arcsec]
  s = (config.ccd.pixel_size / 1.e4)^2. ; area of 1 pixel on CCD [cm^2]
  f = config.var.focal_length ; focal length of XRT [cm]

  if keyword_set(eff_area) then begin
    temp = fltarr(6,6)
    temp[*,*] = -1.
    temp[0,1] =  0. ; Al-mesh
    temp[1,0] =  1. ; Al-poly
    temp[2,0] =  2. ; C-poly
    temp[0,2] =  3. ; Ti-poly
    temp[3,0] =  4. ; Be-thin
    temp[4,0] =  5. ; Be-med
    temp[5,0] =  6. ; Al-med
    temp[0,4] =  7. ; Al-thick
    temp[0,5] =  8. ; Be-thick
    temp[1,1] =  9. ; Al-poly/Al-mesh
    temp[1,2] = 10. ; Al-poly/Ti-poly
    temp[1,4] = 11. ; Al-poly/Al-thick
    temp[1,5] = 12. ; Al-poly/Be-thick
    temp[2,2] = 13. ; C-poly/Ti-poly
    temp[2,4] = 14. ; C-poly/Al-thick

    if temp[fw1, fw2] ne -1 then begin
      temp = eff_area[temp[fw1, fw2]].effar
      ea = interpol(temp.eff_area[0:temp.length-1], temp.wave[0:temp.length-1], lambda_spectrum) > 0.
      if keyword_set(info) and n_elements(temp.name) ne 0 then begin
        print
        print, temp.name
        print
      endif
    endif else begin
      ea = fltarr(n_elements(lambda_spectrum))
      ea[*] = 0.
      message = [message, '']
      message = [message, '*****  WARNING from XRT_FLUX.PRO  *****************************************']
      message = [message, 'Your inputted EFF_AREA as a keyword does not contain']
      message = [message, '  the effective area information about']
      message = [message, '    '+config.filter1[fw1].name+' (FW1) / '+config.filter2[fw2].name+' (FW2).']
      message = [message, '*****************************************  WARNING from XRT_FLUX.PRO  *****']
    endelse
  endif else begin
    ea = xrt_eff_area(lambda_spectrum, fw1, fw2, time, cal=cal, index=index, contamination_thickness=contamination_thickness, info=info, message=message)
  endelse

  ea = rebin( ea, n_elements(lambda_spectrum), n_elements(te_spectrum) ) ; effective area [cm ^ 2]

  FP = spectrum * s * ea / (f^2.) ; photon number flux detected by CCD 1 pixel from CEM = 1 [cm^-5] plasma

  h = 6.6261e-27 ; plank constant
  c = 2.9979e10 ; speed of light [cm/s]

  cf = rebin( (h*c/(lambda_spectrum*1.e-8)), n_elements(lambda_spectrum), n_elements(te_spectrum) ) ; factor to convert photon count to erg
  FE = FP * cf ; energy flux detected by CCD 1 pixel from CEM = 1 [cm^-5] plasma

  cf = 3.65*1.602*1.e-12 ; factor to convert erg to electron count
  EC = FE / cf ; electron count from CCD 1 pixel from CEM = 1 [cm^-5] plasma

  if (n_elements(cem) eq 0) then cem = 0.
  cf = 10.^cem                                ; factor to convert CEM

  if (n_elements(vem) ne 0) then begin
    if keyword_set(index) then time = anytim(index.date_obs, /ecs)
    if keyword_set(time)  then l = 696000.e5 / get_rb0p(time, /radius, /quiet) else l = 726.e5
    cf = 10.^( vem - (alog10(p*l)*2.) )  ; factor to convert VEM
  endif

  flux = total(EC,1) * cf

  gain = config.ccd.gain

  if not keyword_set(electron) then flux = flux / gain ; convert electron count to DN.

  if keyword_set(datapoint) then te = te_spectrum else flux = INTERPOL( flux, te_spectrum, te )

; --- filter name ------------------------------------------------------------

  fw1name = config.filter1[fw1].name
  fw2name = config.filter2[fw2].name

;  print, 'filter (FW1/FW2): '+fw1name+' / '+fw2name


; --- show message ------------------------------------------------------------

  if n_elements(message) ge 2 then begin
    if message[0] eq 'XRT_FLUX' then hprint, [message[1:*], '']
  endif

; --- return result -----------------------------------------------------------

  return, flux

END
