; $Id: hfbs_reddyn.pro,v 1.13 2005/02/09 16:58:01 dimeo Exp $
;###############################################################################
;
; NAME:
;  HFBS_REDDYN
;
; PURPOSE:
;
;
; CATEGORY:
;  DAVE, HFBS, data reduction
;
; AUTHOR:
;   Robert M. Dimeo, Ph.D.
;   NIST Center for Neutron Research
;   100 Bureau Drive
;   Gaithersburg, MD 20899
;   Phone: (301) 975-8135
;   E-mail: robert.dimeo@nist.gov
;   http://www.ncnr.nist.gov/staff/dimeo
;
; 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 of if the code in this file is
;  included in another product.
;
;###############################################################################
; hfbs_redDyn.pro
;
; Main reduction widget program for dynamic runs on HFBS.
; This program gets called from hfbs_runreduce.pro.
;
; Written by R.M.Dimeo (01/14/02)
;
; Modification history:
; ---------------------
;
; 01/18/02 (RMD):	Grouping detectors and summing files now is done
;					using the method of minimum-variance for combining
;					measurements.(Ref: Stuart Meyer, Data Analysis for
;					Scientists and Engineers, Wiley and Sons (1975), pp. 42-43).
;
;;;;;;;;;;;;;;;;;;;;;
pro hfbs_redDynCancel,event
widget_control,event.top,get_uvalue = pState
(*pState).msg = 'CANCEL'
widget_control,event.top,/destroy
return
end
;;;;;;;;;;;;;;;;;;;;;
pro hfbs_redDynQuit,event
widget_control,event.top,get_uvalue = pState
if n_elements(*(*pState).outFilePtr) eq 0 then begin
  void = dialog_message(dialog_parent = event.top,'No new DAVE files')
  return
endif else begin
  (*pState).msg = 'DISMISS'
  widget_control,event.top,/destroy
endelse

return
end
;;;;;;;;;;;;;;;;;;;;;
pro hfbsrdSelFiles,event
widget_control,event.top,get_uvalue = pState
files = dialog_pickfile(dialog_parent = event.top,/read, $
                               filter = ['*.hfbs'],$
                               title = 'Select raw data file',$
                               path = (*pState).path,$
                               /multiple_files)
nfiles = n_elements(files)
if (1.0*total(file_test(files,/regular)) ne nfiles) then begin
  void = dialog_message(dialog_parent = event.top,'At least one of the selected files is invalid')
  return
endif
*(*pState).filePtr = files
widget_control,(*pState).fileText,set_value = files
return
end
;;;;;;;;;;;;;;;;;;;;;
pro hfbsrdSelVanFile,event
widget_control,event.top,get_uvalue = pState
file = dialog_pickfile(dialog_parent = event.top,/read, $
                               filter = ['*.hfbs'],$
                               title = 'Select vanadium file',$
                               path = (*pState).path)
if (1.0*(file_test(file,/regular)) ne 1) then begin
  void = dialog_message(dialog_parent = event.top,'File is invalid')
  return
endif
(*pState).vanFile = file
widget_control,(*pState).vanText,set_value = file
return
end
;;;;;;;;;;;;;;;;;;;;;
pro hfbsrdSelBgFile,event
widget_control,event.top,get_uvalue = pState
files = dialog_pickfile(dialog_parent = event.top,/read, $
                               filter = ['*.hfbs'],$
                               title = 'Select background file(s)',$
                               path = (*pState).path,$
                               /multiple_files)
nfiles = n_elements(files)

if (1.0*total(file_test(files,/regular)) ne nfiles) then begin
  void = dialog_message(dialog_parent = event.top,'At least one of the selected files is invalid')
  return
endif
*(*pState).bgFilePtr = files
widget_control,(*pState).bgText,set_value = files
return
end
;;;;;;;;;;;;;;;;;;;;;
pro hfbsrdDetGroup,event
widget_control,event.top,get_uvalue = pState
yout = hfbsDetGroupWidget(group_leader = event.top,(*pState).selDetPtr)
*(*pState).selDetPtr = yout
return
end
;;;;;;;;;;;;;;;;;;;;;
pro hfbs_add,ePtr,dataPtr,errPtr
; This procedure adds HFBS data sets together correctly
; At this point, all of the data files must have the same
; size.
nfiles = n_elements(dataPtr)
if nfiles eq 1 then return	; here we will leave the pointers unchanged

datSize = size(*dataPtr[0])
ndet = datSize[2]
nchan = datSize[1]
datsum = fltarr(nchan,ndet)
ersum = fltarr(nchan,ndet)

for i = 0,nfiles-1 do begin
  data = *dataPtr[i]
  error = *errPtr[i]

; Use the method of least errors for combining data
  ersum = ersum + 1.0/error^2; *
  datsum = datsum+data/error^2
endfor
datsum = datsum/ersum
newError = fltarr(nchan,ndet)
newError = sqrt(1.0/ersum)

*errPtr[0] = newError
*dataPtr[0] = datsum

return
end
;;;;;;;;;;;;;;;;;;;;;
pro hfbsTreatSingle,event
widget_control,event.top,get_uvalue = pState,/no_copy
widget_control,(*pState).treatGroup,get_value = treatIndex
;widget_control,(*pState).outputGroup,get_value = thisGroup
;thisGroup = thisGroup[0]
;; thisGroup = 0 -> DAVE file output
;; thisGroup = 1 -> CON  file output
nlch = (nrch = 0)
; Read in the individual files
nfiles = n_elements(*(*pState).filePtr)
; Ok, all of the tests have been passed.  So let's start reading in the
; data files.
;
; First desensitize all widgets
widget_control,event.top,sensitive = 0
widget_control,(*pState).info,sensitive = 1
widget_control,(*pState).infoLabel,sensitive = 1
infoText = 'Reading in data file(s)'
widget_control,(*pState).info,set_value = infoText
; Now read in all of the data files
emin = fltarr(nfiles) & emax = fltarr(nfiles)
ePtr = ptrarr(nfiles,/allocate_heap)
dataPtr = ptrarr(nfiles,/allocate_heap)
errPtr = ptrarr(nfiles,/allocate_heap)
headerPtr = ptrarr(nfiles,/allocate_heap)
wbmrate = fltarr(nfiles)
wbmrateErr = fltarr(nfiles)
livetime = fltarr(nfiles)
crates = fltarr(nfiles,16)

for i = 0,nfiles-1 do begin
    file = (*(*pState).filePtr)[i]
    HFBS_ReadHFBS,file,0,energy,data,error,ndet,nchan,comments,$
                integ_int,$
                Norm2Mon = treatIndex[0],$
                norm2One = 0,$
                doppler = fdoppler,$
                ncycles = ncycles,$
                temperature = temperature,$
  				livetime = ltime,$
  				sumwbm = wbm,$
  				detRates = detR

  cRates[i,0:15] = detR[0:15]
  *headerPtr[i] = comments
  *ePtr[i] = energy
  *dataPtr[i] = transpose(data)
  *errPtr[i] = transpose(error)
  wbmrate[i] = wbm/ltime
  livetime[i] = ltime
  wbmrateErr[i] = sqrt(wbm)/ltime
  emin[i] = min(energy) & emax[i] = max(energy)
endfor

; If necessary, read in the background file(s)
nbg = 0
if (treatIndex[2] eq 1) and (n_elements(*(*pState).bgFilePtr) gt 0) then begin
  bgfiles = (*(*pState).bgFilePtr)
  nbg = n_elements(bgFiles)
  ; test if they are valid files
  if 1.0*total(file_test(bgfiles,/regular)) ne nbg then begin
    void = dialog_message(dialog_parent = event.top,'Invalid background file')
    widget_control,event.top,set_uvalue = pState,/no_copy
    return
  endif

  bgEPtr = ptrarr(nbg,/allocate_heap)
  bgPtr = ptrarr(nbg,/allocate_heap)
  bgErrPtr = ptrarr(nbg,/allocate_heap)

  for i = 0,nbg-1 do begin
    HFBS_ReadHFBS,bgfiles[i],0,bgenergy,bgdata,bgerror,ndet,nchan,comments,$
                integ_int,$
                Norm2Mon = treatIndex[0],$
                norm2One = 0,$
                doppler = fdoppler,$
                ncycles = ncycles,$
                temperature = temperature

    emin = [emin,min(bgenergy)]
    emax = [emax,max(bgenergy)]
    *bgEPtr[i] = bgenergy
    *bgPtr[i] = transpose(bgdata)
    *bgErrPtr[i] = transpose(bgerror)
  endfor
endif

infoText = ['Checking "sameness" of files',infoText]
widget_control,(*pState).info,set_value = infoText

; Check for "sameness" of all (signal and background) of the files (energy transfer only)
; Here we will consider energy transfer deviations less than or equal
; to 5% only as acceptable...i.e. the "same"
if (nfiles+nbg) gt 1 then begin
  emaxSdev = (moment(emax))[1]
  eminSdev = (moment(emin))[1]
  if (emaxSdev*100.0 gt 5.0) or (eminSdev*100.0 gt 5.0) then begin
    void = dialog_message(dialog_parent = event.top,$
           ['Energy transfers differ by more than 5%',$
            'Please select new files'])
    ptr_free,ePtr,dataPtr,errPtr
    if nbg gt 0 then begin
      ptr_free,bgEPtr,bgPtr,bgErrPtr
    endif
    ; Sensitize all widgets
	widget_control,event.top,sensitive = 1

    widget_control,event.top,set_uvalue = pState,/no_copy
    return
  endif
endif
infoText = ['Rebinning data to a common dynamic range',infoText]
widget_control,(*pState).info,set_value = infoText
; Ok, all of the data files appear to have a similar dynamic range so
; let's rebin all of the onto an equally-spaced grid
nchan = n_elements(*ePtr[0])
energy = hfbs_makepoints(xlo = max(emin),xhi = min(emax),npts = nchan)
de = energy[1] - energy[0]
ereb = [energy-0.5*de,energy[nchan-1]+0.5*de]
nlch = 0 & nrch = 0
for i = 0,nfiles-1 do begin
  e = *ePtr[i]
  datSize = size(*dataPtr[i])
  ndet = datSize[2]
  nen = datSize[1]
  data = (*dataPtr[i])[*,0:ndet-1]
  err = (*errPtr[i])[*,0:ndet-1]
  ;ndet = ndet-1
  ebnd = [e-0.5*de,e[nen-1]+0.5*de]	; input channel boundaries

  drebin_histo,ebnd,data,err,ereb,y_out,dy_out
  ;dave_rebin,ebnd,data,err,ereb,y_out,dy_out,/silent,nanch = nanch
  nlch = nlch > nanch[0] & nrch = nrch > nanch[1]
  ; There is a possibility that there are values that are NAN
  ; in y_out.  Check for these and eliminate them from the
  ; arrays.

  *ePtr[i] = energy
  *dataPtr[i] = y_out
  *errPtr[i] = dy_out
endfor
if nbg gt 0 then begin	; rebin background files if present
  for i = 0,nbg-1 do begin
    e = *bgEPtr[i]
    datSize = size(*bgPtr[i])
    ndet = datSize[2]
    nen = datSize[1]
    data = (*bgPtr[i])[*,0:ndet-1]
    err = (*bgErrPtr[i])[*,0:ndet-1]
    ;ndet = ndet-1
    ebnd = [e-0.5*de,e[nen-1]+0.5*de]	; input channel boundaries
    ;dave_rebin,ebnd,data,err,ereb,y_out,dy_out,/silent,nanch = nanch
    drebin_histo,ebnd,data,err,ereb,y_out,dy_out


    ;nlch = nlch > nanch[0] & nrch = nrch > nanch[1]
    ; There is a possibility that there are values that are NAN
    ; in y_out.  Check for these and eliminate them from the
    ; arrays.

    *bgEPtr[i] = energy
    *bgPtr[i] = y_out
    *bgErrPtr[i] = dy_out
  endfor
endif
infoText = ['Rebin complete',infoText]
widget_control,(*pState).info,set_value = infoText

; Sum the background files (if present)
if nbg gt 0 then begin
  infoText = ['Summing background files and subtracting from signal files',infoText]
  widget_control,(*pState).info,set_value = infoText
  hfbs_add,bgEPtr,bgPtr,bgErrPtr

  for i = 0,nfiles-1 do begin
    data = *dataPtr[i]
    error = *errPtr[i]
    bg = *bgPtr[0]
    bgerr = *bgErrPtr[0]
    dataSize = size(data)
    nchan = dataSize[1]
    ndet = dataSize[2]
    diff = fltarr(nchan,ndet) & differr = fltarr(nchan,ndet)
    diff[*,1:ndet-1] = data[*,1:ndet-1] - bg[*,1:ndet-1]
    differr[*,1:ndet-1] = sqrt((error[*,1:ndet-1])^2 + (bgerr[*,1:ndet-1])^2)
    ; For the time being we will put the monitor data from the signal data into
    ; the difference file
    diff[*,0] = data[*,0] & differr[*,0] = error[*,0]
    *dataPtr[i] = diff
    *errPtr[i] = differr
  endfor
endif

; Now extract only the useful parts of the data (i.e. not the NAN values)
for i = 0,nfiles-1 do begin
  energy = *ePtr[i]
  nchan = n_elements(energy)
  data = *dataPtr[i]
  error = *errPtr[i]
  *ePtr[i] = energy[nlch:nchan-1-nrch]
  *dataPtr[i] = data[nlch:nchan-1-nrch,*]
  *errPtr[i] = error[nlch:nchan-1-nrch,*]
endfor

infoText = ['Creating DAVE output',infoText]
widget_control,(*pState).info,set_value = infoText
files = *(*pState).filePtr
filename = files
fileOut = strarr(nfiles)
for i = 0,nfiles-1 do begin
  datSize = size(*dataPtr[i])
  ndet = datSize[2]
  extPos = strpos(files[i],'.hfbs')
  filename[i] = strmid(files[i],extPos-11,11)
  fileOut[i] = filepath(filename[i],root_dir = (*!dave_defaults).workDir)
  fileOut[i] = fileOut[i] + 'dyn.dave'
  hfbs_readheader,files[i],header,temperature,fdoppler,sumWBM,sumTBM
  scPos = strpos(header[1],':')
  user = strmid(header[1],scPos+1)
  nheader = n_elements(header)
  caldat,systime(/julian),month,day,year
  date = strcompress(string(month))+$
        '/'+strcompress(string(day))+$
        '/'+strcompress(string(year))
  instrument = 'HFBS'

    ; Should this data set be normalized to a vanadium file?
    if treatIndex[1] eq 1 then begin	; YES, normalize it!
  		infoText = ['Reading in vanadium file','Creating normalization vector',infoText]
  		widget_control,(*pState).info,set_value = infoText
  		HFBS_ReadHFBS,(*pState).vanfile,0,vanenergy,vandata,vanerror,vanndet,vannchan,vancomments,$
        	    vaninteg_int,norm2Mon = 1
  		normFactors = dblarr(vanndet-1)
  		for j = 0,vanndet-2 do begin
    	   normFactors[j] = int_tabulated(vanenergy,vandata[j+1,*],/sort)
  		endfor
  		vanave = (moment(normFactors))[0]
  		normFactors = normFactors/vanave
  		data = *dataPtr[i]
  		error = *errPtr[i]
  		nchan = n_elements(*ePtr[0])
  		u = 1+bytarr(nchan)
  		data[*,1:ndet-1] = data[*,1:ndet-1]/(u#normFactors)
  		error[*,1:ndet-1] = error[*,1:ndet-1]/(u#normFactors)
  		*dataPtr[i] = data
  		*errPtr[i] = error
	endif


  thisFilePath = (*!dave_defaults).datDir;(*(*pState).inPtr).datDir
  *(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr = $
				 {qty:(*dataPtr[i])[*,1:ndet-1],$
				  err:(*errPtr[i])[*,1:ndet-1],$
				  x:*ePtr[i],$
				  y:*(*pState).qPtr}

   				  specific = {nchan:nchan,$
              				  ndet:ndet,$
              				  monPtr:ptr_new((*dataPtr[i])[*,0]),$
              				  monErrPtr:ptr_new((*errPtr[i])[*,0]),$
              					ncycles:0,$
              					phiPtr:ptr_new((*pState).detAngles),$
              					qPtr:(*pState).qPtr,$
              					ePtr:ePtr[i],$
              					instrument:instrument,$
              					wavelength:6.271,$
              					camType:'triangular',$
              					daqmode:'inelastic',$
              					dopplerFrequency:fdoppler,$
              					date:date,$
              					user:user,$
              					veldist:0.0,$
              					temp_sample:temperature,$
              					temp_setpoint:temperature,$
              					temp_control:temperature,$
              					rawFileName:files[i],$
              					comments:header[0],$
              					header:*headerPtr[i],$
              					sumfc:total((*dataPtr[i])[*,0]),$
              					sumtbm:sumTBM,$
              					sumwbm:sumWBM,$
              					wbmRate:wbmRate[i],$
								wbmRateErr:wbmRateErr[i],$
								livetime:livetime[i],$
								cRates:reform(cRates[i,*])}

					*(*(*(*pState).inPtr).dataStrPtr).specificPtr = specific

  					hbar_omega = '!6!sh!r!e/!n !7x!6'
  					xlabel = 'E '
  					ylabel = 'Q '
  					xunits = 'energy:ueV'
  					yunits = 'wavevector:A-1'
  					histlabel = 'I (arbitrary units)'
  					histunits = ''


  					(*(*(*pState).inPtr).dataStrPtr).commonStr.instrument = instrument
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.xtype = 'POINTS'
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.ytype = 'POINTS'
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.xlabel = xlabel
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.ylabel = ylabel
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.histlabel = histlabel
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.xunits = xunits
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.yunits = yunits
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.histunits = histunits
  					treatment = ['file: '+files[i]]
  					treatment = [treatment,'converted from RAW to DAVE',$
  					             'converted to energy','normalized to P(v)']
  					wbmText = 'WBM rate='+strtrim(string(wbmRate[i]),2)+$
  					          '+/-'+strtrim(string(wbmRateErr[i]),2)+' cps'
					treatment = [treatment,wbmText]
  					if treatIndex[0] eq 1 then treatment = [treatment, $
  					   'monitor normalization']
					if (treatIndex[2] eq 1) and file_test((*pState).bgFile) then begin
					  outText = 'Background subtracted: '+(*pState).bgFile
					  treatment = [treatment,outText]
					endif
  					if treatIndex[1] eq 1 then treatment = [treatment,$
  					   'vanadium normalization: '+strtrim((*pState).vanfile,2)]

  					*(*(*(*pState).inPtr).dataStrPtr).commonStr.treatmentPtr = treatment

					; Are the detectors to be regrouped?
					if treatIndex[3] eq 1 then begin	; Yes, regroup them...
    			        infoText = ['Regrouping detectors',infoText]
    			        widget_control,(*pState).info,set_value = infoText
						yout = *(*pState).selDetPtr

						; Now cycle through the detectors and do the grouping
						qty = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).qty
						err = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).err
						x = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).x
						q = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).y
						qtsize = size(qty)
						nx = qtsize[1] & ny = qtsize[2]
						newqty = dblarr(nx,ny)
						ndet = ny
						newq = dblarr(ndet)
						newerr = dblarr(nx,ny)
						y1 = fltarr(nx) & v1 = fltarr(nx)
						ysum = fltarr(nx) & ersum = fltarr(nx)
						; current

						for k = 0,ndet-1 do begin
  							wherevalid = where(yout[k,*] eq 1,count)
  							if count gt 0 then begin
    							for j = 0,count-1 do begin
    							   	v1 = reform(err[*,wherevalid[j]]^2)
    							   	y1 = reform(qty[*,wherevalid[j]])
    							    ersum = ersum + 1.0/v1
									ysum = ysum + y1/v1
      								;newqty[*,k] = qty[*,wherevalid[j]] + newqty[*,k]
	  								;newerr[*,k] = err[*,wherevalid[j]]^2 + newerr[*,k]^2
      								newq[k] = newq[k] + q[wherevalid[j]]	; *
    							endfor
    							newqty[*,k] = ysum/ersum;datsum[*]	; *
    							newerr[*,k] = 1.0/sqrt(ersum);errsum[*]	; *
    							newq[k] = newq[k]/(1.0*count)
    							;newerr[*,k] = sqrt(newerr[*,k])
  							endif
						endfor

						keepGroup = intarr(ndet)
						for k = 0,ndet-1 do begin
  							if total(yout[k,*]) ne 0 then begin
    							keepGroup[k] = 1
  							endif
						endfor
						keepTheseGroups = where(keepGroup eq 1,count)
						; Now reform the elements of the structure, histPtr...
						newHist = {qty:newqty[*,keepTheseGroups],$
                					err:newerr[*,keepTheseGroups],$
                					x:x,$
                					y:newq[keepTheseGroups]}
						*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr = newHist
						text = 'Detectors have been regrouped'
						oldText = *(*(*(*pState).inPtr).dataStrPtr).commonStr.treatmentPtr
						text = [oldText,text]
						*(*(*(*pState).inPtr).dataStrPtr).commonStr.treatmentPtr = text
					endif


					; Now write the pointer out to a dave file
					state = *(*pState).inPtr
					dave_beast_ops,"dup",state,outState
					davePtr = ptr_new(outState,/no_copy)
					save, davePtr, FILENAME = fileOut[i]
					ptr_free,davePtr
				  endfor
thisText = strarr(nfiles+1)
thisText[0] = 'The following files were created: '
for i = 0,nfiles-1 do begin
  thisText[i+1] = strcompress(string(fileOut[i]))
endfor
void = dialog_message(dialog_parent = event.top,thisText,/information)
;;;;;
infoText = ['Data written out',infoText]
widget_control,(*pState).info,set_value = infoText
; Sensitize all widgets
widget_control,event.top,sensitive = 1
*(*pState).outFilePtr = fileOut
widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;;;;;;;;
pro hfbsTreatSum,event
widget_control,event.top,get_uvalue = pState,/no_copy
widget_control,(*pState).treatGroup,get_value = treatIndex
; Read in the individual files
nfiles = n_elements(*(*pState).filePtr)
; Ok, all of the tests have been passed.  So let's start reading in the
; data files.
;
; First desensitize all widgets
widget_control,event.top,sensitive = 0
widget_control,(*pState).info,sensitive = 1
widget_control,(*pState).infoLabel,sensitive = 1
infoText = 'Reading in data file(s)'
widget_control,(*pState).info,set_value = infoText
; Now read in all of the data files
emin = fltarr(nfiles) & emax = fltarr(nfiles)
ePtr = ptrarr(nfiles,/allocate_heap)
dataPtr = ptrarr(nfiles,/allocate_heap)
errPtr = ptrarr(nfiles,/allocate_heap)
headerPtr = ptrarr(nfiles,/allocate_heap)
wbmRate = fltarr(nfiles)
wbmRateErr = fltarr(nfiles)
livetime = fltarr(nfiles)
cRates = fltarr(nfiles,16)

for i = 0,nfiles-1 do begin
    file = (*(*pState).filePtr)[i]
    HFBS_ReadHFBS,file,0,energy,data,error,ndet,nchan,comments,$
                integ_int,$
                Norm2Mon = treatIndex[0],$
                norm2One = 0,$
                doppler = fdoppler,$
                ncycles = ncycles,$
                temperature = temperature,$
                livetime = ltime,$
                sumwbm = sumwbm,$
                detRates = detR
  cRates[i,*] = detR[*]
  *headerPtr[i] = comments
  *ePtr[i] = energy
  *dataPtr[i] = transpose(data)
  *errPtr[i] = transpose(error)
  livetime[i] = ltime
  emin[i] = min(energy) & emax[i] = max(energy)
  wbmRate[i] = sumwbm/ltime
  wbmRateErr[i] = sqrt(sumwbm)/ltime
endfor

aveRate = fltarr(16)
for j = 0,15 do begin
  aveRate[j] = (moment(cRates[*,j]))[0]
endfor

cRates = aveRate

livetime = total(livetime)
; Add the rates using the method of least-variance
weights = 1.0/(wbmRateErr^2)
num = total(wbmRate*weights)
wbm = num/total(weights)
wbmErr = 1.0/sqrt(total(weights))
wbmRate = wbm & wbmRateErr = wbmErr

; If necessary, read in the background file(s)
nbg = 0
if (treatIndex[2] eq 1) and (n_elements(*(*pState).bgFilePtr) gt 0) then begin
  bgfiles = (*(*pState).bgFilePtr)
  nbg = n_elements(bgFiles)
  ; test if they are valid files
  if 1.0*total(file_test(bgfiles,/regular)) ne nbg then begin
    void = dialog_message(dialog_parent = event.top,'Invalid background file')
    widget_control,event.top,set_uvalue = pState,/no_copy
    return
  endif

  bgEPtr = ptrarr(nbg,/allocate_heap)
  bgPtr = ptrarr(nbg,/allocate_heap)
  bgErrPtr = ptrarr(nbg,/allocate_heap)

  for i = 0,nbg-1 do begin
    HFBS_ReadHFBS,bgfiles[i],0,bgenergy,bgdata,bgerror,ndet,nchan,comments,$
                integ_int,$
                Norm2Mon = treatIndex[0],$
                norm2One = 0,$
                doppler = fdoppler,$
                ncycles = ncycles,$
                temperature = temperature
    emin = [emin,min(bgenergy)]
    emax = [emax,max(bgenergy)]
    *bgEPtr[i] = bgenergy
    *bgPtr[i] = transpose(bgdata)
    *bgErrPtr[i] = transpose(bgerror)
  endfor
endif

infoText = ['Checking "sameness" of files',infoText]
widget_control,(*pState).info,set_value = infoText

; Check for "sameness" of all (signal and background) of the files (energy transfer only)
; Here we will consider energy transfer deviations less than or equal
; to 5% only as acceptable...i.e. the "same"
if (nfiles+nbg) gt 1 then begin
  emaxSdev = (moment(emax))[1]
  eminSdev = (moment(emin))[1]
  if (emaxSdev*100.0 gt 5.0) or (eminSdev*100.0 gt 5.0) then begin
    void = dialog_message(dialog_parent = event.top,$
           ['Energy transfers differ by more than 5%',$
            'Please select new files'])
    ptr_free,ePtr,dataPtr,errPtr
    if nbg gt 0 then begin
      ptr_free,bgEPtr,bgPtr,bgErrPtr
    endif
	; Sensitize all widgets
	widget_control,event.top,sensitive = 1
    widget_control,event.top,set_uvalue = pState,/no_copy
    return
  endif
endif
infoText = ['Rebinning data to a common dynamic range',infoText]
widget_control,(*pState).info,set_value = infoText
; Ok, all of the data files appear to have a similar dynamic range so
; let's rebin all of the onto an equally-spaced grid
nchan = n_elements(*ePtr[0])
energy = hfbs_makepoints(xlo = max(emin),xhi = min(emax),npts = nchan)
de = energy[1] - energy[0]
ereb = [energy-0.5*de,energy[nchan-1]+0.5*de]
nlch = 0 & nrch = 0
for i = 0,nfiles-1 do begin
  e = *ePtr[i]
  datSize = size(*dataPtr[i])
  ndet = datSize[2]
  nen = datSize[1]
  data = (*dataPtr[i])[*,0:ndet-1]
  err = (*errPtr[i])[*,0:ndet-1]
;  ndet = ndet-1
  ebnd = [e-0.5*de,e[nen-1]+0.5*de]	; input channel boundaries
  dave_rebin,ebnd,data,err,ereb,y_out,dy_out,/silent,nanch = nanch
  nlch = nlch > nanch[0] & nrch = nrch > nanch[1]
  ; There is a possibility that there are values that are NAN
  ; in y_out.  Check for these and eliminate them from the
  ; arrays.

  *ePtr[i] = energy
  *dataPtr[i] = y_out
  *errPtr[i] = dy_out
endfor
if nbg gt 0 then begin	; rebin background files if present
  for i = 0,nbg-1 do begin
    e = *bgEPtr[i]
    datSize = size(*bgPtr[i])
    ndet = datSize[2]
    nen = datSize[1]
    data = (*bgPtr[i])[*,0:ndet-1]
    err = (*bgErrPtr[i])[*,0:ndet-1]
    ;ndet = ndet-1
    ebnd = [e-0.5*de,e[nen-1]+0.5*de]	; input channel boundaries
    dave_rebin,ebnd,data,err,ereb,y_out,dy_out,/silent,nanch = nanch
    nlch = nlch > nanch[0] & nrch = nrch > nanch[1]
    ; There is a possibility that there are values that are NAN
    ; in y_out.  Check for these and eliminate them from the
    ; arrays.

    *bgEPtr[i] = energy
    *bgPtr[i] = y_out
    *bgErrPtr[i] = dy_out
  endfor
endif
infoText = ['Rebin complete',infoText]
widget_control,(*pState).info,set_value = infoText

; Now sum the signal files
infoText = ['Summing signal files',infoText]
widget_control,(*pState).info,set_value = infoText
hfbs_add,ePtr,dataPtr,errPtr
; Sum the background files (if present)
if nbg gt 0 then begin
  hfbs_add,bgEPtr,bgPtr,bgErrPtr
  data = *dataPtr[0]
  error = *errPtr[0]
  bg = *bgPtr[0]
  bgerr = *bgErrPtr[0]
  dataSize = size(data)
  nchan = dataSize[1]
  ndet = dataSize[2]
  diff = fltarr(nchan,ndet) & differr = fltarr(nchan,ndet)
  diff[*,1:ndet-1] = data[*,1:ndet-1] - bg[*,1:ndet-1]
  differr[*,1:ndet-1] = sqrt((error[*,1:ndet-1])^2 + (bgerr[*,1:ndet-1])^2)
  ; For the time being we will put the monitor data from the signal data into
  ; the difference file
  diff[*,0] = data[*,0] & differr[*,0] = error[*,0]
  *dataPtr[0] = diff
  *errPtr[0] = differr
endif

; Now extract only the useful parts of the data (i.e. not the NAN values)
energy = *ePtr[0]
nchan = n_elements(energy)
data = *dataPtr[0]
error = *errPtr[0]
*ePtr[0] = energy[nlch:nchan-1-nrch]
*dataPtr[0] = data[nlch:nchan-1-nrch,*]
*errPtr[0] = error[nlch:nchan-1-nrch,*]

;;;;;
infoText = ['Creating DAVE output',infoText]
widget_control,(*pState).info,set_value = infoText
files = *(*pState).filePtr
filename = files
energy = *ePtr[0]
nchan = n_elements(energy)
sumWBM = 0.0 & sumTBM = 0.0
user = ""
doppler = 0.0
temp = 0.0
for i = 0,nfiles-1 do begin
  hfbs_readheader,files[i],header,temperature,fdoppler,totWBM,totTBM
  sumWBM = sumWBM + totWBM
  sumTBM = sumTBM + totTBM
  scPos = strpos(header[1],':')
  newuser = strmid(header[1],scPos+1)
  user = [user,newuser]
  doppler = [doppler,fdoppler]
  temp = [temp,temperature]
endfor
ntemp = n_elements(temp)
temp = temp[1:ntemp-1]
ndop = n_elements(doppler)
doppler = doppler[1:ndop-1]
nheader = n_elements(header)
caldat,systime(/julian),month,day,year
date = strcompress(string(month))+$
	'/'+strcompress(string(day))+$
	'/'+strcompress(string(year))
instrument = 'HFBS'

; Should this data set be normalized to a vanadium file?
if treatIndex[1] eq 1 then begin	; YES, normalize it!
  infoText = ['Reading in vanadium file','Creating normalization vector',infoText]
  widget_control,(*pState).info,set_value = infoText
  HFBS_ReadHFBS,(*pState).vanfile,0,vanenergy,vandata,vanerror,vanndet,vannchan,vancomments,$
            vaninteg_int,norm2Mon = 1
  vanSize = size(vandata)
  ndet = vanSize[1]
  normFactors = dblarr(ndet-1)
  for i = 0,ndet-2 do begin
       normFactors[i] = int_tabulated(vanenergy,vandata[i+1,*],/sort)
  endfor
  vanave = (moment(normFactors))[0]
  normFactors = normFactors/vanave
  data = *dataPtr[0]
  error = *errPtr[0]
  nchan = n_elements(*ePtr[0])
  u = 1+bytarr(nchan)
  data[*,1:ndet-1] = data[*,1:ndet-1]/(u#normFactors)
  error[*,1:ndet-1] = error[*,1:ndet-1]/(u#normFactors)
  *dataPtr[0] = data
  *errPtr[0] = error
endif

qty = (*dataPtr[0])[*,1:ndet-1]
err = (*errPtr[0])[*,1:ndet-1]

thisFilePath = (*!dave_defaults).datDir;(*(*pState).inPtr).datDir
*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr = $
				      {qty:qty,$
				       	err:err,$
				      	x:energy,$
				      	y:*(*pState).qPtr}

					specific = {nchan:nchan,$
              					ndet:ndet,$
              					monPtr:ptr_new((*dataPtr[0])[*,0]),$;qty[*,0]),$
              					monErrPtr:ptr_new((*errPtr[0])[*,0]),$;err[*,0]),$
              					ncycles:0,$
              					phiPtr:ptr_new((*pState).detAngles),$
              					qPtr:(*pState).qPtr,$
              					ePtr:ePtr[0],$
              					instrument:instrument,$
              					wavelength:6.271,$
              					camType:'triangular',$
              					daqmode:'inelastic',$
              					dopplerFrequency:fdoppler,$
              					date:date,$
              					user:user,$
              					veldist:0.0,$
              					temp_sample:temp,$
              					temp_setpoint:temp,$
              					temp_control:temp,$
              					rawFileName:files,$
              					comments:header[0],$
              					header:*headerPtr[0],$
              					sumfc:total((*dataPtr[0])[*,0]),$
              					sumtbm:sumTBM,$
              					sumwbm:sumWBM,$
              					wbmRate:wbmRate,$
              					wbmRateErr:wbmRateErr,$
              					livetime:livetime,$
              					cRates:cRates}
					*(*(*(*pState).inPtr).dataStrPtr).specificPtr = specific

  					hbar_omega = '!6!sh!r!e/!n !7x!6'
  					xlabel = 'E '
  					ylabel = 'Q '
  					xunits = 'energy:ueV'
  					yunits = 'wavevector:A-1'
  					histlabel = 'I (arbitrary units)'
  					histunits = ''


  					(*(*(*pState).inPtr).dataStrPtr).commonStr.instrument = instrument
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.xtype = 'POINTS'
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.ytype = 'POINTS'
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.xlabel = xlabel
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.ylabel = ylabel
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.histlabel = histlabel
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.xunits = xunits
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.yunits = yunits
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.histunits = histunits
  					treatment = ['The following files were summed together: ']
					for i = 0,nfiles-1 do begin
					  treatment = [treatment,files[i]]
					endfor
  					treatment = [treatment,'converted from RAW to DAVE',$
  					             'converted to energy',$
  					             'normalized to P(v)']
					wbmText = 'WBM rate='+strtrim(string(wbmRate),2)+$
					          '+/-'+strtrim(string(wbmRateErr),2)+' cps'
					treatment = [treatment,wbmText]
  					if treatIndex[0] eq 1 then treatment = [treatment,$
  					    'monitor normalization']
					if (treatIndex[2] eq 1) then begin
					  treatment = [treatment,'Background subtracted: ']
					  nbg = n_elements(*(*pState).bgFilePtr)
					  for k = 0,nbg-1 do begin
  					    treatment = [treatment,(*(*pState).bgFilePtr)[k]]
					  endfor
					endif
  					if treatIndex[1] eq 1 then treatment = [treatment,$
  					   'vanadium normalization: '+$
  					   strtrim((*pState).vanfile,2)]

  					*(*(*(*pState).inPtr).dataStrPtr).commonStr.treatmentPtr = treatment

					; Are the detectors to be regrouped?
					if treatIndex[3] eq 1 then begin	; Yes, regroup them...
    			        infoText = ['Regrouping detectors',infoText]
    			        widget_control,(*pState).info,set_value = infoText
						yout = *(*pState).selDetPtr

						; Now cycle through the detectors and do the grouping
						qty = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).qty
						err = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).err
						x = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).x
						q = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).y

						qtsize = size(qty)
						nx = qtsize[1] & ny = qtsize[2]
						newqty = dblarr(nx,ny)
						ndet = ny
						newq = dblarr(ndet)
						newerr = dblarr(nx,ny)
						for i = 0,ndet-1 do begin
  							wherevalid = where(yout[i,*] eq 1,count)
  							if count gt 0 then begin
    							for j = 0,count-1 do begin
      								newqty[*,i] = qty[*,wherevalid[j]] + newqty[*,i]
	  								newerr[*,i] = err[*,wherevalid[j]]^2 + newerr[*,i]^2
      								newq[i] = newq[i] + q[wherevalid[j]]
    							endfor
    							newq[i] = newq[i]/(1.0*count)
    							newerr[*,i] = sqrt(newerr[*,i])
  							endif
						endfor

						keepGroup = intarr(ndet)
						for i = 0,ndet-1 do begin
  							if total(yout[i,*]) ne 0 then begin
    							keepGroup[i] = 1
  							endif
						endfor
						keepTheseGroups = where(keepGroup eq 1,count)
						; Now reform the elements of the structure, histPtr...
						newHist = {qty:newqty[*,keepTheseGroups],$
                					err:newerr[*,keepTheseGroups],$
                					x:x,$
                					y:newq[keepTheseGroups]}
						*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr = newHist
						text = 'Detectors have been regrouped'
						oldText = *(*(*(*pState).inPtr).dataStrPtr).commonStr.treatmentPtr
						text = [oldText,text]
						*(*(*(*pState).inPtr).dataStrPtr).commonStr.treatmentPtr = text
					endif

					; Now write the pointer out to a dave file
					state = *(*pState).inPtr
					dave_beast_ops,"dup",state,outState
					davePtr = ptr_new(outState,/no_copy)
					if nfiles gt 1 then begin
					  fileOut = dialog_pickfile(dialog_parent = event.top,/write, $
                                 filter = ['*.dave'],$
                                 title = 'DAVE output filename',$
                                 path = (*!dave_defaults).workDir)
                    endif else begin
           		      files = *(*pState).filePtr
				      extPos = strpos(files[0],'.hfbs')
				      filename = strmid(files[0],extPos-11,11)
				      fileOut = filepath(filename,root_dir = (*!dave_defaults).workDir)
                    endelse
                    fileOut = fileOut+'dyn.dave'
					save, davePtr, FILENAME = fileOut
					*(*pState).outFilePtr = fileOut
					ptr_free,davePtr
;;;;;
infoText = ['Data written out',infoText]
widget_control,(*pState).info,set_value = infoText
; Sensitize all widgets
widget_control,event.top,sensitive = 1

widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;;;;;;;;
pro hfbsrdProceed,event
widget_control,event.top,get_uvalue = pState,/no_copy
; Before proceeding, we must check to see if all of the fields have been
; properly filled out
nfiles = n_elements(*(*pState).filePtr)
if nfiles lt 1 then begin
  widget_control,event.top,set_uvalue = pState,/no_copy
  void = dialog_message(dialog_parent = event.top,'No files selected')
  return
endif
widget_control,(*pState).treatGroup,get_value = treatIndex
if treatIndex[1] eq 1 then begin
  if (not file_test((*pState).vanFile)) or ((*pState).vanFile eq '') then begin
    treatIndex[1] = 0
    widget_control,(*pState).treatGroup,set_value = treatIndex
    widget_control,event.top,set_uvalue = pState,/no_copy
    void = dialog_message(dialog_parent = event.top,'No vanadium file selected')
    return
  endif
endif
if (treatIndex[2] eq 1) and (n_elements(*(*pState).bgFilePtr) eq 0) then begin
  treatIndex[2] = 0
  widget_control,(*pState).treatGroup,set_value = treatIndex
  widget_control,event.top,set_uvalue = pState,/no_copy
  void = dialog_message(dialog_parent = event.top,'No background file selected')
  return
endif

; Do we want to sum the data together or
; save the files individually?
widget_control,(*pState).runGroup,get_value = runIndex
if runIndex[0] eq 0 then treat = "INDIVIDUAL" else treat = "SUM"
case treat of
"SUM":	begin
		  widget_control,event.top,set_uvalue = pState,/no_copy
		  hfbsTreatSum,event
		  widget_control,event.top,get_uvalue = pState,/no_copy
		  (*pState).msg = 'PROCEED'
		  widget_control,event.top,set_uvalue = pState,/no_copy
		  return
;		  widget_control,event.top,/destroy
		end
else:	begin
		  widget_control,event.top,set_uvalue = pState,/no_copy
		  hfbsTreatSingle,event
		  widget_control,event.top,get_uvalue = pState,/no_copy
		  (*pState).msg = 'PROCEED'
		  widget_control,event.top,set_uvalue = pState,/no_copy
		  return
		end
endcase

; Ok, all of the tests have been passed.  So let's start reading in the
; data files.
;
; First desensitize all widgets
widget_control,event.top,sensitive = 0
widget_control,(*pState).info,sensitive = 1
widget_control,(*pState).infoLabel,sensitive = 1
infoText = 'Reading in data file(s)'
widget_control,(*pState).info,set_value = infoText
; Now read in all of the data files
emin = fltarr(nfiles) & emax = fltarr(nfiles)
ePtr = ptrarr(nfiles,/allocate_heap)
dataPtr = ptrarr(nfiles,/allocate_heap)
errPtr = ptrarr(nfiles,/allocate_heap)
for i = 0,nfiles-1 do begin
    file = (*(*pState).filePtr)[i]
    HFBS_ReadHFBS,file,0,energy,data,error,ndet,nchan,comments,$
                integ_int,$
                Norm2Mon = treatIndex[0],$
                norm2One = 0,$
                doppler = fdoppler,$
                ncycles = ncycles,$
                temperature = temperature;,$
  *ePtr[i] = energy
  *dataPtr[i] = transpose(data)
  *errPtr[i] = transpose(error)
  emin[i] = min(energy) & emax[i] = max(energy)
endfor
infoText = ['Checking "sameness" of files',infoText]
widget_control,(*pState).info,set_value = infoText
; Sensitize all widgets
widget_control,event.top,sensitive = 1

; Check for "sameness" of all of the files (energy transfer only)
; Here we will consider energy transfer deviations less than or equal
; to 5% only as acceptable...i.e. the "same"
if nfiles gt 1 then begin
  emaxSdev = (moment(emax))[1]
  eminSdev = (moment(emin))[1]
  if (emaxSdev*100.0 gt 5.0) or (eminSdev*100.0 gt 5.0) then begin
    void = dialog_message(dialog_parent = event.top,$
           ['Energy transfers differ by more than 5%',$
            'Please select new files'])
    ptr_free,ePtr,dataPtr,errPtr
    widget_control,event.top,set_uvalue = pState,/no_copy
    return
  endif
endif
infoText = ['Rebinning data to a common dynamic range',infoText]
widget_control,(*pState).info,set_value = infoText
; Ok, all of the data files appear to have a similar dynamic range so
; let's rebin all of the onto an equally-spaced grid
nchan = n_elements(*ePtr[0])
energy = hfbs_makepoints(xlo = max(emin),xhi = min(emax),npts = nchan)
de = energy[1] - energy[0]
ereb = [energy-0.5*de,energy[nchan-1]+0.5*de]
nlch = 0 & nrch = 0
for i = 0,nfiles-1 do begin
  e = *ePtr[i]
  datSize = size(*dataPtr[i])
  ndet = datSize[2]
  nen = datSize[1]
  data = (*dataPtr[i])[*,0:ndet-1]
  err = (*errPtr[i])[*,0:ndet-1]
  ndet = ndet-1
  ebnd = [e-0.5*de,e[nen-1]+0.5*de]	; input channel boundaries
  dave_rebin,ebnd,data,err,ereb,y_out,dy_out,/silent,nanch = nanch
  nlch = nlch > nanch[0] & nrch = nrch > nanch[1]
  ; There is a possibility that there are values that are NAN
  ; in y_out.  Check for these and eliminate them from the
  ; arrays.

  *ePtr[i] = energy
  *dataPtr[i] = y_out
  *errPtr[i] = dy_out
endfor
infoText = ['Rebin complete',infoText]
widget_control,(*pState).info,set_value = infoText
; Are we subtracting a background run?
if treatIndex[2] eq 1 then begin		; YES, so read in the file
  if not file_test((*pState).bgFile) then begin	; Is there a background file present?
    void = dialog_message(dialog_parent = event.top,$
           'You must select a background file first')
    widget_control,event.top,set_uvalue = pState,/no_copy
    return
  endif
  infoText = ['Reading in background file',infoText]
  widget_control,(*pState).info,set_value = infoText
  HFBS_ReadHFBS,(*pState).bgFile,0,bgEnergy,bgData,bgError,bgndet,bgnchan,bgcomments,$
                integ_int,$
                Norm2Mon = treatIndex[0],$
                norm2One = 0,$
                doppler = bgdoppler,$
                ncycles = bgcycles,$
                temperature = bgtemperature
  ; Transpose the data and error arrays
  bgData = transpose(bgData)
  bgError = transpose(bgError)
  ; Test the dynamic range for "sameness"
    emax = [emax,max(bgEnergy)] & emin = [emin,min(bgEnergy)]

    emaxSdev = (moment(emax))[1]
    eminSdev = (moment(emin))[1]
    if (emaxSdev*100.0 gt 5.0) or (eminSdev*100.0 gt 5.0) then begin
      void = dialog_message(dialog_parent = event.top,$
             ['Energy transfers differ by more than 5%',$
              'Please select new files'])
      ptr_free,ePtr,dataPtr,errPtr
      widget_control,event.top,set_uvalue = pState,/no_copy
      return
    endif
  ; Ok, the background file and the signal file have a similar dynamic range
  ; Rebin the background data onto the same grid as the signal files
  nbge = n_elements(bgEnergy)
  ebgbnd = [bgEnergy-0.5*de,bgEnergy[nbge-1]+0.5*de]	; input channel boundaries
  dave_rebin,ebgbnd,bgData,bgError,ereb,y_out,dy_out,/silent,nanch = nanch
  nlch = nlch > nanch[0] & nrch = nrch > nanch[1]
  bgDataPtr = ptr_new(y_out[nlch:nchan-1-nrch,*])
  bgErrorPtr = ptr_new(dy_out[nlch:nchan-1-nrch,*])
endif


for i = 0,nfiles-1 do begin
  energy = (*ePtr[i])[nlch:nchan-1-nrch]
  data = (*dataPtr[i])[nlch:nchan-1-nrch,*]
  error = (*errPtr[i])[nlch:nchan-1-nrch,*]
  *ePtr[i] = energy
  *dataPtr[i] = data
  *errPtr[i] = error
  ; Shall we perform the background subtraction here?
  if (treatIndex[2] eq 1) and (file_test((*pState).bgFile) eq 1) then begin
    infoText = ['Subtracting background from data files',infoText]
    widget_control,(*pState).info,set_value = infoText
    *dataPtr[i] = data - *bgDataPtr
    *errPtr[i] = sqrt(error^2+(*bgErrorPtr)^2)
  endif
endfor

; The rebinning is finished.  Are we going to perform a normalization
; to a vanadium run?
if treatIndex[1] eq 1 then begin	; YES, normalize it!
    infoText = ['Reading in vanadium file','Creating normalization vector',infoText]
    widget_control,(*pState).info,set_value = infoText
    HFBS_ReadHFBS,(*pState).vanfile,0,vanenergy,vandata,vanerror,vanndet,vannchan,$
            vancomments,vaninteg_int,norm2Mon = 1
    vanSize = size(vanData)
    vandet = vanSize[1]
    normFactors = dblarr(vandet-1)
    for i = 0,vandet-2 do begin
       normFactors[i] = int_tabulated(vanenergy,vandata[i+1,*],/sort)
    endfor
   	vanave = (moment(normFactors))[0]
    normFactors = normFactors/vanave
endif

case treat of
"INDIVIDUAL":	begin
				  ; Sift out the individual filenames
				  ; Note that the following code which parses the
				  ; names of the files assumes explicitly that the
				  ; HFBS filename ends with ".HFBS" and is 11 characters
				  ; long (after the .HFBS has been stripped off).
    			  infoText = ['Creating DAVE output',infoText]
    			  widget_control,(*pState).info,set_value = infoText
				  files = *(*pState).filePtr
				  filename = files
				  fileOut = strarr(nfiles)
				  for i = 0,nfiles-1 do begin
				    extPos = strpos(files[i],'.hfbs')
				    filename[i] = strmid(files[i],extPos-11,11)
					fileOut[i] = filepath(filename[i],root_dir = (*!dave_defaults).workDir)
					fileOut[i] = fileOut[i] + '.dave'
				    hfbs_readheader,files[i],header,temperature,fdoppler,sumWBM,sumTBM
				    scPos = strpos(header[1],':')
				    user = strmid(header[1],scPos+1)
				    nheader = n_elements(header)
				    caldat,systime(/julian),month,day,year
				    date = strcompress(string(month))+$
				           '/'+strcompress(string(day))+$
				           '/'+strcompress(string(year))
				    instrument = 'HFBS'

					; Should this data set be normalized to a vanadium file?
					if treatIndex[1] eq 1 then begin	; yes...normalize it...
					  data = *dataPtr[i]
					  error = *errPtr[i]
					  nchan = n_elements(*ePtr[i])
					  u = 1+bytarr(nchan)
					  data[*,1:ndet] = data[*,1:ndet]/(u#normFactors)
					  error[*,1:ndet] = error[*,1:ndet]/(u#normFactors)
    				  *dataPtr[i] = data
    				  *errPtr[i] = error
  					endif


				    thisFilePath = (*!dave_defaults).datDir;(*(*pState).inPtr).datDir
				    *(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr = $
				      		{qty:(*dataPtr[i])[*,1:ndet],$
				       		 err:(*errPtr[i])[*,1:ndet],$
				      		 x:*ePtr[i],$
				      		 y:*(*pState).qPtr}

   					specific = {nchan:nchan,$
              					ndet:ndet,$
              					monPtr:ptr_new((*dataPtr[i])[*,0]),$
              					monErrPtr:ptr_new((*errPtr[i])[*,0]),$
              					ncycles:0,$
              					phiPtr:ptr_new(detAngles),$
              					qPtr:(*pState).qPtr,$
              					ePtr:ePtr[i],$
              					instrument:instrument,$
              					wavelength:6.271,$
              					camType:'triangular',$
              					daqmode:'inelastic',$
              					dopplerFrequency:fdoppler,$
              					date:date,$
              					user:user,$
              					veldist:0.0,$
              					temp_sample:temperature,$
              					temp_setpoint:temperature,$
              					temp_control:temperature,$
              					rawFileName:files[i],$
              					comments:header[0],$
              					sumfc:total((*dataPtr[i])[*,0]),$
              					sumtbm:sumTBM,$
              					sumwbm:sumWBM}
					*(*(*(*pState).inPtr).dataStrPtr).specificPtr = specific

  					hbar_omega = '!6!sh!r!e/!n !7x!6'
  					xlabel = 'E '
  					ylabel = 'Q '
  					xunits = 'energy:ueV'
  					yunits = 'wavevector:A-1'
  					histlabel = 'I (arbitrary units)'
  					histunits = ''


  					(*(*(*pState).inPtr).dataStrPtr).commonStr.instrument = instrument
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.xtype = 'POINTS'
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.ytype = 'POINTS'
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.xlabel = xlabel
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.ylabel = ylabel
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.histlabel = histlabel
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.xunits = xunits
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.yunits = yunits
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.histunits = histunits
  					treatment = ['file: '+file]
  					treatment = [treatment,'converted from RAW to DAVE',$
  					             'converted to energy','normalized to P(v)']

  					if treatIndex[0] eq 1 then treatment = [treatment, $
  					   'monitor normalization']
					if (treatIndex[2] eq 1) and file_test((*pState).bgFile) then begin
					  outText = 'Background subtracted: '+(*pState).bgFile
					  treatment = [treatment,outText]
					endif
  					if treatIndex[1] eq 1 then treatment = [treatment,$
  					   'vanadium normalization: '+strtrim((*pState).vanfile,2)]

  					*(*(*(*pState).inPtr).dataStrPtr).commonStr.treatmentPtr = treatment

					; Are the detectors to be regrouped?
					if treatIndex[3] eq 1 then begin	; Yes, regroup them...
    			        infoText = ['Regrouping detectors',infoText]
    			        widget_control,(*pState).info,set_value = infoText
						yout = *(*pState).selDetPtr

						; Now cycle through the detectors and do the grouping
						qty = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).qty
						err = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).err
						x = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).x
						q = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).y
						qtsize = size(qty)
						nx = qtsize[1] & ny = qtsize[2]
						newqty = dblarr(nx,ny)
						ndet = ny
						newq = dblarr(ndet)
						newerr = dblarr(nx,ny)

						; current
						for k = 0,ndet-1 do begin
  							wherevalid = where(yout[k,*] eq 1,count)
  							if count gt 0 then begin
    							for j = 0,count-1 do begin
    							   	v1 = reform(err[*,wherevalid[j]]^2)
    							   	y1 = reform(qty[*,wherevalid[j]])
    							    ersum = ersum + 1.0/v1
									ysum = ysum + y1/v1
      								newq[k] = newq[k] + q[wherevalid[j]]	; *
    							endfor
    							newqty[*,k] = ysum/ersum
    							newerr[*,k] = 1.0/sqrt(ersum)
    							newq[k] = newq[k]/(1.0*count)
  							endif
						endfor

						keepGroup = intarr(ndet)
						for k = 0,ndet-1 do begin
  							if total(yout[k,*]) ne 0 then begin
    							keepGroup[k] = 1
  							endif
						endfor
						keepTheseGroups = where(keepGroup eq 1,count)
						; Now reform the elements of the structure, histPtr...
						newHist = {qty:newqty[*,keepTheseGroups],$
                					err:newerr[*,keepTheseGroups],$
                					x:x,$
                					y:newq[keepTheseGroups]}
						*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr = newHist
						text = 'Detectors have been regrouped'
						oldText = *(*(*(*pState).inPtr).dataStrPtr).commonStr.treatmentPtr
						text = [oldText,text]
						*(*(*(*pState).inPtr).dataStrPtr).commonStr.treatmentPtr = text
					endif


					; Now write the pointer out to a dave file
					state = *(*pState).inPtr
					dave_beast_ops,"dup",state,outState
					davePtr = ptr_new(outState,/no_copy)
					save, davePtr, FILENAME = fileOut[i]
					ptr_free,davePtr
				  endfor
				end
"SUM":			begin
				  ; Sift out the individual filenames
				  ; Note that the following code which parses the
				  ; names of the files assumes explicitly that the
				  ; HFBS filename ends with ".HFBS" and is 11 characters
				  ; long (after the .HFBS has been stripped off).
    			  infoText = ['Creating DAVE output',infoText]
    			  widget_control,(*pState).info,set_value = infoText
				  files = *(*pState).filePtr
				  filename = files
				  energy = *ePtr[0]
				  nchan = n_elements(energy)
				  sum = fltarr(nchan,ndet+1)
				  ersum = fltarr(nchan,ndet+1)
				  sumWBM = 0.0 & sumTBM = 0.0
				  user = ""
				  doppler = 0.0
				  temp = 0.0
				  for i = 0,nfiles-1 do begin
				    ;print,'Number of energy transfers: ',n_elements(*ePtr[i])
				    sum = sum + (*dataPtr[i])
				    ersum = ersum + ((*errPtr[i]))^2
					hfbs_readheader,files[i],header,temperature,fdoppler,totWBM,totTBM
					sumWBM = sumWBM + totWBM
					sumTBM = sumTBM + totTBM
				    scPos = strpos(header[1],':')
				    newuser = strmid(header[1],scPos+1)
				    user = [user,newuser]
				    doppler = [doppler,fdoppler]
				    temp = [temp,temperature]
				  endfor
				  ntemp = n_elements(temp)
				  temp = temp[1:ntemp-1]
				  ndop = n_elements(doppler)
				  doppler = doppler[1:ndop-1]
				  ptr_free,ePtr
				  ptr_free,dataPtr
				  ptr_free,errPtr
				  ePtr = ptr_new(energy)
				  dataPtr = ptr_new(sum)
				  errPtr = ptr_new(sqrt(ersum))
				  nheader = n_elements(header)
				  caldat,systime(/julian),month,day,year
				  date = strcompress(string(month))+$
				           '/'+strcompress(string(day))+$
				           '/'+strcompress(string(year))
				  instrument = 'HFBS'

					; Should this data set be normalized to a vanadium file?
					if treatIndex[1] eq 1 then begin	; yes...normalize it...
					  data = *dataPtr
					  error = *errPtr
					  nchan = n_elements(*ePtr)
					  u = 1+bytarr(nchan)
					  data[*,1:ndet] = data[*,1:ndet]/(u#normFactors)
					  error[*,1:ndet] = error[*,1:ndet]/(u#normFactors)
    				  *dataPtr = data
    				  *errPtr = error
  					endif


				    thisFilePath = (*!dave_defaults).datDir;(*(*pState).inPtr).datDir
				    *(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr = $
				      		{qty:(*dataPtr)[*,1:ndet],$
				       		 err:(*errPtr)[*,1:ndet],$
				      		 x:energy,$
				      		 y:*(*pState).qPtr}

   					specific = {nchan:nchan,$
              					ndet:ndet,$
              					monPtr:ptr_new((*dataPtr)[*,0]),$
              					monErrPtr:ptr_new((*errPtr)[*,0]),$
              					ncycles:0,$
              					phiPtr:ptr_new(detAngles),$
              					qPtr:(*pState).qPtr,$
              					ePtr:ePtr,$
              					instrument:instrument,$
              					wavelength:6.271,$
              					camType:'triangular',$
              					daqmode:'inelastic',$
              					dopplerFrequency:fdoppler,$
              					date:date,$
              					user:user,$
              					veldist:0.0,$
              					temp_sample:temp,$
              					temp_setpoint:temp,$
              					temp_control:temp,$
              					rawFileName:files,$
              					comments:header[0],$
              					sumfc:total((*dataPtr)[*,0]),$
              					sumtbm:sumTBM,$
              					sumwbm:sumWBM}
					*(*(*(*pState).inPtr).dataStrPtr).specificPtr = specific

  					hbar_omega = '!6!sh!r!e/!n !7x!6'
  					xlabel = 'E '
  					ylabel = 'Q '
  					xunits = 'energy:ueV'
  					yunits = 'wavevector:A-1'
  					histlabel = 'I (arbitrary units)'
  					histunits = ''


  					(*(*(*pState).inPtr).dataStrPtr).commonStr.instrument = instrument
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.xtype = 'POINTS'
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.ytype = 'POINTS'
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.xlabel = xlabel
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.ylabel = ylabel
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.histlabel = histlabel
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.xunits = xunits
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.yunits = yunits
  					(*(*(*pState).inPtr).dataStrPtr).commonStr.histunits = histunits
  					treatment = ['The following files were summed together: ']
					for i = 0,nfiles-1 do begin
					  treatment = [treatment,files[i]]
					endfor
  					treatment = [treatment,'converted from RAW to DAVE',$
  					             'converted to energy','normalized to P(v)']

  					if treatIndex[0] eq 1 then treatment = [treatment, $
  					   'monitor normalization']
					if (treatIndex[2] eq 1) and file_test((*pState).bgFile) then begin
					  outText = 'Background subtracted: '+(*pState).bgFile
					  treatment = [treatment,outText]
					endif
  					if treatIndex[1] eq 1 then treatment = [treatment,$
  					   'vanadium normalization: '+strtrim((*pState).vanfile,2)]

  					*(*(*(*pState).inPtr).dataStrPtr).commonStr.treatmentPtr = treatment

					; Are the detectors to be regrouped?
					if treatIndex[3] eq 1 then begin	; Yes, regroup them...
    			        infoText = ['Regrouping detectors',infoText]
    			        widget_control,(*pState).info,set_value = infoText
						yout = *(*pState).selDetPtr

						; Now cycle through the detectors and do the grouping
						qty = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).qty
						err = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).err
						x = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).x
						q = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).y

						qtsize = size(qty)
						nx = qtsize[1] & ny = qtsize[2]
						newqty = dblarr(nx,ny)
						ndet = ny
						newq = dblarr(ndet)
						newerr = dblarr(nx,ny)
						for i = 0,ndet-1 do begin
  							wherevalid = where(yout[i,*] eq 1,count)
  							if count gt 0 then begin
    							for j = 0,count-1 do begin
      								newqty[*,i] = qty[*,wherevalid[j]] + newqty[*,i]
	  								newerr[*,i] = err[*,wherevalid[j]]^2 + newerr[*,i]^2
      								newq[i] = newq[i] + q[wherevalid[j]]
    							endfor
    							newq[i] = newq[i]/(1.0*count)
    							newerr[*,i] = sqrt(newerr[*,i])
  							endif
						endfor

						keepGroup = intarr(ndet)
						for i = 0,ndet-1 do begin
  							if total(yout[i,*]) ne 0 then begin
    							keepGroup[i] = 1
  							endif
						endfor
						keepTheseGroups = where(keepGroup eq 1,count)
						; Now reform the elements of the structure, histPtr...
						newHist = {qty:newqty[*,keepTheseGroups],$
                					err:newerr[*,keepTheseGroups],$
                					x:x,$
                					y:newq[keepTheseGroups]}
						*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr = newHist
						text = 'Detectors have been regrouped'
						oldText = *(*(*(*pState).inPtr).dataStrPtr).commonStr.treatmentPtr
						text = [oldText,text]
						*(*(*(*pState).inPtr).dataStrPtr).commonStr.treatmentPtr = text
					endif

					; Now write the pointer out to a dave file
					state = *(*pState).inPtr
					dave_beast_ops,"dup",state,outState
					davePtr = ptr_new(outState,/no_copy)
					fileOut = dialog_pickfile(dialog_parent = event.top,/write, $
                               filter = ['*.dave'],$
                               title = 'DAVE output filename',$
                               path = (*!dave_defaults).workDir)
                    fileOut = fileOut+'.dave'
					save, davePtr, FILENAME = fileOut
					ptr_free,davePtr
				end
else:
endcase

(*pState).msg = 'PROCEED'
widget_control,event.top,set_uvalue = pState,/no_copy
widget_control,event.top,/destroy
return
end
;;;;;;;;;;;;;;;;;;;;;
pro hfbsrdSaveSettings,event
widget_control,event.top,get_uvalue = pState,/no_copy
file = dialog_pickfile(dialog_parent = event.top,/write, $
                               filter = ['*.rds'],$
                               title = 'Name of settings file',$
                               path = (*pState).path)
if file eq "" then begin
  widget_control,event.top,set_uvalue = pState,/no_copy
  return
endif
file = file+'.rds'

files = *(*pState).filePtr
widget_control,(*pState).treatGroup,get_value = treatIndex
widget_control,(*pState).runGroup,get_value = runIndex
vanFile = (*pState).vanFile
bgFile = (*pState).bgFile

save, files,treatIndex,runIndex,vanFile,bgFile, filename = file

widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;;;;;;;;
pro hfbsrdRestoreSettings,event
widget_control,event.top,get_uvalue = pState,/no_copy
file = dialog_pickfile(dialog_parent = event.top,/read, $
                               filter = ['*.rds'],$
                               title = 'Name of settings file',$
                               path = (*pState).path)
if file eq "" then begin
  widget_control,event.top,set_uvalue = pState,/no_copy
  return
endif
restore,file

*(*pState).filePtr = files
widget_control,(*pState).treatGroup,set_value = treatIndex
widget_control,(*pState).runGroup,set_value = runIndex
(*pState).vanFile = vanFile
(*pState).bgFile = bgFile
widget_control,(*pState).vanButton,sensitive = treatIndex[1]
widget_control,(*pState).bgButton,sensitive = treatIndex[2]
widget_control,(*pState).detGrp,sensitive = treatIndex[3]
widget_control,(*pState).fileText,set_value = files
widget_control,(*pState).vanText,set_value = vanFile
widget_control,(*pState).bgText,set_value = bgFile
widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;;;;;;;;
pro hfbs_redDynWriteCon,event
widget_control,event.top,get_uvalue = pState

return
end
;;;;;;;;;;;;;;;;;;;;;
pro hfbs_redDyn_event,event
widget_control,event.top,get_uvalue = pState,/no_copy
case event.id of
(*pState).treatGroup:	begin
						  widget_control,(*pState).treatGroup,get_value = index
						  ;index[0] = 1
						  ;widget_control,(*pState).treatGroup,set_value = index
						  widget_control,(*pState).vanButton,sensitive = index[1]
						  widget_control,(*pState).bgButton,sensitive = index[2]
						  widget_control,(*pState).detGrp,sensitive = index[3]
						end
else:
endcase
widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;;;;;;;;
function hfbs_redDyn,group_leader = group_leader
; Widget definition module
widget_control,group_leader,get_uvalue = statePtr	; get the pointer information from group leader
inPtr = (*statePtr).davePtr

butSize = 150
tlb = widget_base(/col,/modal,group_leader = group_leader,$
      title = 'Dynamic Run Data Reduction')
topBase = widget_base(tlb,/row)

colBase1 = widget_base(topBase,/col);;;;;;;;;;;;;;;;
runTypes = ['Single sample runs','Sum all runs']
runGroup = cw_bgroup(colBase1,runTypes,/col,/exclusive,$
           /no_release,set_value = 0,/return_index)
treatTypes = ['Monitor normalization (always on)','Vanadium normalization',$
              'Background subtraction','Detector grouping']
treatGroup = cw_bgroup(colBase1,treatTypes,/col,/nonexclusive,$
           set_value = [1,0,0,0],/return_index)
infoLabel = widget_label(colBase1,value = 'Information')
info = widget_text(colBase1,xsize = 30,ysize = 3,/scroll,/editable,sensitive = 1)

colBase2 = widget_base(topBase,/col);;;;;;;;;;;;;;;;
void = widget_button(colBase2,xsize = butSize,value = 'Select raw data file(s)',$
       event_pro = 'hfbsrdSelFiles')
void = widget_label(colBase2,value = '')	; place holder for nice layout
void = widget_label(colBase2,value = '')	; place holder for nice layout
void = widget_label(colBase2,value = '')	; place holder for nice layout
void = widget_label(colBase2,value = '')	; place holder for nice layout

vanButton = widget_button(colBase2,xsize = butSize,$
       value = 'Select vanadium file',sensitive = 0,$
       event_pro = 'hfbsrdSelVanFile')
bgButton = widget_button(colBase2,xsize = butSize,$
       value = 'Select background file(s)',sensitive = 0,$
       event_pro = 'hfbsrdSelBgFile')
detGrp = widget_button(colBase2,xsize = butSize,$
       value = 'Specify detector grouping',$
       event_pro = 'hfbsrdDetGroup',sensitive = 0)

;outputTypes = ['DAVE file','CON file']
;outputGroup = cw_bgroup(colBase2,outputTypes,/col,/exclusive,frame = 1,$
;           set_value = 0,/return_index,label_top = 'Output filetype')

colBase3 = widget_base(topBase,/col);;;;;;;;;;;;;;;;
void = widget_label(colBase3,value = 'Signal file(s)')
fileText = widget_text(colBase3,ysize = 5,xsize = 30,/scroll,/editable)
void = widget_label(colBase3,value = 'Vanadium file')
vanText = widget_text(colBase3,xsize = 30,/scroll,/editable)
void = widget_label(colBase3,value = 'Background file(s)')
bgText = widget_text(colBase3,xsize = 30,ysize = 2,/scroll,/editable)

butBase = widget_base(tlb,/row)
butBase1 = widget_base(butBase,/col)
void = widget_button(butBase1,xsize = butSize,value = 'Restore settings',$
       event_pro = 'hfbsrdRestoreSettings')
void = widget_button(butBase1,xsize = butSize,value = 'Save settings',$
       event_pro = 'hfbsrdSaveSettings')
butBase2 = widget_base(butBase,/col)
void = widget_button(butBase2,xsize = butSize,value = 'Accept',$
       event_pro = 'hfbsrdProceed')
void = widget_button(butBase2,xsize = butSize,value = 'Cancel',$
       event_pro = 'hfbs_redDynCancel')
butBase3 = widget_base(butBase,/col)
void = widget_button(butBase3,xsize = butSize,value = 'View new DAVE files',$
       event_pro = 'hfbs_redDynQuit')

centertlb,tlb
widget_control,tlb,/realize

; Calculate the q-values for future use here
detAngles = [14.46,20.98,27.08,32.31,36.0,43.75,51.5,59.25,67.0,$
             74.75,82.5,90.25,98.0,105.75,113.5,121.5]
lamo = 6.27
q = (4.0*!pi/lamo)*sin(0.5*!dtor*detAngles)
qPtr = ptr_new(q)

path = (*!dave_defaults).datDir;(*inPtr).datDir
thisArray = 0*intarr(16,16)
for i = 0,15 do begin
 thisArray[i,i] = 1
endfor
selDetPtr = ptr_new(thisArray,/no_copy)
msg = 'CANCEL'
state = {filePtr:ptr_new(/allocate_heap),$
         selDetPtr:selDetPtr,$
         treatGroup:treatGroup,$
;         outputGroup:outputGroup,$
         runGroup:runGroup,$
         path:path,$
         vanFile:'',$
         bgFile:'',$
         detGrp:detGrp,$
         bgButton:bgButton,$
         vanButton:vanButton,$
         fileText:fileText,$
         vanText:vanText,$
         bgText:bgText,$
         msg:msg,$
         inPtr:inPtr,$
         qPtr:qPtr,$
         detAngles:detAngles,$
         info:info,$
         infoLabel:infoLabel,$
         bgFilePtr:ptr_new(/allocate_heap),$
         monPtr:ptr_new(/allocate_heap),$
         monErrPtr:ptr_new(/allocate_heap),$
         outFilePtr:ptr_new(/allocate_heap)}

pState = ptr_new(state,/no_copy)
widget_control,tlb,set_uvalue = pState
xmanager,'hfbs_redDyn',tlb
return,pState
end