; $Id: dtas_data__define.pro,v 1.54.2.1 2008/06/30 18:08:17 azuah Exp $
;###############################################################################
;
; NAME:
;  DTAS_DATA__DEFINE
;
; PURPOSE:
;  Class for TAS data.
;
; CATEGORY:
;  DAVE, TAS, 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.
;
;###############################################################################
; +
; Uses: MPCURVEFIT, GET_PEAK_POS
; Modification history:
;  RMD - began mods to allow reading in ICE data.
; -
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro dtas_gaussians,x,p,yfit,_Extra = extra
np = n_elements(p)
ng = (np-1)/3
yfit = p[0]
for i = 0,ng-1 do begin
   area = p[3*i+1] & center = p[3*i+2] & fwhm = p[3*i+3]
   sig = fwhm/2.354
;   yfit = yfit + (area/sqrt(2.0*!dpi*sig^2))*exp(-0.5*((x-center)/sig)^2)
   yfit = yfit + area*exp(-0.5*((x-center)/sig)^2) ; RTA-use height instead of area-req by J Lynn
endfor
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro dtas_lorentzians,x,p,yfit,_Extra = extra
np = n_elements(p)
ng = (np-1)/3
yfit = p[0]
for i = 0,ng-1 do begin
   area = p[3*i+1] & center = p[3*i+2] & fwhm = p[3*i+3]
   gam = 0.5*fwhm
;   yfit = yfit + (area*gam/!dpi)/((x-center)^2+gam^2)
   yfit = yfit + (area*!dpi*gam)*(gam/!dpi)/((x-center)^2+gam^2) ; RTA - use height instead of area - req by J Lynn
                                ;area of lor = 2/(pi*fwhm) = 1/(pi*gam)
endfor
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_remove_char,str,char
char_pos = strpos(str,char)
while char_pos[0] ne -1 do begin
   str_len = strlen(str)
   if char_pos eq 0 then begin
      str = strmid(str,1,str_len-1)
   endif
   if char_pos eq (str_len-1) then begin
      str = strmid(str,0,str_len-1)
   endif
   if char_pos ne 0 and char_pos ne str_len-1 then begin
      str1 = strmid(str,0,char_pos)
      str2 = strmid(str,char_pos+1,str_len-char_pos)
      str = str1+str2
   endif
   char_pos = strpos(str,char)
endwhile
return,str
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data_remove_quotes,line
; Removes all (single) quotation marks
new_line = dtas_remove_char(line,"'")
return,new_line
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro dtas_data::cleanup
ptr_free,self.data_file_contents,self.collim_ptr,self.xtal_orientation_ptr
ptr_free,self.instrument_ptr,self.motors_ptr,self.lattice_ptr
ptr_free,self.mosaic_ptr,self.econfig_ptr,self.qconfig_ptr
ptr_free,self.treatment_ptr,self.mcf_ptr,self.fit_ptr
ptr_free,self.descriptr,self.header_ptr,self.orientation_ptr,self.anaPkgPtr
heap_free,self.data_ptr
heap_free,self.plot_ptr
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::update_display_name,str
ppos = strpos(self.display_name,'.')
if ppos eq -1 then return,0
extension = strmid(self.display_name,ppos)
beginning = strmid(self.display_name,0,ppos)
self.display_name = beginning+str+extension
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::write_ascii,filename
if n_params() eq 0 then return,0
if n_elements(*self.plot_ptr) eq 0 then return,0
x = *(*self.plot_ptr).x & y = *(*self.plot_ptr).y
dy = *(*self.plot_ptr).dy & xtitle = (*self.plot_ptr).xtitle
ytitle = (*self.plot_ptr).ytitle

nx = n_elements(x)
this_format = '(3f15.5)'
openw,lun,filename,/get_lun
printf,lun,xtitle+' ',ytitle+' ','Error'
for i = 0,nx-1 do begin
   printf,lun,x[i],y[i],dy[i],format = this_format
endfor
free_lun,lun,/force
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::display,_Extra = extra
if n_elements(*self.data_ptr) eq 0 then return,0
if n_elements(*self.plot_ptr) eq 0 then return,0
x = *(*self.plot_ptr).x & y = *(*self.plot_ptr).y
dy = *(*self.plot_ptr).dy & xtitle = (*self.plot_ptr).xtitle
ytitle = (*self.plot_ptr).ytitle & title = (*self.plot_ptr).title
plot,x,y,title = title,xtitle = xtitle,ytitle = ytitle,_Extra = extra
errplot,x,y-dy,y+dy,width = 0.0
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::auto_gauss_fit,msg = msg,_Extra = extra,fit_text = fit_text, $
   n = n,plot_mon = plot_mon
if n_elements(plot_mon) eq 0 then plot_mon = 0B
msg = ''
fit_text = ''
if n_elements(n) eq 0 then n = 1
if n_elements(*self.plot_ptr) eq 0 then return,0
x = *(*self.plot_ptr).x
if plot_mon then begin
   y = self->get_monitor()
   dy = sqrt(y)
endif else begin
   y = *(*self.plot_ptr).y
   dy = *(*self.plot_ptr).dy
endelse
if total(dy) eq 0.0 then begin
   msg = 'Error bars must be present for the fit'
   return,0
endif
peak_loc = GET_PEAK_POS( x,y,n,fwhm = fwhm,indices = indices)
indices = fix(indices)
if n ne n_elements(peak_loc) then begin
   msg = 'Fit failed'
   return,0
endif
fwhm = abs(fwhm)
; Fit with a Gaussian
bg = min(y)
for i = 0,n-1 do begin
   sigma = fwhm[i]/2.354
   center = peak_loc[i]
   area = (y[indices[i]]-bg)*sqrt(2.0*!dpi)*sigma
   if i eq 0 then begin
      init_parms = [bg,area,center,fwhm[i]]
   endif else begin
      init_parms = [init_parms,area,center,fwhm[i]]
   endelse
endfor
p = init_parms
parinfo = replicate({limited:[0,0], limits:[0.D,0]}, n_elements(p))
; Limit the fwhm to a positive number
np = n_elements(p)
for i = 0,n-1 do begin
   area_index = 3*i+1
   fwhm_index = 3*i+3
   parinfo(fwhm_index).limited(0) = 1
   parinfo(fwhm_index).limits(0) = 0D
   parinfo(area_index).limited(0) = 1
   parinfo(area_index).limits(0) = 0D
endfor
where_zero = where(y eq 0.0,count_bad)
if count_bad gt 0 then dy[where_zero] = 1D
quiet = 1
yfit = MPCURVEFIT(x, y, 1.d/dy^2, p, dp, $
                  FUNCTION_NAME='dtas_gaussians',status = status, $
                  /autoderivative,quiet = quiet,parinfo = parinfo,chisq = chisq)
dof = n_elements(x)-np
chi_reduced = chisq/dof
if status gt 0 then begin
   ; Create a fit with a higher density of points
   nx = n_elements(x)
   xhi = max(x,min = xlo)
   nnx = 3*nx
   dx = (xhi-xlo)/(nnx-1.0)
   xsm = xlo+dx*findgen(nnx)
   dtas_gaussians,xsm,p,ysm
;   *self.fit_ptr = {x:xsm,yfit:ysm}
   parms = 'Background: '
   pfmt = '(G10.3)'
   efmt = '(G8.2)'
   for i = 0,n-1 do begin
      parms = [parms,'Pk Hgt: ','Center: ','FWHM: ']
   endfor
   str = ['____________________','Fit parameters']
   str = [str,parms[0]+ $
          strtrim(string(p[0],format=pfmt),2)+' +/- '+ $
          strtrim(string(dp[0],format=efmt),2)]
   counter = 0
   for j = 0,n-1 do begin
      str = [str,'---Gaussian #'+strtrim(string(j+1),2)+'---']
      for i = 0,2 do begin
          str = [str,parms[counter+1]+' '+ $
                 strtrim(string(p[counter+1],format=pfmt),2)+' +/- '+ $
                 strtrim(string(dp[counter+1],format=efmt),2)]
         counter = counter + 1
      endfor
   endfor
   chi_format = '(G10.4)'
   str = [str,'','Chi-squared: '+strtrim(string(chi_reduced,$
      format = chi_format),2),'------------']
   ret = self->update_treatment(str)
   fit_text = str
   *self.fit_ptr = {x:xsm,yfit:ysm,fit_text:str}
endif else begin
   return,0
endelse

return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::auto_lorentz_fit,msg = msg,_Extra = extra,fit_text = fit_text, $
   n = n,plot_mon = plot_mon
if n_elements(plot_mon) eq 0 then plot_mon = 0B
msg = ''
fit_text = ''
if n_elements(n) eq 0 then n = 1
if n_elements(*self.plot_ptr) eq 0 then return,0
x = *(*self.plot_ptr).x
if plot_mon then begin
   y = self->get_monitor()
   dy = sqrt(y)
endif else begin
   y = *(*self.plot_ptr).y
   dy = *(*self.plot_ptr).dy
endelse
if total(dy) eq 0.0 then begin
   msg = 'Error bars must be present for the fit'
   return,0
endif
peak_loc = GET_PEAK_POS( x,y,n,fwhm = fwhm,indices = indices)
fwhm = abs(fwhm)
; Fit with a Lorentzian
bg = min(y)
for i = 0,n-1 do begin
   gam = 0.5*fwhm[i]
   center = peak_loc[i]
   area = (y[indices[i]]-bg)*!dpi*gam
   if i eq 0 then begin
      init_parms = [bg,area,center,fwhm[i]]
   endif else begin
      init_parms = [init_parms,area,center,fwhm[i]]
   endelse
endfor
p = init_parms
parinfo = replicate({limited:[0,0], limits:[0.D,0]}, n_elements(p))
; Limit the fwhm to a positive number
np = n_elements(p)
for i = 0,n-1 do begin
   area_index = 3*i+1
   fwhm_index = 3*i+3
   parinfo(fwhm_index).limited(0) = 1
   parinfo(fwhm_index).limits(0) = 0D
   parinfo(area_index).limited(0) = 1
   parinfo(area_index).limits(0) = 0D
endfor
where_zero = where(y eq 0.0,count_bad)
if count_bad gt 0 then dy[where_zero] = 1D
quiet = 1
yfit = MPCURVEFIT(x, y, 1.d/dy^2, p, dp, $
                  FUNCTION_NAME='dtas_lorentzians',status = status, $
                  /autoderivative,quiet = quiet,parinfo = parinfo,chisq = chisq)
dof = n_elements(x)-np
chi_reduced = chisq/dof
if status gt 0 then begin

   ; Create a fit with a higher density of points
   nx = n_elements(x)
   xhi = max(x,min = xlo)
   nnx = 3*nx
   dx = (xhi-xlo)/(nnx-1.0)
   xsm = xlo+dx*findgen(nnx)
   dtas_lorentzians,xsm,p,ysm
;   *self.fit_ptr = {x:xsm,yfit:ysm}

   parms = 'Background: '
   pfmt = '(G10.3)'
   efmt = '(G8.2)'
   for i = 0,n-1 do begin
      parms = [parms,'Pk Hgt: ','Center: ','FWHM: ']
   endfor
   str = ['____________________','Fit parameters']
   str = [str,parms[0]+ $
          strtrim(string(p[0],format=pfmt),2)+' +/- '+ $
          strtrim(string(dp[0],format=efmt),2)]
   counter = 0
   for j = 0,n-1 do begin
      str = [str,'---Lorentzian #'+strtrim(string(j+1),2)+'---']
      for i = 0,2 do begin
          str = [str,parms[counter+1]+' '+ $
                 strtrim(string(p[counter+1],format=pfmt),2)+' +/- '+ $
                 strtrim(string(dp[counter+1],format=efmt),2)]
         counter = counter + 1
      endfor
   endfor
   chi_format = '(f10.2)'
   str = [str,'','Chi-squared: '+strtrim(string(chi_reduced,$
      format = chi_format),2),'------------']
   ret = self->update_treatment(str)
   fit_text = str
   *self.fit_ptr = {x:xsm,yfit:ysm,fit_text:str}
endif else begin
   return,0
endelse

return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::get_property,   filename = filename,             $
  contents = contents,             $
  display_name = display_name,     $
  treatment = treatment,           $
  var_names = var_names,           $
  plot_str = plot_str,             $
  total_mon = total_mon,           $
  signal_type = signal_type,       $
  extension = extension,           $
  descriptr_str = descriptr_str,   $
  fit_ptr = fit_ptr,               $
  time = time,                     $
  hfield = hfield,                 $
  shift_value = shift_value,       $
  second_var_name = second_var_name,  $
  header = header,                 $
  data = data,                     $
  scan = scan $
  ,anaPkgStr = anaPkgStr $
  ,anaMode =  anaMode


if (arg_present(anaPkgStr)) then $
  if (n_elements(*self.anaPkgPtr) ne 0) then anaPkgStr=(*self.anaPkgPtr)

if (arg_present(anaMode)) then begin
    anaMode = (n_elements(*self.anaPkgPtr) ne 0)? $
              (*self.anaPkgPtr).mode : -1
endif

scan = self.scan
if arg_present(header) then begin
   if n_elements(*self.header_ptr) ne 0 then begin
      header = *self.header_ptr
   endif else begin
      header = 'No header information available'
   endelse
endif
if arg_present(data) then begin
   if n_elements(self.data_ptr) ne 0 then begin
      if n_elements(*self.data_ptr) ne 0 then data = *self.data_ptr
   endif
endif
if arg_present(second_var_name) then second_var_name = self.second_var_name
if arg_present(fit_ptr) then begin
   if n_elements(*self.fit_ptr) ne 0 then begin
      fit_ptr = self.fit_ptr
   endif else begin
      fit_ptr = 0
   endelse
endif
if arg_present(descriptr_str) then begin
   if n_elements(*self.descriptr) ne 0 then begin
      descriptr_str = *self.descriptr
   endif
endif
if arg_present(time) then begin
   if n_elements(*self.data_ptr) ne 0 then begin
      data = *self.data_ptr
      tags = tag_names(data)
      time_index = where(strupcase(tags) eq 'MIN',count_time)
      if (count_time eq 0) then $ ; then look for TIME tag 
        time_index = where(strupcase(tags) eq 'TIME',count_time)
      if count_time ne 0 then begin
         time = *data.(time_index[0])
      endif
   endif
endif
if arg_present(shift_value) then shift_value = self.shift_value
if arg_present(hfield) then hfield = self.hfield
if arg_present(signal_type) then signal_type = self.signal_type
if arg_present(total_mon) then total_mon = self.tot_mon
if arg_present(extension) then extension = self.extension
if arg_present(plot_str) and n_elements(*self.plot_ptr) ne 0 then begin
   plot_str = *self.plot_ptr
endif
if arg_present(contents) and n_elements(*self.data_file_contents) ne 0 then begin
   contents = *self.data_file_contents
endif
if arg_present(filename) and self.filename ne '' then begin
   filename = self.filename
endif
if arg_present(display_name) and self.filename ne '' then begin
   display_name = self.display_name
endif
;if arg_present(treatment) and n_elements(*self.treatment_ptr) ne 0 then begin
;   treatment = *self.treatment_ptr
;endif
if (arg_present(treatment)) then begin
    treatment = (n_elements(*self.treatment_ptr) gt 0)? *self.treatment_ptr : ''
endif
if arg_present(var_names) and n_elements(*self.data_ptr) ne 0 then begin
   var_names = tag_names(*self.data_ptr)
endif
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::set_descriptr,var_name
tags = tag_names(*self.data_ptr)
if strupcase(var_name) eq 'HFIELD' then begin
   dstr =   {  descriptrstr,           $
               name:'Hfield:G',        $
               units:'G',              $
               legend:'H (G)',         $
               qty:self.hfield,        $
               err:0.0                 }
   *self.descriptr = dstr
   return,1
endif
match = where(strupcase(tags) eq strupcase(var_name),count_match)
;print,'Number of matches: ',count_match
if count_match eq 0 then return,0
data = *self.data_ptr
qty = *data.(match[0])
ave_qty = (moment(qty))[0]
dstr =   {  descriptrstr,                    $
            name:tags[match[0]]+':arb',      $
            units:'arb',                     $
            legend:tags[match[0]]+' (arb)',  $
            qty:ave_qty,                    $
            err:0.0                          }
*self.descriptr = dstr
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::set_index_descriptr,number
dstr =   {  descriptrstr,           $
            name:'Index:i',         $
            units:'arb',            $
            legend:'Index',         $
            qty:number,             $
            err:0.0                 }
*self.descriptr = dstr

return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::set_property,   filename = filename,                $
  contents = contents,                $
  xvar_name = xvar_name,              $
  yvar_name = yvar_name,              $
  signal_type = signal_type,          $
  data = data,                        $
  display_name = display_name,        $
  hfield = hfield,                    $
  shift_value = shift_value,          $
  second_var_name = second_var_name,  $
  plot_str = plot_str,                $
  descriptr_str = descriptr_str $
  ,anaPkgStr = anaPkgStr $
  ,show_TD = show_TD $
  ,anaPkgUpdData = anaPkgUpdData

if n_elements(second_var_name) ne 0 then begin
   self.second_var_name = second_var_name
   ret = self->set_descriptr(second_var_name)
   new_treatment = 'Second independent variable selected: '+ second_var_name
   ret = self->update_treatment(new_treatment)
endif
if n_elements(descriptr_str) ne 0 then *self.descriptr = descriptr_str
if n_elements(shift_value) ne 0 then self.shift_value = shift_value
if n_elements(hfield) ne 0 then self.hfield = hfield
if n_elements(signal_type) ne 0 then self.signal_type = signal_type
if n_elements(display_name) ne 0 then self.display_name = display_name
if n_elements(plot_str) ne 0 then *self.plot_ptr = plot_str
if n_elements(data) ne 0 then begin
   *self.data_ptr = data
endif
if n_elements(contents) ne 0 then *self.data_file_contents = contents
if n_elements(filename) ne 0 then self.filename = filename
if (n_elements(anaPkgStr) gt 0) then begin
    (*self.anaPkgPtr) = anaPkgStr
    anaMode = anaPkgStr.mode
    
    if (keyword_set(anaPkgUpdData) && (n_elements(*self.data_ptr) gt 0)) then begin
        if (anaMode ge 1 && anaMode le 3) then begin
            ;; Deal with Primary or Diffraction detectors (depends on current
            ;; analyzer mode)
            detsInSum = strsplit(anaPkgStr.sigDetsInSum,';',/extract,count=nDets)
            
            nd = n_elements(*(*self.plot_ptr).y)
            yBuf = fltarr(nd)*0.0
            if (nDets gt 0) then begin
                ret = self->get_property(var_names = var_names)
                for i=0,nDets-1 do begin
                    ind = where(strupcase(var_names) eq strupcase(detsInSum[i]))
                    yBuf = yBuf + *(*self.data_ptr).(ind[0]) 
                endfor
            endif
            dyBuf = yBuf
            ind = where(dyBuf le 0.0,cnt)
            if (cnt gt 0) then dyBuf[ind] = 1.0
            dyBuf = sqrt(dyBuf)
            
            ;; update plot structure
            *(*self.plot_ptr).y = yBuf 
            *(*self.plot_ptr).dy = dyBuf
            
            ;; update data structure with new sums
            nCol = n_tags((*self.data_ptr))
            *(*self.data_ptr).(nCol-2) = yBuf 
            *(*self.data_ptr).(nCol-1) = dyBuf

            ;; Also update 'detector' column with new sum
            iCol = where(strupcase(var_names) eq 'DETECTOR', cnt)
            if (cnt) then *(*self.data_ptr).(iCol) = yBuf
        endif
        if (anaMode eq 2 || anaMode eq 3) then begin
            ;; Deal with Door detectors
            detsInSum = strsplit(anaPkgStr.tdDetsInSum,';',/extract,count=nDets)
            yBuf *= 0.0
            if (nDets gt 0) then begin
                ret = self->get_property(var_names = var_names)
                for i=0,nDets-1 do begin
                    ind = where(strupcase(var_names) eq strupcase(detsInSum[i]))
                    yBuf = yBuf + *(*self.data_ptr).(ind[0]) 
                endfor
            endif

            *(*self.plot_ptr).TDy = yBuf ; update plot structure
            (*self.plot_ptr).show_TD = (n_elements(show_TD) gt 0)? show_TD : 1
        endif
    endif
endif

if n_elements(xvar_name) ne 0 then begin
   if n_elements(*self.data_ptr) eq 0 then return,0
   var_names = tag_names(*self.data_ptr)
   ;ret = self->get_property(var_names = var_names)
   where_exist = where(strupcase(var_names) eq strupcase(xvar_name),count_ok)
   if count_ok gt 0 then begin
      *(*self.plot_ptr).x = *(*self.data_ptr).(where_exist[0])
      (*self.plot_ptr).xtitle = xvar_name
;      new_treatment = 'Independent variable selected: '+ xvar_name
;      ret = self->update_treatment(new_treatment)
   endif
endif

if n_elements(yvar_name) ne 0 then begin
   if n_elements(*self.data_ptr) eq 0 then return,0
   ret = self->get_property(var_names = var_names)
   where_exist = where(strupcase(var_names) eq strupcase(yvar_name),count_ok)
   if count_ok gt 0 then begin
       yBuf = *(*self.data_ptr).(where_exist[0])
       *(*self.plot_ptr).y = yBuf ; update plot_str signal
       (*self.plot_ptr).ytitle = yvar_name ; update plot_str dep label

       nCol = n_tags((*self.data_ptr))
       *(*self.data_ptr).(nCol-2) = yBuf ; update data structure with Signal
       
       dyBuf = yBuf
       ind = where(dyBuf le 0.0,cnt)
       if (cnt) then dyBuf[ind] = 1.0
       dyBuf = sqrt(dyBuf)
       *(*self.data_ptr).(nCol-1) = dyBuf ; update data structure Error col
       *(*self.plot_ptr).dy = dyBuf ; update plot_str Error
   endif
endif
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::update_treatment,new
if n_elements(*self.treatment_ptr) eq 0 then begin
   *self.treatment_ptr = new
endif else begin
   *self.treatment_ptr = [*self.treatment_ptr,new]
endelse
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::convert_data_to_array
if n_elements(*self.data_ptr) eq 0 then return,0
data = *self.data_ptr
tags = tag_names(data)
ntags = n_elements(tags)
nx = n_elements(*data.(0))
darray = dblarr(nx,ntags)
for i = 0,ntags-1 do begin
   darray[*,i] = *data.(i)
endfor
return,darray
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::convert_array_to_data,darray
if n_elements(*self.data_ptr) eq 0 then return,0
if n_params() eq 0 then return,0
data = *self.data_ptr
tags = tag_names(data)
ntags = n_elements(tags)
for i = 0,ntags-1 do begin
   *data.(i) = darray[*,i]
endfor
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::fast_background_subtraction,bg, o = o
; Here bg is assumed to be in counts/minute
if n_elements(*self.data_ptr) eq 0 then return,0
if self.scan eq 'I' then return,0
if self.scan eq 'ALIGNMENT' then return,0
ret = self->get_property(data = data)
tags = tag_names(data)
ntitles = n_elements(tags)
y = *(*self.data_ptr).(ntitles-2)
dy = *(*self.data_ptr).(ntitles-1)
ret = self->get_property(time = time)
; For ICP instruments, time is recorded in minutes
; For ICE instruments, time is recorded in seconds
; If dealing with ICE data, use a 1/60 scalefactor to convert to minutes 
sfactor = (self.isICE)? 1.0/60.0 : 1.0
y = y-bg*time*sfactor
dy = dy
*(*self.data_ptr).(ntitles-2) = y
*(*self.data_ptr).(ntitles-1) = dy
self.ytitle = 'CORRECTED COUNTS'
(*self.plot_ptr).ytitle = self.ytitle
new_treatment = 'Fast background subtraction applied: '+ $
   strtrim(string(bg),2) + $
   ' (cts/minute)'
ret = self->update_treatment(new_treatment)
str = '_fbg'
ret = self->update_display_name(str)
if arg_present(o) then o = self->clone()
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::calibration,factor,o = o
if n_elements(*self.data_ptr) eq 0 then return,0
tags = tag_names(*self.data_ptr)
ntitles = n_elements(tags)
y = *(*self.data_ptr).(ntitles-2)
dy = *(*self.data_ptr).(ntitles-1)
y = y*double(factor)
dy = dy*double(factor)
*(*self.data_ptr).(ntitles-2) = y
*(*self.data_ptr).(ntitles-1) = dy
new_treatment = 'Scale factor applied: '+strtrim(string(factor),2)
ret = self->update_treatment(new_treatment)
str = '_cal'
ret = self->update_display_name(str)
if arg_present(o) then o = self->clone()
self.ytitle = 'CORRECTED COUNTS'
(*self.plot_ptr).ytitle = self.ytitle
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::set_monitor,mon_new
if n_elements(*self.data_ptr) eq 0 then return,0
if self.scan eq 'ALIGNMENT' then return,0
tags = tag_names(*self.data_ptr)
data = *self.data_ptr
mon_index = where(strupcase(tags) eq 'MON',count_mon)
if (count_mon eq 0) then $      ; then try looking for MONITOR tag
  mon_index = where(strupcase(tags) eq 'MONITOR',count_mon)
if count_mon eq 0 then return,0
*(*self.data_ptr).(mon_index) = mon_new
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::get_monitor
if n_elements(*self.data_ptr) eq 0 then return,0
if self.scan eq 'ALIGNMENT' then return,0
tags = tag_names(*self.data_ptr)
data = *self.data_ptr
mon_index = where(strupcase(tags) eq 'MON',count_mon)
if (count_mon eq 0) then $      ; then try looking for MONITOR tag
  mon_index = where(strupcase(tags) eq 'MONITOR',count_mon)
if count_mon eq 0 then return,0B
mon = *(*self.data_ptr).(mon_index)
;mon = *(*self.data_ptr).mon
return,mon
end


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::normalize_to_monitor,o = o
if n_elements(*self.data_ptr) eq 0 then return,0
if self.scan eq 'ALIGNMENT' then return,0
tags = tag_names(*self.data_ptr)
data = *self.data_ptr
ntitles = n_elements(tags)

mon_index = where(strupcase(tags) eq 'MON',count_mon)
if (count_mon eq 0) then $      ; then try looking for MONITOR tag
  mon_index = where(strupcase(tags) eq 'MONITOR',count_mon)

mon = *(*self.data_ptr).(mon_index)

y = *(*self.data_ptr).(ntitles-2)
dy = *(*self.data_ptr).(ntitles-1)
y = y/mon
dy = dy/mon
*(*self.data_ptr).(ntitles-2) = y
*(*self.data_ptr).(ntitles-1) = dy
new_treatment = 'Normalized to beam monitor'
ret = self->update_treatment(new_treatment)
str = '_norm2mon'
ret = self->update_display_name(str)
self.ytitle = 'CORRECTED COUNTS'
(*self.plot_ptr).ytitle = self.ytitle
if arg_present(o) then o = self->clone()
return,1
end


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::normalize_to_time,o = o
if n_elements(*self.data_ptr) eq 0 then return,0
if self.scan eq 'ALIGNMENT' then return,0
tags = tag_names(*self.data_ptr)
data = *self.data_ptr

ntitles = n_elements(tags)

void = self->get_property(time=mon)
if (void ne 1 || n_elements(mon) eq 0) then return, 0
y = *(*self.data_ptr).(ntitles-2)
dy = *(*self.data_ptr).(ntitles-1)
y = y/mon
dy = dy/mon
*(*self.data_ptr).(ntitles-2) = y
*(*self.data_ptr).(ntitles-1) = dy

; HACK! RTA
; set real monitor to 1.0 to avoid double normalization downstream
mon = mon*0.0 + 1.0
void = self->set_monitor(mon)

new_treatment = 'Normalized to counting time'
ret = self->update_treatment(new_treatment)
str = '_norm2time'
ret = self->update_display_name(str)
self.ytitle = 'CORRECTED COUNTS'
(*self.plot_ptr).ytitle = self.ytitle
if arg_present(o) then o = self->clone()
return,1
end


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::monitor_correction_factor,o = o, msg=msg
if n_elements(*self.data_ptr) eq 0 then return,0

msg = ''
doCorrection = 0
tol = 0.0001                     ; meV
fileExt = strupcase(self.extension)
nCols = n_tags(*self.data_ptr)
switch fileExt of
   ;; set the instrument-dependent correction coefficients
   'BT7':
   'BT9': begin
      ;;CF[Ei] = 6.123 - 0.5963*Ei
      ;;               + 0.026244* (Ei)^2
      ;;               - 0.0004843* (Ei)^3
      ;;               + 2.881x10^6* (Ei)^4
      M0 =  6.1230
      M1 = -5.9630e-1
      M2 =  2.6244e-2
      M3 = -4.8430e-4
      M4 =  2.8810e-6
      break
   end

   'NG5': begin
      ;;CF[Ei] = 1.2776 - 0.078968*Ei
      ;;                  + 0.0099952* (Ei)^2
      ;;                  - 0.00060495* (Ei)^3
      ;;                  + 1.4203x10^-5* (Ei)^4      
      M0 =  1.2776
      M1 = -7.8968e-2
      M2 =  9.9952e-3
      M3 = -6.0495e-4
      M4 =  1.4203e-5
      break
   end
   else: return, 0
endswitch
switch fileExt of
   'BT7': begin
      if (~self.isICE) then break
      ;; Is PG in use?
      if (strtrim(string(self.dspaceM,format='(F5.3)'),2) ne '3.354') then return, 0

      ;; Ensure Ei is NOT fixed by checking whether Ef IS fixed
      if (strupcase(self.fixedEType) ne 'EF') then return, 0
      Ef = self.fixedEValue
      if (Ef le 0.0) then return, 0
      ;; Get energy Transfer
      tags = strupcase(tag_names(*self.data_ptr))
      index = where(tags eq 'E',eFound)
      if (eFound ne 1) then return, 0
      eTransfer = (*(*self.data_ptr).(index[0]))

      doCorrection = 1
      break
   end

   'NG5':
   'BT9': begin
      if n_elements(*self.econfig_ptr) eq 0 then return,0
      if n_elements(*self.mcf_ptr) eq 0 then return,0
      if self.scan ne 'Q' then return,0
      tags = tag_names(*self.econfig_ptr)
      data_tags = tag_names(*self.data_ptr)
      if tags[2] eq 'EM' then return,0
      dsp = (*self.econfig_ptr).m_dsp
      ;; Ensure PG mono is in use
      if (strtrim(string(dsp,format='(F5.3)'),2) ne '3.354') then return, 0
      ea_index = where(tags eq 'EA')
      Ef = (*self.econfig_ptr).(ea_index[0])
      if (Ef le 0.0) then return, 0
      ;y = *(*self.data_ptr).(nCols-2)
      ;dy = *(*self.data_ptr).(nCols-1)
      ;mcf = *self.mcf_ptr
      ;e_mcf = reform(mcf[0,*]) - Ef
      ;c_mcf = reform(mcf[1,*])
      ;;; Interpolate the monitor correction factor data to the energy grid of
      ;;; the current file.
      ok1 = where(strupcase(data_tags) eq 'EMEV',count_emev)
      ok2 = where(strupcase(data_tags) eq 'E',count_e)
      epos = -1
      if count_emev gt 0 then epos = ok1[0]
      if count_e gt 0 then epos = ok2[0]
      if epos eq -1 then return, 0
      ;energy = *(*self.data_ptr).(epos)
      ;mcf_interpol = interpol(c_mcf,e_mcf,energy)
      ;y = y*mcf_interpol
      ;dy = dy*mcf_interpol
      eTransfer = *(*self.data_ptr).(epos)

      doCorrection = 1
      break
   end

   else: return, 0
endswitch

if (doCorrection) then begin
   ;; Check whether E (hence Ei) is varying
   nEt = n_elements(eTransfer)
   diff = eTransfer[1:nEt-1] - eTransfer[0:nEt-2]
   void = where(abs(diff) gt tol, eIsVarying)
   if (eIsVarying eq 0) then return, 0 
   Ei = double(Ef + eTransfer)  ; double necessary for calculation below

   monCor = fltarr(nEt)
   index = indgen(nEt)
   if (fileExt ne 'NG5') then begin
      ;; BT7 and BT9 have additional energy-dependent restrictions
      index = where(Ei ge 5 and Ei le 34, count)         
      if (count ne nEt) then begin
         void = where(Ei lt 5,cnt)
         if (cnt gt 0) then begin
            msg = 'Monitor correction not possible for incident energy values below 5 meV'
            void = dialog_message(msg,/error)
            return, 0
         endif
         
         indexAbove34 = where(Ei gt 34,EiAbove34)
         if (EiAbove34 gt 0) then monCor[indexAbove34] = 1.0
      endif
   endif
   Eii = Ei[index]

   monCor[index] = M0 + M1*Eii + M2*Eii^2 + M3*Eii^3 + M4*Eii^4
   print,self.filename
   print,'         E        Ei          Mon. Cor. Fac.'
   for i=0,nEt-1 do print,eTransfer[i],Ei[i],monCor[i]

   *(*self.data_ptr).(nCols-2) = *(*self.data_ptr).(nCols-2) * monCor
   *(*self.data_ptr).(nCols-1) = *(*self.data_ptr).(nCols-1) * monCor
   new_treatment = 'Monitor correction factor applied'
   ret = self->update_treatment(new_treatment)
   str = '_moncor'
   ret = self->update_display_name(str)
   self.ytitle = 'CORRECTED COUNTS'
   (*self.plot_ptr).ytitle = self.ytitle
endif

if arg_present(o) then o = self->clone()
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::resolution_correction, o = o
if n_elements(*self.data_ptr) eq 0 then return,0

doCorrection = 0
tol = 0.0001                     ; meV
fileExt = strupcase(self.extension)
nCols = n_tags(*self.data_ptr)

switch fileExt of
   'BT7': begin
      if (~self.isICE) then break

      ;; Ensure Ef is NOT fixed by checking whether Ei IS fixed
      if (strupcase(self.fixedEType) ne 'EI') then return, 0
      Ei = self.fixedEValue
      if (Ei le 0.0) then return, 0
      ;; Get energy Transfer
      tags = strupcase(tag_names(*self.data_ptr))
      index = where(tags eq 'E',eFound)
      if (eFound ne 1) then return, 0
      eTransfer = (*(*self.data_ptr).(index[0]))
      ;; Check whether E (hence Ef) is varying
      nEt = n_elements(eTransfer)
      diff = eTransfer[1:nEt-1] - eTransfer[0:nEt-2]
      void = where(abs(diff) gt tol, eIsVarying)
      if (eIsVarying eq 0) then return, 0 
      Ef = double(Ei - eTransfer) ; double necessary for calculation below

      dA = self.dspaceM
      if (dA le 0.0) then return, 0

      ;; Get theta-A (=A6/2)
      index = where(tags eq 'A6',a6Found)
      if (a6Found ne 1) then return, 0
      A6 = (*(*self.data_ptr).(index[0]))
      thetaA = A6/2.0 *!pi/180.0 ; in radians!



      doCorrection = 1
      break
   end

   'NG5':
   'BT9': begin
      if n_elements(*self.econfig_ptr) eq 0 then return,0
      if n_elements(*self.mcf_ptr) eq 0 then return,0
      if self.scan ne 'Q' then return,0
      tags = tag_names(*self.econfig_ptr)
      data_tags = tag_names(*self.data_ptr)
      if tags[2] eq 'EA' then return,0
      em_index = where(tags eq 'EM')
      Ei = (*self.econfig_ptr).(em_index[0])
      if (Ei le 0.0) then return, 0
      ok1 = where(strupcase(data_tags) eq 'EMEV',count_emev)
      ok2 = where(strupcase(data_tags) eq 'E',count_e)
      epos = -1
      if count_emev gt 0 then epos = ok1[0]
      if count_e gt 0 then epos = ok2[0]
      if epos eq -1 then return, 0
      eTransfer = *(*self.data_ptr).(epos)
      ;; Check whether E (hence Ef) is varying
      nEt = n_elements(eTransfer)
      diff = eTransfer[1:nEt-1] - eTransfer[0:nEt-2]
      void = where(abs(diff) gt tol, eIsVarying)
      if (eIsVarying eq 0) then return, 0 
      Ef = double(Ei - eTransfer) ; double necessary for calculation below
      ;; Determine theta-A (=A6/2)
      dA = (*self.econfig_ptr).a_dsp
      if (dA le 0.0) then return, 0
      lambdaA = sqrt(81.80425/Ef)
      thetaA = asin(lambdaA/(2.0*dA)) ; in radians!
      
      doCorrection = 1
      break
   end

   else: return, 0
endswitch
if (doCorrection) then begin
   ;; resCor = Norm/(cot(A6/2)*Ef^1.5)
   ;; where Norm = Ei^1.5 * cot(asin(!pi/(0.69472*dA*sqrt(Ei))))
   arg = asin(!pi/(0.6947*dA*sqrt(double(Ei))))
   norm = (Ei^1.5) / tan(arg)
   cotThetaA = 1/tan(thetaA)
   resCor = norm/(cotThetaA * (Ef^1.5))

   print,self.filename
   for i=0,nEt-1 do print,eTransfer[i],Ef[i],resCor[i]

   *(*self.data_ptr).(nCols-2) = *(*self.data_ptr).(nCols-2) * resCor
   *(*self.data_ptr).(nCols-1) = *(*self.data_ptr).(nCols-1) * resCor
   new_treatment = 'Corrected for resolution volume'
   ret = self->update_treatment(new_treatment)
   str = '_rescor'
   ret = self->update_display_name(str)
   self.ytitle = 'CORRECTED COUNTS'
   (*self.plot_ptr).ytitle = self.ytitle
endif

; if (self.scan ne 'Q') then return,0
; ; Calculate the resolution volume correction factor (unscaled)
; tags = tag_names(*self.econfig_ptr)
; if tags[2] eq 'EM' then begin
;       em = (*self.econfig_ptr).em
;       lambda_m = sqrt(81.80425/em)
;       dm = (*self.econfig_ptr).m_dsp
;       theta_m = asin(lambda_m/(2.0*dm))
;       dtags = tag_names(*self.data_ptr)
;       e_index = where(strupcase(dtags) eq 'E')
;       ea = em - *(*self.data_ptr).(e_index[0])
;       lambda_a = sqrt(81.80425/ea)
;       da = (*self.econfig_ptr).a_dsp
;       theta_a = asin(lambda_a/(2.0*da))
; endif else begin
;       return,0
; endelse
; ko = 2.0*!dpi/lambda_m
; kf = 2.0*!dpi/lambda_a
; cot_thetam = 1.0/tan(theta_m)
; cot_thetaa = 1.0/tan(theta_a)
; ; Calculate the scale factor "AMP" such that the resolution volume
; ; correction always is unity at the elastic position.
; if da eq dm then amp = 1.0 else $
;    amp = sqrt(((da*ko)^2 - (!pi)^2)/(((dm*ko)^2 - (!pi)^2)))
; r = amp*((ko/kf)^3)*cot_thetam/cot_thetaa
;    ; Normalize the correction factor to 1 at a point as close to the elastic line
;    ; as possible.
; energy = *(*self.data_ptr).(e_index[0])
; ;min_energy = min(abs(energy),imin)
; ;r = r/r[imin]
; ntags = n_tags(*self.data_ptr)
; *(*self.data_ptr).(ntags-2) = r*(*(*self.data_ptr).(ntags-2))
; *(*self.data_ptr).(ntags-1) = r*(*(*self.data_ptr).(ntags-1))
; new_treatment = 'Corrected for resolution volume'
; ret = self->update_treatment(new_treatment)
; str = '_rescor'
; ret = self->update_display_name(str)
; self.ytitle = 'CORRECTED COUNTS'
; (*self.plot_ptr).ytitle = self.ytitle


if arg_present(o) then o = self->clone()
return,1
end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::detailed_balance, o = o,msg = msg
msg = ''
if n_elements(*self.data_ptr) eq 0 then return,0
if self.scan ne 'Q' then return,0
tags = tag_names(*self.data_ptr)
ok1 = where(strupcase(tags) eq 'EMEV',count_emev)
ok2 = where(strupcase(tags) eq 'E',count_e)
epos = -1
if count_emev gt 0 then epos = ok1[0]
if count_e gt 0 then epos = ok2[0]
if epos eq -1 then return,0
tpos = -1
ok3 = where(strupcase(tags) eq 'TACT',count_tact)
ok4 = where(strupcase(tags) eq 'T',count_t)
if count_tact gt 0 then tpos = ok3[0]
if count_t gt 0 then tpos = ok4[0]
if tpos eq -1 then return,0

ntitles = n_elements(tags)
energy = *(*self.data_ptr).(epos)
temperature = *(*self.data_ptr).(tpos)
where_zero_temp = where(temperature eq 0.0, count_zero)
if count_zero gt 1 then begin
   msg = 'There are temperatures with a value of 0'
   return,0
endif
y = *(*self.data_ptr).(ntitles-2)
dy = *(*self.data_ptr).(ntitles-1)
db_factor = exp(-0.5*11.6*energy/temperature)
y = y*db_factor
dy = dy*db_factor
*(*self.data_ptr).(ntitles-2) = y
*(*self.data_ptr).(ntitles-1) = dy
new_treatment = 'Corrected for detailed balance'
ret = self->update_treatment(new_treatment)
str = '_sym'
ret = self->update_display_name(str)
self.ytitle = 'CORRECTED COUNTS'
(*self.plot_ptr).ytitle = self.ytitle
if arg_present(o) then o = self->clone()
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::udpate_descriptr,  TEMPERATURE = temperature
if keyword_set(temperature) then begin
   ; Is the temperature column defined?
   tags = tag_names(*self.data_ptr)
   where_temperature = where((strupcase(tags) eq "TACT") or $
      (strupcase(tags) eq "TEMP"),count)
   if count eq 0 then return,0
   data = *self.data_ptr
   temperature = *data.(where_temperature[0])
   if n_elements(temperature) gt 1 then begin
      ave_temp = (moment(temperature))[0]
   endif else begin
      ave_temp = temperature[0]
   endelse
   print,'Temperature: ',ave_temp
   dstr =   {  descriptrstr,           $
               name:'Temperature',   $
               units:'K',              $
               legend:'T (K)',         $
               qty:ave_temp,           $
               err:0.0                 }
   *self.descriptr = dstr
endif

return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::write_dave,dir,detnorm,det
if n_params() eq 0 then cd,current = dir
per_pos = strpos(self.display_name,'.')
if per_pos[0] eq -1 then begin
   filename = self.display_name+'.dave'
endif else begin
   filename = strmid(self.display_name,0,per_pos)+'.dave'
endelse
plot_str = *self.plot_ptr

specificstr = {title:'Single Data File'}
x = *plot_str.x
z = *plot_str.y
dz = *plot_str.dy
xtitle = plot_str.xtitle
ztitle = plot_str.ytitle
treatment = (n_elements(*self.treatment_ptr) gt 0)? *self.treatment_ptr : ""
scan = self.scan

if (n_elements(det) eq 0) then det=1
if (n_elements(detnorm) eq 0) then detnorm = 1

mon = self->get_monitor()
if scan ne 'ALIGNMENT' then begin
    ; Is it normalized to the beam monitor?
    index = where(treatment eq 'Normalized to beam monitor',count_treat)
    mon_norm = count_treat eq 1
    
    if mon_norm then mon_ave = mon else mon_ave = mon[0]
    if det then begin
       if detnorm then begin
          z = z*mon_ave/mon
          dz = dz*mon_ave/mon
       endif else begin
          ztitle = 'Raw detector counts'
       endelse
    endif
endif


ret =  create_dave_pointer(daveptr,          $
                     instrument = 'TAS', $
                     qty = z,         $
                     qtunits = '',      $
                     qtlabel = ztitle,      $
                     err = dz,          $
                     xvals = x,         $
                     xtype = 'POINTS',         $
                     xunits = '',      $
                     xlabel = xtitle,      $
                     yvals = 0.0,         $
                     ytype = 'POINTS',$
                     yunits = '',$
                     ylabel = '',$
                     specificstr = specificstr,$
                     treatment = treatment,  $
                     ermsg = errmsg)
save,daveptr,filename = dir+filename
heap_free,daveptr

return,dir+filename
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::write_ascii,dir
if n_params() eq 0 then cd,current = dir
per_pos = strpos(self.display_name,'.')
if per_pos[0] eq -1 then begin
   filename = dir+self.display_name+'.txt'
endif else begin
   filename = dir+strmid(self.display_name,0,per_pos)+'.txt'
endelse
ret = self->get_property(contents = contents)
nlines = n_elements(contents)
if nlines lt 1 then return,0
openw,lun,filename,/get_lun
for i = 0,nlines-1 do printf,lun,contents[i]
free_lun,lun,/force

return,filename
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::get_hfield
; This function sifts through all of the tags for the structures found during
; the data read and determines if there is a magnetic field tag named HFIELD.
; If so then the data member called HFIELD is defined.
if n_elements(*self.data_ptr) ne 0 then begin
   data_tags = tag_names(*self.data_ptr)
   hd_index = where(strupcase(data_tags) eq 'HFIELD',count_data)
   if count_data ne 0 then begin
      h_array = *(*self.data_ptr).hfield
      hfield = (moment(h_array))[0]
   endif
endif
if n_elements(*self.qconfig_ptr) ne 0 then begin
   Q_tags = tag_names(*self.qconfig_ptr)
   hq_index = where(strupcase(Q_tags) eq 'HFIELD',count_q)
   if count_q ne 0 then hfield = (*self.qconfig_ptr).hfield
endif
if n_elements(*self.instrument_ptr) ne 0 then begin
   i_tags = tag_names(*self.instrument_ptr)
   hi_index = where(strupcase(i_tags) eq 'HFIELD',count_i)
   if count_i ne 0 then hfield = (*self.instrument_ptr).hfield
endif
if n_elements(hfield) ne 0 then self.hfield = hfield
return,1
end


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::read_ice
; This function requires two external functions: DAVE_READ_ICE and
; DAVE_PARSE_ICE.
read_ok = dave_read_ice(self.filename,dstring=dstring,errmsg=errmsg)
if ~read_ok then begin
    void = dialog_message(errmsg)
    return,0B
endif
parse_ok = dave_parse_ice(dstring,dstruct,header=header $
                          ,indep_var_pos=indep_var_pos $
                          ,dep_var_pos=dep_var_pos $
                          ,lattice=lattice $
                          ,fixedEType=fixedEType $
                          ,fixedEValue=fixedEValue $
                          ,dSpaceM=dSpaceM $
                          ,dSpaceA=dSpaceA $
                          ,orientation=orientation $
                          ,sdesc=sdesc $
                          ,anaPkgStr=anaPkgStr $
                          ,errmsg=errmsg $
                         )
if ~parse_ok then begin
    void = dialog_message(errmsg)
    return,0B
endif
(*self.data_file_contents) = dstring
(*self.header_ptr) = header       ;dstruct.header
self.display_name = dtas_get_filename(self.filename)
self.isICE = 1


; Ok now we have the entire data structure with titles and all
; stored in dstruct.  Now we need to convert it to the form used
; throughout the TAS data reduction.  In other words...warp it into
; the ICP format.

; What is the file extension?
ppos = strpos(self.filename,'.')
self.extension = strmid(self.filename,ppos+1)
self.display_name = dtas_get_filename(self.filename)

;*** RTA move to dave_parse_ice
; Now reform the data structure DSTRUCT so that the data are stored
; in pointers
;ntags = n_tags(dstruct)
;names = tag_names(dstruct)
;s = create_struct(names[0],ptr_new(dstruct.(0)))
;for i = 1,ntags-1 do $
;   s = create_struct(s,names[i],ptr_new(dstruct.(i)))

;*** RTA move to dave_parse_ice
; Replace the field labeled 'MONITOR' with one labeled 'MON'
;mon_index = where(names eq 'MONITOR')
;for i = 0,ntags-1 do begin
;   if i eq mon_index then tag = 'MON' else tag = names[i]
;   if i eq 0 then $
;      out_struct = create_struct(tag,s.(i)) else $
;      out_struct = create_struct(out_struct,tag,s.(i))
;endfor


;*** RTA move to dave_parse_ice
; Remove the header information from the structure
;names = tag_names(out_struct)
;header_index = where(names eq 'HEADER')
;for i = 0,n_elements(names)-1 do begin
;   if i ne header_index then begin
;      tag = names[i]
;      if i eq 0 then new_struct = create_struct(tag,out_struct.(i)) else $
;         new_struct = create_struct(new_struct,tag,out_struct.(i))
;   endif
;endfor

;*** Move to dave_parse_ice
; Is there an 'ERROR' column?
;error = sqrt(*new_struct.detector)
;bad = where(error eq 0.0,count_bad)
;if count_bad gt 0 then error[bad] = 1.0
;new_struct = create_struct(new_struct,'ERROR',ptr_new(error))
;names = tag_names(new_struct)

; Finally add an index column (first)
;new_struct = create_struct('INDEX', $
;   ptr_new(findgen(n_elements(error))),new_struct)

; Lattice
*self.lattice_ptr = lattice
; Orientation
*self.orientation_ptr = orientation
; Fixed anergy and its value
self.fixedEType = fixedEType
self.fixedEValue = fixedEValue
; Monochromator and Analyzer d spacing
self.dspaceA = dspaceA
self.dspaceM = dspaceM
; Scan description
self.sdesc = sdesc

; Data structure
*self.data_ptr = dstruct

ntitles = n_tags(*self.data_ptr)
titles = tag_names(*self.data_ptr)
if is_ice(self.filename) then count_index = ntitles else $
   count_index = ntitles-2

;*** RTA move to dave_parse_ice
; Determine which of the independent variables is varying
;imax = -1
;for i = count_index-1,2,-1 do begin
;   col = *((*self.data_ptr).(i))
;   n = n_elements(col)
;   if n gt 1 then begin
;      if col[1] ne col[2] then imax = i
;   endif else begin
;      imax = i
;   endelse
;endfor

; With the ICE files we will always choose the "INDEX" field
; as the independent variable (until we can figure out a better
; way of determining the "real" independent variable).
;imax = 0
;this_index = where(tag_names(*self.data_ptr) eq strupcase(plot_indep_var))


; Retrieve plottable data
x = ptr_new(*(*self.data_ptr).(indep_var_pos))
xtitle = titles[indep_var_pos]
y = ptr_new(*(*self.data_ptr).(dep_var_pos))
ytitle = titles[dep_var_pos]
dy = ptr_new(*(*self.data_ptr).error)

;; BT7 Analyzer package details
nd = n_elements(*y)
TDy = fltarr(nd)*0.0
anaMode = 0
if (n_elements(anaPkgStr) gt 0) then begin
    (*self.anaPkgPtr) = anaPkgStr  

    ;; Retrieve door detector data
    anaMode = anaPkgStr.mode
    if (anaMode eq 2 || anaMode eq 3) then begin
        detsInSum = strsplit(anaPkgStr.TDDetsInSum,';',/extract,count=nDets)
        if (nDets gt 0) then begin
            for i=0,nDets-1 do begin
                ind = where(strupcase(titles) eq strupcase(detsInSum[i]))
                TDy = TDy + *(*self.data_ptr).(ind[0]) 
            endfor
        endif
    endif
endif

;self.tot_mon = (*(*self.data_ptr).mon)[0]
tags = tag_names(*self.data_ptr)
mon_index = where(strupcase(tags) eq 'MON',count_mon)
if (count_mon eq 0) then $      ; then try looking for MONITOR tag
  mon_index = where(strupcase(tags) eq 'MONITOR',count_mon)
self.tot_mon = (*(*self.data_ptr).(mon_index))[0]

mon_counts = strtrim(string(self.tot_mon,format = '(e15.3)'),2)
ytitle = 'COUNTS PER '+mon_counts+' MONITOR'
self.ytitle = ytitle
plot_str = {x:x,y:y,dy:dy,TDy:ptr_new(TDy),anaMode:anaMode,show_td:1B $
            ,xtitle:xtitle,ytitle:self.ytitle,title:self.display_name}
*self.plot_ptr = plot_str
new_treatment = 'Raw data file read in: '+self.display_name
ret = self->update_treatment(new_treatment)

; Set the descriptive variable to the average temperature of the file
; as a starting point (default).
ret = self->udpate_descriptr(/temperature)
ret = self->get_hfield()

;ret = self->get_property(descriptr_str = d)

return,1B
end


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::read_file

catch,the_error
if the_error ne 0 then begin
   catch,/cancel
   void = dialog_message(!error_state.msg)
   if n_elements(lun) ne 0 then free_lun,lun,/force
   return,0
endif

if not file_test(self.filename) then return,0

; Test if the file is an ICE file
if is_ice(self.filename) then begin
   ; If so then read it in...
   ret = self->read_ice()
   ; ...and get out
   return,1B
endif

; What is the file extension?
ppos = strpos(self.filename,'.',/reverse_search)
self.extension = strmid(self.filename,ppos+1)

forbidden_char = ['#','-','(',')','.'] ; these characters cannot be structure
; tag names.
n_forbidden = n_elements(forbidden_char)
; Get the display name out
self.display_name = dtas_get_filename(self.filename)
; Read in the entire file into a string array first
dum = ''
openr,lun,self.filename,/get_lun
counter = 0L
while not eof(lun) do begin
   readf,lun,dum
   if counter eq 0L then text_data = dum else text_data = [text_data,dum]
   counter = counter + 1L
endwhile
free_lun,lun,/force
*self.data_file_contents = text_data
; Is the file an alignment curve?  Look at the 2nd line and determine if
; it is two or three columns of data....
num_elements = n_elements(strsplit(text_data[1],/extract))
ret = self->get_property(display_name = display_name)

if num_elements le 6 then begin
   self.scan = 'ALIGNMENT'
   *self.header_ptr = text_data[0]
   new_treatment = 'Raw data file read in: '+display_name
   ret = self->update_treatment(new_treatment)
   alignment_titles = 'Motor no. 1'
   for j = 2,10 do begin
      alignment_titles = [alignment_titles,'Motor no. '+strtrim(string(j),2)]
   endfor
   alignment_titles = [alignment_titles,'intensity','temp']
   alignment_titles = strlowcase(strcompress(alignment_titles,/remove_all))
   new_al_titles = 'motor_no_1'
   for j = 2,10 do begin
      new_al_titles = [new_al_titles,  $
         'motor_no_'+strtrim(string(j),2)]
   endfor
   new_al_titles = [new_al_titles,'intensity','temp']
;   new_al_titles=['motor_no_1','motor_no_2','motor_no_3','motor_no_4',  $
;                  'intensity','temp']
   ; Get the titles out from the first line
   n_t = n_elements(alignment_titles)
   title_count = 0L
   for i = 0,n_t-1 do begin
      title_pos = strpos(strlowcase(strcompress(text_data[0],/remove_all)),   $
         alignment_titles[i])
      if title_pos[0] ne -1 then begin
         if title_count eq 0L then begin
            char_pos = title_pos[0]
            title_index = i
            col_header = new_al_titles[i]
         endif else begin
            char_pos = [char_pos,title_pos[0]]
            title_index = [title_index,i]
            col_header = [col_header,new_al_titles[i]]
         endelse
         title_count = title_count + 1L
      endif
   endfor
   char_pos_sort = sort(char_pos)
   title_index = title_index[char_pos_sort]



   _intensity_index = where(col_header eq 'intensity',complement = _xindex)
   data_index = [_xindex,_intensity_index]
   darray = dblarr(counter-1,num_elements)
   for i = 1,counter-1 do begin
      darray[i-1,*] = (double(strsplit(text_data[i],/extract)))[*]
   endfor
   darray = darray[*,data_index];

   titles = new_al_titles[title_index]
   ; Now move the intensity into the last column
   ntitles = n_elements(titles)
   if titles[ntitles-1] ne 'intensity' then begin
      int_index = where(titles eq 'intensity',complement = xxindex)
      titles = [titles[xxindex],titles[int_index]]
   endif


   ; Write DARRAY into a structure
   s = create_struct(strupcase(titles[0]),ptr_new(darray[*,0]))
   for i = 1,n_elements(titles)-1 do begin
      s = create_struct(s, strupcase(titles[i]),ptr_new(darray[*,i]))
   endfor
   ; Add an 'ERROR' column?
   ntitles = n_elements(titles)
   error = sqrt(darray[*,ntitles-1])

   bad = where(error eq 0.0,count_bad)
   s_size = size(darray,/dimensions)
   nx = s_size[0] & ny = s_size[1]
   if count_bad gt 0 then error[bad] = 1.0
   s = create_struct(s,'ERROR',ptr_new(error))
   s = create_struct('INDEX',ptr_new(dindgen(nx)),s)
   *self.data_ptr = s
   x = ptr_new(darray[*,0]) & y = ptr_new(darray[*,ny-1])
   dy = ptr_new(error)
   plot_str = {x:x,y:y,dy:dy,xtitle:strupcase(titles[0]),anaMode:0, $
      ytitle:strupcase(titles[ny-1]),title:display_name}
   *self.plot_ptr = plot_str
;   ;titles = ['Motor_3','Motor_4','Intensity']
;   if num_elements eq 2 then begin
;      titles = titles[0:1]
;      dy = ptr_new(sqrt(darray[*,1]))
;      x = ptr_new(darray[*,0]) & y = ptr_new(darray[*,1])
;      plot,*x,*y,psym = 4
;      errplot,*x,*y-*dy,*y+*dy,width = 0.0
;      plot_str = {x:x,y:y,dy:dy,xtitle:titles[0],ytitle:titles[1],title:display_name}
;      (*self.data_ptr) = create_struct(titles[0],x,titles[1],y,   $
;         'ERROR',dy)
;      *self.plot_ptr = plot_str
;   endif else begin
;      dy =ptr_new(sqrt(darray[*,2]))
;      x = ptr_new(darray[*,0]) & y = ptr_new(darray[*,2])
;      (*self.data_ptr) = create_struct(titles[0],x,titles[1],y,'ERROR',dy)
;      plot_str = {x:x,y:y,dy:dy,xtitle:titles[0],ytitle:titles[2],title:display_name}
;      *self.plot_ptr = plot_str
;   endelse
   return,1
endif
file_length = counter

dum = ''
first_line = strsplit(text_data[0],/extract)
;print,'----------------'
;for i = 0,n_elements(first_line)-1 do print,first_line[i]
; Extract the scan type:  I buffer, Q buffer, or B buffer
if (strpos(strupcase(self.filename),'.ADD'))[0] ne -1 then $
   self.add = 1B else self.add = 0B
;   if first_line[1] eq "'" then counter = 2 else counter = 1
   case strlen(first_line[1]) of
   1:       counter = 2
   4:       counter = 3
   else:    counter = 1
   endcase
   ;if strlen(first_line[1]) eq 1 then counter = 2 else counter = 1
   ;print,'Counter: ',counter
   if self.add then self.scan = dtas_data_remove_quotes(first_line[6]) else $
      self.scan = dtas_data_remove_quotes(first_line[counter+2])
; Extract the date, monitor counts, prefactor, base, num_pts, and type
; If it is an "ADD" file then the first_line is different
if not self.add then begin
   self.date = first_line[counter]
   self.time = strmid(first_line[counter+1],0,strlen(first_line[counter+1])-1)
   self.mon = long(first_line[counter+3])
   self.prf = long(first_line[counter+4])
   self.base = first_line[counter+5]
   self.num_pts = fix(first_line[counter+6])
   self.type = first_line[counter+7]
endif else begin
   self.date = first_line[2]+first_line[3]+first_line[5]
   self.time = first_line[4]
   self.mon = long(first_line[7])
   self.prf = long(first_line[8])
   self.base = first_line[9]
   self.num_pts = fix(first_line[10])
   self.type = first_line[11]
endelse
self.tot_mon = self.mon*self.prf
; Get the comment line out
self.comments = text_data[2]

instrument_line = text_data[3]
instrument_line_titles = strsplit(text_data[4],/extract)
;print,'# titles: ',n_elements(instrument_line_titles)

instrument_line_split = strsplit(instrument_line,/extract)
;print,'# in split: ',n_elements(instrument_line_split)

; If this is a polarized beam file (BA,BB, etc.) then an error in the
; ICP file prevents the # DETS field from being filled in (it is just not
; there in the ICP file).  Therefore we need to add another value to the
; instrument_line_split array.
if (n_elements(instrument_line_titles) eq 7) and $
   (n_elements(instrument_line_split) eq 11) then begin
   instrument_line_split = [instrument_line_split,'1']
endif

;for i = 0,n_elements(instrument_line_split)-1 do print,instrument_line_split[i]
; Extract the collimations
collimations = intarr(4)
for i = 0,3 do begin
   if strlen(instrument_line_split[i]) lt 4 then begin   ; ok
      collimations[i] = fix(instrument_line_split[i])
      next_index = i
   endif else begin  ; uh-oh
      collimations[i] = 0
      next_index = i-1
   endelse
endfor

;collimations = fix(instrument_line_split[0:3])

*self.collim_ptr =   {  in_pile:          collimations[0],  $
                        before_sample:    collimations[1],  $
                        after_sample:     collimations[2],  $
                        before_detector:  collimations[3]   }


; Extract the mosaic
mosaic = fix(instrument_line_split[next_index:next_index+2])

;mosaic = fix(instrument_line_split[4:6])
*self.mosaic_ptr =   {  monochromator:    mosaic[0],        $
                        sample:           mosaic[1],        $
                        analyzer:         mosaic[2]         }

; Extract the rest of the instrument and sample information from the third and
; fourth lines.
; First extract the remaining fields (removing the collimation and mosaic fields).
rem_instrument_line_split = instrument_line_titles[2:*]
for i = 0,n_forbidden-1 do begin
   for j = 0,n_elements(rem_instrument_line_split)-1 do begin
      rem_instrument_line_split[j] = dtas_remove_char(rem_instrument_line_split[j], $
         forbidden_char[i])
   endfor
endfor
; Is xstal orientation included?
where_xstal_orientation = where(strupcase(rem_instrument_line_split) eq $
   'XSTAL',count_xstal)

if count_xstal ne 0 then begin
;   orientations = instrument_line_split[7:13]
;   print,instrument_line_split[next_index+3]
   orientations = instrument_line_split[next_index+3:*]
   *self.xtal_orientation_ptr =  {  hu:fix(orientations[0]),         $
                                    ku:fix(orientations[1]),         $
                                    lu:fix(orientations[2]),         $
                                    angle:double(orientations[3]),   $
                                    hv:fix(orientations[4]),         $
                                    kv:fix(orientations[5]),         $
                                    lv:fix(orientations[6])          }

endif else begin
   ; Fill up the instrument_ptr...
   n_inst = n_elements(rem_instrument_line_split)
   if n_inst gt 0 then begin
      s = create_struct(rem_instrument_line_split[0], $
         double(instrument_line_split[7]))
   endif
   if n_inst gt 1 then begin
      for i = 1,n_inst-1 do begin
         s = create_struct(s,rem_instrument_line_split[i],  $
               double(instrument_line_split[7+i]))
      endfor
   endif
   *self.instrument_ptr = s
endelse

; Identify the line number at which the 'data' begins based on the type of
; scan.
case self.scan of
'I':     nheader_lines = 12
'B':     nheader_lines = 18
'Q':     nheader_lines = 11
'ADD':   nheader_lines = 11
else:
endcase

header_info = text_data[0:nheader_lines-1]
*self.header_ptr = header_info
titles = strsplit(text_data[nheader_lines],/extract)
ntitles = n_elements(titles)
data_length = file_length-nheader_lines-1


if data_length eq 1 then begin
   strout = 'File: '+self.filename+' has a single data point'
   void = dialog_message(strout,/information)
endif

; For I and B buffers, read in the motor controls
nmotor = 0
if self.scan eq 'I' or self.scan eq 'B' then begin
   if self.scan eq 'I' then start = 5
   if self.scan eq 'B' then start = 11
   motor = dblarr(data_length,6)
   for j = 0,5 do begin
      ; Parse the line
      motor_line = double(strsplit(text_data[start+j],/extract))
      motor[*,j] = motor_line[1]+motor_line[2]*dindgen(data_length)
      label = 'A'+strtrim(string(j+1),2)
      void = where(titles eq label,inDarray)
      if (~inDarray) then begin
          ;; values for this motor are not in darray, so make a note
          mindex = (n_elements(mindex) eq 0)? j : [mindex,j]
          mtitles = (n_elements(mtitles) eq 0)? label : [mtitles,label]
      endif
   endfor
;   label = 'A1'
;   motor_struct = create_struct(label,motor[*,0])
;   for j = 0,5 do begin
;      label = 'A'+strtrim(string(j+1),2)
;      motor_struct = create_struct(motor_struct,label,motor[*,j])
;   endfor
;   *self.motors_ptr = motor_struct
   
endif

nmotor = n_elements(mindex)
darray = dblarr(data_length,nmotor+ntitles+1)

;; copy data columns to data array
for i = 0,data_length-1 do begin
    darray[i,nmotor+0:nmotor+ntitles-1] = $
      double(strsplit(text_data[nheader_lines+i+1],/extract))
endfor

;; if applicable, add motor data from header to data array and update titles
if (nmotor gt 0) then begin
    for i = 0,nmotor -1 do begin
        ;; copy the motor data to the data array
        darray[*,i] = motor[*,mindex[i]]
    endfor
    titles = [mtitles,titles]   ; update titles to include motors added
    ntitles = n_elements(titles)
endif

; For B buffers get the lattice parameters
if self.scan eq 'B' then begin
   lattice_nums = double(strsplit(text_data[5],/extract))
   lattice =   {  a:lattice_nums[0],      $
                  b:lattice_nums[1],      $
                  c:lattice_nums[2],      $
                  alpha:lattice_nums[3],  $
                  beta:lattice_nums[4],   $
                  gamma:lattice_nums[5]   }
   *self.lattice_ptr = lattice
endif

; For Q or B buffers get the energy and q setup information out
if self.scan eq 'Q' or self.scan eq 'B' then begin
   line_index = 8;7
   e_nums = double(strsplit(text_data[line_index-1],/extract))
   em = strpos(text_data[line_index],' EM ')
   an = strpos(text_data[line_index],' EA ')
   tags = ['E_center','Delta_E','EM','M_DSP','A_DSP','TEMP_START','TEMP_INC']
   if em[0] ne -1 then tags[2] = 'EM'
   if an[0] ne -1 then tags[2] = 'EA'
   ntags = n_elements(tags)
   s = create_struct(tags[0],e_nums[0])
   for j = 1,6 do s = create_struct(s,tags[j],e_nums[j])
   *self.econfig_ptr = s

   next_index = 9
   q_nums = double(strsplit(text_data[next_index],/extract))
   qtags = ['h_cen','k_cen','l_cen','dh','dk','dl','hfield']
   ntags = n_elements(qtags)
   sq = create_struct(qtags[0],q_nums[0])
   for j = 1,6 do sq = create_struct(sq,qtags[j],q_nums[j])
   *self.qconfig_ptr = sq
endif

for i = 0,ntitles-1 do begin
   for j = 0,n_forbidden-1 do titles[i] = dtas_remove_char(titles[i],forbidden_char[j])
endfor

; Make copy of Counts column an call it 'Signal' and add it to the end
cntInd = where(strupcase(titles) eq 'COUNTS',okay)
if (okay) then begin
    darray[*,ntitles] = darray[*,cntInd]
    titles = [titles,'Signal']
    ntitles++
endif

; Write DARRAY into a structure
s = create_struct(titles[0],ptr_new(darray[*,0]))
for i = 1,ntitles-1 do begin
   s = create_struct(s, titles[i],ptr_new(darray[*,i]))
endfor
; Is there an 'ERROR' column?
tags = tag_names(s)
ok = where(strupcase(tags) eq 'ERROR',count_error)
if count_error eq 0 then begin
   error = sqrt(darray[*,ntitles-1])
   bad = where(error eq 0.0,count_bad)
   if count_bad gt 0 then error[bad] = 1.0
   s = create_struct(s,'ERROR',ptr_new(error))
   ntitles = ntitles+1
endif

; Stick a monitor column in too!
where_mon = where(strupcase(titles) eq 'MON',count_mon)
if count_mon eq 0 then begin
   new_array = replicate(self.tot_mon,data_length)
   s = create_struct('MON',ptr_new(new_array),s)
endif
; Finally add an index column (first)
s = create_struct('INDEX',ptr_new(dindgen(data_length)),s)
*self.data_ptr = s
ret = self->get_property(display_name = display_name)
new_treatment = 'Raw data file read in: '+display_name
ret = self->update_treatment(new_treatment)

; Determine which of the independent variables is varying
ntitles = n_tags(*self.data_ptr)
titles = tag_names(*self.data_ptr)

count_index = ntitles-2
imax = -1
for i = count_index-1,2,-1 do begin
   col = *((*self.data_ptr).(i))
   n = n_elements(col)
   if n gt 1 then begin
      if col[1] ne col[2] then imax = i
   endif else begin
      imax = i
   endelse
endfor

x = ptr_new(*(*self.data_ptr).(imax))
xtitle = titles[imax]
y = ptr_new(*(*self.data_ptr).(ntitles-2))
dy = ptr_new(*(*self.data_ptr).(ntitles-1))
ytitle = titles[ntitles-2]

mon_counts = strtrim(string(self.tot_mon,format = '(e15.3)'),2)
ytitle = 'COUNTS PER '+mon_counts+' MONITOR'
self.ytitle = ytitle
plot_str = {x:x,y:y,dy:dy,anaMode:0,xtitle:xtitle,ytitle:self.ytitle,title:display_name}
*self.plot_ptr = plot_str
; Set the descriptive variable to the average temperature of the file
; as a starting point (default).
ret = self->udpate_descriptr(/temperature)
ret = self->get_hfield()

ret = self->get_property(descriptr_str = d)


; Load in the monitor correction factor data
if n_elements(*self.econfig_ptr) ne 0 then begin
   dsp = (*self.econfig_ptr).m_dsp
   this_format = '(f10.3)'
   case strtrim(string(dsp,format = this_format),2) of
   '3.354':   $
      begin
         filename = !DAVE_AUXILIARY_DIR+'monitor_correction_factor.txt'
;         if file_which('monitor_correction_factor.txt') eq '' then begin
;            filename = 'monitor_correction_factor.txt'
;         endif else begin
;            filename = file_which('monitor_correction_factor.txt')
;         endelse
         ret = self->read_mcf(filename)
      end
   else:
   endcase
endif
;case strupcase(self.extension) of
;'BT2':   $
;   begin
;      if file_which('monitor_correction_factor.txt') eq '' then begin
;         filename = 'monitor_correction_factor.txt'
;      endif else begin
;         filename = file_which('monitor_correction_factor.txt')
;      endelse
;      ret = self->read_mcf(filename)
;   end
;else:
;endcase
catch,/cancel
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::shift_spectrum,value
if n_params() ne 0 then begin
   shift_value = value
   self.shift_value = value
endif else begin
   shift_value = self.shift_value
endelse
plot_str = *self.plot_ptr
xtitle = plot_str.xtitle
data = *self.data_ptr
tags = tag_names(data)
x_index = where(strupcase(tags) eq strupcase(xtitle),count)
if count eq 0 then return,0
*data.(x_index) = *data.(x_index) + shift_value
*self.data_ptr = data
*plot_str.x = *data.(x_index)
*self.plot_ptr = plot_str
new_treatment = 'Spectrum shifted by: '+strtrim(string(shift_value),2)
ret = self->update_treatment(new_treatment)
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::read_mcf,filename
if file_test(filename) eq 0 then return,0
openr,lun,filename,/get_lun
s = ''
counter = 0
while not eof(lun) do begin
   readf,lun,s
   s_split = double(strsplit(s,/extract))
   if counter eq 0 then mcf = s_split else $
      mcf = [[mcf],[s_split[0],s_split[1]]]
   counter = counter + 1
endwhile
free_lun,lun,/force
*self.mcf_ptr = mcf
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::get_private, econfig_ptr = econfig_ptr,                $
  qconfig_ptr = qconfig_ptr,                $
  collim_ptr = collim_ptr,                  $
  mosaic_ptr = mosaic_ptr,                  $
  motors_ptr = motors_ptr,                  $
  shift_value = shift_value,                $
  header_ptr = header_ptr,                  $
  data_file_contents = data_file_contents,  $
  add = add,                                $
  extension = extension,                    $
  scan = scan,                              $
  prf = prf,                                $
  tot_mon = tot_mon,                        $
  base = base,                              $
  num_pts = num_pts,                        $
  type = type,                              $
  date = date,                              $
  time = time,                              $
  comments = comments,                      $
  fit_ptr = fit_ptr,                        $
  mon = mon,                                $
  plot_ptr = plot_ptr,                      $
  mcf_ptr = mcf_ptr,                        $
  instrument_ptr = instrument_ptr,          $
  lattice_ptr = lattice_ptr,                $
  xtal_orientation_ptr = xtal_orientation_ptr, $
  treatment = treatment,                    $
  data_ptr = data_ptr,                      $
  display_name = display_name,              $
  signal_type = signal_type,                $
  descriptr = descriptr,                    $
  hfield = hfield,                          $
  second_var_name = second_var_name,        $
  orientation_ptr=orientation_ptr $
  ,fixedEType=fixedEType $
  ,fixedEValue=fixedEValue $
  ,dSpaceM=dSpaceM $
  ,dSpaceA=dSpaceA $
  ,isICE=isICE $                ; is data from an ICE formated file? 0=>no, 1=>yes
  ,anaPkgStr=anaPkgStr $
  ,sdesc=sdesc $
  ,filename = filename

; It is assumed that all of the keywords are called here!
if n_elements(*self.data_ptr) ne 0 then header_ptr = self.header_ptr
if n_elements(*self.data_ptr) ne 0 then data_ptr = self.data_ptr
if n_elements(*self.econfig_ptr) ne 0 then econfig_ptr = self.econfig_ptr
if n_elements(*self.qconfig_ptr) ne 0 then qconfig_ptr = self.qconfig_ptr
if n_elements(*self.collim_ptr) ne 0 then collim_ptr = self.collim_ptr
if n_elements(*self.mosaic_ptr) ne 0 then mosaic_ptr = self.mosaic_ptr
if n_elements(*self.motors_ptr) ne 0 then motors_ptr = self.motors_ptr
if n_elements(*self.descriptr) ne 0 then descriptr = self.descriptr
if n_elements(*self.data_file_contents) ne 0 then $
   data_file_contents = self.data_file_contents
if (n_elements(*self.orientation_ptr) ne 0) then orientation_ptr = self.orientation_ptr
if (n_elements(*self.anaPkgPtr) ne 0) then anaPkgStr = (*self.anaPkgPtr)

fixedEType = self.fixedEType
fixedEValue = self.fixedEValue
dSpaceM = self.dSpaceM
dSpaceA = self.dSpaceA
isICE = self.isICE
sdesc = self.sdesc
second_var_name = self.second_var_name
shift_value = self.shift_value
signal_type = self.signal_type
add = self.add
scan = self.scan
extension = self.extension
prf = self.prf
tot_mon = self.tot_mon
base = self.base
num_pts = self.num_pts
type = self.type
date = self.date
time = self.time
comments = self.comments
hfield = self.hfield
display_name = self.display_name
if n_elements(*self.fit_ptr) ne 0 then fit_ptr = self.fit_ptr
mon = self.mon
if n_elements(*self.plot_ptr) ne 0 then plot_ptr = self.plot_ptr
if n_elements(*self.mcf_ptr) ne 0 then mcf_ptr = self.mcf_ptr
if n_elements(*self.instrument_ptr) ne 0 then $
   instrument_ptr = self.instrument_ptr
if n_elements(*self.lattice_ptr) ne 0 then $
   lattice_ptr = self.lattice_ptr
if n_elements(*self.xtal_orientation_ptr) ne 0 then $
   xtal_orientation_ptr = self.xtal_orientation_ptr
if n_elements(*self.treatment_ptr) ne 0 then treatment = *self.treatment_ptr
filename = self.filename
return,0
end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::set_private, econfig = econfig,                        $
  qconfig = qconfig,                        $
  collim = collim,                          $
  mosaic = mosaic,                          $
  motors = motors,                          $
  shift_value = shift_value,                $
  data_file_contents = data_file_contents,  $
  add = add,                                $
  scan = scan,                              $
  prf = prf,                                $
  tot_mon = tot_mon,                        $
  base = base,                              $
  num_pts = num_pts,                        $
  type = type,                              $
  extension = extension,                    $
  date = date,                              $
  time = time,                              $
  comments = comments,                      $
  fit_ptr = fit_ptr,                        $
  mon = mon,                                $
  header_ptr = header_ptr,                  $
  plot_ptr = plot_ptr,                      $
  mcf_ptr = mcf_ptr,                        $
  instrument_ptr = instrument_ptr,          $
  lattice_ptr = lattice_ptr,                $
  descriptr = descriptr,                    $
  xtal_orientation_ptr = xtal_orientation_ptr, $
  treatment = treatment,                    $
  _data = _data,                            $
  display_name = display_name,              $
  signal_type = signal_type,                $
  hfield = hfield,                          $
  second_var_name = second_var_name,        $
  orientation_ptr=orientation_ptr $
  ,fixedEType=fixedEType $
  ,fixedEValue=fixedEValue $
  ,dSpaceM=dSpaceM $
  ,dSpaceA=dSpaceA $
  ,isICE=isICE $                ; is data from an ICE formated file? 0=>no, 1=>yes
  ,anaPkgStr=anaPkgStr $
  ,sdesc=sdesc $
  ,filename = filename

if (n_elements(fixedEType) ne 0) then self.fixedEType = fixedEType
if (n_elements(fixedEValue) ne 0) then self.fixedEValue = fixedEValue
if (n_elements(dSpaceM) ne 0) then self.dSpaceM = dSpaceM
if (n_elements(dSpaceA) ne 0) then self.dSpaceA = dSpaceA
if (n_elements(isICE) ne 0) then self.isICE = isICE
if (n_elements(sdesc) ne 0) then self.sdesc = sdesc

if n_elements(second_var_name) ne 0 then self.second_var_name = second_var_name
if n_elements(signal_type) ne 0 then self.signal_type = signal_type
if n_elements(hfield) ne 0 then self.hfield = hfield
if n_elements(shift_value) ne 0 then self.shift_value = shift_value
if n_elements(_data) ne 0 then begin
   ntags = n_tags(_data)
   if ntags gt 0 then begin
      names = tag_names(_data)
      var_ptr = ptrarr(ntags,/allocate_heap)
      for i = 0,ntags-1 do begin
         *var_ptr[i] = *(_data).(i)
      endfor
      s = create_struct(names[0],var_ptr[0])
      for i = 1,ntags-1 do begin
         s = create_struct(s, names[i],var_ptr[i])
      endfor
   endif
     *self.data_ptr = s
endif
if n_elements(extension) ne 0 then self.extension = extension
if n_elements(display_name) ne 0 then self.display_name = display_name
if n_elements(econfig) ne 0 then *self.econfig_ptr = econfig
if n_elements(qconfig) ne 0 then *self.qconfig_ptr = qconfig
if n_elements(collim) ne 0 then *self.collim_ptr = collim
if n_elements(mosaic) ne 0 then *self.mosaic_ptr = mosaic
if n_elements(motors) ne 0 then *self.motors_ptr = motors
if n_elements(data_file_contents) ne 0 then *self.data_file_contents = $
   data_file_contents
if (n_elements(anaPkgStr) gt 0) then (*self.anaPkgPtr) = anaPkgStr

if n_elements(add) ne 0 then self.add = add
if n_elements(scan) ne 0 then self.scan = scan
if n_elements(prf) ne 0 then self.prf = prf
if n_elements(tot_mon) ne 0 then self.tot_mon = tot_mon
if n_elements(base) ne 0 then self.base = base
if n_elements(num_pts) ne 0 then self.num_pts = num_pts
if n_elements(type) ne 0 then self.type = type
if n_elements(date) ne 0 then self.date = date
if n_elements(time) ne 0 then self.time = time
if n_elements(comments) ne 0 then self.comments = comments
if n_elements(descriptr) ne 0 then begin
   if n_elements(*descriptr) ne 0 then *self.descriptr = *descriptr
endif
if n_elements(header_ptr) ne 0 then begin
   if n_elements(*header_ptr) ne 0 then *self.header_ptr = *header_ptr
endif
if n_elements(fit_ptr) ne 0 then begin
   if n_elements(*fit_ptr) ne 0 then *self.fit_ptr = *fit_ptr
endif
if n_elements(mon) ne 0 then self.mon = mon
if n_elements(plot_ptr) ne 0 then begin
   if n_elements(*plot_ptr) ne 0 then begin
      plot_str = *plot_ptr
      ntags = n_tags(plot_str)
      nPtr = (n_tags(plot_str) eq 9)? 4 : 3
      if ntags gt 0 then begin
         names = tag_names(plot_str)
         var_ptr = ptrarr(nPtr,/allocate_heap)
         for i = 0,nPtr-1 do begin
            *var_ptr[i] = *plot_str.(i)
         endfor
         s = create_struct(names[0],var_ptr[0])
         for i = 1,nPtr-1 do begin
            s = create_struct(s, names[i],var_ptr[i])
         endfor
         for i = nPtr,ntags-1 do begin
            s = create_struct(s,names[i],plot_str.(i))
         endfor
      endif
     *self.plot_ptr = s
   endif
endif
if n_elements(mcf_ptr) ne 0 then begin
   if n_elements(*mcf_ptr) ne 0 then *self.mcf_ptr = *mcf_ptr
endif
if n_elements(instrument_ptr) ne 0 then begin
   if n_elements(*instrument_ptr) ne 0 then *self.instrument_ptr = *instrument_ptr
endif
if n_elements(lattice_ptr) ne 0 then begin
   if n_elements(*lattice_ptr) ne 0 then *self.lattice_ptr = *lattice_ptr
endif
if n_elements(xtal_orientation_ptr) ne 0 then $
   *self.xtal_orientation_ptr = *xtal_orientation_ptr
if n_elements(treatment) ne 0 then *self.treatment_ptr = treatment
if n_elements(filename) ne 0 then self.filename = filename
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::clone
ret = self->get_private(   econfig_ptr = econfig_ptr,                $
                           qconfig_ptr = qconfig_ptr,                $
                           collim_ptr = collim_ptr,                  $
                           mosaic_ptr = mosaic_ptr,                  $
                           header_ptr = header_ptr,                  $
                           motors_ptr = motors_ptr,                  $
                           data_file_contents = data_file_contents,  $
                           data_ptr = data_ptr,                      $
                           add = add,                                $
                           scan = scan,                              $
                           prf = prf,                                $
                           tot_mon = tot_mon,                        $
                           base = base,                              $
                           num_pts = num_pts,                        $
                           type = type,                              $
                           date = date,                              $
                           time = time,                              $
                           extension = extension,                    $
                           comments = comments,                      $
                           fit_ptr = fit_ptr,                        $
                           mon = mon,                                $
                           shift_value = shift_value,                $
                           plot_ptr = plot_ptr,                      $
                           mcf_ptr = mcf_ptr,                        $
                           instrument_ptr = instrument_ptr,          $
                           lattice_ptr = lattice_ptr,                $
                           xtal_orientation_ptr = xtal_orientation_ptr, $
                           treatment = treatment,                    $
                           display_name = display_name,              $
                           signal_type = signal_type,                $
                           descriptr = descriptr,                    $
                           hfield = hfield,                          $
                           second_var_name = second_var_name,        $
                           orientation_ptr=orientation_ptr $
                           ,fixedEType=fixedEType $
                           ,fixedEValue=fixedEValue $
                           ,dSpaceM=dSpaceM $
                           ,dSpaceA=dSpaceA $
                           ,isICE=isICE $ ; is data from an ICE formated file? 0=>no, 1=>yes
                           ,anaPkgStr=anaPkgStr $
                           ,sdesc=sdesc, $
                           filename = filename                       )
if n_elements(data_ptr) ne 0 then begin
   if n_elements(*data_ptr) ne 0 then data = *data_ptr
endif
if n_elements(econfig_ptr) ne 0 then begin
   if n_elements(*econfig_ptr) ne 0 then econfig = *econfig_ptr
endif
if n_elements(qconfig_ptr) ne 0 then begin
   if n_elements(*qconfig_ptr) ne 0 then qconfig = *qconfig_ptr
endif
if n_elements(collim_ptr) ne 0 then begin
   if n_elements(*collim_ptr) ne 0 then collim = *collim_ptr
endif
if n_elements(mosaic_ptr) ne 0 then begin
   if n_elements(*mosaic_ptr) ne 0 then mosaic = *mosaic_ptr
endif
if n_elements(motors_ptr) ne 0 then begin
   if n_elements(*motors_ptr) ne 0 then motors = *motors_ptr
endif
if n_elements(data_file_contents) ne 0 then begin
   if n_elements(*data_file_contents) ne 0 then data_file_contents = *data_file_contents
endif

oclone = obj_new('dtas_data')
ret = oclone->set_private(       econfig = econfig,                        $
                                 qconfig = qconfig,                        $
                                 collim = collim,                          $
                                 mosaic = mosaic,                          $
                                 header_ptr = header_ptr,                  $
                                 motors = motors,                          $
                                 _data = data,                              $
                                 data_file_contents = data_file_contents,  $
                                 add = add,                                $
                                 scan = scan,                              $
                                 prf = prf,                                $
                                 shift_value = shift_value,                $
                                 tot_mon = tot_mon,                        $
                                 base = base,                              $
                                 num_pts = num_pts,                        $
                                 type = type,                              $
                                 date = date,                              $
                                 time = time,                              $
                                 comments = comments,                      $
                                 fit_ptr = fit_ptr,                        $
                                 mon = mon,                                $
                                 plot_ptr = plot_ptr,                      $
                                 mcf_ptr = mcf_ptr,                        $
                                 instrument_ptr = instrument_ptr,          $
                                 lattice_ptr = lattice_ptr,                $
                                 xtal_orientation_ptr = xtal_orientation_ptr, $
                                 treatment = treatment,                    $
                                 extension = extension,                    $
                                 display_name = display_name,              $
                                 signal_type = signal_type,                $
                                 descriptr = descriptr,                    $
                                 hfield = hfield,                          $
                                 second_var_name = second_var_name,        $
                                 orientation_ptr=orientation_ptr $
                                 ,fixedEType=fixedEType $
                                 ,fixedEValue=fixedEValue $
                                 ,dSpaceM=dSpaceM $
                                 ,dSpaceA=dSpaceA $
                                 ,isICE=isICE $ ; is data from an ICE formated file? 0=>no, 1=>yes
                                 ,anaPkgStr=anaPkgStr $
                                 ,sdesc=sdesc, $
                                 filename = filename)
return,oclone
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function dtas_data::init,  filename = filename,       $
                           signal_type = signal_type, $
                           read = read
if n_elements(filename) eq 0 then filename = ''
if n_elements(signal_type) eq 0 then signal_type = 'SIGNAL'
self.signal_type = signal_type
self.scan = ''
self.filename = filename
self.prf = 0L
self.mon = 0L
self.tot_mon = 0L
self.base = ''
self.num_pts = 0
self.type = ''
self.date = ''
self.time = ''
self.display_name = ''
self.second_var_name = 'Temperature'
self.mcf_ptr = ptr_new(/allocate_heap)
self.hfield = 0D
self.shift_value = 0D
self.header_ptr = ptr_new(/allocate_heap)
self.fit_ptr = ptr_new(/allocate_heap)
self.collim_ptr = ptr_new(/allocate_heap)
self.motors_ptr = ptr_new(/allocate_heap)
self.mosaic_ptr = ptr_new(/allocate_heap)
self.data_ptr = ptr_new(/allocate_heap)
self.econfig_ptr = ptr_new(/allocate_heap)
self.qconfig_ptr = ptr_new(/allocate_heap)
self.lattice_ptr = ptr_new(/allocate_heap)
self.orientation_ptr = ptr_new(/allocate_heap)
self.instrument_ptr = ptr_new(/allocate_heap)
self.treatment_ptr = ptr_new(/allocate_heap)
self.plot_ptr = ptr_new(/allocate_heap)
self.xtal_orientation_ptr = ptr_new(/allocate_heap)
self.data_file_contents = ptr_new(/allocate_heap)
self.anaPkgPtr = ptr_new(/allocate_heap)
self.descriptr = ptr_new(/allocate_heap)
self.ytitle = 'COUNTS'
self.extension = ''
if self.filename ne '' then begin

   ret = self->read_file()
   if ret ne 1 then begin
      self->cleanup
      return,0
   endif
endif

return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro dtas_data__define
  class =  {  dtas_data                    $
              ,data_file_contents:ptr_new() $
              ,display_name:''             $
              ,data_ptr:ptr_new()           $
              ,extension:''                 $
              ,add:0B                      $
              ,scan:''                      $
              ,prf:0L                       $
              ,tot_mon:0L                   $
              ,base:''                      $
              ,num_pts:0                    $
              ,type:''                      $
              ,date:''                      $
              ,time:''                      $
              ,comments:''                  $
              ,header_ptr:ptr_new()         $
              ,fit_ptr:ptr_new()            $
              ,descriptr:ptr_new()          $
              ,mon:0L                       $
              ,signal_type:''               $
              ,ytitle:''                    $
              ,hfield:0D                    $
              ,shift_value:0D               $
              ,plot_ptr:ptr_new()           $
              ,mcf_ptr:ptr_new()            $
              ,collim_ptr:ptr_new()         $
              ,econfig_ptr:ptr_new()        $
              ,qconfig_ptr:ptr_new()        $
              ,mosaic_ptr:ptr_new()         $
              ,instrument_ptr:ptr_new()     $
              ,motors_ptr:ptr_new()         $
              ,lattice_ptr:ptr_new()        $
              ,xtal_orientation_ptr:ptr_new()  $
              ,second_var_name:''           $
              ,treatment_ptr:ptr_new()      $
              ,orientation_ptr:ptr_new() $
              ,fixedEType:'' $
              ,fixedEValue:0.0 $
              ,dSpaceM:0.0 $
              ,dSpaceA:0.0 $
              ,isICE:0B $       ; is data from an ICE formated file? 0=>no, 1=>yes
              ,anaPkgPtr:ptr_new() $ ; info about BT7 analyzer package
              ,sdesc:'' $
              ,filename:'' $
           }
  
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro dtas_data_test, Q = Q, I = I, B = B, A = A
; Simple test program for the
dir = 'c:\dimeo\data\TAS_DATA\'
if n_elements(A) eq 0 then A = 0
if n_elements(Q) eq 0 then Q = 0
if n_elements(I) eq 0 then I = 0
if n_elements(B) eq 0 then B = 0
if Q+I+B eq 0 then Q = 1
Q_file = 'GCSNI047.BT2'
if Q ne 0 then filename = dir+Q_file;'PZN2J042.BT2';      A Q buffer
if I ne 0 then filename = dir+'MNCO1001.BT9';     An I buffer
if B ne 0 then filename = dir+'UCDMN025.BT2';     A B buffer
if A ne 0 then filename = dir+'alignment_curve_1.txt';'mn123036.add'
o = obj_new('dtas_data',filename = filename)
;ret = o->read_file()
; If appropriate, correct the data for the resolution volume
;ret = o->fast_background_subtraction(2.0)
;ret = o->resolution_correction()
;ret = o->detailed_balance()
;ret = o->monitor_correction_factor()
;ret = o->get_property(treatment = treatment,var_names = var_names)
ret = o->get_private(type = type,scan = scan)
;print,'Type: ',type
;print,'Scan: ',scan
ret = o->display(psym = 4)
;obj_destroy,o
;window,0
;ret = o->auto_gauss_fit(psym = 4)

;print,'Valid o: ',obj_valid(o)
oclone = o->clone()
;ret = oclone->set_property(xvar_name = 'A3')
;window,1
;;ret = oclone->auto_gauss_fit(psym = 6)
;ret = oclone->display(psym = 6)
;ret = oclone->get_property(contents = contents,treatment = treatment)
obj_destroy,[o,oclone]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro dtas_ice_test
dir = 'C:\bhd\dave_development\dave\programs\testing\ICE\'
file = dir + 'e-sca1348.bt0'
file = dir + 'i-sca1353.bt0'  ;  problem file
file = dir + 'q-sca1346.bt0'

o = obj_new('dtas_data',filename = file)

obj_destroy,o
end
