;+
; NAME:
;       XMAP
;
; PURPOSE:
;
;       XMAP is used to display 2-D (or higher) data. It is a
;       widget based program with several options and functions that
;       allows data to be displayed in a nukmber of modes.
;
;
; CATEGORY:
;       Hansteen/Wikstol Data analysis SW
;
; CALLING SEQUENCE:
;       xmap, data, hdr, aux, group_leader = groupleader, ncolors=ncolors
;
; 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:
;       linelist: list of line indexes
;       group_leader: Widget parent (if any).
;       ncolors: Number of colors for xmap. Default is
;                !d.n_colors<256.
;
;
; Outputs:
;       None
;
; CALLS:
;
;
; COMMON BLOCKS:
;
;
; PROCEDURE:
;       XMAP 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 or higher. XMAP consists
;       of many functions that is caled whenever the user does
;       something in the widget program.
;
; RESTRICTIONS:
;
;
; MODIFICATION HISTORY:
;       12-Sep-2002: Oivind Wikstol. First version.
;       15-Feb-2007: Viggo Hansteen - reverse x-axis if raster.
;       29-Sep-2007: A. Gardini - Pointers freed by cleanup. Other changes 
;                                 already made in Jun-2007
;        3-Dec-2007: A. Gardini - Freed pointers.
;       17-Dec-2007: A. Gardini - Fixed "Plot pixel values" problem:
;                                 realsize=1, ypscale removed, ptrs corrected
;       19-Dec-2007: A. Gardini - Drawimage used in xmap_pixplot.
;        3-Jan-2008: A. Gardini - Initialization of the continuum in wd_def.
;                                 Ghosted "Define line" and "Save" buttons. 
;        8-Feb-2008: A. Gardini - Cleaning. "Define line" button erased in
;                                 the plot of moments. 
;       17-Feb-2008: A. Gardini - Added sliders in the plot of moments.
;       20-Feb-2008: A. Gardini - Error corrected in the slider definition.
;       18-Mar-2008: A. Gardini - Changed the column order in moment objects.
;       19-Mar-2008: A. Gardini - Set the iwin keyword in xmap_save_moment.
;       10-Oct-2008: A. Gardini - Added groupl calling xmoment, cleanup check
;       11-Nov-2008: A. Gardini - Corrected dx and dy in xmap_warcsec. 
;       30-Apr-2009: A. Gardini - Fixed 1 pixel shift error.
;       16-Jun-2009: A. Gardini - Set getypos(iwin) in xmap_warcsec.
;       19-Aug-2009: A. Gardini - Fixed bug in the xscale in xmap_warcsec.
;
; $Id: xmap.pro 391 2010-07-01 14:35:52Z viggoh $
;-
;
; save as postscript file
pro xmap_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
  xmap_draw, pseudoevent
  device,/close_file
  set_plot,thisdevice
end

; save as jpeg file
pro xmap_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 xmap_draw, event
  widget_control, event.top, get_uvalue = info
  if !d.name ne 'PS' then  wset, (*info).wid

;  (*info).d_xsz = sz(1)
;  (*info).d_ysz = sz(2)
  imagepos = [0.20, 0.1, 0.95, 0.95]
  xytitle = *(*info).aux->getxytitle()
  (*info).xtitle = xytitle[(*info).xdim]
  (*info).ytitle = xytitle[(*info).ydim]
;  if (*info).ct eq 99 then begin
;    ctfile=getenv('SSW')+'/hinode/eis/idl/ancillary/bluegreyred.sav'
;    if (file_info(ctfile)).exists then begin
;      restore,ctfile,/verb
;      tvlct,r,g,b
;     loadct,0
;    endif else loadct,0
;  endif ; else begin
;    loadct,(*info).ct
;    tvlct,r,g,b,/get
;  endelse
  if (*info).xdim eq 2 then rotate=0 else rotate=0
  plot_image,rotate(*(*info).drawimage,rotate),origin=(*info).origin,$
             scale=(*info).scale, $
             xtitle = (*info).xtitle, ytitle = (*info).ytitle, /nosquare, $
             max=(*info).max,min=(*info).min
;  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

  ;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 = (*info).min
  ymax = (*info).max
  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.8, 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 xmap_dwoption, event
  widget_control, event.top, get_uvalue = info
  (*info).dwoption = event.value
  return, 0
end

; wavelength selection buttons
function xmap_dsoption, event
  widget_control, event.top,get_uvalue=info
  case event.value of
  0: xmap_wpix, event
  1: xmap_warcsec, event
  endcase
  return,0
end

; change x/y axes scale to pixels
pro xmap_wpix, event
  widget_control, event.top, get_uvalue = info
  ; change titles in aux object
  *(*info).aux-> setxytitle,sscale='pixels'
  ; set titles for image plots
  (*info).xtitle = (*(*info).aux-> getxytitle())[(*info).xdim]
  (*info).ytitle = (*(*info).aux-> getxytitle())[(*info).ydim]
  ; set scale for images
  (*info).origin=[0.0,0.0]
  (*info).scale=[1.0,1.0]
  pseudoevent={widget_base,id:0L, $
               top:event.top, handler:0l, x:(*info).tlb_xsz, y:(*info).tlb_ysz}
  xmap_draw, pseudoevent
end

; change x/y scale to arcsec
pro xmap_warcsec, event
  widget_control, event.top, get_uvalue = info
   ; change titles in aux object
  *(*info).aux-> setxytitle,sscale='arcsec'
  ; set titles for image plots
  (*info).xtitle = (*(*info).aux-> getxytitle())[(*info).xdim]
  (*info).ytitle = (*(*info).aux-> getxytitle())[(*info).ydim]
  xscale = (*(*info).data->getxpos())
  n1=n_elements(xscale)-1
  dx=abs(xscale[0]-xscale[n1])/n1
  iwin=(*info).linelist
  yscale = (*(*info).data->getypos(iwin))  
  dy=(max(yscale)-min(yscale))/(n_elements(yscale)-1)
  (*info).origin=[min([xscale[0],xscale[n1]]),min(yscale)]
  (*info).scale=[dx,dy]
  
  pseudoevent={widget_base,id:0L, $
               top:event.top, handler:0l, x:(*info).tlb_xsz, y:(*info).tlb_ysz}
  xmap_draw, pseudoevent
end


; slider to select exposure within a raster pos (if multiple)
pro xmap_expprp_slider, event
  widget_control, event.top,get_uvalue=info
  (*info).exprp=event.value
  nr=(*info).exprp-1
  (*info).expindx = indgen((*info).nraster)*(*info).nexpprp + (*info).exprp - 1
  
  widget_control,(*info).exposuretext, $
         set_value=strtrim(string((*(*info).data->getexp())[nr], $
                           format='(a,f5.2,a)'),2)+' s'

  ; create resize pseudoevent to draw selected line
  pseudoevent={widget_base,id:0l, $
               top:(*info).tlb, handler:0l, x:(*info).tlb_xsz, y:(*info).tlb_ysz}
  xmap_resize, pseudoevent
end

; select line from linelist
pro xmap_lineselect, event
  widget_control, event.top, get_uvalue = info
  (*info).line = (*info).linelist[event.index]

  ; create resize pseudoevent to draw selected line
  pseudoevent={widget_base,id:0l, $
               top:(*info).tlb, handler:0l, x:(*info).tlb_xsz, y:(*info).tlb_ysz}
  xmap_resize, pseudoevent
end

; select data product to display (in case of moments)
pro xmap_dpselect, event
  widget_control, event.top, get_uvalue = info
  (*info).dpnr = event.index
  ; create resize pseudoevent to draw selected data
  pseudoevent={widget_base,id:0l, $
               top:(*info).tlb, handler:0l, x:(*info).tlb_xsz, y:(*info).tlb_ysz}
  xmap_resize, pseudoevent
end

; zoom in draw window:
pro xmap_zoom, event
  widget_control,event.top,get_uvalue=info
  if event.type gt 2 then return

  ;set up axis titles for line plots (options 1 or 2 below)
  varname = *(*info).aux->getvariablename()
  varname = varname[0] +': column average'
  xytitle = *(*info).aux->getxytitle()

  events=['down','up','motion']
  thisevent=events[event.type]
  window, /pixmap, /free, xsize = (*info).d_xsz, ysize = (*info).d_ysz
  plot_image,*(*info).drawimage,origin=(*info).origin,scale=(*info).scale, $
        xtitle = (*info).xtitle, ytitle = (*info).ytitle, /nosquare
  imageposx = [!x.margin[0]*!d.x_ch_size,(*info).d_xsz-!x.margin[1]*!d.x_ch_size]
  imageposy = [!y.margin[0]*!d.y_ch_size,(*info).d_ysz-!y.margin[1]*!d.y_ch_size]
  imagepos = [imageposx[0],imageposy[0],imageposx[1],imageposy[1]]
;  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
  (*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
       image = *(*info).drawimage
       sz=size(image)
       dxfac = 1./(imagepos[2]-imagepos[0])
       dyfac = 1./(imagepos[3]-imagepos[1])
       sx=((*info).sx-imagepos[0])*dxfac*sz[1]
       sy=((*info).sy-imagepos[1])*dyfac*sz[2]
       dx=(event.x-imagepos[0])*dxfac*sz[1]
       dy=(event.y-imagepos[1])*dyfac*sz[2]
       sx = (sx < sz[1] - 1) > 0
       sy = (sy < sz[2] - 1) > 0
       dx = (dx < sz[1] - 1) > 0
       dy = (dy < sz[2] - 1) > 0
       image=image[sx<dx:sx>dx,sy<dy:sy>dy]
       xscale = (*info).origin[0]+indgen(sz[1])*(*info).scale[0]
       yscale = (*info).origin[1]+indgen(sz[2])*(*info).scale[1]
       xscale = xscale[sx<dx:sx>dx]
       yscale = yscale[sy<dy:sy>dy]
       sz=size(image)
       pos=[sx<dx,sx>dx,sy<dy,sy>dy]
       mind = min(sz[0:2])
       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]
                xytitle = *(*info).aux->getxytitle()
                dmean = total(image, 2)/sz[2]
                if sz[0] ge 2 then begin
                  xlineplot, dmean, xscale = xscale, $
                             title = varname, $
                             xtitle = xytitle[(*info).xdim], $
                             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]
                xytitle = *(*info).aux->getxytitle()
                dmean = total(image, 1)/sz[1]
                if sz[0] ge 2 then begin
                  xlineplot, dmean, xscale = yscale, $
                             title = varname, $
                             xtitle = xytitle[(*info).ydim], $
                             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

; Popup window for line selection
;pro xmap_pickline, event
;  widget_control, event.top ,get_uvalue = info
;  ; open window for line selection
;  lineselect_widget = widget_base(title = 'Select line', $
;                group_leader = (*info).tlb,/row)
;  closefield = widget_base(lineselect_widget,/column)
;  closebutton = widget_button(closefield, value = 'OK', $
;                              event_pro = 'xmap_pickline_destroy')
;  line_base = widget_base(lineselect_widget,/column,/frame)
;  linelist = cw_bgroup(line_base, (*info).linelist, /return_index, $
;                       /exclusive, event_func = 'xmap_pickline_pick')
;  widget_control, lineselect_widget, set_uvalue = info
;  widget_control, lineselect_widget, /realize
;  xmanager, 'Select line', lineselect_widget, $
;             /no_block, group_leader = (*info).tlb
;end

; get the value of the selected line from the line list:
;function xmap_pickline_pick, event
;  widget_control, event.top, get_uvalue = info
;  (*info).line = event.value
;  return, 0
;end

; close Line selection widget
;pro xmap_pickline_destroy, event
;  widget_control, event.top, get_uvalue = info
; if (*info).messenger eq (*info).animenu then begin
;   xmap_anim, event
;  endif
;  widget_control, event.top,/destroy
;end

; Controls the animation event: If only one line,
; start animation, if several line, then pop up
; line selection window first.
;pro xmap_control_anim,event
;  widget_control, event.top, get_uvalue = info
;  if (*info).nwin lt 2 then begin
;    xmap_anim, event
;  endif else begin
;    (*info).messenger = (*info).animenu
;    xmap_pickline, event
;  endelse
;end

; create animation widget and launch animation
pro xmap_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!',/center)
    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

; select color table
pro xmap_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 = 'xmap 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}
        xmap_draw, pseudoevent
      endif
    endcase
  endcase
  widget_control, event.top, set_uvalue = info
end


; select color table
pro xmap_bgr, event
  widget_control, event.top, get_uvalue=info
  ctfile=getenv('SSW')+'/hinode/eis/idl/ancillary/bluegreyred.sav'
  if (file_info(ctfile)).exists then begin
      restore,ctfile,/verb
      tvlct,r,g,b
      (*info).ct=99
  endif else loadct,0
  pseudoevent={widget_button,id:0L, $
               top:event.top, handler:0l, select:1}
  xmap_draw, pseudoevent
  widget_control, event.top, set_uvalue = info
end


; protect colors
pro xmap_protect_colors,event
  widget_control, event.top, get_uvalue = info
  tvlct, (*info).r, (*info).g, (*info).b, (*info).bottom
end

pro xmap_momminslider, event
  widget_control, event.top,get_uvalue=info
  (*info).min=event.value
  pseudoevent={widget_button,id:0L, $
    top:event.top, handler:0l, select:1}
  widget_control,event.top,set_uvalue=info
  xmap_draw,pseudoevent
end

pro xmap_mommaxslider, event
  widget_control, event.top,get_uvalue=info
  (*info).max=event.value
  pseudoevent={widget_button,id:0L, $
    top:event.top, handler:0l, select:1}
  widget_control,event.top,set_uvalue=info
  xmap_draw,pseudoevent
end

; resize main window and set up drawimage
pro xmap_resize, event
  widget_control, event.top ,get_uvalue = info

  ; set up image in it`s original size:
  if (*info).xdim eq 2 then rotate=1 else rotate=4
  if stregex(strlowcase((*info).comment),'moment',/boolean) then begin
    *(*info).data-> getwin, (*info).line, wd
    drawimage = rotate(reform(wd[(*info).dpnr, *, *]),rotate)
;   if (*info).dpnr eq 1 then begin ; velocity
;     (*info).max=30.
;     (*info).min=-30.
;     (*info).ct=99
;   endif else begin
;     (*info).max=max(drawimage)
;     (*info).min=min(drawimage)
;     (*info).ct=0
;   endelse
    (*info).max=max(drawimage)
    (*info).min=min(drawimage)
    (*info).ct=0
    widget_control, (*info).momminslider, set_slider_min=min(drawimage), $
                                          set_slider_max=max(drawimage), $
                                          set_value=min(drawimage)
    widget_control, (*info).mommaxslider, set_slider_min=min(drawimage), $
                                          set_slider_max=max(drawimage), $
                                          set_value=max(drawimage)
    (*info).colorbar_title=(*(*info).aux->getvariablename())[(*info).dpnr]+$
                          ' '+(*(*info).aux->getunit())[(*info).dpnr]
  endif else begin
    wd=float(*(*info).data-> getvar((*info).line))
    lpx=(*(*info).data-> getwd_def())[(*info).line].line_px
    cpx=(*(*info).data-> getwd_def())[(*info).line].cont_px
    sz = size(wd[lpx[0]:lpx[1],*,*])
    csz = size(wd[cpx[0]:cpx[1],*,*])
;
    if (*info).nexpprp eq 1 then begin
      if csz[1] gt 1 then cont = total(wd[cpx[0]:cpx[1],*,*],1)/csz[1] else cont=0.0
      drawimage = rotate(total(wd[lpx[0]:lpx[1],*,*], 1)/sz[1]-cont,rotate)
    endif else begin
;     if csz[1] gt 1 then cont = total(wd[cpx[0]:cpx[1],*,*],1)/csz[1] else cont=0.0
      cont = total(wd[cpx[0]:cpx[1],*,(*info).expindx],1)/csz[1]
      drawimage = rotate(total(wd[lpx[0]:lpx[1],*,(*info).expindx],1)/sz[1]-cont,rotate)
    endelse
    (*info).max=max(drawimage)
    (*info).min=min(drawimage)
    (*info).ct=0
  endelse
; resize if necessary:
  if event.x ne (*info).tlb_xsz or event.y ne (*info).tlb_ysz then begin
    (*info).d_xsz = (event.x - (*info).lcol_xsz-(*info).cb_xsz) > 1
    (*info).d_ysz = event.y
    widget_control, (*info).drawid, xsize = (*info).d_xsz, $
                    ysize = (*info).d_ysz
    widget_control, (*info).colorbarid, draw_ysize = (*info).d_ysz
  endif
  ; resize image and axis if not original image size
  sz = size(drawimage)
  nx = sz(1)
  ny = sz(2)
  if (*info).realsize then begin
    ptr_free,(*info).drawimage
    (*info).drawimage = ptr_new(uintarr(nx, ny))
    *(*info).drawimage = drawimage
    ptr_free,(*info).xscale
    (*info).xscale = ptr_new(nx)
    *(*info).xscale = findgen(nx)
    ptr_free,(*info).yscale
    (*info).yscale = ptr_new(ny)
    *(*info).yscale = findgen(ny)
;   (*info).ypscale = ptr_new(nx)
;   *(*info).ypscale = interpol(findgen(ny), sz[1])
  endif else begin
;    drawimage = congrid(drawimage, (*info).d_xsz, (*info).d_ysz)
;    sz = size(drawimage)
    ptr_free,(*info).xscale
    (*info).xscale = ptr_new(sz(1))
    *(*info).xscale = interpol(findgen(nx), sz(1))
    ptr_free,(*info).yscale
    (*info).yscale = ptr_new(sz(2))
    *(*info).yscale = interpol(findgen(ny), sz(2))
    ptr_free,(*info).drawimage
    (*info).drawimage = ptr_new(uintarr(sz(1), sz(2)))
    *(*info).drawimage = drawimage
;   (*info).ypscale = ptr_new(sz(1))
;   *(*info).ypscale = interpol(findgen(ny), sz(1))
  endelse
  (*info).tlb_xsz = event.x
  (*info).tlb_ysz = event.y
  ; draw image
  pseudoevent={widget_button,id:0L, $
               top:event.top,handler:0l,select:1}
  widget_control,event.top,set_uvalue=info 
  xmap_draw, pseudoevent
end

pro xmap_pixplot, 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
; SUBSTITUTED THE image COMPUTATION BELOW WITH A PROPER USE OF drawimge
; if (*info).comment eq 'moments' then begin
;   *(*info).data-> getwin, (*info).line, wd
; image = wd[*, *, (*info).dpnr]
; endif else begin
;   *(*info).data-> getwin, (*info).line, wd, pos
;   sz = size(wd)
;   image = uintarr(sz(2), (*info).nraster)
;   image = total(wd,1)/sz(1)
; endelse
  ; set up titles for plot
  xytitle = *(*info).aux-> getxytitle()
; varname = *(*info).aux-> getvariablename()
; varname = varname[0]
  varname = (*info).colorbar_title
  case mode of
    0: begin
         return
       end
    1: begin
;           if (*info).xdim eq 2 then rotate=1 else rotate=4
;           xlineplot, rotate(image,rotate), $
            xlineplot, *(*info).drawimage, $
                      xscale=*(*info).xscale, $
                      xtitle = xytitle[(*info).xdim], $
                      ytitle = varname, $
                      cslider_title = xytitle[(*info).ydim], $
                      groupl = (*info).tlb
       end
    2: begin
;           xlineplot, rotate(transpose(image),3) , $
            xlineplot, transpose(*(*info).drawimage), $
;                     xscale=*(*info).ypscale, $
                      xtitle = xytitle[(*info).ydim], $
                      ytitle = varname, $
                      cslider_title = xytitle[(*info).xdim], $
                      groupl = (*info).tlb
       end
    else: print,'xmap_lineplot: Impossible mode!!'
  endcase
end

; save data
pro xmap_save_moments, event
  widget_control, event.top, get_uvalue = info

  if obj_isa(*(*info).data,'eis_moment') then $
  *(*info).data->save,iwin=(*info).linelist
end
 
pro xmap_linedef, event
  widget_control, event.top, get_uvalue = info
  *(*info).data-> getwin, (*info).line, wd, pos
  if pos[0] gt 2147 then begin
    pos[0]=pos[0]-2148
    lambda = ((*(*info).data->getlambda()).scale_a)[pos[0]:pos[0]+pos[1]-1]
  endif else begin
    lambda = ((*(*info).data->getlambda()).scale_b)[pos[0]:pos[0]+pos[1]-1]
  endelse
  xmoment,*(*info).data, wd, (*info).line, lambda, groupl = event.top
  if not (ptr_valid(info)) then return ; if xmap window closes
  pseudoevent={widget_base,id:0l, $
               top:(*info).tlb, handler:0l, x:(*info).tlb_xsz, y:(*info).tlb_ysz}
  xmap_resize, pseudoevent
end
 
; close xmap
pro xmap_destroy, event
  widget_control, event.top,/destroy
end

pro xmap_cleanup, tlb
  widget_control, tlb, get_uvalue = info
  wdelete, (*info).mainpixid
  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 xmap, data, hdr, aux, linelist = linelist, group_leader = group, $
              ncolors = ncolors, filename = filename
  @environment
  if n_params() lt 3 then begin
    message, $
      'xmap: A data object, header object and aux object 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 = ''
  if n_elements(linelist) eq 0 then linelist = 0 
  line = linelist[0]
  ; drawing window size in relation to screen
    if n_elements(scfac) eq 0 then scfac=0.6
  screensize=get_screen_size()
  sz=screensize*scfac
  xsz = sz[0]
  ysz = sz[1]

  ; get axis titles:
  ydim = 1
  sit_and_stare = data->getsit_and_stare()
  if sit_and_stare then xdim = 3 else xdim = 2

  nwin=data->getnwin()
  nraster = data->getnraster()   ; number of raster positions
  nslit = data-> getyw()         ; number of slit positions
  nslit = nslit[line]
  nexp = data-> getnexp()
  nexpprp = data->getnexp_prp()  ; number of exp pr. raster pos.

  ; 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  
  expindx = 0
  exprp = 0
  ; check if more than one exposure/raster pos. If not return
  if (sit_and_stare) then begin 
    if nexp le 1 then begin
      warning = 'Less than 2 exposures in raster. Can not build map. Returning'     
      ok = dialog_message(warning,/center)
      return
    endif
    case data->getdatasource() of
      'fits': exp=(data->getexp())[0]
      'ccsds': exp=(hdr[0]->getexp_info()).exp_dur/100.
      else: exp=1.0
    endcase
    origin = [0.0,0.0]
    scale = [exp,1.0] 
    xscale = indgen(nexp)*scale[0]*exp+origin[0]
    yscale = indgen(nslit)*scale[0]+origin[0]
;   ypscale = yscale  
    aspect = scale[0]/10.*float(nexp)/scale[1]/float(nslit)
  endif else begin
    if nraster le 1 then begin
      warning = 'Less than 2 raster pos. in raster. Can not build map. Returning'
      ok = dialog_message(warning,/center)
      return
    endif
    origin = [0.0,0.0]
    scale = [1.0,1.0] 
    xscale = indgen(nraster)*scale[0]+origin[0]
    yscale = indgen(nslit)*scale[0]+origin[0]
;   ypscale = yscale
    aspect = (data->getdx_size())*float(nraster)/scale[1]/float(nslit)
 endelse

  if nexpprp gt 1 then begin
    exprp = 1 ; intitialize first exp at each raster pos.
    expindx = indgen(nraster)*nexpprp + exprp - 1
  endif

  data->getwin, line, wd, pos
  comment = data-> getcomment()
  if stregex(strlowcase(comment),'moment',/boolean) then begin
; line/cont limits defined in xmoments
  endif else begin
; line/cont limits reset
    data->setline_px,line,[0,(size(wd))[1]-1]
    data->setcont_px,line,[0,0]
  endelse
  
  xsz = aspect*ysz
  calc_xysize,xsz,ysz,d_xsz,d_ysz
; initialize size of draw window:
  window, /pixmap, /free, xsize = d_xsz, ysize = d_ysz
  pixid = !d.window

  ; base widget:
  xwt = 'XMap - '+aux-> gettitle() + '   '   ; xmap 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 = 'xmap_ps')
  jpgmenu=widget_button(savemenu, value='JPG', event_pro = 'xmap_jpeg')
  exitmenu=widget_button(filemenu, value='Close', $
                         event_pro='xmap_destroy')

  optmenu=widget_button(menubar,value='Options', uvalue='options')
  colmenu=widget_button(optmenu, value='Colour table', $
                                 event_pro='xmap_colors')
  colmenu=widget_button(optmenu, value='Color table BGR', $
                                 event_pro='xmap_bgr')
  ;display window:
  displaybase = widget_base(rcol, /row)
  drawid=widget_draw(displaybase, retain = 2,$
                     xsize = d_xsz, ysize = d_ysz, $
                     /button_events, event_pro='xmap_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)

  if stregex(strlowcase(comment),'moment',/boolean) then begin
    colorbar_title=(aux->getvariablename())[0]+' '+(aux->getunit())[0]
  endif else begin
    colorbar_title=data->gettitle()+' '+(data->getunit())[0]
  endelse

  ; 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 = 'xmap_dwoption')

;  sliderbase = widget_base(lcol, /column)
;
;  rslider = -1
;  if nraster gt 1 or ntime gt 1 then begin
;    nr = nraster > ntime
;    title = 'Exposure nr'
;    rslider = widget_slider(sliderbase, xsize=120, $
;                            minimum=0, maximum=nr-1, $
;                            title='Exposure #', $
;                            value=0, $
;                            event_pro='xmap_rslider',/drag)
;  endif

  lsubcol = widget_base(lcol, /row)
  if nexpprp gt 1 then begin
    sliderbase = widget_base(lsubcol, /column)
    exprp = 1
    expprpslider = widget_slider(sliderbase, xsize = 90, $
                                 minimum = 1, maximum = nexpprp, $
                                 title = 'Exp.# at rast. pos.', $
                                 value = 1, $
                                 event_pro = 'xmap_expprp_slider')
  endif

  id = (hdr[0]-> getline_id())[line]
  idbase = widget_base(lsubcol,/col)
  idtext = widget_label(idbase,value = strtrim(id,2),/align_left)
  
  exposurebase = widget_base(idbase,/col)
  exposuretext = widget_label(exposurebase, $
    value = 'Exp = '+strtrim(string((data->getexp())[0],format='(a,f5.2)'),2)+' s', $
    /align_left)
  
  aux_data=data->getaux_data()
  fmirr=*aux_data.fmirr
  fmirrbase = widget_base(idbase,/col)
  fmirrtext = widget_label(fmirrbase, $
    value = 'Fine mirror: '+ string(fmirr[0],format='(i4)')+  $
                       ' - '+string(fmirr[n_elements(fmirr)-1],format='(i4)'), $
    /align_left)
    
  xycenbase = widget_base(idbase,/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
    
  pixplotfield = widget_base(lcol, /column, /frame)
  pixnames = ['Not active', 'Row plot', 'Column plot']
  pixelplot = widget_droplist(pixplotfield, value = pixnames, $
                              title = 'Plot pixel values', $
                              event_pro = 'xmap_pixplot')

  ; create droplist menu for selecting line
  if n_elements(linelist) gt 1 then begin
    ll = widget_base(lcol, /column, /frame)
    ll_title = 'Select line'
    ll_names = (hdr[0]-> getline_id())[linelist]
    ll_menu = widget_droplist(ll, value = ll_names, title = ll_title, $
                               event_pro = 'xmap_lineselect')
  endif
  
  if not sit_and_stare then begin 
    dsbase = widget_base(lcol, /row, /frame)
    ds_names = ['Pixels/step', 'Arcsec']
    dsbutton = cw_bgroup(dsbase, ds_names, /return_index, $
                            /exclusive, set_value = 0, $
                            event_func = 'xmap_dsoption')
  endif
                            
  ; create menu for selecting data product (if moments/gauss_fit):
  comment = data-> getcomment()
  if stregex(strlowcase(comment),'moment',/boolean) then begin
    dp_base = widget_base(lcol, /column, /frame)
    dp_title = 'Select data'
    dp_names = aux-> getvariablename()
    dp_names = dp_names[where (dp_names ne '')]
    dp_menu = widget_droplist(dp_base, value = dp_names, title = dp_title, $
                              event_pro = 'xmap_dpselect')

    min = min(wd[0, *, *])
    max = max(wd[0, *, *])
    mommintitle = 'Minimum plot value'
    mommaxtitle = 'Maximum plot value'
    momminslider = widget_slider(dp_base, xsize=120, $
                          minimum=fix(min), maximum=fix(max), $
                          title=mommintitle, $
                          value=fix(min), $
                          event_pro = 'xmap_momminslider', /drag)
    mommaxslider = widget_slider(dp_base, xsize=120, $
                          minimum=fix(min), maximum=fix(max), $
                          title=mommaxtitle, $
                          value=fix(max), $
                          event_pro = 'xmap_mommaxslider', /drag)

  endif else begin
    momminslider=-1
    mommaxslider=-1
  endelse

  buttonrow1=widget_base(lcol,/row)
  if stregex(strlowcase(comment),'moment',/boolean) then begin
    savefield = widget_base(buttonrow1, /column)
    savebutton = widget_button(savefield, value = 'Save Moments', $
                               event_pro = 'xmap_save_moments')
  endif else begin
    linedeffield=widget_base(buttonrow1,/column)
    linedefbutton=widget_button(linedeffield,value='Define Line', $
                              event_pro = 'xmap_linedef')
  endelse
  closefield = widget_base(buttonrow1, /column)
  closebutton = widget_button(closefield, value = 'Close     ', $
                              event_pro = 'xmap_destroy')
                              
  eis_icon_base=widget_base(lcol,/col)
  eis_icon                   = widget_draw(eis_icon_base  ,             $
                                retain      = 2,                        $ 
                                XSize       = 210,                      $
                                YSize       = 105,                      $
                                frame       = 1)  

  ; 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

  ; define the info structure, used send information around
  info = {drawimage:ptr_new(), $
          xscale:ptr_new(), $
          yscale:ptr_new(), $
;         ypscale:ptr_new(), $
          origin:origin, $
          scale:scale, $
          max:0.0,$ 
          min:0.0,$
          ct:0,$
          data:ptr_new(data), $
          hdr:ptr_new(hdr), $
          aux:ptr_new(aux), $
          exposuretext:exposuretext, $
          fmirrtext:fmirrtext, $
          xycentext:xycentext, $
          xdim:xdim, $
          ydim:ydim, $
          nwin:nwin, $
          nraster:nraster, $
          nexp:nexp, $
          nexpprp:nexpprp, $
          exprp:exprp, $
          expindx:expindx, $
          rpos:0, $
          line:line, $
          linelist:linelist, $
          dpnr:0, $
          comment:comment, $
          screensize:screensize, $
          lcol_xsz:lcol_xsz, $
          d_xsz:d_xsz, $
          d_ysz:d_ysz, $
          x_scroll_size:d_xsz, $
          y_scroll_size:d_ysz, $
          cb_xsz:cb_xsz, $
          tlb:tlb, $
          tlb_xsz:tlb_xsz, $
          tlb_ysz:tlb_ysz, $
          realsize:1, $
          lcol:lcol, $
          rcol:rcol,  $
          r:r, g:g, b:b, $
          bottom:bottom, $
          ncolors:ncolors, $
          sx:0, $
          sy:0, $
          messenger:0, $
          dwoption:0, $
          dwoption_menu:dwoption_menu, $
          drawid:drawid, $
          colorbarid:colorbarid, $
          colorbar_title:colorbar_title,$
          pixelplot:pixelplot,  $
          drawcolor:drawcolor, $
          mainpixid:pixid, $
          pixid:pixid, $
          xtitle:' ', $
          ytitle :' ', $
          momminslider:momminslider,$
          mommaxslider:mommaxslider,$
          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
  
  
  widget_control, eis_icon , get_value = drawID
  wset,drawID
  fileName = concat_dir(GETENV('ancillary') , 'eis_logo_sarah_small.jpg')
  read_jpeg , filename , icon
  icon_resized = CONGRID(icon,3,210,105)
  tvscl,icon_resized , true = 1

  ; create pseudoevent and send this event to xmap_draw,
  ; in order to draw the image
  pseudoevent={widget_base,id:0l, $
               top:tlb, handler:0l, x:tlb_xsz, y:tlb_ysz}
  xmap_resize, pseudoevent

  xmanager, 'ql', tlb, /no_block, event_handler = 'xmap_resize', $
            group_leader = group, cleanup = 'xmap_cleanup'

end
