;+
; NAME:
;       XDETECTOR
;
; PURPOSE:
;
;       XDETECTOR 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:
;       xdetector, 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:
;       group_leader: Widget parent (if any).
;       ncolors: Number of colors for xdetector. Default is
;                !d.n_colors<256.
;
;
; OUTPUTS:
;       None
;
; CALLS:
;
;
; COMMON BLOCKS:
;
;
; PROCEDURE:
;       XDETECTOR 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. XDETECTOR 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.
;       20-APR-2004: Oivind Wikstol - Added funtions to change
;                                     wavl. scale [pix/Angstr.]
;       29-Sep-2007: A. Gardini     - Added some cleanup and some minor 
;                                     changes.Other changes already set in 
;                                     June 2007.
;        3-Dec-2007: A. Gardini     - Freed pointers.    
;        9-May-2008: A. Gardini     - Added check on filenames of movies.
;       28-Nov-2008: A. Gardini     - Fixed image in xdetector_zoom.
;       30-Apr-2009: A. Gardini     - Fixed 1 pixel shift error.
;
; $Id: xdetector.pro,v 1.17 2009/04/30 09:02:08 gardini Exp $
;-
;
; save as postscript file
pro xdetector_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
  xdetector_draw, pseudoevent
  device,/close_file
  set_plot,thisdevice
end

; save as jpeg file
pro xdetector_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 xdetector_draw, event
  widget_control, event.top, get_uvalue = info
  if !d.name ne 'PS' then  wset, (*info).wid
  erase
    xs = !x.margin[0]*!d.x_ch_size
    ys = !y.margin[0]*!d.y_ch_size
    tv, bytscl(*(*info).drawimage), xs, ys
   plot, *(*info).xscale, *(*info).yscale, /nodata, xstyle = 1, $
         ystyle = 1, /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 = 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.01, 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 xdetector_dwoption, event
  widget_control, event.top, get_uvalue = info
  (*info).dwoption = event.value
  return, 0
end

; wavelength selection buttons
function xdetector_wloption, event
  widget_control, event.top,get_uvalue=info
  case event.value of
  0: xdetector_wpix, event
  1: xdetector_wangstr, event
  endcase
  return,0
end

; slider to select exposure number
pro xdetector_expslider, event
  widget_control, event.top,get_uvalue=info
  (*info).expnr=event.value
  nr=(*info).expnr
  ; read new data (for selected position) into detector variable
  for i=0,(*info).nwin-1 do begin
    *(*info).data->getwin, (*info).lindx[i], wd, pos
    if pos[0] gt 2147 then pos[0] = pos[0]-2148
    (*info).detector[pos[0]:pos[0]+pos[1]-1,pos[2]:pos[2]+pos[3]-1] = $
            wd[*, *, nr]
  endfor

; update exposure time and fine mirror
  
  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 raster position
  
  pseudoevent={widget_base,id:0L, $
    top:event.top, handler:0l, x:(*info).tlb_xsz,  y:(*info).tlb_ysz}
  widget_control, event.top, set_uvalue=info
  xdetector_resize, pseudoevent
end

; slider to select exposure within a raster pos (if multiple)
pro xdetector_expprp_slider, event
  widget_control, event.top,get_uvalue=info
  (*info).exprp=event.value
  (*info).expnr = (*info).nexpprp*((*info).rpos - 1) + (*info).exprp - 1
  nr=(*info).expnr
  
; read new data (for selected exposure) into detector variable
  for i=0,(*info).nwin-1 do begin
    *(*info).data->getwin, (*info).lindx[i], wd, pos
    if pos[0] gt 2147 then pos[0] = pos[0]-2148
    (*info).detector[pos[0]:pos[0]+pos[1]-1,pos[2]:pos[2]+pos[3]-1] = $
            wd[*, *, (*info).expnr]
  endfor
  
; update exposure time and fine mirror

  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 raster position
      
  pseudoevent={widget_base,id:0L, $
    top:event.top, handler:0l, x:(*info).tlb_xsz,  y:(*info).tlb_ysz}
  widget_control, event.top, set_uvalue=info
  xdetector_resize, pseudoevent
end

; slider to select raster position (used only when multiple exp
; pr. rast. pos)
pro xdetector_rast_slider, event
  widget_control, event.top,get_uvalue=info
  (*info).rpos = event.value
  (*info).expnr = (*info).nexpprp*((*info).rpos - 1) + (*info).exprp - 1
  nr=(*info).expnr
  
; read new data (for selected exposure) into detector variable
  
  for i=0,(*info).nwin-1 do begin
    *(*info).data->getwin, (*info).lindx[i], wd, pos
    if pos[0] gt 2147 then pos[0] = pos[0]-2148
    (*info).detector[pos[0]:pos[0]+pos[1]-1,pos[2]:pos[2]+pos[3]-1] = $
            wd[*, *, (*info).expnr]
  endfor
  
; update exposure time and fine mirror

  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 raster position
  pseudoevent={widget_base,id:0L, $
    top:event.top, handler:0l, x:(*info).tlb_xsz,  y:(*info).tlb_ysz}
  widget_control, event.top, set_uvalue=info
  xdetector_resize, pseudoevent
end



; zoom in draw window:
pro xdetector_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'

  events=['down','up','motion']
  thisevent=events[event.type]
  window, /pixmap, /free, xsize = (*info).d_xsz, ysize = (*info).d_ysz
  if (*info).realsize then $
     window, /pixmap, /free, xsize = (*info).xvs, ysize = (*info).yvs
;  imagepos = [0.10, 0.15, 0.95, 0.9]
  xs = !x.margin[0]*!d.x_ch_size
  ys = !y.margin[0]*!d.y_ch_size
  tv, bytscl(*(*info).drawimage), xs, ys
;  tvimage, bytscl(*(*info).drawimage), position = imagepos, /erase, /nointerp
  plot, *(*info).xscale, *(*info).yscale, /nodata, xstyle = 1, ystyle = 1, $
        /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
;       dxfac = 1./(imagepos[2]-imagepos[0])
;       dyfac = 1./(imagepos[3]-imagepos[1])
       sx = (*info).sx - xs
       sy = (*info).sy - ys
       dx = event.x - xs
       dy = event.y - ys
;       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).xps - 1)) > 0
       sy = (sy < ((*info).yps - 1)) > 0
       dx = (dx < ((*info).xps - 1)) > 0
       dy = (dy < ((*info).yps - 1)) > 0
       image = *(*info).drawimage
       detector = (*info).detector
       imagesize=size(image)
       detsize=size(detector)
       xrescale = float(detsize(1))/float(imagesize(1))
       yrescale = float(detsize(2))/float(imagesize(2))
       detsx = round(sx * xrescale)     
       detsy = round(sy * yrescale)     
       detdx = round(dx * xrescale)     
       detdy = round(dy * yrescale)     
       x1 = detsx<detdx
       x2 = detsx>detdx
       y1 = detsy<detdy
       y2 = detsy>detdy
;      xscale = *(*info).xscale
;      yscale = *(*info).yscale
;      xscale = xscale[sx<dx:sx>dx]
;      yscale = yscale[sy<dy:sy>dy]
;      image=image[sx<dx:sx>dx,sy<dy:sy>dy]
       xscale = (*info).lambda[x1:x2]
       yscale = indgen(y2-y1+1)+y1
       image = detector[x1:x2,y1:y2]
       sz=size(image)
       mind = min(sz[0:2])
;      pos=[sx<dx,sx>dx,sy<dy,sy>dy]
       pos=[x1,x2,y1,y2]
       
       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).ytitle, $
                             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] +': column average'
                dmean = total(image, 2)/sz[2]
                if sz[0] ge 2 then begin
                  xlineplot, dmean, xscale = xscale, $
                             title = varname, $
                             xtitle = (*info).xtitle, $
                             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]
         if (*info).realsize then $
           device,copy=[0,0,(*info).xvs,(*info).yvs,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 xdetector_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,xoff=200,yoff=200)
  closefield = widget_base(lineselect_widget,/column)
  closebutton = widget_button(closefield, value = 'OK', $
                              event_pro = 'xdetector_pickline_destroy')
  line_base = widget_base(lineselect_widget,/column,/frame)
  linelist = cw_bgroup(line_base, (*info).linelist, /return_index, $
                       /exclusive, event_func = 'xdetector_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 xdetector_pickline_pick, event
  widget_control, event.top, get_uvalue = info
  defdir = ''
  (*info).line = event.value + (*info).lindx[0]
  return, 0
end

; close Line selection widget
pro xdetector_pickline_destroy, event
  widget_control, event.top, get_uvalue = info
   xdetector_anim, event
  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 xdetector_control_anim,event
  widget_control, event.top, get_uvalue = info
  if (*info).nwin lt 2 then begin
    xdetector_anim, event
  endif else begin
    xdetector_pickline, event
  endelse
end

; create animation widget and launch animation
pro xdetector_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:
  ct=0
  repeat begin
    ct=ct+1
    afile = 'adata'+strtrim(string(ct),2)+'.dat'
  endrep until ((findfile(afile))[0] eq '')
  
  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 xdetector_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]
  ; set scale for images
  if((*info).det_a) then xscale = findgen(2148)+2148 else xscale= findgen(2148)
  (*info).lambda = xscale
  pseudoevent={widget_base,id:0L, $
               top:event.top, handler:0l, x:(*info).tlb_xsz, y:(*info).tlb_ysz}
  xdetector_resize, pseudoevent
end

; change wavelength scale to Angstrom
pro xdetector_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]

  lambda_struct = *(*info).data-> getlambda()
  if (*info).det_a then lambda = lambda_struct.scale_a else $
     lambda = lambda_struct.scale_b 

  (*info).lambda = lambda
  pseudoevent={widget_base,id:0L, $
               top:event.top, handler:0l, x:(*info).tlb_xsz, y:(*info).tlb_ysz}
  xdetector_resize, pseudoevent
end

; select color table
pro xdetector_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 = 'xdetector 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}
        xdetector_draw, pseudoevent
      endif
    end
  endcase

  widget_control, event.top, set_uvalue = info
end

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

; resize main window
pro xdetector_resize, event
  widget_control, event.top ,get_uvalue = info
  (*info).tlb_xsz = event.x
  (*info).tlb_ysz = event.y
  (*info).d_xsz = (event.x - (*info).lcol_xsz-(*info).cb_xsz) > 0
  (*info).d_ysz = event.y
  if(*info).realsize then begin
    xvs = (*info).ccd_xsz + total(!x.margin)*!d.x_ch_size
    yvs = (*info).ccd_ysz + total(!y.margin)*!d.y_ch_size
;    calc_xysize, (*info).ccd_xsz, (*info).ccd_ysz, xvs, yvs
    widget_control, (*info).drawid, $
                    draw_xsize = xvs,  draw_ysize = yvs
    (*info).xvs = xvs
    (*info).yvs = yvs
    (*info).xps = (*info).ccd_xsz  ; x-plot-size 
    (*info).yps = (*info).ccd_ysz  ; y-plot-size
    drawimage = (*info).detector
    xscale = (*info).lambda
    yscale = findgen((*info).ccd_ysz)
    ptr_free,(*info).xscale
    ptr_free,(*info).yscale
    ptr_free,(*info).drawimage
    (*info).xscale = ptr_new((*info).ccd_xsz)
    (*info).yscale = ptr_new((*info).ccd_ysz)
    (*info).drawimage = ptr_new(uintarr((*info).ccd_xsz, (*info).ccd_ysz))
    *(*info).drawimage = drawimage
    *(*info).xscale = xscale
    *(*info).yscale = yscale
  endif else begin
   (*info).xps = (*info).d_xsz - total(!x.margin)*!d.x_ch_size  ; x-plot-size
    (*info).yps = (*info).d_ysz - total(!y.margin)*!d.y_ch_size  ; y-plot-size
    widget_control, (*info).drawid, xsize = (*info).d_xsz, $
    ysize = (*info).d_ysz, draw_xsize = (*info).d_xsz, $
    draw_ysize = (*info).d_ysz
    xscale = (*info).lambda
    yscale = findgen((*info).ccd_ysz)
    ;   clutch to avoid bug in idl congrid function
    if (*info).ccd_ysz gt 1024 then begin
      detector=rebin((*info).detector(*, *),(*info).ccd_xsz/4, $
                    (*info).ccd_ysz/4,/sample)
    endif else begin
      detector = (*info).detector
    endelse
    ptr_free,(*info).xscale
    ptr_free,(*info).yscale
    ptr_free,(*info).drawimage
    drawimage = congrid(detector, (*info).xps, (*info).yps)
    (*info).xscale = ptr_new((*info).yps)
    (*info).yscale = ptr_new((*info).xps)
    *(*info).xscale = interpol(xscale, (*info).xps)
    *(*info).yscale = interpol(yscale, (*info).yps)
    (*info).drawimage = ptr_new(uintarr((*info).xps, (*info).yps))
    *(*info).drawimage = drawimage
  endelse

  widget_control, (*info).colorbarid, draw_ysize = (*info).d_ysz < (*info).yps
  pseudoevent={widget_button,id:0L, $
               top:event.top,handler:0l,select:1}
  xdetector_draw, pseudoevent
end

pro xdetector_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
  ; set up titles for plot
  varname = *(*info).aux-> getvariablename()
  varname = varname[0]
  case mode of
    0:begin
        return
      end
    1: begin
            data = (*info).detector(*, *)
            xlineplot, data, xscale = (*info).lambda, $
                       xtitle = (*info).xtitle, $
                       cslider_title = (*info).ytitle, $
                       ytitle = varname, $
                       groupl = (*info).tlb
       end
    2: begin
            data = transpose((*info).detector(*, *))
            xlineplot, data, xtitle = (*info).ytitle, $
                       cslider_title = (*info).xtitle, $
                       ytitle = varname, $
                       groupl = (*info).tlb
       end
  endcase
end

; control real size ccd display or not:
pro xdetector_realsize, event
  widget_control, event.top, get_uvalue = info
  (*info).realsize = event.select
; create resize event to resize draw widget
  pseudoevent={widget_base,id:0l, $
               top:(*info).tlb, handler:0l, x:(*info).tlb_xsz, y:(*info).tlb_ysz}
  xdetector_resize, pseudoevent
end

; close xdetector
pro xdetector_destroy, event
  widget_control, event.top,/destroy
end

pro xdetector_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
end

pro xdetector, data, hdr, aux, lindx, group_leader = group, $
               ncolors = ncolors, filename = filename
  @environment
  if n_params() lt 4 then begin
    message, $
      'xdetector: A data object, header object, aux object and line index arraymust 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
  ccd_sz=data->getccd_sz()
  d_xsz = sz[0]
  d_ysz = sz[1]
  nwin = n_elements(lindx)
  nraster = data->getnraster()   ; number of raster positions
  nexp = data->getnexp()
  ntime = data-> getntime()      ;
  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.
  sit_and_stare = data-> getsit_and_stare()
  if sit_and_stare then nexpprp = 1  
  nslit = (data-> getyw())[0]
  ys = (data-> getys())[0]
  ccd_sz=data->getccd_sz()
  ccd_sz[0] = ccd_sz[0]/2
  detector = fltarr(ccd_sz[0], ccd_sz[1])

  det_a = 0
  for i=0,nwin-1 do begin
   data->getwin, lindx[i], wd, pos
    if pos[0] gt 2147 then begin
      pos[0] = pos[0]-2148
      det_a = 1
      pscale = findgen(2148)+2148
    endif else begin
      pscale= findgen(2148)
    endelse
    detector(pos[0]:pos[0]+pos[1]-1,pos[2]:pos[2]+pos[3]-1)=wd(*, *, 0)
  endfor
  
  ; get wavelengtgth scale for detector B (170-215 Å)
  ; or A (250-295 Å)
  ; so far they are in pixels
  lambda_struct = data-> getlambda()

  if det_a then lambda = lambda_struct.scale_a else $
     lambda = lambda_struct.scale_b

  ; check if wavl. scale is in pixels or Angstr. (set in aux object)
  ; if 'pixels' then change lambda to pscale
  scale = aux->getwscale()
  if scale eq 'pixels' then lambda = pscale

  ;create linelist
  
  wnames = (hdr[0]-> getline_id())[lindx]
  
; get x and y titles for axis plots:
  xytitle = aux-> getxytitle()
  xdim = 0
  ydim = 1
  xtitle = (aux-> getxytitle())[xdim]
  ytitle = (aux-> getxytitle())[ydim]
  ; initialize size of draw window (ccd display):
  window, /pixmap, /free, xsize = d_xsz, ysize = d_ysz
  tv, bytscl(detector, top = ncolors)
  pixid = !d.window

  ; base widget:
  xwt = 'Xdetector - ' + aux-> gettitle() + '   '  ; xdetector 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 = 'xdetector_ps')
  jpgmenu=widget_button(savemenu, value='JPG', event_pro = 'xdetector_jpeg')
  exitmenu=widget_button(filemenu, value='Close', $
                         event_pro='xdetector_destroy')

  optmenu=widget_button(menubar,value='Options', uvalue='options')
  colmenu=widget_button(optmenu, value='Colour table', $
                                 event_pro='xdetector_colors')
  animenu=widget_button(optmenu, value='Create Animation', $
                                 event_pro='xdetector_control_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='xdetector_wpix')
  angstrmenu=widget_button(wscalemenu, value=angstr,event_pro='xdetector_wangstr')

  ;display window:
  displaybase = widget_base(rcol, /row)
  drawid=widget_draw(displaybase, retain = 2,$
                     xsize = d_xsz, ysize = d_ysz, $
                     x_scroll_size = d_xsz, y_scroll_size = d_ysz, $
                       /button_events, event_pro='xdetector_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
  dwoption_names = [menu[0], menu[1], menu[2]]
  dwoption_menu = cw_bgroup(dwoption, dwoption_names, /return_index, $
                            /exclusive, set_value = 0, $
                            event_func = 'xdetector_dwoption')

  lsubcol0 = widget_base(lcol, /row)
  sliderbase = widget_base(lsubcol0,/col)
  expslider = -1
  if nexp gt 1 then begin
    if nexpprp le 1 then begin 
      nr = nexp
      title = 'Exposure nr'
      expslider = widget_slider(sliderbase, xsize=90, $
                              minimum=0, maximum=nr-1, $
                              title='Exp # ', $
                              value=0, $
                              event_pro='xdetector_expslider',/drag)
    endif else begin
      exprp = 1
      expprpslider = widget_slider(sliderbase, xsize = 120, $
                                minimum = 1, maximum = nexpprp, $
                                title = 'Exp # at rast. pos.', $
                                value = 1, $
                                event_pro = 'xdetector_expprp_slider')

      rpos = 1
      rastposslider = widget_slider(sliderbase, xsize = 120, $
                                minimum = 1, maximum = nraster, $
                                title = 'Raster position', $
                                value = 1, $
                                event_pro = 'xdetector_rast_slider')
    endelse
  endif
  
  exposurebase = widget_base(lsubcol0,/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
  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 = 'xdetector_lineplot')
                              
  lsubcol1 = widget_base(lcol, /row)
  colorbase = widget_base(lsubcol1,/col)
  colorbutton=widget_button(colorbase, value='Colour table', $
                                 event_pro='xdetector_colors')
  animbase = widget_base(lsubcol1,/col)
  animbutton=widget_button(animbase, value='Create Animation', $
                                event_pro='xdetector_control_anim')
                                
  wlbase = widget_base(lcol, /row, /frame)
  angstr = string("305B)+'ngstr'+string("370B)+'m'
  wl_names = ['Pixels', angstr]
  wlbutton = cw_bgroup(wlbase, wl_names, /return_index, $
                            /exclusive, set_value = 0, $
                            event_func = 'xdetector_wloption')
                                
  realsizefield = widget_base(lcol, /column, /nonexclusive)
  realsizebutton = widget_button(realsizefield, $
                   value = 'Real size CCD display', $
                    event_pro = 'xdetector_realsize')
  closefield = widget_base(lcol, /column)
  closebutton = widget_button(closefield, value = 'Close', $
                              event_pro = 'xdetector_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

  ; set realsizebutton to de-select:
  widget_control, realsizebutton, set_button = 0
  imagepos = [0.01, 0.04, 0.99, 0.99]
  ; 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 = {detector:detector, $
          drawimage:ptr_new(), $
          xscale:ptr_new(), $
          yscale:ptr_new(), $
          data:ptr_new(data), $
          hdr:ptr_new(hdr), $
          aux:ptr_new(aux), $
          exposuretext:exposuretext, $
          fmirrtext:fmirrtext, $
          xycentext:xycentext, $
          ccd_xsz:ccd_sz[0], $
          ccd_ysz:ccd_sz[1], $
          xdim:0, $
          ydim:1, $
          det_a:det_a, $
          nwin:nwin, $
          lindx:lindx, $
          nraster:nraster, $
          nexp:0, $
          nexpprp:nexpprp, $
          exprp:1, $
          rpos:1, $
          ntime:ntime,  $
          nslit:nslit, $
          ys:ys, $
          expnr:0, $
          imagepos:imagepos, $
          line:0, $
          lambda:lambda, $
          screensize:screensize, $
          realsize:0, $
          lcol_xsz:lcol_xsz, $
          d_xsz:d_xsz, $
          d_ysz:d_ysz, $
          xps:0, $
          yps:0, $
          xvs:0, $
          yvs:0, $
          cb_xsz:cb_xsz, $
          tlb:tlb, $
          tlb_xsz:tlb_xsz, $
          tlb_ysz:tlb_ysz, $
          lcol:lcol, $
          rcol:rcol,  $
          r:r, g:g, b:b, $
          bottom:bottom, $
          ncolors:ncolors, $
          sx:0, $
          sy:0, $
          linelist:wnames, $
          dwoption:0, $
          dwoption_menu:dwoption_menu, $
          animenu:animenu, $
          drawid:drawid, $
          colorbarid:colorbarid, $
          colorbar_title:colorbar_title,$
          pixelplot:pixelplot,  $
          drawcolor:drawcolor, $
          mainpixid:pixid, $
          pixid:pixid, $
          xtitle:xtitle, $
          ytitle :ytitle, $
          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 xdetector_draw,
  ; in order to draw the image
  pseudoevent={widget_base,id:0l, $
               top:tlb, handler:0l, x:tlb_xsz, y:tlb_ysz}
  xdetector_resize, pseudoevent
;  xdetector_draw, pseudoevent

                       
  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

  xmanager, 'ql', tlb, /no_block, event_handler = 'xdetector_resize', $
            group_leader = group, cleanup = 'xdetector_cleanup'

end

