;+
; NAME:
;       xwhisker
;
; PURPOSE:
;
;       xwhisker is used to display 2-D spectroscopic data as whisker plots
;       (images). I.e. Intensity[wavelength, y].
;       Typically y will be solar_x (for a raster) or
;       for sit-and-stare observations it will be time.
;
; CATEGORY:
;       Hansteen/Wikstol Data analysis SW
;
; CALLING SEQUENCE:
;       xwhisker, data, hdr, auxo, line, group_leader = group_leader
;
; INPUTS:
;       data: Data object. Must follow the structure of the superclass
;             HW_DATA.
;       hdr: Header object. Must follow the structure of the superclass
;             HW_HDR.
;       aux: Auxiliary object. Must follow the structure of the
;            superclass HW_AUX.
;
; KEYWORD PARAMETERS:
;       group_leader: Widget parent (if any).
;
;
; OUTPUTS:
;       None
;
; CALLS:
;
;
; COMMON BLOCKS:
;
;
; PROCEDURE:
;       xwhisker defines the widgets and displays data. It has several
;       options for displaying data in different modes, zooming,
;       selecting colors, file output etc. It is a QL-tool for
;       displaying data of 2 dimensions. xwhisker consists
;       of many functions that is called whenever the user does
;       something in the widget program.
;
; RESTRICTIONS:
;
;
; MODIFICATION HISTORY:
;       2002-august: Oivind Wikstol. 1. version
;       20-APR-2004: Oivind Wikstol - Added funtions to change wavl. 
;                                     scale [pix/Angstr.]
;       29-Sep-2007: Alessandro Gardini - Pointers freed by cleanup. Other 
;                                     changes already made on Jun-2007.
;        3-Dec-2007: A. Gardini     - Freed pointers.
;
; $Id: xwhisker.pro,v 1.10 2007/12/03 14:43:58 gardini Exp $
;-
;
; save as postscript file
;edited at home
pro xwhisker_ps,event
  thisfile=dialog_pickfile(/write,file='idl.ps')
  if thisfile eq '' then return
  widget_control,event.top,get_uvalue=info
  thisdevice=!d.name
  set_plot,'ps',/copy
  device,file=thisfile,_extra=keywords,/inches,bits_per_pixel=8,/color
  pseudoevent={widget_button,id:0L, $
    top:event.top, handler:0l, select:1}
  widget_control,event.top,set_uvalue=info
  xwhisker_draw,pseudoevent
  device,/close_file
  set_plot,thisdevice
end

; save as jpeg file
pro xwhisker_jpeg,event
  thisfile=dialog_pickfile(/write,file='idl.jpg')
  if thisfile eq '' then return
  widget_control,event.top,get_uvalue=info
  wset,(*info).wid
  snapshot=tvrd()
  tvlct,r,g,b,/get
  s=size(snapshot)
  image24=bytarr(3,s[1],s[2])
  image24(0,*,*)=r(snapshot)
  image24(1,*,*)=g(snapshot)
  image24(2,*,*)=b(snapshot)
  write_jpeg,thisfile,image24,true=1,quality=75
end

;display image in the draw window:
pro xwhisker_draw, event
  widget_control, event.top, get_uvalue = info
  if !d.name ne 'PS' then  wset, (*info).wid
  widget_control, (*info).drawid, xsize = (*info).d_xsz, $
                  ysize = (*info).d_ysz
  ; make new drawimage and axes
  sz = size((*info).image)
  xscale=(*info).lambda
  yscale=findgen(sz[2])
  drawimage = congrid((*info).image, (*info).d_xsz, (*info).d_ysz)
  (*info).xticks=fix((*info).d_xsz/100)
  sz = size(drawimage)
  ptr_free,(*info).xscale
  ptr_free,(*info).yscale
  ptr_free,(*info).ypscale
  ptr_free,(*info).drawimage
  (*info).drawimage = ptr_new(uintarr(sz(1), sz(2)))
  *(*info).drawimage = drawimage
  (*info).xscale = ptr_new(sz(1))
  (*info).ypscale = ptr_new(sz(1))
  (*info).yscale = ptr_new(sz(2))
  *(*info).xscale = interpol((*info).lambda, sz(1))
  *(*info).yscale = interpol(yscale, sz(2))
  *(*info).ypscale = interpol(yscale, sz(1))
  imagepos = [0.20, 0.10, 0.95, 0.95]
  tvimage, bytscl(*(*info).drawimage), position = imagepos, /erase,/nointerp
  plot, *(*info).xscale, *(*info).ypscale, /nodata, xstyle = 1, $
        ystyle = 1, position = imagepos, /noerase, $
        xtitle = (*info).xtitle, ytitle = (*info).ytitle, $
        xticks=(*info).xticks, xminor =(*info).xticks*2
  ;create colorbar:
  widget_control, (*info).colorbarid, get_value = wid
  if !d.name ne 'PS' then wset, wid

  ; first erase previous colorbar
  bar = intarr((*info).cb_xsz, (*info).d_ysz)*0
  tv, bar

  ; find max and min values of drawimage to produce color bar y-scale
   ymin = min(*(*info).drawimage)
  ymax = max(*(*info).drawimage)
  if ymax-ymin eq 0.0 then ymax=ymin+1
  format='(f10.1)'
  if ymax-ymin lt 10 then format='(f7.4)'
  hw_colorbar, position = [0.82, 0.15, 0.95, 0.9], range = [ymin, ymax], $
            /vertical , format=format, title=(*info).colorbar_title

end

; get the value of the draw window option menu:
function xwhisker_dwoption, event
  widget_control, event.top, get_uvalue = info
  (*info).dwoption = event.value
  return, 0
end

; slider to select exposure within a raster pos (if multiple)
pro xwhisker_expprp_slider, event
  widget_control, event.top,get_uvalue=info
  (*info).exprp=event.value
  (*info).expindx = indgen((*info).nraster)*(*info).nexpprp + (*info).exprp - 1
  nr=(*info).exprp-1
  *(*info).data-> getwin, (*info).line, wd, pos
  (*info).image = reform(wd[*,(*info).slitpos,(*info).expindx])
  widget_control,(*info).exposuretext, $
         set_value=strtrim(string((*(*info).data->getexp())[nr], $
                           format='(a,f5.2,a)'),2)+' s'                           
  aux_data=*(*info).data->getaux_data()
  widget_control,(*info).fmirrtext, $
    set_value = 'Fine mirror: '+ string((*aux_data.fmirr)[nr],format='(i6)')    
 ; display new exposure nr
  pseudoevent={widget_button,id:0L, $
    top:event.top, handler:0l, select:1}
  widget_control,event.top,set_uvalue=info
  xwhisker_draw,pseudoevent
end



; slider to select raster position
pro xwhisker_slitslider, event
  widget_control, event.top,get_uvalue=info
  (*info).slitpos=event.value
  ;"new" way of assigning data, using assoc
;  a = assoc((*info).alu, uintarr((*info).nlam, (*info).nraster))
;  (*info).image = a[(*info).slitpos]
  ; "old" way:
  *(*info).data-> getwin, (*info).line, wd, pos
  if (*info).nexpprp le 1 then begin
    (*info).image = reform(wd[*,(*info).slitpos,*])
  endif else begin
    (*info).image = reform(wd[*,(*info).slitpos,(*info).expindx])
  endelse
 ; display new raster position
  pseudoevent={widget_button,id:0L, $
    top:event.top, handler:0l, select:1}
  widget_control,event.top,set_uvalue=info
  xwhisker_draw,pseudoevent
end

; zoom in draw window:
pro xwhisker_zoom, event
  widget_control,event.top,get_uvalue=info
  if event.type gt 2 then return
  events=['down','up','motion']
  thisevent=events[event.type]
  window, /pixmap, /free, xsize = (*info).d_xsz, ysize = (*info).d_ysz
  imagepos = [0.20, 0.1, 0.95, 0.95]
  tvimage, bytscl(*(*info).drawimage), position = imagepos, /erase, /nointerp
  plot, *(*info).xscale, *(*info).ypscale, /nodata, xstyle = 1, ystyle = 1, $
        position = imagepos, /noerase, xtitle = (*info).xtitle, $
        ytitle = (*info).ytitle, xticks=(*info).xticks, xminor=(*info).xticks*2
  (*info).pixid = !d.window

  case thisevent of
    'down': begin
    ;  turn motion events on2
    ;  set static corner
    widget_control,(*info).drawid,draw_motion_events=1
    (*info).sx=event.x
    (*info).sy=event.y
  endcase
    'up': begin
      ;  erase last box
      ;  turn motion events off
       device,copy=[0,0,(*info).d_xsz,(*info).d_ysz,0,0, $
       (*info).pixid]
       widget_control,(*info).drawid,draw_motion_events=0
       dxfac = 1./(imagepos[2]-imagepos[0])
       dyfac = 1./(imagepos[3]-imagepos[1])
       sx=((*info).sx-imagepos[0]*(*info).d_xsz)*dxfac
       sy=((*info).sy-imagepos[1]*(*info).d_ysz)*dyfac
       dx=(event.x-imagepos[0]*(*info).d_xsz)*dxfac
       dy=(event.y-imagepos[1]*(*info).d_ysz)*dyfac
       sx = (sx < (*info).d_xsz - 1) > 0
       sy = (sy < (*info).d_ysz - 1) > 0
       dx = (dx < (*info).d_xsz - 1) > 0
       dy = (dy < (*info).d_ysz - 1) > 0
       image = *(*info).drawimage
       image=image[sx<dx:sx>dx,sy<dy:sy>dy]
       xscale = *(*info).xscale
       yscale = *(*info).yscale
       xscale = xscale[sx<dx:sx>dx]
       yscale = yscale[sy<dy:sy>dy]
       sz=size(image)
       mind = min(sz[0:2])
       pos=[sx<dx,sx>dx,sy<dy,sy>dy]
       case (*info).dwoption of
            0:begin
                if mind ge 2 then begin
                  xmax = (*info).screensize[0]
                  ymax = (*info).screensize[1]
                  image=congrid(image,sz[1]*2 < xmax, sz[2]*2 < ymax)
                  xscale = interpol(xscale, sz[1]*2 < xmax)
                  yscale = interpol(yscale, sz[2]*2 < ymax)
                  xzoom, image, xscale, yscale, xtitle = (*info).xtitle, $
                         ytitle = (*info).ytitle, group_leader=event.top
                endif
              end
            1:begin
                ;set up axis titles for line plots (options 1 or 2 below)
                varname = *(*info).aux->getvariablename()
                varname = varname[0] +': column average'
                dmean = total(image, 1)/sz[1]
                if sz[0] ge 2 then begin
                  xlineplot, dmean, xscale = yscale, $
                  title = varname, $
                  xtitle = (*info).xytitle[(*info).ydim], $
                  ytitle = varname, $
                  groupl = event.top
                endif
              end
            2:begin
                ;set up axis titles for line plots (options 1 or 2 below)
                varname = *(*info).aux->getvariablename()
                varname = varname[0] +': row average'
                dmean = total(image, 2)/sz[2]
                if sz[0] ge 2 then begin
                  xlineplot, dmean, xscale = xscale, $
                    title = varname, $
                    xtitle = (*info).xytitle[(*info).xdim], $
                    ytitle = varname, $
                    groupl = event.top
                endif
              end
            endcase
         endcase
       'motion':  begin
       ;  erase previous box
       ;  draw new box
         dx=event.x
         dy=event.y
         sx=(*info).sx
         sy=(*info).sy
         wset,(*info).wid
         device,copy=[0,0,(*info).d_xsz,(*info).d_ysz,0,0,(*info).pixid]
         plots,[sx,sx,dx,dx,sx],[sy,dy,dy,sy,sy],/device, $
            color=(*info).drawcolor
       endcase
    endcase
  wdelete, (*info).pixid
  noaction:
end

; create animation widget and launch animation
pro xwhisker_anim, event
  widget_control, event.top, get_uvalue = info
  *(*info).data-> getwin, (*info).line, wd, pos

  sz = size(wd)
  ndim = sz[0]
  xsize = sz[1]
  ysize = sz[2]

  if ndim lt 3 then begin
    ok = dialog_message('Data array must be 3-D to make animation!')
    return
  endif

  ; bytscale data to save time in animation tool
  wdb = bytscl(wd)

  ; write data to assoc file:
  afile = 'adata'+strtrim(string((*info).line), 2)+'.dat'
  openw, lu, afile, /get_lun
  rec = assoc(lu, wdb)
  rec[0] = wdb
  close, lu & free_lun, lu

  ; start ximovie, with the delete keyword (afile is removed from disc
  ; when ximovie is closed
  ximovie, afile, xsize, ysize, group_leader = (*info).tlb, /fdelete
  return
end

; change wavelength scale to pixels
pro xwhisker_wpix, event
  widget_control, event.top, get_uvalue = info
  ; change titles in aux object
  *(*info).aux-> setwscale,'pixels'
  *(*info).aux-> setxytitle,wscale='pixels'
  ; set titles for image plots
  (*info).xtitle = (*(*info).aux-> getxytitle())[(*info).xdim]
  (*info).ytitle = (*(*info).aux-> getxytitle())[(*info).ydim]

  pos = (*info).pos
  pscale = findgen(pos[1]) + pos[0]
  (*info).lambda = pscale
  pseudoevent={widget_button,id:0L, $
               top:event.top, handler:0l, select:1}
  xwhisker_draw, pseudoevent
end

; change wavelength scale to Angstrom
pro xwhisker_wangstr, event
  widget_control, event.top, get_uvalue = info
   ; change titles in aux object
  *(*info).aux-> setwscale,string("305B)
  *(*info).aux-> setxytitle,wscale=string("305B)
  ; set titles for image plots
  (*info).xtitle = (*(*info).aux-> getxytitle())[(*info).xdim]
  (*info).ytitle = (*(*info).aux-> getxytitle())[(*info).ydim]

  pos = (*info).pos
  lstart = pos[0]
  lstop = pos[0]+pos[1]-1
  lambda_struct = *(*info).data-> getlambda()
  ; wavelength scale detector B
  if lstart le 2147 then begin
    det = 'B'
    lambda = lambda_struct.scale_b[lstart:lstop]
    ; wavelength scale detector A
  endif else begin
    det = 'A'
    lambda = lambda_struct.scale_a[lstart-2148:lstop-2148]
  endelse

  (*info).lambda = lambda
  pseudoevent={widget_button,id:0L, $
               top:event.top, handler:0l, select:1}
  xwhisker_draw, pseudoevent
end




; select color table
pro xwhisker_colors, event
  widget_control, event.top, get_uvalue=info
  thisevent = tag_names(event, /structure_name)
  case thisevent of
  'WIDGET_BUTTON': begin
      xcolors, ncolors = (*info).ncolors, bottom = (*info).bottom, $
        title = 'xwhisker colors (' + strtrim((*info).wid, 2) + ')', $
        group_leader = event.top, notifyid = [event.id, event.top]
      endcase
  'XCOLORS_LOAD': begin
      (*info).r = event.r((*info).bottom:(*info).ncolors-1 + (*info).bottom)
      (*info).g = event.g((*info).bottom:(*info).ncolors-1 + (*info).bottom)
      (*info).b = event.b((*info).bottom:(*info).ncolors-1 + (*info).bottom)
      if !d.n_colors gt 256 then begin
        pseudoevent={widget_button,id:0L, $
          top:event.top, handler:0l, select:1}
        xwhisker_draw, pseudoevent
      endif
    endcase
  endcase
  widget_control, event.top, set_uvalue = info
end

; protect colors
pro xwhisker_protect_colors,event
  widget_control, event.top, get_uvalue = info
  tvlct, (*info).r, (*info).g, (*info).b, (*info).bottom
end

; resize main window
pro xwhisker_resize, event
  widget_control, event.top ,get_uvalue = info
  (*info).d_xsz = (event.x - (*info).lcol_xsz-(*info).cb_xsz) > 0
  (*info).d_ysz = event.y
  widget_control, (*info).drawid, xsize = (*info).d_xsz, $
                   ysize = (*info).d_ysz
  ; draw new image
  widget_control, (*info).colorbarid, draw_ysize = (*info).d_ysz
  pseudoevent={widget_button,id:0L, $
               top:event.top,handler:0l,select:1}
  xwhisker_draw, pseudoevent
end

pro xwhisker_lineplot, event
  widget_control, event.top, get_uvalue = info
  thisevent=tag_names(event,/structure_name)
  case thisevent of
    'WIDGET_DROPLIST': begin
      mode = event.index
      end
      else:
  endcase
  xytitle = *(*info).aux-> getxytitle()
  varname = *(*info).aux-> getvariablename()
  varname = varname[0]
  case mode of
    0: begin
         return
       end
    1: begin
            data = (*info).image(*, *)
            xlineplot, data, xscale = (*info).lambda, $
                       xtitle = xytitle[(*info).xdim], $
                       cslider_title = xytitle[(*info).ydim], $
                       ytitle = varname, groupl = (*info).tlb
       end
    2: begin
            data = transpose((*info).image(*, *))
            xlineplot, data, xtitle = xytitle[(*info).ydim], $
                       cslider_title = xytitle[(*info).xdim], ytitle = varname, $
                       groupl = (*info).tlb
       end
  endcase
end

; close xwhisker
pro xwhisker_destroy, event
  widget_control, event.top,/destroy
end

pro xwhisker_cleanup, tlb
  widget_control, tlb, get_uvalue = info
  wdelete, (*info).mainpixid
;  free_lun, (*info).alu
  if file_test((*info).afile, /regular) then $
  file_delete, (*info).afile
  ptr_free, (*info).data 
  ptr_free, (*info).hdr 
  ptr_free, (*info).aux 
  ptr_free, (*info).drawimage 
  ptr_free, (*info).xscale 
  ptr_free, (*info).yscale 
  ptr_free, (*info).ypscale 
  ptr_free, info
end

pro xwhisker , data, hdr, aux, line, group_leader = group, $
              ncolors = ncolors, filename = filename
  @environment
  if n_params() lt 4 then begin
    message, $
      'xwhisker: A data object, header object, aux object and line must be given', $
       /cont
    return
  endif

  if n_elements(ncolors) eq 0 then ncolors = (!d.n_colors < 256)
  if n_elements(drawcolor) eq 0 then drawcolor=!p.color
  if n_elements(filename) eq 0 then filename = ''
  ; drawing window size in relation to screen
    if n_elements(scfac) eq 0 then scfac=0.6
  screensize=get_screen_size()
  sz=screensize*scfac
  d_xsz = sz[1]/2
  d_ysz = sz[0]

  sit_and_stare = data->getsit_and_stare()

  nslit=data->getyw()
  nslit = nslit[line]
  nraster = data-> getnraster()
  nexp = data-> getnexp()
  nexpprp = data->getnexp_prp()  ; number of exp pr. raster pos.
  slitpos = 0

  ; so far QL can not handle sit-and-stare with different exposure times 
  ; (when it is run as "multiple exp pr rast. pos. 
  ; Will have to deal with that...
  ;
  ; OW 14-april 2005.
  if sit_and_stare then nexpprp = 1  

  data-> getwin, line, wd, pos
  if nexpprp le 1 then begin
    image = reform(wd[*,slitpos,*])
    expindx = 0
  endif else begin
    expnr_at_rp = 1 ; intitialize first exp at each raster pos.
    expindx = indgen(nraster)*nexpprp + expnr_at_rp - 1
    image = reform(wd[*, slitpos, expindx])
  endelse

  ; get wavelength scale for detectors B (170-215 Å)
  ; and A (250-295 Å)
  ; determine if detector A or B:
  lstart = pos[0]
  lstop = pos[0]+pos[1]-1
  pscale = findgen(pos[1]) + pos[0]
  lambda_struct = data-> getlambda()
  ; wavelength scale detector B
  if lstart le 2147 then begin
    det = 'B'
    lambda = lambda_struct.scale_b[lstart:lstop]
    ; wavelength scale detector A
  endif else begin
    det = 'A'
    lambda = lambda_struct.scale_a[lstart-2148:lstop-2148]
  endelse

  ; set lambda to wavelength or pixel scale:
  scale = aux->getwscale()
  if scale eq 'pixels' then lambda = pscale

  ; initialize size of draw window
  sz = size(wd)
  ndim = sz[0]
  xsz = sz[1]
  nlam = xsz
  ysz = sz[3]
  ; test using associated variabels:
  ;open temporary file, print data and close the file:
  afile = 'line'+strtrim(string(line), 2)+'.dat' 
  openw, alu, afile, /get_lun
  for i = 0, nslit-1 do writeu, alu, reform(wd[*, i, *])
  close, alu & free_lun, alu
  ; open file for reading and define associated variable
;  openu, alu, afile, /get_lun
;  a = assoc(alu,  uintarr(nlam, nraster))
;  ap = ptr_new(a)
;  image = a[slitpos]
  ;"old" way of initializing image without associates
;  image = reform(wd[*,slitpos,*])

  xdim = 0
  if sit_and_stare then ydim = 3 else ydim = 2
  xytitle = aux-> getxytitle()
  xtitle = xytitle[xdim]
  ytitle = xytitle[ydim]
  window, /pixmap, /free, xsize = xsz, ysize = ysz
  tv, bytscl(image, top = ncolors)
  pixid = !d.window

  ; base widget:
  xwt = 'XWhisker - '+aux-> gettitle() + '   '   ; xwhisker window title
  tlb = widget_base(/row, title=xwt, tlb_size_events = 1, $
                    mbar=menubar, xoffset=100, yoffset=100)
  lcol = widget_base(tlb, /frame, /column)      ;left column.
  rcol = widget_base(tlb, /column)      ;right column.

  ; create pulldown menus on the base widget menubar
  filemenu=widget_button(menubar, value='File',/menu, uvalue='file')
  savemenu=widget_button(filemenu, value='Save as', uvalue='save', /menu)
  psmenu=widget_button(savemenu, value='Postscript', event_pro = 'xwhisker_ps')
  jpgmenu=widget_button(savemenu, value='JPG', event_pro = 'xwhisker_jpeg')
  exitmenu=widget_button(filemenu, value='Close', event_pro='xwhisker_destroy')

  optmenu=widget_button(menubar,value='Options', uvalue='options')
  colmenu=widget_button(optmenu, value='Colour table', $
                               event_pro='xwhisker_colors')
  animenu=widget_button(optmenu, value='Create Animation', $
                               event_pro='xwhisker_anim')
  wscalemenu=widget_button(optmenu, value='Change wavelength scale',/menu)
  angstr = string("305B)+'ngstr'+string("370B)+'m'
  pixmenu=widget_button(wscalemenu, value='Pixels',event_pro='xwhisker_wpix')
  angstrmenu=widget_button(wscalemenu, value=angstr,event_pro='xwhisker_wangstr')

  ;display window:
  displaybase = widget_base(rcol, /row)
  drawid=widget_draw(displaybase, retain = 2,$
                     xsize = d_xsz, ysize = d_ysz, $
                       /button_events, event_pro='xwhisker_zoom')
  cb_xsz = 84  ; xsize of color bar draw widget
  ; create color bar to the right of display window:
  colorbarid = widget_draw(displaybase, retain = 2, xsize = cb_xsz, $
                           ysize = d_ysz)
  colorbar_title=data->gettitle()+' '+(data->getunit())[0]
  ; create menu for controlling action in draw window
  dwoption = widget_base(lcol, /column, /frame)
  dwoption_title = widget_label(dwoption, value = 'Window action')
  menu = (aux->getmenu()).action
  if sit_and_stare then begin
    dwoption_names = [menu[0], menu[2], menu[4]]
  endif else begin
    dwoption_names = [menu[0], menu[2], menu[3]]
  endelse
  dwoption_menu = cw_bgroup(dwoption, dwoption_names, /return_index, $
                            /exclusive, set_value = 0, $
                            event_func = 'xwhisker_dwoption')

  lsubcol = widget_base(lcol, /row)
  sliderbase = widget_base(lsubcol,/col)
  
  if nexpprp gt 1 then begin
    exprp = 1
    expprpslider = widget_slider(sliderbase, xsize = 90, $
                                 minimum = 1, maximum = nexpprp, $
                                 title = 'Exp.# at rast. pos.', $
                                 value = 1, $
                                 event_pro = 'xwhisker_expprp_slider')
  endif
  
  exposurebase = widget_base(lsubcol,/col)
  exposuretext = widget_label(exposurebase, $
    value = strtrim(string((data->getexp())[0],format='(a,f5.2)'),2)+' s', $
    /align_left)
  
  aux_data=data->getaux_data()
  fmirrbase = widget_base(exposurebase,/col)
  fmirrtext = widget_label(fmirrbase, $
    value = strtrim('Fine mirror: '+ string((*aux_data.fmirr)[0],format='(i6)'),2), $
    /align_left)
    
  xycenbase = widget_base(exposurebase,/col)
  if data-> getdatasource() eq 'fits' then begin
    xycentext = widget_label(xycenbase, $
      value = 'Xcen: '+ string((data->getxcen())[0],format='(i4)')+ $
             ' Ycen: '+ string((data->getycen())[0],format='(i4)'), $
      /align_left)
  endif else begin
    xycentext = widget_label(xycenbase, $
      value = 'Xcen: -999'+ $
             ' Ycen: -999', $
      /align_left)
  endelse

  title = 'Slit Position'
  slitslider = widget_slider(sliderbase, xsize=90, $
                          minimum=0, maximum=nslit-1, title=title, $
                          value=0, event_pro='xwhisker_slitslider',/drag)

  lineplotbase = widget_base(lcol, /column)
  names = ['Not active', 'Row plot', 'Column plot']
  lineplot = widget_droplist(lineplotbase, value = names, $
                              title = 'Plot pixel values', $
                              event_pro = 'xwhisker_lineplot')

  closefield = widget_base(lcol, /column)
  closebutton = widget_button(closefield, value = 'Close', $
                              event_pro = 'xwhisker_destroy')

  ; realize main window:
  widget_control, tlb, /realize, tlb_get_size = tlb_sz

  ; define size of widget and the menu column
  tlb_xsz = tlb_sz[0]  ; xsize of whole widget in pixels
  tlb_ysz = tlb_sz[1]  ; ysize of whole widget in pixels
  lcol_xsz = tlb_xsz - d_xsz - cb_xsz

  ; get window id of display window
  widget_control, drawid, get_value = wid
  wset, wid

  ;get and save color table
  tvlct, r, g, b, /get
  bottom = 0
  if (!d.n_colors le 256) then begin
    r = r[bottom:ncolors-1+bottom]
    g = g[bottom:ncolors-1+bottom]
    b = b[bottom:ncolors-1+bottom]
  endif

  ; set up default display mode:
  info = {drawimage:ptr_new(), $
          image:image, $
          xdim:xdim, $
          ydim:ydim, $
          xscale:ptr_new(), $
          yscale:ptr_new(), $
          ypscale:ptr_new(), $
          data:ptr_new(data), $
          hdr:ptr_new(hdr), $
          aux:ptr_new(aux), $
          exposuretext:exposuretext, $
          fmirrtext:fmirrtext, $
          xycentext:xycentext, $
          xticks:0, $
          nslit:nslit,  $
          nlam:nlam, $
          nraster:nraster, $
          nexp:nexp, $
          expindx:expindx, $
          nexpprp:nexpprp, $
          exprp:1, $
          ndim:ndim, $
          line:line, $
          lambda:lambda, $
          pos:pos, $
          screensize:screensize, $
          lcol_xsz:lcol_xsz, $
          d_xsz:d_xsz, $
          d_ysz:d_ysz, $
          cb_xsz:cb_xsz, $
          tlb:tlb, $
          r:r, g:g, b:b, $
          bottom:bottom, $
          ncolors:ncolors, $
          sx:0, $
          sy:0, $
          dwoption:0, $
          dwoption_menu:dwoption_menu, $
          drawid:drawid, $
          colorbarid:colorbarid, $
          colorbar_title:colorbar_title,$
          lineplot:lineplot,  $
          slitpos:slitpos, $
          drawcolor:drawcolor, $
          mainpixid:pixid, $
          pixid:pixid, $
          xtitle:xtitle, $
          ytitle:ytitle, $
          xytitle:xytitle, $
          afile:afile, $
          wid:wid}
  info = ptr_new(info, /no_copy)
  ; set user value of tlb widget to be the info ptr
  widget_control, tlb, set_uvalue = info
  ; create pseudoevent and send this event to xwhisker_draw,
  ; in order to draw the image
  pseudoevent={widget_button,id:0L, $
               top:tlb, handler:0l, select:1}
  xwhisker_draw, pseudoevent

  xmanager, 'xwhisker', tlb, /no_block, event_handler = 'xwhisker_resize', $
            group_leader = group, cleanup = 'xwhisker_cleanup'

end
