; $Id: dm_dcs2spe.pro,v 1.37 2007/07/17 21:27:16 ymqiu Exp $
;#######################################################################
;
; NAME:
;  dm_dcs2spe
;
; PURPOSE:
;  this program converts dcs files into spe files
;
; CATEGORY:
;  dcs tools
;
; AUTHOR:
;  Yiming Qiu
;  NIST Center for Neutron Research
;  100 Bureau Drive, Gaithersburg, MD 20899-6102
;  United States
;  yiming.qiu@nist.gov
;  July, 2007
;
; 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.
;
;#######################################################################

; convert open_file to a spe file and saved in save_path
; parameters:
;   open_path:      opening file path
;   open_file:      file name, excluding the directory
;   bg_rate:        background rate to be subtracted,in cts/hr
;   bg_error:       error of above
;   ebin_size:      E rebin size
; keywords:
;   qty,err,weight: data
;   absp_info:      pointer to absorption information
;   bgdataPtr:      pointer to backgound file data
;   deteffPtr:      pointer to detector efficiency data
;   detPtr:         a pointer to detector info
;   eadjust:        adjust the elastic peak position
;   edep_yn:        1:calculate energy dependent detector effeciency
;   ei:             incident energy
;   error:          1 if any error occurs, the results should be discarded
;                   possible cases of errors: 1.different file type 2.shutter closed for all files
;   intntyp:        intensity type 0-2
;   maskPtr:        detector mask pointer
;   montype:        monitor type
;   parent:         group leader, message is centered on the parent widget
;   powder:         if set or equal to 1 then powder mode
;   save_file:      file name(including directory) to be saved
;   savedet:        if set, detector profile will be saved


pro dm_convert_dcs2spe,open_path,open_file,bg_rate,bg_error,ebin_size,qty=qty,dqty=dqty,weight=weight,save_file=save_file,$
    parent=parent,bgdataPtr=bgdataPtr,deteffPtr=deteffPtr,savedet=savedet,detPtr=detPtr,maskPtr=maskPtr,powder=powder,$
    absp_info=absp_info,edep_yn=edep_yn,ei=ei,intntyp=intntyp,bgtype=bgtype,error=error,eadjust=eadjust,montype=montype
    dm_load_dcsdata,open_path,open_file,qty=qty,dqty=dqty,weight=weight,monrate=monrate,kfactor=kfactor,parent=parent,emean=emean,$
       error=error,info=info,ehist=ehist,eadjust=eadjust,montype=montype
    if error eq 1 then return

    ei = float(!dcs_hsq2mn/(info.ch_wl)^2)      ;incident energy

    if keyword_set(save_file) then begin
       mesg  = widget_base(title='converting...',/col,/base_align_center,group_leader=parent,map=0)
       label = widget_label(mesg,value=' ',/dynamic_resize,/align_center)
       widget_control,mesg,/realize,map=1
       dm_center_kid,mesg,parent

       ndet = n_elements(qty[0,*])
       nen  = n_elements(qty[*,0])

       ;subtract overall background
       if finite(bg_rate) then begin
          widget_control,label,set_value='subtracting overall background...'
          dm_center_kid,mesg,parent
          tmp_value = bg_rate/3600./monrate*(fltarr(nen)+1.)
          if ptr_valid(deteffPtr) then $
            tmp_value = tmp_value#(*deteffPtr) $
          else $
            tmp_value = tmp_value#(fltarr(ndet)+1.)
          qty = temporary(qty)-temporary(tmp_value)
          if finite(bg_error) then begin
            tmp_value = bg_error/3600./monrate*(fltarr(nen)+1.)
            if ptr_valid(deteffPtr) then $
                tmp_value = tmp_value#(*deteffPtr) $
            else $
                tmp_value = tmp_value#(fltarr(ndet)+1.)
            dqty = sqrt(temporary(dqty)^2+(temporary(tmp_value))^2)
          endif
          tmp_value = 0
       endif

       ;subtract background file data
       if ptr_valid(bgdataPtr) then begin
          widget_control,label,set_value='subtracting'+$
            ((bgtype eq 1)?'detector dependent background':'empty can')+' data...'
          dm_center_kid,mesg,parent
          if bgtype eq 0 then begin
             qty  = temporary(qty)-(*bgdataPtr).qty
             dqty = sqrt(temporary(dqty)^2+((*bgdataPtr).err)^2)
          endif else begin
             qty = temporary(qty)-(fltarr(nen)+1.0)#(*bgdataPtr)
          endelse
       endif

       ;detector efficiency adjustment
       if ptr_valid(deteffPtr) then begin
          widget_control,label,set_value='detector efficiency adjustment...'
          dm_center_kid,mesg,parent
          eff  = (fltarr(nen)+1.0)#(*deteffPtr)
          qty  = temporary(qty)/eff
          dqty = temporary(dqty)/eff
       endif

       ;kfactor adjustment
       case intntyp of
          0:    tmp=(kfactor)^4
          1:    begin
                ;ask for a sample temperature
                old = info.temperature
                notvalid = 1
                while notvalid do begin
                   temp = dm_dialog_input('sample temperature:',/float,default=old,dialog_parent=parent,$
                            title='Detailed blance calculation')
                   widget_control,/hourglass
                   if finite(temp) then $
                      if temp gt 0 then begin
                         info.temperature = temp
                         notvalid = 0 ;valid temperature given
                      endif
                endwhile
                ;calculate detailed balance factor
                kb  = 8.617342e-2    ;Boltzmann constant in mev.k^-1
                dbal= exp(-emean/(2.0*kb*temp))
                tmp = (kfactor)^4*dbal
                end
          2:    tmp = (kfactor)^3
          else: tmp = (kfactor)^4    ;S(Q,omega)
       endcase

       ;energy depedent detector efficiency adjustment
       if edep_yn eq 1 then begin
          det_thick    = 1.0     ; assumed detector thickness in cm.
          sigma_acoeff = 0.4466  ; (from Jeremy in cm-1/lambda_f) absorption factor of He3 gas
          sigma_s      = 0.0008  ; (from Jeremy in cm-1) sigma_s+
          wl0          = info.ch_wl
          sumtd        = sigma_acoeff*wl0*kfactor+sigma_s
          ;deteff_inv  = 1.0/(1.0-exp(-det_thick*sumtd))
          deteff_inv   = sumtd/(sumtd-sigma_s)/(1.0-exp(-det_thick*sumtd))    ;from Jeremy's Equation 9
          sumtd        = 0
          tmp          = temporary(tmp)*temporary(deteff_inv)
       endif
       for i=0,ndet-1 do begin
           qty[*,i]  = qty[*,i]*tmp
           dqty[*,i] = dqty[*,i]*tmp
       endfor
       tmp = 0  ;free up the memory


       ;rebin E
       if ebin_size gt 1 then dm_grid_ebin,ebin_size,qty,dqty,emean,histdata=ehist

       tt   = (*detPtr).two_theta
       dtt  = (*detPtr).dtwo_theta
       psi  = (*detPtr).psi
       dpsi = (*detPtr).dpsi

       ;mask detectors
       if ptr_valid(maskPtr) then begin
          widget_control,label,set_value='masking detectors...'
          dm_center_kid,mesg,parent
          ndet = n_elements(tt)
          tmp  = intarr(ndet)
          tmp[*maskPtr] = -1
          ind  = where(tmp eq 0,count)
          if count ne 0 then begin
             qty = qty[*,ind]
             dqty= dqty[*,ind]
             tt  = tt[ind]
             dtt = dtt[ind]
             psi = psi[ind]
             dpsi= dpsi[ind]
          endif
       endif

       ;absorption correction
       if ptr_valid(absp_info) then begin
          info= [(*absp_info)[0],(*absp_info)[2:(n_elements(*absp_info)-1)]]
          tmp = dm_calc_shielding(info,ei,emean,tt,interp=(*absp_info)[1],group_leader=parent)
          qty = temporary(qty)*tmp
          dqty= temporary(dqty)*temporary(tmp)
          widget_control,/hourglass
       endif

       if keyword_set(powder) then begin
          ;combine equivalent detectors
          widget_control,label,set_value='combining equivalent detectors...'
          dm_center_kid,mesg,parent
          tt   = abs(temporary(tt))
          ind  = sort(tt)
          ndet = n_elements(tt)
          qty  = qty[*,ind]
          dqty = dqty[*,ind]
          tt   = tt[ind]
          dtt  = dtt[ind]
          psi  = psi[ind]
          dpsi = dpsi[ind]
          ind  = uniq(tt)
          nun  = n_elements(ind)
          j    = 0L
          nen  = n_elements(qty[*,0])
          for i= 0L,nun-1 do begin
              qtmp = dblarr(nen)
              etmp = dblarr(nen)
              itmp = 0L
              while(tt[j] eq tt[ind[i]]) do begin
                 if dtt[i] lt dtt[j] then dtt[i]=dtt[j]
                 if dpsi[i] lt dpsi[j] then dpsi[i]=dpsi[j]
                 qtmp = temporary(qtmp)+qty[*,j]
                 etmp = temporary(etmp)+dqty[*,j]
                 itmp = itmp+1
                 j    = j+1
                 if j eq ndet then break
              endwhile
              qty[*,i] = qtmp/itmp
              dqty[*,i]= etmp/itmp
          endfor
          qty  = qty[*,0:nun-1]
          dqty = dqty[*,0:nun-1]
          dtt  = dtt[0:nun-1]
          dpsi = dpsi[0:nun-1]
          tt   = tt[ind]
          psi  = psi[ind]
       endif else begin
          ;convert two theta and psi to spe compatible format
          delta= max(psi)                    ;=7.6285 degree is the upper and lower row angle
          ndet = n_elements(tt)
          sind = sin(delta*!dtor)
          for i=0, ndet-1 do begin
              bank = fix(psi[i]/delta*1.2)    ;-1:lower 0:middle 1:upper
              if bank eq 0 then begin         ;middle bank
                 if tt[i] lt 0 then psi[i]=0.0 else psi[i]=180.0
              endif else begin
                 ang = asin(sind/sin(tt[i]*!dtor))/!dtor
                 ang = (ang ge 0)*180.0-ang
                 if bank eq 1 then psi[i]=ang else psi[i]=360.0-ang
              endelse
          endfor
          tt  = abs(tt)
          dtt = abs(dtt)
       endelse
       widget_control,label,set_value='saving as '+save_file[0]
       dm_center_kid,mesg,parent
       openw,unit,save_file,/get_lun,error=openerr
       if openerr ne 0 then begin
          ok = dialog_message("Can't write in "+save_file[0],/error,dialog_parent=parent)
          widget_control,mesg,/destroy
          return
       endif

       dm_write_spe,unit,tt,ehist,transpose(qty),transpose(dqty)    ;in dm_write_spe xdat[nx],ydat[ny] zdat[nx,ny]

       if n_elements(savedet) eq 1 then begin
          if savedet then begin
             detfile = dm_choose_file('phx',title='Please Select a File for Writing the Detector Profile File',$
                       dialog_parent=parent,/write,file='det.phx')
             if strlen(detfile) ne 0 then begin
                widget_control,label,set_value='saving detetor profile as '+detfile
                dm_center_kid,mesg,parent
                widget_control,/hourglass
                dm_write_phx,detfile,tt,dtt,psi,dpsi
             endif
          endif
       endif
       widget_control,mesg,/destroy
    end
    ; Clear any floating-point underflows that has occurred
    tmp = check_math(mask=32)
end


;save current settings in file dcs2spe.cfg
pro dm_save_cfg,state
    tmp1 = state.open_filesel->getproperty(/path)
    tmp2 = state.save_filesel->getproperty(/path)
    cd,state.root
    cfg  = state.root+state.pathsep+'dcs2spe.cfg'
    openw,unit,cfg,/get_lun,error=err
    if err ne 0 then return
    printf,unit,'opendir:'+tmp1
    printf,unit,'savedir:'+tmp2
    printf,unit,'bg_rate:'+dm_to_string(state.bg_rate)
    printf,unit,'bg_erro:'+dm_to_string(state.bg_error)
    printf,unit,'bg_eran:'+dm_to_string(state.bgeran[0])+'&'+dm_to_string(state.bgeran[1])
    printf,unit,'ebin_sz:'+dm_to_string(state.ebin_size)
    free_lun,unit
end


;load default settings
pro dm_load_cfg,state
    cd,current = current
    state.root = current
    cfg = current+state.pathsep+'dcs2spe.cfg'
    tmp = file_test(cfg)
    if tmp eq 0 then begin ;doesn't exist
       state.bg_rate   = 0.0
       state.bg_error  = 0.0
       state.bgeran    = [!values.f_nan,!values.f_nan]
       state.ebin_size = 1
       state.open_filesel->set_path,current
       state.save_filesel->set_path,current
       defsysv,'!dave_defaults',exists=exists
       if exists then $
         if ptr_valid(!dave_defaults) then begin
         state.open_fileSel->set_path,(*!dave_defaults).datDir
         state.save_filesel->set_path,(*!dave_defaults).workDir
         endif
       return
    endif
    openr,unit,cfg,/get_lun
    tmp=' '
    while(not eof(unit)) do begin
       readf,unit,tmp
       head = strmid(tmp,0,8)
       tmp  = strmid(tmp,8,strlen(tmp)-8)
       case head of
          'opendir:':state.open_filesel->set_path,tmp
          'savedir:':state.save_filesel->set_path,tmp
          'bg_rate:':state.bg_rate   = float(tmp)
          'bg_erro:':state.bg_error  = float(tmp)
          'bg_eran:':state.bgeran    = dm_to_number(strsplit(tmp,'&',/extract,/preserve))
          'ebin_sz:':state.ebin_size = fix(tmp)
          else:
       endcase
    endwhile
    free_lun,unit
end

;clear all objects and widget hierarchy
pro dm_dcs2spe_Exit,tlb
    widget_control,tlb,get_uvalue=state,/no_copy
    ptr_free,state.bgdata,state.eff,state.mask,state.detPosPtr,state.absp_info
    dm_save_cfg,state
    obj_destroy,[state.open_filesel,state.save_filesel]
    widget_control,tlb,/destroy
    online_help,/quit           ;close the help file if it is opened by online_help
end

;event handler
pro dm_dcs2spe_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
    widget_control,event.handler,get_uvalue=state,/no_copy
    state.open_filesel->getproperty,path=open_path,file=open_file
    state.save_filesel->getproperty,path=save_path,file=save_file

    ;catch and ignore all errors in this program
    catch, myerror
    if myerror ne 0 then begin
       ok=dialog_message(dialog_parent=state.tlb,!error_state.msg,/error)
       catch,/cancel
       widget_control,event.handler,set_uvalue=state,/no_copy
       return
    end

    case (event.id) of
       state.tlb:    widget_control,event.id,scr_xsize=state.geom[0],scr_ysize=state.geom[1]
       state.loadBut:begin
          if n_elements(open_file) eq 0 then begin
              ok=dialog_message('Please select DCS files first.',/error,dialog_parent=event.handler)
              break
          endif
          ptr_free,state.bgdata
          widget_control,state.clearBut,sensitive=0
          if state.bgflType eq 1 then begin
             default = dm_to_string(state.bgeran) & ok=0
             while (not ok) do begin
                new = dm_dialog_input(['from:','to:'],title='Energy range',xsize=100,default=default,/float,$
                   dialog_parent=state.tlb,info='In units of meV')
                if total(finite(new)) eq 2 then $
                   if new[1] gt new[0] then begin
                      state.bgeran = new
                      e_range = new & ok = 1
                   endif
             endwhile
             dm_load_dcsdata,open_path,open_file,qty=qty,dqty=dqty,t_chan=2,$
                   e_range=e_range,avgsum=0,title='loading background file...',comment=comment,$
                   parent=event.handler,error=error,eadjust=state.eadjust,montype=state.monType
             if error eq 1 then break
             if n_elements(qty) ne 0 then begin
                state.bgdata = ptr_new(qty)
                widget_control,state.clearBut,sensitive=1
             endif
          endif else begin
             dm_convert_dcs2spe,open_path,open_file,qty=qty,dqty=dqty,weight=weight,error=error,$
                parent=event.handler,eadjust=state.eadjust,montype=state.monType
             if error eq 1 then break
             state.bgdata = ptr_new({qty:temporary(qty),err:temporary(dqty)})
             widget_control,state.clearBut,sensitive=1
          endelse
         end
       state.clearBut:begin
          widget_control,state.clearBut,sensitive=0
          ptr_free,state.bgdata
         end
       state.bgflEmpt:begin
          widget_control,state.clearBut,sensitive=0
          ptr_free,state.bgdata
          state.bgflType = 0
          dm_toggle_menubut,state.bgflEmpt,state.bgflDet
         end
       state.bgflDet:begin
          widget_control,state.clearBut,sensitive=0
          ptr_free,state.bgdata
          state.bgflType = 1
          dm_toggle_menubut,state.bgflDet,state.bgflEmpt
         end
       state.loadV:begin
          if n_elements(open_file) eq 0 then begin
             ok=dialog_message('Please select DCS files first.',/error,dialog_parent=event.handler)
             break
          endif
          ptr_free,state.eff
          widget_control,state.clearV,sensitive=0
          dm_convert_dcs2spe,open_path,open_file,qty=qty,dqty=dqty,weight=weight,ei=ei,error=error,$
              parent=event.handler,eadjust=state.eadjust,montype=state.monType
          if error eq 1 then break
          ;subtract empty can
          if ptr_valid(state.bgdata) and (state.bgflType eq 0) then begin
             ans = dialog_message('Do you want to subtract the empty can data from the vanadium data?',$
                   /question,dialog_parent=event.handler)
             if ans eq 'Yes' then $
                qty = qty-(*state.bgdata).qty
          endif
          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=event.handler)
          if min(strlen(parm)) gt 0 then begin
             parm = dm_to_number(parm,/float)
             if total(finite(parm)) eq 4 then begin
                tth    = (*state.detPosPtr).two_theta
                factor = dm_calc_shielding([1,parm],ei,0,tth,group_leader=event.handler)
                eff    = eff*factor/mean(factor)
             endif else begin
                ok = dialog_message('Invalid inputs. Absorption correction for vanadium sample is disabled.',$
                       dialog_parent=event.handler,/error)
             endelse
          endif
          state.eff = ptr_new(eff,/no_copy)
          widget_control,state.clearV,sensitive=1
         end
       state.clearV:begin
          widget_control,state.clearV,sensitive=0
          ptr_free,state.eff
         end
       state.combBut:begin
          if n_elements(open_file) lt 2 then begin
             ok = dialog_message('Please choose 2 or more data files.',/error,dialog_parent=event.handler)
             break
          endif
          if n_elements(save_file) eq 0 then save_file='combine.spe' else begin
             if save_file eq '.spe' or strlen(save_file) eq 0 then save_file='combine.spe' else begin
                tmp = strmid(save_file,3,4,/reverse_offset)
                if strlowcase(tmp) ne '.spe' then save_file=save_file+'.spe'
             endelse
          endelse
          state.save_filesel->set_file,filename=save_file
          save_file = save_path+state.pathsep+save_file
          dm_convert_dcs2spe,open_path,open_file,state.bg_rate,state.bg_error,state.ebin_size,$
              save_file=save_file,parent=event.handler,bgdataPtr=state.bgdata,deteffPtr=state.eff,$
              savedet=state.yn,detPtr=state.detPosPtr,maskPtr=state.mask,powder=state.samptyp,$
              absp_info=state.absp_info,edep_yn=state.edep_yn,intntyp=state.intntyp,$
              bgtype=state.bgflType,eadjust=state.eadjust,montype=state.monType
          state.save_filesel->set_path
          state.save_filesel->set_file,filename=''
         end
       state.convBut:begin
          if n_elements(open_file) eq 0 then begin
             ok=dialog_message('Please select DCS files first.',/error,dialog_parent=event.handler)
             break
          endif
          nfile= n_elements(open_file)
          yn   = intarr(nfile)
          yn[nfile-1]=state.yn
          for i=0,nfile-1 do begin
            ;generate the output file name according to input file name
            save_file = strsplit(open_file[i],'.',/extract)
            state.save_filesel->set_file,filename=save_file[0]+'.spe'
            save_file = save_path+state.pathsep+save_file[0]+'.spe'
            dm_convert_dcs2spe,open_path,open_file[i],state.bg_rate,state.bg_error,state.ebin_size,$
              save_file=save_file,parent=event.handler,bgdataPtr=state.bgdata,deteffPtr=state.eff,$
              savedet=yn[i],detPtr=state.detPosPtr,maskPtr=state.mask,powder=state.samptyp,$
              absp_info=state.absp_info,edep_yn=state.edep_yn,intntyp=state.intntyp,$
              bgtype=state.bgflType,eadjust=state.eadjust,montype=state.monType
            state.save_filesel->set_path    ;update the save directory
            state.save_filesel->set_file,filename=' '
          endfor
         end
       state.doneBut:begin
          widget_control,event.handler,set_uvalue=state,/no_copy
          widget_control,event.handler,/destroy
          return
         end
       state.mkcnBut:begin   ;view central banks only
          ptr_free,state.mask
          mask = dm_mask_detbanks([-1,1])
          state.mask = ptr_new(mask,/no_copy)
          dm_toggle_menubut,state.mkcnBut,[state.mkloBut,state.mkupBut]
          widget_control,state.mkclBut,sensitive=1
         end
       state.mkloBut:begin   ;view lower banks only
          ptr_free,state.mask
          mask = dm_mask_detbanks([0,1])
          state.mask = ptr_new(mask,/no_copy)
          dm_toggle_menubut,state.mkloBut,[state.mkcnBut,state.mkupBut]
          widget_control,state.mkclBut,sensitive=1
         end
       state.mkupBut:begin   ;view upper banks only
          ptr_free,state.mask
          mask = dm_mask_detbanks([-1,0])
          state.mask = ptr_new(mask,/no_copy)
          dm_toggle_menubut,state.mkupBut,[state.mkloBut,state.mkcnBut]
          widget_control,state.mkclBut,sensitive=1
         end
       state.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(state.mask) then begin
             exist   =   1
             n_mask  =   n_elements(*state.mask)
             if n_mask le 20 then begin
                default=strcompress(string(*state.mask,format='('+string(n_mask)+'(i5,","))'),/remove_all)
                if strmid(default,0,/reverse_offset) eq ',' then $
                   default=strmid(default,0,strlen(default)-1)
             endif
             ptr_free,state.mask
          endif else exist=0
          dm_toggle_menubut,state.mkcnBut,[state.mkcnBut,state.mkloBut,state.mkupBut]
          widget_control,state.mkclBut,sensitive=0
          tmp = dm_dialog_input(dialog_parent=state.tlb,'Det num:',title='Masking detectors',default=default,$
            info=['Detector number starts from 0 to 912 for DCS.','eg:370,373 or 370:374 c'],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=state.tlb)
             break
          endif else begin
             status = ''
             index  = strpos(tmp,'c',/reverse_search)
             if index[0] ne -1 then status='c'
             index  = strpos(tmp,'C',/reverse_search)
             if index[0] ne -1 then status='c'
             index  = strpos(tmp,'u',/reverse_search)
             if index[0] ne -1 then status='u'
             index  = strpos(tmp,'U',/reverse_search)
             if index[0] ne -1 then status='u'
             index  = strpos(tmp,'l',/reverse_search)
             if index[0] ne -1 then status='l'
             index  = strpos(tmp,'L',/reverse_search)
             if index[0] ne -1 then status='l'

             ind0  = strsplit(tmp,'[a-zA-Z '+string(9b)+',:-]',/regex)
             ind1  = strsplit(tmp,':-')
             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(tmp,'[a-zA-Z '+string(9b)+',:-]',/regex,/extract)
             mask = -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],/int)
                       if finite(tmp2) then mask=[mask,tmp1+findgen(abs(tmp2-tmp1)+1)] $
                       else mask = [mask,tmp1]
                    endif else mask = [mask,tmp1]
                 endif
             endfor
             index    =  where(mask ge 0,count)
             if count ne 0 then begin
                mask=fix(mask[index]+0.1,type=3)
                case status of
                    'c': mask=dm_common(mask,dm_mask_detbanks(0),/no_copy)
                    'l': mask=dm_common(mask,dm_mask_detbanks(-1),/no_copy)
                    'u': mask=dm_common(mask,dm_mask_detbanks(1),/no_copy)
                    else:
                endcase
             endif
          endelse
          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
                state.mask = ptr_new(mask[ind])
                widget_control,state.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=state.tlb) $
                else ok=dialog_message('No valid detector mask is specified.',dialog_parent=state.tlb)
             endelse
             ind=-1
          endif
         end
       state.mkrdBut:begin
          fdir = state.open_filesel->getproperty(/path)
          file = dialog_pickfile(path=dir,dialog_parent=state.tlb)
          if strlen(file) eq 0 then break
          if ptr_valid(state.mask) then ptr_free,state.mask
          dm_toggle_menubut,state.mkcnBut,[state.mkcnBut,state.mkloBut,state.mkupBut]
          widget_control,state.mkclBut,sensitive=0
          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=state.tlb)
             mask = mask-ok
             ind  = where((mask lt 913) and (mask ge 0),count)
             if count ne 0 then begin
                state.mask = ptr_new(mask[ind])
                widget_control,state.mkclBut,sensitive=1
             endif
          endif
         end
       state.mkclBut:begin
          ptr_free,state.mask  ;clear the mask
          dm_toggle_menubut,state.mkcnBut,[state.mkcnBut,state.mkloBut,state.mkupBut]
          widget_control,state.mkclBut,sensitive=0
         end
       state.crstBut:begin
          state.samptyp = 0
          dm_toggle_menubut,state.crstBut,state.powdBut
         end
       state.powdBut:begin
          state.samptyp = 1
          dm_toggle_menubut,state.powdBut,state.crstBut
         end
       state.yesBut:begin
          state.yn = 1
          dm_toggle_menubut,state.yesBut,state.noBut
         end
       state.noBut:begin
          dm_toggle_menubut,state.noBut,state.yesBut
          state.yn = 0
         end
       state.intnTyp0:if state.intntyp ne 0 then begin
          state.intntyp = 0
          dm_toggle_menubut,state.intnTyp0,[state.intnTyp1,state.intnTyp2]
         endif
       state.intnTyp1:if state.intntyp ne 1 then begin
          state.intntyp = 1
          dm_toggle_menubut,state.intnTyp1,[state.intnTyp0,state.intnTyp2]
         endif
       state.intnTyp2:if state.intntyp ne 2 then begin
          state.intntyp = 2
          dm_toggle_menubut,state.intnTyp2,[state.intnTyp1,state.intnTyp0]
         endif
       state.abspNon:begin
          ptr_free,state.absp_info
          dm_toggle_menubut,state.abspNon,[state.abspAnn,state.abspCyl,state.abspSph]
         end
       state.abspAnn:begin
          default = [1,!values.f_nan,!values.f_nan,!values.f_nan,!values.f_nan]
          if ptr_valid(state.absp_info) then begin
             default[0:3] = (*(state.absp_info))[1:4]
             if (*(state.absp_info))[0] eq 1 then default[4] =   (*(state.absp_info))[5]
            ptr_free,state.absp_info
          endif
          dm_toggle_menubut,state.abspAnn,[state.abspNon,state.abspCyl,state.abspSph]
          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(['L0(cm):','L1(cm):','Rout(cm):','Rin(cm):','Interpolate:'],$
                   default=[default[1:4],default[0]],/float,info=mesg,is_droplist=[0,0,0,0,1],$
                   droplist_content=ptr_new(['No','Yes']),/return_number,$
                   title='Annular geometry',xsize=140,dialog_parent=state.tlb)
          if total(finite(info)) eq 5 then state.absp_info=ptr_new([1,info[4],info[0:3]]) $
          else begin
            dm_toggle_menubut,state.abspNon,[state.abspAnn,state.abspCyl,state.abspSph]
            ok=dialog_message('Invalid inputs. Absorption correction is disabled.',dialog_parent=state.tlb,/error)
          endelse
         end
       state.abspCyl:begin
          default = [1,!values.f_nan,!values.f_nan,!values.f_nan]
          if ptr_valid(state.absp_info) then begin
             default = (*(state.absp_info))[1:4]
             ptr_free,state.absp_info
          endif
          dm_toggle_menubut,state.abspCyl,[state.abspNon,state.abspAnn,state.abspSph]
          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(['L0(cm):','L1(cm):','R(cm):','Interpolate:'],$
                   default=[default[1:3],default[0]],/float,info=mesg,is_droplist=[0,0,0,1],$
                   droplist_content=ptr_new(['No','Yes']),/return_number,$
                   title='Cylindrical geometry',xsize=140,dialog_parent=state.tlb)
          if total(finite(info)) eq 4 then state.absp_info=ptr_new([0,info[3],info[0:2]]) $
          else begin
             dm_toggle_menubut,state.abspNon,[state.abspAnn,state.abspCyl,state.abspSph]
             ok=dialog_message('Invalid inputs. Absorption correction is disabled.',dialog_parent=state.tlb,/error)
          endelse
         end
       state.abspSph:begin
          default = [1,!values.f_nan,!values.f_nan,!values.f_nan]
          if ptr_valid(state.absp_info) then begin
             default =   (*(state.absp_info))[1:4]
             ptr_free,state.absp_info
          endif
          dm_toggle_menubut,state.abspSph,[state.abspNon,state.abspAnn,state.abspCyl]
          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(['L0(cm):','L1(cm):','R(cm):','Interpolate:'],$
                   default=[default[1:3],default[0]],/float,info=mesg,is_droplist=[0,0,0,1],$
                   droplist_content=ptr_new(['No','Yes']),/return_number,$
                   title='Spherical geometry',xsize=140,dialog_parent=state.tlb)
          if total(finite(info)) eq 4 then state.absp_info=ptr_new([2,info[3],info[0:2]]) $
          else begin
             dm_toggle_menubut,state.abspNon,[state.abspAnn,state.abspCyl,state.abspSph]
             ok=dialog_message('Invalid inputs. Absorption correction is disabled.',dialog_parent=state.tlb,/error)
          endelse
         end
       state.monFC0: begin
          state.monType = 0
          dm_toggle_menubut,state.monFC0,[state.monBM1,state.monTIME]
         end
       state.monBM1: begin
          state.monType = 1
          dm_toggle_menubut,state.monBM1,[state.monFC0,state.monTIME]
         end
       state.monTIME: begin
          state.monType = 2
          dm_toggle_menubut,state.monTIME,[state.monBM1,state.monFC0]
         end
       state.eadjBut:begin
          state.eadjust = (1b)-state.eadjust
          dm_set_button,event.id,state.eadjust,onstring='Elastic Peak Position Adjustment Enabled',$
              offstring='Elastic Peak Position Adjustment Disabled'
         end
       state.edepEff:begin
          state.edep_yn = (1b)-state.edep_yn
          dm_set_button,event.id,state.edep_yn,onstring='E-Dependent Detector Efficiency Correction Enabled',$
              offstring='E-Dependent Detector Efficiency Correction Disabled'
         end
       state.hpctBut:if strlen(state.helpfile) 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(state.helpfile,tlb=event.top) $
          else $
             online_help,book=state.helpfile,/full_path
         endif
       state.bgInfo:begin
          widget_control,event.id,get_value=tmp
          state.bg_rate = dm_to_number(tmp,/float)
         end
       state.bgError:begin
          widget_control,event.id,get_value=tmp
          state.bg_error = dm_to_number(tmp,/float)
         end
       state.eBin:begin
          widget_type = widget_info(event.id,/type)
          if widget_type eq 8 then tmp_value=widget_info(event.id,/droplist_select) $
          else if widget_type eq 12 then begin
             tmp_value=event.index
             if dm_to_string(state.rebinsize[tmp_value]) ne event.str then break
          endif else tmp_value=0
          state.ebin_size = state.rebinsize[tmp_value]
         end
       else: ;nothing
    endcase
    widget_control,event.handler,set_uvalue=state,/no_copy
end

;main program
pro dm_dcs2spe,event
    state={ group_leader:   0L, $   ;group leader
         tlb:               0L, $   ;top level base
         open_filesel:obj_new(),$   ;open file selector
         save_filesel:obj_new(),$   ;save file selector
         bg_rate:           0E, $   ;overall background in cts/hour
         bg_error:          0E, $   ;associated error
         ebin_size:         1s, $   ;E binning size
         rebinsize: [1s,2s,4s,5s,8s,10s,20s,25s,40s,50s], $
                                    ;allowed e rebin size
         bgInfo:            0L, $   ;fast neutron background text box
         bgError:           0L, $   ;associated error text box
         bgflType:          0s, $   ;0:empty can 1:detector dependent energy gain side background
         bgflEmpt:          0L, $   ;empty can bg file type button
         bgflDet:           0L, $   ;detector dependent bg file type button
         bgeran:       [0e,0e], $   ;energy range for detector dependent bg
         monType:           1s, $   ;monitor type 0:FC0 1:BM1 2:duration
         monFC0:            0L, $   ;FC0 button
         monBM1:            0L, $   ;BM1 button
         monTIME:           0L, $   ;duration button
         eBin:              0L, $   ;E binning size text box
         loadBut:           0L, $   ;load background file
         clearBut:          0L, $   ;clear background file
         loadV:             0L, $   ;load vanadium file
         clearV:            0L, $   ;clear vanadium file
         combBut:           0L, $   ;combine files into a single spe file button
         convBut:           0L, $   ;convert button
         doneBut:           0L, $   ;done button
         mkupBut:           0L, $   ;mask central and lower bank button
         mkcnBut:           0L, $   ;mask top and lower bank button
         mkloBut:           0L, $   ;mask top and central bank button
         mkstBut:           0L, $   ;set mask button
         mkrdBut:           0L, $   ;read mask file button
         mkclBut:           0L, $   ;clear the mask button
         yesBut:            0L, $   ;create detector file
         noBut:             0L, $   ;don't create detector file
         yn:                0s, $   ;0 no 1 yes
         eadjBut:           0L, $   ;elastic peak position adjustment button
         eadjust:           0s, $   ;0: no adjustment 1:adjust elastic peak
         edepEff:           0L, $   ;E-dependent det. efficiency correction button
         edep_yn:           1s, $   ;0 no 1 yes
         abspNon:           0L, $   ;no absorption correction button
         abspCyl:           0L, $   ;absorption correction for cylinder button
         abspAnn:           0L, $   ;absorption correction for annulus button
         abspSph:           0L, $   ;absorption correction for sphere button
         hpctBut:           0L, $   ;help content button
         crstBut:           0L, $   ;single crystal button
         powdBut:           0L, $   ;powder button
         samptyp:           0s, $   ;0-single crystal, 1-powder
         intnTyp0:          0L, $   ;S(Q,omega) button
         intnTyp1:          0L, $   ;symmetrized S(Q,omega) button
         intnTyp2:          0L, $   ;d2(sigma)/d(Omega)d(Ef) button
         intntyp:           0s, $   ;0-S(Q,omega) 1-Symmetrized S(Q,omega) 2-d2(sigma)/d(Omega)d(Ef)
         root:              '', $   ;root directory
         pathsep:           '', $   ;path seperator
         helpfile:'dcs_mslice.pdf',$;help file
         geom:   [0L,0L,0L,0L], $   ;xsize,ysize,xoffset,yoffset
         bgdata:     ptr_new(), $   ;background data
         eff:        ptr_new(), $   ;detector efficiency
         mask:       ptr_new(), $   ;mask pointer
         detPosPtr:  ptr_new(), $   ;detector positions
         absp_info:  ptr_new()  $   ;absorption information
    }
    registerName    ='dm_dcs2spe'
    if xregistered(registerName) then return   ;only allow one copy to be running at one time
    ;get the correct path separator
    if float(!version.release) ge 5.5 then state.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
       state.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
    if n_elements(event) ne 0 then begin
       state.group_leader = event.top
       state.tlb = widget_base(title='Convert DCS data files to SPE format',/col,kill_notify='dcs2spe_Exit',$
                group_leader=event.top,/tlb_size_event,mbar=mbar,xpad=0,ypad=0)
       ;widget_control,event.top,sensitive=0
    endif else $
       state.tlb = widget_base(title='Convert DCS data files to SPE format',/col,kill_notify='dcs2spe_Exit',$
                /tlb_size_event,mbar=mbar,xpad=0,ypad=0)
    ;menu bar
    filemenu = widget_button(mbar,value='File',/menu)
    maskmenu = widget_button(mbar,value='Mask',/menu)
    optnmenu = widget_button(mbar,value='Option',/menu)
    sampmenu = widget_button(optnmenu,value='Sample Type',/menu)
    detnmenu = widget_button(optnmenu,value='Create Detector File',/menu)
    itypmenu = widget_button(optnmenu,value='Intensity Type',/menu)
    abspmenu = widget_button(optnmenu,value='Absorption Correction',/menu)
    bgflmenu = widget_button(optnmenu,value='BG File Type',/menu)
    mtypmenu = widget_button(optnmenu,value='Monitor Type',/menu)
    helpmenu = widget_button(mbar,value='Help',/menu)
    defsysv,'!DAVE_AUXILIARY_DIR',exists=exists
    if exists then state.helpfile = !DAVE_AUXILIARY_DIR+state.helpfile $
    else state.helpfile = file_which(state.helpfile,/include)
    state.detPosPtr = dm_load_detpos(/dcs)  ;load detector informations
    state.doneBut   = widget_button(filemenu,value='Exit',uvalue='doneBut',uname='DONE')
    state.mkcnBut   = dm_widget_button(maskmenu,value='Mask upper and lower banks',uvalue='mkcnBut',uname='VIEWCENTRALBANK')
    state.mkupBut   = dm_widget_button(maskmenu,value='Mask central and lower banks',uvalue='mkupBut',uname='VIEWUPPERBANK')
    state.mkloBut   = dm_widget_button(maskmenu,value='Mask upper and central banks',uvalue='mkloBut',uname='VIEWLOWERBANK')
    state.mkstBut   = widget_button(maskmenu,value='Set your own mask...',uvalue='mkstBut',uname='SETMASK')
    state.mkrdBut   = widget_button(maskmenu,value='Read mask file...',uvalue='mkrdBut',uname='READMASK')
    state.mkclBut   = widget_button(maskmenu,value='Clear the mask',uvalue='mkclBut',uname='CLEARMASK',sensitive=0,/separator)
    state.crstBut   = dm_widget_button(sampmenu,value='Single Crystal',uvalue='crstBut',uname='SINGLECRYSTAL')
    state.powdBut   = dm_widget_button(sampmenu,value='Powder',uvalue='powdBut',uname='POWDER')
    state.samptyp   = 1                             ;0-single crystal, 1-powder
    dm_toggle_menubut,state.powdBut,state.crstBut   ;default single crystal
    state.yesBut    = dm_widget_button(detnmenu,value='Yes')
    state.noBut     = dm_widget_button(detnmenu,value='No')
    state.yn        = 0                             ;default not saving
    dm_toggle_menubut,state.noBut,state.yesBut
    state.intnTyp0  = dm_widget_button(itypmenu,value='S(Q,omega)',uname='intnTyp0')
    state.intnTyp1  = dm_widget_button(itypmenu,value='Symmetrized S(Q,omega)',uname='intnTyp1')
    state.intnTyp2  = dm_widget_button(itypmenu,value='d2(sigma)/d(Omega)d(Ef)',uname='intnTyp2')
    state.intntyp   = 0                             ;default S(Q,omega)
    dm_toggle_menubut,state.intnTyp0,[state.intnTyp1,state.intnTyp2]
    state.abspNon   = dm_widget_button(abspmenu,value='None',uname='abspNone')
    state.abspCyl   = dm_widget_button(abspmenu,value='Cylinder',uname='abspCylinder')
    state.abspAnn   = dm_widget_button(abspmenu,value='Annulus',uname='abspAnnulus')
    state.abspSph   = dm_widget_button(abspmenu,value='Sphere',uname='abspSphere')
    dm_toggle_menubut,state.abspNon,[state.abspAnn,state.abspCyl,state.abspSph]
    state.bgflEmpt  = dm_widget_button(bgflmenu,value='Empty Can',uname='bgflEmpt')
    state.bgflDet   = dm_widget_button(bgflmenu,value='Detector Dependent Background',uname='bgflDet')
    dm_toggle_menubut,state.bgflEmpt,state.bgflDet
    state.monFC0    = dm_widget_button(mtypmenu,value='FC0',uname='monFC0')
    state.monBM1    = dm_widget_button(mtypmenu,value='BM1',uname='monBM1')
    state.monTIME   = dm_widget_button(mtypmenu,value='Duration',uname='monTIME')
    dm_toggle_menubut,state.monBM1,[state.monFC0,state.monTIME]
    state.eadjBut   = dm_widget_button(optnmenu,value='Elastic Peak Position Adjustment',uname='eAdjust',$
               set_button=state.eadjust,onstring='Elastic Peak Position Adjustment Enabled',$
               offstring='Elastic Peak Position Adjustment Disabled',/separator)
    state.edepEff   = dm_widget_button(optnmenu,value='E-Dependent Detector Efficiency Correction',uname='edepEff',$
               set_button=state.edep_yn,onstring='E-Dependent Detector Efficiency Correction Enabled',$
               offstring='E-Dependent Detector Efficiency Correction Disabled')
    state.hpctBut   = widget_button(helpmenu,value='Help',uvalue='hpctBut',uname='HELPCONTENT')

    ;menu bar separator for windows system
    if !version.os_family eq 'Windows' then begin
       mbar_sep     = widget_label(state.tlb,sensitive=0,/dynamic_resize)
       tmp          = 0
    endif else tmp  = 3
    row             = widget_base(state.tlb,/row,ypad=0)
    openCol         = widget_base(row,/col,ypad=0)
    cmdCol          = widget_base(row,/col,/align_center,ypad=0)
    saveCol         = widget_base(row,/col,ypad=0)

    label           = widget_label(openCol,value='DCS file directory')
    label           = widget_label(saveCol,value='SPE file directory')

    state.open_filesel = obj_new('dm_filesel',parent=openCol,ysize=11+tmp,/frame,filter='.dcs')
    state.save_filesel = obj_new('dm_filesel',parent=saveCol,ysize=9+tmp,/write,/frame,filter='.spe')

    dm_load_cfg,state   ;load previous saved settings

    label         = widget_label(cmdcol,value='Overall background rate')
    label         = widget_label(cmdcol,value='(cts/hr/det):')
    state.bgInfo  = widget_text(cmdcol,uvalue='bgInfo',value=dm_to_string(state.bg_rate),/editable,/all_events)
    label         = widget_label(cmdcol,value='Associated error:')
    state.bgError = widget_text(cmdcol,uvalue='bgError',value=dm_to_string(state.bg_error),/editable,/all_events)
    geom          = widget_info(state.bgError,/geom)
    label         = widget_label(cmdcol,value='Energy binning size:')
    select        = where(state.rebinsize eq state.ebin_size,count)
    if count ne 1 then begin
       select = 0 &  state.ebin_size = 1
    endif
    state.eBin    = dm_widget_droplist(cmdcol,uvalue='eBin',value=dm_to_string(state.rebinsize),xsize=geom.scr_xsize,$
                    select=select)
    line          = widget_base(cmdcol,/row,xpad=0,space=0,ypad=0)
    state.loadBut = widget_button(line,value='Load BG',uvalue='loadBut',uname='LOADBGFILE',xsize=geom.scr_xsize/2)
    state.clearBut= widget_button(line,value='Clear BG',uvalue='clearBut',uname='CLEARBGFILE',xsize=geom.scr_xsize/2,sensitive=0)
    line          = widget_base(cmdcol,/row,xpad=0,space=0,ypad=0)
    state.loadV   = widget_button(line,value='Load V',uvalue='loadV',uname='LOADVFILE',xsize=geom.scr_xsize/2)
    state.clearV  = widget_button(line,value='Clear V',uvalue='clearV',uname='CLEARVFILE',xsize=geom.scr_xsize/2,sensitive=0)
    state.convBut = widget_button(cmdCol,value='Convert',uvalue='convBut',uname='CONVERT')
    state.combBut = widget_button(cmdCol,value='Combine',uvalue='combBut',uname='COMBINE')

    if float(!version.release) ge 5.6 then begin
       widget_control,state.loadBut,tooltip="Go to Option->BG File Type to change the background file type"
    endif

    dm_center_kid, state.tlb   ;centering the top level base
    widget_control,state.tlb,/realize
    geom          = widget_info(state.tlb,/geometry)
    state.geom    = [geom.scr_xsize,geom.scr_ysize,geom.xoffset,geom.yoffset]
    ;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=state.geom[0]
       widget_control,state.tlb,scr_xsize=state.geom[0],scr_ysize=state.geom[1]
    endif

    tlb = state.tlb
    widget_control,state.tlb,set_uvalue=state,/no_copy
    xmanager,registerName,tlb,cleanup='dm_dcs2spe_Exit',/no_block
end