FUNCTION make_xrt_sr, eff_areas, channels, verbose=verbose, quiet=quiet,  $
                      qabort=qabort, qstop=qstop

; =========================================================================
;+
; PROJECT:
;       Solar-B / XRT 
;
; NAME:
;       
;       MAKE_XRT_SR
;
; CATEGORY:
;       
;       Instrument response
;
; PURPOSE:
;
;       Produce the spectral response functions for a set of XRT x-ray 
;       channels (including the CCD contamination layer).
;       (This subroutine of <make_xrt_wave_resp.pro> replaces
;       <calc_xrt_spec_resp.pro>.)
;
; CALLING SEQUENCE:
;
;       Result = MAKE_XRT_SR( eff_areas, channels [,/verbose] [,/quiet] 
;                  [,qabort=qabort] [,/qstop]                           )
;
; INPUTS:
;
;       EFF_AREAS - [Mandatory] (structure array,
;                                {XRT_eff_area_vNNNN} [Nresponses])
;                   This structure array contains data and
;                   information about the effective areas for a
;                   set of x-ray channels paired with contamination
;                   layer thicknesses.
;
;                   EFF_AREAS {XRT_eff_area_vNNNN}
;                   - TYPE            (string scalar)
;                   - EFF_STR_VERSION (string scalar)
;                   - EFF_STR_DESCR   (string scalar)
;                   - NAME            (string scalar)
;                   - WAVE            (float array, [Nwave])
;                   - WAVE_UNITS      (string scalar)
;                   - EFF_AREA        (float array, [Nwave])
;                   - EFF_AREA_UNITS  (string scalar)
;                   - LENGTH          (long scalar)
;                   - GAIN_USED       (float scalar)
;                   - HISTORY         (string array, [3])
;                   - COMMENTS        (string array, [5])
;
;                   Here are descriptions of the fields in the
;                   "XRT_eff_area" structure.:
;
;                   TYPE: (string scalar)
;                       [Default value = 'XRT_eff_area'.]
;                       This is the generic name of the structure
;                       that contains the effective areas and
;                       related information. The version of the
;                       structure definition might evolve, but
;                       the TYPE should remain constant. See
;                       EFF_STR_VERSION. This field should NOT
;                       be changed.
;                   EFF_STR_VERSION: (string scalar)
;                       [The default value = 'XRT_eff_area_vNNNN',
;                       where NNNN is a 4-digit number.]
;                       This is the version number of the "XRT_eff_area"
;                       structure definition. In addition to being
;                       recorded in this field, this is also the
;                       "unique structure name" in the IDL sense.
;                       This field should NOT be changed.
;                   EFF_STR_DESCR: (string scalar)
;                       This is a sentence or two that describes the
;                       purpose of this structure type. This field
;                       should NOT be changed.
;                   NAME: (string scalar)
;                       This is a name for this pair of XRT x-ray
;                       channel and contamination layer thickness.
;                       This string should be a concise identifier
;                       (although it may not be unique). Some
;                       programs may refer to this string, so its
;                       usage should be regularized. This field
;                       MAY be changed, but the default is
;                       recommended.
;                   WAVE: (float array, [Nwave])
;                       The wavelength abscissa of the effective
;                       area function (see EFF_AREA tag) for a
;                       specified pair of XRT x-ray channel and
;                       contamination layer thickness. The values
;                       must make a montonically increasing
;                       sequence of floating point numbers,
;                       starting from the first address of the
;                       array. If the sequence is shorter than
;                       the length of this array, then all addresses
;                       after the sequence ends should have a
;                       value of zero. The sequence length is
;                       recorded in the LENGTH tag. The values
;                       must be consistent with the units named
;                       in WAVE_UNITS.
;                   WAVE_UNITS: (string scalar)
;                       Units of the value in the WAVE tag. The units
;                       must be 'Angstroms' (so that other programs
;                       can reliably interpret WAVE).
;                   EFF_AREA: (float array, [Nwave])
;                       The x-ray channel's effective area as a
;                       function of wavelength (see WAVE), with
;                       accounting for some thickness of the CCD
;                       contamination layer. The values must
;                       make a sequence of floating point numbers,
;                       starting from the first address of the
;                       array, and should correspond in position
;                       to values of WAVE. If the sequence is
;                       shorter than the length of this array,
;                       then all addresses after the sequence
;                       ends should have a value of zero. The
;                       sequence length is recorded in the LENGTH
;                       tag. The values must be consistent with
;                       the units named in EFF_AREA_UNITS.
;                   EFF_AREA_UNITS: (string scalar)
;                       Units of the value in the EFF_AREA tag.
;                       The units must be 'cm^2' (so that other
;                       programs can reliably interpret EFF_AREA).
;                   LENGTH: (long scalar)
;                       The length of the paired sequences of WAVE
;                       and EFF_AREA, indicating how much of those
;                       arrays contains useful information. E.g.:
;                       IDL> len = eff_areas[0].length
;                       IDL> plot, eff_areas[0].wave[0:len-1],  $
;                       IDL>       eff_areas[0].eff_area[0:len-1]
;                   HISTORY: (string array, [3])
;                       This text array is for XRT programs to
;                       record any instance in which they have
;                       modified the content of the "XRT_eff_area"
;                       type of structure for this particular
;                       pair of XRT x-ray channel and contamination
;                       layer thickness.  On creation, a line is
;                       added for the creation of the "XRT_eff_area"
;                       structure in <make_xrt_ea.pro>.  An entry
;                       string is composed of (a) a program name,
;                       (b) the program's version/date, (c) colon
;                       separator, (d) Timestamp (in parentheses)
;                       of when the program completed the described
;                       action, and (e) a summation of what the
;                       program created or modified in the
;                       "XRT_eff_area" structure.  Values are
;                       inserted starting at the lowest address
;                       of this array. Remaining unused addresses
;                       are filled with the empty string.  Filled
;                       strings should NOT be overwritten.  Users
;                       should use the COMMENTS field to add their
;                       own notations to this structure.
;                   COMMENTS: (string array, [5])
;                       A tag for adding notations regarding this
;                       specific effective area.  Users and
;                       programs are encouraged to put content
;                       in the lower addresses, and assign empty
;                       strings {''} to the higher, unused
;                       addresses.
;
;       CHANNELS  - [Mandatory] (structure array,
;                                {XRT_chn_config_vNNNN} [Nthicknesses])
;                   This is an array of structures of type
;                   "XRT_chn_config" and with a structure name
;                   of the form {XRT_chn_config_vNNNN}. For a
;                   more complete description of this complicated
;                   structure, see the XRT Analysis Guide. The
;                   base set of channels is provided in the XRT SSWIDL
;                   tree by a file with a pathname like this:
;       $SSW_XRT/idl/response/channels/xrt_channels_vNNNN.geny
;                   That file is automatically found, read, and passed
;                   to <make_xrt_sr.pro> if <make_xrt_wave_resp.pro>
;                   is used as the interface, as intended.
;
; KEYWORDS:
;
;       /VERBOSE  - [Optional] (Boolean) If set, print out extra
;                   information. Overrides "/quiet" (see Note #2).
;       /QUIET    - [Optional] (Boolean) If set, suppress messages
;                   (see Note #2).
;       /QSTOP    - [Optional] (Boolean) For debugging.
;
;
; OUTPUTS:
;
;       Return    - [Mandatory] (structure array,
;       (SPEC_RESP)              {XRT_spec_resp_vNNNN} [Nresponses])
;                   This structure array contains data and
;                   information about the spectral responses for a
;                   set of x-ray channels paired with contamination
;                   layer thicknesses. 
;
;                   SPEC_RESP {XRT_spec_resp_vNNNN}
;                   - TYPE            (string scalar)
;                   - SRS_STR_VERSION (string scalar)
;                   - SRS_STR_DESCR   (string scalar)
;                   - NAME            (string scalar)
;                   - WAVE            (float array, [Nwave])
;                   - WAVE_UNITS      (string scalar)
;                   - SPEC_RESP       (float array, [Nwave])
;                   - SPEC_RESP_UNITS (string scalar)
;                   - LENGTH          (long scalar)
;                   - HISTORY         (string array, [3])
;                   - COMMENTS        (string array, [5])
;
;                   Here are descriptions of the fields in the
;                   "XRT_spec_resp" structure.:
;
;                   TYPE: (string scalar)
;                       [Default value = 'XRT_spec_resp'.]
;                       This is the generic name of the structure
;                       that contains the spectral responses and
;                       related information. The version of the
;                       structure definition might evolve, but
;                       the TYPE should remain constant. See
;                       SRS_STR_VERSION. This field should NOT
;                       be changed.
;                   SRS_STR_VERSION: (string scalar)
;                       [The default value = 'XRT_spec_resp_vNNNN',
;                       where NNNN is a 4-digit number.]
;                       This is the version number of the "XRT_spec_resp"
;                       structure definition. In addition to being
;                       recorded in this field, this is also the
;                       "unique structure name" in the IDL sense.
;                       This field should NOT be changed.
;                   SRS_STR_DESCR: (string scalar)
;                       This is a sentence or two that describes the
;                       purpose of this structure type. This field
;                       should NOT be changed.
;                   NAME: (string scalar)
;                       This is a name for this pair of XRT x-ray
;                       channel and contamination layer thickness.
;                       This string should be a concise identifier
;                       (although it may not be unique). Some
;                       programs may refer to this string, so its
;                       usage should be regularized. This field
;                       MAY be changed, but the default is
;                       recommended.
;                   WAVE: (float array, [Nwave])
;                       The wavelength abscissa of the spectral
;                       response function (see SpeC_RESP tag) for a
;                       specified pair of XRT x-ray channel and
;                       contamination layer thickness. The values
;                       must make a montonically increasing
;                       sequence of floating point numbers,
;                       starting from the first address of the
;                       array. If the sequence is shorter than
;                       the length of this array, then all addresses
;                       after the sequence ends should have a
;                       value of zero. The sequence length is
;                       recorded in the LENGTH tag. The values
;                       must be consistent with the units named
;                       in WAVE_UNITS.
;                   WAVE_UNITS: (string scalar)
;                       Units of the value in the WAVE tag. The units
;                       must be 'Angstroms' (so that other programs
;                       can reliably interpret WAVE).
;                   SPEC_RESP: (float array, [Nwave])
;                       The x-ray channel's spectral response as a
;                       function of wavelength (see WAVE), with
;                       accounting for some thickness of the CCD
;                       contamination layer. The values must
;                       make a sequence of floating point numbers,
;                       starting from the first address of the
;                       array, and should correspond in position
;                       to values of WAVE. If the sequence is
;                       shorter than the length of this array,
;                       then all addresses after the sequence
;                       ends should have a value of zero. The
;                       sequence length is recorded in the LENGTH
;                       tag. The values must be consistent with
;                       the units named in SPEC_RESP_UNITS.
;                   SPEC_RESP_UNITS: (string scalar)
;                       Units of the value in the SPEC_RESP tag.
;                       The units must be 'el cm^2 sr ph^-1 pix^-1' 
;                       (or 'DN cm^2 sr ph^-1 pix^-1') so that other 
;                       programs can reliably interpret SPEC_RESP.
;                   LENGTH: (long scalar)
;                       The length of the paired sequences of WAVE
;                       and SPEC_RESP, indicating how much of those
;                       arrays contains useful information. E.g.:
;                       IDL> len = sresps[0].length
;                       IDL> plot, sresps[0].wave[0:len-1],   $
;                       IDL>       sresps[0].spec_resp[0:len-1]
;                   GAIN_USED: (float scalar)
;                       This field records the camera gain value
;                       that was applied to SPEC_RESP to convert the 
;                       SPEC_RESP_UNITS from 'el cm^2 sr ph^-1 pix^-1' 
;                       to 'DN cm^2 sr ph^-1 pix^-1'. If the conversion
;                       has not been applied, then GAIN_USED = -1.0.
;                       GAIN_USED has values of 'el DN^-1'. A "DN" refers
;                       to electronic Data Numbers, for XRT's 12-bit
;                       ADU (Analog to Digital Unit) converter.
;                   HISTORY: (string array, [3])
;                       This text array is for XRT programs to
;                       record any instance in which they have
;                       modified the content of the "XRT_spec_resp"
;                       type of structure for this particular
;                       pair of XRT x-ray channel and contamination
;                       layer thickness.  On creation, a line is
;                       added for the creation of the "XRT_spec_resp"
;                       structure in <make_xrt_sr.pro>.  An entry
;                       string is composed of (a) a program name,
;                       (b) the program's version/date, (c) colon
;                       separator, (d) timestamp (in parentheses)
;                       of when the program completed the described
;                       action, and (e) a summation of what the
;                       program created or modified in the
;                       "XRT_spec_resp" structure.  Values are
;                       inserted starting at the lowest address
;                       of this array. Remaining unused addresses
;                       are filled with the empty string.  Filled
;                       strings should NOT be overwritten.  Users
;                       should use the COMMENTS field to add their
;                       own notations to this structure.
;                   COMMENTS: (string array, [5])
;                       A tag for adding notations regarding this
;                       specific spectral response.  Users and
;                       programs are encouraged to put content
;                       in the lower addresses, and assign empty
;                       strings {''} to the higher, unused
;                       addresses.
;
;       QABORT    - [Optional] (Boolean) Indicates whether the program
;                   exited gracefully without completing. (Might be
;                   useful for calling programs.)
;                   0: Program ran to completion.
;                   1: Program aborted before completion.
;
; EXAMPLES:
;
;       This program is a subroutine of <make_xrt_wave_resp.pro>.
;
; COMMON BLOCKS:
;
;       none
;
; NOTES:
;
;       1) A discussion of the calculation of the spectral response
;          function (and associated quantities and units).
;
;          More information about the relation of the spectral response to
;          the temperature response, and its usage to calculate XRT
;          observations for plasmas, may be found in the XRT Analysis
;          Guide ("XAG") and in the program header of
;          <make_xrt_wave_resp.pro>.
;
;          The spectral response function indicates the detector
;          signal (in CCD electrons for XRT) produced by a photon
;          of given energy. It contains all of the information about
;          the channel response as a function of wavelength. As
;          described in the XAG, it has units of 'el cm^2 sr ph^-1 pix^-1', 
;          which may be interpreted as "electrons (CCD signal) x 
;          effective area x solid angle per CCD pixel per photon".
;          (The spectral response function may also be given in units of
;          'DN cm^2 sr ph^-1 pix^-1', by dividing the spectral response
;          by the camera gain, which has units of 'el DN^-1'. A "DN" 
;          refers to electronic Data Numbers, for XRT's 12-bit ADU 
;          (Analog to Digital Unit) converter. This change in units is
;          immaterial in understanding the physical meaning of the 
;          spectral response, so either set of units is allowed. This 
;          conversion may be handled in a consistent way by using the
;          XRT routines.)
;
;          The spectral response function is calculated from the
;          effective area and some other instrumental characteristics.
;
;          SR = EA * (energy per photon) * (electrons freed per energy)
;               * (solid angle subtended by telescope pixel)
;
;          The effective area EA(w) is a function of (photon)
;          wavelength, and has units of 'cm^2'. It contains information
;          about the geometric aperture multiplied by the "transmission"
;          factors all along the optical path. The solid angle
;          subtended by a pixel in a telescope is (pixel area)/(focal
;          length)^2 ~ [sr pix-1]. The energy required to free a
;          CCD electron is a characteristic of the CCD. So the
;          equation looks like this:
;
;          SR(w) = EA(w) * (hc/w) * (pix_len/foc_len)^2 / eV_per_el
;
;          [el cm^2 sr ph^-1 pix^-1] = [cm^2] * [eV ph^-1] * [sr pix^-1]
;                                      / [eV el^-1]
;
;
;       2) There are three levels of verbosity.
;          a) "verbose" = highest priority. All errors and messages are
;                         displayed. ("if q_vb")
;          b) "quiet" = lower priority. No errors or messages are
;                       displayed. ("if q_qt")
;          c) neither = lowest priority. All errors and some messages are
;                       displayed. ("if not q_qt")
;
;       3) This subroutine of <make_xrt_wave_resp.pro> replaces
;          <calc_xrt_spec_resp.pro>.
;
; CONTACT:
;
;       Comments, feedback, and bug reports regarding this routine may be
;       directed to this email address:
;                xrt_manager ~at~ head.cfa.harvard.edu
;
; MODIFICATION HISTORY:
;
progver = 'v2008-Sep-01' ;--- (M.Weber) Written. Derived from
;                             <calc_xrt_spec_resp.pro>, v2007-May-16.
progver = 'v2008-Oct-01' ;--- (M.Weber) Reviewed version.
;
;-
; =========================================================================


; === Initial setup ==============================

  ;=== Set Booleans which control print statements.
  ;=== Keyword "verbose" overrules "quiet".
  q_vb = keyword_set(verbose)
  q_qt = keyword_set(quiet) and (q_vb eq 0)


  ;=== Initialize program constants.
  prognam = 'MAKE_XRT_SR'
  prognul = '           '


  ;=== Announce version of program.
  if q_vb then box_message, prognam+': Running ' + progver + '.'
  if q_vb then print, prognam+': Performing initial setup...'


  ;=== Set some keyword Booleans.
  qstop    = keyword_set(qstop)
  qabort   = 0B


  ;=== Some basic program values.
  nrsp = n_elements(eff_areas)
  eff_tagnames = ['type', 'eff_str_version', 'eff_str_descr', 'name', $
                  'wave', 'wave_units', 'eff_area', 'eff_area_units', $
                  'length', 'history', 'comments'                      ]
  chn_tagnames = ['type', 'geom', 'ccd']
  geo_tagnames = ['type', 'foc_len']
  ccd_tagnames = ['type', 'eV_per_el', 'pixel_size']
  h = 4.136e-15         ;; Planck's constant [eV s]
  c = 2.998e+18         ;; Speed of light [Angstroms s^-1]


  ;; In this next bit, we define some structure templates
  ;; that will be used further on.

  ;=== Define the {XRT_spec_resp} stucture.
  srs_str_version = 'XRT_SPEC_RESP_V0001'
  srs_str = create_struct(name=srs_str_version,                            $
                        'type', 'XRT_SPEC_RESP',                           $
             'srs_str_version', srs_str_version,                           $
               'srs_str_descr', 'Provides spectral response for an XRT '   $
                                + 'channel, for a given thickness of the ' $
                                + 'CCD contamination layer.',              $
                        'name', '',                                        $
                        'wave', fltarr(5000),                              $
                  'wave_units', 'Angstroms',                               $
                   'spec_resp', fltarr(5000),                              $
             'spec_resp_units', 'el cm^2 sr ph^-1 pix^-1',                 $
                      'length', 0L,                                        $
                   'gain_used', -1.0,                                      $
                     'history', strarr(3),                                 $
                    'comments', strarr(5)                                   )


  if q_vb then print, prognam+': Performing initial setup... OK'


; === Check inputs ===============================

  if q_vb then print, prognam+': Checking inputs...'


  ;=== Check that some input has been given.
  if (n_params() ne 2) then begin
    if (not q_qt) then box_message,                            $
        [prognam+': There should be exactly two input parameters:', $
         prognul+'  EFF_AREAS and GEOMETRY.', $
         prognul+'  See program header. Aborting...'   ]
    qabort = 1B
    return, 0
  endif


  ;=== Checks on EFF_AREAS input.
  ;; If EFF_AREAS is not a structure, then abort...
  if (datatype(eff_areas) ne 'STC') then begin
    if (not q_qt) then box_message,                   $
      [prognam+': Input EFF_AREAS must be a structure. ', $
       prognul+'  See program header. Aborting...'     ]
    qabort = 1B
    return, 0

  ;; Else if EFF_AREAS is a structure...
  endif else begin

    ;; If EFF_AREAS doesn't have the correct tags, then abort...
    if not required_tags(eff_areas[0], eff_tagnames) then begin
      if (not q_qt) then box_message,                             $
        [prognam+': Input EFF_AREAS does not have required tags:', $
         prognul+'  ' + eff_tagnames,                             $
         prognul+'  See program header. Aborting...'               ]
      qabort = 1B
      return, 0

    ;; Else if EFF_AREAS does have the TYPE tag...
    endif else begin

      ;; If EFF_AREAS.TYPE isn't correct...
      if (eff_areas[0].type ne 'XRT_eff_area') then begin
;;        if (not q_qt) then box_message,                   $
;;          [prognam+': Input EFF_AREAS must be a structure ', $
;;           prognul+'  with ID "XRT_eff_area_vNNNN".', $
;;           prognul+'  See program header. Aborting...'     ]
;;        qabort = 1B
;;        return, 0
      endif
    endelse

  endelse


  ;=== Checks on CHANNELS input.
  ;; If CHANNELS is not a structure, then abort...
  if (datatype(channels) ne 'STC') then begin
    if (not q_qt) then box_message,                   $
      [prognam+': Input CHANNELS must be a structure. ', $
       prognul+'  See program header. Aborting...'     ]
    qabort = 1B
    return, 0

  ;; Else if CHANNELS is a structure...
  endif else begin

    ;; If CHANNELS doesn't have the correct tags, then abort...
    if not required_tags(channels[0], chn_tagnames) then begin
      if (not q_qt) then box_message,                             $
        [prognam+': Input CHANNELS does not have required tags:', $
         prognul+'  ' + chn_tagnames,                             $
         prognul+'  See program header. Aborting...'               ]
      qabort = 1B
      return, 0

    ;; Else if CHANNELS does have the TYPE tag...
    endif else begin

      ;; If CHANNELS.TYPE isn't correct...
      if (channels[0].type ne 'XRT_chn_config') then begin
;;        if (not q_qt) then box_message,                   $
;;          [prognam+': Input CHANNELS must be a structure ', $
;;           prognul+'  with ID "XRT_chn_config_vNNNN".', $
;;           prognul+'  See program header. Aborting...'     ]
;;        qabort = 1B
;;        return, 0
      endif
    endelse

  endelse


  ;=== Checks on CHANNELS.GEOMETRY substructure.
  ;; If CHANNELS.GEOMETRY is not a structure, then abort...
  if (datatype(channels[0].geom) ne 'STC') then begin
    if (not q_qt) then box_message,                   $
      [prognam+': Input CHANNELS.GEOMETRY must be a structure. ', $
       prognul+'  See program header. Aborting...'     ]
    qabort = 1B
    return, 0

  ;; Else if CHANNELS.GEOMETRY is a structure...
  endif else begin

    ;; If CHANNELS.GEOMETRY doesn't have the correct tags, then abort...
    if not required_tags(channels[0].geom, geo_tagnames) then begin
      if (not q_qt) then box_message,                             $
        [prognam+': Input CHANNELS.GEOMETRY does not have required tags:', $
         prognul+'  ' + geo_tagnames,                             $
         prognul+'  See program header. Aborting...'               ]
      qabort = 1B
      return, 0

    ;; Else if CHANNELS.GEOMETRY does have the TYPE tag...
    endif else begin

      ;; If CHANNELS.GEOMETRY.TYPE isn't correct...
      if (channels[0].geom.type ne 'XRT_geometry') then begin
;;        if (not q_qt) then box_message,                   $
;;          [prognam+': CHANNELS.GEOMETRY must be a structure ', $
;;           prognul+'  with ID "XRT_geometry_vNNNN".', $
;;           prognul+'  See program header. Aborting...'     ]
;;        qabort = 1B
;;        return, 0
      endif
    endelse

  endelse


  ;=== Checks on CHANNELS.CCD substructure.
  ;; If CHANNELS.CCD is not a structure, then abort...
  if (datatype(channels[0].ccd) ne 'STC') then begin
    if (not q_qt) then box_message,                   $
      [prognam+': Input CHANNELS.CCD must be a structure. ', $
       prognul+'  See program header. Aborting...'     ]
    qabort = 1B
    return, 0

  ;; Else if CHANNELS.CCD is a structure...
  endif else begin

    ;; If CHANNELS.CCD doesn't have the correct tags, then abort...
    if not required_tags(channels[0].ccd, ccd_tagnames) then begin
      if (not q_qt) then box_message,                             $
        [prognam+': Input CHANNELS.CCD does not have required tags:', $
         prognul+'  ' + ccd_tagnames,                             $
         prognul+'  See program header. Aborting...'               ]
      qabort = 1B
      return, 0

    ;; Else if CHANNELS.CCD does have the TYPE tag...
    endif else begin

      ;; If CHANNELS.CCD.TYPE isn't correct...
      if (channels[0].ccd.type ne 'XRT_ccd') then begin
;;        if (not q_qt) then box_message,                   $
;;          [prognam+': CHANNELS.CCD must be a structure ', $
;;           prognul+'  with ID "XRT_ccd_vNNNN".', $
;;           prognul+'  See program header. Aborting...'     ]
;;        qabort = 1B
;;        return, 0
      endif
    endelse
    
  endelse


  if q_vb then print, prognam+': Checking inputs... OK'


; === Initialize the output array. ===========================

  if q_vb then print, prognam+': Initializing output array...'

  ;=== Prepare the {XRT_spec_resp} structure array.
  spec_resp      = replicate(srs_str, nrsp)
  spec_resp.name = eff_areas.name 
               

  if q_vb then print, prognam+': Initializing output array... OK'


; === Solve spectral responses. ==============================

  if q_vb then print, prognam+': Solving the spectral responses...'


  for irsp = 0,(nrsp-1) do begin

    if q_vb then print, prognam+': Working on channel ' +   $
                        strcompress(irsp+1,/rem) + ' of ' + $
                        strcompress(nrsp,/rem) + '.'

    wlen = eff_areas[irsp].length

    spec_resp[irsp].length = wlen
    spec_resp[irsp].wave[0:wlen-1] = eff_areas[irsp].wave[0:wlen-1]

    ;; See Note #1 for a discussion of the factors in this.
    ;; The units of channels.ccd.pixel_size are [microns], not [cm],
    ;; so a correction factor is necessary here.
    pix_size = channels[irsp].ccd.pixel_size / 1d4
    spec_resp[irsp].spec_resp[0:wlen-1] =                                 $
                             eff_areas[irsp].eff_area[0:wlen-1]           $
                             * (h * c / eff_areas[irsp].wave[0:wlen-1])   $
                             * (pix_size / channels[irsp].geom.foc_len)^2 $
                             / channels[irsp].ccd.eV_per_el

  endfor  ;; ("irsp"-loop; loop over array of effective areas)

  if q_vb then print, prognam+': Solving the spectral responses... OK'


; === Finish =====================================

  get_utc, utc, /stime
  hist_string = prognam+' '+progver+': ('+utc+' UTC) Generated {' $
                + spec_resp.type+'} structure with name "'        $
                + spec_resp.name+'".'
  spec_resp.history[0] = hist_string

  if q_vb then box_message, prognam+': ... Finished.'

  if qstop then stop

  return, spec_resp


END ;======================================================================
