; $Id: dcs_mslice.pro,v 1.109 2008/03/19 20:46:50 ymqiu Exp $
;#######################################################################
;
; NAME:
;  dcs_mslice
;
; PURPOSE:
;  Viewing and analyzing neutron time-of-flight data.
;
; CATEGORY:
;  dcs time-of-flight
;
; history:
;  06/2003: IDL5.6 compatible, include all functionality of matlab mslice, and windows .hlp help file
;  10/2003: IDL6.0 compatible, add diffuse scattering type, and dcs_mslice.pdf help file
;  09/2004: Make IDL dcs_mslice extendable to other TOF instruments, documentation in dcs_mslice_addftype.pdf
;  06/2005: IDL6.1 compatible, add diffuse scattering multiple energy type, rearange sample types
;  11/2005: Remove some items in the droplists, and add extra HKL range limitation
;  03/2006: Add INX file type
;  03/2007: Add grouped data fitting in powder mode, i.e. add QENS data reduction
;           modifications in background subtraction, especially the treatment of dark count files
;  07/2007: Add empty can subtraction from vanadium file in the first two sample types
;           Add automatic Bragg peak masking
;  02/2008: Compatible with inverse geometry TOF instruments
;  ??/2008: Add MACS
;
; AUTHOR:
;  Yiming Qiu
;  NIST Center for Neutron Research
;  100 Bureau Drive, Gaithersburg, MD 20899-6102
;  United States
;  yiming.qiu@nist.gov
;  March, 2008
;
; LICENSE:
;  The software in this file is written by an employee of
;  National Institute of Standards and Technology
;  as part of the DAVE software project.
;
;  The DAVE software package is not subject to copyright protection
;  and is in the public domain. It should be considered as an
;  experimental neutron scattering data reduction, visualization, and
;  analysis system. As such, the authors assume no responsibility
;  whatsoever for its use, and make no guarantees, expressed or
;  implied, about its quality, reliability, or any other
;  characteristic. The use of certain trade names or commercial
;  products does not imply any endorsement of a particular product,
;  nor does it imply that the named product is necessarily the best
;  product for the stated purpose. We would appreciate acknowledgment
;  if the DAVE software is used or if the code in this file is
;  included in another product.
;
;#######################################################################

;files need to be included
@dm_calc_projection
@dm_choose_cutdata
@dm_choose_slicedata
@dm_choose_trajdata
@dm_det_spurion
@dm_filemenu
@dm_filetools
@dm_load_parameter
@dm_mask_detbanks
@dm_plot_cut
@dm_plot_slice
@dm_plot_trajectory
@dm_save_parameter
@dm_to_fit
@dcs_plotdetmask    ;for plotting masks

;kill the object
pro dcs_mslice_Exit,tlb
    widget_control,tlb,get_uvalue=self
    if obj_valid(self) then obj_destroy,self
end

;widget event handler
pro dcs_mslice_event,event
    widget_control,event.handler,get_uvalue=self
    if obj_valid(self) then self->event,event
end

;absorption correction
;varible:
;   type: -1-none 0-cylinder 1-annulus 2-sphere
pro dcs_mslice::absorption,type
    abspNon = widget_info(self.tlb,find_by_uname='abspNone')
    abspCyl = widget_info(self.tlb,find_by_uname='abspCylinder')
    abspAnn = widget_info(self.tlb,find_by_uname='abspAnnulus')
    abspSph = widget_info(self.tlb,find_by_uname='abspSphere')
    default = [0,!values.f_nan,!values.f_nan,!values.f_nan,!values.f_nan]
    if ptr_valid(self.absp_info) then begin
       ninfo = n_elements(*(self.absp_info))
       default[0:(ninfo-2)] = (*(self.absp_info))[1:(ninfo-1)]
       ptr_free,self.absp_info
    endif
    case type of
          0 :   begin   ;cylinder
                onbut  = abspCyl
                offbut = [abspNon,abspAnn,abspSph]
                names  = ['L0(cm):','L1(cm):','R(cm):','Interpolate:']
                title  = 'Cylindrical geometry'
                end
          1 :   begin   ;annulus
                onbut  = abspAnn
                offbut = [abspNon,abspCyl,abspSph]
                names  = ['L0(cm):','L1(cm):','Rout(cm):','Rin(cm):','Interpolate:']
                title  = 'Annular geometry'
                end
          2 :   begin   ;sphere
                onbut  = abspSph
                offbut = [abspNon,abspAnn,abspCyl]
                names  = ['L0(cm):','L1(cm):','R(cm):','Interpolate:']
                title  = 'Spherical geometry'
                end
        else:   begin   ;none
                onbut  = abspNon
                offbut = [abspAnn,abspCyl,abspSph]
                end
    endcase
    nitem = n_elements(names)
    if nitem ne 0 then begin
       default = [default[1:(nitem-1)],default[0]]
       is_droplist = intarr(nitem) & is_droplist[nitem-1] = 1
       if self.samp_typ ge 2 then default[0]=0 ;no need to interpolate for diffuse scattering type
       mesg = ['L0 is the energy independent mean free path;',$
               'L1 is the energy dependent mean free path for',$
               '2200m/s or 25.3 meV neutron.',$
               'The effective mean free path is:',$
               'L=1/{1/L0+1/(L1*sqrt[E(meV)/25.3])}' ]
       info = dm_dialog_input(names,default=default,/float,info=mesg,$
                is_droplist=is_droplist,droplist_content=ptr_new(['No','Yes']),$
                /return_number,title=title,xsize=140,dialog_parent=self.tlb)
       if total(finite(info)) eq nitem then begin
          self.absp_info=ptr_new([type,info[nitem-1],info[0:(nitem-2)]])
       endif else begin
          onbut  = abspNon
          offbut = [abspAnn,abspCyl,abspSph]
          ok = dialog_message('Invalid inputs. Absorption correction is disabled.',dialog_parent=self.tlb,/error)
       endelse
    endif
    dm_toggle_menubut,onbut,offbut
end

;adjust the viewing axis label according to hkle value
pro dcs_mslice::adjust_viewlabel,uid
    tmp = ([[self.view_u1],[self.view_u2],[self.view_u3]])[*,uid]
    if self.samp_typ ne 1 then tmp[3] = 0
    if tmp[0] ne 0 then $
       label = 'H'      $
    else if tmp[1] ne 0 then $
       label = 'K'      $
    else if tmp[2] ne 0 then $
       label = 'L'      $
    else if tmp[3] ne 0 then $
       label = 'E'
    if n_elements(label) ne 0 then begin
       if uid eq 0 then begin
          self.view_u1lab[1] = label
          self->my_widget_control,'viewU1lab',self.projBas,set_value=label
       endif else if uid eq 1 then begin
          self.view_u2lab[1] = label
          self->my_widget_control,'viewU2lab',self.projBas,set_value=label
       endif else begin
          self.view_u3lab = label
          self->my_widget_control,'viewU3lab',self.projBas,set_value=label
       endelse
    endif
end

;keyword:
;   init: if not set, free some data pointers
pro dcs_mslice::change_samptyp,new_typ,init=init
    old_typ  = self.samp_typ
    self.samp_typ = new_typ
    self->my_widget_control,'showPowder',sensitive=(self.samp_typ ge 2)
    self->my_widget_control,'darkCorr',sensitive=((self.samp_typ ge 2) and (self.ftype eq 0))
    self->my_widget_control,['vaxisMenu','hklRan'],sensitive=(self.samp_typ ne 0)
    self->my_widget_control,'neg2th',sensitive=(self.samp_typ eq 0)
    self->my_widget_control,'bgtcBut',sensitive=(self.samp_typ ne 2)
    if old_typ eq new_typ then return
    sampTyp  = widget_info(self.fileBas,find_by_uname='sampTyp')
    powdBut  = widget_info(self.fileBas,find_by_uname='powdTyp')
    crystTyp = widget_info(self.fileBas,find_by_uname='crystTyp')
    sct1But  = widget_info(self.fileBas,find_by_uname='crystTyp1')
    sct2But  = widget_info(self.fileBas,find_by_uname='crystTyp2')
    sct3But  = widget_info(self.fileBas,find_by_uname='crystTyp3')
    case self.samp_typ of
       0: dm_toggle_menubut,powdBut,[sct1But,sct2But,sct3But]
       1: dm_toggle_menubut,sct1But,[powdBut,sct2But,sct3But]
       2: dm_toggle_menubut,sct2But,[powdBut,sct1But,sct3But]
       3: dm_toggle_menubut,sct3But,[powdBut,sct1But,sct2But]
       else:
    endcase
    sptypes = ['Powder','Single Crystal','Diffuse Scattering Single E','Diffuse Scattering Multiple E']
    widget_control,sampTyp,set_value=sptypes[self.samp_typ]
    if (float(!version.release) ge 5.6) then begin
       widget_control,crystTyp,set_button=(self.samp_typ ge 1)  ;doesn't work as of IDL6.1
    endif
    if keyword_set(init) then return
    if (self.samp_typ ge 2) or (old_typ ge 2) then begin    ;if changed from/to diffuse scattering type
       (*self.oifac)=1.0
       ;clear data
       ptr_free,self.kfactor,self.dataStrPtr,self.powd_line
       self->my_widget_control,['addBut','clearDat'],sensitive=0          ;disallow adding data and clear data
       self->my_widget_control,'titlLab',set_value='' & self.titl_lab=''  ;clear title label
       self->my_widget_control,'legdLab',set_value='' & self.legd_lab=''  ;clear legend label
       ;clear background
       ptr_free,self.bgdata,self.bgratePtr,self.bgtchnPtr,self.bgdetsPtr
       self->my_widget_control,'bgclBut',sensitive=0
    endif
    ptr_free,self.projStrPtr
    self->reset_file
    self->reset_pdt
end

;clear mask pointer and set the menu items accordingly
pro dcs_mslice::clear_mask
    if ptr_valid(self.mask) then begin
       ptr_free,self.mask
       mkngBut = widget_info(self.tlb,find_by_uname='mkngBut')
       mkcnBut = widget_info(self.tlb,find_by_uname='mkcnBut')
       mkloBut = widget_info(self.tlb,find_by_uname='mkloBut')
       mkupBut = widget_info(self.tlb,find_by_uname='mkupBut')
       mkulBut = widget_info(self.tlb,find_by_uname='mkulBut')
       mkmlBut = widget_info(self.tlb,find_by_uname='mkmlBut')
       mkucBut = widget_info(self.tlb,find_by_uname='mkucBut')
       dm_toggle_menubut,mkngBut,[mkngBut,mkcnBut,mkloBut,mkupBut,mkulBut,mkmlBut,mkucBut]
       self->my_widget_control,['mksvBut','mkclBut'],sensitive=0
    endif
end

; adds an object to the list and shows its title to the view menu or deletes an object from the list
; and removes the corresponding item in the view menu
; parameter:
;   opcode:   0: add plotwindow , this is the default operation
;             1: make plotwindow current, object keyword must be given
;             2: keep the plotwindow, object keyword must be given
;             3: delete plotwindow, object keyword must be given
;             4: kill all plot windows
; keyword:
;   type:     0:slice 1:cut 2:trajectory
;   title:    string of the button name to be added to the view menu
;   object:   opcode=1,2--object chosen opcode=3--object to be deleted
pro dcs_mslice::dm_add_plotwindow,opcode,type=type,title=title,object=object
    if n_elements(opcode) eq 0 then opcode=0   ;default add plot window
    viewMenu = widget_info(self.tlb,find_by_uname='viewMenu')
    if widget_info(viewMenu,/valid_id) eq 0 then return
    case opcode of
       0:begin
         if not obj_valid(self.current) then return
         ;create the unique id for the view menu item
         id  = self->dm_get_id(self.current)
         ;check if the current object is already in the list, if not add it to the list
         all = self.gr_list->get(/all,count=count)
         in  = 0b
         for i=0,count-1 do begin
             if all[i] eq self.current then begin
                in = 1b
                break
             endif
         endfor
         if in eq 0 then begin    ;not in the list
            self.gr_list->add,self.current            ;add the object to the list
            id = dm_widget_button(viewMenu,value='',uname=id,separator=(count eq 0)) ;add the item to the view menu
         endif else begin     ;in the list, find the menu item id
            id = widget_info(viewMenu,find_by_uname=id)
         endelse
         ;generate proper string for the menu item
         if n_elements(type) eq 0 then type=0
         case type of
            0:   value = 'Slice: '
            1:   value = 'Cut: '
            2:   value = 'Trajectory: '
            else:value = 'Slice: '
         endcase
         if n_elements(title) ne 0 then value=value+strtrim(title,2)
         if widget_info(id,/valid_id) eq 1 then begin
            if float(!version.release) ge 5.6 then $
               widget_control,id,set_value=value,set_button=1 $
            else $
               widget_control,id,set_value=value
         endif
         self->my_widget_control,['killAll','arrPlot'],viewMenu,sensitive=1
         end
       1:begin 
         if obj_valid(self.current) and (float(!version.release) ge 5.6) then begin   ;remove the current check mark
            id = self->dm_get_id(self.current) ;locate the corresponding view menu item id
            self->my_widget_control,id,viewMenu,set_button=0
         endif
         all = self.gr_list->get(/all,count=count)
         for i=0,count-1 do begin
            if  all[i] ne object then all[i]->setproperty,keep=1 $
            else self.current=all[i]
         endfor
         if float(!version.release) ge 5.6 then begin ;add check mark to the current plot window
            id = self->dm_get_id(self.current)
            self->my_widget_control,id,viewMenu,set_button=1
         endif
         end
       2:begin          
         self.current=obj_new()
         if float(!version.release) ge 5.6 then begin ;remove check mark from the view menu
            id = self->dm_get_id(object)  ;locate the corresponding view menu item id
            self->my_widget_control,id,viewMenu,set_button=0
         endif
         end
       3:begin       
         all = self.gr_list->get(/all,count=count)
         for i=0,count-1 do begin   ;destroy all the plot menu items
             id = self->dm_get_id(all[i])
             self->my_widget_control,id,viewMenu,get_value=value,/destroy  ;remove the item in the view menu
             if n_elements(info) eq 0 then info = [id,value] $  ;save the names
             else info = [[info],[[id,value]]]
         endfor      
         self.gr_list->remove,object       ;remove the object from the list
         all = self.gr_list->get(/all,count=count)
         for i=0,count-1 do begin   ;reconstruct the plot menu items
             id  = self->dm_get_id(all[i])
             all[i]->getproperty,keep=keep,title=title
             value = title ;change the menu name to the title of the plot
             id1 = where(info[0,*] eq id,existed)
             if existed ne 0 then begin
                tmp = info[1,id1[0]]
                tmp = strsplit(tmp,':',/extract,/preserve_null)
                if n_elements(tmp) ne 0 then value=tmp[0]+': '+title ;include the type string
             endif
             id = dm_widget_button(viewMenu,uname=id,value=value,separator=(i eq 0),set_button=(1-keep))
         endfor
         self->my_widget_control,['killAll','arrPlot'],viewMenu,sensitive=(count gt 0)
         end
       4:begin
         all = self.gr_list->get(/all,count=count)
         if count gt 0 then obj_destroy,all
         end
       else:
    endcase
end

;arrange the plot windows
pro dcs_mslice::dm_arrange_plot,cascade=cascade
    oplots = self.gr_list->get(/all,count=count)
    if count eq 0 then return
    for i=0,count-1 do oplots[i]->totop
    if count eq 1 then return
    device,get_screen_size=scr_size
    if keyword_set(cascade) then begin
       oplots[count-1]->getproperty,xsize=xsize,ysize=ysize & ysize=ysize+20
       xstep = (40<((scr_size[0]-xsize)/count))
       ystep = (40<((scr_size[1]-ysize)/count))
       xoff  = 5>((scr_size[0]-xstep*count-xsize)/2)
       yoff  = 5>((scr_size[1]-ystep*count-ysize)/2)
       for i=0,count-1 do begin
           oplots[i]->getproperty,tlb=tlb
           widget_control,tlb,xoffset=((xoff+xstep*i)<(scr_size[0]-10)),$
                yoffset=((yoff+ystep*i)<(scr_size[1]-10))
       endfor
    endif else begin
       if count le 4 then ncol=2 $
       else if count le 9 then ncol=3 $
       else ncol=4
       xsize = intarr(count) & ysize = intarr(count) & wid = lonarr(count)
       for i=0,count-1 do begin
           oplots[i]->getproperty,tlb=tlb,xsize=tmpx,ysize=tmpy
           wid[i] = tlb & xsize[i] = tmpx+10 & ysize[i] = tmpy+75
       endfor
       nrow = (count+ncol-1)/ncol
       roww = intarr(nrow) & rowh = intarr(nrow) & xoff = intarr(nrow)
       for i=0,nrow-1 do begin
           roww[i] = total(xsize[ncol*i:((ncol*(i+1)-1)<(count-1))])
           rowh[i] = max(ysize[ncol*i:((ncol*(i+1)-1)<(count-1))])
           xoff[i] = 0>((scr_size[0]-roww[i])/2)
       endfor
       yoff = 0>((scr_size[1]-total(rowh))/2)
       for i=0,count-1 do begin
           row = i/ncol
           col = (i mod ncol)
           if xoff[row] eq 0 then xoffset=scr_size[0]/ncol*col $
           else begin
              xoffset = xoff[row]
              if col ne 0 then $
                 xoffset = (xoffset+total(xsize[row*ncol:row*ncol+col-1]))<(scr_size[0]-20)
           endelse
           if yoff eq 0 then yoffset=scr_size[1]/nrow*row $
           else begin
              yoffset = yoff
              if row ne 0 then $
                 yoffset = (yoffset+total(rowh[0:row-1]))<(scr_size[1]-20)
           endelse
           widget_control,wid[i],xoffset=xoffset,yoffset=yoffset
       endfor
    endelse
end

;create a unique id for an object
function dcs_mslice::dm_get_id,object
    help,object,output=id & id=strsplit(id,' ',/extract) &  id=id[n_elements(id)-1]
    tmp = strsplit(id,'()',/extract) & if n_elements(tmp) eq 3 then id=tmp[0]+tmp[2]
    return,id
end

;object event handler
pro dcs_mslice::event,event
    compile_opt IDL2    ;,strictarrsubs
                        ;idl2=defint32,strictarr
                        ;strictarr:   [] to index array
                        ;strictarrsubs: error when out-of-range indices,IDL5.6 or after
    WIDGET_CONTROL,/HOURGLASS
    ;catch and ignore all errors in this program
    catch, myerror
    if myerror ne 0 then begin
       catch,/cancel
       errmesg = !error_state.msg
       if obj_valid(self) then $
          if (self.samp_typ eq 3) and (!error_state.name eq 'IDL_M_CNTGETMEM') then $
             errmesg = [errmesg,'','Please reduce the energy range, or use single E option.']
       ok = dialog_message(errmesg,/error)
       if obj_valid(self) then self.error=1
       return
    end
    widget_type = widget_info(event.id,/type)
    case widget_type of
       1:tmp_value = event.select                               ;button
       3:begin                                                  ;text box
         widget_control,event.id,get_value=tmp_value
         tmp_value = strtrim(tmp_value,2)
         end
       8:tmp_value = widget_info(event.id,/droplist_select)     ;drop list
       12:begin                                                 ;combobox
         tmp_value = event.index
         widget_control,event.id,get_value=tmp_list
         if tmp_list[tmp_value] ne event.str then begin         ;to avoid events from set_value in unix operating system
            return
         endif
         end
       else:
    endcase
    if n_elements(tmp_value) eq 1 then tmp_value=tmp_value[0]

    resetu1 = 0 & resetu2 = 0 & resetu3 = 0

    uname = widget_info(event.id,/uname)
    type  = tag_names(event,/structure)
    case strlowcase(type) of
        'dm_plot_make_current': uname = type
        'dm_plot_keep':         uname = type
        'dm_plot_kill':         uname = type
        'widget_context':       uname = 'status'
        else:
    endcase
    case strlowcase(uname) of
        'dm_plot_make_current': self->dm_add_plotwindow,1,object=event.object   ;this event is sent from dm_plot window
        'dm_plot_keep':         self->dm_add_plotwindow,2,object=event.object   ;this event is sent from dm_plot window
        'dm_plot_kill':         self->dm_add_plotwindow,3,object=event.object   ;this event is sent from dm_plot window
        'tlb':begin
            geom  = widget_info(self.tlb,/geometry)
            space = total(1-self.view)*geom.space*(!version.os_family eq 'Windows')
            if float(!version.release) ge 5.5 then $
               widget_control,self.tlb,xsize=self.geom[0],ysize=self.geom[1]-space $
            else $
               widget_control,self.tlb,scr_xsize=self.geom[0],scr_ysize=self.geom[1]-space
          end
        'saveslicedave': self->save_slice,/dave
        'saveslicespe':  self->save_slice,/spe
        'savesliceiexy': self->save_slice,/iexy
        'saveslicexyie': self->save_slice,/xyie
        'savecutxye':    self->save_cut,/xye
        'savecutdave':   self->save_cut,/dave
        'hist_0':        self->set_filehistory,choose=0
        'hist_1':        self->set_filehistory,choose=1
        'hist_2':        self->set_filehistory,choose=2
        'hist_3':        self->set_filehistory,choose=3
        'hist_4':        self->set_filehistory,choose=4
        'hist_5':        self->set_filehistory,choose=5
        'hist_6':        self->set_filehistory,choose=6
        'hist_7':        self->set_filehistory,choose=7
        'hist_8':        self->set_filehistory,choose=8
        'hist_9':        self->set_filehistory,choose=9
        'clearhist': begin
            ptr_free,self.file_hist
            self.n_history = 0
            self->set_filehistory
           end
        'exitbut':begin
            widget_control,self.tlb,/destroy
            return
          end
        'ldpmbut':begin  ;load parameter file
            parmfile = dm_choose_file('prm',dialog_parent=self.tlb,/read)
            if strlen(parmfile) ne 0 then self->dm_load_parameter,parmfile
          end
        'svpmbut':begin ;save parameters into a file
            parmfile = dm_choose_file('prm',dialog_parent=self.tlb,/write)
            if strlen(parmfile) ne 0 then self->dm_save_parameter,parmfile
          end
        'knpmbut':begin  ;change smoothing kernel
            old = dm_to_string(float(self.disp_sm_kernel))
            old = '[['+old[0]+' ,'+old[1]+' ,'+old[2]+'],['+old[3]+' ,'+old[4]+' ,'+old[5]+'],['+old[6]+' ,'+old[7]+' ,'+old[8]+']]'
            new = dm_dialog_input('kernel matrix:',title='Change smoothing kernel',default=old,xsize=250,dialog_parent=self.tlb)
            new = dm_to_number(strsplit(new,'[], '+string(9b),/extract),/float)
            if n_elements(new) ne 9 then begin
               ok = dialog_message('Please input a 3x3 matrix.',/error,dialog_parent=self.tlb)
               break
            endif
            if max(abs(new[indgen(3,3)]-new[transpose(indgen(3,3))])) ne 0.0 then begin
               ok = dialog_message('Please input a symmetric matrix.',/error,dialog_parent=self.tlb)
               break
            endif
            if total(new[0:8]) ne 0 then self.disp_sm_kernel=new[indgen(3,3)]
          end
        'ssfcbut':begin    ;change self-shielding factor
            old = self.ssfac
            new = dm_dialog_input('self-shielding factor:',title='Change self-shielding factor',default=old,$
               /float,info='I=I_samp-ssfac*I_can',dialog_parent=self.tlb)
            if finite(new) then $
               if new ne self.ssfac then $
                  self.ssfac=new
          end
        'oifcbut':begin  ;change overall intensity factor
            old = (*self.oifac)
            if (self.samp_typ ge 2) and ptr_valid(self.dataStrPtr) then begin
               filename = (*self.dataStrPtr).filename
               new = dm_dialog_listinput(filename,title='Change overall intensity factor',default=old,$
                      label='Factor',dialog_parent=self.tlb,xvalue=(*self.dataStrPtr).rotation,reset=1,$
                      info=['The factors will be reset to 1 every time', 'the Load Data button is pressed.'])
            endif else begin
               new = dm_dialog_input('overall intensity factor:',title='Change overall intensity factor',default=old,/float,$
                    dialog_parent=self.tlb,info=['This factor will be reset to 1 every time', 'a file is loaded.'])
            endelse
            if total(finite(new)) eq n_elements(new) then $
               *self.oifac = new
          end
        'ddirbut':begin    ;set data directory
            old = self.fileSel->getproperty(/path)
            new = dialog_pickfile(/directory,path=old,dialog_parent=self.tlb)
            if (strlen(new) ne 0) and (strlowcase(old) ne strlowcase(new)) then $
               self.fileSel->set_path,new
          end
        'wdirbut':begin  ;set working directory
            old = self.fileSel->getproperty(/path)
            ;check if !dave_defaults is defined, if not, define it
            defsysv,'!dave_defaults',exists=exists
            if exists then $
               exists = ptr_valid(!dave_defaults)
            if exists eq 0 then $
               defsysv,'!dave_defaults',ptr_new({datdir:old,workdir:old,pdfreader:'',web_browser:''}) $
            else $
               old = (*!dave_defaults).workdir
            new = dialog_pickfile(/directory,path=old,dialog_parent=self.tlb)
            if (strlen(new) ne 0) and (strlowcase(old) ne strlowcase(new)) then $
               (*!dave_defaults).workdir = new
          end
        'bgovbut':begin  ;overall background rate
            value = !values.f_nan & nvalue = 1
            if ptr_valid(self.bgratePtr) then begin
               value  = mean((*self.bgratePtr)[*,0])
               nvalue = 2   ;dark count file existed
            endif
            tmp_value = dm_dialog_input(dialog_parent=self.tlb,'background rate:',info='in (cts/hr/det)',/float,$
               default=dm_to_string(value))
            if finite(tmp_value) then begin
               if tmp_value gt 0 then begin
                  if nvalue gt 1 then begin
                     ok = dialog_message('Do you want to replace the existing dark count file data?',/question,/default_no,dialog_parent=self.tlb)
                     if ok eq 'No' then break
                  endif
                  ptr_free,self.bgratePtr
                  self.bgratePtr = ptr_new(tmp_value)
                  self->my_widget_control,'bgclBut',sensitive=1
               endif
            endif
          end
        'bgclbut':begin
            ptr_free,self.bgdata,self.bgratePtr,self.bgtchnPtr,self.bgdetsPtr
            widget_control,event.id,sensitive=0
          end
        'vdclbut':begin
            widget_control,event.id,sensitive=0
            ptr_free,self.eff
          end
        'mkngbut': self->dm_mask_detbanks, 'negative'   ;mask negative angle detectors
        'mkcnbut': self->dm_mask_detbanks, 'center'     ;mask central bank
        'mklobut': self->dm_mask_detbanks, 'lower'      ;mask lower bank
        'mkupbut': self->dm_mask_detbanks, 'upper'      ;mask upper bank
        'mkulbut': self->dm_mask_detbanks, 'uplow'      ;mask upper and lower banks
        'mkmlbut': self->dm_mask_detbanks, 'cenlow'     ;mask central and lower banks
        'mkucbut': self->dm_mask_detbanks, 'upcen'      ;mask upper and central banks
        'mkstbut':begin ;set mask
            default=''
            ;clean the mask, if the number of masked detectors is less than 20, save it to the default
            if ptr_valid(self.mask) then begin
               exist  = 1
               n_mask = n_elements(*self.mask)
               if n_mask le 20 then begin
                  default = strcompress(string(*self.mask,format='('+string(n_mask)+'(i5,","))'),/remove_all)
                  if strmid(default,0,/reverse_offset) eq ',' then $
                     default = strmid(default,0,strlen(default)-1)
               endif
            endif else exist=0
            self->clear_mask    ;clear the mask
            tmp = dm_dialog_input(dialog_parent=self.tlb,'Det num:',title='Masking detectors',default=default,$
               info=['Detector number starts from 0 to 912 for DCS.','eg:370,373 or 370:374c'],xsize=200)
            if strlen(tmp) eq 0 then begin
               if exist then ok=dialog_message(['No detector is specified.',$
                  'Previously set detector mask has been cleared.'],dialog_parent=self.tlb)
               break
            endif else begin
               tmpstrs = strsplit(tmp,',',/extract,count=count1)
               for ii=0,count1-1 do begin
                   status = ''
                   index  = strpos(tmpstrs[ii],'c',/reverse_search)
                   if index[0] ne -1 then status='c'
                   index  = strpos(tmpstrs[ii],'C',/reverse_search)
                   if index[0] ne -1 then status='c'
                   index  = strpos(tmpstrs[ii],'u',/reverse_search)
                   if index[0] ne -1 then status='u'
                   index  = strpos(tmpstrs[ii],'U',/reverse_search)
                   if index[0] ne -1 then status='u'
                   index  = strpos(tmpstrs[ii],'l',/reverse_search)
                   if index[0] ne -1 then status='l'
                   index  = strpos(tmpstrs[ii],'L',/reverse_search)
                   if index[0] ne -1 then status='l'

                   ind0  = strsplit(tmpstrs[ii],'[a-zA-Z '+string(9b)+',:-]',/regex)
                   ind1  = strsplit(tmpstrs[ii],':-')
                   index = -1L
                   for i=1,n_elements(ind1)-1 do begin
                       ind2 = where(ind0 eq ind1[i],count)
                       if count ne 0 then index=[index,ind2]
                   endfor
                   n_index = n_elements(index)
                   if n_index ne 1 then index=index[1:n_index-1]-1
                   tmp = strsplit(tmpstrs[ii],'[a-zA-Z '+string(9b)+',:-]',/regex,/extract)
                   tmpmask = -1L
                   for i=0,n_elements(tmp)-1 do begin
                       tmp1 = dm_to_number(tmp[i],/float)
                       if finite(tmp1) then begin
                          ind0 = where(index eq i,count)
                          if count ne 0 then begin
                             i = i+1
                             tmp2 = dm_to_number(tmp[i],/float)
                             if finite(tmp2) then tmpmask=[tmpmask,tmp1+findgen(abs(tmp2-tmp1)+1)] $
                             else tmpmask = [tmpmask,tmp1]
                          endif else tmpmask = [tmpmask,tmp1]
                       endif
                   endfor
                   index = where(tmpmask ge 0,count)
                   if count ne 0 then begin
                      tmpmask = fix(tmpmask[index]+0.1,type=3)
                      case status of
                        'c': tmpmask=dm_common(tmpmask,dm_mask_detbanks(0),/no_copy)
                        'l': tmpmask=dm_common(tmpmask,dm_mask_detbanks(-1),/no_copy)
                        'u': tmpmask=dm_common(tmpmask,dm_mask_detbanks(1),/no_copy)
                        else:
                      endcase
                      if n_elements(mask) eq 0 then $
                         mask = tmpmask $
                      else $
                         mask = [mask,tmpmask]
                   endif
               endfor
            endelse
            if n_elements(mask) eq 0 then count=0 $
            else ind = where(finite(mask) eq 1,count)
            if count ne 0 then begin
               mask = mask[ind]
               ind  = where((mask lt 913) and (mask ge 0),count)
               if count ne 0 then begin
                  self.mask = ptr_new(mask[ind])
                  self->my_widget_control,['mksvBut','mkclBut'],sensitive=1
               endif else begin
                  if exist then ok=dialog_message(['No valid detector is specified.',$
                     'Previously set detector mask has been cleared.'],dialog_parent=self.tlb) $
                  else ok = dialog_message('No valid detector mask is specified.',dialog_parent=self.tlb)
               endelse
               ind = -1
            endif
          end
        'mkpldnum':begin ;plot and set mask by detector number
            ;must have data
            if not ptr_valid(self.dataStrPtr) then begin
               ok = dialog_message('Please load data files first.',dialog_parent=self.tlb)
               widget_control,event.id,sensitive=0
               break
            endif
            case self.samp_typ of
                 0: detsum = total((*self.dataStrPtr).qty,1)
                 1: detsum = total((*self.dataStrPtr).qty,1)
                 2: detsum = (*self.dataStrPtr).qty[*,0]
                 3: detsum = total((*self.dataStrPtr).qty[*,*,0],1)
            endcase
            ndet  = n_elements(detsum)
            blist = intarr(ndet)
            if ptr_valid(self.mask) then begin
               ind = where(*self.mask lt ndet,count)
               if count gt 0 then $
                  blist[0:count-1] = (*self.mask)[ind]+1
            endif
            self->plot_mask,detsum,blist
          end
        'mkplangl':begin ;plot and set mask by angle, only available for DCS
            ;must have data
            if not ptr_valid(self.dataStrPtr) then begin
               ok = dialog_message('Please load data files first.',dialog_parent=self.tlb)
               widget_control,event.id,sensitive=0
               break
            endif
            case self.samp_typ of
                 0: detsum = total((*self.dataStrPtr).qty,1)
                 1: detsum = total((*self.dataStrPtr).qty,1)
                 2: detsum = (*self.dataStrPtr).qty[*,0]
                 3: detsum = total((*self.dataStrPtr).qty[*,*,0],1)
            endcase
            ndet  = n_elements(detsum)
            blist = intarr(ndet)
            if ptr_valid(self.mask) then begin
               ind = where(*self.mask lt ndet,count)
               if count gt 0 then $
                  blist[0:count-1] = (*self.mask)[ind]+1
            endif
            self->plot_mask,detsum,blist,/angle
          end
        'mkbpbut':begin ;automatically mask bragg peaks
            if not ptr_valid(self.dataStrPtr) then begin
               ok = dialog_message('Please load data files first.',dialog_parent=self.tlb)
               widget_control,event.id,sensitive=0
               break
            endif
            if ptr_valid(self.mask) then begin
               ok = dialog_message('This operation will remove the existing masks. Do you want to continue?',$
                    /question,dialog_parent=self.tlb)
               if ok eq 'No' then break
               self->clear_mask     ;clear the mask
            endif
            case self.samp_typ of
                 0: detsum = total((*self.dataStrPtr).qty,1)
                 1: detsum = total((*self.dataStrPtr).qty,1)
                 2: detsum = (*self.dataStrPtr).qty[*,0]
                 3: detsum = total((*self.dataStrPtr).qty[*,*,0],1)
            endcase
            ndet  = n_elements(detsum)

            ;smooth data
            x = indgen(ndet) & y = smooth(detsum,4) & yerr = sqrt(abs(y))

            ;search for peaks
            ;method A: 1 find the highest peak, fit it with a Gaussian, width w0
            ;          2 replace the peak with background value
            ;          3 repeat 1 & 2, if w<0.4w0 or w>2.5w0, not a valid peak
            ;          4 false peak if peak intensity is less than 2.5% of the strongest peak
            ;          5 stop when two consecutive false peaks
            false_peak = 0
            fit_fwhm  = !values.f_nan
            fit_max   = !values.f_nan
            while (false_peak lt 2) do begin   ;search for peaks
                ;find the maximum
                if finite(fit_fwhm) then begin
                   ymax = max(y,ind_ymax,min=ymin)
                   fwhm = fit_fwhm
                endif else begin
                   i0 = 20<(ndet/20)
                   ymax = max(y[i0:ndet-1],ind_ymax,min=ymin)
                   fwhm = 10<(ndet/20)
                   ind_ymax = ind_ymax+i0
                endelse
                yave = mean(y)
                ;find peak boundaries
                ip_0 = where(y[ind_ymax:ndet-1] le (ymax-1./3*(ymax-yave)),count)
                if count ne 0 then begin
                   ip_1 = (ind_ymax+ip_0[0]*3)<(ndet-1) ;peak boundary
                   ip_0 = 0>(ind_ymax-ip_0[0]*3)
                endif else begin
                   ip_0 = where(y[0:ind_ymax] ge (ymax-1./3*(ymax-yave)),count)
                   if count eq 0 then begin
                      ip_0 = 0
                      ip_1 = ndet-1
                   endif else begin
                      ip_1 = (ind_ymax+(ind_ymax-ip_0[count-1])*3)<(ndet-1)
                      ip_0 = 0>(ind_ymax-(ind_ymax-ip_0[count-1])*3)
                   endelse
                endelse
                if (ip_1-ip_0 eq ndet-1) or (ip_1-ip_0 lt 4) then break
                ;fit the peak with a Gaussian
                estimates = [ymax,x[ind_ymax],fwhm/sqrt(8.*alog(2)),y[ip_1]]
                result = gaussfit(x[ip_0:ip_1],y[ip_0:ip_1],params,estimates=estimates,$
                         measure_errors=yerr[ip_0:ip_1],nterms=n_elements(estimates))
                fwhm   = abs(params[2])*sqrt(8.*alog(2))
                if not finite(fit_max)  then fit_max = params[0]
                if not finite(fit_fwhm) then fit_fwhm = fwhm
                ip_0   = (0>(fix(params[1]-fwhm))<(ndet-1))
                ip_1   = (0>(fix(params[1]+fwhm))<(ndet-1))
                if (ip_1-ip_0 eq ndet-1) or (ip_1-ip_0 lt 4) then break
                if (fwhm gt 0.4*fit_fwhm) and (fwhm lt 2.5*fit_fwhm) then begin
                   if params[0] gt 0.025*fit_max then begin
                      false_peak = 0   ;clear the false peak flag
                      if n_elements(mask) eq 0 then $
                         mask = ip_0+indgen(ip_1-ip_0+1)+1 $
                      else $
                         mask = [mask,ip_0+indgen(ip_1-ip_0+1)+1]
                   endif else $
                      false_peak = false_peak+1
                endif else $
                   false_peak = false_peak+1
                ;replace the peak with the background
                y[ip_0:ip_1] = params[3]
            endwhile
            x = 0 & y = 0 & yerr = 0
            if n_elements(mask) eq 0 then $
               mask = [0] $
            else $
               mask = mask[uniq(mask,sort(mask))]
            if n_elements(mask) eq ndet then mask = [0]
            self->plot_mask,detsum,mask
          end
        'mkrdbut':begin ;read mask file
            file = dm_choose_file('',/read,dialog_parent=self.tlb,title='Read mask file:')
            if strlen(file) eq 0 then return
            self->clear_mask    ;clear the mask
            openr,unit,file,/get_lun
            tmp = ''
            while(not eof(unit)) do begin
                readf,unit,tmp
                tmp = strtrim(tmp,2)
                if strlen(tmp) ne 0 then begin
                   tmp1 = strsplit(tmp,' ,'+string(9b),/extract,count=count1)
                   if finite(dm_to_number(tmp1[0])) then begin  ;make sure it's not a comment line
                      for i=0L,count1-1L do begin
                          tmp2 = strsplit(tmp1[i],'-:',/extract,count=count2)
                          tmp2 = dm_to_number(tmp2,/long)
                          if count2 eq 2 then $
                             tmp2 = min(tmp2)+lindgen(abs(tmp2[1]-tmp2[0])+1)
                          if n_elements(mask) eq 0 then mask=tmp1 else mask=[mask,tmp2]
                      endfor
                   endif
                endif
            endwhile
            free_lun,unit
            if n_elements(mask) ne 0 then begin
               ok = dm_dialog_input('det number starts from',default=0,droplist_content=ptr_new(['0','1']),$
                    is_droplist=[1],/return_number,dialog_parent=self.tlb)
               self.mask = ptr_new(mask-ok)
               self->my_widget_control,['mksvBut','mkclBut'],sensitive=1
            endif
          end
        'mksvbut':begin ;save mask in a file
            if ptr_valid(self.mask) then begin
               file = dm_choose_file('msk',/write,dialog_parent=self.tlb,title='Save mask in an ASCII file.')
               if strlen(file) eq 0 then break
               openw,unit,file,/get_lun,error=openerr
               if openerr ne 0 then begin
                  ok = dialog_message("Can't write in "+file[0],/error,dialog_parent=self.tlb)
               endif else begin
                  widget_control,/hourglass  ;busy signal
                  printf,unit,*(self.mask)
                  free_lun,unit
               endelse
            endif
          end
        'mkclbut': self->clear_mask         ;clear the mask
        'directgeom':if self.instrgeom ne 0 then $
            self->set_instrgeom,geom=0
        'inversegeom':if self.instrgeom ne 1 then $
            self->set_instrgeom,geom=1
        'intntyp0':if self.intn_typ ne 0 then begin
            self.intn_typ = 0
            intnTyp1 = widget_info(self.tlb,find_by_uname='intnTyp1')
            intnTyp2 = widget_info(self.tlb,find_by_uname='intnTyp2')
            intnTyp3 = widget_info(self.tlb,find_by_uname='intnTyp3')
            intnTyp4 = widget_info(self.tlb,find_by_uname='intnTyp4')
            dm_toggle_menubut,event.id,[intnTyp1,intnTyp2,intnTyp3,intnTyp4]
            ;need to recalculate projections
            ptr_free,self.projStrPtr
            self->set_display_button
          endif
        'intntyp1':if self.intn_typ ne 1 then begin
            self.intn_typ = 1
            intnTyp0 = widget_info(self.tlb,find_by_uname='intnTyp0')
            intnTyp2 = widget_info(self.tlb,find_by_uname='intnTyp2')
            intnTyp3 = widget_info(self.tlb,find_by_uname='intnTyp3')
            intnTyp4 = widget_info(self.tlb,find_by_uname='intnTyp4')
            dm_toggle_menubut,event.id,[intnTyp0,intnTyp2,intnTyp3,intnTyp4]
            ;need to recalculate projections
            ptr_free,self.projStrPtr
            self->set_display_button
          endif
        'intntyp2':if self.intn_typ ne 2 then begin
            self.intn_typ = 2
            intnTyp0 = widget_info(self.tlb,find_by_uname='intnTyp0')
            intnTyp1 = widget_info(self.tlb,find_by_uname='intnTyp1')
            intnTyp3 = widget_info(self.tlb,find_by_uname='intnTyp3')
            intnTyp4 = widget_info(self.tlb,find_by_uname='intnTyp4')
            dm_toggle_menubut,event.id,[intnTyp0,intnTyp1,intnTyp3,intnTyp4]
            ;need to recalculate projections
            ptr_free,self.projStrPtr
            self->set_display_button
          endif
        'intntyp3':if self.intn_typ ne 3 then begin
            self.intn_typ = 3
            intnTyp0 = widget_info(self.tlb,find_by_uname='intnTyp0')
            intnTyp1 = widget_info(self.tlb,find_by_uname='intnTyp1')
            intnTyp2 = widget_info(self.tlb,find_by_uname='intnTyp2')
            intnTyp4 = widget_info(self.tlb,find_by_uname='intnTyp4')
            dm_toggle_menubut,event.id,[intnTyp0,intnTyp1,intnTyp2,intnTyp4]
            ;need to recalculate projections
            ptr_free,self.projStrPtr
            self->set_display_button
          endif
        'intntyp4':if self.intn_typ ne 4 then begin
            self.intn_typ = 4
            intnTyp0 = widget_info(self.tlb,find_by_uname='intnTyp0')
            intnTyp1 = widget_info(self.tlb,find_by_uname='intnTyp1')
            intnTyp2 = widget_info(self.tlb,find_by_uname='intnTyp2')
            intnTyp3 = widget_info(self.tlb,find_by_uname='intnTyp3')
            dm_toggle_menubut,event.id,[intnTyp0,intnTyp1,intnTyp2,intnTyp3]
            ;need to recalculate projections
            ptr_free,self.projStrPtr
            self->set_display_button
          endif
        'intneint': begin
            self.eint_yn = (1b)-self.eint_yn
            dm_set_button,event.id,self.eint_yn,onstring='E-Integrated Intensity Enabled',$
                offstring='E-Integrated Intensity Disabled'
            ;need to recalculate projections
            ptr_free,self.projStrPtr
            self->set_display_button
          end
        'binavg':if self.bin_avgsum ne 0 then begin
            self.bin_avgsum = 0
            binSum = widget_info(self.tlb,find_by_uname='binSum')
            dm_toggle_menubut,event.id,binSum
          endif
        'binsum':if self.bin_avgsum ne 1 then begin
            self.bin_avgsum = 1
            binAvg = widget_info(self.tlb,find_by_uname='binAvg')
            dm_toggle_menubut,event.id,binAvg
          endif
        'bincsyes': if self.bin_conststep ne 1 then begin
            self.bin_conststep = 1
            bincsNo  = widget_info(self.tlb,find_by_uname='bincsNo')
            dm_toggle_menubut,event.id,bincsNo
          endif
        'bincsno': if self.bin_conststep ne 0 then begin
            self.bin_conststep = 0
            bincsYes  = widget_info(self.tlb,find_by_uname='bincsYes')
            dm_toggle_menubut,event.id,bincsYes
          endif
        'monsum':if self.mon_sumfit ne 0 then begin
            self.mon_sumfit = 0
            monFit = widget_info(self.tlb,find_by_uname='monFit')
            dm_toggle_menubut,event.id,monFit
          endif
        'monfit':if self.mon_sumfit ne 1 then begin
            self.mon_sumfit= 1
            monSum = widget_info(self.tlb,find_by_uname='monSum')
            dm_toggle_menubut,event.id,monSum
          endif
        'monfc0':if self.dcs_mon ne 0 then begin
            self.dcs_mon = 0
            monBM1  = widget_info(self.tlb,find_by_uname='monBM1')
            monTIME = widget_info(self.tlb,find_by_uname='monTIME')
            dm_toggle_menubut,event.id,[monBM1,monTIME]
            self->my_widget_control,'bgovBut',sensitive=1
          endif
        'monbm1':if self.dcs_mon ne 1 then begin
            self.dcs_mon = 1
            monFC0  = widget_info(self.tlb,find_by_uname='monFC0')
            monTIME = widget_info(self.tlb,find_by_uname='monTIME')
            dm_toggle_menubut,event.id,[monFC0,monTIME]
            self->my_widget_control,'bgovBut',sensitive=1
          endif
        'montime':if self.dcs_mon ne 2 then begin
            self.dcs_mon = 2
            monFC0  = widget_info(self.tlb,find_by_uname='monFC0')
            monBM1  = widget_info(self.tlb,find_by_uname='monBM1')
            dm_toggle_menubut,event.id,[monFC0,monBM1]
          endif
        'abspnone':     self->absorption,-1
        'abspcylinder': self->absorption,0
        'abspannulus':  self->absorption,1
        'abspsphere':   self->absorption,2
        'vaxisarbi': if self.view_ortharbi ne 1 then begin
            self.view_ortharbi = 1
            vOrth = widget_info(self.tlb,find_by_uname='vaxisOrtho')
            dm_toggle_menubut,event.id,vOrth
            self->my_widget_control,'viewAxis',set_value='  Viewing Axes:'
          endif
        'vaxisortho':if self.view_ortharbi ne 0 then begin
            self.view_ortharbi = 0
            vArbi = widget_info(self.tlb,find_by_uname='vaxisArbi')
            dm_toggle_menubut,event.id,vArbi
            self->my_widget_control,'viewAxis',set_value='  Orthogonal Viewing Axes:'
          endif
        'powdernone':if self.powd_typ ne 0 then begin
            ptr_free,self.powd_line
            self.powd_typ = 0
            al = widget_info(self.tlb,find_by_uname='powderAl')
            cu = widget_info(self.tlb,find_by_uname='powderCu')
            st = widget_info(self.tlb,find_by_uname='powderSt')
            dm_toggle_menubut,event.id,[al,cu,st]
          end
        'powderal':if self.powd_typ ne 1 then begin
            ptr_free,self.powd_line
            self.powd_typ = 1
            no = widget_info(self.tlb,find_by_uname='powderNone')
            cu = widget_info(self.tlb,find_by_uname='powderCu')
            st = widget_info(self.tlb,find_by_uname='powderSt')
            dm_toggle_menubut,event.id,[no,cu,st]
          endif
        'powdercu':if self.powd_typ ne 2 then begin
            ptr_free,self.powd_line
            self.powd_typ = 2
            al = widget_info(self.tlb,find_by_uname='powderAl')
            no = widget_info(self.tlb,find_by_uname='powderNone')
            st = widget_info(self.tlb,find_by_uname='powderSt')
            dm_toggle_menubut,event.id,[al,no,st]
          endif
        'powderst':if self.powd_typ ne 3 then begin
            ptr_free,self.powd_line
            self.powd_typ = 3
            al = widget_info(self.tlb,find_by_uname='powderAl')
            cu = widget_info(self.tlb,find_by_uname='powderCu')
            no = widget_info(self.tlb,find_by_uname='powderNone')
            dm_toggle_menubut,event.id,[al,cu,no]
          endif
        'neg2th':begin
            self.negative2th = (1b)-self.negative2th
            dm_set_button,event.id,self.negative2th,onstring='Preserve Negative 2theta Angle Value',$
               offstring='Use Absolute 2theta Angle Value'
            ;need to recalculate projections if negative 2theta exists
            if ptr_valid(self.detPosPtr) then $
               if min((*self.detPosPtr).two_theta) lt 0 then begin
                  ptr_free,self.projStrPtr
                  self->set_display_button
               endif
          end
        'hklran':begin
            self.hklran_yn = (1b)-self.hklran_yn
            dm_set_button,event.id,self.hklran_yn,onstring='Allow Extra HKL Range',$
               offstring='Disallow Extra HKL Range'
            if self.view[1] then self->reset_pdt
          end
        'darkcorr':begin
            self.dcor_yn = (1b)-self.dcor_yn
            ptr_free,self.dcor_info
            if self.dcor_yn then begin
               self.filesel->getproperty,path=open_path,file=open_file
               if n_elements(open_file) eq 0 then begin
                  ok = dialog_message(dialog_parent=self.tlb,'Please select dark angle correction files first.',/error)
                  self.dcor_yn = 0b
               endif else begin
                  default = self.dcor_eqran
                  eqran   = dm_dialog_input(['E_start (meV)','E_end (meV)','2theta_start',$
                            '2theta_end'],title='Specify E, 2theta range:',xsize=80,$
                            default=default,info=['The total intensity in the specified range will',$
                            'be used to calculate the dark angle correction.'],dialog_parent=self.tlb)
                  if total(finite(eqran)) ne 4 then $
                     self.dcor_yn = 0b $
                  else if (eqran[0] ge eqran[1]) or (eqran[2] ge eqran[3]) then $
                     self.dcor_yn = 0b
                  if self.dcor_yn eq 0 then $
                     ok = dialog_message('Invalid input. Dark angle correction is disabled.',dialog_parent=self.tlb) $
                  else begin
                     self.dcor_eqran = eqran
                     det_tt = (*self.detPosPtr).two_theta
                     index  = where((abs(det_tt) ge self.dcor_eqran[2]) and (abs(det_tt) le self.dcor_eqran[3]),count)
                     if count eq 0 then begin
                        ok  = dialog_message(['The specified 2theta angle is beyond the detector range.',$
                              'Dark angle correction is skipped.'],dialog_parent=self.tlb)
                        self.dcor_yn = 0b
                     endif else begin
                        dm_load_dcsdata,open_path,open_file,qty=tmp_qty,t_chan=2,e_range=self.dcor_eqran[0:1],$
                              ang=ang,parent=self.tlb,/raw,title='Load Dark Angle Files',eadjust = self.eadjust,$
                              montype=self.dcs_mon
                        tmp_qty = tmp_qty[index,*]
                        tmp_qty = total(tmp_qty,1)
                        tmp_qty = max(tmp_qty)/tmp_qty
                        self.dcor_info = ptr_new({factor:tmp_qty,a2:reform(ang[0,*])})
                     endelse
                  endelse
               endelse
            endif
            dm_set_button,event.id,self.dcor_yn,onstring='Dark Angle Correction Enabled',$
               offstring='Dark Angle Correction Disabled'
            ;need to recalculate projections
            ptr_free,self.projStrPtr
            self->set_display_button
          end
        'eadjust':begin
            self.eadjust = (1b)-self.eadjust
            dm_set_button,event.id,self.eadjust,onstring='Elastic Peak Position Adjustment Enabled',$
                    offstring='Elastic Peak Position Adjustment Disabled'
            ;need to reload data
            self.monrate = 0d
            ptr_free,self.kfactor,self.dataStrPtr,self.projStrPtr
            self->my_widget_control,'addBut',sensitive=0     ;disallow adding data
            self->my_widget_control,'clearDat',sensitive=0   ;disallow clear data button
            self->my_widget_control,'titlLab',set_value='' & self.titl_lab=''   ;clear title label
            self->my_widget_control,'legdLab',set_value='' & self.legd_lab=''   ;clear legend label
            self->set_display_button
          end
        'edepeff':begin
            self.edep_yn = (1b)-self.edep_yn
            dm_set_button,event.id,self.edep_yn,onstring='E-Dependent Detector Efficiency Correction Enabled',$
                    offstring='E-Dependent Detector Efficiency Correction Disabled'
            ;need to recalculate projections
            ptr_free,self.projStrPtr
            self->set_display_button
          end
        'errbar':begin
            self.errbar = (1b)-self.errbar
            dm_set_button,event.id,1-self.errbar,onstring='Error Bar Disabled',offstring='Error Bar Enabled'
          end
        'viewspurion': self->dm_det_spurion
        'useitool': begin
            self.useitool = (1b)-self.useitool
            dm_set_button,event.id,self.useitool,onstring='Use Classical Plotting',offstring='Use iTools Plotting'
          end
        'killall': self->dm_add_plotwindow,4
        'arrcascade': self->dm_arrange_plot,/cascade
        'arrtable': self->dm_arrange_plot
        'hpctbut':if strlen(self.helpfile[0]) ne 0 then begin
            launch = 0
            defsysv,'!dave_defaults',exists=exists
            if exists then $
               if ptr_valid(!dave_defaults) then $
                  if strlen((*!dave_defaults).pdfreader) ne 0 then launch = 1
            if launch eq 1 then $
               void = launch_help(self.helpfile[0],tlb=self.tlb) $
            else $
               online_help,book=self.helpfile[0],/full_path
          endif
        'hpftbut':if strlen(self.helpfile[1]) ne 0 then begin
            launch = 0
            defsysv,'!dave_defaults',exists=exists
            if exists then $
               if ptr_valid(!dave_defaults) then $
                  if strlen((*!dave_defaults).pdfreader) ne 0 then launch = 1
            if launch eq 1 then $
               void = launch_help(self.helpfile[1],tlb=self.tlb) $
            else $
               online_help,book=self.helpfile[1],/full_path
          endif
        'selfbut':ok = dialog_message(*self.info,/information,dialog_parent=self.tlb,title=$
                       'About Mslice for '+(*self.ftypename)[self.ftype])
        'cleardat':  begin
            self.monrate = 0d
            ptr_free,self.kfactor,self.dataStrPtr,self.projStrPtr
            self->my_widget_control,['addBut','mkplBut','mkbpBut'],sensitive=0  ;disallow adding data & plotting mask
            widget_control,event.id,sensitive=0                                 ;disallow clear data button
            self->my_widget_control,'titlLab',set_value='' & self.titl_lab=''   ;clear title label
            self->my_widget_control,'legdLab',set_value='' & self.legd_lab=''   ;clear legend label
            self->set_display_button
          end
        'intnlab':  self.intn_lab = tmp_value   ;intensity label
        'titllab':  self.titl_lab = tmp_value   ;title label
        'legdlab':  self.legd_lab = tmp_value   ;legend label
        'powdtyp':  self->change_samptyp,0
        'crysttyp1':self->change_samptyp,1
        'crysttyp2':self->change_samptyp,2
        'crysttyp3':self->change_samptyp,3
        'viewproj':begin
            self.view[0] = (1b)-self.view[0]
            dm_set_button,event.id,self.view[0],onstring='Hide Projection',offstring='Show Projection'
            self->reset_pdt
          end
        'viewdisp':begin
            self.view[1] = (1b)-self.view[1]
            dm_set_button,event.id,self.view[1],onstring='Hide Display',offstring='Show Display'
            self->reset_pdt
          end
        'viewtraj':begin
            self.view[2] = (1b)-self.view[2]
            dm_set_button,event.id,self.view[2],onstring='Hide Trajectory',offstring='Show Trajectory'
            self->reset_pdt
          end
        'ebin':  begin    ;ebin size /energy range
            if self.samp_typ ge 2 then begin   ;diffuse scattering
               self.e_bin[self.samp_typ] = tmp_value
               if tmp_value eq 2 then begin     ;specify energy range
                  default = dm_to_string(self.e_range)
                  items   = ['from:','to:']
                  info    = ['Energy range is in units of meV.','Data files need to be reloaded.']
                  if self.samp_typ eq 3 then begin
                     default = [default,dm_to_string(self.e_bin[4])]
                     items   = [items,'E rebin size:']
                  endif
                  new = dm_dialog_input(items,title='Energy range',default=default,/float,$
                        dialog_parent=self.tlb,info=info)
                  self.e_bin[self.samp_typ] = 1
                  self.e_range[*] = !values.f_nan
                  if total(finite(new[0:1])) eq 2 then $
                     if new[1] gt new[0] then begin
                        self.e_range = new[0:1]
                        self.e_bin[self.samp_typ] = 2
                     endif
                  if self.e_bin[self.samp_typ] eq 1 then begin
                     ok = dialog_message('Invalid energy range. Elastic peak option is used.',dialog_parent=self.tlb)
                     dm_set_droplist,event.id,select=1
                  endif
                  if self.samp_typ eq 3 then begin  ;rebin size
                     new = fix(new[2])
                     if new le 0 then begin
                        new = 1
                        ok = dialog_message('Invalid rebin size. 1 is used instead.',dialog_parent=self.tlb)
                     endif
                     self.e_bin[4] = new
                  end
               endif else if self.samp_typ eq 3 then begin  ;need to ask for rebin size for multiple E type
                  new = dm_to_string(self.e_bin[4])
                  new = dm_dialog_input('E rebin size:', title='Rebin size',default=new,/int,dialog_parent=self.tlb)
                  if new le 0 then begin
                     new = 1
                     ok = dialog_message('Invalid rebin size. 1 is used instead.',dialog_parent=self.tlb)
                  endif
                  self.e_bin[4] = new
               endif
            endif else $    ;single crystal or powder
               self.e_bin[self.samp_typ] = (*self.rebinsize)[tmp_value]
          end
        'latta': self.latt_parm[0] = dm_to_number(tmp_value,/float)   ;a
        'lattb': self.latt_parm[1] = dm_to_number(tmp_value,/float)   ;b
        'lattc': self.latt_parm[2] = dm_to_number(tmp_value,/float)   ;c
        'lattaa':self.latt_parm[3] = dm_to_number(tmp_value,/float)   ;alpha
        'lattbb':self.latt_parm[4] = dm_to_number(tmp_value,/float)   ;beta
        'lattcc':self.latt_parm[5] = dm_to_number(tmp_value,/float)   ;gama
        'orieux':self.orie_u[0]    = dm_to_number(tmp_value,/float)   ;ux
        'orieuy':self.orie_u[1]    = dm_to_number(tmp_value,/float)   ;uy
        'orieuz':self.orie_u[2]    = dm_to_number(tmp_value,/float)   ;uz
        'orievx':self.orie_v[0]    = dm_to_number(tmp_value,/float)   ;vx
        'orievy':self.orie_v[1]    = dm_to_number(tmp_value,/float)   ;vy
        'orievz':self.orie_v[2]    = dm_to_number(tmp_value,/float)   ;vz
        'oriepsi':self.orie_psi    = dm_to_number(tmp_value,/float)   ;psi
        'viewu1typ':if self.view_u1typ ne tmp_value then begin
            self.view_u1typ    = tmp_value
            self.view_u1lab[0] = self.view_label[tmp_value]
            self->my_widget_control,'viewU1lab',set_value=self.view_u1lab[0]
            resetu1 = 1 & islabel = 1
          endif
        'viewu1h': begin
            tmp     = dm_to_number(tmp_value,/float)
            resetu1 = finite(tmp)?(finite(self.view_u1[0])?((self.view_u1[0] eq tmp)?0:1):(1)):(0)
            self.view_u1[0] = tmp
          end
        'viewu1k': begin
            tmp     = dm_to_number(tmp_value,/float)
            resetu1 = finite(tmp)?(finite(self.view_u1[1])?((self.view_u1[1] eq tmp)?0:1):(1)):(0)
            self.view_u1[1] = tmp
          end
        'viewu1l': begin
            tmp     = dm_to_number(tmp_value,/float)
            resetu1 = finite(tmp)?(finite(self.view_u1[2])?((self.view_u1[2] eq tmp)?0:1):(1)):(0)
            self.view_u1[2] = tmp
          end
        'viewu1e': begin
            tmp     = dm_to_number(tmp_value,/float)
            resetu1 = finite(tmp)?(finite(self.view_u1[3])?((self.view_u1[3] eq tmp)?0:1):(1)):(0)
            self.view_u1[3] = tmp
          end
        'viewu1lab':if self.view_u1lab[(self.samp_typ ge 1)] ne tmp_value then begin
            self.view_u1lab[(self.samp_typ ge 1)] = (strlen(tmp_value) eq 0)?' ':tmp_value
            if self.samp_typ eq 0 then $
               self.view_label[self.view_u1typ] = self.view_u1lab[0]
            resetu1 = 1 & islabel = 1
          endif
        'viewu2typ':if self.view_u2typ ne tmp_value then begin
            self.view_u2typ    = tmp_value
            self.view_u2lab[0] = self.view_label[tmp_value]
            self->my_widget_control,'viewU2lab',set_value=self.view_u2lab[0]
            resetu2 = 1 & islabel = 1
          endif
        'viewu2h': begin
            tmp     = dm_to_number(tmp_value,/float)
            resetu2 = finite(tmp)?(finite(self.view_u2[0])?((self.view_u2[0] eq tmp)?0:1):(1)):(0)
            self.view_u2[0] = tmp
          end
        'viewu2k': begin
            tmp     = dm_to_number(tmp_value,/float)
            resetu2 = finite(tmp)?(finite(self.view_u2[1])?((self.view_u2[1] eq tmp)?0:1):(1)):(0)
            self.view_u2[1] = tmp
          end
        'viewu2l': begin
            tmp     = dm_to_number(tmp_value,/float)
            resetu2 = finite(tmp)?(finite(self.view_u2[2])?((self.view_u2[2] eq tmp)?0:1):(1)):(0)
            self.view_u2[2] = tmp
          end
        'viewu2e': begin
            tmp     = dm_to_number(tmp_value,/float)
            resetu2 = finite(tmp)?(finite(self.view_u2[3])?((self.view_u2[3] eq tmp)?0:1):(1)):(0)
            self.view_u2[3] = tmp
          end
        'viewu2lab':if self.view_u2lab[(self.samp_typ ge 1)] ne tmp_value then begin
            self.view_u2lab[(self.samp_typ ge 1)] = (strlen(tmp_value) eq 0)?' ':tmp_value
            if self.samp_typ eq 0 then $
               self.view_label[self.view_u2typ] = self.view_u2lab[0]
            resetu2 = 1 & islabel = 1
          endif
        'viewu3h': begin
            tmp     = dm_to_number(tmp_value,/float)
            resetu3 = finite(tmp)?(finite(self.view_u3[0])?((self.view_u3[0] eq tmp)?0:1):(1)):(0)
            self.view_u3[0] = tmp
          end
        'viewu3k': begin
            tmp     = dm_to_number(tmp_value,/float)
            resetu3 = finite(tmp)?(finite(self.view_u3[1])?((self.view_u3[1] eq tmp)?0:1):(1)):(0)
            self.view_u3[1] = tmp
          end
        'viewu3l': begin
            tmp     =  dm_to_number(tmp_value,/float)
            resetu3 = finite(tmp)?(finite(self.view_u3[2])?((self.view_u3[2] eq tmp)?0:1):(1)):(0)
            self.view_u3[2] = tmp
          end
        'viewu3e':   begin
            tmp     = dm_to_number(tmp_value,/float)
            resetu3 = finite(tmp)?(finite(self.view_u3[3])?((self.view_u3[3] eq tmp)?0:1):(1)):(0)
            self.view_u3[3] = tmp
          end
        'viewu3lab':if self.view_u3lab ne tmp_value then begin
            self.view_u3lab = (strlen(tmp_value) eq 0)?' ':tmp_value
            resetu3 = 1 & islabel = 1
          endif
        'calcprj': self->dm_calc_projection    ;calculate projection
        'dispperp': if self.disp_perp ne tmp_value then begin
            self.disp_perp = tmp_value
            self->reset_display,/reset
          endif
        'disptfrom':  self.disp_tran[0]  = dm_to_number(tmp_value,/float)
        'disptto':    self.disp_tran[1]  = dm_to_number(tmp_value,/float)
        'extrahkl':   self.disp_hkl      = tmp_value
        'hkltfrom':   self.disp_hklran[0]= dm_to_number(tmp_value,/float)
        'hkltto':     self.disp_hklran[1]= dm_to_number(tmp_value,/float)
        'dispfold':   self.disp_fold     = (1b)-self.disp_fold
        'disphfrom':  self.disp_hran[0]  = dm_to_number(tmp_value,/float)
        'disphto':    self.disp_hran[1]  = dm_to_number(tmp_value,/float)
        'disphstep':  self.disp_hstep    = dm_to_number(tmp_value,/float)
        'dispvfrom':  self.disp_vran[0]  = dm_to_number(tmp_value,/float)
        'dispvto':    self.disp_vran[1]  = dm_to_number(tmp_value,/float)
        'dispvstep':  self.disp_vstep    = dm_to_number(tmp_value,/float)
        'dispifrom':  self.disp_iran[0]  = dm_to_number(tmp_value,/float)
        'dispito':    self.disp_iran[1]  = dm_to_number(tmp_value,/float)
        'dispsmooth': self.disp_smooth   = dm_to_number(tmp_value,/int)
        'dispshading':self.disp_shading  = tmp_value
        'dispcolor':  self.disp_color    = tmp_value
        'dispfitslice': self->dm_to_fit,/slice
        'dispplotslice':self->dm_plot_slice             ;plot slice
        'dispsurfslice':self->dm_plot_slice,/surfplot   ;surf slice
        'cutx':  if self.cut_x[self.samp_typ] ne tmp_value then begin
            self.cut_x[self.samp_typ] = tmp_value
            self->reset_display,/reset
          endif
        'cutfrom':   self.cut_ran[0]   = dm_to_number(tmp_value,/float)
        'cutto':     self.cut_ran[1]   = dm_to_number(tmp_value,/float)
        'cutstep':   self.cut_step     = dm_to_number(tmp_value,/float)
        'cutt1from': self.cut_t1ran[0] = dm_to_number(tmp_value,/float)
        'cutt1to':   self.cut_t1ran[1] = dm_to_number(tmp_value,/float)
        'cutt2from': self.cut_t2ran[0] = dm_to_number(tmp_value,/float)
        'cutt2to':   self.cut_t2ran[1] = dm_to_number(tmp_value,/float)
        'cuty':      self.cut_y[self.samp_typ] = tmp_value
        'cutyfrom':  self.cut_yran[0]  = dm_to_number(tmp_value,/float)
        'cutyto':    self.cut_yran[1]  = dm_to_number(tmp_value,/float)
        'cutsymbol': self.cut_symbol   = tmp_value
        'cutcolor':  self.cut_color    = tmp_value
        'cutline':   self.cut_line     = tmp_value
        'cutfit':    self->dm_to_fit
        'cutplot':   self->dm_plot_cut
        'cutoplot':  self->dm_plot_cut,/overplot
        'trajx':     self.traj_x[self.samp_typ] = tmp_value
        'trajxfrom': self.traj_xran[0] = dm_to_number(tmp_value,/float)
        'trajxto':   self.traj_xran[1] = dm_to_number(tmp_value,/float)
        'trajy':     self.traj_y[self.samp_typ] = tmp_value
        'trajyfrom': self.traj_yran[0] = dm_to_number(tmp_value,/float)
        'trajyto':   self.traj_yran[1] = dm_to_number(tmp_value,/float)
        'trajz':     self.traj_z[self.samp_typ] = tmp_value
        'trajzfrom': self.traj_zran[0] = dm_to_number(tmp_value,/float)
        'trajzto':   self.traj_zran[1] = dm_to_number(tmp_value,/float)
        'plottra':   self->dm_plot_trajectory                ;plot trajectory
        'oplottra':  self->dm_plot_trajectory,/overplot     ;overplot trajectory
        'status':  begin  ;context menu
            menuid = widget_info(event.id,find_by_uname='contextMenu')
            status  = 'status_'+['geom','montyp','bgrate','bgdet','bgtch','bgcan','van','mask','int',$
                      'eint','bin','bincs','absp','eadj','edep','dcor']
            if !version.os_family eq 'Windows' then begin
               for i=0, n_elements(status)-1 do $
                   self->my_widget_control,status[i],menuid,/destroy
               for i=0, n_elements(status)-1 do $
                   void = dm_widget_button(menuid,_extra=self->getstatus(status[i],/init),uname=status[i])
            endif else begin
               for i=0, n_elements(status)-1 do $
                   self->my_widget_control,status[i],menuid,_extra=self->getstatus(status[i])
            endelse
            self->my_widget_control,'status_dcor',menuid,sensitive=((self.samp_typ ge 2) and (self.ftype eq 0))
            self->my_widget_control,'status_'+['montyp','eadj'],menuid,sensitive=(self.ftype eq 0)
            widget_displaycontextmenu,event.id,event.x,event.y,menuid
          end
        'status_geom':   ok = self->getstatus(strlowcase(uname),/help)
        'status_montyp': ok = self->getstatus(strlowcase(uname),/help)
        'status_bgrate': ok = self->getstatus(strlowcase(uname),/help)
        'status_bgtch':  ok = self->getstatus(strlowcase(uname),/help)
        'status_bgdet':  ok = self->getstatus(strlowcase(uname),/help)
        'status_bgcan':  ok = self->getstatus(strlowcase(uname),/help)
        'status_van':    ok = self->getstatus(strlowcase(uname),/help)
        'status_mask':   ok = self->getstatus(strlowcase(uname),/help)
        'status_int':    ok = self->getstatus(strlowcase(uname),/help)
        'status_eint':   ok = self->getstatus(strlowcase(uname),/help)
        'status_bin':    ok = self->getstatus(strlowcase(uname),/help)
        'status_bincs':  ok = self->getstatus(strlowcase(uname),/help)
        'status_absp':   ok = self->getstatus(strlowcase(uname),/help)
        'status_eadj':   ok = self->getstatus(strlowcase(uname),/help)
        'status_edep':   ok = self->getstatus(strlowcase(uname),/help)
        'status_dcor':   ok = self->getstatus(strlowcase(uname),/help)
        else:begin
            passed = self->dm_filetools(uname,event=event)  ;check for file type and file tools events
            if not passed then begin            ;view specified plot window
               all = self.gr_list->get(/all,count=count)
               for i=0,count-1 do begin
                   id = self->dm_get_id(all[i])
                   if id eq uname then begin
                      all[i]->totop
                      break
                   endif
               endfor
            endif
          end
    endcase
    if resetu1 then begin
       if n_elements(islabel) eq 0 then self->adjust_viewlabel,0
       if self.samp_typ gt 0 then begin
          if self.samp_typ eq 1 then $    ;single crystal
             tmp = self.view_u1 $
          else $                          ;diffuse scattering
             tmp = [self.view_u1[0:2],0]
          self.traj_type[3] = dm_set_viewlabel(self.view_u1lab[(self.samp_typ ge 1)],tmp)
       endif
       self->reset_trajectory,/reset
       self->reset_display,/reset
    endif
    if resetu2 then begin
       if n_elements(islabel) eq 0 then self->adjust_viewlabel,1
       if self.samp_typ gt 0 then begin
          if self.samp_typ eq 1 then $    ;single crystal
             tmp = self.view_u2 $
          else $                    ;diffuse scattering
             tmp = [self.view_u2[0:2],0]
          self.traj_type[4] = dm_set_viewlabel(self.view_u2lab[(self.samp_typ ge 1)],tmp)
       endif
       self->reset_trajectory,/reset
       self->reset_display,/reset
    endif
    if resetu3 then begin
       if n_elements(islabel) eq 0 then self->adjust_viewlabel,2
       self.traj_type[5] = dm_set_viewlabel(self.view_u3lab,self.view_u3)
       self->reset_trajectory,/reset
       self->reset_display,/reset
    endif
    if strlowcase(uname) ne 'calcprj' then self.error=0    ;reset the error flag
end

function dcs_mslice::getproperty,tlb=tlb,error=error
    catch, myerror
    if myerror ne 0 then begin
       catch,/cancel
       ok = dialog_message(!error_state.msg,/error)
       error = 1
       return,0
    end
    error = 0
    if keyword_set(tlb) then return,self.tlb
end

pro dcs_mslice::getproperty,tlb=tlb,error=error
    ;catch and ignore all errors in this program
    catch, myerror
    if myerror ne 0 then begin
       catch,/cancel
       ok = dialog_message(!error_state.msg,/error)
       error = 1
       return
    end
    error = 0
    if arg_present(tlb) then tlb=self.tlb
end

;get the status string or keywords for context sensitive menu
function dcs_mslice::getstatus,name,help=help,init=init
    status   = ''
    if keyword_set(help) then begin
       case strlowcase(name) of
           'status_geom':  status = ['Go to "Option->Instrument Geometry" to change this setting.']
           'status_montyp':status = ['Go to "Option->Monitor Count->DCS Monitor Choice" to change this setting.']
           'status_bgrate':status = ['Go to "Background->Set Overall Background Rate..." to change this value',' or',$
                                     'go to "Background->Load Dark Count File(s)" to change this value',' or',$
                                     'go to "Background->Clear Background" to clear all backgrounds.']
           'status_bgtch': status = ['Go to "Background->Load Time Channel Background File(s)" to change this value',' or',$
                                     'go to "Background->Clear Background" to clear all backgrounds.']
           'status_bgdet': status = ['Go to "Background->Load Detector Background File(s)" to change this value',' or',$
                                     'go to "Background->Clear Background" to clear all backgrounds.']
           'status_bgcan': status = ['Go to "Background->Load Empty Can File(s)" to change this value',' or',$
                                     'go to "Background->Clear Background" to clear all backgrounds.']
           'status_van':   status = ['Go to "Background->Load Vanadium File(s)" to change this value',' or',$
                                     'go to "Background->Clear Vanadium" to clear it.']
           'status_mask':  status = ['Go to Mask menu to change it',' or',$
                                     'go to "Mask->Clear Mask" to clear the existing mask.']
           'status_int':   status = ['Go to "Option->View Intensity As" to change this setting.']
           'status_eint':  status = ['Go to "Option->View Intensity As" to change this setting.']
           'status_bin':   status = ['Go to "Option->Binning Method" to change this setting.']
           'status_bincs': status = ['Go to "Option->Binning Method->Constant Intervals" to change this setting.']
           'status_eadj':  status = ['Go to "Option->Elastic Peak Position Adjustment" to change this setting.']
           'status_edep':  status = ['Go to "Option->E-Dependent Detector Efficiency Correction" to change this setting.']
           'status_dcor':  status = ['Go to "Option->Dark Angle Correction" to change this setting.']
           'status_absp':  status = ['Go to "Option->Apsorption Correction" to change this setting.']
           else:
       endcase
       ok = dialog_message(dialog_parent=self.tlb,status,/info)
       return,status
    endif
    if !version.os_family eq 'Windows' then sep=string(9b)+': ' else sep=': '
    case strlowcase(name) of
        'status_geom':  status = 'instrument geometry'+sep+(['direct','inverse'])[self.instrgeom]
        'status_montyp':status = 'monitor type'+sep+(['FC0','BM1','Duration'])[self.dcs_mon]
        'status_bgrate':begin
                        status = 'dark count'+sep
                        if ptr_valid(self.bgratePtr) then begin
                           nvalue = n_elements(*self.bgratePtr)
                           if nvalue eq 1 then $
                              status = status+dm_to_string(*self.bgratePtr)+' cts/hr/det' $
                           else $
                              status = status+'File'
                        endif else $
                           status = status+'none'
                        end
        'status_bgtch': status = 'time channel background'+sep+(ptr_valid(self.bgtchnPtr)?'yes':'none')
        'status_bgdet': status = 'detector background'+sep+(ptr_valid(self.bgdetsPtr)?'yes':'none')
        'status_bgcan': status = 'empty can'+sep+(ptr_valid(self.bgdata)?'yes':'none')
        'status_van':   status = 'detector efficiency'+sep+(ptr_valid(self.eff)?'yes':'none')
        'status_mask':  status = 'detector mask'+sep+(ptr_valid(self.mask)?'yes':'none')
        'status_int':   status = 'intensity'+sep+(['S(Q,omega)','Sym. S(Q,omega)', 'd2sigma/dOmegadEf','Chi(Q,Omega)','Unadjusted'])[self.intn_typ]
        'status_eint':  status = 'E-integrated intensity'+sep+(['no','yes'])[self.eint_yn]
        'status_bin':   status = 'binning'+sep+(['average','sum'])[self.bin_avgsum]
        'status_bincs': status = 'constant binning interval'+sep+(['no','yes'])[self.bin_conststep]
        'status_eadj':  status = 'elastic peak adjustment'+sep+(['no','yes'])[self.eadjust]
        'status_edep':  status = 'E-dep efficiency correction'+sep+(['no','yes'])[self.edep_yn]
        'status_dcor':  status = 'dark angle correction'+sep+(['no','yes'])[self.dcor_yn]
        'status_absp':  begin
                        status = 'absorption correction'+sep
                        if ptr_valid(self.absp_info) then begin
                           status = status+(['cylinder','annulus','sphere'])[(*self.absp_info)[0]]
                        endif else $
                           status = status+'none'
                        end
        else:
    endcase
    ;change the string to keywords
    if keyword_set(init) then $
       result = {value:status} $
    else $
       result = {set_value:status}
    if float(!version.release) ge 5.6 then begin
       tmp = strsplit(status,':',/extract)
       tmp = strtrim(tmp[n_elements(tmp)-1],2)
       set_button = ((tmp ne 'no') and (tmp ne 'none'))
       result = create_struct(result,'set_button',set_button)
    endif
    return,result
end

;get the device symbol font in different operating systems
function dcs_mslice::getsymbolfont,fsize
    fonts=['symbol*',$
           '-adobe-symbol-medium-r-normal--14-140-75-75-p-85-adobe-fontspecific',$
           '-adobe-symbol-medium-r-normal--14-100-100-100-p-85-adobe-fontspecific']
    fonts[0] = fonts[0]+dm_to_string(fsize+2,/int)
    catch, myerror
    if myerror ne 0 then begin
       return,fonts[0]
    end
    result = fonts[0]
    switch !version.os_family of
        'Windows':break
        'unix':
        'MacOS':begin
                spawn,'xlsfonts',result,errresult,exit_status=error
                if error ne 0 then $
                   device,get_fontnames=result,set_font='*'    ;will pop up a window, reason for using xlsfonts first
                nlist = n_elements(result)
                tmp   = bytarr(nlist)
                for i=0,nlist-1 do begin
                    tmp[i] = ((strpos(strlowcase(result[i]),'symbol'))<0)+1
                endfor
                index = where(tmp,count)
                if count ne 0 then f_list=result[index]
                nlist = n_elements(f_list)
                if nlist ne 0 then begin
                   tmp = intarr(nlist)
                   for i=0,nlist-1 do tmp[i]=dm_to_number((strsplit(f_list[i],'[A-Za-z\-]',/regex,/extract))[0],/int)
                   void = min(abs(tmp-fsize+2),index)
                   fonts[1] = f_list[index[0]]
                endif
                result = fonts[1]
                break
                end
        else:
    endswitch
    return,result
end

;a widget_control use uname instead of id as identifier
pro dcs_mslice::my_widget_control,uname,base,_ref_extra=extra
    if n_elements(base) eq 0 then base=self.tlb
    if n_elements(extra) ne 0 then begin
       for i=0,n_elements(uname)-1 do begin
           wid = widget_info(base,find_by_uname=uname[i])
           if wid ne 0 then widget_control,wid,_extra=extra
       endfor
    endif
end

;plot and set mask
;parameter:
;   detsum: [ndet], sum of the intensity at each detector
;   blist:  [ndet], non 0 elements are the index numbers of the masked detectors
;keyword:
;   angle:  if set, plot vs angle instead of vs det number
pro dcs_mslice::plot_mask,detsum,blist,angle=angle
    pblist = ptr_new(blist,/no_copy)
    ;help string
    helptext = [    $
	    "Use the mouse left button to zoom, the right button to mask/unmask. ", $
		"If ''XZOOM'' is displayed on a button in the top row, zooming only ", $
		"occurs in x. If ''XYZOOM'' is displayed zooming occurs in x and y. ", $
		"Click on the ''XZOOM/XYZOOM'' button to toggle between these states. ", $
		"If ''MASK'' is displayed on the other button in the top row, the right ", $
		"button is used to mask one or more detectors. If ''UNMASK'' is displayed ", $
		"the right button unmasks detectors. ", $
		"Click on the ''MASK/UNMASK'' button to toggle between these states. ", $
		"The sliders may also be used to define the displayed detector range. ", $
		"The most recent zoom may be ''undone'' using the ''Undo zoom'' button. ", $
		"To return to the previous user interface click the ''PROCEED'' button."]
    if keyword_set(angle) then $
       dcs_plotdetmask_2th,self.tlb,'',detsum,pblist,helptext $
    else $
       dcs_plotdetmask,self.tlb,'',detsum,pblist,helptext
    ind = where(*pblist gt 0,count)
    self->clear_mask    ;clear the mask
    if count ne 0 then begin
       self.mask = ptr_new((*pblist)[ind]-1)
       self->my_widget_control,['mksvBut','mkclBut'],sensitive=1
    endif
    ptr_free,pblist
end

;reset droplist values according to the labels
pro dcs_mslice::reset_droplist
    if self.samp_typ gt 0 then begin
       if self.samp_typ eq 1 then begin ;single crystal
          tmp1 = self.view_u1
          tmp2 = self.view_u2
       endif else begin                 ;diffuse scattering
          tmp1 = [self.view_u1[0:2],0]
          tmp2 = [self.view_u2[0:2],0]
       endelse
       self.traj_type[3] = dm_set_viewlabel(self.view_u1lab[1],tmp1)
       self.traj_type[4] = dm_set_viewlabel(self.view_u2lab[1],tmp2)
       self.traj_type[5] = dm_set_viewlabel(self.view_u3lab,self.view_u3)
       if self.samp_typ ge 2 then $     ;E for the diffuse scattering type
       self.traj_type[5] = dm_set_viewlabel('E',[0,0,0,1])  ;diffuse scattering type
    endif
end

;(re)create all the data file widgets
pro dcs_mslice::reset_file
    if not obj_valid(self.fileSel) then begin ;create the widgets
       self.fileBas = widget_base(self.tlb,/row,/frame,ypad=1,xpad=0,space=0,map=0)
       widget_control,self.fileBas,update=0
       if !version.os_family eq 'unix' then ysize=11 else ysize=9
       self.fileSel = obj_new('dm_filesel',parent=self.fileBas, filter='.'+(*self.ftypeext)[self.ftype],$
           ysize=ysize,ypad=0,group_leader=self.tlb)
       ;get the correct path separator
       defsysv,'!dave_defaults',exists=exists
       if exists then $
          if ptr_valid(!dave_defaults) then self.fileSel->set_path,(*!dave_defaults).datDir
       fileCol   = widget_base(self.fileBas,/col,/align_bottom,ypad=0,xpad=0,space=0)
       sampleRow = widget_base(fileCol,/row,ypad=0,xpad=0,space=0)
       samplab   = widget_label(sampleRow,value='aa (deg)',/align_center)
       geom      = widget_info(samplab,/geometry)
       if strlen(self.symfont) eq 0 then self.symfont=self->getsymbolfont(2*(fix(geom.scr_ysize)/2))
       self.xsize[1] = geom.xsize
       widget_control,samplab,set_value='Sample'
       sampTyp   = dm_widget_button(sampleRow,value='Powder',/menu,xsize=168,uname='sampTyp')
       if float(!version.release) ge 5.6 then $
          widget_control,sampTyp,tooltip='Press to select a sample type.'
       powdBut   = dm_widget_button(sampTyp,value='Powder',uname='powdTyp')
       crystTyp  = widget_button(sampTyp,value='Single Crystal',uname='crystTyp',/menu)
       sct1But   = dm_widget_button(crystTyp,value='Single Crystal',uname='crystTyp1')
       sct2But   = dm_widget_button(crystTyp,value='Diffuse Scattering Single E',uname='crystTyp2')
       sct3But   = dm_widget_button(crystTyp,value='Diffuse Scattering Multiple E',uname='crystTyp3')
       ebinRow   = widget_base(fileCol,/row,ypad=0,xpad=0,space=0)
       ebinLab   = widget_label(ebinRow,value='E rebin size',/align_center,uname='ebinLab')
       eBin      = dm_widget_droplist(ebinRow,xsize=170,uname='eBin')
       labelRow  = widget_base(fileCol,/row,ypad=0,xpad=0,space=0)
       intn_lab  = widget_label(labelRow,value='Intensity Label',/align_center)
       intnLab   = widget_text(labelRow,value='',/editable,/all_events,uname='intnLab')
       labelRow  = widget_base(fileCol,/row,ypad=0,xpad=0,space=0)
       titl_lab  = widget_label(labelRow,value='Title Label',/align_center)
       titlLab   = widget_text(labelRow,value='',/editable,/all_events,uname='titlLab')
       labelRow  = widget_base(fileCol,/row,ypad=0,xpad=0,space=0)
       legd_lab  = widget_label(labelRow,value='Legend Label',/align_center)
       legdLab   = widget_text(labelRow,value='',/editable,/all_events,uname='legdLab')
       loadRow   = widget_base(fileCol,/row,ypad=0,xpad=0,space=0,/align_right)
       loadBut   = widget_button(loadRow,value='Load Data',uname='loadBut',xsize=self.xsize[4])
       addBut    = widget_button(loadRow,value='Add Data',uname='addBut',sensitive=0,xsize=self.xsize[4])
       geom      = widget_info(intn_lab,/geometry)
       xsize     = geom.xsize+40
       widget_control,samplab,xsize=xsize
       widget_control,intn_lab,xsize=xsize
       widget_control,titl_lab,xsize=xsize
       widget_control,legd_lab,xsize=xsize
       widget_control,ebinLab,xsize=xsize
       geom      = widget_info(loadRow,/geometry)
       widget_control,intnLab,scr_xsize=geom.xsize
       widget_control,titlLab,scr_xsize=geom.xsize
       widget_control,legdLab,scr_xsize=geom.xsize
       geom      = widget_info(self.fileBas,/geometry)
       self.xsize[0] = geom.xsize
       row       = widget_base(fileCol,/row,xpad=0,ypad=0,/align_right,space=0)
       clearDat  = widget_button(row,value='Clear Data',uname='clearDat',sensitive=0,xsize=self.xsize[4]*2)
       widget_control,self.fileBas,/update,/map
       self.xsize[4] = 67+5*(!version.os_family eq 'Windows')
    endif
    ;reset all values
    tmp = self.samp_typ & self.samp_typ = -1
    self->change_samptyp,tmp,/init
    if self.samp_typ ge 2 then begin    ;diffuse scattering
       self->my_widget_control,'ebinLab',set_value='Energy Range'
       self->my_widget_control,'eBin',set_value=['All','Elastic Peak','Specify']
       tmp = self.e_bin[self.samp_typ]
       if tmp gt 2 then begin
          tmp = 1
          self.e_bin[self.samp_typ] = 1    ;default elastic peak
       end
    endif else begin
       self->my_widget_control,'ebinLab',set_value='E Rebin Size'
       self->my_widget_control,'eBin',set_value=dm_to_string(*(self.rebinsize))
       tmp = where(*(self.rebinsize) eq self.e_bin[self.samp_typ],count)
       if count eq 0 then self.e_bin[self.samp_typ]=1
       tmp = (0>(tmp[0]))
    endelse
    dm_set_droplist,widget_info(self.tlb,find_by_uname='eBin'),select=tmp
    self->my_widget_control,'intnLab',set_value=self.intn_lab
    self->my_widget_control,'titlLab',set_value=self.titl_lab
    self->my_widget_control,'legdLab',set_value=self.legd_lab
end

;(re)create and set values of all the widgets in self.projBas
;keyword:
;   reset:    if set, only set the existing widget values, otherwise regenerate all the widgets
pro dcs_mslice::reset_projection,reset=reset
    if not keyword_set(reset) then begin ;(re)generate all the widgets
       if widget_info(self.projBas,/valid_id) eq 0 then begin
          self.projBas = widget_base(self.tlb,/frame,xpad=0,ypad=0,map=0,space=0,xsize=self.xsize[0])
       endif
       widget_control,self.projBas,update=0
       if self.view[0] eq 0 then return
       extra = widget_base(self.projBas,/col,ypad=1,xpad=0)
       switch self.samp_typ of
         0:begin ;powder
           row    = widget_base(extra,/row,ypad=0,xpad=0,space=0)
           left   = widget_base(row,/col,xpad=0,ypad=0)
           right  = widget_base(row,/col,xpad=0,ypad=0,/align_bottom)
           label  = widget_label(left,value='  Viewing Axes:',/align_left,uname='viewAxis')
           row    = widget_base(left,/row,ypad=0,xpad=0,space=0)
           label  = widget_label(row,value='',xsize=self.xsize[1]+self.xsize[2])
           label2 = widget_label(row,value='Label',/align_center)
           row    = widget_base(left,/row,ypad=0,xpad=0)
           label  = widget_label(row,value='u1',xsize=self.xsize[1],/align_center)
           viewU1typ = dm_widget_droplist(row,value=self.view_type,xsize=self.xsize[2],uname='viewU1typ')
           viewU1lab = widget_text(row,value='',xsize=self.xsize[3],/editable,/all_events,ysize=1,uname='viewU1lab')
           geom   = widget_info(viewU1lab,/geometry)
           widget_control,label2,xsize=geom.scr_xsize
           row    = widget_base(left,/row,ypad=0,xpad=0)
           label  = widget_label(row,value='u2',xsize=self.xsize[1],/align_center)
           viewU2typ = dm_widget_droplist(row,value=self.view_type,xsize=self.xsize[2],uname='viewU2typ')
           viewU2lab = widget_text(row,value='',xsize=self.xsize[3],/editable,/all_events,ysize=1,uname='viewU2lab')
           geom   = widget_info(left,/geom)
           widget_control,right,xsize=self.xsize[0]-geom.xsize-1,/context_events
           break
           end
         1:         ;single crystal
         2:         ;diffuse scattering single E
         3:begin    ;diffuse scattering multiple E
           toprow  = widget_base(extra,/row,ypad=0,xpad=0,space=0)
           left    = widget_base(toprow,/col,ypad=0,xpad=0)
           row     = widget_base(left,/row,ypad=0,xpad=0,space=0)
           label   = widget_label(row,value='  Unit Cell Lattice Parameters:')
           row     = widget_base(left,/row,ypad=0,xpad=0)
           label   = widget_label(row,value='a ('+string('c5'XB)+')',xsize=self.xsize[1],/align_center)
           lattA   = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='lattA')
           label   = widget_label(row,value='b ('+string('c5'XB)+')',xsize=self.xsize[1],/align_center)
           lattB   = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='lattB')
           label   = widget_label(row,value='c ('+string('c5'XB)+')',xsize=self.xsize[1],/align_center)
           lattC   = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='lattC')
           row     = widget_base(left,/row,ypad=0,xpad=0)
           label   = widget_label(row,value='a ('+string('B0'XB)+')',xsize=self.xsize[1],/align_center,font=self.symfont)
           lattAA  = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='lattAA')
           label   = widget_label(row,value='b ('+string('B0'XB)+')',xsize=self.xsize[1],/align_center,font=self.symfont)
           lattBB  = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='lattBB')
           label   = widget_label(row,value='g ('+string('B0'XB)+')',xsize=self.xsize[1],/align_center,font=self.symfont)
           lattCC  = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='lattCC')
           geom    = widget_info(left,/geometry)
           xsize   = self.xsize[0]-geom.xsize
           right   = widget_base(toprow,/col,ypad=0,xpad=0,xsize=xsize)
           xsize   = fix(xsize/6.,type=3)
           row     = widget_base(right,/row,ypad=0,xpad=0,space=0)
           label   = widget_label(row,value='  Crystal Orientation:')
           row     = widget_base(right,/row,ypad=0,xpad=0,space=0)
           label   = widget_label(row,value='ux',xsize=xsize,/align_center)
           orieUx  = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='orieUx')
           label   = widget_label(row,value='uy',xsize=xsize,/align_center)
           orieUy  = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='orieUy')
           label   = widget_label(row,value='uz',xsize=xsize,/align_center)
           orieUz  = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='orieUz')
           row     = widget_base(right,/row,ypad=0,xpad=0,space=0)
           label   = widget_label(row,value='vx',xsize=xsize,/align_center)
           orieVx  = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='orieVx')
           label   = widget_label(row,value='vy',xsize=xsize,/align_center)
           orieVy  = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='orieVy')
           label   = widget_label(row,value='vz',xsize=xsize,/align_center)
           orieVz  = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='orieVz')
           row     = widget_base(right,/row,ypad=0,xpad=0,space=0)
           label   = widget_label(row,value='Psi',/align_center,xsize=xsize)
           oriePsi = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='oriePsi')
           oriepsiLab = widget_label(row,value='  angle of ki^u',uname='oriepsiLab',/dynamic_resize)   ; positive if (ki x u)||Qz (up)
           row     = widget_base(extra,/row,ypad=0,xpad=0,space=0)
           left    = widget_base(row,/col,xpad=0,ypad=0)
           right   = widget_base(row,/col,xpad=0,ypad=0,/align_bottom)
           label   = widget_label(left,value='  Orthogonal Viewing Axes:',/align_left,uname='viewAxis')
           row     = widget_base(left,/row,ypad=0,xpad=0)
           label   = widget_label(row,value='',xsize=self.xsize[1],/align_center)
           label   = widget_label(row,value='a*',xsize=self.xsize[1],/align_center)
           label   = widget_label(row,value='b*',xsize=self.xsize[1],/align_center)
           label   = widget_label(row,value='c*',xsize=self.xsize[1],/align_center)
           if self.samp_typ eq 1 then $
              label = widget_label(row,value='Energy',xsize=self.xsize[1],/align_center)
           label1  = widget_label(row,value='Label',xsize=self.xsize[1],/align_center)
           row     = widget_base(left,/row,ypad=0,xpad=0)
           label   = widget_label(row,value='u1',xsize=self.xsize[1],/align_center)
           viewU1h = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='viewU1h')
           viewU1k = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='viewU1k')
           viewU1l = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='viewU1l')
           if self.samp_typ eq 1 then $
              viewU1e = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='viewU1e')
           viewU1lab = widget_text(row,value='',xsize=self.xsize[3],/editable,/all_events,ysize=1,uname='viewU1lab')
           geom    = widget_info(viewU1lab,/geom)
           widget_control,label1,xsize=geom.scr_xsize
           row     = widget_base(left,/row,ypad=0,xpad=0)
           label   = widget_label(row,value='u2',xsize=self.xsize[1],/align_center)
           viewU2h = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='viewU2h')
           viewU2k = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='viewU2k')
           viewU2l = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='viewU2l')
           if self.samp_typ eq 1 then $
              viewU2e = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='viewU2e')
           viewU2lab = widget_text(row,value='',xsize=self.xsize[3],/editable,/all_events,ysize=1,uname='viewU2lab')
           if self.samp_typ eq 1 then begin
              row     = widget_base(left,/row,ypad=0,xpad=0)
              label   = widget_label(row,value='u3',xsize=self.xsize[1],/align_center)
              viewU3h = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='viewU3h')
              viewU3k = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='viewU3k')
              viewU3l = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='viewU3l')
              viewU3e = widget_text(row,value='',scr_xsize=self.xsize[1],/editable,/all_events,ysize=1,uname='viewU3e')
              viewU3lab = widget_text(row,value='',xsize=self.xsize[3],/editable,/all_events,ysize=1,uname='viewU3lab')
           endif
           geom =widget_info(left,/geom)
           widget_control,right,xsize=self.xsize[0]-geom.xsize-1,/context_events
           break
           end
         else:
       endswitch
       row     = widget_base(right,/row,xpad=0,ypad=0,/align_right,space=0)
       calcPrj = widget_button(row,value='Calculate Projections',uname='calcPrj',xsize=self.xsize[4]*2)
       if float(!version.release) ge 5.6 then begin  ;tips for some widget buttons
          widget_control,calcPrj,tooltip='Calculate the projection before any plots can be made.'
       endif
       context = widget_base(right,/CONTEXT_MENU,UNAME='contextMenu')
       status  = 'status_'+['geom','montyp','bgrate','bgdet','bgtch','bgcan','van','mask','int',$
                      'eint','bin','bincs','absp','eadj','edep','dcor']
       for i=0, n_elements(status)-1 do $
           void = dm_widget_button(context,_extra=self->getstatus(status[i],/init),uname=status[i])
       self->my_widget_control,'status_dcor',sensitive=((self.samp_typ ge 2) and (self.ftype eq 0))
    endif
    if self.view[0] eq 0 then return
    ;now set all the values
    switch self.samp_typ of
      0:begin   ;powder
        value = self.view_type[0:3+(self.ftype eq 0?1:0)]
        if (self.ftype gt 0) and (self.view_u1typ eq 4) then begin
           self.view_u1typ = 1
           self.view_u1lab[0] = self.view_label[self.view_u1typ]
        endif
        if (self.ftype gt 0) and (self.view_u2typ eq 4) then begin
           self.view_u2typ = 0
           self.view_u2lab[0] = self.view_label[self.view_u2typ]
        endif
        dm_set_droplist,widget_info(self.projBas,find_by_uname='viewU1typ'),set_value=value,select=self.view_u1typ
        dm_set_droplist,widget_info(self.projBas,find_by_uname='viewU2typ'),set_value=value,select=self.view_u2typ
        break
        end
      1:        ;single crystal
      2:        ;diffuse scattering single energy
      3:begin   ;diffuse scattering multiple energy
        self->my_widget_control,'viewAxis',self.projBas,set_value=(self.view_ortharbi?'  Viewing Axes:':'  Orthogonal Viewing Axes:')
        self->my_widget_control,'lattA',self.projBas,set_value=dm_to_string(float(self.latt_parm[0]))
        self->my_widget_control,'lattB',self.projBas,set_value=dm_to_string(float(self.latt_parm[1]))
        self->my_widget_control,'lattC',self.projBas,set_value=dm_to_string(float(self.latt_parm[2]))
        self->my_widget_control,'lattAA',self.projBas,set_value=dm_to_string(float(self.latt_parm[3]))
        self->my_widget_control,'lattBB',self.projBas,set_value=dm_to_string(float(self.latt_parm[4]))
        self->my_widget_control,'lattCC',self.projBas,set_value=dm_to_string(float(self.latt_parm[5]))
        self->my_widget_control,'orieUx',self.projBas,set_value=dm_to_string(self.orie_u[0],/int)
        self->my_widget_control,'orieUy',self.projBas,set_value=dm_to_string(self.orie_u[1],/int)
        self->my_widget_control,'orieUz',self.projBas,set_value=dm_to_string(self.orie_u[2],/int)
        self->my_widget_control,'orieVx',self.projBas,set_value=dm_to_string(self.orie_v[0],/int)
        self->my_widget_control,'orieVy',self.projBas,set_value=dm_to_string(self.orie_v[1],/int)
        self->my_widget_control,'orieVz',self.projBas,set_value=dm_to_string(self.orie_v[2],/int)
        self->my_widget_control,'oriePsi',self.projBas,set_value=dm_to_string(self.orie_psi)
        self->my_widget_control,'viewU1h',self.projBas,set_value=dm_to_string(self.view_u1[0],/int)
        self->my_widget_control,'viewU1k',self.projBas,set_value=dm_to_string(self.view_u1[1],/int)
        self->my_widget_control,'viewU1l',self.projBas,set_value=dm_to_string(self.view_u1[2],/int)
        self->my_widget_control,'viewU2h',self.projBas,set_value=dm_to_string(self.view_u2[0],/int)
        self->my_widget_control,'viewU2k',self.projBas,set_value=dm_to_string(self.view_u2[1],/int)
        self->my_widget_control,'viewU2l',self.projBas,set_value=dm_to_string(self.view_u2[2],/int)
        if self.samp_typ eq 1 then begin
           self->my_widget_control,'viewU1e',self.projBas,set_value=dm_to_string(self.view_u1[3],/int)
           self->my_widget_control,'viewU2e',self.projBas,set_value=dm_to_string(self.view_u2[3],/int)
           self->my_widget_control,'viewU3h',self.projBas,set_value=dm_to_string(self.view_u3[0],/int)
           self->my_widget_control,'viewU3k',self.projBas,set_value=dm_to_string(self.view_u3[1],/int)
           self->my_widget_control,'viewU3l',self.projBas,set_value=dm_to_string(self.view_u3[2],/int)
           self->my_widget_control,'viewU3e',self.projBas,set_value=dm_to_string(self.view_u3[3],/int)
           self->my_widget_control,'viewU3lab',self.projBas,set_value=self.view_u3lab
           self->my_widget_control,'oriepsiLab',self.projBas,set_value='  angle of ki^u'  ; positive if (ki x u)||Qz (up)
        endif else begin
           self->my_widget_control,'oriepsiLab',self.projBas,set_value='  first angle of ki^u'; positive if (ki x u)||Qz (up)
        endelse
        break
        end
      else:
    endswitch
    self->my_widget_control,'viewU1lab',self.projBas,set_value=self.view_u1lab[(self.samp_typ ge 1)]
    self->my_widget_control,'viewU2lab',self.projBas,set_value=self.view_u2lab[(self.samp_typ ge 1)]
end

;(re)create and set values of all the widgets in self.dispBas
;keyword:
;   reset:    if set, only set the existing widget values, otherwise regenerate all the widgets
pro dcs_mslice::reset_display,reset=reset
    if not keyword_set(reset) then begin   ;(re)generate all the widgets
       if widget_info(self.dispBas,/valid_id) eq 0 then $
          self.dispBas = widget_base(self.tlb,/frame,xpad=0,ypad=0,map=0,space=0,xsize=self.xsize[0])
       widget_control,self.dispBas,update=0
       if self.view[1] eq 0 then return
       extra = widget_base(self.dispBas,/col,xpad=0,ypad=1)
       xsize = fix((self.xsize[0]-3.*self.xsize[1]-self.xsize[2])/4.,type=3)
       self.xsize[4] = xsize
       ;adjust button size
       calcPrj     = widget_info(self.projBas,find_by_uname='calcPrj')
       if calcPrj ne 0 then $
          widget_control,calcPrj,scr_xsize=self.xsize[4]*2
       slice_label = ['  Display:','  Slice Plane:','  Display:','  Slice Plane:']
       row         = widget_base(extra,/row,xpad=0,ypad=0,space=0)
       label       = widget_label(row,value=slice_label[self.samp_typ])
       if (self.samp_typ eq 1) or (self.samp_typ eq 3) then begin
          row      = widget_base(extra,/row,xpad=0,ypad=0,space=0)
          label    = widget_label(row,value='perp to',xsize=self.xsize[1],/align_center)
          dispPerp = dm_widget_droplist(row,value=self.traj_type[3:5],xsize=self.xsize[2],uname='dispPerp')
          label    = widget_label(row,value='thick',xsize=self.xsize[1],/align_center)
          dispTfrom= widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='dispTfrom')
          label    = widget_label(row,value='to:',xsize=self.xsize[1],/align_center)
          dispTto  = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='dispTto')
          label    = widget_label(row,value='',xsize=10)
          exclbas  = widget_base(row,/row,xpad=0,ypad=0,space=0,/nonexclusive)
          dispFold = widget_button(exclbas,value = 'Fold x-axis',uname='dispFold')
       endif
       row       = widget_base(extra,/row,xpad=0,ypad=0,space=0)
       label     = widget_label(row,value='',xsize=self.xsize[1],/align_center)
       label     = widget_label(row,value='H Label',xsize=self.xsize[1]+self.xsize[2],/align_center,uname='h_label')
       dispHfrom = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='dispHfrom')
       label     = widget_label(row,value='to:',xsize=self.xsize[1],/align_center)
       dispHto   = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='dispHto')
       label     = widget_label(row,value='step',xsize=xsize,/align_center)
       dispHstep = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='dispHstep')
       row       = widget_base(extra,/row,xpad=0,ypad=0,space=0)
       label     = widget_label(row,value='',xsize=self.xsize[1],/align_center)
       label     = widget_label(row,value='V Label',xsize=self.xsize[1]+self.xsize[2],/align_center,uname='v_label')
       dispVfrom = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='dispVfrom')
       label     = widget_label(row,value='to:',xsize=self.xsize[1],/align_center)
       dispVto   = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='dispVto')
       label     = widget_label(row,value='step',xsize=xsize,/align_center)
       dispVstep = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='dispVstep')
       if (self.samp_typ ne 0) and self.hklran_yn then begin
          row      = widget_base(extra,/row,xpad=0,ypad=0,space=0)
          label    = widget_label(row,value='',xsize=self.xsize[1],/align_center)
          extraHKL = dm_widget_droplist(row,value=self.traj_type[0:2],xsize=self.xsize[2],uname='extraHKL')
          label    = widget_label(row,value='thick',xsize=self.xsize[1],/align_center)
          hklTfrom = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='hklTfrom')
          label    = widget_label(row,value='to:',xsize=self.xsize[1],/align_center)
          hklTto   = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='hklTto')
          label    = widget_label(row,value='  <-- also used in cut',xsize=xsize*2-5,/align_left)
       endif
       row       = widget_base(extra,/row,xpad=0,ypad=0,space=0)
       label     = widget_label(row,value='',xsize=self.xsize[1],/align_center)
       label     = widget_label(row,value='intensity range',xsize=self.xsize[1]+self.xsize[2],/align_center)
       dispIfrom = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='dispIfrom')
       label     = widget_label(row,value='to:',xsize=self.xsize[1],/align_center)
       dispIto   = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='dispIto')
       label     = widget_label(row,value='color    map ',xsize=xsize*1.5,/align_center)
       row   = widget_base(extra,/row,xpad=0,ypad=0,space=0)
       label = widget_label(row,value='',xsize=self.xsize[1],/align_center)
       label = widget_label(row,value='smoothing level',xsize=self.xsize[1]+self.xsize[2],/align_center)
       dispSmooth = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='dispSmooth')
       label = widget_label(row,value='shading',xsize=self.xsize[1],/align_center)
       dispShading   = dm_widget_droplist(row,value=['Flat','Gouraud'],xsize=xsize,uname='dispShading')
       dispColor     = dm_widget_droplist(row,value=self.dispcmap,xsize=xsize*2,uname='dispColor')
       row       = widget_base(extra,/row,xpad=0,ypad=0,space=0)
       label     = widget_label(row,value='',xsize=3*self.xsize[1]+self.xsize[2]+xsize,/align_center)
       dispFitSlice  = widget_button(row,value='Fit',xsize=xsize,sensitive=0,uname='dispFitSlice')
       dispPlotSlice = widget_button(row,value='Plot Slice',xsize=xsize,sensitive=0,uname='dispPlotSlice')
       dispSurfSlice = widget_button(row,value='Surf Slice',xsize=xsize,sensitive=0,uname='dispSurfSlice')
       row   = widget_base(extra,/row,xpad=0,ypad=0,space=0,/align_left)
       label = widget_label(row,value='  Cut:',xsize=self.xsize[1],/align_center)
       row   = widget_base(extra,/row,xpad=0,ypad=0,space=0)
       label = widget_label(row,value='along',xsize=self.xsize[1],/align_center)
       case self.samp_typ of
         0:cutX = dm_widget_droplist(row,value=[self.view_u1lab[0],self.view_u2lab[0]],xsize=self.xsize[2],uname='cutX') ;powder
         1:cutX = dm_widget_droplist(row,value=self.traj_type[3:5],xsize=self.xsize[2],uname='cutX')    ;single crystal
         2:cutX = dm_widget_droplist(row,value=self.traj_type[3:4],xsize=self.xsize[2],uname='cutX')    ;diffuse scattering single E
         3:cutX = dm_widget_droplist(row,value=self.traj_type[3:5],xsize=self.xsize[2],uname='cutX')    ;diffuse scattering multipe E
         else:
       endcase
       label    = widget_label(row,value='from:',xsize=self.xsize[1],/align_center)
       cutFrom  = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='cutFrom')
       label    = widget_label(row,value='to:',xsize=self.xsize[1],/align_center)
       cutTo    = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='cutTo')
       label    = widget_label(row,value='step',xsize=xsize,/align_center)
       cutStep  = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='cutStep')
       row      = widget_base(extra,/row,xpad=0,ypad=0,space=0)
       label    = widget_label(row,value='',xsize=self.xsize[1],/align_center)
       label    = widget_label(row,value='T1 Label',xsize=self.xsize[1]+self.xsize[2],/align_center,uname='t1_label')
       cutT1from= widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='cutT1from')
       label    = widget_label(row,value='to:',xsize=self.xsize[1],/align_center)
       cutT1to  = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='cutT1to')
       if (self.samp_typ eq 1) or (self.samp_typ eq 3) then begin
          row   = widget_base(extra,/row,xpad=0,ypad=0,space=0)
          label = widget_label(row,value='',xsize=self.xsize[1],/align_center)
          label = widget_label(row,value='T2 Label',xsize=self.xsize[1]+self.xsize[2],/align_center,uname='t2_label')
          cutT2from = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='cutT2from')
          label = widget_label(row,value='to:',xsize=self.xsize[1],/align_center)
          cutT2to = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='cutT2to')
       endif
       if (!version.os_family eq 'Windows') or (float(!version.release) ge 5.6) then begin
          label = widget_label(row,value='symbol',xsize=xsize,/align_center)
          cutColor = dm_widget_droplist(row,value=self.colors,xsize=xsize,uname='cutColor')
       endif
       row   = widget_base(extra,/row,xpad=0,ypad=0,space=0)
       label = widget_label(row,value='y',xsize=self.xsize[1],/align_center)
       case self.samp_typ of
         0:cutY = dm_widget_droplist(row,value=['Intensity',self.view_type[0:3]],xsize=self.xsize[2],uname='cutY') ;powder
         1:cutY = dm_widget_droplist(row,value=['Intensity',self.traj_type[0:6]],xsize=self.xsize[2],uname='cutY') ;single crystal
         2:cutY = dm_widget_droplist(row,value=['Intensity',self.traj_type[0:4]],xsize=self.xsize[2],uname='cutY') ;diffuse scattering single E
         3:cutY = dm_widget_droplist(row,value=['Intensity',self.traj_type[0:5]],xsize=self.xsize[2],uname='cutY') ;diffuse scattering multiple E
         else:
       endcase
       label    = widget_label(row,value='range',xsize=self.xsize[1],/align_center)
       cutYfrom = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='cutYfrom')
       label    = widget_label(row,value='to:',xsize=self.xsize[1],/align_center)
       cutYto   = widget_text(row,value='',scr_xsize=xsize,/editable,/all_events,ysize=1,uname='cutYto')
       if (!version.os_family eq 'Windows') or (float(!version.release) ge 5.6)  then begin
          cutSymbol = dm_widget_droplist(row,value=self.symbols,xsize=xsize,uname='cutSymbol')
          cutLine   = dm_widget_droplist(row,value=self.lines,xsize=xsize,uname='cutLine')
          row       = widget_base(extra,/row,xpad=0,ypad=0,space=0)
          label     = widget_label(row,value='',xsize=3*self.xsize[1]+self.xsize[2]+xsize,/align_center)
          cutFit    = widget_button(row,value='Fit',xsize=xsize,sensitive=0,uname='cutFit')
          cutPlot   = widget_button(row,value='Plot Cut',xsize=xsize,sensitive=0,uname='cutPlot')
          cutOplot  = widget_button(row,value='Oplot Cut',xsize=xsize,sensitive=0,uname='cutOplot')
       endif else begin
          row       = widget_base(extra,/row,xpad=0,ypad=0,space=0)
          label     = widget_label(row,value='',xsize=self.xsize[1],/align_center)
          tmprow    = widget_base(row,/row,xpad=0,ypad=0,space=0,xsize=2*self.xsize[1]+self.xsize[2]+2*xsize)
          label     = widget_label(tmprow,value='symbol',/align_center)
          cutColor  = widget_droplist(tmprow,value=self.colors,uname='cutColor')
          cutSymbol = widget_droplist(tmprow,value=self.symbols,uname='cutSymbol')
          cutLine   = widget_droplist(tmprow,value=self.lines,uname='cutLine')
          cutPlot   = widget_button(row,value='Plot Cut',xsize=xsize,sensitive=0,uname='cutPlot')
          cutOplot  = widget_button(row,value='Oplot Cut',xsize=xsize,sensitive=0,uname='cutOplot')
          row       = widget_base(extra,/row,xpad=0,ypad=0,space=0)
          label     = widget_label(row,value='',xsize=3*self.xsize[1]+self.xsize[2]+3.*xsize,/align_center)
          cutFit    = widget_button(row,value='Fit',xsize=xsize,sensitive=0,uname='cutFit')
       endelse

       if float(!version.release) ge 5.6 then begin  ;tips for some widget buttons
          widget_control,dispFitSlice,tooltip='Fit the grouped slice data in PAN(Peak Analysis).'
          widget_control,dispPlotSlice,tooltip='Contour plot the slice.'
          widget_control,dispSurfSlice,tooltip='Surface plot the slice.'
          widget_control,cutOplot,tooltip='Overplot the cut in the current plot window.'
          widget_control,cutFit,tooltip='Fit the cut data in PAN(Peak Analysis).'
       endif
    endif
    ;set all the values
    self->set_display_button    ;include some menu buttons and all display buttons
    if self.view[1] eq 0 then return
    case self.samp_typ of
      0:begin  ;powder
        self->my_widget_control,'cutX',self.dispBas,set_value=[self.view_u1lab[0],self.view_u2lab[0]]
        self->my_widget_control,'cutY',self.dispBas,set_value=['Intensity',self.view_type[0:3]]
        end
      1:begin  ;single crystal
        dm_set_droplist,widget_info(self.dispBas,find_by_uname='dispPerp'),set_value=self.traj_type[3:5],select=self.disp_perp
        self->my_widget_control,'dispTfrom',self.dispBas,set_value=dm_to_string(self.disp_tran[0])
        self->my_widget_control,'dispTto',self.dispBas,set_value=dm_to_string(self.disp_tran[1])
        self->my_widget_control,'dispFold',self.dispBas,set_button=self.disp_fold
        self->my_widget_control,'cutX',self.dispBas,set_value=self.traj_type[3:5]
        self->my_widget_control,'cutT2from',self.dispBas,set_value=dm_to_string(self.cut_t2ran[0])
        self->my_widget_control,'cutT2to',self.dispBas,set_value=dm_to_string(self.cut_t2ran[1])
        self->my_widget_control,'cutY',self.dispBas,set_value=['Intensity',self.traj_type[0:6]]
        end
      2:begin  ;diffuse scattering single E
        self->my_widget_control,'cutX',self.dispBas,set_value=self.traj_type[3:4]
        self->my_widget_control,'cutY',self.dispBas,set_value=['Intensity',self.traj_type[0:4]]
        end
      3:begin
        self->my_widget_control,'cutX',self.dispBas,set_value=self.traj_type[3:5]
        self->my_widget_control,'cutY',self.dispBas,set_value=['Intensity',self.traj_type[0:5]]
        dm_set_droplist,widget_info(self.dispBas,find_by_uname='dispPerp'),set_value=self.traj_type[3:5],select=self.disp_perp
        self->my_widget_control,'dispTfrom',self.dispBas,set_value=dm_to_string(self.disp_tran[0])
        self->my_widget_control,'dispTto',self.dispBas,set_value=dm_to_string(self.disp_tran[1])
        self->my_widget_control,'dispFold',self.dispBas,set_button=self.disp_fold
        self->my_widget_control,'cutT2from',self.dispBas,set_value=dm_to_string(self.cut_t2ran[0])
        self->my_widget_control,'cutT2to',self.dispBas,set_value=dm_to_string(self.cut_t2ran[1])
        end
      else:
    endcase
    ;intelligent cut step
    notE = [([self.view_u1typ,self.view_u2typ])[self.cut_x[0]] ne 0,$
            ([self.view_u1[3],self.view_u2[3],self.view_u3[3]])[self.cut_x[1]] ne 1,1b,$
            ([0,0,1])[self.cut_x[3]] ne 1]
    if notE[self.samp_typ] and (not finite(self.cut_step)) then self.cut_step=0.01
    viewlbs = [self.view_u1lab[(self.samp_typ ge 1)],self.view_u2lab[(self.samp_typ ge 1)],self.view_u3lab]
    if self.samp_typ eq 3 then viewlbs[2] = 'E'
    head    = ['horizontal range ','vertical range ']
    names0  = ['h_label','v_label']
    names1  = ['t1_label','t2_label']
    for i=0,1 do begin
        labels = head[i]+[viewlbs[i],viewlbs[(self.disp_perp+i+1) mod 3],viewlbs[i],$
                 viewlbs[(self.disp_perp+i+1) mod 3]]
        self->my_widget_control,names0[i],self.dispBas,set_value=labels[self.samp_typ]
        ;intelligent step
        notE = [([self.view_u1typ,self.view_u2typ])[i] ne 0,$
                ([self.view_u1[3],self.view_u2[3],self.view_u3[3]])[(self.disp_perp+i+1) mod 3] ne 1,$
                1b,([0,0,1])[(self.disp_perp+i+1) mod 3] ne 1]
        if notE[self.samp_typ] then begin
           if (i eq 0) and (not finite(self.disp_hstep)) then self.disp_hstep=0.035
           if (i eq 1) and (not finite(self.disp_vstep)) then self.disp_vstep=0.035
        endif
        labels = 'thickness range '+[viewlbs[(self.cut_x[0]+i+1) mod 2],viewlbs[(self.cut_x[1]+i+1) mod 3],$
                 viewlbs[(self.cut_x[2]+i+1) mod 2],viewlbs[(self.cut_x[3]+i+1) mod 3]]
        self->my_widget_control,names1[i],self.dispBas,set_value=labels[self.samp_typ]
    endfor
    self->my_widget_control,'dispHfrom', self.dispBas,set_value=dm_to_string(self.disp_hran[0])
    self->my_widget_control,'dispHto',   self.dispBas,set_value=dm_to_string(self.disp_hran[1])
    self->my_widget_control,'dispHstep', self.dispBas,set_value=dm_to_string(self.disp_hstep)
    self->my_widget_control,'dispVfrom', self.dispBas,set_value=dm_to_string(self.disp_vran[0])
    self->my_widget_control,'dispVto',   self.dispBas,set_value=dm_to_string(self.disp_vran[1])
    self->my_widget_control,'dispVstep', self.dispBas,set_value=dm_to_string(self.disp_vstep)
    self->my_widget_control,'dispIfrom', self.dispBas,set_value=dm_to_string(self.disp_iran[0])
    self->my_widget_control,'dispIto',   self.dispBas,set_value=dm_to_string(self.disp_iran[1])
    dm_set_droplist,widget_info(self.dispBas,find_by_uname='dispColor'),  select=self.disp_color
    dm_set_droplist,widget_info(self.dispBas,find_by_uname='dispShading'),select=self.disp_shading
    dm_set_droplist,widget_info(self.dispBas,find_by_uname='cutX'),       select=self.cut_x[self.samp_typ]
    dm_set_droplist,widget_info(self.dispBas,find_by_uname='cutColor'),   select=self.cut_color
    dm_set_droplist,widget_info(self.dispBas,find_by_uname='cutY'),       select=self.cut_y[self.samp_typ]
    dm_set_droplist,widget_info(self.dispBas,find_by_uname='cutSymbol'),  select=self.cut_symbol
    dm_set_droplist,widget_info(self.dispBas,find_by_uname='cutLine'),    select=self.cut_line
    self->my_widget_control,'dispSmooth',self.dispBas,set_value=dm_to_string(self.disp_smooth,/int)
    self->my_widget_control,'cutFrom',   self.dispBas,set_value=dm_to_string(self.cut_ran[0])
    self->my_widget_control,'cutTo',     self.dispBas,set_value=dm_to_string(self.cut_ran[1])
    self->my_widget_control,'cutStep',   self.dispBas,set_value=dm_to_string(self.cut_step)
    self->my_widget_control,'cutT1from', self.dispBas,set_value=dm_to_string(self.cut_t1ran[0])
    self->my_widget_control,'cutT1to',   self.dispBas,set_value=dm_to_string(self.cut_t1ran[1])
    self->my_widget_control,'cutYfrom',  self.dispBas,set_value=dm_to_string(self.cut_yran[0])
    self->my_widget_control,'cutYto',    self.dispBas,set_value=dm_to_string(self.cut_yran[1])
    if (self.samp_typ ne 0) and self.hklran_yn then begin
       dm_set_droplist,widget_info(self.dispBas,find_by_uname='extraHKL'),select=self.disp_hkl
       self->my_widget_control,'hklTfrom',self.dispBas,set_value=dm_to_string(self.disp_hklran[0])
       self->my_widget_control,'hklTto',self.dispBas,set_value=dm_to_string(self.disp_hklran[1])
    endif
end

;(re)create and set values of all the widgets in self.trajBas
;keyword:
;   reset:    if set, only set the existing widget values, otherwise regenerate all the widgets
pro dcs_mslice::reset_trajectory,reset=reset
    if not keyword_set(reset) then begin   ;(re)generate all the widgets
       if widget_info(self.trajBas,/valid_id) eq 0 then $
          self.trajBas = widget_base(self.tlb,/frame,xpad=0,ypad=0,map=0,space=0,xsize=self.xsize[0])
       widget_control,self.trajBas,update=0
       if self.view[2] eq 0 then return
       extra    = widget_base(self.trajBas,/row,ypad=1,xpad=0,space=0)
       left     = widget_base(extra,/col,ypad=0,xpad=0)
       label    = widget_label(left,value='  Detector Trajectories:',/align_left)
       row      = widget_base(left,/row,ypad=0,xpad=0,space=0)
       label    = widget_label(row,value='x',xsize=self.xsize[1],/align_center)
       trajX    = dm_widget_droplist(row,value=self.traj_type,xsize=self.xsize[2],uname='trajX')
       label    = widget_label(row,value='from:',xsize=self.xsize[1],/align_center)
       trajXfrom= widget_text(row,value='',scr_xsize=self.xsize[4],/editable,/all_events,ysize=1,uname='trajXfrom')
       label    = widget_label(row,value='to:',xsize=self.xsize[1],/align_center)
       trajXto  = widget_text(row,value='',scr_xsize=self.xsize[4],/editable,/all_events,ysize=1,uname='trajXto')
       row      = widget_base(left,/row,ypad=0,xpad=0,space=0)
       label    = widget_label(row,value='y',xsize=self.xsize[1],/align_center)
       trajY    = dm_widget_droplist(row,value=self.traj_type,xsize=self.xsize[2],uname='trajY')
       label    = widget_label(row,value='from:',xsize=self.xsize[1],/align_center)
       trajYfrom= widget_text(row,value='',scr_xsize=self.xsize[4],/editable,/all_events,ysize=1,uname='trajYfrom')
       label    = widget_label(row,value='to:',xsize=self.xsize[1],/align_center)
       trajYto  = widget_text(row,value='',scr_xsize=self.xsize[4],/editable,/all_events,ysize=1,uname='trajYto')
       geom     = widget_info(left,/geom)
       right    = widget_base(extra,/col,/align_bottom,ypad=0,xpad=0,xsize=self.xsize[0]-geom.xsize-1)
       row      = widget_base(right,/row,/align_right,xpad=0,ypad=0,space=0)
       plotTra  = widget_button(row,value='Plot Trajectories',uname='plotTra',sensitive=0,xsize=self.xsize[4]*2)
       row      = widget_base(left,/row,ypad=0,xpad=0,space=0)
       label    = widget_label(row,value='z',xsize=self.xsize[1],/align_center)
       trajZ    = dm_widget_droplist(row,value=self.traj_type,xsize=self.xsize[2],uname='trajZ')
       label    = widget_label(row,value='from:',xsize=self.xsize[1],/align_center)
       trajZfrom= widget_text(row,value='',scr_xsize=self.xsize[4],/editable,/all_events,ysize=1,uname='trajZfrom')
       label    = widget_label(row,value='to:',xsize=self.xsize[1],/align_center)
       trajZto  = widget_text(row,value='',scr_xsize=self.xsize[4],/editable,/all_events,ysize=1,uname='trajZto')
       row      = widget_base(right,/row,/align_right,xpad=0,ypad=0,space=0)
       oplotTra = widget_button(row,value='Oplot Trajectories',uname='oplotTra',sensitive=0,xsize=self.xsize[4]*2)
       if float(!version.release) ge 5.6 then $     ;tips for some widget buttons
          widget_control,oplotTra,tooltip='Overplot the trajectories in the current plot window.'
    endif
    if self.view[2] eq 0 then return
    ;;set all values
    ;make plot button sensitive if projection is calculated
    self->my_widget_control,'plotTra', self.trajBas,sensitive=ptr_valid(self.projStrPtr)
    self->my_widget_control,'oplotTra',self.trajBas,sensitive=(ptr_valid(self.projStrPtr) and (self.samp_typ ne 0))
    case self.samp_typ of
      0:begin  ;powder
        value = [self.view_type[0:3+(self.ftype eq 0?1:0)],'None'] & nvalue = n_elements(value)
        self->my_widget_control,['trajX','trajY','trajZ'],self.trajBas,set_value=value
        if self.traj_x[0] ge nvalue then self.traj_x[0] = nvalue-1
        if self.traj_y[0] ge nvalue then self.traj_y[0] = nvalue-1
        if self.traj_z[0] ge nvalue then self.traj_z[0] = nvalue-1
        end
      1:begin  ;single crystal
        self->my_widget_control,['trajX','trajY','trajZ'],self.trajBas,set_value=self.traj_type
        end
      2:begin  ;diffuse scattering single E
        self->my_widget_control,['trajX','trajY','trajZ'],self.trajBas,set_value=[self.traj_type[0:4],self.traj_type[7]]
        end
      3:begin  ;diffuse scattering multiple E
        self->my_widget_control,['trajX','trajY','trajZ'],self.trajBas,set_value=[self.traj_type[0:5],self.traj_type[7]]
        end
      else:
    endcase
    dm_set_droplist,widget_info(self.trajBas,find_by_uname='trajX'),select=self.traj_x[self.samp_typ]
    dm_set_droplist,widget_info(self.trajBas,find_by_uname='trajY'),select=self.traj_y[self.samp_typ]
    dm_set_droplist,widget_info(self.trajBas,find_by_uname='trajZ'),select=self.traj_z[self.samp_typ]
    self->my_widget_control,'trajXfrom',self.trajBas,set_value=dm_to_string(self.traj_xran[0])
    self->my_widget_control,'trajXto',  self.trajBas,set_value=dm_to_string(self.traj_xran[1])
    self->my_widget_control,'trajYfrom',self.trajBas,set_value=dm_to_string(self.traj_yran[0])
    self->my_widget_control,'trajYto',  self.trajBas,set_value=dm_to_string(self.traj_yran[1])
    self->my_widget_control,'trajZfrom',self.trajBas,set_value=dm_to_string(self.traj_zran[0])
    self->my_widget_control,'trajZto',  self.trajBas,set_value=dm_to_string(self.traj_zran[1])
end

;reset menu item sensitivity and ticks accordingly
;keywords:
;   geomsensitive: if set to 1: instrument geometry menus will be sensitive
;                  if set to 0: instrument geometry menus will be insensitive
;                  if not set, no action
pro dcs_mslice::reset_menu,geomsensitive=geomsensitive
    ;file menu: add a click to the current file type
    ftypemenu  = widget_info(self.tlb,find_by_uname='ftypeMenu')
    checked    = widget_info(ftypemenu,find_by_uname='ftype_'+dm_to_string(self.ftype))
    for i=0,n_elements(*self.ftypename)-1 do begin
        if i ne self.ftype then begin
           tmp = widget_info(ftypemenu,find_by_uname='ftype_'+dm_to_string(i))
           unchecked = (n_elements(unchecked) eq 0)?tmp:[unchecked,tmp]
        endif
    endfor
    dm_toggle_menubut,checked,unchecked
    self->my_widget_control,['savesliceMenu','savecutMenu'],sensitive=(ptr_valid(self.projStrPtr) and ptr_valid(self.dataStrPtr))
    ;background menu
    self->my_widget_control,'vdclBut',sensitive=ptr_valid(self.eff)
    self->my_widget_control,'bgclBut',sensitive=(total(ptr_valid([self.bgtchnPtr,self.bgratePtr,self.bgdetsPtr,self.bgdata])) ne 0)
    ;mask menu
    self->my_widget_control,['mkdbMenu'],sensitive=(self.ftype eq 0)
    self->my_widget_control,['mkclBut','mksvBut'],sensitive=ptr_valid(self.mask)
    self->my_widget_control,['mkplBut','mkbpBut'],sensitive=ptr_valid(self.dataStrPtr)
    self->my_widget_control,'mkplangl',sensitive=self.ftype eq 0
    if ptr_valid(self.mask) eq 0 then begin
       mkngBut  = widget_info(self.tlb,find_by_uname='mkngBut')
       mkcnBut  = widget_info(self.tlb,find_by_uname='mkcnBut')
       mkloBut  = widget_info(self.tlb,find_by_uname='mkloBut')
       mkupBut  = widget_info(self.tlb,find_by_uname='mkupBut')
       mkulBut  = widget_info(self.tlb,find_by_uname='mkulBut')
       mkmlBut  = widget_info(self.tlb,find_by_uname='mkmlBut')
       mkucBut  = widget_info(self.tlb,find_by_uname='mkucBut')
       dm_toggle_menubut,mkcnBut,[mkngBut,mkcnBut,mkloBut,mkupBut,mkulBut,mkmlBut,mkucBut]
    endif
    ;option menu
    binSum   = widget_info(self.tlb,find_by_uname='binSum')
    binAvg   = widget_info(self.tlb,find_by_uname='binAvg')
    bincsYes = widget_info(self.tlb,find_by_uname='bincsYes')
    bincsNo  = widget_info(self.tlb,find_by_uname='bincsNo')
    monSum   = widget_info(self.tlb,find_by_uname='monSum')
    monFit   = widget_info(self.tlb,find_by_uname='monFit')
    monFC0   = widget_info(self.tlb,find_by_uname='monFC0')
    monBM1   = widget_info(self.tlb,find_by_uname='monBM1')
    monTIME  = widget_info(self.tlb,find_by_uname='monTIME')
    intnTyp0 = widget_info(self.tlb,find_by_uname='intnTyp0')
    intnTyp1 = widget_info(self.tlb,find_by_uname='intnTyp1')
    intnTyp2 = widget_info(self.tlb,find_by_uname='intnTyp2')
    intnTyp3 = widget_info(self.tlb,find_by_uname='intnTyp3')
    intnTyp4 = widget_info(self.tlb,find_by_uname='intnTyp4')
    viewOrth = widget_info(self.tlb,find_by_uname='vaxisOrtho')
    viewArbi = widget_info(self.tlb,find_by_uname='vaxisArbi')
    abspNon  = widget_info(self.tlb,find_by_uname='abspNone')
    abspAnn  = widget_info(self.tlb,find_by_uname='abspAnnulus')
    abspCyl  = widget_info(self.tlb,find_by_uname='abspCylinder')
    abspSph  = widget_info(self.tlb,find_by_uname='abspSphere')
    powderNo = widget_info(self.tlb,find_by_uname='powderNone')
    powderAl = widget_info(self.tlb,find_by_uname='powderAl')
    powderCu = widget_info(self.tlb,find_by_uname='powderCu')
    powderSt = widget_info(self.tlb,find_by_uname='powderSt')
    self->set_instrgeom,geom=self.instrgeom,sensitive=geomsensitive
    case self.intn_typ of
            0:   dm_toggle_menubut,intnTyp0,[intnTyp1,intnTyp2,intnTyp3,intnTyp4]
            1:   dm_toggle_menubut,intnTyp1,[intnTyp0,intnTyp2,intnTyp3,intnTyp4]
            2:   dm_toggle_menubut,intnTyp2,[intnTyp0,intnTyp1,intnTyp3,intnTyp4]
            3:   dm_toggle_menubut,intnTyp3,[intnTyp0,intnTyp1,intnTyp2,intnTyp4]
            4:   dm_toggle_menubut,intnTyp4,[intnTyp0,intnTyp1,intnTyp2,intnTyp3]
            else:begin
                 self.intn_typ = 0
                 dm_toggle_menubut,intnTyp0,[intnTyp1,intnTyp2,intnTyp3,intnTyp4]
                 end
    endcase
    dm_set_button,widget_info(self.tlb,find_by_uname='intnEint'),self.eint_yn,$
       onstring='E-Integrated Intensity Enabled',offstring='E-Integrated Intensity Disabled'
    if self.bin_avgsum    eq 0 then dm_toggle_menubut,binAvg,binSum    else dm_toggle_menubut,binSum,binAvg
    if self.bin_conststep eq 0 then dm_toggle_menubut,bincsNo,bincsYes else dm_toggle_menubut,bincsYes,bincsNo
    if self.mon_sumfit    eq 0 then dm_toggle_menubut,monSum,monFit    else dm_toggle_menubut,monFit,monSum
    case self.dcs_mon of
            0:   dm_toggle_menubut,monFC0,[monBM1,monTIME]
            1:   dm_toggle_menubut,monBM1,[monFC0,monTIME]
            2:   dm_toggle_menubut,monTIME,[monFC0,monBM1]
            else:
    endcase
    if ptr_valid(self.absp_info) then begin
       case (*(self.absp_info))[0] of
            0:   dm_toggle_menubut,abspCyl,[abspNon,abspAnn,abspSph]
            1:   dm_toggle_menubut,abspAnn,[abspNon,abspCyl,abspSph]
            2:   dm_toggle_menubut,abspSph,[abspNon,abspCyl,abspAnn]
            else:dm_toggle_menubut,abspNon,[abspCyl,abspAnn,abspSph]
       endcase
    endif else   dm_toggle_menubut,abspNon,[abspCyl,abspAnn,abspSph]
    if self.view_ortharbi eq 0 then dm_toggle_menubut,viewOrth,viewArbi else dm_toggle_menubut,viewArbi,viewOrth
    case self.powd_typ of
            0:   dm_toggle_menubut,powderNo,[powderAl,powderCu,powderSt]
            1:   dm_toggle_menubut,powderAl,[powderNo,powderCu,powderSt]
            2:   dm_toggle_menubut,powderCu,[powderNo,powderAl,powderSt]
            3:   dm_toggle_menubut,powderSt,[powderNo,powderAl,powderCu]
            else:dm_toggle_menubut,powderNo,[powderAl,powderCu,powderSt]
    endcase
    dm_set_button,widget_info(self.tlb,find_by_uname='neg2th'),self.negative2th,$
       onstring='Preserve Negative 2theta Angle Value',$
       offstring='Use Absolute 2theta Angle Value'
    dm_set_button,widget_info(self.tlb,find_by_uname='hklRan'), self.hklran_yn,$
       onstring='Allow Extra HKL Range',$
       offstring='Disallow Extra HKL Range'
    dm_set_button,widget_info(self.tlb,find_by_uname='darkCorr'), self.dcor_yn,$
       onstring='Dark Angle Correction Enabled',$
       offstring='Dark Angle Correction Disabled'
    dm_set_button,widget_info(self.tlb,find_by_uname='eAdjust'), self.eadjust,$
       onstring='Elastic Peak Position Adjustment Enabled',$
       offstring='Elastic Peak Position Adjustment Disabled'
    dm_set_button,widget_info(self.tlb,find_by_uname='edepEff'), self.edep_yn,$
       onstring='E-Dependent Detector Efficiency Correction Enabled',$
       offstring='E-Dependent Detector Efficiency Correction Disabled'
    dm_set_button,widget_info(self.tlb,find_by_uname='edepEff'), self.edep_yn,$
       onstring='E-Dependent Detector Efficiency Correction Enabled',$
       offstring='E-Dependent Detector Efficiency Correction Disabled'
    dm_set_button,widget_info(self.tlb,find_by_uname='errBar'),1-self.errbar,$
       onstring='Error Bar Disabled',$
       offstring='Error Bar Enabled'
    self->my_widget_control,['eAdjust','moncMenu'],sensitive=(self.ftype eq 0)
    self->change_samptyp,self.samp_typ
    ;window menu
    dm_set_button,widget_info(self.tlb,find_by_uname='viewProj'),self.view[0],onstring='Hide Projection',offstring='Show Projection'
    dm_set_button,widget_info(self.tlb,find_by_uname='viewDisp'),self.view[1],onstring='Hide Display',offstring='Show Display'
    dm_set_button,widget_info(self.tlb,find_by_uname='viewTraj'),self.view[2],onstring='Hide Trajectory',offstring='Show Trajectory'
end

;reset projection,display,and trajectory window
pro dcs_mslice::reset_pdt
    WIDGET_CONTROL,/HOURGLASS

    self->reset_droplist        ;adjust droplist values if necessary

    widget_control,self.tlb,update=0
    geom1_old = widget_info(self.projBas,/geometry)
    geom2_old = widget_info(self.dispBas,/geometry)
    geom3_old = widget_info(self.trajBas,/geometry)
    widget_control,self.trajBas,/destroy
    widget_control,self.dispBas,/destroy
    widget_control,self.projBas,/destroy
    self->reset_projection
    self->reset_display
    self->reset_trajectory
    geom1  = widget_info(self.projBas,/geometry)
    geom2  = widget_info(self.dispBas,/geometry)
    geom3  = widget_info(self.trajBas,/geometry)
    margin = total(1-self.view)*geom1.margin*2*(!version.os_family eq 'Windows')
    if float(!version.release) ge 5.5 then begin
       self.geom[1] = self.geom[1]+geom1.ysize+geom2.ysize+geom3.ysize-$
                      (geom1_old.ysize+geom2_old.ysize+geom3_old.ysize)
       widget_control,self.tlb,ysize=self.geom[1]-margin
    endif else begin
       self.geom[1] = self.geom[1]+geom1.scr_ysize+geom2.scr_ysize+geom3.scr_ysize-$
                      (geom1_old.scr_ysize+geom2_old.scr_ysize+geom3_old.scr_ysize)
       widget_control,self.tlb,scr_ysize=self.geom[1]-margin
    endelse
    widget_control,self.tlb,/update
    widget_control,self.projBas,/update,/map
    widget_control,self.dispBas,/update,/map
    widget_control,self.trajBas,/update,/map
end

;save cuts in files
;keyword:
;   dave:   if set, save cut as dave files
;   xye:    if set, save cut as x, y, yerr 3-column file
pro dcs_mslice::save_cut,dave=dave,xye=xye
    if (not ptr_valid(self.projStrPtr)) or (not ptr_valid(self.dataStrPtr)) or self.error then begin
       ok = dialog_message('Please load data and calculate projection first.',dialog_parent=self.tlb)
       return
    endif

    ext = ''
    if keyword_set(dave) then ext = 'dave'
    if keyword_set(xye)  then ext = 'xye'
    if strlen(ext) eq 0  then return

    file = dm_choose_file(ext,/write,dialog_parent=self.tlb,title='Save cut as '+ext+' file.')
    file = file[0]
    if strlen(file) eq 0 then return
    openw,unit,file,/get_lun,error=openerr
    if openerr ne 0 then begin
       ok = dialog_message("Can't write in "+file,/error,dialog_parent=self.tlb)
       return
    endif

    ;select data
    self->dm_choose_cutdata,xdat=xdat,ydat=ydat,yerr=yerr,xtit=xtit,ytit=ytit
    if (not self.errbar) and (n_elements(yerr) ne 0) then tmp=temporary(yerr)   ;destroy yerr

    if keyword_set(xye) then begin
       for i=0L,n_elements(xdat)-1 do begin
           if n_elements(yerr) ne 0 then printf,unit,xdat[i],ydat[i],yerr[i] $
           else printf,unit,xdat[i],ydat[i]
       endfor
    endif

    if keyword_set(dave) then begin
       if n_elements(yerr) ne 0 then $
          ret = create_dave_pointer(    $
                daveptr,                $
                qty     = ydat,         $
                qtlabel = ytit,         $
                err     = yerr,         $
                xvals   = xdat,         $
                xtype   = 'POINT',      $
                xlabel  = xtit          $
          ) $
       else $
          ret = create_dave_pointer(    $
                daveptr,                $
                qty     = ydat,         $
                qtlabel = ytit,         $
                xvals   = xdat,         $
                xtype   = 'POINT',      $
                xlabel  = xtit          $
          )
       save,daveptr,filename=file
       heap_free,daveptr
    endif

    free_lun,unit
end

;save slice in files
;keywords:
;   dave:   if set, save slice as grouped DAVE file, for PAN fitting
;   dPtr:   if present, will pass the slice data as a dave pointer
;   iexy:   if set, save slice as Int, Err, X, Y 4-column file
;   spe:    if set, save slice as spe file
;   xyie:   if set, save slice as X, Y, Int, Err matrix file
pro dcs_mslice::save_slice,dave=dave,dPtr=davePtr,iexy=iexy,spe=spe,xyie=xyie
    if (not ptr_valid(self.projStrPtr)) or (not ptr_valid(self.dataStrPtr)) or self.error then begin
       ok = dialog_message('Please load data and calculate projection first.',dialog_parent=self.tlb)
       return
    endif

    dcs_filler = -1e20

    ext = ''
    if keyword_set(dave) then ext = 'dave'
    if keyword_set(iexy) then ext = 'iexy'
    if keyword_set(spe)  then ext = 'spe'
    if keyword_set(xyie) then ext = 'xyie'

    if not arg_present(davePtr) then begin
       if strlen(ext) eq 0 then return
       file = dm_choose_file(ext,/write,dialog_parent=self.tlb,title='Save cut as '+ext+' file.')
       file = file[0]
       if strlen(file) eq 0 then return
       openw,unit,file,/get_lun,error=openerr
       if openerr ne 0 then begin
          ok = dialog_message("Can't write in "+file,/error,dialog_parent=self.tlb)
          return
       endif
    endif

    ;select data
    self->dm_choose_slicedata,xdat=xdat,ydat=ydat,zdat=zdat,zerr=zerr,xtit=xtit,ytit=ytit,zran=zran,zmin=zmin
    index = where(finite(zdat) eq 0, count)
    if count ne 0 then begin
       zdat[index] = dcs_filler
       zerr[index] = -1.0               ;signifies missing data
    endif

    nx = n_elements(xdat) & ny = n_elements(ydat)

    if keyword_set(iexy) then begin
       for i=0L,nx-1L do begin
           for j=0L,ny-1L do begin
               printf,unit,zdat[i,j],zerr[i,j],xdat[i],ydat[j]
           endfor
       endfor
    endif

    if keyword_set(spe) then begin
       dm_write_spe,unit,xdat,ydat,zdat,zerr
    endif

    if keyword_set(xyie) then begin
       printf,unit,nx,ny
       printf,unit,' '
       for i=0L,nx-1L do printf,unit,xdat[i]
       printf,unit,' '
       for i=0L,ny-1L do printf,unit,ydat[i]
       printf,unit,' '
       printf,unit,zdat,format='('+dm_to_string(nx)+'(g13.6," "))'
       printf,unit,' '
       printf,unit,zerr,format='('+dm_to_string(nx)+'(g13.6," "))'
    endif

    if keyword_set(dave) or arg_present(davePtr) then begin
       if count ne 0 then begin ;creat mask
          mask = bytarr(nx,ny)+1b
          mask[index] = 0b
          mask = bits2bytes(transpose(mask))
       endif

       ;contruct DAVE pointer
       xunit = ''
       yunit = 'meV'
       if self.samp_typ eq 0 then begin
          xtit  = self.view_label[self.view_u1typ]
          xunit = self.view_unit[self.view_u1typ]
          ytit  = self.view_label[self.view_u2typ]
          yunit = self.view_unit[self.view_u2typ]
       endif
       davePtr = dm_define_pointer()
       ptr_free,(*(*davePtr).dataStrPtr).commonStr.histPtr
       (*(*davePtr).dataStrPtr).commonStr.histPtr = $
         ptr_new({qty:transpose(temporary(zdat)),err:transpose(temporary(zerr)),x:ydat,y:xdat})
	   (*(*davePtr).dataStrPtr).commonStr.xunits = yunit
	   (*(*davePtr).dataStrPtr).commonStr.xlabel = ytit
	   (*(*davePtr).dataStrPtr).commonStr.yunits = xunit
	   (*(*davePtr).dataStrPtr).commonStr.ylabel = xtit
	   (*(*davePtr).dataStrPtr).commonStr.histlabel = $
	     (['S(Q,omega)','Symmetrized S(Q,Omega)','d2sigma/dOmegadE','Chi(Q,omega)',''])[self.intn_typ]

       if count ne 0 then begin ;mask
          ;add PAN_MASK and DCS_FILLER info to specificPtr
          specific = (*(*(*davePtr).dataStrPtr).specificPtr)
          tags = strupcase(tag_names(specific))
          loc = where(tags eq 'PAN_MASK',count)
          if count eq 0 then specific = create_struct('PAN_MASK',ptr_new(mask),specific) $
          else *specific.pan_mask = mask
          loc = where(tags eq 'DCS_FILLER',count)
          if count eq 0 then specific = create_struct('DCS_FILLER',dcs_filler,specific) $
          else specific.dcs_filler = dcs_filler
    	  (*(*(*davePtr).dataStrPtr).specificPtr) = specific
       endif

       if n_elements(unit) ne 0 then begin
          free_lun,unit
          save,davePtr,filename=file
          heap_free,davePtr
       endif
    endif

    if n_elements(unit) ne 0 then free_lun,unit
end

;set the buttons after projection is changed
pro dcs_mslice::set_display_button
    self->my_widget_control,['savesliceMenu','savecutMenu'],sensitive=(ptr_valid(self.projStrPtr) and ptr_valid(self.dataStrPtr))
    self->my_widget_control,'viewSpurion',sensitive=ptr_valid(self.dataStrPtr) and $
          ptr_valid(self.projStrPtr) and (self.samp_typ lt 2) and (self.instrgeom eq 0)
    if widget_info(self.dispBas,/valid_id) then begin
       self->my_widget_control,['dispFitSlice','dispPlotSlice','dispSurfSlice','cutFit','cutPlot','cutOplot'],self.dispBas,$
             sensitive=(ptr_valid(self.projStrPtr) and ptr_valid(self.dataStrPtr))
       if self.samp_typ gt 0 then self->my_widget_control,'dispFitSlice',self.dispBas,sensitive=0
    endif
    if widget_info(self.trajBas,/valid_id) then begin
       self->my_widget_control,'plotTra', self.trajBas,sensitive=ptr_valid(self.projStrPtr)
       self->my_widget_control,'oplotTra',self.trajBas,sensitive=(ptr_valid(self.projStrPtr) and (self.samp_typ ne 0))
    endif
end

pro dcs_mslice::set_filehistory,info,dir,files,choose=choose
    if n_elements(choose) eq 1 then begin
       self.filesel->set_path,(*(self.file_hist[choose]))[2]
       ftype = strmid((*(self.file_hist[choose]))[0],6,strlen((*(self.file_hist[choose]))[0])-6)
       if ftype ne self.ftype then ok=self->dm_filetools((*(self.file_hist[choose]))[0])
       self.filesel->getproperty,dFiles=dFiles
       for i=3,n_elements(*(self.file_hist[choose]))-1 do begin
           ind = where(dFiles eq (*(self.file_hist[choose]))[i],count)
           if count ne 0 then begin
              if n_elements(selected) eq 0 then selected=ind $
              else selected=[selected,ind]
           endif
       endfor
       if n_elements(selected) ne 0 then self.filesel->set_file,selected,/highlight
       return
    endif
    num = n_elements(self.file_hist)    ;capacity
    if (n_elements(info) ne 0) and (n_elements(dir) ne 0) and (n_elements(files) ne 0) then begin
       for i=0,self.n_history-1 do begin  ;check if this entry already exists
           if dir ne (*(self.file_hist[i]))[2] then continue
           if n_elements(files) ne n_elements(*(self.file_hist[i]))-3 then continue
           same = 1b
           for j=0, n_elements(files)-1 do $
               if files[j] ne (*(self.file_hist[i]))[3+j] then same=0b
           if same then return ;entry exists
       endfor
       if self.n_history lt num then begin ;empty room available
          if self.n_history ne 0 then $
             self.file_hist[1:self.n_history] = self.file_hist[0:self.n_history-1]
          self.file_hist[0] = ptr_new(['ftype_'+dm_to_string(self.ftype,/int),info,dir,files])
          self.n_history = self.n_history+1
       endif else begin                    ;full
          ptr_free,self.file_hist[num-1]
          self.file_hist[1:num-1] = self.file_hist[0:num-2]
          self.file_hist[0] = ptr_new(['ftype_'+dm_to_string(self.ftype,/int),info,dir,files])
       endelse
    endif
    histmenu = widget_info(self.tlb,find_by_uname='history')
    widget_control,histmenu,sensitive=(self.n_history gt 0)
    self->my_widget_control,'clearHist',sensitive=(self.n_history gt 0)
    for i=0,num-1 do self->my_widget_control,'hist_'+dm_to_string(i,/int),histmenu,/destroy
    for i=0,self.n_history-1 do begin
        void = widget_button(histmenu,value=dm_to_string(i,/int)+' '+$
               (*(self.file_hist[i]))[1],uname='hist_'+dm_to_string(i))
    endfor
end

;set instrument geometry and adjust the proper menu items
pro dcs_mslice::set_instrgeom,geom=geom,sensitive=sensitive
    igeoDir  = widget_info(self.tlb,find_by_uname='directGeom')
    igeoInv  = widget_info(self.tlb,find_by_uname='inverseGeom')
    if n_elements(geom) ne 0 then begin
       self.instrgeom = 0>(geom)<1
       if self.instrgeom eq 0 then begin    ;direct geometry
          dm_toggle_menubut,igeoDir,igeoInv
          self->my_widget_control,'edepEff',sensitive=1
          self->my_widget_control,'viewSpurion',$
             sensitive=ptr_valid(self.dataStrPtr) and ptr_valid(self.projStrPtr) and (self.samp_typ lt 2)
       endif else begin                     ;inverse geometry
          dm_toggle_menubut,igeoInv,igeoDir
          self->my_widget_control,['edepEff','viewSpurion'],sensitive=0
       endelse
    endif
    if n_elements(sensitive) ne 0 then begin
       widget_control,igeoDir,sensitive=sensitive
       widget_control,igeoInv,sensitive=sensitive
    endif
end

;cleanup, life cycle method
pro dcs_mslice::Cleanup
    ;save parameters in dcs_mslice.prm if allowed
    cd,self.root
    defsysv,'!dave_defaults',exists=exists
    if exists then $
       if ptr_valid(!dave_defaults) then begin
          current = (*!dave_defaults).workDir
          if (file_test(current,/directory))[0] then cd,current
       endif
    openw,unit,'dcs_mslice.prm',/get_lun,error=openerr
    if openerr eq 0 then begin
       free_lun,unit
       self->dm_save_parameter,'dcs_mslice.prm'
    endif
    cd,self.root
    if widget_info(self.tlb,/valid_id) then widget_control,self.tlb,/destroy
    ptr_free,self.rebinsize,self.bgdata,self.mask,self.eff,self.kfactor,self.detPosPtr,self.dataStrPtr
    ptr_free,self.info,self.absp_info,self.powd_line,self.file_hist,self.bgratePtr,self.bgtchnPtr,self.bgdetsPtr
    ptr_free,self.oifac,self.ftypename,self.ftypeext,self.projStrPtr
    obj_destroy,self.gr_list
    obj_destroy,self.fileSel
    ;online_help,/quit           ;close the help file if it is opened by online_help
end

;initialization, life cycle method
;usage:
;   void=obj_new('dcs_mslice',group_leader=group_leader)
;parameters:
;   NONE
;keyword:
;   groupleader:    groupleader widget ID
function dcs_mslice::Init,group_leader=group_leader
    if n_elements(group_leader) ne 0 then self.group_leader=group_leader
    registerName = 'dcs_mslice'
    if xregistered(registerName) then begin ;only allow one dcs_mslice running
       FORWARD_FUNCTION LookupManagedWidget
       id = LookupManagedWidget(registername)
       widget_control,id,iconify=0
       return,0
    endif
    ;error handler
    catch, myerror
    if myerror ne 0 then begin
       catch,/cancel
       ok = dialog_message(!error_state.msg,/error)
       ptr_free,self.bgdata,self.bgratePtr,self.bgtchnPtr,self.bgdetsPtr,self.mask,self.eff,self.kfactor
       ptr_free,self.projStrPtr,self.info,self.absp_info,self.powd_line,self.file_hist
       ptr_free,self.detPosPtr,self.dataStrPtr
       obj_destroy,self.gr_list
       obj_destroy,self.fileSel
       return, 0
    end

    ;initialize the data
    self.instrgeom      = 0     ;default direct geometry
    self.ftype          = 0     ;default is DCS files
    self.dcor_yn        = 0
    self.edep_yn        = 1
    self.eadjust        = 0
    self.eint_yn        = 0
    self.intn_typ       = 0     ;default S(q,w)
    self.powd_typ       = 0     ;no powder line
    self.dcor_eqran     = [!values.f_nan,!values.f_nan,!values.f_nan,!values.f_nan]
    self.xsize          = [0L,0L,120L,9L,92L]
    self.ssfac          = 1.0
    self.oifac          = ptr_new(1.0)
    self.view_ortharbi  = 0     ;orthogonal
    self.bin_avgsum     = 0     ;average
    self.bin_conststep  = 0     ;average value
    self.mon_sumfit     = 1     ;fit
    self.dcs_mon        = 1     ;use bm1 as the monitor
    self.temperature    = 300.0
    self.view           = [1b,1b,1b]
    self.bgeran         = [-20,-10]
    self.intn_lab       = 'Intensity (arb. units)'
    self.samp_typ       = 0     ;default powder
    self.rebinsize      = ptr_new([1s,2s,4s,5s,8s,10s,20s,25s,40s,50s])
    self.e_bin          = [1,1,1,1,1]
    self.e_range        = [!values.f_nan,!values.f_nan]
    self.latt_parm      = [10d,10d,10d,90d,90d,90d]
    self.orie_u         = [1e,0e,0e]
    self.orie_v         = [0e,1e,0e]
    self.orie_offset    = !values.f_nan
    self.view_type      = ['Energy','|Q|','2Theta','Det Group Number','Time Channel']
    self.view_label     = ['E','|Q|','2theta','Detector Group','Time']
    self.view_unit      = ['meV','!3'+string('c5'XB)+'!U-1!N','!3'+string('b0'XB),'','us']
    self.view_u1typ     = 1
    self.view_u1        = [1,0,0,0]
    self.view_u2        = [0,1,0,0]
    self.view_u3        = [0,0,0,1]
    self.view_u1lab     = ['|Q|','H']
    self.view_u2lab     = ['E','K']
    self.view_u3lab     = 'E'
    self.disp_perp      = 2
    self.disp_tran      = [!values.f_nan,!values.f_nan]
    self.disp_hran      = [!values.f_nan,!values.f_nan]
    self.disp_vran      = [!values.f_nan,!values.f_nan]
    self.disp_hstep     = 0.035
    self.disp_vstep     = !values.f_nan
    self.disp_iran      = [!values.f_nan,!values.f_nan]
    self.disp_smooth    = 1
    self.disp_sm_kernel = [[0.1e,0.2e,0.1e],[0.2e,0.8e,0.2e],[0.1e,0.2e,0.1e]]
    self.disp_shading   = 1
    self.dispcmap       = ['B-W LINEAR','BLUE/WHITE','GRN-RED-BLU-WHTt','RED TEMPERATURE','BLUE/GREEN/RED/YELLOW','STD GAMMA-II',$
                           'PRISM','RED-PURPLE','GREEN/WHITE LINEAR','GRN/WHT EXPONENTIAL','GREEN-PINK','BLUE-RED','16 LEVEL',$
                           'RAINBOW','STEPS','STERN SPECIAL','Haze','Blue-Pastel-Red','Pastels','Hue Sat Lightness 1',$
                           'Hue Sat Lightness 2','Hue Sat Value 1','Hue Sat Value 2','Purple-Red+Stripes','Beach','Mac Style',$
                           'Eos A','Eos B','Hardcandy','Nature','Ocean','Peppermint','plasma','Blue-Red','Rainbow','Blue Waves',$
                           'Volcano','Waves','Rainbow18','Rainbow+white','Rainbow+black']
    self.disp_color     = 13    ;rainbow
    self.cut_x          = [0s,0s,0s,0s]
    self.cut_y          = [0s,0s,0s,0s]
    self.cut_ran        = [!values.f_nan,!values.f_nan]
    self.cut_step       = 0.035
    self.cut_t1ran      = [!values.f_nan,!values.f_nan]
    self.cut_t2ran      = [!values.f_nan,!values.f_nan]
    self.cut_yran       = [!values.f_nan,!values.f_nan]
    self.cut_symbol     = 0s
    self.symbols        = ['circle','filled circle','diamond','filled diamond','triangle','filled triangle',$
                           'inverted triangle','filled inverted triangle','square','filled square',$
                           'plus','star','dot','cross','greater','less','no symbol']
    self.cut_color      = 0
    self.colors         = ['white','red','blue','magenta','green','cyan','yellow','grey','dark grey','dark red','dark blue',$
                           'dark magenta','dark green','dark cyan','dark yellow']
    self.cut_line       = 0
    self.lines          = ['solid','dotted','dashed','dash dot','dash dot dot dot','long dash','no line']
    self.traj_type      = ['H','K','L','[Qh,0,0]','[0,Qk,0]','E (meV)','Energy','None']
    self.traj_x         = [1,3,3,3]
    self.traj_xran      = [!values.f_nan,!values.f_nan]
    self.traj_y         = [0,4,4,4]
    self.traj_yran      = [!values.f_nan,!values.f_nan]
    self.traj_z         = [4,7,5,6]
    self.traj_zran      = [!values.f_nan,!values.f_nan]
    self.gr_list        = obj_new('IDL_Container')
    self.errbar         = 1b
    self.useitool       = 0b
    self.negative2th    = 0b
    self.a2[*]          = !values.f_nan
    self.info           = ptr_new(['--Mslice for DCS --', $
                           'Based on the NCNR DCS data reduction programs by John Copley',$
                           'and the matlab version of mslice by Radu Coldea.',$
                           'Yiming Qiu(yiming.qiu@nist.gov)  3/2008'])
    cd,current=current
    self.root           = current
    self.helpfile       = ['dcs_mslice.pdf','dcs_mslice_addftype.pdf']
    defsysv,'!DAVE_AUXILIARY_DIR',exists=exists
    if exists then self.helpfile = !DAVE_AUXILIARY_DIR+self.helpfile $
    else begin
       self.helpfile[0] = file_which(self.helpfile[0],/include)
       self.helpfile[1] = file_which(self.helpfile[1],/include)
    endelse

    if float(!version.release) ge 5.5 then self.pathsep=call_function("path_sep") $
    else begin
       defsysv,'!delimiter',exists=exists
       if not exists then begin
          case !version.os_family of
            'Windows':  defsysv,'!delimiter','\'
            'unix':     defsysv,'!delimiter','/'
            'MacOS':    defsysv,'!delimiter',':'
            else:       defsysv,'!delimiter','/'
          endcase
       endif
       self.pathsep=!delimiter
    endelse

    defsysv,'!dcs_hsq2mn',exists=exists
    if not exists then defsysv,'!dcs_hsq2mn',double(81.804200) ;h^2/2./m_n/e*1e23

    ;generate widgets
    self.tlb = widget_base(title=(*self.info)[0],/column,kill_notify='dcs_mslice_Exit',mbar=bar,$
               group_leader=self.group_leader,ypad=0,xpad=0,uname='tlb',/tlb_size_event,map=0)
    filemenu = widget_button(bar,value='File',/menu)
    parmmenu = widget_button(bar,value='Parameter',/menu)
    bkgrmenu = widget_button(bar,value='Background',/menu)
    maskmenu = widget_button(bar,value='Mask',/menu)
    optnmenu = widget_button(bar,value='Option',/menu)
    viewmenu = widget_button(bar,value='Window',/menu,uname='viewMenu')
    igeomenu = widget_button(optnmenu,value='Instrument Geometry',uname='igeomMenu',/menu)
    itypmenu = widget_button(optnmenu,value='View Intensity As',/menu)
    binmmenu = widget_button(optnmenu,value='Binning Method',/menu)
    moncmenu = widget_button(optnmenu,value='Monitor Count',uname='moncMenu',/menu)
    abspmenu = widget_button(optnmenu,value='Absorption Correction',/menu)
    vaxsmenu = widget_button(optnmenu,value='Viewing Axis',/menu,uname='vaxisMenu',sensitive=0)
    powdmenu = widget_button(optnmenu,value='Show Powder Line',/menu,uname='showPowder',sensitive=0)
    helpmenu = widget_button(bar,value='Help',/menu)
    void     = widget_button(filemenu,value='File Type',uname='ftypeMenu',/menu)
    void     = widget_button(filemenu,value='File Tools',uname='ftoolMenu',/menu,sensitive=0)
    fslimenu = widget_button(filemenu,value='Save Slice Data As',uname='savesliceMenu',/menu,/separator,sensitive=0)
    fcutmenu = widget_button(filemenu,value='Save Cut Data As',uname='savecutMenu',/menu,sensitive=0)
    void     = widget_button(filemenu,value='Recent Files',uname='history',sensitive=0,/menu,/separator)
    void     = widget_button(filemenu,value='Clear File History',uname='clearHist',sensitive=0)
    void     = widget_button(filemenu,value='Exit',uname='exitBut',/separator)
    void     = widget_button(fslimenu,value='DAVE File',uname='saveslicedave')
    void     = widget_button(fslimenu,value='SPE File',uname='saveslicespe')
    void     = widget_button(fslimenu,value='I,Err,X,Y 4-Column File',uname='savesliceiexy')
    void     = widget_button(fslimenu,value='X,Y,I,Err Matrix File',uname='saveslicexyie')
    void     = widget_button(fcutmenu,value='X,Y,Err 3-Column File',uname='savecutxye')
    void     = widget_button(fcutmenu,value='DAVE File',uname='savecutdave')
    void     = widget_button(parmmenu,value='Load Parameters...',uname='ldpmBut')
    void     = widget_button(parmmenu,value='Save Parameters...',uname='svpmBut')
    void     = widget_button(parmmenu,value='Change Self-shielding Factor...',uname='ssfcBut',/separator)
    void     = widget_button(parmmenu,value='Change Overall Intensity Factor...',uname='oifcBut')
    void     = widget_button(parmmenu,value='Change Smoothing Kernel...',uname='knpmBut')
    void     = widget_button(parmmenu,value='Set Data Directory...',uname='ddirBut',/separator)
    void     = widget_button(parmmenu,value='Set Working Directory...',uname='wdirBut')
    void     = widget_button(bkgrmenu,value='Load Empty Can File(s)',uname='emptBut')
    void     = widget_button(bkgrmenu,value='Load Detector Background File(s)',uname='bgflBut')
    void     = widget_button(bkgrmenu,value='Load Time Channel Background File(s)',uname='bgtcBut')
    void     = widget_button(bkgrmenu,value='Load Dark Count File(s)',uname='bgdkBut')
    void     = widget_button(bkgrmenu,value='Set Overall Background Rate...',uname='bgovBut')
    void     = widget_button(bkgrmenu,value='Clear Background',uname='bgclBut',sensitive=0)
    void     = widget_button(bkgrmenu,value='Load Vanadium File(s)',uname='vandBut',/separator)
    void     = widget_button(bkgrmenu,value='Clear Vanadium',uname='vdclBut',sensitive=0)
    mkdbmenu = widget_button(maskmenu,value='DCS Mask',uname='mkdbMenu',/menu)
    void     = dm_widget_button(mkdbmenu,value='Mask Negative Angle Detectors',uname='mkngBut')
    void     = dm_widget_button(mkdbmenu,value='Mask Upper Bank',uname='mkupBut')
    void     = dm_widget_button(mkdbmenu,value='Mask Central Bank',uname='mkcnBut')
    void     = dm_widget_button(mkdbmenu,value='Mask Lower Bank',uname='mkloBut')
    void     = dm_widget_button(mkdbmenu,value='Mask Upper and Lower Banks',uname='mkulBut')
    void     = dm_widget_button(mkdbmenu,value='Mask Central and Lower Banks',uname='mkmlBut')
    void     = dm_widget_button(mkdbmenu,value='Mask Upper and Central Banks',uname='mkucBut')
    stmkmenu = widget_button(maskmenu,value='Set Mask',/menu)
    void     = widget_button(stmkmenu,value='Set Mask...',uname='mkstBut')
    plmkmenu = widget_button(stmkmenu,value='Plot Mask...',uname='mkplBut',sensitive=0,/menu)
    void     = widget_button(plmkmenu,value='By Detector Number',uname='mkpldnum')
    void     = widget_button(plmkmenu,value='By Angle',uname='mkplangl')
    void     = widget_button(stmkmenu,value='Mask Bragg Peaks...',uname='mkbpBut',sensitive=0)
    void     = widget_button(maskmenu,value='Read Mask File...',uname='mkrdBut',/separator)
    void     = widget_button(maskmenu,value='Save Mask File...',uname='mksvBut',sensitive=0)
    void     = widget_button(maskmenu,value='Clear Mask',uname='mkclBut',sensitive=0,/separator)
    void     = dm_widget_button(igeomenu,value='Direct',uname='directGeom')
    void     = dm_widget_button(igeomenu,value='Inverse',uname='inverseGeom')
    void     = dm_widget_button(itypmenu,value='S(Q,omega)',uname='intnTyp0')
    void     = dm_widget_button(itypmenu,value='Symmetrized S(Q,omega)',uname='intnTyp1')
    void     = dm_widget_button(itypmenu,value='d2(sigma)/d(Omega)d(Ef)',uname='intnTyp2')
    void     = dm_widget_button(itypmenu,value='Chi(Q,omega)',uname='intnTyp3')
    void     = dm_widget_button(itypmenu,value='Unadjusted by ki/kf factor',uname='intnTyp4')
    void     = dm_widget_button(itypmenu,value='E-Integrated Intensity',uname='intnEint',set_button=self.eint_yn,$
                onstring='E-Integrated Intensity Enabled',offstring='E-Integrated Intensity Disabled',/separator)
    void     = dm_widget_button(binmmenu,value='Average',uname='binAvg')
    void     = dm_widget_button(binmmenu,value='Sum',uname='binSum')
    bincsmenu = widget_button(binmmenu,value='Constant Intervals',/menu,/separator)
    void     = dm_widget_button(bincsmenu,value='Yes',uname='bincsYes')
    void     = dm_widget_button(bincsmenu,value='No',uname='bincsNo')
    void     = dm_widget_button(moncmenu,value='Sum',uname='monSum')
    void     = dm_widget_button(moncmenu,value='Integrated Intensity',uname='monFit')
    mondmenu = widget_button(moncmenu,value='Monitor Choice',/menu,/separator)
    void     = dm_widget_button(mondmenu,value='FC0',uname='monFC0')
    void     = dm_widget_button(mondmenu,value='BM1',uname='monBM1')
    void     = dm_widget_button(mondmenu,value='Duration',uname='monTIME')
    void     = dm_widget_button(optnmenu,value='Preserve Negative 2theta Angle Value',uname='neg2th',$
               set_button=self.negative2th,onstring='Preserve Negative 2theta Angle Value',$
               offstring='Use Absolute 2theta Angle Value',/separator)
    void     = dm_widget_button(optnmenu,value='Allow Extra HKL Range',uname='hklRan',$
               set_button=self.dcor_yn,onstring='Allow Extra HKL Range',$
               offstring='Disallow Extra HKL Range',sensitive=0)
    void     = dm_widget_button(optnmenu,value='Dark Angle Correction',uname='darkCorr',$
               set_button=self.dcor_yn,onstring='Dark Angle Correction Enabled',$
               offstring='Dark Angle Correction Disabled',sensitive=0)
    void     = dm_widget_button(optnmenu,value='Elastic Peak Position Adjustment',uname='eAdjust',$
               set_button=self.eadjust,onstring='Elastic Peak Position Adjustment Enabled',$
               offstring='Elastic Peak Position Adjustment Disabled')
    void     = dm_widget_button(optnmenu,value='E-Dependent Detector Efficiency Correction',uname='edepEff',$
               set_button=self.edep_yn,onstring='E-Dependent Detector Efficiency Correction Enabled',$
               offstring='E-Dependent Detector Efficiency Correction Disabled')
    void     = dm_widget_button(optnmenu,value='Hide Error Bar',uname='errBar',set_button=1-self.errbar,$
               onstring='Error Bar Disabled',offstring='Error Bar Enabled')
    void     = widget_button(optnmenu,value='View Spurion Caused by Detector',uname='viewSpurion',$
               sensitive=0,/separator)
;    if float(!version.release) ge 6.0 then $
;    void     = dm_widget_button(optnmenu,value='Use iTools Plotting',uname='useItool',set_button=self.useitool,$
;               onstring='Use Classical Plotting',offstring='Use iTools Plotting',/separator,sensitive=0)
    void     = dm_widget_button(viewmenu,value='Projection',uname='viewProj',set_button=self.view[0],$
               onstring='Hide Projection',offstring='Show Projection')
    void     = dm_widget_button(viewmenu,value='Display',uname='viewDisp',set_button=self.view[1],$
               onstring='Hide Display',offstring='Show Display')
    void     = dm_widget_button(viewmenu,value='Trajectory',uname='viewTraj',set_button=self.view[2],$
               onstring='Hide Trajectory',offstring='Show Trajectory')
    void     = widget_button(viewmenu,value='Kill All Plot Windows',uname='killAll',/separator,sensitive=0)
    arrpmenu = widget_button(viewmenu,value='Arrange Plots',uname='arrPlot',sensitive=0,/menu)
    void     = dm_widget_button(powdmenu,value='None',uname='powderNone')
    void     = dm_widget_button(powdmenu,value='Al',uname='powderAl')
    void     = dm_widget_button(powdmenu,value='Cu',uname='powderCu')
    void     = dm_widget_button(powdmenu,value='Stainless Steel',uname='powderSt')
    void     = dm_widget_button(vaxsmenu,value='Orthogonal',uname='vaxisOrtho')
    void     = dm_widget_button(vaxsmenu,value='Arbitrary',uname='vaxisArbi')
    void     = dm_widget_button(abspmenu,value='None',uname='abspNone')
    void     = dm_widget_button(abspmenu,value='Cylinder',uname='abspCylinder')
    void     = dm_widget_button(abspmenu,value='Annulus',uname='abspAnnulus')
    void     = dm_widget_button(abspmenu,value='Sphere',uname='abspSphere')
    void     = widget_button(arrpmenu,value='Cascade',uname='arrCascade')
    void     = widget_button(arrpmenu,value='Table',uname='arrTable')
    void     = widget_button(helpmenu,value='Contents...',uname='hpctBut')
    void     = widget_button(helpmenu,value='How to Add a New File Type...',uname='hpftBut')
    void     = widget_button(helpmenu,value='About Mslice for DCS...',uname='selfBut',/separator)

    ;menu bar separator for windows system
    if !version.os_family eq 'Windows' then $
       mbar_sep = widget_label(self.tlb,sensitive=0,/dynamic_resize) $
    else $
       self.xsize[2] = self.xsize[2]+20

    self->dm_filemenu,/init ;also set up menu items
    self->reset_file

    ;load dcs_mslice.prm if existed
    parmfile = 'dcs_mslice.prm'
    parmpath = self.root
    defsysv,'!dave_defaults',exists=exists
    if exists then $
       if ptr_valid(!dave_defaults) then begin
          current = (*!dave_defaults).workDir
          if (file_test(current,/directory))[0] then parmpath=current
       endif
    if file_test(parmpath+self.pathsep+parmfile,/read) then $
       self->dm_load_parameter,parmpath+self.pathsep+parmfile,/init

    self->reset_droplist        ;adjust droplist values if necessary
    self->reset_projection
    self->reset_display
    self->reset_trajectory
    dm_center_kid,self.tlb
    widget_control,self.projBas,/update,/map
    widget_control,self.dispBas,/update,/map
    widget_control,self.trajBas,/update,/map
    widget_control,self.tlb,/realize,/update,/map
    geom  = widget_info(self.tlb,/geometry)
    space = total(1-self.view)*geom.space*(!version.os_family eq 'Windows')
    if float(!version.release) ge 5.5 then $
       self.geom = [geom.xsize,geom.ysize]+[0,space] $
    else begin
       self.geom = [geom.scr_xsize,geom.scr_ysize]+[0,space]
       widget_control,self.tlb,scr_xsize=self.geom[0],scr_ysize=self.geom[1]-space
    endelse
    ;show the horizontal bar style menu bar separator
    if n_elements(mbar_sep) ne 0 then begin
       sep = bytarr(1000) & sep[*] = byte(175) & sep = string(sep)
       widget_control,mbar_sep,set_value=sep,xsize=self.geom[0]
    endif
    widget_control,self.tlb,set_uvalue=self
    if self.eint_yn then $
       ok = dialog_message(['E-integrated intensity is enabled.',$
            'Go to "Option->View Intensity As" to disable it.'],dialog_parent=self.tlb)
    xmanager,registerName,self.tlb,cleanup='dcs_mslice_Exit',/no_block
    ;itregister, 'dm_UI','dm_ui',/user_interface         ;itool plotting
    return,1
end

;definition of dcs_mslice class
pro dcs_mslice__define
    void={dcs_mslice,               $
         group_leader:     0L,      $ ;group leader
         tlb:              0L,      $ ;container base of most of the widgets
         xsize:     lonarr(5),      $ ;to record the xsize
         geom:        [0L,0L],      $ ;xsize,ysize
         ssfac:          1.0e,      $ ;self shielding factor
         oifac:     ptr_new(),      $ ;overall intensity factor
                                    $ ;   scalor: powder and single crystal mode
                                    $ ;   vector: diffuse scattering mode
         temperature:    300e,      $ ;sample temperature for detailed balance calculation
         view:     [1b,1b,0b],      $ ;flag for window viewing option
         instrgeom:        0s,      $ ;instrument geometry  0:direct    1:inverse
         ftype:            0s,      $ ;file types: 0-DCS 1-SPE ...
         ftypename: ptr_new(),      $ ;store file type names: 0-"DCS" 1-"SPE" ...
         ftypeext:  ptr_new(),      $ ;store file type extensions
         bgratePtr: ptr_new(),      $ ;a pointer to the overall background rate or detector dark count array [[bgrate],[dbgrate]]
         bgeran:      [0e,0e],      $ ;background energy range
         bgtchnPtr: ptr_new(),      $ ;pointer which points to {tchan:[start,end] qty:[end-start+1]} background information
         bgdetsPtr: ptr_new(),      $ ;pointer which points to an [ndet] array of background
         bgdata:    ptr_new(),      $ ;pointer which points to a data structure which contains the background information
                                    $ ;-single crystal,powder
                                    $ ; {qty:[ntchan,ndet], err:[ntchan,ndet]}
                                    $ ;-diffuse scattering
                                    $ ; {qty:[ndet],err:[ndet]} or {qty:[nen,ndet],err[nen,ndet]}
         intn_typ:         0s,      $ ;intensity type
                                    $ ;0-S(Q,omega) 1-Symmetrized S(Q,omega) 2-d2sigma/dOmegadEf 3-Chi(Q,omega) 4-raw data
         mon_sumfit:       0s,      $ ;flag for monitor count calculation method 0:sum 1:gauss fit area
         dcs_mon:          1s,      $ ;dcs monitor choice: 0-fc0 1-bm1 2-duration; if 2, overall background rate is disabled
         bin_avgsum:       0s,      $ ;flag for binning method 0:average 1:sum
         bin_conststep:    0s,      $ ;flag for constant binning intervals 0:no  1:yes
         view_ortharbi:    0s,      $ ;flag for ortho or arbitrary viewing axis 0:orthogonal 1:arbitrary
         powd_typ:         0s,      $ ;0-none 1-Al 2-Cu 3-Stainless Steel
         eint_yn:          0b,      $ ;flag for E-Integrated intensity
                                    $ ;if set, then in Q-cut, I=sum(I[i,j].dE[i,j])/sum(dE[i,j])*E_width
         negative2th:      0b,      $ ;flag for perserving negative 2th in powder mode
         hklran_yn:        0b,      $ ;flag for allowing extra hkl range in single crystal modes
         eadjust:          0b,      $ ;flag for elastic peak adjustment 0:no 1:yes
         errbar:           1b,      $ ;flag for showing error bar
         useitool:         0b,      $ ;flag for using itools
         dcor_yn:          0b,      $ ;flag for dark angle correction in diffuse scattering modes
         dcor_eqran:fltarr(4),      $ ;E and 2theta range for the dark angle correction or tchan background
         dcor_info: ptr_new(),      $ ;a pointer points to {factor:[n_A2], a2:[n_A2]}
         edep_yn:          0b,      $ ;flag for calculating energy dep. det. effectioncy 0:no 1:yes

         mask:      ptr_new(),      $ ;detector mask pointer
         eff:       ptr_new(),      $ ;detector efficiency pointer
         fileSel:   obj_new(),      $ ;data file selection
         fileBas:          0L,      $ ;file selection base
         intn_lab:         '',      $ ;intensity label
         legd_lab:         '',      $ ;legend label for 1d plot
         titl_lab:         '',      $ ;title label
         monrate:          0e,      $ ;monitor rate from dcs data file
         kfactor:   ptr_new(),      $ ;(ki/kf)
                                    $ ;-powder,single crystal,diffuse scattering multiple E
                                    $ ; [ntchan] not rebinned
                                    $ ;-diffuse scattering sinegle E
                                    $ ; 1 for elastic and all time channels ki/kf_ave for the others
         samp_typ:         1s,      $ ;0-powder, 1-single crystal, 2-diffuse scattering single E, 3-diffuse multiple E
         rebinsize: ptr_new(),      $ ;allowed rebin size
         e_bin:     intarr(5),      $ ;ebin size/erange choice
                                    $ ; [0:1] e_bin size [2:3] erange choice [4] e_bin size for diffuse scattering mult. E
         e_range:     [0e,0e],      $ ;diffuse scattering energy range
         projBas:          0L,      $ ;projection base
         dispBas:          0L,      $ ;display base
         latt_parm: dblarr(6),      $ ;lattice parameters [a,b,c,alpha,beta,gamma]
         latt_recparm:dblarr(6),    $ ;reciprocal lattice parameters
         orie_u:   [1e,0e,0e],      $ ;[ux,uy,uz]
         orie_v:   [0e,1e,0e],      $ ;[vx,vy,vz]
         orie_psi:         0e,      $ ;psi
         orie_offset:      0e,      $ ;save the offset angle of psi
         view_type: strarr(5),      $ ;view  type ['Energy','|Q|','2Theta','Det Group Number','Time Channel']
         view_label:strarr(5),      $ ;labels     ['E','|Q|','2Theta','Det Group', 'T']
         view_unit: strarr(5),      $ ;units      ['(meV)','(A^-1)','(^o)','','(usec)'
         view_u1typ:       1s,      $ ;powder u1 type 0-E, 1-Q, 2-2theta, 3-Det Group
         view_u1:   fltarr(4),      $ ;[u1h,u1k,u1l,u1e]
         view_u1lab:strarr(2),      $ ;['|Q|','Qh'] -u1 label
         view_u2typ:       0s,      $ ;powder u2 type 0-E, 1-Q, 2-2theta, 3-Det Group
         view_u2:   fltarr(4),      $ ;[u2h,u2k,u2l,u2e]
         view_u2lab:strarr(2),      $ ;['E','Qk']   -u2 label
         view_u3:   fltarr(4),      $ ;[u3h,u3k,u3l,u3e]
         view_u3lab:      'E',      $ ;u3 label
         disp_perp:        2s,      $ ;perp to axis number
         disp_tran: fltarr(2),      $ ;thickness [from,to]
         disp_fold:        0b,      $ ;flag for folding x axis, single crystal only
         disp_hran: fltarr(2),      $ ;hor. ran. [from,to]
         disp_hstep:       0e,      $ ;horizontal step
         disp_vran: fltarr(2),      $ ;ver. ran. [from,to]
         disp_vstep:       0e,      $ ;vertical step
         disp_hkl:         0s,      $ ;extra hkl range number
         disp_hklran:fltarr(2),     $ ;hkl thickness [from, to]
         disp_iran: fltarr(2),      $ ;intensity range[from,to]
         disp_smooth:      1s,      $ ;smooth level
         disp_sm_kernel:fltarr(3,3),$ ;default smooth kernel
         disp_shading:     1s,      $ ;shading 0-flat 1-Gouraud
         dispcmap: strarr(41),      $ ;color map names
         disp_color:      13s,      $ ;color map number 13-RAINBOW
         cut_x:     intarr(4),      $ ;cut along axis number
         cut_ran:   fltarr(2),      $ ;cut range
         cut_step:         0e,      $ ;cut step
         cut_t1ran: fltarr(2),      $ ;thickness 1 range
         cut_t2ran: fltarr(2),      $ ;thickness 2 range
         cut_y:     intarr(4),      $ ;y axis number
         cut_yran:  fltarr(2),      $ ;y range
         cut_symbol:       0s,      $ ;plot symbol number
         symbols:  strarr(17),      $ ;symbol names
         cut_color:        0s,      $ ;color number
         colors:   strarr(15),      $ ;color names
         cut_line:         0s,      $ ;linestyle number,default solid line
         lines:     strarr(7),      $ ;linestyle names
         traj_type: strarr(8),      $ ;traj type names
         trajBas:          0L,      $ ;detector trajectory base
         traj_x:    intarr(4),      $ ;trajectory x type
         traj_xran: fltarr(2),      $ ;[xfrom,xto]
         traj_y:    intarr(4),      $ ;trajectory y type
         traj_yran: fltarr(2),      $ ;[yfrom,yto]
         traj_z:    intarr(4),      $ ;trajectory z type
         traj_zran: fltarr(2),      $ ;[zfrom,zto]
         traj_layer:       0s,      $ ;for trajectory overplot coloring
         detPosPtr: ptr_new(),      $ ;pointer which points to a structure
                                    $ ;{two_theta:[ndet], dtwo_theta:[ndet], psi:[ndet], dpsi:[ndet]}
         dataStrPtr:ptr_new(),      $ ;pointer which points to a data structure
                                    $ ;-single crystal,powder
                                    $ ; {qty:[ntchan,ndet], err:[ntchan,ndet], e:[ntchan],weight:weight,eief:eief,ewid:ewid[ntchan],$
                                    $ ;  info:{ch_wl:ch_wl,ch_ms:ch_ms,ch_srdenom:ch_srdenom,ch_res:ch_res,tsdmin:tsdmin,$
                                    $ ;  temperature:temperature,time:[ntchan]}}    time is only for dcs data
                                    $ ;-diffuse scattering
                                    $ ; {qty:[ndet,nfiles],err:[ndet,nfiles],rotation:[nfiles],weight:[nfiles],eief:eief,ewid:ewid[ntchan],$
                                    $ ;  info:{ch_wl:ch_wl,ch_ms:ch_ms,ch_srdenom:ch_srdenom,ch_res:ch_res,tsdmin:tsdmin,$
                                    $ ;  temperature:temperature},filename:open_file,filepath:open_path}
         projStrPtr:ptr_new(),      $ ;pointer which points to a structure
                                    $ ;-single crystal
                                    $ ; {V:[3,nen,ndet],hkl:[3,nen,ndet],en:[nen],two_theta:[ndet],$
                                    $ ;  qty:[nen,ndet],err:[nen,ndet],ewid:[nen]}
                                    $ ;-powder
                                    $ ; {Q:[nen,ndet],en:[nen],two_theta:[ndet],qty:[nen,ndet],err:[nen,ndet],ewid:[nen],time:[nen]}
                                    $ ;-diffuse scattering
                                    $ ; single E
                                    $ ; {V:[3,ndet,nfile],hkl:[3,ndet,nfile],en:[1],two_theta:[ndet],$
                                    $ ;  qty:[ndet,nfile],err:[ndet,nfile]}
                                    $ ; multiple E
                                    $ ; {V:[3,nen,ndet,nfile],hkl:[3,nen,ndet,nfile],en:[nen],two_theta:[ndet],$
                                    $ ;  qty:[nen,ndet,nfile],err:[nen,ndet,nfile]}
         powd_line: ptr_new(),      $ ;powder line for diffuse scattering mode
         absp_info: ptr_new(),      $ ;absorption information [type,interoplate,l0,l1,Rin,Rout]
                                    $ ; type: 0-cylinder 1-annulus 2-sphere
         file_hist:ptrarr(10),      $ ;save the latest 10 file selections
         n_history:        0s,      $ ;number of histories
         gr_list:   obj_new(),      $ ;container of all the graphic objects
         current:   obj_new(),      $ ;current plot object
         error:            0b,      $ ;error flag
         helpfile:    ['',''],      $ ;help file
         root:             '',      $ ;root directory
         pathsep:          '',      $ ;path separator
         symfont:          '',      $ ;symbol font name
         eief:             0e,      $ ;save fixed energy, Ei for direct geometry, Ef for inverse geometry
         a2:        fltarr(4),      $ ;save a2 start,end,step info, a2[3] saves the first file angle
         info:      ptr_new()       $ ;self information
    }
end

pro dcs_mslice,event
    if n_elements(event) ne 0 then $
       void = obj_new('dcs_mslice',group_leader=event.top) $
    else $
       void = obj_new('dcs_mslice')
end
