; $Id: dm_filetools.pro,v 1.16 2008/03/19 20:46:50 ymqiu Exp $
;#######################################################################
;
; NAME:
;  dm_filetools
;
; PURPOSE:
;  handle file type menu and file tool menu events and all data file loading related events
;
; CATEGORY:
;  dcs_mslice
;
; 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.
;
;#######################################################################

; parameter:
;   eventname: event name = widget_info(event.id,/uname)
; keyword:
;   event:     passed event structure

;files need to be included
@dm_load_dcsdata
@dm_load_spe
@dm_load_phx
@dm_load_inx

;combine data with same rotation angles
;parameters:
;   ang:        [nang] rotation angle
;   qty,dqty:   [*,nang] or [*,*,nang] data
;   weight:     [nang] weight of the data
pro dm_combine_a2,ang,qty,dqty,weight
    ang = fix(ang*(200.0d)+0.5,type=3)/200.0    ;  accurate up to 0.005 degree
    ind = sort(ang) & nang = n_elements(ang)
    if total(abs(ind-indgen(nang))) ne 0 then begin
       ndim   = size(qty,/n_dimensions)
       ang    = ang[ind]
       weight = weight[ind]
       if ndim eq 2 then begin      ;single E
          qty  = qty[*,ind]
          dqty = dqty[*,ind]
       endif else begin             ;multiple E
          qty  = qty[*,*,ind]
          dqty = dqty[*,*,ind]
       endelse
       ind = uniq(ang)
       nun = n_elements(ind)
       if nun ne nang then begin
          j = 0L
          for i=0L,nun-1 do begin
              qtmp = 0.0
              etmp = 0.0
              wgt  = 0.0
              while(ang[j] eq ang[ind[i]]) do begin
                 if ndim eq 2 then begin     ;single E
                    qtmp = temporary(qtmp)+qty[*,j]*weight[j]
                    etmp = temporary(etmp)+dqty[*,j]*dqty[*,j]*weight[j]*weight[j]
                 endif else begin            ;multiple E
                    qtmp = temporary(qtmp)+qty[*,*,j]*weight[j]
                    etmp = temporary(etmp)+dqty[*,*,j]*dqty[*,*,j]*weight[j]*weight[j]
                 endelse
                 wgt = wgt+weight[j]
                 j   = j+1L
                 if j eq nang then break
              endwhile
              if wgt eq 0 then wgt=1.0
              weight[i] = wgt
              if ndim eq 2 then begin    ;single E
                 qty[*,i]  = qtmp/wgt
                 dqty[*,i] = sqrt(etmp)/wgt
              endif else begin           ;multiple E
                 qty[*,*,i]  = qtmp/wgt
                 dqty[*,*,i] = sqrt(etmp)/wgt
              endelse
          endfor
          qtmp = 0 & etmp=0  ;free up the memory
          if ndim eq 2 then begin        ;single E
             qty  = qty[*,0:nun-1]
             dqty = dqty[*,0:nun-1]
          endif else begin               ;multiple E
             qty  = qty[*,*,0:nun-1]
             dqty = dqty[*,*,0:nun-1]
          endelse
          ang    = ang[ind]
          weight = weight[0:nun-1]
       endif
    endif
end

function dcs_mslice::dm_filetools,eventname,event=event,init=init
    handled = 1b    ;event handled flag
    if strmid(eventname,0,6) eq 'ftype_' then begin ;file type selection event
       type = dm_to_number(strmid(eventname,6,strlen(eventname)-6),/int)
       eventname = 'ftype_'
    endif
    case strlowcase(eventname) of
        'emptbut':begin  ;load empty can file(s)
            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 empty can files first.',/error)
               break
            endif
            case self.ftype of
                 0: begin   ;dcs data
                    self->dm_load_dcs_emptycan,open_path,open_file,parent=event.handler,error=error,$
                        comment=comment,qty=qty,dqty=dqty,ang=ang,weight=weight
                    end
                 1: begin   ;spe file
                    self->dm_load_spe,open_path,open_file,parent=event.handler,error=error,$
                        qty=qty,dqty=dqty,ang=ang,t_chan=self.e_bin[self.samp_typ],e_range=self.e_range,$
                        eint_yn=self.eint_yn,avgsum=self.bin_avgsum,diffuse=(self.samp_typ ge 2),$
                        title='loading empty can file...',diffetyp=(self.samp_typ eq 3)
                    end
                 2: begin   ;inx file
                    self->dm_load_inx,open_path,open_file,parent=event.handler,error=error,$
                        qty=qty,dqty=dqty,ang=ang,t_chan=self.e_bin[self.samp_typ],e_range=self.e_range,$
                        eint_yn=self.eint_yn,avgsum=self.bin_avgsum,diffuse=(self.samp_typ ge 2),$
                        title='loading empty can file...',diffetyp=(self.samp_typ eq 3),comment=comment
                    end
                 else: error =1b ;do nothing
            endcase
            cd,self.root
            if keyword_set(error) then break
            if n_elements(qty) ne 0 then begin ;background file eg. empty can files
               ptr_free,self.bgdata
               if n_elements(ang) eq 0 then ang=0
               if (self.samp_typ eq 3) and (self.e_bin[4] gt 1) then begin
                  tmp = size(qty,/dimension)
                  dm_grid_ebin,self.e_bin[4],qty,dqty,fltarr(tmp[0]),avgsum=self.bin_avgsum
               endif
               if n_elements(weight) ne n_elements(ang) then weight = fltarr(n_elements(ang))+1.0
               ;combine data with the same angles
               dm_combine_a2,ang,qty,dqty,weight
               weight = 0
               self.bgdata=ptr_new({qty:temporary(qty),err:temporary(dqty),rotation:temporary(ang)})
               if n_elements(comment) eq 0 then comment=(*self.ftypename)[self.ftype]+' empty can data'
               self->set_filehistory,comment,open_path,open_file
               self->my_widget_control,'bgclBut',sensitive=1
            endif
          end
        'bgflbut':begin  ;load detector dependent background file(s)
            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 background files first.',/error)
               break
            endif
            ;quest for the energy range
            default = dm_to_string(self.bgeran) & ok=0
            while (not ok) do begin
                new = dm_dialog_input(['from:','to:'],title='Energy range',xsize=100,default=default,/float,$
                        dialog_parent=self.tlb,info='In units of meV')
                if total(finite(new)) eq 2 then $
                   if new[1] gt new[0] then begin
                      self.bgeran = new
                      ok = 1
                   endif
            endwhile
            case self.ftype of
                 0: begin   ;dcs data
                    self->dm_load_dcs_detbackground,open_path,open_file,parent=event.handler,error=error,$
                        comment=comment,qty=qty,dqty=dqty
                    end
                 1: begin   ;spe file
                    self->dm_load_spe_detbackground,open_path,open_file,parent=event.handler,error=error,$
                        qty=qty,dqty=dqty
                    end
                 2: begin   ;inx file
                    self->dm_load_inx_detbackground,open_path,open_file,parent=event.handler,error=error,$
                        qty=qty,dqty=dqty,comment=comment
                    end
                 else: error =1b ;do nothing
            endcase
            cd,self.root
            if keyword_set(error) then break
            if n_elements(qty) ne 0 then begin ;background file
               ptr_free,self.bgdetsPtr
               self.bgdetsPtr = ptr_new(qty)
               if n_elements(comment) eq 0 then comment=(*self.ftypename)[self.ftype]+' det. background data'
               self->set_filehistory,comment,open_path,open_file
               self->my_widget_control,'bgclBut',sensitive=1
            endif
          end
        'bgtcbut':begin  ;load time channel background file(s)
            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 background files first.',/error)
               break
            endif
            default = self.dcor_eqran & ok = 1b
            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 averaged intensity in the specified two theta range',$
                              'will be used as the background for the time channels in',$
                              'the specified E range.'],dialog_parent=self.tlb)
            message = 'Invalid input.'
            if total(finite(eqran)) ne 4 then $
               ok = 0b $
            else if (eqran[0] ge eqran[1]) or (eqran[2] ge eqran[3]) then $
               ok = 0b $
            else if ptr_valid(self.detPosPtr) then begin
               det_tt = (*self.detPosPtr).two_theta
               index  = where((abs(det_tt) ge eqran[2]) and (abs(det_tt) le eqran[3]),count)
               if count eq 0 then begin
                  ok = 0b
                  message = 'Two theta range is incompatible with the detector angles.'
               endif
            endif
            if not ok then begin
               message = [message,'The background file'+$
                        ((n_elements(open_file) gt 1)?'s are':' is')+' not loaded.']
               ok = dialog_message(message,dialog_parent=self.tlb)
               break
            endif
            self.dcor_eqran = eqran
            case self.ftype of
                 0: begin   ;dcs data
                    self->dm_load_dcs_tchanbackground,open_path,open_file,parent=event.handler,error=error,$
                        comment=comment,qty=qty,dqty=dqty,emean=emean
                    end
                 1: begin   ;spe file
                    self->dm_load_spe_tchanbackground,open_path,open_file,parent=event.handler,error=error,$
                        qty=qty,dqty=dqty,emean=emean
                    end
                 2: begin   ;inx file
                    self->dm_load_inx_tchanbackground,open_path,open_file,parent=event.handler,error=error,$
                        qty=qty,dqty=dqty,comment=comment,emean=emean
                    end
                 else: error =1b ;do nothing
            endcase
            cd,self.root
            if keyword_set(error) then break
            if not ptr_valid(self.detPosPtr) then begin
               ok = dialog_message('The detector information is missing. Background data is discarded.',$
                    dialog_parent=self.tlb)
               break
            endif
            if n_elements(qty) ne 0 then begin ;background file
               if (self.samp_typ eq 3) and (self.e_bin[4] gt 1) then begin
                  dm_grid_ebin,self.e_bin[4],qty,dqty,emean,avgsum=self.bin_avgsum
               endif
               det_tt = (*self.detPosPtr).two_theta
               index  = where((abs(det_tt) ge eqran[2]) and (abs(det_tt) le eqran[3]),count)
               if count eq 0 then begin
                  ok = 0b
                  ok = dialog_message('Two theta range is incompatible with the detector angles.',$
                       dialog_parent=self.tlb)
                  break
               endif
               qty = qty[*,index]
               qty = total(qty,2)/count
               ptr_free,self.bgtchnPtr
               self.bgtchnPtr = ptr_new({emean:emean,qty:qty})
               if n_elements(comment) eq 0 then comment=(*self.ftypename)[self.ftype]+' tchan. background data'
               self->set_filehistory,comment,open_path,open_file
               self->my_widget_control,'bgclBut',sensitive=1
            endif
          end
        'bgdkbut':begin  ;shutter closed dark count file(s)
            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 count files first.',/error)
               break
            endif
            case self.ftype of
                 0: begin   ;dcs data
                    self->dm_load_dcs_darkcount,open_path,open_file,parent=event.handler,error=error,$
                        comment=comment,bgrate=bgrate,dbgrate=dbgrate
                    end
                 1: begin   ;spe file
                    ok = dialog_message('Not implemented.',dialog_parent=self.tlb)
                    error = 1b
                    end
                 2: begin   ;inx file
                    ok = dialog_message('Not implemented.',dialog_parent=self.tlb)
                    error = 1b
                    end
                 else: error =1b ;do nothing
            endcase
            cd,self.root
            if keyword_set(error) then break
            if n_elements(bgrate) ne 0 then begin ;background file eg. empty can files
               ptr_free,self.bgratePtr
               self.bgratePtr=ptr_new([[bgrate],[dbgrate]])
               if n_elements(comment) eq 0 then comment=(*self.ftypename)[self.ftype]+' dark count file'
               self->set_filehistory,comment,open_path,open_file
               self->my_widget_control,'bgclBut',sensitive=1
            endif
          end
        'vandbut':begin  ;load vanadium file(s)
            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 vanadium files first.',/error)
               break
            endif
            case self.ftype of
                 0: begin   ;dcs data
                    self->dm_load_dcs_vanadium,open_path,open_file,parent=event.handler,error=error,$
                        comment=comment,qty=qty,ei=eief
                    end
                 1: begin   ;spe file
                    self->dm_load_spe,open_path,open_file,qty=qty,parent=event.handler,$
                        title='loading vanadium file...',error=error,eief=eief
                    end
                 2: begin   ;inx file
                    self->dm_load_inx,open_path,open_file,qty=qty,parent=event.handler,$
                        title='loading vanadium file...',error=error,eief=eief,comment=comment
                    end
                 else: error =1b ;do nothing
            endcase
            cd,self.root
            if keyword_set(error) then break
            if n_elements(comment) eq 0 then comment=(*self.ftypename)[self.ftype]+' vanadium data'
            self->set_filehistory,comment,open_path,open_file
            if (self.samp_typ lt 2) and ptr_valid(self.bgdata) then begin  ;empty can subtraction
               size1 = size(qty,/dimensions)
               size2 = size((*self.bgdata).qty,/dimensions)
               if n_elements(size1) eq n_elements(size2) and total(abs(size1-size2)) eq 0 then begin
                  ans = dialog_message('Do you want to subtract the empty can data from the vanadium data?',$
                       /question,dialog_parent=self.tlb)
                  if ans eq 'Yes' then $
                     qty = qty-(*self.bgdata).qty
               endif
            endif
            ptr_free,self.eff
            eff = dm_calc_deteff(qty,/fit)
            ;add absorption correction
            mesg = [ 'To skip the absorption correction for vanadium file,',$
                     'press OK without filling in all the information.',$
                     '',$
                     '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])}' ]
            default = ['2.8','2.7','','']
            parm = dm_dialog_input(['L0(cm):','L1(cm):','Rout(cm):','Rin(cm):'],$
                default=default,info=mesg,title='Absorption correction for vanadium',$
                xsize=140,dialog_parent=self.tlb)
            if min(strlen(parm)) gt 0 then begin
               parm = dm_to_number(parm,/float)
               if total(finite(parm)) eq 4 then begin
                  tth    = (*self.detPosPtr).two_theta
                  factor = dm_calc_shielding([1,parm],eief,0,tth,group_leader=self.tlb)
                  eff    = eff*factor/mean(factor)
               endif else begin
                  ok = dialog_message('Invalid inputs. Absorption correction for vanadium sample is disabled.',dialog_parent=self.tlb)
               endelse
            endif
            self.eff = ptr_new(eff,/no_copy)
            self->my_widget_control,'vdclBut',sensitive=1
          end
        'loadbut':begin  ;load data file(s)
            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 data files first.',/error)
               break
            endif
            case self.ftype of
                 0: begin   ;dcs data
                    if self.samp_typ ge 2 then $
                       if self.e_bin[self.samp_typ] ne 2 then self.e_range=[!values.f_nan,!values.f_nan]
                    self->dm_load_dcs,open_path,open_file,parent=event.handler,error=error,$
                        comment=comment,qty=qty,dqty=dqty,weight=weight,ang=ang,ei=eief,$
                        info=info,ewid=ewid,emean=emean,monrate=monrate,kfactor=kfactor,tmean=tmean
                    end
                 1: begin   ;spe file
                    e_range = self.e_range
                    self->dm_load_spe,open_path,open_file,parent=event.handler,diffuse=(self.samp_typ ge 2),$
                        /phxfile,avgsum=self.bin_avgsum,e_range=e_range,t_chan=self.e_bin[self.samp_typ],error=error,$
                        qty=qty,dqty=dqty,eief=eief,ang=ang,emean=emean,info=info,ewid=ewid,$
                        eint_yn=self.eint_yn,kfactor=kfactor,diffetyp=(self.samp_typ eq 3)
                    if (self.samp_typ ge 2) and (n_elements(e_range) ne 0) then self.e_range=e_range
                    end
                 2: begin   ;inx file
                    e_range = self.e_range
                    self->dm_load_inx,open_path,open_file,parent=event.handler,diffuse=(self.samp_typ ge 2),$
                        avgsum=self.bin_avgsum,e_range=e_range,t_chan=self.e_bin[self.samp_typ],error=error,$
                        qty=qty,dqty=dqty,eief=eief,ang=ang,emean=emean,info=info,ewid=ewid,eint_yn=self.eint_yn,$
                        kfactor=kfactor,diffetyp=(self.samp_typ eq 3),comment=comment
                    if (self.samp_typ ge 2) and (n_elements(e_range) ne 0) then self.e_range=e_range
                    end
                 else: error =1b ;do nothing
            endcase
            cd,self.root
            if keyword_set(error) then break
            ;readjust psi value inteligently
            if (n_elements(ang) ne 0) and finite(self.orie_offset) and (self.view[0] eq 1) and (self.samp_typ ge 1) then begin
               self.orie_psi = ang[0]+self.orie_offset
               self->my_widget_control,'oriePsi',self.projBas,set_value=dm_to_string(self.orie_psi)
            endif
            if n_elements(monrate) eq 0 then monrate = 1.0
            if n_elements(kfactor) eq 0 then kfactor = 1.0
            if n_elements(info)    eq 0 then info = {temperature:300}
            if n_elements(tmean)   eq 0 then tmean = 0.0
            self.monrate=monrate
            ptr_free,self.dataStrPtr,self.projStrPtr
            if self.samp_typ ge 2 then begin
               nang =  n_elements(ang)
               if n_elements(weight) eq 0 then weight=fltarr(nang)+1.0
               if (self.samp_typ eq 3) and (self.e_bin[4] gt 1) then begin
                  dm_grid_ebin,self.e_bin[4],qty,dqty,emean,avgsum=self.bin_avgsum
                  if n_elements(kfactor) gt 1 then $
                     dm_grid_ebin,self.e_bin[4],kfactor $
                  else begin
                     if self.instrgeom eq 0 then $
                        kfactor = sqrt(eief/(eief-emean)) $
                     else $
                        kfactor = sqrt((eief+emean)/eief)
                  endelse
                  if n_elements(ewid) ne 0 then dm_grid_ebin,self.e_bin[4],ewid
               endif
               if n_elements(ewid) eq 0 then ewid=1.0
               self.a2[3] = ang[0]  ;save the angle of first file
               ;combine data with the same A2 angles
               dm_combine_a2,ang,qty,dqty,weight
               (*self.oifac) = fltarr(n_elements(ang))+1.0     ;reset the overall intensity factor to 1.0
            endif else begin
               if n_elements(weight) eq 0 then weight=1.0
               if n_elements(ewid) eq 0   then ewid=fltarr(n_elements(emean))+1.0
               if n_elements(ang) eq 0    then ang=!values.f_nan
               (*self.oifac) = 1.0 ;reset the overall intensity factor to 1.0
            endelse
            self.dataStrPtr = ptr_new({qty:temporary(qty),err:temporary(dqty),weight:temporary(weight),$
                    rotation:temporary(ang),info:temporary(info),eief:temporary(eief),ewid:temporary(ewid),e:temporary(emean),$
                    time:tmean,filename:open_file,filepath:open_path})
            ptr_free,self.kfactor & self.kfactor=ptr_new(kfactor,/no_copy)
            self->my_widget_control,['addBut','clearDat','mkplBut','mkbpBut'],sensitive=1     ;allow adding data & clear data & plot mask
            if (finite(self.orie_psi) eq 0) and (self.samp_typ ge 2) then begin
               self.orie_psi = (*self.dataStrPtr).rotation[0]
               if self.view[0] eq 1 then $
                  self->my_widget_control,'oriePsi',set_value=dm_to_string(self.orie_psi)
            endif
            self->set_display_button
            if n_elements(comment) eq 0 then begin
               comment = '' & legend = ''
            endif else begin    ;legend and comments for dm_plot
               tmp    = strsplit(comment,', '+string(9b),/extract) &ntmp=n_elements(tmp)
               itmp   = where(['mk','k','t','tesla','gauss','pa'] eq strlowcase(tmp[ntmp-1]),count)
               legend = tmp[(0>(ntmp-1))]
               if (count ne 0) or strlen(tmp[ntmp-1]) eq 1 then $
                  if ntmp ge 2 then legend=tmp[ntmp-2]+' '+legend
               if legend eq 'T=' then begin
                  tmp = dm_to_string((*self.dataStrPtr).info.temperature)+' K'
                  legend  = legend+tmp
                  comment = comment+tmp
               endif
            endelse
            self->my_widget_control,'legdLab',set_value=legend & self.legd_lab=legend
            self->my_widget_control,'titlLab',set_value=comment & self.titl_lab=comment

            if strlen(comment) eq 0 then comment=(*self.ftypename)[self.ftype]+' data '+open_file[0]+(n_elements(open_file) gt 1?'...':'')
            self->set_filehistory,comment,open_path,open_file
          end
        'addbut':begin   ;add dcs data file to current data pointer
            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 data files first.',/error)
               break
            endif
            case self.ftype of
                 0: begin   ;dcs data
                    info = (*self.dataStrPtr).info
                    self->dm_load_dcs,open_path,open_file,parent=event.handler,error=error,$
                        comment=comment,qty=qty,dqty=dqty,weight=weight,ang=ang,$
                        info=info,title='adding data file...'
                    end
                 1: begin   ;spe file
                    info = (*self.dataStrPtr).info
                    e_range = self.e_range
                    self->dm_load_spe,open_path,open_file,parent=event.handler,diffuse=(self.samp_typ ge 2),$
                        avgsum=self.bin_avgsum,e_range=e_range,t_chan=self.e_bin[self.samp_typ],error=error,qty=qty,dqty=dqty,$
                        eief=eief,ang=ang,emean=emean,info=info,eint_yn=self.eint_yn,diffetyp=(self.samp_typ eq 3)
                    end
                 2: begin   ;inx file
                    info = (*self.dataStrPtr).info
                    e_range = self.e_range
                    self->dm_load_inx,open_path,open_file,parent=event.handler,diffuse=(self.samp_typ ge 2),$
                        avgsum=self.bin_avgsum,e_range=e_range,t_chan=self.e_bin[self.samp_typ],error=error,qty=qty,dqty=dqty,$
                        eief=eief,ang=ang,emean=emean,info=info,eint_yn=self.eint_yn,diffetyp=(self.samp_typ eq 3)
                    end
                 else: error = 1b ;do nothing
            endcase
            cd,self.root
            if keyword_set(error) then break
            if n_elements(comment) eq 0 then comment=(*self.ftypename)[self.ftype]+' data'
            self->set_filehistory,comment,open_path,open_file
            if self.samp_typ ge 2 then begin
               if n_elements(weight) eq 0 then weight = fltarr(n_elements(ang))+1.0
               if self.samp_typ eq 3 then begin
                  if self.e_bin[4] gt 1 then begin
                     tmp = size(qty,/dimension)
                     dm_grid_ebin,self.e_bin[4],qty,dqty,fltarr(tmp[0]),avgsum=self.bin_avgsum
                  endif
                  qty = [[[(*self.dataStrPtr).qty]],[[temporary(qty)]]]
                  err = [[[(*self.dataStrPtr).err]],[[temporary(dqty)]]]
               endif else begin
                  qty = [[(*self.dataStrPtr).qty],[temporary(qty)]]
                  err = [[(*self.dataStrPtr).err],[temporary(dqty)]]
               endelse
               weight = [(*self.dataStrPtr).weight,temporary(weight)]
               ang    = [(*self.dataStrPtr).rotation,temporary(ang)]
               filename = [(*self.dataStrPtr).filename,open_file]
               e      = (*self.dataStrPtr).e
               eief   = (*self.dataStrPtr).eief
               info   = (*self.dataStrPtr).info
               ewid   = (*self.dataStrPtr).ewid
               path   = (*self.dataStrPtr).filepath
               time   = (*self.dataStrPtr).time
               ;combine data with the same A2 angles
               dm_combine_a2,ang,qty,err,weight
               (*self.oifac) = fltarr(n_elements(ang))+1.0     ;reset the overall intensity factor to 1.0
               ptr_free,self.dataStrPtr
               self.dataStrPtr=ptr_new({qty:temporary(qty),err:temporary(err),weight:temporary(weight),$
                   rotation:temporary(ang),info:temporary(info),eief:temporary(eief),ewid:temporary(ewid),$
                   e:temporary(e),time:time,filename:temporary(filename),filepath:path})
            endif else begin
               if n_elements(weight) eq 0 then weight = 1.0
               (*self.dataStrPtr).qty = ((*self.dataStrPtr).qty)*((*self.dataStrPtr).weight)+qty*weight
               (*self.dataStrPtr).err = sqrt((((*self.dataStrPtr).err)*((*self.dataStrPtr).weight))^2+(dqty*weight)^2)
               (*self.dataStrPtr).weight = ((*self.dataStrPtr).weight)+weight
               (*self.dataStrPtr).qty = ((*self.dataStrPtr).qty)/((*self.dataStrPtr).weight)
               (*self.dataStrPtr).err = ((*self.dataStrPtr).err)/((*self.dataStrPtr).weight)
            endelse
          end
        'ftype_':   begin
            if self.ftype eq type then break   ;no change
            ;may need to adjust trajectory axes
            if type*self.ftype eq 0 then begin
               noneid = [5,4]
               if self.traj_x[0] eq noneid[type eq 0?0:1] then self.traj_x[0] = 1
               if self.traj_y[0] eq noneid[type eq 0?0:1] then self.traj_y[0] = 0
               if self.traj_z[0] eq noneid[self.ftype eq 0?0:1] then $
                  self.traj_z[0] = noneid[type eq 0?0:1]
            endif
            self.ftype = type
            ;remove all relevant data
            if not keyword_set(init) then begin
               ptr_free,self.detPosPtr,self.dataStrPtr,self.projStrPtr
               self->set_display_button
               ;clear all possible background data and mask
               self.monrate = 1.0
               ptr_free,self.eff,self.bgtchnPtr,self.bgratePtr,self.bgdetsPtr,self.bgdata,self.mask
            endif
            self->dm_filemenu       ;reset file menu and other menus
            self.fileSel->set_filter,'.'+(*self.ftypeext)[type]          ;change file filter
            ;change the about ... information in the help menu
            (*self.info)[0] = '--Mslice for '+(*self.ftypename)[type]+' --'
            ;(*self.info)[3] = 'Yiming Qiu(yiming.qiu@nist.gov)  3/2008' ;add your own name here if you like
            widget_control,self.tlb,tlb_set_title=(*self.info)[0]
            self->my_widget_control,'selfBut',set_value='About Mslice for '+(*self.ftypename)[type]+'...'
            if (self.samp_typ eq 0) and (not keyword_set(init)) then begin    ;powder only, the droplist items may have changed
               reset_disp = ((self.view_u1typ eq 4) or (self.view_u2typ eq 4))
               self->reset_projection,/reset
               self->reset_trajectory,/reset
               if reset_disp then self->reset_display,/reset
            endif
          end

        ;DCS tools
        'dcs_cspebut':  dm_dcs2spe,event        ;convert dcs files to spe files
        'dcs_algnbut':  dcs_cryst_align,event,[self.latt_parm,self.orie_u,self.orie_v]  ;plot dcs single crystal alignment files

        ;put the events of your own instrument specific tools below

        else: handled = 0b      ;event not handled
    endcase

    return,handled
end