
;+
; NAME
;
;     EIS_RASTER_BROWSER
;
; PROJECT
;
;     HINODE/EIS
;
; EXPLANATION
;
;     This routine is used to browse 3D EIS data-cubes. It is based on
;     software available in the SOHO/CDS software.
;
;     Within the image display window, the mouse buttons are used as:
;        LEFT   Zoom in to image (factor 2).
;        MIDDLE Choose a new spatial pixel for spectrum display.
;        RIGHT  Zoom out from image (factor 2).
;
;     Similarly, for the spectrum display windows, the mouse buttons are
;     used as:
;        LEFT   Zoom in to spectrum (factor 2).
;        MIDDLE Choose a new spectrum pixel for image display.
;        RIGHT  Zoom out from spectrum (factor 2).
;
; INPUTS
;
;     FILE   Can be either the name of an EIS data file, or an EIS data
;            object.
;
; OPTIONAL INPUTS
;
;     NO_OFFSET  The routine automatically corrects for the spatial Y-offset
;                between different wavelengths. Setting this keyword switches off the
;                correction. Note that the correction truncates the images
;                in the Y direction.
;
; KEYWORDS
;
;     NO_GOES   If set, then the routine will not attempt to retrieve
;               the GOES data.
;
; EXAMPLES
;
;     This shows how a set of rasters can be loaded and viewed with
;     eis_raster_browser. 
;
;     IDL> files=eis_find_file('16-feb-2011 07:44',/sequence,/level1)
;     IDL> eis_raster_browser,file
;
; CALLS
;
;     EIS_GET_HEAD_STRUC, EIS_DEBIAS, EIS_DESPIKE
;     EIS_ORBIT_SPLINE_QUICK, EIS_EXPOSURE_TIMES, EIS_FIND_WINDOW
;     EIS_WINWVL_HDR, EIS_CCD_OFFSET
;
; HISTORY
;
;     Version 1, 11-Jan-2007, Peter Young
;     Version 2, 13-Jan-2007, Peter Young
;       added de-spike option, and hardcopy button
;     Version 3, 23-Jan-2007, Peter Young
;       spectral zooming now implemented and selected spatial pixel
;       remains consistent when changing windows; the routine also
;       crudely corrects for the Y offset between the two EIS CCDs
;     Version 4, 1-Feb-2007, Peter Young
;       reverse images in X-direction; added checks to ensure routine is not
;       used on sit-and-stare or slot data; allowed the input FILE to be
;       a data object or a filename
;     Version 5, 15-Feb-2007, Peter Young
;       implemented manual image scaling; attempts to correct for orbital
;       variation; deals correctly with nexp_prp>1 data
;     Version 6, 21-Feb-2007, Peter Young
;       modified the orbital variation treatment
;     Version 7, 17-Jul-2007, Peter Young
;       complete overhaul of routine. Now shows 4 image/spectrum windows. No
;       longer stores arrays in separate structure, but uses object. Allows
;       binning of spectrum to produce image.
;     Version 8, 18-Jul-2007, Peter Young
;       adjusted correction for screen size
;     Version 9, 10-Jan-2008, Peter Young
;       a help button has been added, and various cosmetic effects 
;       implemented.
;     Version 10, 8-Feb-2008, Peter Young
;       modified call to eis_despike following revision to eis_despike; also
;       implemented /no_neighbour option.
;     Version 11, 13-Feb-2008, Peter Young
;       corrected bug for calculation of default xpix value; modified widget
;       text to reduce size of widget; spectrum zoom is now reset if a new
;       window is chosen.
;     Version 12, 15-Feb-2008, Peter Young
;       implemented line ID feature; modified Help text
;     Version 13, 6-Mar-2008, Peter Young
;       changed call to routine 'ave' to 'average'; modified method for
;       checking if CHIANTI is included in user's SSW session (now use 
;       'which' command.
;     Version 14, 20-Feb-2009, Peter Young
;       corrected bug when nexp_prp>1
;     Version 15, 10-Nov-2010, Peter Young
;       now handles image scaling correctly for rasters with that a
;       mirror step size larger than the slit width; switched off line
;       IDs when full CCD spectra are shown
;     Version 16, 11-Jan-2011, Peter Young
;       switched over to the gethkwavecorr method for obtaining orbit
;       correction; force image minimum to be 0
;     Version 17, 15-Apr-2011, Peter Young
;       Added text label to indicate the time of each exposure.
;     Version 18, 23-May-2011, Peter Young
;       Fixed bug introduced in Ver. 17; set orb_corr=1 for all
;       rasters now (only rasters longer than 10 mins previously). 
;     Version 19, 7-Jul-2011, Peter Young
;       Adjusted the displayed images so that a wavelength dependent
;       Y-offset is applied rather than a fixed offset that depends on
;       which CCD the line is from.
;     Version 20, 14-Jul-2011, Peter Young
;       Now sigrange to get default min and max for displaying images;
;       also introduced a missing value to help with image scaling.
;     Version 21, 3-Apr-2012, Peter Young
;       Now uses CHIANTI 7 for line IDs.
;     Version 22, 5-Apr-2012, Peter Young
;       Routine now only displays line IDs if the wavelength window is
;       3 angstroms or less wide (for full CCD spectra it can take a
;       long time to show line IDs); spectra are now displayed with
;       ysty=3. 
;     Version 23, 30-Apr-2012, Peter Young
;       Now plots the GOES light curve for the raster duration in the
;       bottom left corner of the GUI.
;     Version 24, 4-May-2012, Peter Young
;       Changed image cursor so that it's visible in both light
;       and dark regions.
;     Version 25, 24-May-2012, Peter Young
;       The displayed time for each exposure now corresponds to the
;       midpoint of the exposure (not the start).
;     Version 26, 9-Aug-2012, Peter Young
;       Modified GOES plot to make it more "tidy".
;     Version 27, 10-Aug-2012, Peter Young
;       Modified how line IDs are added in order to speed up process.
;     Version 28, 19-Sep-2013, Peter Young
;       Added /NO_GOES keyword.
;     Version 29, 25-Mar-2014, Peter Young
;       First attempt at implementing sit-and-stare mode. Needs
;       polishing.
;     Version 30, 23-May-2014, Peter Young
;       Added a button for choosing image scaling (log or linear);
;       also removed despike and orb_corr buttons as I never used
;       them.
;     Version 31, 5-Aug-2014, Peter Young
;       If the input FILE is an array of filenames belonging to the
;       same raster, then a new widget appears allowing you to flick
;       between the rasters.
;     Version 32, 12-Aug-2014, Peter Young
;       Fixed bug when working out Y-positions (I was using 256.32 as
;       reference instead of 195.12); also now use eis_aia_offsets to
;       modify coordinates.
;     Version 33, 1-Oct-2014, Peter Young
;       Fixed bug when plotting exposure times on GOES plot for
;       sit-and-stare data. 
;     Version 34, 17-Oct-2014, Peter Young
;       The 'Time' box now displays the correct time for sit-and-stare
;       data.
;     Version 35, 23-Oct-2014, Peter Young
;       Fixed crash if the wave_corr file is not found.
;     Version 36, 2-Mar-2015, Peter Young
;       Routine now exits if there's only a single raster position.
;     Version 37, 4-Apr-2016, Peter Young
;       Updated my contact details in case of error; no change to
;       code.
;     Version 38, 30-Jan-2019, Peter Young
;       Added labels to axes; added 'Color' to the main button group,
;       and removed 'Hardcopy'; changed button group to row from
;       column.
;     Version 39, 23-Aug-2019, Peter Young
;       Fixed some issues with GOES plot implementation; updated my
;       affiliation.
;     Version 40, 6-Dec-2019, Peter Young
;       Fixed bug when nexp_prp>1.
;     Version 41, 09-Jun-2022, Peter Young
;       X-axis for sit-and-stare data was not correct, so fixed.
;     Version 42, 15-Aug-2025, Peter Young
;       Implemented the matplotlib color tables. You will need to
;       have the routine matplotlib_rgb_table.
;     Version 43, 10-Feb-2026, Peter Young
;       Added "image type" widget for allowing lambda-Y images to be
;       viewed.
;-

;------------------------------
PRO eis_browser_coltable, desc=desc, state=state, set_value=set_value
;
; This provides the list of color tables for the color pull-down menu
; (output 'desc'). It also sets the color table if 'state' and
; 'set_value' are specified.
;
; **Be careful when adding new color tables. Need to update 'desc' and
; **the if statements.


desc=['1\COLOR', $
      '0\B+W','0\Blue','0\Red','0\AIA 193', $
      '0\Viridis','0\Plasma','0\Inferno','0\Magma','0\Cividis']

IF NOT have_proc('matplotlib_rgb_table') THEN desc=desc[0:-6]
IF NOT have_proc('aia_lct') THEN remove,4,desc

desc[-1]=desc[-1].replace('0\','2\')

n_ct=n_elements(desc)

IF n_tags(state) NE 0 AND n_elements(set_value) NE 0 THEN BEGIN
  state.wid_data.coltable=set_value+3
  widget_control,state.browser_base,set_uvalue=state
 ;
  CASE 1 OF
    desc[set_value+1].contains('B+W'): loadct,0
    desc[set_value+1].contains('Blue'): loadct,1
    desc[set_value+1].contains('Red'): loadct,3
    desc[set_value+1].contains('AIA 193'): aia_lct,r,g,b,wavelnth=193,/load
    desc[set_value+1].contains('Viridis'): BEGIN
      ct=matplotlib_rgb_table(0)
      tvlct,ct
    END 
    desc[set_value+1].contains('Plasma'): BEGIN
      ct=matplotlib_rgb_table(1)
      tvlct,ct
    END 
    desc[set_value+1].contains('Inferno'): BEGIN
      ct=matplotlib_rgb_table(2)
      tvlct,ct
    END 
    desc[set_value+1].contains('Magma'): BEGIN
      ct=matplotlib_rgb_table(3)
      tvlct,ct
    END 
    desc[set_value+1].contains('Cividis'): BEGIN
      ct=matplotlib_rgb_table(4)
      tvlct,ct
    END
    ELSE: loadct,3
  END 
ENDIF 

END


;-------------------------
PRO browser_update_widdata, state, meta
;
; This takes the metadata structure (see browser_get_metadata)
; and modifies entries in wid_data. (This is needed when a new object
; is loaded.)
;
wid_data=state.wid_data

wid_data.xpos=meta.xpos
wid_data.ypos=meta.ypos
wid_data.midtime=meta.midtime
wid_data.stud_acr=meta.stud_acr
wid_data.date_obs=meta.date_obs
wid_data.sit_stare=meta.sit_stare
wid_data.origin=meta.origin
wid_data.scale=meta.scale
wid_data.tscale=meta.tscale

state.wid_data=wid_data
widget_control,state.browser_base,set_uvalue=state

END



;---------------------------------
FUNCTION browser_get_metadata, data, hdrstr
;
; I've added this subroutine in order to enable multiple
; rasters to be viewed with raster_browser. It extracts certain
; critical metadata from the data object (data).
;

;
; Check if sit-and-stare data-set
;
obsmode=data->getobsmode()
IF obsmode NE 'scanning' THEN sit_stare=1 ELSE sit_stare=0

;
; Get the EIS-AIA offset that applies to data-set
;
date_obs=data->getinfo('DATE_OBS')
xy=eis_aia_offsets(date_obs)

;
; Get xpos and ypos values. Note that ypos is defined for the 195.12 A
; by default.
;
xpos=data->getxpos() + xy[0]
ypos=data->getypos() + xy[1]


; Coordinates of bottom-left of raster
IF sit_stare EQ 1 THEN BEGIN 
  origin=[0,min(ypos)]
ENDIF ELSE BEGIN 
  origin=[min(xpos),min(ypos)]
ENDELSE 

; 
; When displaying images, I need to pad them because of the spatial
; offsets in Y (which can be up to 20 pixels). The shortest
; wavelengths need to be padded at the top of the image and the
; longest at the bottom of the image. I thus have to re-define origin
; to apply to the shortest wavelength (166 A) by applying an offset
; relative to the ypos reference wavelength (195.12 A).
;
yoffset=eis_ccd_offset(166.0)-eis_ccd_offset(195.12)
origin[1]=origin[1]-yoffset




;
; Gets the mid-point time of each exposure in '12:00:00' format. This
; is stored in wid_data. 
;
ti1=data->getti_1()
ti2=data->getti_2()
midti=(ti2-ti1)/2.+ti1
utc=data->ti2utc(midti)
midtime=anytim2utc(utc,/ccsds,/time_only,/trunc)
;
; Need to reverse midtime for sit-and-stare data.
;
IF sit_stare EQ 0 THEN midtime=reverse(midtime)


; Get image scaling. Tscale gives the size of an x-pixel in seconds
; (only for sit-and-stare).
;
IF sit_stare EQ 0 THEN BEGIN
  fmir_ss=data->getinfo('FMIR_SS')
  scale=[float(fmir_ss)/4.,1]
  tscale=-1.
ENDIF ELSE BEGIN
  nmt=n_elements(midtime)
  tscale=median(anytim2tai(midtime[1:*])-anytim2tai(midtime[0:nmt-2]))
  scale=[1,1]
ENDELSE 


exp=data->getexp()
exptime=exp[0]

outstr={ origin: origin, $
         scale: scale, $
         tscale: tscale, $
         midtime: midtime, $
         sit_stare: sit_stare, $
         xpos: xpos, $
         ypos: ypos, $
         stud_acr: data->getinfo('STUD_ACR'), $
         date_obs: data->getinfo('DATE_OBS'), $
         exptime: exptime }

return,outstr

END


;---------------------------
PRO browser_update_info, state
;
; This updates the metadata displayed on the left-side of the
; widget. This is needed when browsing multiple files.
;

xpix=state.wid_data.xpix
tmid=state.wid_data.midtime
widget_control,state.ttext,set_val='Time: '+tmid[xpix]

date_obs=state.data->getinfo('DATE_OBS')
ex=anytim(/ex,date_obs)
val='START TIME: '+strpad(trim(ex[0]),2,fill='0')+':'+strpad(trim(ex[1]),2,fill='0')+' UT'
widget_control,state.text3,set_val=val

END



;--------------------
PRO browser_goes_plot, state
;
; This plots the GOES light curve for the time period for which the
; EIS raster spans. It also overplots the time period for the
; particular exposure that the user has selected.
;
wset,state.wid_data.goes_plot_id
no_goes=state.wid_data.no_goes

IF NOT keyword_set(no_goes) THEN BEGIN
  g=state.goes
  data=g->getdata(/struct)
ENDIF 


IF keyword_set(no_goes) OR n_tags(data) EQ 0 THEN BEGIN
  plot,/nodata,[0,1],[0,1],xsty=4,ysty=4,xmarg=0,ymarg=0
  xyouts,0.5,0.5,align=0.5,'NO GOES DATA',charsiz=2
ENDIF ELSE BEGIN 
  g=state.goes
  data=g->getdata(/struct,/quiet)

  pos=[0.14,0.12,0.92,0.89]
  g->plot,showclass=1,xsty=1,legend=0,position=pos,/low,/no_timestamp, $
          xtit='',/quiet
    
  ti1=state.data->getti_1()
  ti2=state.data->getti_2()

  tai1=state.data->ti2tai(ti1)
  tai2=state.data->ti2tai(ti2)
  
  utc1=anytim2utc(/ccsds,tai1)
  utc2=anytim2utc(/ccsds,tai2)
  
  IF state.wid_data.sit_stare EQ 0 THEN BEGIN 
    utc1=utc1[state.wid_data.nx-state.wid_data.xpix-1]
    utc2=utc2[state.wid_data.nx-state.wid_data.xpix-1]
  ENDIF ELSE BEGIN
    utc1=utc1[state.wid_data.xpix]
    utc2=utc2[state.wid_data.xpix]
  ENDELSE 

  outplot,[utc1,utc1],[1e-10,1e10]
  outplot,[utc2,utc2],[1e-10,1e10]

  clear_utplot
ENDELSE 


END


;-----------------------
FUNCTION oplot_line_ids, wrange, yrange, id_file

openr,lin,id_file,/get_lun
wvl=0.
ion=''
i=0
WHILE eof(lin) NE 1 DO BEGIN
  readf,lin,format='(f8.0,2x,a10)',wvl,ion
 ;
  IF wvl GE wrange[0] AND wvl LE wrange[1] THEN BEGIN
    y75=0.75*yrange[1]+0.25*yrange[0]
    y25=0.25*yrange[1]+0.75*yrange[0]
    ypos=(10-(i MOD 10))*(y75-y25)/10. + y25
    xyouts,wvl,ypos,trim(ion),charsiz=1.2
    oplot,[1,1]*wvl,[-(y75-y25)/15.,0]+ypos
    i=i+1
  ENDIF 
ENDWHILE 
free_lun,lin

return,0

END


PRO browser_calc_zoom_params, state, pwin
;
; Calculates the pixel ranges to be displayed given the zoom
; parameters and selected pixels. The ranges are stored in
; wid_data.xrange, .yrange, .lrange.
;
iwin=state.wid_data.iwin[pwin]
lam=state.data->getlam(iwin)

nx=state.wid_data.nxpos
ny=state.wid_data.ny
nl=n_elements(lam)

xpix=state.wid_data.xpix
ypix=state.wid_data.ypix
lpix=state.wid_data.ilambda[pwin]

origin=state.wid_data.origin
scale=state.wid_data.scale


;
; Get x-range and y-range for images
; ----------------------------------
zoom=state.wid_data.im_zoom
;
; The parameter zoom ranges from 0 to 7, and the zoom
; factor is then 2^zoom. From the value of zoom we can work out the
; pixel range of 'im' that is to be plotted. The pixel ranges are
; [xlim1:xlim2,ylim1:ylim2]. 
;
xlim1=0
ylim1=0
;
IF zoom NE 0 THEN BEGIN
  ix=nx*abs(scale[0])/2/2^zoom
  iy=ny*abs(scale[1])/2/2^zoom
  ixy=max([ix,iy])
 ;
  xlim1=xpix-fix(ixy/abs(scale[0]))
  xlim2=xpix+fix(ixy/abs(scale[0]))
  IF xlim1 LT 0 THEN BEGIN
    xlim2=min([xlim2-xlim1,nx-1])
    xlim1=0
  ENDIF
 ;
  IF xlim2 GE nx THEN BEGIN
    xlim1=max([xlim1-(xlim2-nx),0])
    xlim2=nx-1
  ENDIF
 ; 
  ylim1=ypix-fix(ixy/abs(scale[1]))
  ylim2=ypix+fix(ixy/abs(scale[1]))
  IF ylim1 LT 0 THEN BEGIN
    ylim2=min([ylim2-ylim1,ny-1])
    ylim1=0
  ENDIF
 ;
  IF ylim2 GE ny THEN BEGIN
    ylim1=max([ylim1-(ylim2-ny),0])
    ylim2=ny-1
  ENDIF
 ;
  state.wid_data.xrange=[xlim1,xlim2]
  state.wid_data.yrange=[ylim1,ylim2]
ENDIF ELSE BEGIN
  state.wid_data.xrange=[0,nx-1]
  state.wid_data.yrange=[0,ny-1]
ENDELSE 


;
; Get range for wavelength window
; -------------------------------
spec_zoom=state.wid_data.spec_zoom[pwin]
;
IF spec_zoom NE 0 THEN BEGIN 
  nlz=nl/2/2^(spec_zoom)
  IF nlz EQ 0 THEN BEGIN
    ;
    ; Prevents window being one pixel wide.
    ;
    state.wid_data.spec_zoom[pwin]=spec_zoom-1
  ENDIF ELSE BEGIN 
    i0=max([lpix-nlz,0])
    i1=min([lpix+nlz,nl-1])
    state.wid_data.lrange[*,pwin]=[max([i0,0]),min([i1,nl-1])]
  ENDELSE 
ENDIF ELSE BEGIN
  state.wid_data.lrange[*,pwin]=[0,nl-1]
ENDELSE 

widget_control,state.browser_base,set_uvalue=state


END



;---------
FUNCTION get_wd, state, pwin=pwin, iwin=iwin, iexp=iexp, basic=basic
;
; Extracts the 3D data array from the data object, performing processing and
; re-formatting as necessary.
;
; The /basic keyword is needed for the orbital correction and omits some
; of the processing steps.
;

missing=-100
IF n_elements(iwin) EQ 0 THEN iwin=state.wid_data.iwin[pwin]
wd=state.data->getvar(iwin)
k=where(wd EQ 0,nk)
IF nk NE 0 THEN wd[k]=missing
lam=state.data->getlam(iwin)
midlam=mean(lam)   ; wavelength of middle of window

;
; Check dark current status for window, and remove dark current with
; eis_debias if necessary. Note that debiased data gets sent back to object.
;
IF state.wid_data.dc[iwin] EQ 0 THEN BEGIN
  eis_debias,wd
  state.data->setvar, wd, iwin
  state.wid_data.dc[iwin]=1
  widget_control,state.browser_base,set_uvalue=state
ENDIF

;
; Check cosmic ray status for window, and remove cosmic rays with
; eis_despike if necessary. Note that debiased data gets sent back to object.
;
IF state.wid_data.cr[iwin] EQ 0 AND state.wid_data.despike EQ 1 THEN BEGIN
  nexp_prp=state.data->getnexp_prp()
;  expt=state.data->getexp()
  eis_despike,wd,wdds,nexp_prp,/no_neigh
  state.data->setvar, wdds, iwin
  state.wid_data.cr[iwin]=1
  wd=temporary(wdds)
  widget_control,state.browser_base,set_uvalue=state
ENDIF

siz=size(wd)

ls=siz[1]
xs=siz[3]
ys=siz[2]

;
; Check if there are multiple exposures at each slit position, and then
; re-define WD accordingly. Note that nexp_prp contains the index of
; the exposure set. 
;
nexp=state.hdrstr.nexp
IF state.wid_data.nexp_prp GE 0 THEN BEGIN
  nexp_prp=state.hdrstr.nexp_prp
  nn=nexp/nexp_prp
  ii=indgen(nn)*nexp_prp + state.wid_data.nexp_prp
  wd=temporary(wd[*,*,ii])
  iexp=ii
ENDIF ELSE BEGIN
  iexp=indgen(nexp)
ENDELSE

IF keyword_set(basic) THEN return,wd

;
; This performs the Y CCD offset.
;
siz=size(wd)
wd2=fltarr(siz[1],siz[2]+22,siz[3])+missing
;wd2=fltarr(siz[1],siz[2]+17,siz[3])
ccdoff=eis_ccd_offset(midlam)
ccdoffref=eis_ccd_offset(166.0)
pixoff=round(ccdoffref-ccdoff)
siz2=size(wd2)
ny2=siz2[2]
wd2[*,pixoff:siz[2]+pixoff-1,*]=wd

;;   wd2[*,17:ys+17-1,*]=wd
;; ENDIF ELSE BEGIN
;;   wd2[*,0:ys-1,*]=wd
;; ENDELSE
wd=temporary(wd2)
ys=ys+22

;
; Flip X and Y in data array and reverse X.
;
wd=rearrange(temporary(wd),[1,3,2])
IF state.wid_data.sit_stare EQ 0 THEN wd=reverse(temporary(wd),2)

siz=size(wd)
IF state.wid_data.nx EQ -1 THEN BEGIN
  state.wid_data.nx=siz[2]
  state.wid_data.ny=siz[3]
  widget_control,state.browser_base,set_uvalue=state
ENDIF

return,wd

END



;--------------------
PRO correct_orb_shift, state
;
; Corrects the WVL array in WIND for the variation of the 195 line centroid
; during the raster.
; ***This subroutine is no longer used. PRY 11-Jan-2011.***
data=state.data
hdr=state.hdrstr

iwin=eis_find_window(195.12,hdr)
IF iwin NE -1 THEN BEGIN
  wd=get_wd(state,iwin=iwin,iexp=iexp,/basic)
 ;
  ll=eis_winwvl_hdr(state.hdrstr,iwin)
  i=where(ll GE 194.9 AND ll LE 195.35)
  wd=temporary(wd[i,*,*])
 ;
  eis_exposure_times,data,t
 ;
  IF state.wid_data.nexp_prp GE 0 THEN t=t[iexp]
 ;
  shifts=eis_orbit_spline_quick(t,temporary(wd),t)
;  state.wid_data.shifts=reverse(shifts)
  widget_control,state.browser_base,set_uvalue=state

ENDIF

END

;--------------------
PRO browser_plot_image, state, pwin, ps=ps
;
; Plots the image in the upper window. Setting /ps sends the plot to a
; postscript file.
;

iwin=state.wid_data.iwin[pwin]

wd=get_wd(state,pwin=pwin)
;
siz=size(wd)
ls=siz[1]
xs=siz[2]
ys=siz[3]

lbin=state.wid_data.lbin
lambda=state.wid_data.lambda[pwin]

;
; Create WVL array, giving wavelengths as a function of exposure number.
;
ll=eis_winwvl_hdr(state.hdrstr,state.wid_data.iwin[pwin])

IF state.wid_data.shift_set EQ 1 THEN shifts=state.wid_data.shifts ELSE shifts=state.wid_data.shifts-state.wid_data.shifts
wvl=fltarr(ls,xs)
FOR i=0,xs-1 DO wvl[*,i]=ll-shifts[i]


xpix=state.wid_data.xpix
ypix=state.wid_data.ypix
lpix=state.wid_data.ilambda[pwin]

ypos=state.wid_data.ypos

origin=state.wid_data.origin
scale=state.wid_data.scale

zoom=state.wid_data.im_zoom

;
; The following assumes that WIND.WVL has already been set up correctly by
; make_wind_struc.
;

IF state.wid_data.im_type EQ 1 THEN BEGIN
  nx=ls
  ny=ys
  im=fltarr(nx,ny)
  im=reform(wd[*,xpix,*])
  ;
  lam=wvl[*,xpix-1]
  scale=[1.0,1.0]
ENDIF ELSE BEGIN
  IF state.wid_data.orb_corr EQ 1 THEN BEGIN
    nx=xs
    ny=ys
    im=fltarr(nx,ny)
    FOR i=0,nx-1 DO BEGIN
      getmin=min(abs(wvl[*,i]-lambda),lpix)
      lrange=[max([0,lpix-lbin/2]),min([ls-1,lpix+lbin/2])]
      im[i,*]=average(wd[lrange[0]:lrange[1],i,*],1,missing=-100)
    ENDFOR
  ENDIF ELSE BEGIN
    getmin=min(abs(ll-lambda),lpix)
    lrange=[max([0,lpix-lbin/2]),min([ls-1,lpix+lbin/2])]
    im=average(wd[lrange[0]:lrange[1],*,*],1,missing=-100)
  ENDELSE
ENDELSE 

xlim1=0
ylim1=0

browser_calc_zoom_params, state, pwin


IF keyword_set(ps) THEN BEGIN
  dname=!d.name
  !p.font=0
  set_plot,'ps'
  device,file='idl.ps',/color,bits=16
  plot_image,im,scale=scale,orig=origin, title='Zoom='+trim(2^zoom)
  device,/close
  set_plot,dname
  !p.font=-1
  results=dialog_message('Image plot sent to postscript file idl.ps in current working directory')
ENDIF


;
; This loads up the image to be plotted, depending if a X-Y plot or a
; lambda-Y plot is to be shown.
;
IF state.wid_data.im_type EQ 1 THEN BEGIN
  ;
  lam=state.data->getlam(iwin)
  nl=n_elements(lam)
  i0=state.wid_data.lrange[0,pwin]
  i1=state.wid_data.lrange[1,pwin]
  j0=state.wid_data.yrange[0]
  j1=state.wid_data.yrange[1]
  im=im[i0:i1,j0:j1]
  ;
  origin=origin+[i0,j0]
ENDIF ELSE BEGIN
  i0=state.wid_data.xrange[0]
  i1=state.wid_data.xrange[1]
  j0=state.wid_data.yrange[0]
  j1=state.wid_data.yrange[1]
  im=im[i0:i1,j0:j1]
  ;
  origin=origin+[scale[0]*i0,scale[1]*j0]
ENDELSE 


;
; GET MINIMUM AND MAXIMUM INTENSITIES FOR IMAGE DISPLAY
; -----------------------------------------------------
IF state.wid_data.autoint[pwin] EQ 0 THEN BEGIN
  widget_control,state.min_text[pwin],get_value=intmin
  widget_control,state.max_text[pwin],get_value=intmax
  intmin=float(intmin)
  intmax=float(intmax)
ENDIF ELSE BEGIN
  chck=sigrange(im,range=range,fraction=0.99,missing=-100)
  intmin=max([range[0],0])
  intmax=range[1]
;  intmin=min(im)
;  intmin=max([intmin,0.])
;  intmax=max(im)
  widget_control,state.min_text[pwin],set_value=trim(string(format='(f10.1)',intmin))
  widget_control,state.max_text[pwin],set_value=trim(string(format='(f10.1)',intmax))
  widget_control,state.browser_base,set_uvalue=state
ENDELSE

IF state.wid_data.linlog EQ 1 THEN BEGIN
  im=alog10(im)
  intmin=alog10(max([0,intmin]))
  intmax=alog10(intmax)
ENDIF 

wset,state.wid_data.im_plot_id[pwin]

IF state.wid_data.im_type EQ 1 THEN BEGIN
 ;
 ;  This is for the lambda-Y images plots
 ;
  IF keyword_set(state.wid_data.linlog) THEN BEGIN
   ;
   ; The following tries to set intmin in such a way that the color table
   ; is not wasted on noisy pixels in the background. If you need to
   ; adjust, change the number 10 in n_im/10
   ;
    k=where(im GE 0,n_im)
    IF n_im LT 100 THEN BEGIN
      intmin=1
    ENDIF ELSE BEGIN
      ks=sort(im[k])
      vals=im[k[ks[0:n_im/10]]]
      intmin=alog10(max([mean(vals),intmin,1]))
    ENDELSE 
    intmax=alog10(intmax)
   ;
    im=alog10(im>0)
  ENDIF
 ;
  plot_image,im,xsty=5,ysty=5,min=intmin,max=intmax
 ;
  IF state.wid_data.velocity EQ 1 THEN BEGIN
    rlambda=state.wid_data.lambda[pwin]
    xra=[lam[i0],lam[i1]]
    xra=lamb2v(xra-rlambda,rlambda)
    axis,xaxis=0,xra=xra,xsty=1,xtitle='Velocity / km s!u-1!n'
    axis,xaxis=1,xra=xra,xsty=1,charsiz=0.0001
  ENDIF ELSE BEGIN 
    xra=[lam[i0],lam[i1]]
    axis,xaxis=0,xra=xra,xsty=1,xtitle='Wavelength / A'
    axis,xaxis=1,xra=xra,xsty=1,charsiz=0.0001
  ENDELSE 
 ;
  yra=[origin[1],origin[1]+(j1-j0)*scale[1]]
  axis,yaxis=0,yra=yra,ytit='Y / arcsec',ysty=1
  axis,yaxis=1,yra=yra,charsiz=0.00001,ysty=1
 ;
  usersym,[0,-1,1,0,1,-1,0],[0,-1,1,0,-1,1,0],th=2
  plots,(lpix-i0),(ypix-j0),psym=8,symsiz=2,col=1
  usersym,[0,0,0,0,1,-1,0],[0,-1,1,0,0,0,0],th=2
  plots,(lpix-i0),(ypix-j0),psym=8,symsiz=2
 ;
ENDIF ELSE BEGIN 
 
;
; PLOT IMAGE
; ----------
  ytitle='Solar-Y / arcsec'
  IF state.wid_data.sit_stare EQ 1 THEN BEGIN
    xtitle='Time / pix [ 1 pix = '+trim(string(format='(f10.1)',state.wid_data.tscale))+' s ]'
  ENDIF ELSE BEGIN
    xtitle='Solar-X / arcsec'
  ENDELSE

  plot_image,im,scale=scale,orig=origin, title='Zoom='+trim(2^zoom), $
             min=intmin,max=intmax, $
             xtitle=xtitle,ytitle=ytitle
  usersym,[0,-1,1,0,1,-1,0],[0,-1,1,0,-1,1,0],th=2
  plots,(xpix-i0)*scale[0]+origin[0],(ypix-j0)*scale[1]+origin[1],psym=8,symsiz=2,col=1
  usersym,[0,0,0,0,1,-1,0],[0,-1,1,0,0,0,0],th=2
  plots,(xpix-i0)*scale[0]+origin[0],(ypix-j0)*scale[1]+origin[1],psym=8,symsiz=2
ENDELSE 

END


;------------------
PRO browser_plot_spectrum, state, pwin
;
; Plots the spectrum in the lower window.
;
;wind=state.wind
;wd=wind.data

iwin=state.wid_data.iwin[pwin]

wd=get_wd(state,pwin=pwin)
;
siz=size(wd)
ls=siz[1]
xs=siz[2]
ys=siz[3]

spec_zoom=state.wid_data.spec_zoom[pwin]

;
; Create WVL array, giving wavelengths as a function of exposure number.
;
ll=eis_winwvl_hdr(state.hdrstr,state.wid_data.iwin[pwin])

IF state.wid_data.shift_set EQ 1 THEN shifts=state.wid_data.shifts ELSE shifts=state.wid_data.shifts-state.wid_data.shifts
wvl=fltarr(ls,xs)
FOR i=0,xs-1 DO wvl[*,i]=ll-shifts[i]
;wvl=wind.wvl
siz=size(wvl)
nw=siz[1]

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

;
; If the orbital correction is being performed then re-define LPIX for the
; purposes of plotting the spectrum. The value in WIND is not actually
; changed.
;
lambda=state.wid_data.lambda[pwin]
orb_corr=state.wid_data.orb_corr
IF orb_corr EQ 1 THEN BEGIN
  getmin=min(abs(lambda-wvl[*,xpix]),imin)
  lpix=imin
ENDIF ELSE BEGIN
  getmin=min(abs(ll-lambda),lpix)
ENDELSE

state.wid_data.ilambda[pwin]=lpix

browser_calc_zoom_params, state, pwin
;
irange=state.wid_data.lrange[*,pwin]
wrange=wvl[irange,xpix]

spec=reform(wd[*,xpix,ypix])

;
; Get intensity units
;
int_units = (state.data -> getunit())[0]


wset,state.wid_data.spec_plot_id[pwin]
plot,wvl[*,xpix],spec,psym=10,/xsty,xrange=wrange, $
     tit='lpix='+trim(lpix),ysty=3, $
     xtitle='Wavelength / '+string(197b), $
     ytitle='Intensity / '+trim(int_units)
usersym,[-1,1,0,-1,1,0],[-1,1,0,1,-1,0],th=2
plots,wvl[lpix,xpix],spec[lpix],psym=8,symsiz=2

wcheck=wrange[1]-wrange[0] LE 3.0
IF state.wid_data.line_ids EQ 1 AND wcheck EQ 1 THEN result=oplot_line_ids(wrange,!y.crange,state.wid_data.id_file)

widget_control,state.browser_base,set_uvalue=state


END





;------------------
PRO browser_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 browser_base_event, event

WIDGET_CONTROL,Event.top, get_uvalue=state


k=where(event.id EQ state.im_plot,nk)
IF nk GT 0 THEN BEGIN
  pwin=k[0]
 ;
 ; RESPOND TO MOUSE CLICKS ON IMAGE PLOT
 ; -------------------------------------
  CASE event.release OF
    1: BEGIN
      widget_control,state.browser_base,get_uvalue=state
      im_zoom=state.wid_data.im_zoom
      IF im_zoom LT 6 THEN im_zoom=im_zoom+1
      state.wid_data.im_zoom=im_zoom
      widget_control,state.browser_base,set_uvalue=state
       ;
      FOR i=0,3 DO BEGIN
        browser_plot_image,state,i
        browser_plot_spectrum,state,i
      ENDFOR
    END
     ;
    2: BEGIN
      widget_control,state.browser_base,get_uvalue=state
       ;
       ; make sure coordinate conversion takes place on image plot, so need
       ; to re-plot the image
       ;
      browser_plot_image,state,pwin
       ;
      xy=convert_coord(round(event.x),round(event.y), $
                       /device,/to_data)
       ;
      origin=state.wid_data.origin

      IF state.wid_data.im_type EQ 0 THEN BEGIN 
        scale=state.wid_data.scale
       ;
        xpix=round(xy[0]-origin[0])/scale[0]+0.5
        ypix=(round(xy[1])-origin[1])/scale[1]+0.5 
       ;
        IF state.wid_data.im_type EQ 0 THEN state.wid_data.xpix=fix(xpix)
        state.wid_data.ypix=fix(ypix)
       ;
        nx=state.wid_data.nx
        ny=state.wid_data.ny
        
        IF (state.wid_data.xpix GE 0) AND (state.wid_data.xpix LT nx) AND $
           (state.wid_data.ypix GE 0) AND (state.wid_data.ypix LT ny) THEN BEGIN
       ;
          xt='X-pixel: '+trim(state.wid_data.xpix)
          widget_control,state.xtext,set_value=xt
       ;
          yt='Y-pixel: '+trim(state.wid_data.ypix)
          widget_control,state.ytext,set_value=yt
       ;
          t_display=state.wid_data.midtime[state.wid_data.xpix]
          tt='Time: '+trim(t_display)
          widget_control,state.ttext,set_value=tt
       ;
          widget_control,state.browser_base,set_uvalue=state
       ;
          FOR i=0,3 DO BEGIN
            browser_plot_image,state,i
            browser_plot_spectrum,state,i
          ENDFOR
          browser_goes_plot,state
        ENDIF 
      ENDIF ELSE BEGIN
        ll=eis_winwvl_hdr(state.hdrstr,state.wid_data.iwin[pwin])
        nl=n_elements(ll)
        ny=state.wid_data.ny

        print,xy[0:1]
        state.wid_data.ilambda[pwin]=round(xy[0])+state.wid_data.lrange[0,pwin]
        xpix=state.wid_data.xpix
        state.wid_data.lambda[pwin]=ll[state.wid_data.ilambda[pwin]]-state.wid_data.shifts[xpix]
        state.wid_data.ypix=round(xy[1])+state.wid_data.yrange[0]
          ;
        IF (state.wid_data.ilambda[pwin] GE 0) AND $
           (state.wid_data.ilambda[pwin] LT nl) AND $
           (state.wid_data.ypix GE 0) AND (state.wid_data.ypix LT ny) THEN BEGIN
          widget_control,state.browser_base,set_uvalue=state
       ;
          FOR i=0,3 DO BEGIN
            browser_plot_image,state,i
            browser_plot_spectrum,state,i
          ENDFOR
          browser_goes_plot,state
        ENDIF 
      ENDELSE
        ;
    END
     ;
    4: BEGIN
      widget_control,state.browser_base,get_uvalue=state
      im_zoom=state.wid_data.im_zoom
      IF im_zoom gt 0 THEN im_zoom=im_zoom-1
      state.wid_data.im_zoom=im_zoom
      widget_control,state.browser_base,set_uvalue=state
       ;
       ;
      FOR i=0,3 DO BEGIN
        browser_plot_image,state,i
        browser_plot_spectrum,state,i
      ENDFOR
    END

    ELSE: 
  ENDCASE
ENDIF


spec_plot=state.spec_plot
k=where(event.id EQ spec_plot,nk)
IF nk GT 0 THEN BEGIN
  pwin=k[0]
 ;
 ; RESPOND TO MOUSE CLICKS ON SPECTRUM PLOT
 ; ----------------------------------------
  CASE event.release OF
    1: BEGIN
      widget_control,state.browser_base,get_uvalue=state
      spec_zoom=state.wid_data.spec_zoom[pwin]
      IF spec_zoom LT 6 THEN spec_zoom=spec_zoom+1
      state.wid_data.spec_zoom[pwin]=spec_zoom
      widget_control,state.browser_base,set_uvalue=state
     ;
      browser_plot_image,state,pwin
      browser_plot_spectrum,state,pwin
    END
   ;
    2: BEGIN
      widget_control,state.browser_base,get_uvalue=state
     ;
     ; make sure coordinate conversion takes place on spectrum plot, so need
     ; to re-plot the spectrum
     ;
      browser_plot_spectrum,state,pwin
     ;
;      lpix=round(event.x+0.5)
      lpix=round(event.x)
      xy=convert_coord(lpix,0., $
                       /device,/to_data)
      lambda=xy[0]

      ll=eis_winwvl_hdr(state.hdrstr,state.wid_data.iwin[pwin])
      IF state.wid_data.shift_set EQ 1 THEN shifts=state.wid_data.shifts ELSE shifts=state.wid_data.shifts-state.wid_data.shifts
      xpix=state.wid_data.xpix
      wvl=ll-shifts[xpix]
     ;
      iwin=state.wid_data.iwin[pwin]
      getmin=min(abs(lambda-wvl),lpix)
;      state.wid_data.lpix[iwin]=lpix
      state.wid_data.lambda[pwin]=lambda
      state.wid_data.ilambda[pwin]=lpix
      widget_control,state.browser_base,set_uvalue=state
       ;
      browser_plot_image,state,pwin
      browser_plot_spectrum,state,pwin
    END
     ;
    4: BEGIN
      widget_control,state.browser_base,get_uvalue=state
      spec_zoom=state.wid_data.spec_zoom[pwin]
      IF spec_zoom gt 0 THEN spec_zoom=spec_zoom-1
      state.wid_data.spec_zoom[pwin]=spec_zoom
      widget_control,state.browser_base,set_uvalue=state
       ;
      browser_plot_image,state,pwin
      browser_plot_spectrum,state,pwin
    END

    ELSE: 
  ENDCASE
ENDIF



;
; CHOOSE A NEW WAVELENGTH WINDOW
; ------------------------------
pd_window=state.pd_window
k=where(event.id EQ pd_window,nk)
IF nk GT 0 THEN BEGIN
  pwin=k[0]
  IF event.index GT 0 THEN BEGIN
    state.wid_data.iwin[pwin]=event.index-1
   ;
   ; change label for window
   ;
    id=state.data->getline_id()
    widget_control,state.window_lbl[pwin], $
         set_value='CURRENT WINDOW: '+trim(id[event.index-1])
   ;
   ; Choose default wavelength pixel for new window
   ;
    ll=eis_winwvl_hdr(state.hdrstr,event.index-1)
    nl=n_elements(ll)
    state.wid_data.lambda[pwin]=ll[nl/2]
   ;
   ; Reset zoom back to 1
   ; 
    state.wid_data.spec_zoom[pwin]=0
   ;
    widget_control,state.browser_base,set_uvalue=state
   ;
    browser_plot_image,state,pwin
    browser_plot_spectrum,state,pwin
  ENDIF
END

;
; MANUAL INTENSITY SCALING OF IMAGES - MINIMUM VALUE
; --------------------------------------------------
mintext=state.min_text
k=where(event.id EQ mintext,nk)
IF nk GT 0 THEN BEGIN
  pwin=k[0]
  state.wid_data.autoint[pwin]=0
  widget_control,state.browser_base,set_uvalue=state
  browser_plot_image,state,pwin
END


;
; MANUAL INTENSITY SCALING OF IMAGES - MAXIMUM VALUE
; --------------------------------------------------
maxtext=state.max_text
k=where(event.id EQ maxtext,nk)
IF nk GT 0 THEN BEGIN
  pwin=k[0]
  state.wid_data.autoint[pwin]=0
  widget_control,state.browser_base,set_uvalue=state
  browser_plot_image,state,pwin
END


;
; AUTOMATIC INTENSITY SCALING OF IMAGES
; -------------------------------------
autoint=state.auto_int
k=where(event.id EQ autoint,nk)
IF nk GT 0 THEN BEGIN
  pwin=k[0]
  state.wid_data.autoint[pwin]=1
  widget_control,state.browser_base,set_uvalue=state
  browser_plot_image,state,pwin
END



CASE event.id OF

  state.file_slider: BEGIN
    filestr=state.wid_data.filestr
    IF event.value NE filestr.current THEN BEGIN 
      state.wid_data.filestr.current=event.value
      d=obj_new('eis_data',filestr.filelist[event.value])
      state.data=d
      meta=browser_get_metadata(d)
      browser_update_widdata,state,meta
      browser_update_info, state
      widget_control,state.browser_base,set_uvalue=state
      FOR i=0,3 DO BEGIN
        browser_plot_image,state,i
        browser_plot_spectrum,state,i
      ENDFOR    
      browser_goes_plot,state
    ENDIF 
  END 

  state.file_butt1: BEGIN
    filestr=state.wid_data.filestr
    val=max([filestr.current-1,0])
    IF val NE filestr.current THEN BEGIN
      state.wid_data.filestr.current=val
      d=obj_new('eis_data',filestr.filelist[val])
      state.data=d
      meta=browser_get_metadata(d)
      browser_update_widdata,state,meta
      browser_update_info, state
      widget_control,state.browser_base,set_uvalue=state
      widget_control,state.file_slider,set_value=val
      FOR i=0,3 DO BEGIN
        browser_plot_image,state,i
        browser_plot_spectrum,state,i
      ENDFOR    
      browser_goes_plot,state
    ENDIF 
  END 

  state.file_butt2: BEGIN
    filestr=state.wid_data.filestr
    val=min([filestr.current+1,filestr.nfiles-1])
    IF val NE filestr.current THEN BEGIN
      state.wid_data.filestr.current=val
      d=obj_new('eis_data',filestr.filelist[val])
      state.data=d
      meta=browser_get_metadata(d)
      browser_update_widdata,state,meta
      browser_update_info, state
      widget_control,state.browser_base,set_uvalue=state
      widget_control,state.file_slider,set_value=val
      FOR i=0,3 DO BEGIN
        browser_plot_image,state,i
        browser_plot_spectrum,state,i
      ENDFOR    
      browser_goes_plot,state
    ENDIF 
  END 



  state.despike: BEGIN
    state.wid_data.despike=event.value
    widget_control,state.browser_base,set_uvalue=state
    FOR i=0,3 DO BEGIN
      browser_plot_image,state,i
      browser_plot_spectrum,state,i
    ENDFOR
  END

  state.log_butt: BEGIN
    state.wid_data.linlog=event.value
    widget_control,state.browser_base,set_uvalue=state
    FOR i=0,3 DO BEGIN
      browser_plot_image,state,i
      browser_plot_spectrum,state,i
    ENDFOR    
  END 

  state.orb_corr: BEGIN
    state.wid_data.orb_corr=event.value
    IF event.value EQ 0 THEN BEGIN
      state.wid_data.shift_set=0
;      state.wid_data.shifts=0.
    ENDIF ELSE BEGIN
      state.wid_data.shift_set=1
;      correct_orb_shift,state
    ENDELSE
    widget_control,state.browser_base,set_uvalue=state
   ;
    FOR i=0,3 DO BEGIN
      browser_plot_image,state,i
      browser_plot_spectrum,state,i
    ENDFOR
  END

  state.wpix_sum: BEGIN
    wpix=[1,3,5,7]
    state.wid_data.lbin=wpix[event.value]
    widget_control,state.browser_base,set_uvalue=state
   ;
    FOR i=0,3 DO BEGIN
      browser_plot_image,state,i
      browser_plot_spectrum,state,i
    ENDFOR
    
  END

  state.lids_butts: BEGIN
    widget_control,state.lids_butts,get_value=chck
    IF chck NE state.wid_data.line_ids THEN BEGIN
      state.wid_data.line_ids=event.value
      widget_control,state.browser_base,set_uvalue=state
      FOR i=0,3 DO BEGIN
        browser_plot_spectrum,state,i
      ENDFOR
    ENDIF
  END 

 ;
 ; Switch between image types (X-Y or lambda-Y)
 ;
  state.im_type_butts: BEGIN
    widget_control,state.im_type_butts,get_value=chck
    IF chck NE state.wid_data.im_type THEN BEGIN
      state.wid_data.im_type=event.value
      widget_control,state.browser_base,set_uvalue=state
      widget_control,state.exp_base,sens=event.value
      widget_control,state.exp_slider,set_value=state.wid_data.xpix
      widget_control,/hourglass
      FOR i=0,3 DO BEGIN
        browser_plot_image,state,i
      ENDFOR
    ENDIF
  END 

 ;
 ; Use slider and/or buttons to change exposure number.
 ;
  state.exp_slider: BEGIN
   ;
    ;; xpix=event.value
    ;; IF xpix GT state.wid_data.nx-1 THEN BEGIN
    ;;   xpix=state.wid_data.nx-1
    ;;   widget_control,state.exp_slider,set_value=xpix-ichunk*nxpos
    ;; ENDIF
    state.wid_data.xpix=event.value
   ;
    widget_control,state.browser_base,set_uvalue=state
    meta=browser_get_metadata(state.data)
    browser_update_widdata,state,meta
    browser_update_info,state
    FOR i=0,3 DO BEGIN
;      browser_update_image,state,i
;      browser_update_spectrum,state,i
      browser_plot_image,state,i
      browser_plot_spectrum,state,i
    ENDFOR    
    browser_goes_plot,state
  END 
 ;
  state.exp_butt1: BEGIN
    xpix=state.wid_data.xpix
    IF xpix NE 0 THEN BEGIN
      state.wid_data.xpix=xpix-1
      meta=browser_get_metadata(state.data)
      browser_update_widdata,state,meta
      browser_update_info,state
      widget_control,state.browser_base,set_uvalue=state
      widget_control,state.exp_slider,set_value=state.wid_data.xpix
      FOR i=0,3 DO BEGIN
;        browser_update_image,state,i
;        browser_update_spectrum,state,i
        browser_plot_image,state,i
        browser_plot_spectrum,state,i
      ENDFOR    
      browser_goes_plot,state
    ENDIF 
  END 
 ;
  state.exp_butt2: BEGIN
    xpix=state.wid_data.xpix
    IF xpix NE state.wid_data.nx-1 THEN BEGIN
      state.wid_data.xpix=xpix+1
      meta=browser_get_metadata(state.data)
      browser_update_widdata,state,meta
      browser_update_info,state
      widget_control,state.browser_base,set_uvalue=state
      widget_control,state.exp_slider,set_value=state.wid_data.xpix
      FOR i=0,3 DO BEGIN
;        browser_update_image,state,i
;        browser_update_spectrum,state,i
        browser_plot_image,state,i
        browser_plot_spectrum,state,i
      ENDFOR    
      browser_goes_plot,state
    ENDIF 
  END 



  
  state.nexp_prp: BEGIN
    widget_control,state.browser_base,get_uval=state
    state.wid_data.nexp_prp=event.value
    widget_control,state.browser_base,set_uval=state
   ;
    FOR i=0,3 DO BEGIN
      browser_plot_image,state,i
      browser_plot_spectrum,state,i
    ENDFOR
  END

  state.exit: BEGIN
    CASE event.value OF

      0: widget_control, event.top, /destroy
      1: BEGIN
        browser_font,font
        str1=['HELP FOR EIS_RASTER_BROWSER',$
'',$
'eis_raster_browser is used to browse the 3D data cubes produced by the',$
'EIS instrument from narrow slit rasters. ',$
'',$
'You will see four pairs of images in the graphic user interface',$
'(GUI). The top row of four shows images in four of the emission lines,',$
'the bottom row of four show spectra containing the four emission lines.',$
'',$
'A star in the images and a cross in the spectra indicate the pixel',$
'that is highlighted from the data cube. Thus the image represents a',$
'slice through the data cube at the specified wavelength pixel',$
'(actually it is an average of several wavelength pixels - see below).',$
'',$
'USING THE MOUSE BUTTONS',$
'',$
'You can change the chosen pixel by clicking with the MIDDLE mouse',$
'button in either of the two graphic windows. Clicking in the image',$
'changes the spatial pixel; clicking in the spectrum changes the',$
'wavelength pixel.',$
'',$
'You can zoom into and out of the images and spectra by using the LEFT',$
'and RIGHT mouse buttons.  The LEFT zooms in; the RIGHT button zooms',$
'out.',$
'',$
'CHANGING THE WAVELENTH WINDOWS',$
'',$
'Above each of the four pairs of graphic windows is a drop-down list',$
'menu which allows you to choose different wavelength windows.',$
'',$
'ADJUSTING THE INTENSITY SCALING',$
'',$
'Above each of the four pairs of graphic windows are two text boxes',$
'which allow you to change the intensity scaling in the images. (This',$
'is useful to bring out weak features in the images.)  By default the',$
'routine uses the minimum and maximum of the image. You can reset the',$
'values by clicking on the AUTO button.',$
'',$
'DE-SPIKE? - REMOVING COSMIC RAYS/HOT PIXELS',$
'',$
'On the left-hand side of the GUI is a button to de-spike the',$
'images. Note that it may take several seconds to clean each of the',$
'arrays.',$
'',$
'CORRECT ORBITAL VARIATION?',$
'',$
'The EIS emission lines move around on the detector during the',$
'satellite orbit (100mins) which thus affects the appearance of images',$
'derived from a single wavelength pixel on the detector. The routine',$
'makes a crude effort to correct for this by checking the orbital',$
'variation of the Fe XII 195 line. This can be switched off using the',$
'buttons on the left-hand side of the GUI.',$
'',$
'HOW MANY WAVELENGTH PIXELS TO SUM?',$
'',$
'The orbital variation correction above can lead to vertical stripes in',$
'the data if only one wavelength pixel is used to derive the images. By',$
'averaging over several pixels, this striping can be mostly',$
'removed. The default is to average over 5 pixels. The buttons on the',$
'left-hand side of the widget can be used to change to 1, 3, 5 or 7',$
'pixels.',$
'',$
'SHOW LINE IDS?',$
'',$
'If this option is selected then suggested line identifications are',$
'overplotted on the spectrum. These IDs are not complete and may not be',$
'accurate in all conditions (e.g., Ca XVII will not be present in quiet',$
'Sun conditions), but it is hoped they will be a useful guidance for',$
'understanding the data. The wavelengths are from the CHIANTI',$
'database. Note that you must have the CHIANTI database installed in',$
'Solarsoft for this feature to work.',$
'',$
'FURTHER INFORMATION',$
'',$
'A fixed spatial offset of 17 pixels has been applied to images for the',$
'two wavelength bands.',$
'']

        xpopup,str1,tfont=font,bfont=font,xsiz=70,ysiz=30, $
             title='HELP file for eis_raster_browser'
      END
      
      ELSE: BEGIN
       ;
       ; Have to subtract 3 as exit=0, help=1, color=2, so coltables start at 3.
       ;
        new_coltable=event.value-3
        coltable=state.wid_data.coltable
        IF coltable NE event.value THEN BEGIN
          eis_browser_coltable,state=state,set_value=new_coltable
         ;
          FOR i=0,3 DO BEGIN
            browser_plot_image,state,i
            browser_plot_spectrum, state, i
          ENDFOR    
        ENDIF 
      END  
      
    ENDCASE

  END

  ELSE:

ENDCASE

END


;-----------------
PRO browser_widget, data, hdrstr, group=group, no_offset=no_offset, $
                    no_goes=no_goes, filestr=filestr

IF n_tags(filestr) EQ 0 THEN filestr=0

IF NOT keyword_set(no_goes) THEN no_goes=0

id=data->getline_id()
i=where(id NE '')
nwind=n_elements(id[i])

;
; Apply scale factors to the plot windows if the screen size is small
;
ss=get_screen_size()
CASE 1 OF 
  ss[0] LT 1024: plot_scale=0.7
  ss[0] GE 1024 AND ss[0] LT 1280: plot_scale=1.0
  ss[0] GE 1280 AND ss[0] LT 1600: plot_scale=1.0
  ss[0] GE 1600 AND ss[0] LT 1900: plot_scale=1.3
  ss[0] GE 1900: plot_scale=1.5
ENDCASE


browser_font,font
browser_font,bigfont,/big
browser_font,fixfont,/fixed

IF keyword_set(no_offset) THEN offset=0 ELSE offset=17


meta=browser_get_metadata(data)

sit_stare=meta.sit_stare


;
; Only perform orbital correction if raster duration longer than
; 10 minutes. **UPDATE: since orbit correction taken from housekeeping
; data, then no need to do this, therefore set orb_corr=1 in all cases.
;
;duration=anytim(hdrstr.date_end,/tai)-anytim(hdrstr.date_obs,/tai)
;IF duration LE 600. THEN orb_corr=0 ELSE orb_corr=1
orb_corr=1

nexp=hdrstr.nexp
nexp_prp=hdrstr.nexp_prp
IF nexp_prp GT 1 THEN nexp=nexp/nexp_prp

xpos=meta.xpos
ypos=meta.ypos
origin=meta.origin
scale=meta.scale
date_obs=meta.date_obs
stud_acr=meta.stud_acr
midtime=meta.midtime
tscale=meta.tscale


;; xpos=data->getxpos()
;; ypos=data->getypos()

;; ; Coordinates of bottom-left of raster
;; IF sit_stare EQ 1 THEN BEGIN 
;;   origin=[0,min(ypos)]
;; ENDIF ELSE BEGIN 
;;   origin=[min(xpos),min(ypos)]
;; ENDELSE 

;; ; Get image scaling
;; ;
;; IF sit_stare EQ 0 THEN BEGIN
;;   scale=[float(hdrstr.fmir_ss)/4.,1]
;; ENDIF ELSE BEGIN
;;   scale=[1,1]
;; ENDELSE 


;
; Check if CHIANTI exists in the user's SSW distribution; if yes, then enable
; line ID plotting (line_ids=1)
;
which,'ion2filename',outfile=outfile,/quiet
IF trim(outfile) EQ '' THEN BEGIN
  line_ids=0 
ENDIF ELSE BEGIN
  line_ids=1
ENDELSE 


;
; This lookup table contains a list of EIS line IDs.
;
file=concat_dir(getenv('SSW'),'hinode')
file=concat_dir(file,'eis')
file=concat_dir(file,'idl')
file=concat_dir(file,'atest')
file=concat_dir(file,'pyoung')
file=concat_dir(file,'eis_chianti_lookup_table.txt')
chck=file_test(file)
IF chck EQ 1 THEN idfile=file ELSE idfile=''



wid_data={iwin: intarr(4), $     ; index of wavelength window
          im_zoom: 0, $  ; image zoom factor (min=1, max=10)
          spec_zoom: intarr(4), $  ; spectrum zoom factor (min=1, max=10)
          im_plot_id: intarr(4), $ ; window ID for image
          spec_plot_id: intarr(4),  $  ; window ID for spectrum
          despike: 0, $     ; De-spike info
          offset: offset,  $     ; allow for offset between CCDs
          orb_corr: orb_corr, $    ; Orbital correction
          autoint: bytarr(4)+1,   $    ; Auto-scale intensity? (1=yes)
          nexp_prp: -1, $
          xpix: 0, $
          ypix: 0,  $
          nx: -1, $
          ny:-1, $
          dc: bytarr(nwind), $
          cr: bytarr(nwind), $
          ccd: bytarr(nwind), $
          lbin: 5, $
          line_ids: line_ids, $
          origin: origin, $
          scale: scale, $
          xpos: xpos, $
          nxpos: n_elements(xpos), $
          ypos: ypos, $
          midtime: midtime, $
          date_obs: date_obs, $
          stud_acr: stud_acr, $
          shifts: fltarr(nexp), $
          shift_set: 1, $
          lambda: fltarr(4), $
          ilambda: intarr(4), $
          goes_plot_id: 0, $
          sit_stare: sit_stare, $
          no_goes: no_goes, $
          linlog: 0, $
          filestr: filestr, $
          coltable: 0, $
          tscale: tscale, $
          im_type: 0b, $
          xrange: intarr(2), $
          yrange: intarr(2), $
          lrange: intarr(2,4), $
          velocity: 0, $
          id_file: idfile $
          }

corr=data->gethkwavecorr(/wvl_cube)
IF n_tags(corr) NE 0 THEN wid_data.shifts=corr.im[*,0]



;
; Work out default IWIN values for each of the four plot windows.
;
wid_data.lambda=[256.32,195.12,284.16,192.82]
nwin=hdrstr.nwin
FOR j=0,3 DO BEGIN
  i=eis_find_window(wid_data.lambda[j],hdrstr,ll=ll)
  IF i EQ -1 THEN BEGIN
    i=min([0,nwin-1])
    ll=eis_winwvl_hdr(hdrstr,i)
    nl=n_elements(ll)
    wid_data.lambda[j]=ll[nl/2]
  ENDIF
  wid_data.iwin[j]=i
ENDFOR


;
; Work out wid_data.ccd using the TDETX tag in HDRSTR. 
; wid_data.ccd indicates which CCD the window lies on (0 - SW, 1 - LW).
;
tdetx=hdrstr.tdetx
bits=str_sep(tdetx,' ')
bits=fix(bits)
i=bits GT 2098
wid_data.ccd=i




;
; Check calibration status of object, and set dark current (dc) and cosmic
; ray (cr) status in wid_data.
;
calstat=data->getcalstat()
IF calstat.dc EQ 1 THEN wid_data.dc=1
IF calstat.cr EQ 1 THEN wid_data.cr=1

browser_base=widget_base(/row,map=1,title='EIS_RASTER_BROWSER')

;
; Here I create the buttons at the top-left of the GUI.
;  - the color table method is taken from iris_raster_browser.
;  - note that I'm removing the old Hardcopy button (which didn't work
;    anyways). 
;
subbase1=widget_base(browser_base,/col,map=1)
;; exit=cw_bgroup(subbase1,/row,['EXIT','HELP','Hardcopy'], $
;;                font=bigfont)
eis_browser_coltable,desc=desc
desc=['0\EXIT','0\HELP',desc]
exit=cw_pdmenu(subbase1,desc,font=bigfont)


;
; PIXEL NUMBER
; ------------
textbase=widget_base(subbase1,/col,frame=1)
pixtext=widget_label(textbase,value='Selected image pixel',font=font)
xt='X-pixel: '+trim(0)
xtext=widget_label(textbase,value=xt,font=font,xsiz=100)
yt='Y-pixel: '+trim(0)
ytext=widget_label(textbase,value=yt,font=font,xsiz=100)
utc=data->ti2utc()
tt='Time: '+trim(midtime[0])
ttext=widget_label(textbase,value=tt,font=font,xsiz=100)



;
; WIDGET FOR FLICKING BETWEEN RASTERS
; -----------------------------------
IF n_tags(filestr) NE 0 THEN BEGIN
  nf=filestr.nfiles
  file_base=widget_base(subbase1,/row,frame=1)
  title='File no. (0-'+trim(nf-1)+')'
  file_slider=widget_slider(file_base,min=0,max=nf-1,font=font,title=title)
  file_butt1=widget_button(file_base,value='-',font=bigfont)
  file_butt2=widget_button(file_base,value='+',font=bigfont)
ENDIF ELSE BEGIN
  file_slider=0
  file_butt1=0
  file_butt2=0
ENDELSE 

;
; DE-SPIKE BUTTONS
; ----------------
; 23-May-2014 - I decided to switch this off as I never use it. Make
;               sure to remove the despike=0 line if you re-implement
;               it. 
;
despike=0
;; IF calstat.cr NE 1 THEN BEGIN
;;   despike_base=widget_base(subbase1,/col,frame=1)
;;   despike_text=widget_label(despike_base,val='De-spike?', $
;;                             font=font,/align_left)
;;   despike=cw_bgroup(despike_base,['Off','On'], $
;;                     set_value=0,/exclusive,font=font,/row)
;; ENDIF ELSE BEGIN
;;   despike_base=-1
;;   despike_text=-1
;;   despike=-1
;; ENDELSE 

;
; REMOVE ORBITAL VARIATION
; ------------------------
; 23-May-2014 - decided to switch this off as I never use it. Make
;               sure to remove the orb_corr=0 line if you re-implement
;               it. 
orb_corr=0
;; IF orb_corr EQ 1 THEN BEGIN
;;   orb_base=widget_base(subbase1,/col,frame=1)
;;   orb_text1=widget_label(orb_base,val='Correct orbital', $
;;                          font=font,/align_left)
;;   orb_text2=widget_label(orb_base,val='variation?', $
;;                          font=font,/align_left)
;;   orb_corr=cw_bgroup(orb_base,/exclusive,['No','Yes'], $
;;                      set_value=wid_data.orb_corr,/row,font=font)
;; ENDIF


; 
; LINEAR-LOG BUTTON FOR IMAGE SCALING
; -----------------------------------
log_base=widget_base(subbase1,/col,frame=1)
log_text=widget_label(log_base,val='Image scaling', $
                         font=font,/align_left)
log_butt=cw_bgroup(log_base,/exclusive,['Linear','Log'], $
                     set_value=wid_data.linlog,/row,font=font)

;
; NUMBER OF PIXELS FOR WAVELENGTH SUMMATION
; -----------------------------------------
wpix_base=widget_base(subbase1,/col,frame=1)
wpix_text1=widget_label(wpix_base,val='How many wavelength', $
                       font=font,/align_left)
wpix_text2=widget_label(wpix_base,val='pixels to sum?', $
                       font=font,/align_left)
wpix=[1,3,5,7]
i=where(wid_data.lbin EQ wpix)
wpix_sum=cw_bgroup(wpix_base,/exclusive,trim(wpix), $
                   set_value=i,/row,font=font)

;
; SWITCH LINE IDS ON OR OFF
; -------------------------
IF wid_data.id_file NE '' THEN BEGIN 
  lids_base=widget_base(subbase1,/col,frame=1)
  lids_text=widget_label(lids_base,val='Show line IDS?', $
                         font=font,/align_left)
  lids_butts=cw_bgroup(lids_base,['No','Yes'], $
                       set_value=wid_data.line_ids,/exclusive,font=font,/row)
ENDIF ELSE BEGIN
  lids_butts=0
ENDELSE 

;
; NEXP_PRP > 1 BUTTONS
; --------------------
IF hdrstr.nexp_prp GT 1 THEN BEGIN
  nexp_prp_base=widget_base(subbase1,/col,frame=1)
  wid_data.nexp_prp=0
  text=trim(indgen(hdrstr.nexp_prp))
  exp=data->getexp()
  exp=exp[0:hdrstr.nexp_prp-1]
  expstr=trim(string(format='(f12.1)',exp))+' s'
  nexp_prp_text=widget_label(nexp_prp_base,val='Choose exposure', $
                         font=font,/align_left)
  nexp_prp=cw_bgroup(nexp_prp_base,expstr,/exclusive, $
                  set_value=wid_data.nexp_prp,/col,font=font)

ENDIF ELSE BEGIN
  nexp_prp=0
ENDELSE

;
; Images: X-Y, or lambda-Y
; ---------------------------------
im_type_base=widget_base(subbase1,/col,frame=1)
im_type_text=widget_label(im_type_base,val='Image type:', $
                      font=font,/align_left)
IF sit_stare EQ 1 THEN options=['time-Y','lambda-Y'] ELSE options=['X-Y','lambda-Y']
im_type_butts=cw_bgroup(im_type_base,options, $
                    set_value=wid_data.im_type,/exclusive,font=font,/row)

nxpos=n_elements(xpos)
exp_base=widget_base(im_type_base,/row,frame=1,sens=0)
title='Exp no. (0-'+trim(nxpos-1)+')'
exp_slider=widget_slider(exp_base,min=0,max=nxpos-1,font=font, $
                         title=title)
exp_butt1=widget_button(exp_base,value='-',font=bigfont)
exp_butt2=widget_button(exp_base,value='+',font=bigfont)


text1=widget_label(subbase1,val='STUDY: '+stud_acr,font=font, $
                   /align_left)
ex=anytim(/ex,date_obs)
date=trim(ex[4])+'-'+trim(get_month(ex[5]-1,/trunc))+'-'+trim(ex[6])
text2=widget_label(subbase1,val='DATE: '+date,font=font, $
                   /align_left)
time=strpad(trim(ex[0]),2,fill='0')+':'+strpad(trim(ex[1]),2,fill='0')
text3=widget_label(subbase1,val='START TIME: '+time+' UT',font=font, $
                   /align_left)
IF hdrstr.nexp_prp EQ 1 THEN BEGIN
  exp=data->getexp()
  expstr=trim(string(format='(f10.1)',exp[0]))+' s'
  text4=widget_label(subbase1,val='EXP. TIME: '+expstr,font=font, $
                   /align_left)
ENDIF

goes_plot=widget_draw(subbase1,xsiz=150*plot_scale,ysiz=120*plot_scale)


xsiz=fix(260*plot_scale)
ysiz=fix(250*plot_scale)

choices=trim(id[0:nwind-1])
choices=['Choose a wavelength window',choices]
nc=n_elements(choices)

plot_base=lonarr(4)
int_butt_base=lonarr(4)
min_lbl=lonarr(4)
min_text=lonarr(4)
max_lbl=lonarr(4)
max_text=lonarr(4)
auto_int=lonarr(4)
pd_window=lonarr(4)
im_plot=lonarr(4)
spec_plot=lonarr(4)
window_lbl=lonarr(4)
;
FOR i=0,3 DO BEGIN
  plot_base[i]=widget_base(browser_base,/col)
 ;
  int_butt_base[i]=widget_base(plot_base[i],/row)
  min_lbl[i]=widget_label(int_butt_base[i],value='Min:',font=font)
  min_text[i]=widget_text(int_butt_base[i],value=trim(0.), $
                    font=font,xsiz=7,/editable)
  max_lbl[i]=widget_label(int_butt_base[i],value='Max:',font=font)
  max_text[i]=widget_text(int_butt_base[i],value=trim(0.), $
                    font=font,xsiz=7,/editable)
  auto_int[i]=widget_button(int_butt_base[i],value='Auto',font=font)
 ;
  lbl_text='Current window: '+trim(id[wid_data.iwin[i]])
  window_lbl[i]=widget_label(plot_base[i], $
                             value=lbl_text,/align_left,font=font, $
                            /frame)
  pd_window[i]=widget_droplist(plot_base[i],value=choices,font=font)
 ;
  im_plot[i]=widget_draw(plot_base[i],xsiz=xsiz,ysiz=ysiz,/sens, $
                         /button_events)
 ;
  spec_plot[i]=widget_draw(plot_base[i],xsiz=xsiz,ysiz=ysiz,/sens, $
                        /button_events)
 
ENDFOR


;
; 'images' stores the images for each of the four display windows.
; I add an additional 30 pixels in Y in order to handle Y-offsets
; between the FUV1, FUV2 and NUV channels.
;
images=fltarr(wid_data.nxpos,wid_data.ny+40,4)


;
; 'spectra' contains the 1D spectrum for each window. Note that I pad
; each spectrum to be the maximum size of all of the spectrum windows
;
nl=data->getxw()
spectra=fltarr(max(nl),4)

;
; I use this for storing exposure images
;
expimages=fltarr(max(nl),wid_data.ny+40,4)



;
; Get GOES data. Note sometimes the GOES data structure comes
; back empty, so I set no_goes=1 in this case.
;
IF NOT keyword_set(no_goes) THEN BEGIN 
  g=ogoes()
  IF n_tags(filestr) EQ 0 THEN BEGIN
    tstart=hdrstr.date_obs
    tend=hdrstr.date_end
  ENDIF ELSE BEGIN 
    tstart=filestr.t0
    tend=filestr.t1
  ENDELSE
  g->set,tstart=tstart,tend=tend,mode=1
  gdata=g->getdata(/struct)
  IF n_tags(gdata) EQ 0 THEN BEGIN
    obj_destroy,g
    gdata=0
    g=0
    wid_data.no_goes=1
  ENDIF 
ENDIF ELSE BEGIN
  g=0
ENDELSE


state={data: data, $
       goes: g, $
       hdrstr: hdrstr, $
       exit: exit, $
       wid_data: wid_data, $
       browser_base: browser_base, $
       despike: despike, $
       xtext: xtext, $
       ytext: ytext, $
       ttext: ttext, $
       text3: text3, $
       orb_corr: orb_corr, $
       nexp_prp: nexp_prp, $
       wpix_sum: wpix_sum, $
       im_plot: im_plot, $
       spec_plot: spec_plot, $
       min_text: min_text, $
       max_text: max_text, $
       pd_window: pd_window, $
       window_lbl: window_lbl, $
       lids_butts: lids_butts, $
       log_butt: log_butt, $
       file_slider: file_slider, $
       file_butt1: file_butt1, $
       file_butt2: file_butt2, $
       im_type_butts: im_type_butts, $
       exp_base: exp_base, $
       exp_slider: exp_slider, $
       exp_butt1: exp_butt1, $
       exp_butt2: exp_butt2, $
       auto_int: auto_int }

WIDGET_CONTROL, browser_base, /REALIZE, set_uvalue=state


;
; Store orbital wavelength shifts into WID_DATA if orb_corr set
;
;IF wid_data.orb_corr EQ 1 THEN correct_orb_shift, state

wd=data->getvar(0)
siz=size(temporary(wd))
xsiz=siz[3]/hdrstr.nexp_prp
xpix=fix((xsiz)/2)
ypix=fix((siz[2]+17)/2)
state.wid_data.xpix=xpix
state.wid_data.ypix=ypix

xt='X-pixel: '+trim(state.wid_data.xpix)
widget_control,state.xtext,set_value=xt
;
yt='Y-pixel: '+trim(state.wid_data.ypix)
widget_control,state.ytext,set_value=yt

widget_control,state.exp_slider,set_value=xpix

;
; Get window IDs for graphic windows
;
FOR i=0,3 DO BEGIN
  WIDGET_CONTROL, im_plot[i], GET_VALUE=val
  state.wid_data.im_plot_id[i]=val
 ;
  WIDGET_CONTROL, spec_plot[i], GET_VALUE=val
  state.wid_data.spec_plot_id[i]=val
ENDFOR
;
widget_control,goes_plot,get_value=val
state.wid_data.goes_plot_id=val
;
widget_control,browser_base,set_uvalue=state



;
; Make initial plots
; 
FOR i=0,3 DO BEGIN
  browser_plot_image, state, i
  browser_plot_spectrum, state, i
ENDFOR
;
browser_goes_plot, state

tt='Time: '+trim(midtime[state.wid_data.xpix])
widget_control,state.ttext,set_value=tt


XMANAGER, 'browser_base', browser_base, group=group

END


;---------------------
PRO eis_raster_browser, file, no_offset=no_offset, no_goes=no_goes


;
; The following checks the input 'file' and creates (if necessary)
; the data object (data). If file contains more than one element, then
; the create the structure 'filestr' which is used later.
;
IF datatype(file) EQ 'STR' THEN BEGIN
  nf=n_elements(file)
  IF nf GT 1 THEN BEGIN
   ;
    data=obj_new('eis_data',file[0],datasource='fits')
    t0=data->getinfo('DATE_OBS')
   ;
    d=obj_new('eis_data',file[nf-1],datasource='fits')
    t1=d->getinfo('DATE_END')
    obj_destroy,d
   ;
    filestr={nfiles: nf, filelist: file, current: 0, t0: t0, t1: t1}    
  ENDIF ELSE BEGIN 
    data=obj_new('eis_data',file,datasource='fits')
  ENDELSE 
  swtch=1
ENDIF ELSE BEGIN
  data=file
  swtch=0
ENDELSE


eis_get_hdr_struc,data,hdrstr

IF (hdrstr.slit_ind EQ 1) OR (hdrstr.slit_ind EQ 3) THEN BEGIN
  print,' ** This routine only works with narrow slit data. **'
  return
ENDIF

IF hdrstr.nexp EQ hdrstr.nexp_prp THEN BEGIN
  print,' ** This data-set has only a single raster position and so is not suitable for eis_raster_browser. **'
  return
ENDIF


obsmode=data->getobsmode()


print,''
print,' EIS_RASTER_BROWSER was written by Peter Young (GSFC).'
print,' Please report any errors to peter.r.young -at- nasa.gov'
print,''

obstitle=data->getinfo('OBSTITLE')
obsdesc=data->getinfo('OBS_DEC')
observer=data->getinfo('OBSERVER')
hop_num=data->getinfo('JOP_ID')
sci_obj=data->getinfo('SCI_OBJ')
noaa_num=data->getinfo('NOAA_NUM')

print,'OBSTITLE: '+trim(obstitle)
print,'OBS_DEC:  '+trim(obsdesc)
print,'SCI_OBJ:  '+trim(sci_obj)
print,'NOAA_NUM: '+trim(noaa_num)
print,'EIS observer: '+trim(observer)
print,'HOP number: '+trim(hop_num)
print,''

browser_widget, data, hdrstr, no_offset=no_offset, no_goes=no_goes, filestr=filestr

IF swtch EQ 1 THEN obj_destroy,data

END
