
;+
; NAME
;
;     EIS_WVL_SELECT
;
; PROJECT
;
;     Hinode/EIS
;
; EXPLANATION
;
;     Widget-based tool that allows user to create the WVL_SELECT
;     structure that is passed to EIS_AUTO_FIT. This structure defines
;     the wavelength region that will be used for the fit. E.g.,
;     suppose a wavelength window covers 195.0 to 196.0 angstroms but,
;     in addition to the line of interest, there is another weak line
;     in the window between 195.8 and 195.9 angstroms that the user is
;     not interested in, then EIS_WVL_SELECT can be used to de-select
;     this part of the spectrum from the fit. The situation is
;     complicated by the fact that the wavelength scale changes with
;     the spatial position due to the EIS slit tilt and orbit
;     variation, thus the wavelength pixels de-selected by the user
;     shift depending on the spatial pixel being considered.
;
;     Upon calling EIS_WVL_SELECT, a widget appears showing an image
;     derived from the raster on the left-hand side. Clicking on any
;     pixel in this image brings up the spectrum from this pixel on
;     the right-side of the widget. Across this spectrum you will see
;     a row of stars across the spectrum. By clicking-and-holding the
;     mouse button the user can draw a rubber-band box to select a set
;     of pixels. When the mouse button is released, these pixels will
;     be de-selected, and so will not be included when the fit with
;     EIS_AUTO_FIT is performed.
;
;     By clicking at different spatial pixels one can see that the
;     de-selected pixels will 'track' the movement of the wavelength
;     scale due to spatial wavelength shifts, ensuring that the
;     de-selected region always corresponds to the emission line being
;     ignored. 
;
; INPUTS
;
;     WINDATA    Window structure produced by EIS_GETWINDATA.
;
; OPTIONAL INPUTS
;
;     OFFSET     The wavelength offsets due to spectrum drift and slit
;                tilt are, by default, taken from
;                WINDATA.WAVE_CORR. Specifying OFFSET= allows the user
;                to specify his/her own wavelength offset array. The
;                array must have dimensions (WINDATA.NX,WINDATA.NY).
;
;     IEXP       This is only active if the data-set has nexp_prp>1
;                (i.e., more than one exposure per raster
;                position). It is an index that selects which exposure
;                to use. By default the routine selects the exposure
;                with the longest exposure time.
;
;     SPEC_XSIZ  Specifies the size of the spectrum plot. The default
;                is 600. This is useful if you are displaying a large
;                section of the spectrum.
;
; OUTPUTS
;
;     WVL_SELECT  A structure containing information about the
;                 de-selected region. The tags are given in the
;                 'Programming notes' section below. For writing and
;                 reading this structure to a text file, see the
;                 routines eis_write_wvl_select.pro and
;                 eis_read_wvl_select.pro.
;
; CALLS
;
;     EIS_READ_WVL_SELECT, EIS_WRITE_WVL_SELECT
;
; INTERNAL ROUTINES
;
;     PIX_ALL_TO_WVL_SELECT, WVL_SELECT_DRAWBOX, WVL_SELECT_PIX_ALL,
;     WVL_SELECT_PLOT_PROFILE, WVL_SELECT_PLOT_IMAGE,
;     WVL_SELECT_BASE_EVENT, EIS_WVL_SELECT_WIDGET, WVL_SELECT_FONT
;     WVL_SELECT_IMG_DRAWBOX
;
; PROGRAMMING NOTES
;
;     The tags of WVL_SELECT are:
;
;     .rast_id   The raster ID of the raster from which WINDATA is
;                obtained. 
;
;     .n         The number of selected regions. From the example
;                described above, this will be 2 (for 195.0 to 195.8
;                and 195.9 to 196.0). 
;
;     .min       Fltarr(10). Contains the minimum wavelength for each
;                of the selected regions. From the example above,
;                these will be 195.0 and 195.9 with the others set to
;                zero. 
;
;     .max       Fltarr(10). Contains the maximum wavelength for each
;                of the selected regions. From the example above,
;                these will be 195.8 and 196.0 with the others set to
;                zero. 
;
;     .limit     Fltarr(2). Contains the minimum and maximum
;                wavelengths from the complete set of wavelengths,
;                i.e., min(windata.wvl-offset) and
;                max(windata.wvl+offset). 
;
;     -----
;     The basic operation of the routine is as follows:
;
;     1. For a given pixel [xpix,ypix] the pixels selected by the user
;        are stored in a 1D array called 'pix_all'. This is of same
;        size as windata.wvl but with values of 0 or 1 depending if
;        the pixel is de-selected or selected, respectively. These
;        data are stored in state.wid_data.
;     2. When a new pix_all has been created then the wvl_select
;        structure is created by the routine pix_all_to_wvl_select.
;     3. When the user selects a new spatial pixel, then a new pix_all
;        array is computed from wvl_select using the routine
;        wvl_select_pix_all. This is then used to indicate the
;        selected/de-selected wavelength pixels for the new spatial
;        pixel. 
;
;     An additional point to note is that if the user has de-selected
;     wavelength pixels for one spatial pixel, and then clicks on
;     another spatial pixel to see how the de-selected region looks
;     here, then wvl_select will remain unchanged. It is only if the
;     user starts de-selecting pixels for this new pixel will
;     wvl_select be modified.
;
; RESTRICTIONS
;
;     There is currently no way to 're-select' a pixel after it has
;     been de-selected. The user will need to restart the widget if
;     pixels need to be re-selected.
;
;     Consider the following example: a user de-selects a pixel at the
;     edge of the window. The user then clicks on a new spatial pixel
;     but, because of the wavelength offset, this de-selected pixel
;     disappears in the display (this can happen if pixel 0 is
;     de-selected using a spatial pixel at the top of the raster, and
;     then the user clicks on a spatial pixel at the bottom of the
;     raster). Although the pixel has disappeared in the
;     display, it's information is still stored in
;     wvl_select. However, if the user then de-selects a pixel in the
;     new spectrum display, the information about the original pixel
;     will be lost as wvl_select is re-computed solely using the
;     pixel information in the current spectrum display. The user can
;     restore the original de-selected pixel by clicking again on the
;     original spatial pixel and de-selecting the pixel.
;
; HISTORY
;
;     Version 1, 2-Feb-2010, Peter Young
;     Version 2, 30-Mar-2010, Peter Young
;       updated header
;     Version 3, 19-Apr-2010, Peter Young
;       added a slider for controlling the Y-range of the spectrum
;       plot; fixed when bug clicking on out-of-range pixel; added
;       title to spectrum plot.
;     Version 4, 12-Apr-2011, Peter Young
;       The routine now takes the wavelength offset array from
;       WINDATA.WAVE_CORR. The user can over-ride this by specifying
;       OFFSET=. A subroutine WVL_SELECT_FONT has been added to
;       specify the widget fonts. Added text help at bottom of widget.
;     Version 5, 24-Jun-2011, Peter Young
;       Now uses sigrange to better scale the image.
;     Version 6, 4-Apr-2013, Peter Young
;       Improved image appearance when there are missing data. Also
;       spectrum plot no longer shows -100 values.
;     Version 7, 2-Mar-2015, Peter Young
;       Fixed bug for nexp_prp>1 data; also now applied correct
;       X-scaling to image.
;     Version 8, 9-Jun-2015, Peter Young
;       Fixed Y-scaling problem for IRIS data.
;     Version 9, 23-Jun-2015, Peter Young
;       Cursor was not being plotted in right place, so fixed this.
;     Version 10, 2-Mar-2018, Peter Young
;       Enabled rubber-band box for selecting regions in the image.
;     Version 11, 6-Dec-2019, Peter Young
;       Cosmetic change when displaying information about nexp_prp>1
;       data-sets.
;     Version 12, 9-Dec-2019, Peter Young
;       Fixed bug when extracting the intensity when nexp_prp=1 (iexp
;       was being set to -1).
;     Version 13, 23-Oct-2025, Peter Young
;       Added spec_xsiz= optional input.
;-

;------------------
PRO wvl_select_font, font, big=big, fixed=fixed
;+
;  Defines the fonts to be used in the widgets. Allows for Windows and Unix 
;  operating systems.
;-
CASE !version.os_family OF

  'unix': BEGIN
    IF keyword_set(fixed) THEN fstr='-*-courier-' ELSE $
         fstr='-adobe-helvetica-'
    IF keyword_set(big) THEN str='18' ELSE str='12'
    font=fstr+'bold-r-*-*-'+str+'-*'
  END

  ELSE: BEGIN
    IF keyword_set(fixed) THEN fstr='Courier' ELSE $
         fstr='Arial'
    IF keyword_set(big) THEN str='20' ELSE str='16'
    font=fstr+'*bold*'+str
  END

ENDCASE

END


;------------------------
PRO pix_all_to_wvl_select, state
;
;  Converts the pix_all array to the wvl_select structure. This is the
;  most important part of the eis_wvl_select code.
;
pix_all=state.wid_data.pix_all
wvl_select=state.wvl_select

xpix=state.wid_data.xpix
ypix=state.wid_data.ypix
xcen=round(mean(xpix))
ycen=round(mean(ypix))

offset=state.offset

;
; Reset wvl_select wavelength ranges (note that min and max are fltarr(10)).
;
wvl_select.min=0.
wvl_select.max=0.

n=n_elements(pix_all)

;
; Create wavelength scale for selected pixel.
;
IF n_elements(offset) EQ 1 THEN BEGIN
  wvl=state.windata.wvl
ENDIF ELSE BEGIN 
  wvl=state.windata.wvl-offset[xcen,ycen]
ENDELSE 

i0=where(pix_all EQ 0,ni0)

;
; If pix_all is all 1's (i.e., all pixels are selected), then
; this case is easy!
;
IF ni0 EQ 0 THEN BEGIN
  wvl_select.n=1
  wvl_select.min[0]=wvl_select.limit[0]
  wvl_select.max[0]=wvl_select.limit[1]
  state.wvl_select=wvl_select
  return
ENDIF 


swtch=0
k=0

;
; 'swtch' takes values of 0 or 1 and indicates if pixel i is going to
; be the start of a new wavelength region (0) or not (1). Suppose the
; wavelength pixels are 195.0, 195.1, ..., 196.0 and the user has
; de-selected pixels 195.8 and 195.9. As the code below goes through
; each pixel, then pixel 0 (195.0) will have swtch=0 to indicate it is
; the start of a selected region. swtch is then set to 1. The
; following pixels up to and including 195.7 have pix_all=1 and
; swtch=1 and, with each pixel, the first wavelength region in
; wvl_select (wvl_select.min[0] and wvl_select.max[0]) will be
; increased from [195.0,195.1] ... to [195.0,195.7]. For pixel 8
; (195.8), pix_all=0 and swtch=1, indicating the start of a
; de-selected region. swtch is set to 0 and the first selected
; wavelength region is fixed to be [195.0,195.7], and the wavelength
; region counter (k) is incremented.
;
;
FOR i=0,n-1 DO BEGIN
  CASE 1 OF 
    pix_all[i] EQ 1 AND swtch EQ 0: BEGIN 
      IF i EQ 0 THEN wvl_start=wvl_select.limit[0] ELSE wvl_start=wvl[i]-0.0223/2.
      swtch=1
      IF i EQ n-1 THEN BEGIN
        wvl_end=wvl_select.limit[1]
        wvl_select.min[k]=wvl_start
        wvl_select.max[k]=wvl_end
        k=k+1
        wvl_select.n=k
        swtch=0
      ENDIF 
    END 
    pix_all[i] EQ 0 AND swtch EQ 1: BEGIN
      wvl_end=wvl[i-1]+0.0223/2.
      wvl_select.min[k]=wvl_start
      wvl_select.max[k]=wvl_end
      k=k+1
      wvl_select.n=k
      swtch=0
    END
    pix_all[i] EQ 1 AND swtch EQ 1: BEGIN
      IF i EQ n-1 THEN BEGIN
        wvl_end=wvl_select.limit[1]
        wvl_select.min[k]=wvl_start
        wvl_select.max[k]=wvl_end
        k=k+1
        wvl_select.n=k
        swtch=0
      ENDIF
    END
    ELSE:
  ENDCASE
ENDFOR 

;
; Write out the new wvl_select to a text file
;
eis_write_wvl_select,wvl_select

state.wvl_select=wvl_select
widget_control,state.wvl_select_base,set_uvalue=state

END


;----------------
PRO wvl_select_img_drawbox, event, state, wid
;
; This drawbox is for the image (left panel) and allows multiple
; spatial pixels to be averaged to generate the displayed spectrum. 
;
xsc=state.windata.scale[0]
ysc=state.windata.scale[1]

CASE 1 OF
  event.press EQ 1 AND state.ibox.flag EQ 0: BEGIN
    state.ibox.flag=1
    state.ibox.x0=event.x
    state.ibox.y0=event.y
    state.ibox.wid=wid
    wset,wid
    wvl_select_plot_image, state
    Window, /Pixmap, /Free, XSize=state.ibox.xsiz, YSize=state.ibox.ysiz
    state.ibox.pixid = !D.Window
    Device, Copy=[0, 0, state.ibox.xsiz, state.ibox.ysiz, 0, 0, wid]
    wset,wid
    widget_control,state.wvl_select_base,set_uvalue=state
  END

  event.release EQ 1 AND state.ibox.flag EQ 1: BEGIN
    WDelete, state.ibox.pixid
    state.ibox.flag=0
    state.ibox.x1=event.x
    state.ibox.y1=event.y
    widget_control,state.wvl_select_base,set_uvalue=state
    result=convert_coord([state.ibox.x0,state.ibox.x1], $
                         [state.ibox.y0,state.ibox.y1],/device,/to_data)

    xpix=round([result[0,0]/xsc>0,result[0,1]/xsc>0])
    ypix=round([result[1,0]/ysc>0,result[1,1]/ysc>0])

    nx=state.windata.nx
    ny=state.windata.ny

    xpix=xpix < (nx-1)
    ypix=ypix < (ny-1)

    xpix=xpix[sort(xpix)]
    ypix=ypix[sort(ypix)]

    state.wid_data.xpix=xpix
    state.wid_data.ypix=ypix

   ;
   ; If a region is selected, then the box is left behind on the image
   ; to show what has been selected. If only a pixel was selected,
   ; then I need to plot the location with a cross.
   ;
    IF xpix[0] EQ xpix[1] AND ypix[0] EQ ypix[1] THEN BEGIN
      plots,xpix[0]*xsc,ypix[0]*ysc,psym=1,symsiz=1.5
    ENDIF 

    widget_control,state.wvl_select_base,set_uvalue=state

    wvl_select_plot_profile, state

  END

  state.ibox.flag EQ 1: BEGIN
    Device, Copy=[0, 0, state.ibox.xsiz, state.ibox.ysiz, 0, 0, state.ibox.pixid]
    PlotS, [state.ibox.x0, state.ibox.x0, event.x, event.x, state.ibox.x0], $
         [state.ibox.y0, event.y, event.y, state.ibox.y0, state.ibox.y0], $
         /Device
  END
  
  ELSE: 
  
ENDCASE

END


;----------------
PRO wvl_select_drawbox, event, state, wid
;
; This has been hacked from eis_fit_viewer - it draws a rubber-band
; box for de-selecting wavelength pixels.
;
xpix=state.wid_data.xpix
ypix=state.wid_data.ypix
xcen=round(mean(xpix))
ycen=round(mean(ypix))

wd_wvl=state.windata.wvl
IF n_elements(state.offset) EQ 1 THEN offset=0. ELSE offset=state.offset[xcen,ycen]

CASE 1 OF
  event.press EQ 1 AND state.box.flag EQ 0: BEGIN
    state.box.flag=1
    state.box.x0=event.x
    state.box.y0=event.y
    state.box.wid=wid
    wset,wid
    wvl_select_plot_profile, state
    Window, /Pixmap, /Free, XSize=state.box.xsiz, YSize=state.box.ysiz
    state.box.pixid = !D.Window
    Device, Copy=[0, 0, state.box.xsiz, state.box.ysiz, 0, 0, wid]
    wset,wid
    widget_control,state.wvl_select_base,set_uvalue=state
  END

  event.release EQ 1 AND state.box.flag EQ 1: BEGIN
    WDelete, state.box.pixid
    state.box.flag=0
    state.box.x1=event.x
    state.box.y1=event.y
    widget_control,state.wvl_select_base,set_uvalue=state
    result=convert_coord([state.box.x0,state.box.x1], $
                         [state.box.y0,state.box.y1],/device,/to_data)
    xvals=[result[0,0],result[0,1]]
    pix_all=state.wid_data.pix_all
    wvl=wd_wvl-offset
    i=where(wvl GE xvals[0] AND wvl LE xvals[1],ni)
    IF ni NE 0 THEN pix_all[i]=0b
    state.wid_data.pix_all=pix_all
    widget_control,state.wvl_select_base,set_uvalue=state
    pix_all_to_wvl_select,state
    widget_control,state.wvl_select_base,set_uvalue=state
    wvl_select_plot_profile, state
  END

  state.box.flag EQ 1: BEGIN
    Device, Copy=[0, 0, state.box.xsiz, state.box.ysiz, 0, 0, state.box.pixid]
    PlotS, [state.box.x0, state.box.x0, event.x, event.x, state.box.x0], $
         [state.box.y0, event.y, event.y, state.box.y0, state.box.y0], $
         /Device
  END
  
  ELSE:
  
ENDCASE

END


;---------------------
PRO wvl_select_pix_all, state, pix_all
;
; Converts the wvl_select structure to a pix_all array.
;
xpix=state.wid_data.xpix
ypix=state.wid_data.ypix
xcen=round(mean(xpix))
ycen=round(mean(ypix))

offset=state.offset
wvl_select=state.wvl_select

nwvl=state.windata.nl
pix_all=bytarr(nwvl)

IF n_elements(offset) EQ 1 THEN BEGIN
  wvl=state.windata.wvl
ENDIF ELSE BEGIN
  wvl=state.windata.wvl-offset[xcen,ycen]
ENDELSE 

FOR i=0,wvl_select.n-1 DO BEGIN
  chck=where(wvl GE wvl_select.min[i] AND wvl LE wvl_select.max[i],nchck)
  IF nchck GT 0 THEN pix_all[chck]=1b
ENDFOR


state.wid_data.pix_all=pix_all
widget_control,state.wvl_select_base,set_uvalue=state

END


;---------------------
PRO wvl_select_plot_profile, state
;
; Plots the line profile for the spatial pixel selected by the user,
; together with the selected pixels (stored in pix_all).
;
windata=state.windata
offset=state.offset
xpix=state.wid_data.xpix
ypix=state.wid_data.ypix
yscale=state.wid_data.yscale
iexp=state.iexp

wset,state.wid_data.profile_id

nx=xpix[1]-xpix[0]+1
ny=ypix[1]-ypix[0]+1
xcen=round(mean(xpix))
ycen=round(mean(ypix))


IF n_elements(offset) EQ 1 THEN BEGIN
  wvl=windata.wvl
ENDIF ELSE BEGIN 
  wvl=windata.wvl-offset(xcen,ycen)
ENDELSE


int=windata.int
IF state.windata.hdr.nexp_prp GT 1 THEN BEGIN 
  iexp=state.iexp
  int=int[*,xpix[0]:xpix[1],ypix[0]:ypix[1],iexp]
ENDIF ELSE BEGIN
  int=int[*,xpix[0]:xpix[1],ypix[0]:ypix[1]]
ENDELSE 


CASE 1 OF
  nx EQ 1 AND ny EQ 1: BEGIN
    spec=int[*,0,0]
    tit='X: '+trim(xpix[0])+', Y: '+trim(ypix[0])
  END
  nx EQ 1 AND ny NE 1: BEGIN
    spec=average(int,2,missing=windata.missing)
    tit='X: '+trim(xpix[0])+', Y: ['+trim(ypix[0])+','+trim(ypix[1])+']'
  END 
  nx NE 1 AND ny EQ 1: BEGIN
    spec=average(int,2,missing=windata.missing)
    tit='X: ['+trim(xpix[0])+','+trim(xpix[1])+'], Y: '+trim(ypix[0])
  END 
  nx NE 1 AND ny NE 1: BEGIN
    spec=average(int,[2,3],missing=windata.missing)
    tit='X: ['+trim(xpix[0])+','+trim(xpix[1])+'], Y: ['+trim(ypix[0])+','+trim(ypix[1])+']'
  END
ENDCASE 


yr=[max([min(spec),0]),max(spec)*1.15*yscale]
plot,psym=10,wvl,spec,xsty=3,ysty=3,yrange=yr, tit=tit


wvl_select_pix_all, state, pix_all
i=where(pix_all EQ 1,ni)
IF ni GT 0 THEN BEGIN
  oplot,psym=2,wvl[i],fltarr(ni)+0.5*(yr[1]+yr[0])
  oplot,psym=2,wvl[i],spec[i]
ENDIF

END


;---------------------
PRO wvl_select_plot_image, state
;
; Plots the image to be displayed on the left-side of the widget. The
; image is simply derived by averaging in the wavelength direction.
;
wset,state.wid_data.image_id

windata=state.windata
xpix=state.wid_data.xpix
ypix=state.wid_data.ypix
nexp_prp=state.windata.hdr.nexp_prp
iexp=state.iexp
scale=state.windata.scale
nx=state.windata.nx

;
; Need to check for nexp_prp
;
IF nexp_prp GT 1 THEN BEGIN
  int=windata.int[*,*,*,iexp]
  err=windata.err[*,*,*,iexp]
ENDIF ELSE BEGIN 
  int=windata.int
  err=windata.err
ENDELSE 
i=where(err EQ  windata.missing,ni)
IF ni NE 0 THEN int[i]=windata.missing
image=average(int,1,missing=windata.missing)
imchck=sigrange(image,missing=windata.missing,range=range)
plot_image,image,min=range[0],max=range[1],scale=scale,xsty=5
xx=findgen(nx)
xra=[min(xx),max(xx)]
axis,xaxis=0,xra=xra,xsty=1
axis,xaxis=1,xra=xra,xsty=1,charsiz=0.0001


END


;------------------
PRO wvl_select_base_event, event
;
; Handles widget events.
;
WIDGET_CONTROL,Event.top, get_uvalue=state

CASE event.id OF

 ;
 ; Respond to mouse events on the image.
 ;
  state.image_plot: BEGIN
    wvl_select_img_drawbox, event, state, state.wid_data.image_id
    widget_control,state.wvl_select_base,set_uval=state
  END 

 ;
 ; Respond to mouse events on the spectrum plot.
 ;
  state.profile_plot: BEGIN
    wvl_select_drawbox, event, state, state.wid_data.profile_id
  END

 ;
 ; This handles the slider on the side of the spectrum plot.
 ;
  state.yslider: BEGIN
    widget_control,state.yslider,get_val=iy
    state.wid_data.yscale=iy*0.02
    widget_control,state.wvl_select_base,set_uvalue=state
    wvl_select_plot_profile, state
  END 

  state.exit: widget_control, event.top, /destroy

ENDCASE 

END


;-----------------
PRO eis_wvl_select_widget, windata, offset, wvl_select, group=group, iexp=iexp

wid_data={image_id: 0, $
          profile_id: 0, $
          xpix: [0,0], $
          ypix: [0,0], $
          pix_all: bytarr(windata.nl), $
          yscale: 1.0}

xsiz=wvl_select.spec_xsiz
ysiz=500

wvl_select_font,font
wvl_select_font,bigfont,/big
wvl_select_font,fixfont,/fixed

wvl_select_base=widget_base(/col,map=1,title='EIS_WVL_SELECT')

exit=widget_button(wvl_select_base,value='EXIT',font=bigfont)

plot_base=widget_base(wvl_select_base,/row,map=1)

image_base=widget_base(plot_base,/col,map=1)
spec_base=widget_base(plot_base,/col,map=1)

image_plot=widget_draw(image_base,xsiz=500,ysiz=500,/sens, $
                    /button_events,/motion_events)
imlbl=widget_label(image_base,val='Click-and-drag on image to select spatial pixels',font=font)
profile_plot=widget_draw(spec_base,xsiz=xsiz,ysiz=ysiz,/sens, $
                        /button_events,/motion_events)
speclbl=widget_label(spec_base,val='Click-and-drag on spectrum to de-select pixels from fit',font=font)

value=round(wid_data.yscale/0.02)
yslider=widget_slider(plot_base,/vertical,value=50,min=1,max=60,/suppress_value)

;
; There are two rubber-band boxes used for this routine. "box" is for
; the spectrum plot (right panel) and "ibox" is for the image box
; (left panel).
;
ibox={flag: 0, wid: 0, x0: 0, y0: 0, x1:0, y1:0, $
      xsiz:xsiz, ysiz: ysiz, pixid:0}
box={flag: 0, wid: 0, x0: 0, y0: 0, x1:0, y1:0, $
     xsiz:xsiz, ysiz: ysiz, pixid:0}


state={exit: exit, $
       image_plot: image_plot, $
       profile_plot: profile_plot, $
       wid_data: wid_data, $
       offset: offset, $
       windata: windata, $
       iexp: iexp, $
       wvl_select: wvl_select, $
       wvl_select_base: wvl_select_base, $
       box: box, $
       ibox: ibox, $
       yslider: yslider}

WIDGET_CONTROL, wvl_select_base, /REALIZE, set_uvalue=state

widget_control,image_plot,get_value=image_id
widget_control,profile_plot,get_value=profile_id
wid_data.image_id=image_id
wid_data.profile_id=profile_id

state.wid_data=wid_data
widget_control,wvl_select_base,set_uvalue=state

wvl_select_plot_image, state



XMANAGER, 'wvl_select_base', wvl_select_base, group=group

END


;-----------------
PRO eis_wvl_select, windata, wvl_select, offset=offset, iexp=iexp, spec_xsiz=spec_xsiz


IF n_params() LT 2 THEN BEGIN
  print,'Use: IDL> eis_wvl_select, windata, wvl_select, offset=offset, yscale=yscale'
  return
ENDIF

IF NOT tag_exist(windata,'wave_corr') AND n_elements(offset) EQ 0 THEN BEGIN
  print,'% EIS_WVL_SELECT: Your WINDATA structure is out-of-date and does not contain the WAVE_CORR tag.'
  print,'Please re-generate the structure with EIS_GETWINDATA before calling EIS_WVL_SELECT.'
  print,'Returning...'
  return
ENDIF 

IF windata.nl GE 100 AND n_elements(spec_xsiz) EQ 0 THEN BEGIN
  print,''
  message,/info,/cont,'The wavelength window is large. You can set spec_xsiz= to make the spectrum plot larger. For example, spec_xsiz=1000.'
  print,''
ENDIF 

IF n_elements(spec_xsiz) EQ 0 THEN spec_xsiz=600

;
; This checks for nexp_prp>1
;
nexp_prp=windata.hdr.nexp_prp
IF nexp_prp GT 1 THEN BEGIN
  exp_times=max(windata.exposure_time,dim=1)
  nexp=n_elements(exp_times)
  IF n_elements(iexp) EQ 0 THEN BEGIN
    getmax=max(exp_times,iexp)
    print,'% EIS_WVL_SELECT: this data-set has nexp_prp>1. The exposure times are:'
    FOR i=0,nexp-1 DO BEGIN
      IF i EQ iexp THEN extra_str='  <--' ELSE extra_str=''
      print,format='(i10,f8.1," s",a5)',i,exp_times[i],extra_str
    ENDFOR 
    print,' The largest exposure time (indicated) will be used. Use iexp= to select a different exposure index.'
  ENDIF 
ENDIF ELSE BEGIN
  iexp=-1
ENDELSE 

IF n_elements(offset) EQ 0 THEN BEGIN
  offset=windata.wave_corr
ENDIF ELSE BEGIN
  siz=size(offset)
  IF siz[1] NE windata.nx OR siz[2] NE windata.ny THEN BEGIN
    print,'% EIS_WVL_SELECT: the input OFFSET= has been specified, but the dimensions do not match those of WINDATA.'
    print,'Please check your data.  Returning...'
    return
  ENDIF 
ENDELSE 


wvl_select={rast_id: windata.hdr.rast_id, n: 1, min: fltarr(10), max: fltarr(10), $
            limit: fltarr(2), spec_xsiz: spec_xsiz }

k=where(offset NE windata.missing)

wvlmin=min(windata.wvl-max(offset[k]))
wvlmax=max(windata.wvl-min(offset[k]))

;
; The default for wvl_select is to include the full wavelength range,
; i.e., there is one selected wavelength region (n=1) whose min and
; max is the min and max of the complete range of wavelengths.
;
wvl_select.limit=[wvlmin,wvlmax]
wvl_select.min[0]=wvlmin
wvl_select.max[0]=wvlmax

eis_write_wvl_select,wvl_select,outfile=outfile

eis_wvl_select_widget, windata, offset, wvl_select, iexp=iexp

;
; After the widget has been closed, read the wvl_select text file
; which is then returned to the user as a structure.
;
eis_read_wvl_select,outfile,wvl_select
file_delete,outfile,/allow_nonexistent

END
