pro eis_mapper, date, aia_wvl = aia_wvl, outdir = outdir, htmlfile = htmlfile, $
  obs_struct = obs_struct, next_link = next_link, $
  previous_link = previous_link, yr_link = yr_link, $
  no_processing = no_processing, image_time = image_time
  compile_opt idl2

  ;+
  ; NAME:
  ;    EIS_MAPPER
  ;
  ; PURPOSE:
  ;    To replicate Ken Dere's old EIS mapper webpages. For the
  ;    specified date, a web page is created showing a solar image for
  ;    that date, with boxes showing the location of the EIS rasters.
  ;
  ; CATEGORY:
  ;    Hinode/EIS; catalog.
  ;
  ; INPUTS:
  ;    None.
  ;
  ; OPTIONAL INPUTS:
  ;    Date:   The date in a format such as '12-feb-2014'.
  ;    Aia_Wvl:  The AIA wavelength (integer) to display. By default it
  ;              is 193.
  ;    Outdir:   The name of the directory to which the html files
  ;              should be sent. If not set, then the routine uses
  ;              $EIS_MAPPER.
  ;    Obs_Struct:  By default the routine uses the input DATE to create
  ;                 an observation structure for that date. Setting a
  ;                 structure with OBS_STRUCT over-rides this
  ;                 behavior. (The date is taken from the first entry in
  ;                 OBS_STRUCT.)
  ;    Next_Link:  Html link to the next day. By default the link goes
  ;                to the next day, but this input can over-ride this.
  ;    Previous_Link:  Html link to the previous day. By default the link goes
  ;                to the previous day, but this input can over-ride
  ;                this.
  ;    Yr_Link:  At the top of the output webpage, the year can be given
  ;              a link, which is specified by YR_LINK. It is expected
  ;              the link contains a list of all the dates for the year,
  ;              with links to the individual mapper files. See the
  ;              routines eis_mapper_year and eis_month_calendar for how
  ;              to use this input.
  ;    Image_Time:  By default the routine searches for the image
  ;                 closest to 12:00 UT on the specified DATE. This
  ;                 keyword allows the time to be modified. The string
  ;                 should include the date. For example,
  ;                 image_time='1-jan-2010 07:00'. Do not specify just
  ;                 the time.
  ;
  ; KEYWORD PARAMETERS:
  ;    NO_PROCESSING:  This is used to return the output html filename
  ;              (HTMLFILE) without actually creating the html file.
  ;
  ; OUTPUTS:
  ;    Creates a html file and a png image that are sent to the
  ;    directory $EIS_MAPPER/html/[YEAR] where [YEAR] is the year of the
  ;    input date.
  ;
  ; OPTIONAL OUTPUTS:
  ;    Htmlfile:  The name of the created html file (includes full
  ;               path).
  ;
  ; EXAMPLE:
  ;    IDL> eis_mapper, '12-feb-2014'
  ;
  ; CALLS:
  ;    EIS_MAPPER_AIA_RGB, EIS_MAPPER_AIA_MAP, EIS_MAPPER_EIT_MAP,
  ;    EIS_MAPPER_XRT_MAP, EIS_MAPPER_MDI_MAP,  EIS_MAPPER_GOES,
  ;    EIS_MAPPER_STUDY_TIMES, IRIS_HEK_SWPC_FLARES
  ;
  ; PROGRAMMING NOTES:
  ;    The routine searches for full disk images in the following order:
  ;    1. AIA 193, 2. EIT 195, 3. XRT Ti-Poly, 4. MDI magnetogram.
  ;
  ;    Sometimes the EIS xcen or ycen values can be anomalously
  ;    large. In this case the routine uses the planned xcen and ycen
  ;    values.
  ;
  ; MODIFICATION HISTORY:
  ;    Ver.1, 29-Jun-2018, Peter Young
  ;    Ver.2, 15-Aug-2018, Peter Young
  ;       Now uses $EIS_MAPPER variable to decide where output files
  ;       go; added the year to the top of the html file, with a link to
  ;       the year's master file; now exits if the AIA image is
  ;       not found.
  ;    Ver.3, 22-Aug-2018, Peter Young
  ;       Now uses xcen_plan and ycen_plan if xcen and ycen are
  ;       corrupted.
  ;    Ver.4, 26-Aug-2018, Peter Young
  ;       Now closes object after saving.
  ;    Ver.5, 29-Aug-2018, Peter Young
  ;       If no EIS obs, then print a message on the webpage instead of
  ;       leaving an empty table.
  ;    Ver.6, 26-Sep-2018, Peter Young
  ;       Now uses EIT 195 image if AIA is not available.
  ;    Ver.7, 4-Oct-2018, Peter Young
  ;       Added /no_processing; now uses Hinode/XRT as a third image
  ;       option.
  ;    Ver.8, 14-Sep-2019, Peter Young
  ;       Changed behavior of YR_LINK input, to work better with
  ;       eis_mapper_year.
  ;    Ver.9, 13-Jan-2020, Peter Young
  ;       Now uses planned pointing if the difference between actual and
  ;       planned pointings is more than 200"; disabled XRT check.
  ;    Ver.10, 27-Jan-2020, Peter Young
  ;       Re-enabled XRT check following OSDC fix.
  ;    Ver.11, 10-Feb-2020, Peter Young
  ;       Reversed the pointing change from Ver.9.
  ;    Ver.12, 12-Mar-2020, Peter Young
  ;       Added check on $EIS_MAPPER; performed some updates to the
  ;       header.
  ;    Ver.13, 24-Mar-2020, Peter Young
  ;       Modified calls to the image download routines; renamed
  ;       eis_mapper; updated header.
  ;    Ver.14, 27-Mar-2020, Peter Young
  ;       Fixed problem with color tables and DISPLAY if using a remote
  ;       machine.
  ;    Ver.15, 31-Mar-2020, Peter Young
  ;       Now uses eis_mapper_aia_rgb to get the AIA color table due to
  ;       problem with aia_lct; if outdir not specified then routine now
  ;       puts files in $EIS_MAPPER/html/[YEAR] (i.e., added html).
  ;    Ver.16, 02-Apr-2020, Peter Young
  ;       Added /quiet in calls to xy2lonlat and lonlat2xy to get rid of
  ;       annoying get_rb0p messages.
  ;    Ver.17, 19-Jan-2021, Peter Young
  ;       Caught rare error when calling eis_mapper_aia_rgb; fixed
  ;       problem with aia_wvl whereby it could get modified from the
  ;       input value.
  ;    Ver.18, 09-Feb-2022, Peter Young
  ;       Added image_time optional input.
  ;    Ver.19, 09-Jun-2022, Peter Young
  ;       Added call to eis_mapper_study_times; modified call to
  ;       eis_mapper_goes.
  ;    Ver.20, 13-Jul-2023, Peter Young
  ;       Added the AIA offset to xcen and ycen to give better pointing
  ;       information.
  ;    Ver.21, 02-Aug-2023, Peter Young
  ;       Added flare locations using data from iris_hek_swpc_flares.
  ;    Ver.22, 19-Aug-2023, Peter Young
  ;       Switched to using XRT flare catalog.
  ;    Ver.23, 24-Aug-2023, Peter Young
  ;       Fixed bug for xrt_flarecat call when obs_struct is specified
  ;       rather than date; restricted to C-flares and higher; fixed
  ;       pointing problem for the flare coordinates.
  ;    Ver.24, 25-Aug-2023, Peter Young
  ;       Now uses xcen_corr and ycen_corr (if available) for pointing.
  ;    Ver.25, 31-Aug-2023, Peter Young
  ;       Adjusted how the flare catalog is queried to ensure all flares
  ;       are captured.
  ;    Ver.26, 01-Sep-2023, Peter Young
  ;       Moved xrt_flarecat to after /no_processing.
  ;    Ver.27, 17-Apr-2024, Peter Young
  ;       Fixed problem whereby flares from the day before and day after
  ;       were being listed; changed text color to black for MDI images;
  ;       adjusted image scaling for EIT.
  ;    Ver.28, 18-Apr-2024, Peter Young
  ;       Fixed bug whereby flare structure was not deleted if no flares
  ;       were found in a day. If there are more than 10 C5 flares, then
  ;       I restrict list to C8 or higher.
  ;    Ver.29, 06-Dec-2024, Peter Young
  ;       Added SUVI to the image list due to problems with SDO.
  ;    Ver.30, 30-Jan-2025, Peter Young
  ;       Fixed wvl_str problem for SUVI.
  ;    Ver.31, 28-Apr-2026, Peter Young
  ;       I've added a check to make sure the xrt_flarecat routine is
  ;       available.
  ;-

  if n_params() eq 0 and n_elements(obs_struct) eq 0 then begin
    print, 'Use:  IDL> eis_mapper, date'
    return
  endif

  eis_mapper_dir = getenv('EIS_MAPPER')
  if eis_mapper_dir eq '' then begin
    print, '% EIS_MAPPER: Please define the environment variable $EIS_MAPPER before running this routine. Returning...'
    return
  endif

  if n_elements(aia_wvl) eq 0 then wvl = 193 else wvl = aia_wvl
  wvl_str = strpad(trim(wvl), 4, fill = '0')

  tt0 = systime(1)

  if n_tags(obs_struct) eq 0 then begin
    ;
    ; Convert date to a 24-hour time range (t0,t1) and then get the EIS
    ; metadata.
    ;
    t0 = date
    t0_tai = anytim2tai(t0)
    t1_tai = t0_tai + 86400.
    t1 = anytim2utc(/ccsds, t1_tai)
    ;
    str = eis_obs_structure(t0, t1, count = n)
  endif else begin
    str = obs_struct
    date = anytim2utc(str[0].date_obs, /date, /vms)
    t0 = date
    t0_tai = anytim2tai(t0)
    t1_tai = t0_tai + 86400.
    t1 = anytim2utc(/ccsds, t1_tai)
  endelse

  ;
  ; Get list of SWPC flares (I need to have the relevant IRIS routine, though).
  ;
  ; IF have_proc('iris_hek_swpc_flares') AND n_elements(t0) NE 0 THEN BEGIN
  ; flares=iris_hek_swpc_flares(start=t0,end=t1)
  ; ENDIF

  ;
  ; Process DATE to get doy information.
  ;
  ddoy = doy(date)
  doy_str = strpad(trim(ddoy), 3, fill = '0')
  doy_plus_str = strpad(trim(ddoy + 1), 3, fill = '0')
  doy_minus_str = strpad(trim(ddoy - 1), 3, fill = '0')

  ;
  ; Convert DATE to a standard format.
  ;
  dd_ex = anytim2ex(date)

  ;
  ; Handle OUTDIR optional input.
  ;
  if n_elements(outdir) eq 0 then outdir = concat_dir(eis_mapper_dir, 'html')
  out_dir = concat_dir(outdir, trim(dd_ex[6]))
  ;
  chck = file_info(out_dir)
  if chck.directory eq 0 and not keyword_set(no_processing) then file_mkdir, out_dir

  ;
  ; This is the name of the output html fle.
  ;
  htmlfile = concat_dir(out_dir, 'mapper_' + doy_str + '.html')

  ;
  ; /no_processing is intended just to return the name of the output
  ; html file without actually making it.
  ;
  if keyword_set(no_processing) then return

  ;
  ; Check XRT flare catalog.
  ; I've had to increase the range +- 1 day as flares that peak at the
  ; beginning or end of day don't get returned by xrt_flarecat.
  ;
  xrt_flarecat_dir = getenv('XRT_FLARECAT')
  if xrt_flarecat_dir ne '' then catalog = concat_dir(xrt_flarecat_dir, 'xrt_flarecat.sav')
  ;
  IF have_proc('xrt_flarecat') THEN BEGIN 
    flares = xrt_flarecat(anytim(t0) - 86400., anytim(t1) + 86400., catalog = catalog, /all)
  ENDIF ELSE BEGIN
    message,/info,/cont,'The routine xrt_flarecat was not found, so flare catalog data can not be used.'
  ENDELSE
  ;
  if n_tags(flares) ne 0 then begin
    peak_tai = anytim(flares.peak)
    k = where(peak_tai ge anytim(t0) and peak_tai le anytim(t1), nk)
    if nk gt 0 then begin
      flares = flares[k]
      class = strmid(flares.class, 0, 1)
      k = where(class ge 'C', nk)
      ;
      ; If there's a lot of flares, then limit to events > C5.
      ;
      if nk gt 10 then begin
        class = strmid(flares.class, 0, 2)
        k = where(class ge 'C5', nk)
        if nk gt 10 then k = where(class ge 'C8', nk)
      endif
      if nk eq 0 then junk = temporary(flares) else flares = flares[k]
    endif else begin
      junk = temporary(flares)
    endelse
  endif

  ;
  ; imgsrc takes values:
  ; 1 - AIA
  ; 2 - EIT
  ; 3 - XRT
  ; 4 - MDI/mag
  ;

  imgsrc = 1
  ;
  ; Get the AIA synoptic image (returned as a map). If I don't
  ; find an image on the specified day, then I check the previous day,
  ; then the day after. Also, only check from 2010 onwards.
  ;
  if n_elements(image_time) ne 0 then tcheck = image_time else tcheck = date + ' 12:00'
  extime = anytim(tcheck, /ex)
  yr = extime[6]
  if yr ge 2010 then begin
    map = eis_mapper_aia_map(tcheck, wvl, /quiet)
    if n_tags(map) eq 0 then begin
      t_tai = anytim2tai(tcheck)
      t_tai = t_tai - 12. * 60. * 60. - 10.
      t_ccsds = anytim2utc(t_tai, /ccsds)
      map = eis_mapper_aia_map(t_ccsds, wvl, /quiet)
      ;
      if n_tags(map) eq 0 then begin
        t_tai = anytim2tai(tcheck)
        t_tai = t_tai + 12. * 60. * 60. + 10.
        t_ccsds = anytim2utc(t_tai, /ccsds)
        map = eis_mapper_aia_map(t_ccsds, wvl, /quiet)
      endif
    endif
  endif

  tt1 = systime(1)

  ;
  ; If AIA not available, then try SUVI (for years after 2020).
  ;
  if n_tags(map) eq 0 then begin
    imgsrc = 5
    wvl_options = [94, 131, 171, 195, 284, 304]
    getmin = min(abs(wvl_options - wvl), imin)
    wvl_str = strpad(trim(wvl_options[imin]), 4, fill = '0')
    map = eis_mapper_suvi_map(tcheck, wvl_options[imin], /quiet)
    if n_tags(map) ne 0 then begin
      sub_map, map, smap, xra = [-1200, 1200], yra = [-1200, 1200]
      map = temporary(smap)
    endif
  endif

  ;
  ; If AIA not available, then try EIT.
  ; ***This needs some work on getting the image scaling and color
  ; table correct.***
  ;
  if n_tags(map) eq 0 then begin
    imgsrc = 2
    wvl = 195
    wvl_str = strpad(trim(wvl), 4, fill = '0')
    map = eis_mapper_eit_map(tcheck, wvl, /quiet)
  endif

  ;
  ; PRY, 13-Jan-2020: I've disabled XRT due to a problem with the OSDC.
  ;
  if n_tags(map) eq 0 then begin
    imgsrc = 3
    wvl_str = 'Ti-Poly'
    map = eis_mapper_xrt_map(tcheck, /quiet)
  endif

  if n_tags(map) eq 0 then begin
    imgsrc = 4
    wvl_str = 'mag'
    map = eis_mapper_mdi_map(tcheck, /quiet)
  endif

  ;
  ; Exit if an image wasn't found.
  ;
  if n_tags(map) eq 0 then return

  ;
  case imgsrc of
    1: begin
      rgb_table = eis_mapper_aia_rgb(wvl)
      if rgb_table[0] eq -1 then begin
        print, '% EIS_MAPPER: problem with color table wavelength input: ', wvl
        rgb_table = eis_mapper_aia_rgb(193)
      endif
      instr = 'AIA'
    end
    2: begin
      coltable_file = concat_dir(getenv('SSW_GEN_DATA'), 'color_table.eit')
      loadct, 43, file = coltable_file, rgb_table = rgb_table
      instr = 'EIT'
    end
    3: begin
      rgb_table = 3
      instr = 'XRT'
    end
    4: begin
      rgb_table = 0
      instr = 'MAG'
    end
    5: begin
      rgb_table = aia_rgb_table(wvl)
      instr = 'SUVI'
    end
    else:
  endcase

  ct = 1
  rrep_pfd_sav = -1

  success_flag = 0

  tt2 = systime(1)

  t0_tai = anytim2tai(t0)
  t1_tai = anytim2tai(t1)

  txt_color = 'white'

  if n_tags(map) ne 0 then begin
    aiaobs = map.time
    aiaobs_tai = anytim2tai(aiaobs)
    im = map.data
    case imgsrc of
      1: begin ; SDO/AIA
        case wvl of
          171: im = sqrt(im * (4.99803 / map.dur) > 10 < 6000)
          193: begin
            im = alog10((im * (2.99950 / map.dur) > 120 < 6000))
          end
          else: begin
            im = alog10(im)
          end
        endcase
        log = 0
      end
      2: begin ; SOHO/EIT
        im = im / map.dur * 10. ; I normalize exp. time to 10s
        a = sigrange(im, range = r)
        dmin = max([r[0], 1])
        dmax = r[1]
        log = 1
      end
      3: begin ; Hinode/XRT
        im = im / map.dur * 5. ; factor 5 improves contrast
        a = sigrange(im, range = r)
        dmin = r[0]
        dmax = r[1]
        log = 1
      end
      4: begin ; mag field
        dmin = -200
        dmax = 200
        log = 0
        txt_color = 'black'
      end
      5: begin
        ;
        ; I'm not sure what the SUVI scaling is, so I just use linear.
        ;
        dmin = min(map.data)
        dmax = max(map.data)
        log = 0
      end
    endcase
    map.data = im
    ;
    ; ; im=long(bytscl(im))
    ; ; map.data=im
    xpos = [0.09, 0.99]
    ypos = [0.24, 0.99]
    p = plot_map_obj(map, rgb_table = rgb_table, dim = [800, 940], /buffer, $
      pos = [xpos[0], 0.24, xpos[1], 0.99], $
      title = '', $
      xticklen = 0.015, yticklen = 0.015, $
      xtickdir = 1, ytickdir = 1, $
      log = log, dmin = dmin, dmax = dmax, $
      xth = 2, yth = 2)
    title = anytim2utc(/vms, /date, map.time)
    aia_t_str = anytim2utc(/ccsds, map.time, /trunc, /time) + ' UT'
    pt = text(0.15, 0.95, instr + ' ' + wvl_str + ', ' + trim(title) + ', ' + aia_t_str, color = txt_color)
    xr = p.xrange
    yr = p.yrange
    ;
    if n_tags(flares) ne 0 then begin
      nf = n_elements(flares)
      for i = 0, nf - 1 do begin
        ftime_tai = anytim2tai(flares[i].peak)
        if ftime_tai lt t0_tai or ftime_tai gt t1_tai then continue
        ;
        fclass = strmid(flares[i].class, 0, 1)
        fx = fix(flares[i].x)
        fy = fix(flares[i].y)
        frr = (fx ^ 2 + fy ^ 2)
        ;
        ; Rotate flare positions on the disk.
        ;
        if frr le 920. then begin
          lonlat = xy2lonlat([fx, fy], flares[i].peak, /quiet)
          n_days = (aiaobs_tai - ftime_tai) / 86400.
          dlon = diff_rot(n_days, lonlat[1])
          lonlat[0] = lonlat[0] + dlon
          new_xy = lonlat2xy(lonlat, flares[i].peak, /quiet)
          fx = new_xy[0]
          fy = new_xy[1]
        endif
        ;
        case fclass of
          'X': sym_size = 2.0
          'M': sym_size = 1.5
          else: sym_size = 1.0
        endcase
        ;
        f = plot([1, 1] * fx, [1, 1] * fy, symbol = 'x', $
          color = 'white', sym_thick = 2, sym_size = sym_size, /overplot)
        f = plot([1, 1] * fx, [1, 1] * fy, symbol = '+', $
          color = 'black', sym_thick = 2, sym_size = sym_size, /overplot)
      endfor
      ;
      f_xpos = xpos[0] + 0.03
      f_ypos = ypos[0] + 0.22
      f_dy = 0.015
      fl_txt = text(target = p, f_xpos, f_ypos, 'Flares', color = txt_color)
      for i = 0, nf - 1 do begin
        fl_time = anytim2utc(/ccsds, flares[i].peak, /time, /trunc)
        fl_time = strmid(fl_time, 0, 5)
        fl_lbl = text(target = p, f_xpos, f_ypos - (i + 1) * f_dy, fl_time + ' ' + flares[i].class, color = txt_color)
      endfor
    endif
    ;
    tt3 = systime(3)
    if n_tags(str) gt 0 then begin
      ;
      ; Filter out engineering studies
      ;
      chck = strpos(str.sci_obj, 'ENG')
      k = where(chck lt 0, nk)
      if nk ge 1 then begin
        str = str[k]
        n = nk
      endif else begin
        str = 0
        n = 0
      endelse
      ;
      if n gt 0 then begin
        print, '% EIS_MAPPER:  found ' + trim(n) + ' EIS files on this day.'
        for i = 0, n - 1 do begin
          eisobs = str[i].date_obs
          eisend = str[i].date_end
          eisobs_tai = anytim2tai(eisobs)
          slit_ind = str[i].slit_index
          ;
          ; PRY, 25-Aug-2023: by default use xcen_corr,ycen_corr. Otherwise,
          ; use xcen,ycen, but correct for AIA-EIS offset.
          ;
          xy = eis_aia_offsets(eisobs)
          if finite(str[i].xcen_corr) then xcen = str[i].xcen_corr else xcen = str[i].xcen + xy[0]
          if finite(str[i].ycen_corr) then ycen = str[i].ycen_corr else ycen = str[i].ycen + xy[1]
          ;
          fovx = str[i].fovx
          fovy = str[i].fovy
          rr = sqrt(xcen ^ 2 + ycen ^ 2)
          ;
          xcen_plan = str[i].xcen_plan
          ycen_plan = str[i].ycen_plan
          diff = sqrt((xcen_plan - xcen) ^ 2 + (ycen_plan - ycen) ^ 2)
          ;
          ; Sometimes xcen and ycen get corrupted and end up with very
          ; large values. In this case I replace them with the planned
          ; xcen and ycen values.
          ;
          ; PRY 13-Jan-2020: I've added a check on the difference
          ; between planned and actual due to strange discrepancies
          ; around 31-Mar-2007.
          ;
          ; PRY 10-Feb-2020: I've removed the above change. The
          ; planned coordinates can be in error if the spacecraft
          ; pointing is changed but the planner does not update the EIS
          ; pointing information.
          ;
          if rr ge 1500 then begin
            xcen = str[i].xcen_plan
            ycen = str[i].ycen_plan
            rr = sqrt(xcen ^ 2 + ycen ^ 2)
          endif

          if rr le 920. then begin
            lonlat = xy2lonlat([xcen, ycen], eisobs_tai, /quiet)
            n_days = (aiaobs_tai - eisobs_tai) / 86400.
            dlon = diff_rot(n_days, lonlat[1])
            lonlat[0] = lonlat[0] + dlon
            new_xy = lonlat2xy(lonlat, eisobs, /quiet)
            xcen = new_xy[0]
            ycen = new_xy[1]
          endif
          x0 = xcen - fovx / 2
          x1 = xcen + fovx / 2
          y0 = ycen - fovy / 2
          y1 = ycen + fovy / 2
          ;
          if slit_ind eq 1 or slit_ind eq 3 then color = 'yellow' else color = 'dodger blue'
          q = plot([x0, x1, x1, x0, x0], [y0, y0, y1, y1, y0], linesty = linesty, /overplot, color = color, $
            xrange = xr, yrange = yr, th = 2)
          ;
          time_str = anytim2utc(/ccsds, /time, /trunc, eisobs)
          timeend_str = anytim2utc(/ccsds, /time, /trunc, eisend)
          stud_str = str[i].stud_acr
          xcen_str = string(format = '(f10.1)', xcen)
          ycen_str = string(format = '(f10.1)', ycen)
          obstitle = trim(str[i].obstitle)
          obs_dec = trim(str[i].obs_dec)
          ;
          obs_str = '<tr><td>' + time_str + $
            '<td>' + timeend_str + $
            '<td>' + stud_str + $
            '<td>' + xcen_str + $
            '<td>' + ycen_str + $
            '<td>' + obstitle + $
            '</tr>'
          if n_elements(eis_string) eq 0 then eis_string = obs_str else eis_string = [eis_string, obs_str]
        endfor
      endif else begin
        xr = p.xrange
        yr = p.yrange
        pt = text(0.95 * xr[0] + 0.05 * xr[1], 0.05 * yr[0] + 0.95 * yr[1], /data, 'No EIS studies run today', $
          color = txt_color)
      endelse
    endif
    success_flag = 1
  endif

  tt4 = systime(4)

  ;
  ; Add GOES plot.
  ;
  block_times = eis_mapper_study_times(str)
  pg = eis_mapper_goes(date, position = [xpos[0], 0.05, xpos[1], 0.18], /current, $
    xthick = 2, ythick = 2, thick = 2, xminor = 5, yminor = 0, $
    xticklen = 0.05, yticklen = 0.01, $
    block_times = block_times)

  openw, lout, htmlfile, /get_lun

  date_str = anytim2utc(/vms, date, /date)

  ;
  ; Note that if YR_LINK is specified then I don't check whether
  ; it exists.
  ;
  ; ; count=1
  ; ; yr=dd_ex[6]
  ; ; IF n_elements(yr_link) EQ 0 THEN BEGIN
  ; ;   yr_file=concat_dir(getenv('EIS_MAPPER'),trim(yr)+'.html')
  ; ;   chck=file_search(yr_file,count=count)
  ; ;   yr_link='../'+trim(yr)+'.html'
  ; ; ENDIF
  ;
  yr = dd_ex[6]
  if n_elements(yr_link) eq 0 then begin
    printf, lout, '<h3><b>YEAR: ' + trim(yr) + '</b></h3>'
  endif else begin
    printf, lout, '<h3><b>YEAR: <a href="' + yr_link + '".html">' + trim(yr) + '</a></h3>'
  endelse

  if n_elements(previous_link) ne 0 then begin
    if previous_link eq '' then prev_str = 'PREVIOUS' else prev_str = '<a href=' + previous_link + '>PREVIOUS</a>'
  endif else begin
    prev_str = '<p><a href=mapper_' + doy_minus_str + '.html' + '>PREVIOUS</a>'
  endelse

  if n_elements(next_link) ne 0 then begin
    if next_link eq '' then next_str = 'NEXT' else next_str = '<a href=' + next_link + '>NEXT</a>'
  endif else begin
    next_str = '<a href=mapper_' + doy_plus_str + '.html' + '>NEXT</a>'
  endelse

  printf, lout, prev_str + ' <b>' + date_str + '</b> ' + next_str

  if success_flag eq 1 then begin
    imagefile = concat_dir(out_dir, 'image_' + doy_str + '.png')
    p.save, imagefile, resolution = 96
    p.close
    print, '% EIS_MAPPER:  wrote new image file: ' + imagefile
    printf, lout, '<head>'
    printf, lout, '<style type="text/css">'
    printf, lout, 'table {'
    printf, lout, ' border-spacing: 10px 0;'
    printf, lout, '}'
    printf, lout, '</style>'
    printf, lout, '<body>'
    printf, lout, '<p>'
    printf, lout, '<table><tr><td valign="top"><img src=image_' + doy_str + '.png>'
    ; print,'Created ',outfile
    printf, lout, '<td>'
    n = n_elements(eis_string)
    if n eq 0 then begin
      printf, lout, '<b>No EIS observations today.</b>'
    endif else begin
      printf, lout, '<table>'
      printf, lout, '<tr><td><b>Start<td><b>Stop<td><b>Study<td><b>X-cen<td><b>Y-cen<td><b>Obs. Title</tr>'
      for j = 0, n - 1 do begin
        printf, lout, eis_string[j]
      endfor
    endelse
    printf, lout, '</table></td></tr></table>'
  endif

  tt5 = systime(5)

  free_lun, lout

  print, 'Created ', htmlfile
end
