FUNCTION xrt_flux1102_slmd_fctm, 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, $
;
         corona=corona, hybrid=hybrid, photospheric=photospheric, $
         cr2012=cr2012, ioneq_v6=ioneq_v6, ph2009=ph2009, ph2011=ph2011, $
         cr1992=cr1992, ph2015=ph2015, spe_file=spe_file, $
         sp_info=sp_info, $
;
         frac_open=frac_open, fctm_fact=fctm_fact

; =========================================================================
;+
; PROJECT:
;
;       Solar-B / XRT 
;
; NAME:
;       
;       XRT_FLUX (with frac_open and fctm_fact keywords)
;
; 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. 10.0.
;       (density: 10^9 [cm^-3], ionization equilibrium: chianti.ioneq, abundance: sun_coronal_ext.abund).
;
; CALLING SEQUENCE:
;
;       result = XRT_FLUX_slmd_fctm(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 calcurate 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.
;   FRAC_OPEN  - (float) Open fraction of pre-fileter (0.0 : no opening -- 1.0 : fully open)
;   FCTAM_FACT - (float) Filter contamination enhancement factor
;
; KEYWORDS:
;
;       CAL        - [Optional input] If set as "cal = 1", the flux is calculated based on the calibration in Narukage et al. (2011).
;                                     If set as "cal = 2", the flux is calculated based on the calibration in Narukage et al. (2013).
;                                     Default is "cal = 2" to use the latest calibration result of Narukage et al. (2013).
;       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.
;
; 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.)
;
;       IDL> ofrac=get_pf_openfrac(index)
;       IDL> fctm=get_fctm_fact7_xx(index)  ; xx: filter pair
;       IDL> flux = xrt_flux1102_slmd_fctm(te, index = index, vem = 44., $
;                       /corona, frac_open=ofrac, fctm_fact=fctm)
;
; 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. 2013, Solar Phys., in press
;         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 spe_file keywords.
;          '2015-Sep-11' ;--- (Aki Takeda (MSU)) modified to calculate flux with partially opened pre-filter.
;          '2020-Jun-19' ;--- (Aki Takeda (MSU)) modified to use newer Chianti DB (ver.7.1.3 --> 9.0.1).
;          '2021-Mar-12' ;--- (Aki Takeda (MSU)) modified to use keyword, FCTAM_FACT.
;          '2022-Jan-02' ;--- (Aki Takeda (MSU)) Modified and renamed to use Chianti DB (ver.9.0.1 --> 10.0).
;          '2023-Aug-12' ;--- (Aki Takeda (MSU)) Modified and renamed to use Chianti DB (ver.10.0 --> 10.1).
;                                     added /cr1992 keyword for coronal abundance by Feldman 1992.
;                                     added /ph2015 keyword for photospheric abundance by Scott 2015.
;          '2025-Oct-03' ;--- (Aki Takeda (MSU)) Modified and renamed to use Chianti DB (ver.10.1 --> 11.02).
;-
; =========================================================================

  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

      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

      dir_sp = '/home/takeda/idlpro/xrt/xrt_resp/solar_spectrum/'
;       dir_sp = '/disk/yla/software/xrt_ssw/solar_spectrum/'

;       solar_spe_file = 'XRT_solar_spe-chianti_6.0.1-edensity_1e9-chianti.ioneq-sun_coronal_ext.abund'
      solar_spe_file = dir_sp+'solspec_ch1102_cr2021chianti_adv'
;
      if keyword_set(corona) then       solar_spe_file = dir_sp+'solspec_ch1102_cr2021chianti_adv'
      if keyword_set(photospheric) then solar_spe_file = dir_sp+'solspec_ch1102_ph2021asplund_adv.genx'
      if keyword_set(cr1992) then solar_spe_file = dir_sp+'solspec_ch1102_cr1992feldman_adv.genx'
      if keyword_set(hybrid) then solar_spe_file = dir_sp+'solspec_ch1102_cr2012schmelz_adv.genx'
      if keyword_set(cr2012) then solar_spe_file = dir_sp+'solspec_ch1102_cr2012schmelz_adv.genx'
;      if keyword_set(ph2015) then solar_spe_file = dir_sp+'solspec_ch1010_ph2015scott_chianti.genx'
;      if keyword_set(ph2009) then solar_spe_file = dir_sp+'solspec_ch1000_ph2009asplund_chianti.genx'
;      if keyword_set(ph2011) then solar_spe_file = dir_sp+'solspec_ch1000_ph2011caffau_chianti.genx'
      if keyword_set(spe_file) then solar_spe_file = spe_file

      print,'*** Assumed spectrum file : ', solar_spe_file
;
      restgen, te_spectrum, lambda_spectrum, spectrum, file=solar_spe_file
;       restgenx, te_spectrum, lambda_spectrum, spectrum,  $
;                file = file_prefix + 'database' + ps + 'solar_spe' + ps + solar_spe_file
   ; spectrum : photon number spectrum from solar plasma (n = 10^9 [cm^-3]) [cm^3 s^-1 sr^-1]

    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_slmd_fctm(lambda_spectrum, fw1, fw2, time, cal=cal, $
          index=index, $ ; contamination_thickness=contamination_thickness, $
          info=info, message=message, frac_open=frac_open, fctm_fact=fctm_fact)
    print,'frac_open assumed: ', frac_open
    print,'fctm_fact assumed: ', fctm_fact
  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
