;###############################################################################
;
; NAME:
;  MARSREDUCTION__DEFINE
;
; PURPOSE:
;  See description below.
;
; CATEGORY:
;  DAVE, mars, data reduction
;
; AUTHOR:
;
;PD Dr. Philip Tregenna-Piggott,
;Laboratory for Neutron Scattering,
;ETHZ and Paul-Scherrer Institute,
;CH-5232 Villigen PSI,
;Switzerland.
;
;Tel. :+41 56 310 54 05
;Fax. :+41 56 310 29 39
;Email:philip.tregenna@psi.ch
;
;Based on the Program HFBSREDUCTION__DEFINE by:
;   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.
;
;###############################################################################
;+
; NAME:
;       MARSREDUCTION__DEFINE
;
; PURPOSE:
;
;       This object widget program performs the data reduction steps for
;   data sets collected on the Direct Geometry TOF Spectrometer MARS, at SINQ, PSI.
;   This program is meant to run in the DAVE environment.
;
; AUTHOR:
;
;PD Dr. Philip Tregenna-Piggott,
;Laboratory for Neutron Scattering,
;ETHZ and Paul-Scherrer Institute,
;CH-5232 Villigen PSI,
;Switzerland.
;
;Tel. :+41 56 310 54 05
;Fax. :+41 56 310 29 39
;Email:philip.tregenna@psi.ch
;
; CATEGORY:
;
;       Objects, widgets, data reduction, DAVE software
;
; CALLING SEQUENCE:
;
;       object = obj_new('marsreduction')
;
;
; INPUT PARAMETERS:
;
;       NONE
;
; INPUT KEYWORDS:
;
;   GROUP_LEADER   - Parent widget of MARSREDUCTION object widget
;   NOTIFYID    - Vector of TOP and ID of calling widget
;   WORKDIR      - working directory, where DAVE and/or CON files will be put
;   DATDIR      - data directory, directory of raw data
;
; REQUIRED PROGRAMS:
;
;        DREBIN.PRO
;    OPAN_Q_REBIN_WIDGET.PRO
;   opan_rebin_MARS_Energy_widget.pro
;   opan_MARS_time_rebin_widget.pro
;   marsDetGroupWidget.pro
;   MARS_graphical_masking.pro
;   MARS_scroll_spectra_masking.pro
;   MARS_PlotDiffractionData.pro
;
;
; COMMON BLOCKS:
;
;       NONE
;
; RESTRICTIONS
;
;       NONE
;
; OBJECT METHODS:
;
; There are no explicitly private object methods in IDL but the
; methods used in this class are divided into PUBLIC and PRIVATE
; to indicate which ones should be used by users who wish to run
; the program from the command line, for instance.  Execution of
; the program's controls from the command line is described in the
; example below.
;
; PUBLIC OBJECT PROCEDURE METHODS:
;
;
;
; PRIVATE OBJECT PROCEDURE METHODS:
;
;
; EXAMPLE
;
;
; MODIFICATION HISTORY:
;
;       Written by Philip Tregenna-Piggott, 23 June, 2006.
;-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Obtain programs (Filges and Koennecke) to read in the hdf files
@napi45
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsReductionCleanup,tlb
widget_control,tlb,get_uvalue = self
if obj_valid(self) then begin
  s = size(self->getNotifyIds())
  if s[0] ne 0 then begin
    if s[0] eq 1 then count = 0 else count = s[2]-1
    for j = 0,count do begin
      marsInfo = {marsReductionEvent,$
                            ID:(self->getNotifyIds())[0,j],$
                            Top:(self->getNotifyIds())[1,j],$
                            Handler:0l,$
                            daveFiles:self->getDaveFiles()}
      if widget_info((self->getNotifyIds())[0,j],/valid_id) then begin $
        widget_control,(self->getNotifyIds())[0,j],send_event = marsInfo
      endif
    endfor
  endif else begin
    ;obj_destroy,self
  endelse
endif
obj_destroy,self
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function marsreduction::GetMARSConstants,filename

if file_test(filename) eq 0 then begin
filefound=0
constants={filefound:filefound}
return,constants
endif else begin
filefound=1
constants={filefound:filefound}
endelse
line=''
Constants_str='Constants'
openr,lun,filename,/get_lun
while eof(lun) eq 0 do begin
readf,lun,line
Constants_str=[Constants_str,line]
endwhile
free_lun,lun,/force
Constants_str=Constants_str[1:*]
n=n_elements(Constants_str)
for i = 0,n-1 do begin
ConstantName=strtrim((strsplit(Constants_str[i],'=',/extract))[0],2)
ConstantString=strtrim((strsplit(Constants_str[i],'=',/extract))[1],2)
    if strpos(ConstantString,',') eq -1 then begin
    ConstantValue=double(ConstantString)
    endif else begin
    ConstantString=strtrim((strsplit(ConstantString,',',/extract)),2)
    ConstantValue=double(ConstantString)
    endelse
constants=create_struct(constants,ConstantName,ConstantValue)
endfor
constants=create_struct(constants,name='MARSConstants')
return,constants

end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function marsreduction::GetMARSTimeOffsets,filename

if file_test(filename) eq 0 then begin
filefound=0
timeoffsets={filefound:filefound}
return,timeoffsets
endif else begin
filefound=1
timeoffsets={filefound:filefound}
endelse

line=''
timeoffsets_str='timeoffsets'
openr,lun,filename,/get_lun
while eof(lun) eq 0 do begin
readf,lun,line
timeoffsets_str=[timeoffsets_str,line]
endwhile
free_lun,lun,/force
timeoffsets_str=timeoffsets_str[1:*]
n=n_elements(timeoffsets_str)
if n ne 7 then begin
filefound=0
timeoffsets={filefound:filefound}
return,timeoffsets
endif
valid_names=['master1_timeoffset', $
         'master2_timeoffset', $
         'master3_timeoffset', $
         'master4_timeoffset', $
         'master5_timeoffset', $
         'master6_timeoffset', $
         'master7_timeoffset']
for i = 0,n-1 do begin
Name=strtrim((strsplit(timeoffsets_str[i],'=',/extract))[0],2)
void=where(strmatch(valid_names,name) eq 1,count)
if count eq 0 then begin
filefound=0
timeoffsets={filefound:filefound}
return,timeoffsets
endif
Value=double(strtrim((strsplit(timeoffsets_str[i],'=',/extract))[1],2))
timeoffsets=create_struct(timeoffsets,Name,Value)
endfor
timeoffsets=create_struct(timeoffsets,name='MARSTimeOffsets')

return,timeoffsets
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function marsreduction::getDaveFiles
return,self.daveFiles
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::cleanup
; First let's restore the colors
tvlct,*self.rPtr,*self.gPtr,*self.bPtr
device,decomposed = self.old_dc
;
; Now free up the pointers
ptr_free,self.odataPtr,self.oerrorPtr
ptr_free,self.oxvalsPtr,self.oyvalsPtr
ptr_free,self.dataPtr,self.errorPtr
ptr_free,self.xvalsPtr,self.yvalsPtr
ptr_free,self.notifyIdPtr;,self.daveFiles
ptr_free,self.rPtr,self.bPtr,self.selDetPtr
ptr_free,self.pgroup_leader,self.sigFilePtr
ptr_free,self.vanFilePtr,self.bgFilePtr
ptr_free,self.tempPtr,self.treatmentPtr,self.lambda_fieldPtr,self.oTOFMonitor2Ptr
ptr_free,self.TOFMonitor2Ptr,self.Mon_cumPtr,self.headerPtr,self.instrumentPtr
ptr_free,self.titlePtr,self.gPtr,self.good_detPtr,self.good_ElasticdetPtr
ptr_free,self.TOFMonitor3Ptr,self.ElasticdetPtr,self.TOFMonitor1Ptr
ptr_free,self.oElasticDataPtr,self.oElasticErrorPtr,self.oyvalselasticPtr
ptr_free,self.ElasticDataPtr,self.ElasticErrorPtr,self.yvalselasticPtr,self.ConstantsPtr
ptr_free,self.TOFMonitor2xPtr,self.TOFMonitor3xPtr,self.Vanadium_area_calc_arrayPtr
ptr_free,self.Vanadium_Lambda_arrayPtr,self.Vanadium_Area_ArrayPtr,self.Vanadium_PolyFitArrayPtr
ptr_free,self.timeoffsetsPtr,self.wr_arrayPtr,self.xvalsElasticPtr,self.ElasticDetectorsNamesPtr
;
;
; Delete any pixmap windows
wdelete,self.winPix
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::quit,event = event
; Widget, destroy thyself
widget_control,self.tlb,/destroy
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::selSigFiles,event = event
files = dialog_pickfile(dialog_parent = event.top,/read, $
                               filter = ['*.hdf'],$
                               title = 'Select raw signal data file(s)',$
                               path = self.datDir, $
                               /multiple_files)
;print,'files =',files
nfiles = n_elements(files)
if (1.0*total(file_test(files,/regular)) ne nfiles) then begin
  void = dialog_message(dialog_parent = event.top,/information, $
   'At least one of the selected files is invalid')
  return
endif
*self.sigFilePtr = files
delim=path_sep()
nfiles = n_elements(files)
dispFiles = strarr(nfiles)
for i = 0,nfiles-1 do begin
  text = files[i]
  textLen = strlen(text)
;we must somehow try and recognise a standard mars file
     delimpos=strpos(text,delim,/reverse_search)
    pointpos=strpos(text,'.',/reverse_search)
    length=pointpos-delimpos-1
     if strlowcase(strmid(text,(textlen-11),1)) eq 'n' and $
  strlowcase(strmid(text,(textlen-19),4)) eq 'mars' and $
  length eq 15 then begin
    pos = textLen-10
    dispFiles[i] = strmid(text,pos,6)
  endif else begin
    dispFiles[i] =strmid(text,(delimpos+1),length)
    endelse
endfor
widget_control,self.fileText,set_value = dispFiles
;
;
;
  filename_result = strsplit(files[0],path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)

  widget_control, self.runGroup, get_value=runGroup
;if only one file selected then switch to single sample runs
if rungroup eq 1 and nfiles eq 1 then begin
rungroup=0
  widget_control, self.runGroup, set_value=runGroup
endif
      if runGroup eq 1 then filename+='++'   ;set to 'sum runs'
widget_control, self.stem1, set_value=filename
widget_control, self.diffstem1, set_value=filename

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::selSigRuns,event = event
  widget_control, self.Signal_runs, get_value=strdets
;print,'strdets =',strdets
dets=opan_selectgroups_mars_runs(strdets,group_leader = event.top)
;print,'dets =',dets

nfiles=n_elements(dets)
C=strarr(nfiles)
for i = 0,nfiles-1 do begin
C(i)=strtrim(dets(i),2)
length=strlen(C(i))
zero_add=6-length
    for j=0,zero_add-1 do begin
    C(i)='0'+C(i)
    endfor
endfor
files_short=('*'+C+'.hdf')
files=strarr(nfiles)
;help,files
;help,i
;help,nfiles
;help,files_short
for i = 0, nfiles-1 do begin
;print,'i: ',i
files(i)=file_search(self.datDir,files_short(i))
;print,'files(i): ',files(i)
endfor
;
if (1.0*total(file_test(files,/regular)) ne nfiles) then begin
  void = dialog_message(dialog_parent = event.top,/information, $
   'At least one of the selected files is invalid')
  return
endif
;print, 'help,Sigfiles'
;help,files
*self.sigFilePtr = files
nfiles = n_elements(files)
dispFiles = strarr(nfiles)
for i = 0,nfiles-1 do begin
  text = files[i]
  textLen = strlen(text)
  pos = textLen-10
 ; pos = textLen
    dispFiles[i] = strmid(text,pos,6)
; dispFiles[i] = files(i)
endfor
widget_control,self.fileText,set_value = dispFiles
;
  filename_result = strsplit(files[0],path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)

  widget_control, self.runGroup, get_value=runGroup
;if only one file selected then switch to single sample runs
if rungroup eq 1 and nfiles eq 1 then begin
rungroup=0
  widget_control, self.runGroup, set_value=runGroup
endif
      if runGroup eq 1 then filename+='++'   ;set to 'sum runs'
widget_control, self.stem1, set_value=filename
widget_control, self.diffstem1, set_value=filename

return

end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::selBgFiles,event = event
files = dialog_pickfile(dialog_parent = event.top,/read, $
                               filter = ['*.hdf'],$
                               title = 'Select background data file(s)',$
                               path = self.datDir,$
                               /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,/information, $
   'At least one of the selected files is invalid')
  return
endif
*self.bgFilePtr = files
delim=path_sep()
nfiles = n_elements(files)
dispFiles = strarr(nfiles)
for i = 0,nfiles-1 do begin
  text = files[i]
  textLen = strlen(text)
;we must somehow try and recognise a standard mars file
     delimpos=strpos(text,delim,/reverse_search)
    pointpos=strpos(text,'.',/reverse_search)
    length=pointpos-delimpos-1
     if strlowcase(strmid(text,(textlen-11),1)) eq 'n' and $
  strlowcase(strmid(text,(textlen-19),4)) eq 'mars' and $
  length eq 15 then begin
    pos = textLen-10
    dispFiles[i] = strmid(text,pos,6)
  endif else begin
    dispFiles[i] =strmid(text,(delimpos+1),length)
    endelse
endfor

widget_control,self.bgText,set_value = dispFiles
;print, '*self.bgFilePtr =',*self.bgFilePtr
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::selEmptyRuns,event = event
  widget_control, self.Background_runs, get_value=strdets
;print,'strdets =',strdets
dets=opan_selectgroups_mars_runs(strdets)
;print,'dets =',dets

nfiles=n_elements(dets)
C=strarr(nfiles)
for i = 0,nfiles-1 do begin
C(i)=strtrim(dets(i),2)
length=strlen(C(i))
zero_add=6-length
    for j=0,zero_add-1 do begin
    C(i)='0'+C(i)
    endfor
endfor
files_short=('*'+C+'.hdf')
files=strarr(nfiles)
for i = 0, nfiles-1 do begin
files(i)=file_search(self.datDir,files_short(i))
endfor
;
if (1.0*total(file_test(files,/regular)) ne nfiles) then begin
  void = dialog_message(dialog_parent = event.top,/information, $
   'At least one of the selected files is invalid')
  return
endif
*self.bgFilePtr = files
nfiles = n_elements(files)
dispFiles = strarr(nfiles)
for i = 0,nfiles-1 do begin
  text = files[i]
  textLen = strlen(text)
  pos = textLen-10
 ; pos = textLen
    dispFiles[i] = strmid(text,pos,6)
; dispFiles[i] = files(i)
endfor
widget_control,self.bgText,set_value = dispFiles

;print, '*self.bgFilePtr =',*self.bgFilePtr

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::selVanFile,event = event
files = dialog_pickfile(dialog_parent = event.top,/read, $
                               filter = ['*.hdf'],$
                               title = 'Select vanadium data file',$
                               path = self.datDir,$
                               /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,/error,'The selected file is invalid')
  return
endif
*self.vanFilePtr = files
delim=path_sep()
nfiles = n_elements(files)
dispFiles = strarr(nfiles)
for i = 0,nfiles-1 do begin
  text = files[i]
  textLen = strlen(text)
;we must somehow try and recognise a standard mars file
     delimpos=strpos(text,delim,/reverse_search)
    pointpos=strpos(text,'.',/reverse_search)
    length=pointpos-delimpos-1
     if strlowcase(strmid(text,(textlen-11),1)) eq 'n' and $
  strlowcase(strmid(text,(textlen-19),4)) eq 'mars' and $
  length eq 15 then begin
    pos = textLen-10
    dispFiles[i] = strmid(text,pos,6)
  endif else begin
    dispFiles[i] =strmid(text,(delimpos+1),length)
    endelse
endfor
widget_control,self.vanText,set_value = dispFiles
;print, '*self.vanFilePtr =',*self.vanFilePtr
return
end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::selVanRun,event = event
  widget_control, self.Vanadium_run, get_value=strdets
;print,'strdets =',strdets

if strdets eq 'Automatic' then return

dets=opan_selectgroups_mars_runs(strdets)
;print,'dets =',dets
;help,dets
;dets=dets[0]
nfiles=n_elements(dets)
C=strarr(nfiles)
for i = 0,nfiles-1 do begin
C(i)=strtrim(dets(i),2)
length=strlen(C(i))
zero_add=6-length
    for j=0,zero_add-1 do begin
    C(i)='0'+C(i)
    endfor
endfor
files_short=('*'+C+'.hdf')
files=strarr(nfiles)
for i = 0, nfiles-1 do begin
files(i)=file_search(self.datDir,files_short(i))
endfor
;
if (1.0*total(file_test(files,/regular)) ne nfiles) then begin
  void = dialog_message(dialog_parent = event.top,/information, $
   'At least one of the selected files is invalid')
  return
endif
;print, 'help,Vfiles'
;help,files
;files=files[0]
*self.vanFilePtr = files
nfiles = n_elements(files)
dispFiles = strarr(nfiles)
for i = 0,nfiles-1 do begin
  text = files[i]
  textLen = strlen(text)
  pos = textLen-10
 ; pos = textLen
    dispFiles[i] = strmid(text,pos,6)
; dispFiles[i] = files(i)
endfor
widget_control,self.vanText,set_value = dispFiles
;
;

return

end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::Sum_Vandium_Runs,event = event,err = err

err = 0
if n_elements(*self.vanFilePtr) eq 0 then begin
  err = -1
  return
endif

files = *self.vanFilePtr
nfiles = n_elements(files)
;print,'nfiles = ',nfiles
treat = 'Files used in vanadium calibration:: '

for i = 0,nfiles-1 do begin
  treat = [treat,files[i]]
  self->Nexus_read_raw_mars,files[i],event = event,err = err
  if err eq 1 then return
  if i eq 0 then begin
    data = *self.dataPtr
    temperature = *self.tempPtr
    Mon_cum = *self.Mon_cumPtr
    TOFMonitor1 = *self.TOFMonitor1Ptr
    TOFMonitor2 = *self.TOFMonitor2Ptr
    TOFMonitor3 = *self.TOFMonitor3Ptr
  endif else begin
    data = data+*self.dataPtr
    temperature = [temperature,*self.tempPtr]
    Mon_cum = [Mon_cum,*self.Mon_cumPtr]
    TOFMonitor1+= *self.TOFMonitor1Ptr
    TOFMonitor2+= *self.TOFMonitor2Ptr
    TOFMonitor3+= *self.TOFMonitor3Ptr

  endelse
endfor


*self.treatmentPtr = [*self.treatmentPtr,treat]
error = sqrt(data)
where_zero = where(data eq 0,count_zero)
if count_zero gt 0 then error[where_zero] = 1.0
*self.errorPtr = error
*self.dataPtr = data
*self.Mon_cumPtr = Mon_cum
*self.TOFMonitor1Ptr = TOFMonitor1
*self.TOFMonitor2Ptr = TOFMonitor2
*self.TOFMonitor3Ptr = TOFMonitor3
*self.tempPtr = temperature


return

end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function marsreduction::getnotifyIds
return,*self.notifyIdPtr
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsReductionEvents,event
if dave_set_focus(event) then return
if tag_names(event,/structure_name) eq 'WIDGET_BASE' then begin
  widget_control,event.top,get_uvalue = self
  self->resize,event = event
  return
endif
widget_control,event.id,get_uvalue = cmd
call_method,cmd.method,cmd.object,event = event
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::plotInelasticData,event = event
if n_elements(*self.dataPtr) eq 0 then return
widget_control,self.grpSlider,get_value = val
if (size(*self.dataPtr))[0] eq 1 then val = 1
if val gt (size(*self.dataPtr))[2] then return
;print,'val =',val
;print,'(size(*self.dataPtr))[2] =',(size(*self.dataPtr))[2]
;val = fix(val[0])
;print,'val: ',val
z = reform((*self.dataPtr)[*,val-1])
zerr = reform((*self.errorPtr)[*,val-1])
x = (*self.xvalsPtr)
y = (*self.yvalsPtr)[val-1]
;print,'x =',x
;print,''
;print,'y =',y
;print,''
;print,'z =',z
;print,''
if self.autoscale eq 1 then begin
  self.xrange = [min(x),max(x)]
  dz = 0.1*(max(z)-min(z))
  self.yrange = [min(z)-max(zerr)-dz, $
                 max(z)+max(zerr)+dz]
endif
;print,self.xrange
;print,''
;print,self.yrange
;
widget_control,self.DataOutputTypesGroup,get_value = DataOutput
;
;
if y eq 0 then begin
title=strtrim((*self.headerPtr)[2],2)+', T = '+ $
       strtrim(string((*self.InstrumentPtr).temp),2)+' K, Inelastic Data: Sum Over All Detectors'
endif else begin
    if DataOutput eq 0 then begin
    title=strtrim((*self.headerPtr)[2],2)+', T = '+ $
       strtrim(string((*self.InstrumentPtr).temp),2)+' K, Inelastic Data: Q = '+strtrim(string(y),2)
    endif else begin
    title=strtrim((*self.headerPtr)[2],2)+', T = '+ $
       strtrim(string((*self.InstrumentPtr).temp),2)+' K, Inelastic Data: Phi Group = '+strtrim(string(val),2)
    endelse
endelse


;
purged=where(z ne -1.0,count)
if count ne 0 then begin
xpurge=x[purged]
zpurge=z[purged]
zerrpurge=zerr[purged]
plot,xpurge,zpurge,psym = 4,xrange = self.xrange,yrange = self.yrange, $
     xstyle = 1,ystyle = 1,xtitle = self.xlabel, ytitle = self.zlabel, title = title,color=1,background=12
errplot,xpurge,zpurge-zerrpurge,zpurge+zerrpurge,width = 0.0,color=1
endif else begin
plot,x,z,psym = 4,xrange = self.xrange,yrange = self.yrange, $
     xstyle = 1,ystyle = 1,xtitle = self.xlabel, ytitle = self.zlabel, title = title,color=1,background=12
errplot,x,z-zerr,z+zerr,width = 0.0,color=1
endelse
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::plotElasticData,event = event
if n_elements(*self.ElasticdataPtr) eq 0 then return
widget_control,self.DiffONGroup,get_value = DiffON
if DiffON ne 1 then return
widget_control,self.grpSlider,get_value = val
if (size(*self.dataPtr))[0] eq 1 then begin
InelasticChannels = 1
endif else begin
InelasticChannels=(size(*self.dataPtr))[2]
endelse
    if (size(*self.ElasticdataPtr))[0] eq 1 then begin
    ElasticChannels = 1
    endif else begin
    ElasticChannels=(size(*self.ElasticdataPtr))[2]
    endelse
if val gt InelasticChannels+ElasticChannels then return
if val le InelasticChannels then return
val-=InelasticChannels
;help,val
;help,(*self.ElasticdataPtr)

if ElasticChannels eq 1 then begin
z = *self.ElasticdataPtr
zerr = *self.ElasticErrorPtr
x = *self.xvalsElasticPtr
endif else begin
z = reform((*self.ElasticdataPtr)[*,val-1])
zerr = reform((*self.ElasticErrorPtr)[*,val-1])
x = reform((*self.xvalsElasticPtr)[*,val-1])
endelse

if self.autoscale eq 1 then begin
  self.xrange = [min(x),max(x)]
  dz = 0.1*(max(z)-min(z))
  self.yrange = [min(z)-max(zerr)-dz, $
                 max(z)+max(zerr)+dz]
endif

title = strtrim((*self.headerPtr)[2],2)+', T = '+ $
       strtrim(string((*self.InstrumentPtr).temp),2)+ $
       ' K, Elastic Data from Detector: '+(*self.ElasticDetectorsNamesPtr)[(*self.good_ElasticdetPtr)[val-1]]

plot,x,z,psym = 4,xrange = self.xrange,yrange = self.yrange, $
     xstyle = 1,ystyle = 1,xtitle = self.DiffractionXlabel, ytitle = self.zlabel, title = title,color=3,background=12
;plot,x,z,psym = 4,xrange = self.xrange,yrange = self.yrange, $
;     xstyle = 1,ystyle = 1, title = title,color=4,background = 12
;axis,yaxis = 0, ytitle = self.zlabel, xtitle = self.xlabel ,color=1
errplot,x,z-zerr,z+zerr,width = 0.0,color=3
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::plotMonitorData,event = event
widget_control,self.DiffONGroup,get_value = DiffON
widget_control,self.grpSlider,get_value = val
if (size(*self.dataPtr))[0] eq 1 then begin
InelasticChannels = 1
endif else begin
InelasticChannels=(size(*self.dataPtr))[2]
endelse
if DiffON eq 1 then begin
    if (size(*self.ElasticdataPtr))[0] eq 1 then begin
    ElasticChannels = 1
    endif else begin
    ElasticChannels=(size(*self.ElasticdataPtr))[2]
    endelse
endif else begin
ElasticChannels = 0
endelse
if val gt (InelasticChannels+ElasticChannels+2) then val = InelasticChannels+ElasticChannels+2
if val le InelasticChannels+ElasticChannels then return
val-=(InelasticChannels+ElasticChannels)
;
if val eq 1 then begin
z = *self.TOFMonitor2Ptr
zerr = sqrt(z)
x = *self.TOFMonitor2xPtr
title = strtrim((*self.headerPtr)[2],2)+', T = '+ $
       strtrim(string((*self.InstrumentPtr).temp),2)+' K, Spectrum of Upstream Monitor'
endif else begin
z = *self.TOFMonitor3Ptr
zerr = sqrt(z)
x = *self.TOFMonitor3xPtr
title = strtrim((*self.headerPtr)[2],2)+', T = '+ $
       strtrim(string((*self.InstrumentPtr).temp),2)+' K, Spectrum of Downstream Monitor'
endelse



if self.autoscale eq 1 then begin
  self.xrange = [min(x),max(x)]
  dz = 0.1*(max(z)-min(z))
  self.yrange = [min(z)-max(zerr)-dz, $
                 max(z)+max(zerr)+dz]
endif



plot,x,z,psym = 4,xrange = self.xrange,yrange = self.yrange, $
     xstyle = 1,ystyle = 1,xtitle = self.MonitorsXlabel, ytitle = self.zlabel, title = title,color=6,background=12
errplot,x,z-zerr,z+zerr,width = 0.0,color=6
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::doNothing,event = event
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::ebinning,event = event
widget_control,self.DataOutputTypesGroup,get_value = DataOutputType
; DataOutputType 0 S(Q,w)
; DataOutputType 1 S(theta,t)
if DataOutputType eq 0 then begin
self.xlabel = 'Energy / meV'
self.units=0
endif else begin
self.xlabel = 'Time / microseconds'
self.units=5
endelse
;   is energy binning requested?
widget_control,self.ebin_Group,get_value = thisValue
if thisValue[0] eq 0 then return
if n_elements(*self.dataPtr) eq 0 then return
data = *self.dataPtr
error = *self.errorPtr
x = *self.xvalsPtr
;print,'x: ',x
;help,x
;help,data
;help,error
widget_control,self.ebin_Group1,get_value = ebin_command
;   modify default(0), use previous(1), modify previous(2)
IF DataOutputType ne 1 then begin
;   modify default(0), use previous(1), modify previous(2)
if ebin_command eq 0 then begin
;
total_bins=n_elements(x)
minx=min(x, max = maxx)
nb_xlo=minx
nb_xhi=minx
b_xlo=minx
b_xhi=maxx
nb_nbins=0
b_nbins=total_bins
step=(b_xhi-b_xlo)/(b_nbins-1)
ix=x
;    print,'ix1: ',ix
ix_plus=ix[1:*]
ix_minus=ix[0:(n_elements(ix)-1)]
ix_diff=ix_plus-ix_minus
;print,ix_diff
u=1+bytarr(n_elements(ix_diff))
ustep=step*u
where_int=where(ix_diff gt ustep,count)
if count ge 1 then begin
ix=[ix[where_int[0]],ix[(where_int+1)]]
i_xlo=min(ix, max = i_xhi)
i_nbins=round((step+i_xhi-i_xlo)/step)
endif else begin
i_nbins=0
i_xlo=b_xlo
i_xhi=b_xlo
endelse
range=1
unit=0

ebin = opan_rebin_MARS_Energy_widget(x,nb_xlo=nb_xlo,nb_xhi=nb_xhi,nb_nbins=nb_nbins, $
                    b_xlo=b_xlo,b_xhi=b_xhi,b_nbins=b_nbins,step=step, $
                    i_xlo=i_xlo,i_xhi=i_xhi,i_nbins=i_nbins, total_bins=total_bins, $
                    range=range,unit=unit,group_leader = event.top)

;print,'x: ',x
;print,'b_xlo: ',b_xlo
;print,'b_xhi: ',b_xhi

nb_xlo=ebin.nb_xlo
nb_xhi=ebin.nb_xhi
nb_nbins=ebin.nb_nbins
b_xlo=ebin.b_xlo
b_xhi=ebin.b_xhi
b_nbins=ebin.b_nbins
step=ebin.step
i_xlo=ebin.i_xlo
i_xhi=ebin.i_xhi
i_nbins=ebin.i_nbins
total_bins=ebin.total_bins
range=ebin.range
unit=ebin.unit
cancel=ebin.cancel
;Now write the contents to a file
filename = 'MarsEbinParameters.txt'
filename = filepath(filename,root_dir = self.workDir)
openw,lun,filename,/get_lun
printf,lun,nb_xlo
printf,lun,nb_xhi
printf,lun,nb_nbins
printf,lun,b_xlo
printf,lun,b_xhi
printf,lun,b_nbins
printf,lun,step
printf,lun,i_xlo
printf,lun,i_xhi
printf,lun,i_nbins
printf,lun,total_bins
printf,lun,range
printf,lun,unit
free_lun,lun,/force
;
;print,'unit: ',unit
    if cancel eq 1 then return
       if unit eq 1 then begin
x*=8.06554097d
self.units=1
self.xlabel = 'Energy / Wavenumbers'
       endif
    if unit eq 2 then begin
x*=241.7989052d
self.units=2
self.xlabel = 'Energy / GHz'
    endif
    if unit eq 3 then begin
x*=0.2417989052d
self.units=3
self.xlabel = 'Energy / THz'
    endif
    if unit eq 4 then begin
x*=11.604615407811d
self.units=4
self.xlabel = 'Energy / K'
    endif
endif
;
;   option: modify previous values
if ebin_command eq 1 then begin
;check to see whether file exists
filename = 'MarsEbinParameters.txt'
if file_test(self.workDir+filename) eq 1 then begin
filename = filepath(filename,root_dir = self.workDir)
openr,lun,filename,/get_lun
readf,lun,nb_xlo
readf,lun,nb_xhi
readf,lun,nb_nbins
readf,lun,b_xlo
readf,lun,b_xhi
readf,lun,b_nbins
readf,lun,step
readf,lun,i_xlo
readf,lun,i_xhi
readf,lun,i_nbins
readf,lun,total_bins
readf,lun,range
readf,lun,unit
free_lun,lun,/force
;help,step
;help,x
;print,x
xcall=x
if unit eq 1 then xcall*=8.06554097d
if unit eq 2 then xcall*=241.7989052d
if unit eq 3 then xcall*=0.2417989052d
if unit eq 4 then xcall*=11.604615407811d
ebin = opan_rebin_MARS_Energy_widget(xcall,nb_xlo=nb_xlo,nb_xhi=nb_xhi,nb_nbins=nb_nbins, $
                    b_xlo=b_xlo,b_xhi=b_xhi,b_nbins=b_nbins,step=step, $
                    i_xlo=i_xlo,i_xhi=i_xhi,i_nbins=i_nbins, total_bins=total_bins, $
                    range=range,unit=unit,group_leader = event.top)
;ebin = {nb_xlo:nb_xlo,nb_xhi:nb_xhi,nb_nbins:nb_nbins,b_xlo:b_xlo,b_xhi:b_xhi,b_nbins:b_nbins, $
;       i_xlo:i_xlo,i_xhi:i_xhi,i_nbins:i_nbins,  $
;       range:range, unit:unit, cancel:cancel}
nb_xlo=ebin.nb_xlo
nb_xhi=ebin.nb_xhi
nb_nbins=ebin.nb_nbins
b_xlo=ebin.b_xlo
b_xhi=ebin.b_xhi
b_nbins=ebin.b_nbins
step=ebin.step
i_xlo=ebin.i_xlo
i_xhi=ebin.i_xhi
i_nbins=ebin.i_nbins
total_bins=ebin.total_bins
range=ebin.range
unit=ebin.unit
cancel=ebin.cancel
;Now write the contents to a file
filename = 'MarsEbinParameters.txt'
filename = filepath(filename,root_dir = self.workDir)
openw,lun,filename,/get_lun
printf,lun,nb_xlo
printf,lun,nb_xhi
printf,lun,nb_nbins
printf,lun,b_xlo
printf,lun,b_xhi
printf,lun,b_nbins
printf,lun,step
printf,lun,i_xlo
printf,lun,i_xhi
printf,lun,i_nbins
printf,lun,total_bins
printf,lun,range
printf,lun,unit
free_lun,lun,/force
;
;print,ebin.unit
    if cancel eq 1 then return
       if unit eq 1 then begin
x*=8.06554097d
self.units=1
self.xlabel = 'Energy / Wavenumbers'
       endif
if unit eq 2 then begin
x*=241.7989052d
self.units=2
self.xlabel = 'Energy / GHz'
    endif
    if unit eq 3 then begin
x*=0.2417989052d
self.units=3
self.xlabel = 'Energy / THz'
    endif
    if unit eq 4 then begin
x*=11.604615407811d
self.units=4
self.xlabel = 'Energy / K'
    endif
endif else begin
message=string('THE FILE '+self.workDir+'MarsEbinParameters.txt HAS NOT BEEN FOUND.  REVERTING TO DEFAULT ')
;help,message
msg=message
;help,msg
;msg = 'THE FILE "MarsEbinParameters.txt" HAS NOT BEEN FOUND.  REVERTING TO DEFAULT '
;help,msg
self->flashMessage_create,msg,tlb
wait,5
self->flashMessage_destroy,tlb
;if the file does not exist then revert to default
total_bins=n_elements(x)
minx=min(x, max = maxx)
nb_xlo=minx
nb_xhi=minx
b_xlo=minx
b_xhi=maxx
nb_nbins=0
b_nbins=total_bins
step=(b_xhi-b_xlo)/(b_nbins-1)
ix=x
ix_plus=ix[1:*]
ix_minus=ix[0:(n_elements(ix)-1)]
ix_diff=ix_plus-ix_minus
u=1+bytarr(n_elements(ix_diff))
ustep=step*u
where_int=where(ix_diff gt ustep,count)
if count ge 1 then begin
ix=[ix[where_int[0]],ix[(where_int+1)]]
i_xlo=min(ix, max = i_xhi)
i_nbins=round((step+i_xhi-i_xlo)/step)
endif else begin
i_nbins=0
i_xlo=b_xlo
i_xhi=b_xlo
endelse
range=1
unit=0
ebin = opan_rebin_MARS_Energy_widget(x,nb_xlo=nb_xlo,nb_xhi=nb_xhi,nb_nbins=nb_nbins, $
                    b_xlo=b_xlo,b_xhi=b_xhi,b_nbins=b_nbins,step=step, $
                    i_xlo=i_xlo,i_xhi=i_xhi,i_nbins=i_nbins, total_bins=total_bins, $
                    range=range,unit=unit,group_leader = event.top)
nb_xlo=ebin.nb_xlo
nb_xhi=ebin.nb_xhi
nb_nbins=ebin.nb_nbins
b_xlo=ebin.b_xlo
b_xhi=ebin.b_xhi
b_nbins=ebin.b_nbins
step=ebin.step
i_xlo=ebin.i_xlo
i_xhi=ebin.i_xhi
i_nbins=ebin.i_nbins
total_bins=ebin.total_bins
range=ebin.range
unit=ebin.unit
cancel=ebin.cancel
;Now write the contents to a file
filename = 'MarsEbinParameters.txt'
filename = filepath(filename,root_dir = self.workDir)
openw,lun,filename,/get_lun
printf,lun,nb_xlo
printf,lun,nb_xhi
printf,lun,nb_nbins
printf,lun,b_xlo
printf,lun,b_xhi
printf,lun,b_nbins
printf,lun,step
printf,lun,i_xlo
printf,lun,i_xhi
printf,lun,i_nbins
printf,lun,total_bins
printf,lun,range
printf,lun,unit
free_lun,lun,/force
;
    if cancel eq 1 then return
       if unit eq 1 then begin
x*=8.06554097d
self.units=1
self.xlabel = 'Energy / Wavenumbers'
       endif
if unit eq 2 then begin
x*=241.7989052d
self.units=2
self.xlabel = 'Energy / GHz'
    endif
    if unit eq 3 then begin
x*=0.2417989052d
self.units=3
self.xlabel = 'Energy / THz'
    endif
    if unit eq 4 then begin
x*=11.604615407811d
self.units=4
self.xlabel = 'Energy / K'
    endif
endelse
endif

;
if ebin_command eq 2 then begin

;check to see whether file exists
filename = 'MarsEbinParameters.txt'
if file_test(self.workDir+filename) eq 1 then begin
filename = filepath(filename,root_dir = self.workDir)
openr,lun,filename,/get_lun
readf,lun,nb_xlo
readf,lun,nb_xhi
readf,lun,nb_nbins
readf,lun,b_xlo
readf,lun,b_xhi
readf,lun,b_nbins
readf,lun,step
readf,lun,i_xlo
readf,lun,i_xhi
readf,lun,i_nbins
readf,lun,total_bins
readf,lun,range
readf,lun,unit
free_lun,lun,/force
;
nb_nbins=fix(nb_nbins)
b_nbins=fix(b_nbins)
i_nbins=fix(i_nbins)
range=fix(range)
unit=fix(unit)
;
       if unit eq 1 then begin
x*=8.06554097
self.units=1
self.xlabel = 'Energy / Wavenumbers'
       endif
if unit eq 2 then begin
x*=241.7989052d
self.units=2
self.xlabel = 'Energy / GHz'
    endif
    if unit eq 3 then begin
x*=0.2417989052d
self.units=3
self.xlabel = 'Energy / THz'
    endif
    if unit eq 4 then begin
x*=11.604615407811d
self.units=4
self.xlabel = 'Energy / K'
    endif
endif else begin
;revert to default
message=string('THE FILE '+self.workDir+'MarsEbinParameters.txt HAS NOT BEEN FOUND.  REVERTING TO DEFAULT ')
msg=message
;help,msg
;msg = 'THE FILE "MarsEbinParameters.txt" HAS NOT BEEN FOUND.  REVERTING TO DEFAULT '
;help,msg
self->flashMessage_create,msg,tlb
wait,5
self->flashMessage_destroy,tlb
;if the file does not exist then revert to default
total_bins=n_elements(x)
minx=min(x, max = maxx)
nb_xlo=minx
nb_xhi=minx
b_xlo=minx
b_xhi=maxx
nb_nbins=0
b_nbins=total_bins
step=(b_xhi-b_xlo)/(b_nbins-1)
ix=x
ix_plus=ix[1:*]
ix_minus=ix[0:(n_elements(ix)-1)]
ix_diff=ix_plus-ix_minus
u=1+bytarr(n_elements(ix_diff))
ustep=step*u
where_int=where(ix_diff gt ustep,count)
if count ge 1 then begin
ix=[ix[where_int[0]],ix[(where_int+1)]]
i_xlo=min(ix, max = i_xhi)
i_nbins=round((step+i_xhi-i_xlo)/step)
endif else begin
i_nbins=0
i_xlo=b_xlo
i_xhi=b_xlo
endelse
range=1
unit=0
ebin = opan_rebin_MARS_Energy_widget(x,nb_xlo=nb_xlo,nb_xhi=nb_xhi,nb_nbins=nb_nbins, $
                    b_xlo=b_xlo,b_xhi=b_xhi,b_nbins=b_nbins,step=step, $
                    i_xlo=i_xlo,i_xhi=i_xhi,i_nbins=i_nbins, total_bins=total_bins, $
                    range=range,unit=unit,group_leader = event.top)
nb_xlo=ebin.nb_xlo
nb_xhi=ebin.nb_xhi
nb_nbins=ebin.nb_nbins
b_xlo=ebin.b_xlo
b_xhi=ebin.b_xhi
b_nbins=ebin.b_nbins
step=ebin.step
i_xlo=ebin.i_xlo
i_xhi=ebin.i_xhi
i_nbins=ebin.i_nbins
total_bins=ebin.total_bins
range=ebin.range
unit=ebin.unit
cancel=ebin.cancel
;Now write the contents to a file
filename = 'MarsEbinParameters.txt'
filename = filepath(filename,root_dir = self.workDir)
openw,lun,filename,/get_lun
printf,lun,nb_xlo
printf,lun,nb_xhi
printf,lun,nb_nbins
printf,lun,b_xlo
printf,lun,b_xhi
printf,lun,b_nbins
printf,lun,step
printf,lun,i_xlo
printf,lun,i_xhi
printf,lun,i_nbins
printf,lun,total_bins
printf,lun,range
printf,lun,unit
free_lun,lun,/force
;
    if cancel eq 1 then return
       if unit eq 1 then begin
x*=8.06554097d
self.units=1
self.xlabel = 'Energy / Wavenumbers'
       endif
if unit eq 2 then begin
x*=241.7989052d
self.units=2
self.xlabel = 'Energy / GHz'
    endif
    if unit eq 3 then begin
x*=0.2417989052d
self.units=3
self.xlabel = 'Energy / THz'
    endif
    if unit eq 4 then begin
x*=11.604615407811d
self.units=4
self.xlabel = 'Energy / K'
    endif
endelse
endif
;
case range of
0: begin
;   include all data, only a part of which is to be binned
;   find data not to be binned
        where_x_lt_nb_xhi=where(x lt nb_xhi,count)
;       print,where_x_lt_nb_xhi
;       print,n_elements(where_x_lt_nb_xhi)
        if count ge 1 then begin
        xnb1=x[where_x_lt_nb_xhi]
       xnb=x[where(xnb1 ge nb_xlo)]
       nodata_count=where(x lt nb_xlo,count)
;       temp=x/nb_xhi
;        where_x_lt_nb_xhi=where(temp lt 0.999,count)
;;       print,where_x_lt_nb_xhi
;;       print,n_elements(where_x_lt_nb_xhi)
;        if count ge 1 then begin
;        xnb1=x[where_x_lt_nb_xhi]
;       temp=xnb1/nb_xlo
;       xnb=x[where(temp ge 0.999)]
;       temp=x/nb_xlo
;       nodata_count=where(temp lt 0.999,count)
    ; numerical bug fix
       if fix(nb_xlo) eq fix(min(x)) then begin
       count = -1
       xnb=xnb1
       endif
         if count lt 0 then begin
 ;        print,'count =',count
        datanb=data[0:n_elements(xnb)-1,*]
        errornb=error[0:n_elements(xnb)-1,*]
            endif else begin
        datanb=data[0+count:n_elements(xnb)-1+count,*]
        errornb=error[0+count:n_elements(xnb)-1+count,*]
           endelse
        endif
       xlo = b_xlo & xhi = b_xhi
       nbins = b_nbins
 ;      dx = (xhi-xlo)/(nbins-1.0)
       dx=step
       x_out = xlo+dx*dindgen(nbins)
;      print, 'total =',n_elements(x_out)+n_elements(xnb)+n_elements(nodata)
    end
1: begin
;   include only binned data,
       xlo = b_xlo & xhi = b_xhi
       nbins = b_nbins
 ;      dx = (xhi-xlo)/(nbins-1.0)
       dx=step
       x_out = xlo+dx*dindgen(nbins)
    end
2: begin
;   include only binned data, exclude interpolated region
        x_out = b_xlo+step*dindgen(b_nbins)
;        xlo = i_xhi & xhi = b_xhi
        xlo = b_xlo & xhi = i_xlo
       nbins = b_nbins-i_nbins
       x_out=x_out[where(x_out ge xlo)]
;       temp=x_out/xhi
;       x_out=x_out[where(temp le 1.001)]
end
else:
endcase
;
;
oxrange = '('+strtrim(string(min(x)),2)+','+strtrim(string(max(x)),2)+')'
xrange = '('+strtrim(string(xlo),2)+','+strtrim(string(xhi),2)+')'
if self.units eq 0 then ustring='Energy Units = meV'
if self.units eq 1 then ustring='Energy Units = wavenumbers'
if self.units eq 2 then ustring='Energy Units = GHz'
if self.units eq 3 then ustring='Energy Units = THz'
if self.units eq 4 then ustring='Energy Units = K'
treat = ['Data has been rebinned in Energy.', $
        'Old bins:'+strtrim(string(n_elements(x)),2), $
       ustring, $
        'Old Energy-range: '+oxrange, $
        'New bins:'+strtrim(string(nbins),2), $
        'New Energy-range: ',xrange]
*self.treatmentPtr = [*self.treatmentPtr,treat]

; Ok, we've done the error checking...now do the rebinning
;

;help,x
drebin,x,data,error,x_out,z_out,dz_out, $
    /points,/to_points,err=err,emsg=emsg
;print, 'energy binning'
;help,x
;help,data
;help,error
;help,x_out
;help,z_out
;help,dz_out

print,emsg
if err ne 0 then return

if n_elements(datanb) ne 0 then begin
;print,'n_elements(datanb) =',n_elements(datanb)
z=[datanb,z_out]
dz=[errornb,dz_out]
x=[xnb,x_out]
endif else begin
z=z_out
dz=dz_out
x=x_out
endelse
;
;
*self.dataPtr=z
*self.errorPtr=dz
*self.xvalsPtr=x

;print,z[800,0]
if ebin_command eq 0 then widget_control,self.ebin_group1,set_value = 1 ; as requested by Thierry and Fanni
ENDIF ELSE BEGIN
; the user wishes S(theta,t)
nx=n_elements(x)

if ebin_command eq 0 then begin

tmin=min(x, max = tmax)
ntbins=nx
step=(tmax-tmin)/(ntbins)
time_structure = opan_MARS_time_rebin_widget(tmin,tmax,ntbins,step,x,group_leader = event.top)
;out = {tmin:thmin,tmax:thmax,step:step,ntbins:ntbins,cancel:1}
  if time_structure.cancel eq 1 then return
tmin = time_structure.tmin & tmax = time_structure.tmax
ntbins = time_structure.ntbins
step=time_structure.step
;write the contents to a file
filename = 'MarsTbinParameters.txt'
filename = filepath(filename,root_dir = self.workDir)
openw,lun,filename,/get_lun
printf,lun,tmin
printf,lun,tmax
printf,lun,ntbins
printf,lun,step
free_lun,lun,/force
;
endif

if ebin_command eq 1 then begin

filename = 'MarsTbinParameters.txt'
    if file_test(self.workDir+filename) eq 1 then begin
filename = filepath(filename,root_dir = self.workDir)
openr,lun,filename,/get_lun
readf,lun,tmin
readf,lun,tmax
readf,lun,ntbins
readf,lun,step
free_lun,lun,/force
ntbins=fix(ntbins)


    endif else begin
;revert to default
message=string('THE FILE '+self.workDir+'MarsTbinParameters.txt HAS NOT BEEN FOUND.  REVERTING TO DEFAULT ')
msg=message
self->flashMessage_create,msg,tlb
wait,5
self->flashMessage_destroy,tlb

tmin=min(x, max = tmax)
ntbins=nx
step=(tmax-tmin)/(ntbins)
    endelse
time_structure = opan_MARS_time_rebin_widget(tmin,tmax,ntbins,step,x,group_leader = event.top)
;out = {tmin:thmin,tmax:thmax,step:step,ntbins:ntbins,cancel:1}
  if time_structure.cancel eq 1 then return
tmin = time_structure.tmin & tmax = time_structure.tmax
ntbins = time_structure.ntbins
step=time_structure.step
;write the contents to a file
filename = 'MarsTbinParameters.txt'
filename = filepath(filename,root_dir = self.workDir)
openw,lun,filename,/get_lun
printf,lun,tmin
printf,lun,tmax
printf,lun,ntbins
printf,lun,step
free_lun,lun,/force
;
endif


if ebin_command eq 2 then begin

filename = 'MarsTbinParameters.txt'
    if file_test(self.workDir+filename) eq 1 then begin
filename = filepath(filename,root_dir = self.workDir)
openr,lun,filename,/get_lun
readf,lun,tmin
readf,lun,tmax
readf,lun,ntbins
readf,lun,step
free_lun,lun,/force
ntbins=fix(ntbins)


    endif else begin
;revert to default
message=string('THE FILE '+self.workDir+'MarsTbinParameters.txt HAS NOT BEEN FOUND.  REVERTING TO DEFAULT ')
msg=message
self->flashMessage_create,msg,tlb
wait,5
self->flashMessage_destroy,tlb

tmin=min(x, max = tmax)
ntbins=nx
step=(tmax-tmin)/(ntbins)
time_structure = opan_MARS_time_rebin_widget(tmin,tmax,ntbins,step,x,group_leader = event.top)
;out = {tmin:thmin,tmax:thmax,step:step,ntbins:ntbins,cancel:1}
  if time_structure.cancel eq 1 then return
tmin = time_structure.tmin & tmax = time_structure.tmax
ntbins = time_structure.ntbins
step=time_structure.step
;write the contents to a file
filename = 'MarsTbinParameters.txt'
filename = filepath(filename,root_dir = self.workDir)
openw,lun,filename,/get_lun
printf,lun,tmin
printf,lun,tmax
printf,lun,ntbins
printf,lun,step
free_lun,lun,/force
    endelse
;
endif


oxrange = '('+strtrim(string(min(x)),2)+','+strtrim(string(max(x)),2)+')'
xrange = '('+strtrim(string(tmin),2)+','+strtrim(string(tmax),2)+')'
treat = ['Data has been rebinned in time.', $
        'Old bins:'+strtrim(string(nx),2), $
        'Old time-range: '+oxrange, $
        'New bins:'+strtrim(string(ntbins),2), $
        'New time-range: ',xrange]
*self.treatmentPtr = [*self.treatmentPtr,treat]



 tbins=tmin+step/2.0
 tbins_arr=tbins
    while tbins lt (tmax-step*1.49999) do begin
    tbins+=step
    tbins_arr=[tbins_arr,tbins]
    endwhile


  drebin,x,data,error,tbins_arr,z_out,dz_out,/points,/to_points, $
     err = err,emsg = emsg
;
;
*self.dataPtr=z_out
*self.errorPtr=dz_out
*self.xvalsPtr=tbins_arr

if ebin_command eq 0 then widget_control,self.ebin_group1,set_value = 1 ; as requested by Thierry and Fanni

ENDELSE



return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::Detector_Grouping,event = event
z = *self.dataPtr
dz = *self.errorPtr
x = *self.xvalsPtr
y = *self.yvalsPtr
oy=*self.oyvalsPtr

good_det = *self.good_detPtr
; is the data to be output in spe format
widget_control,self.FormatTypesGroup,get_value = vals


;print, 'self.ndet passed =',self.ndet
;   sum all or re-bin
widget_control,self.PhiBin_Group,get_value = thisValue
    if thisValue[0] eq 0 then begin
    ;sum all
 z=total(z,2)
dz=sqrt(total(dz^2,2))
;print,'total(dz) quick =',total(dz)
;
;
;print,'count =',count
mindz=min(dz[where(dz gt 0)])
wherezero=where(dz eq 0,count)
if count ne 0 then dz(wherezero)=mindz
;print,'count =',count
y=0.0
signdet=1
*self.dataPtr=z
*self.errorPtr=dz
*self.yvalsPtr=y
;*self.xvalsPtr*=241.7989052
self.ndet=signdet
;print,'(size(*self.dataPtr))[2] =',(size(*self.dataPtr))[2]
;print,'(size(sigData))[2] =',(size(sigData))[2]
;print,'(size(sigData))[2] =',(size(sigData))[2]
return
 endif

widget_control,self.PhiBin_Group1,get_value = PhiBin_command
;   modify default(0), use previous(1), modify previous(2)

file='MARSPhiGroupParameters.sav'
   fileOut = filepath(file,root_dir = self.workDir)

    if PhiBin_command eq 0 then begin

    detarray = intarr(10,10)
    if n_elements(good_det) eq 10 then begin
    for i = 0, 9 do begin
    detArray[i,i] = 1
    endfor
    endif else begin
    k=0
    for i = 0, 9 do begin
    present=where(i eq good_det)
    if present ne -1 then begin ;present
     detArray[k,i]=1
     k+=1
     endif
    endfor
    endelse
    *self.selDetPtr = detarray

*self.selDetPtr = marsDetGroupWidget(group_leader = event.top,self.selDetPtr,good_det)


DetPtr=*self.selDetPtr
save, filename=fileout, DetPtr

    endif

    if PhiBin_command eq 1 then begin
        if file_test(self.workDir+file) eq 1 then begin
    restore, fileout
;    help,Detptr
    *self.selDetPtr=Detptr
;       print,'Modify Previous'
        ;print,(size(Detptr))[1]
        ;print,self.ndet
;    wheregtzerowoof=where(total((*self.selDetPtr),2) gt 0)
;woof=(*self.selDetPtr)[wheregtzerowoof,*]
;print,'woof1: ',woof
    *self.selDetPtr = marsDetGroupWidget(group_leader = event.top,self.selDetPtr,good_det)
;wheregtzerowoof=where(total((*self.selDetPtr),2) gt 0)
;woof=(*self.selDetPtr)[wheregtzerowoof,*]
;print,'woof2: ',woof
     DetPtr=*self.selDetPtr
save, filename=fileout, DetPtr
  endif else begin
;revert to default
message=string('THE FILE '+self.workDir+'MARSPhiGroupParameters.sav HAS NOT BEEN FOUND;  REVERTING TO DEFAULT ')
msg=message
self->flashMessage_create,msg,tlb
wait,5
self->flashMessage_destroy,tlb

    detarray = intarr(10,10)
    if n_elements(good_det) eq 10 then begin
    for i = 0, 9 do begin
    detArray[i,i] = 1
    endfor
    endif else begin
    k=0
    for i = 0, 9 do begin
    present=where(i eq good_det)
    if present ne -1 then begin ;present
     detArray[k,i]=1
     k+=1
     endif
    endfor
    endelse
    *self.selDetPtr = detarray

*self.selDetPtr = marsDetGroupWidget(group_leader = event.top,self.selDetPtr,good_det)
DetPtr=*self.selDetPtr
save, filename=fileout, DetPtr

       endelse
    endif


    if PhiBin_command eq 2 then begin
        if file_test(self.workDir+file) eq 1 then begin
    restore, fileout
        *self.selDetPtr=Detptr
       ;print,'Use Previous'
        ;print,(size(Detptr))[1]
        ;print,self.ndet
       endif else begin
       ;revert to default
message=string('THE FILE '+self.workDir+'MARSPhiGroupParameters.sav HAS NOT BEEN FOUND;  REVERTING TO DEFAULT ')
msg=message
self->flashMessage_create,msg,tlb
wait,5
self->flashMessage_destroy,tlb
;array = intarr(self.ndet,self.ndet)
    detarray = intarr(10,10)
    if n_elements(good_det) eq 10 then begin
    for i = 0, 9 do begin
    detArray[i,i] = 1
    endfor
    endif else begin
    k=0
    for i = 0, 9 do begin
    present=where(i eq good_det)
    if present ne -1 then begin ;present
     detArray[k,i]=1
     k+=1
     endif
    endfor
    endelse
    *self.selDetPtr = detarray

*self.selDetPtr = marsDetGroupWidget(group_leader = event.top,self.selDetPtr,good_det)
;print,'woof'
DetPtr=*self.selDetPtr
save, filename=fileout, DetPtr

       endelse
    endif


wheregtzero=where(total((*self.selDetPtr),2) gt 0,num)
;print,'num =',num
yout=(*self.selDetPtr)[wheregtzero,*]
;print,'yout: ',yout
znew=fltarr((size(z))[1],num)
dznew=fltarr((size(z))[1],num)
ynew=fltarr(num)

;print,'*self.selDetPtr: ',*self.selDetPtr
;print,'yout: ',yout
;print,'wheregtzero: ',wheregtzero
treat = ['The data have been binned in groups of phi.', $
        'Number of groups: '+strtrim(string(num),2)]


PhiAngles=[30.0,60.0,90.0,120.0,150.0]
widget_control,self.DataOutputTypesGroup,get_value = DataOutputType
if DataOutputType eq 0 then begin
minx=min(x, max = maxx)
EnergyMidPoint=((maxx-minx)/2.0)+minx
lambda=(*self.InstrumentPtr).lambda
alpha=2.072099427d
E0=81.80320651d/lambda^2
if self.units eq 1 then begin
E0*=8.06554097d
alpha*=8.06554097d
endif
if self.units eq 2 then begin
E0*=241.7989052d
alpha*=241.7989052d
endif
if self.units eq 3 then begin
E0*=0.2417989052d
alpha*=0.2417989052d
endif
if self.units eq 4 then begin
E0*=11.604615407811d
alpha*=11.604615407811d
endif
Qmid= sqrt((2.0d*E0+EnergyMidPoint-2.0d*sqrt(E0*(E0+EnergyMidPoint))*cos(PhiAngles*!dtor))/alpha)
endif




for i = 0, num-1 do begin
whereone=where(yout[i,*] eq 1,count)
whereoneandgood=[-1]
;print,'i: ',i
;print,'whereone: ',whereone
    for r = 0,count-1 do begin
    index=where(whereone[r] eq good_det,number)
    if number ne 0 then whereoneandgood=[whereoneandgood,index]
    endfor


if n_elements(whereoneandgood) ne 1 then begin
whereoneandgood=whereoneandgood[1:*]
n=n_elements(whereoneandgood)

;print,'i2: ',i

    if n gt 1 then begin
    znew[*,i]=total(z[*,whereoneandgood],2)
    dznew[*,i]=sqrt(total((dz[*,whereoneandgood])^2,2))
    endif else begin
;    if whereone eq 8 then print,'total(z[*,whereone8]): ',total(z[*,whereone])
;    if whereone eq 9 then print,'total(z[*,whereone9]): ',total(z[*,whereone])
    znew[*,i]=z[*,whereoneandgood]
    dznew[*,i]=dz[*,whereoneandgood]
    endelse

endif

endfor


;y labelling - separated from the loop above for clarity
;print,'y: ',y
;print,'num: ',num


for i = 0, num-1 do begin
whereone=where(yout[i,*] eq 1,count)
    if count eq 1 then begin
       if    DataOutputType eq 1 then begin
       ynew[i]=oy[whereone[0]]
       endif else begin ;write Q value
       whereangle=where(oy[whereone[0]] eq PhiAngles,count)
       if count eq 0 then return ;should never happen
       ynew[i]=Qmid[whereangle[0]]
       endelse
        endif else begin ; more than one detector
   ;print,'oy[whereone]: ',oy[whereone]
    variance=(moment(oy[whereone]))[1]
    if variance gt 1.0 then begin ; different angle
       ynew[i]=-1
       endif else begin
       if    DataOutputType eq 1 then begin
       ynew[i]=oy[whereone[0]]
       endif else begin ;write Q value
       whereangle=where(round(oy[whereone[0]]) eq round(PhiAngles),count)
       if count eq 0 then return ;should never happen
       ynew[i]=Qmid[whereangle[0]]
       endelse
       endelse
    endelse
       treat=[treat,'Group '+strtrim(string(i+1),2)+': '+ strtrim(string(ynew[i]),2)]
endfor


mindznew=min(dznew[where(dznew gt 0)])
wherezero=where(dznew eq 0,count)
if count ne 0 then dznew(wherezero)=mindznew
;print,'count =',count

*self.dataPtr=znew
*self.errorPtr=dznew
*self.yvalsPtr=ynew

*self.treatmentPtr = [*self.treatmentPtr,treat]

if PhiBin_command eq 0 then widget_control,self.phibin_group1,set_value = 1 ; as requested by Thierry and Fanni

end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::normalize_to_vanadium,event = event

   CATCH, Error_status
if Error_status ne 0 then begin
catch, /cancel
msg=strarr(3)
msg[0]='Unable to Normalise to Vanadium.'
msg[1]='Check to see whether you have removed any dead detectors'
msg[2]='Error Message from IDL: '+!ERROR_STATE.MSG
    void=dialog_message(dialog_parent=event.top,/error,msg)
return
endif
if n_elements(*self.dataPtr) eq 0 then return
;print,'*self.vanFilePtr: ',*self.vanFilePtr
if n_elements(*self.vanFilePtr) eq 0 then return
instrument_details = *self.InstrumentPtr
lambda=instrument_details.lambda


delim=path_Sep()
calfile=!DAVE_AUXILIARY_DIR+'PSI'+delim+'MARS'+delim+'MarsVanadiumCalibration.txt'
IF (*self.vanFilePtr)[0] eq 'Automatic' then begin


if file_test(calfile) eq 1 then begin
FileFound=1
line=''
Calibration_Data='woof'
openr,lun,calfile,/get_lun

while eof(lun) eq 0 do begin
readf,lun,line
line=strtrim(line,2)
;select only lines with the correct reflection
if (strpos(line,';') ne 0) and (strmid(line,0,3) eq self.WorkingReflection) then begin
Calibration_Data=[Calibration_Data,line]
endif
endwhile
free_lun,lun,/force
;
    if n_elements(Calibration_Data) gt 2 then begin
    Calibration_Data=Calibration_Data[1:*]
    DataPresent=1
    endif else begin ; empty file
    DataPresent=0
    endelse
endif else begin ; file not present
FileFound=0
endelse

if FileFound eq 0 then begin
msg=strarr(3)
msg[0]='The file ''MarsVanadiumCalibration.txt'' is '
msg[1]='not present in the PSI/MARS Auxillary Directory'
msg[2]='The automatic vanadium correction procedure cannot be performed.'
    void=dialog_message(dialog_parent=event.top,/error,msg)
return
endif
if DataPresent eq 0 then begin
msg=strarr(2)
msg[0]='The File ''MarsVanadiumCalibration.txt'' contains insufficient data'
msg[1]='with which to perform the automatic vanadium correction procedure'
    void=dialog_message(dialog_parent=event.top,/error,msg)
return
endif
nCalData=n_elements(Calibration_Data)
lambda_array=fltarr(nCalData)
Area_Array=fltarr(10,nCalData)
unix_start_time_array=dblarr(nCalData)
unix_start_time_stringarray=strarr(nCalData)
temp1=ptr_new(0.0)
temp2=ptr_new(fltarr(10))
temp3=ptr_new(double(0.0))
void=''
for i = 0, nCalData - 1 do begin
reads,Calibration_Data[i],void,*temp1,*temp2,*temp3
lambda_array[i]=*temp1
Area_Array[*,i]=*temp2
unix_start_time_array[i]=*temp3
endfor
ptr_free,temp1,temp2,temp3
if (lambda lt min(lambda_array)) or (lambda gt max(lambda_array)) then begin
msg=strarr(3)
msg[0]='Warning: the values for the wavelength documented'
msg[1]='in the file ''MarsVanadiumCalibration.txt'' do not'
msg[2]='encompass the value pertinent to this data set.'
    void=dialog_message(dialog_parent=event.top,/information,msg)
endif
;
;
; there are 31536000 seconds in a year
OneYearAgo=double(systime(/seconds) - 31536000.0)
old = 0
for i = 0, nCalData - 1 do begin
if unix_start_time_array[i] lt OneYearAgo then old = 1
endfor
if old eq 1 then begin
msg=strarr(2)
msg[0]='The File ''MarsVanadiumCalibration.txt'''
msg[1]='contains data that are more than one year old'
    void=dialog_message(dialog_parent=event.top,/information,msg)
endif
;
x=fltarr(nCalData)
y=fltarr(nCalData)
area_calc_array=fltarr(10)
PolyFitArray=fltarr(10,nCalData)
degree=nCalData-2
if degree gt 3 then degree = 3 ;maximum order = 3
x=lambda_array
for i = 0, 9 do begin
y=reform(Area_Array[i,*])
coeff=poly_fit(x,y,degree,status=status,yfit=yfit,/double)
if status ne 0 then begin
msg=strarr(2)
msg[0]='The poly_fit function has failed.'
msg[1]='The automatic vanadium correction procedure cannot be performed.'
    void=dialog_message(dialog_parent=event.top,/error,msg)
return
endif
PolyFitArray[i,*]=yfit
if degree eq 1 then begin ; linear
area_calc_array[i]=coeff[0]+coeff[1]*lambda
endif
;
if degree eq 2 then begin ; quadratic
area_calc_array[i]=coeff[0]+coeff[1]*lambda+coeff[2]*lambda^2
endif
;
if degree eq 3 then begin ; third-order
area_calc_array[i]=coeff[0]+coeff[1]*lambda+coeff[2]*lambda^2+coeff[3]*lambda^3
endif
;
endfor
good_det=*self.good_detPtr


*self.Vanadium_Lambda_arrayPtr=lambda_array; experimental values for lambda
*self.Vanadium_Area_ArrayPtr=Area_Array[good_det,*]; areas read in from the file for the detectors
*self.Vanadium_PolyFitArrayPtr=PolyFitArray[good_det,*]; the calculated fit
*self.Vanadium_area_calc_arrayPtr=area_calc_array[good_det] ;the calculated area
;we need to plot Area_Array against lambda_array for each good_det.
;then overlay the PolyFit as a line and area_calc_array as a point
;
stats = moment(area_calc_array[good_det])
ux = 1+bytarr(n_elements(*self.xvalsPtr))
a = ux#(area_calc_array[good_det]/stats[0])
(*self.dataPtr)/= a
(*self.errorPtr)/= a

treat = 'Normalised using automatic vanadium calibration procedure'
*self.treatmentPtr = [*self.treatmentPtr,treat]

widget_control,self.Misc_Group1,get_value = val
if val[1] eq 1 then begin
Plot_AutoVanFits,lambda_array,Area_Array,PolyFitArray,area_calc_array,lambda, $
                 good_det,group_leader=event.top
endif
return
ENDIF     ; IF (*self.vanFilePtr)[0] eq 'Automatic'



; First pull out the current data values

odata = *self.odataPtr
oerror = *self.oerrorPtr
oxvals = *self.oxvalsPtr
oyvals = *self.oyvalsPtr
oElasticData = *self.oElasticDataPtr
oElasticError = *self.oElasticErrorPtr
oyvalsElastic = *self.oyvalsElasticPtr
oTOFMonitor = *self.oTOFMonitor2Ptr
sigData = *self.dataPtr
sigError = *self.errorPtr
sigx = *self.xvalsPtr
sigy = *self.yvalsPtr
sigTemp = *self.tempPtr
sigMon_cum = *self.Mon_cumPtr
sigTOFMonitor1 = *self.TOFMonitor1Ptr
sigTOFMonitor2 = *self.TOFMonitor2Ptr
sigTOFMonitor3 = *self.TOFMonitor3Ptr
signdet=self.ndet
header=*self.headerPtr
instrument_details = *self.InstrumentPtr
ElasticData=*self.ElasticDataPtr
ElasticError=*self.ElasticErrorPtr
xvalsElastic=*self.xvalsElasticPtr
ElasticAngles = *self.ElasticdetPtr


vanFile = *self.vanFilePtr

self->Sum_Vandium_Runs,event = event,err = err
*self.InstrumentPtr = instrument_details
vdata = *self.dataPtr
vtemperature = *self.tempPtr
vtemperature = vtemperature[0]
if vtemperature eq 0 then vtemperature = 298.0
;help,vtemperature
;print,'vtemperature =',vtemperature
InelasticAngles=*self.yvalsPtr
;print,'*self.xvalsPtr =',*self.xvalsPtr
;
;Apply the same detector filtering as before
;
;
good_det=*self.good_detPtr
vData=vData[*,good_det]
InelasticAngles=InelasticAngles[good_det]

*self.dataPtr = vData
vError = sqrt(vData)
*self.errorPtr = vError
*self.yvalsPtr = InelasticAngles
VanMon_cum = *self.Mon_cumPtr
;
;
widget_control,self.DataOutputTypesGroup,get_value = DataOutput
;convert to energy unless the desired quantity is S(theta,t)
if DataOutput eq 0 then begin
self->convert_to_energy,event = event,/vanadium
endif else begin
self->Time_Bin_Grouping,event = event,/vanadium
endelse
vanData = *self.dataPtr
vanx = *self.xvalsPtr

for i = 0,n_elements(InelasticAngles)-1 do begin
   ; Get a good estimate of the starting parameters for the fits
 y = reform(vanData[*,i])
 x=vanX
 width=max(x)-min(x)
 zeropos=(vanx[where(y eq max(y))])[0]
 coeff=[max(y),zeropos,(width/12.0),0]
  ; Fit
;  print, 'y =',y
;  print, 'x =',x
;  print, 'width =',width
;  print, 'zeropos =',zeropos
;  print,''
 result = gaussfit(x,y,p,chisq=gof,estimates = coeff,nterms = 4)
  ; the next line should be the area
;  print, 'Chisq =',gof
;  print, 'fwhh =',p[2]
;  print, 'max(y) =',p[0]
;  print, 'x position =',p[1]
;  print,''
  a = p[0]*sqrt(2.0*!pi*p[2]^2)
  if i eq 0 then area = a else area = [area,a]
endfor
whereneg=where(area lt 0, count1)
wherebig=where(abs(area) gt 1e6, count2)
wheresmall=where(abs(area) lt 0, count3)
if (count1 ne 0) or (count2 ne 0) or (count3 ne 0) then begin
Faulty=[whereneg,wherebig,wheresmall]
Faulty=Faulty[where(Faulty ne -1)]
Faultystring='detectors: '
for i = 0, n_elements(Faulty) - 1 do begin
if i eq 0 then begin
Faultystring+=strtrim(string(Faulty[i]),2)
endif else begin
Faultystring+=','+strtrim(string(Faulty[i]),2)
endelse
endfor
msg=strarr(3)
msg[0]='CALIBRATION OF DETECTORS FROM VANADIUM RUN HAS FAILED!'
msg[1]='Unable to obtain a reasonable fit of the elastic line'
msg[2]='from '+Faultystring+'.'
    void=dialog_message(dialog_parent=event.top,/error,msg)
;restore data
*self.xvalsPtr = sigx
*self.yvalsPtr = sigy
*self.dataPtr = sigData
*self.errorPtr = sigError
*self.tempPtr = [sigTemp]
*self.Mon_cumPtr = [sigMon_cum,VanMon_cum]
*self.TOFMonitor1Ptr = sigTOFMonitor1
*self.TOFMonitor2Ptr = sigTOFMonitor2
*self.TOFMonitor3Ptr = sigTOFMonitor3
self.ndet=signdet
*self.headerPtr = header
*self.ElasticDataPtr=ElasticData
*self.ElasticErrorPtr=ElasticError
*self.xvalsElasticPtr=xvalsElastic
*self.odataPtr = odata
*self.oerrorPtr = oerror
*self.oxvalsPtr= oxvals
*self.oyvalsPtr = oyvals
*self.oElasticDataPtr = oElasticData
*self.oElasticErrorPtr = oElasticError
*self.oyvalsElasticPtr = oyvalsElastic
*self.oTOFMonitor2Ptr=oTOFMonitor
*self.ElasticdetPtr=ElasticAngles


treat = 'Unable to normalise to vanadium file: '+strtrim(string(vanFile),2)
*self.treatmentPtr = [*self.treatmentPtr,treat]
return
endif
stats = moment(area[0:n_elements(InelasticAngles)-1])
;stats[0] is then the mean average area.  Now divide each area by the mean average
;area = temporary(area)/stats[0]
ux = 1+bytarr(n_elements(sigX))
q = (4.0*!pi/lambda)*sin(0.5*!dtor*InelasticAngles)
;the next line creates n_elements(sigX) columns of exp(0.066*sigY^2) data
;dwf = ux#(exp(-0.0067^(vtemperature/300.0)*q^2))  ; Debye-Waller factor for vanadium
;dwf = ux#(exp(-0.0067*vtemperature/300.0*q^2))  ; Debye-Waller factor for vanadium
dwf = exp(-0.0067*vtemperature/300.0*q^2)  ; Debye-Waller factor for vanadium
area*=dwf

a = ux#(area/stats[0])

;sigData = sigData*dwf/a
;sigError = sigError*dwf/a
sigData/= a
sigError/= a


*self.xvalsPtr = sigx
*self.yvalsPtr = sigy
*self.dataPtr = sigData
*self.errorPtr = sigError
*self.tempPtr = [sigTemp];[sigTemp,bgtemperature]
*self.Mon_cumPtr = [sigMon_cum,VanMon_cum]
*self.TOFMonitor1Ptr = sigTOFMonitor1
*self.TOFMonitor2Ptr = sigTOFMonitor2
*self.TOFMonitor3Ptr = sigTOFMonitor3
self.ndet=signdet
*self.headerPtr = header
*self.ElasticDataPtr=ElasticData
*self.ElasticErrorPtr=ElasticError
*self.xvalsElasticPtr=xvalsElastic
*self.odataPtr = odata
*self.oerrorPtr = oerror
*self.oxvalsPtr= oxvals
*self.oyvalsPtr = oyvals
*self.oElasticDataPtr = oElasticData
*self.oElasticErrorPtr = oElasticError
*self.oyvalsElasticPtr = oyvalsElastic
*self.oTOFMonitor2Ptr=oTOFMonitor
*self.ElasticdetPtr=ElasticAngles

;print,'v ndet =',self.ndet
treat = 'Normalised to vanadium file: '+strtrim(string(vanFile),2)
*self.treatmentPtr = [*self.treatmentPtr,treat]


;save area,lambda,time data collected in unix time and as string
if n_elements(InelasticAngles) ne 10 then return ; only save if all the detectors are o.k.
if DataOutput eq 1 then return ; only include data that have been converted to energy and normalised to the monitor
for i = 0,9 do begin
    if i eq 0 then begin
    AreaString=strtrim(string(Area[i]),2)
    endif else begin
    AreaString=[AreaString,+','+strtrim(string(Area[i]),2)]
    endelse
endfor
CalString=strtrim(string(lambda),2)+','+ $
          AreaString+','+ $
          strtrim(string(self.unix_start_time),2)+','+ $
          strtrim(string(systime(0,self.unix_start_time)),2)


if file_test(calfile) eq 1 then begin
DataPresent=1
line=''
Calibration_Data='woof'
openr,lun,calfile,/get_lun
while eof(lun) eq 0 do begin
readf,lun,line
Calibration_Data=[Calibration_Data,line]
endwhile
free_lun,lun,/force
    if n_elements(Calibration_Data) gt 1 then begin
    Calibration_Data=Calibration_Data[1:*]
    endif else begin ; empty file
    DataPresent=0
    endelse
endif else begin ; file not present
DataPresent=0
endelse
;
if DataPresent eq 1 then begin
Calibration_Data=[Calibration_Data,CalString]
endif else begin
Calibration_Data = CalString
endelse
;write to the file
n=n_elements(Calibration_Data)
openw,lun,calfile,/get_lun
for i = 0, n-1 do begin
printf,lun, Calibration_Data[i]
endfor
free_lun,lun,/force
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::Nexus_read_raw_mars,filename,event = event,err = err
;print,'filename =',filename
;print,'strlen(filename) =',strlen(filename)
;help,filename
if n_elements(filename) eq 0 then Begin
err=-1
return
endif
err = 0
handle=0L
;dummy = nxopen(filename,'read',handle)   ;for nidl
dummy = nxopen(filename,'NXACC_READ',handle) ;for napi45
self.curFile = filename
;
;
;-------- get some global attributes
    dummy1 = nxgetattr(handle,'file_time',start_time,typ) ;start time
    dummy2 = nxgetattr(handle,'file_name',FullFileName, typ) ;full file name
    dummy3 = nxgetattr(handle,'owner',owner,typ) ;user name
    ;string: start_time
    ;string: FullFileName
    ;string: owner

;print,'start_time: ',start_time
;print,'FullFileName: ',FullFileName
;print,'owner: ',owner
;err=1
;return

    ;------ open elastic group
    dummy = nxopengroup(handle,'elastic','NXentry')

    dummy = nxopendata(handle,'end_time')
    dummy = nxgetdata(handle,end_time)
    dummy = nxclosedata(handle)
    ;string: end_time
    dummy = nxopendata(handle,'title')
    dummy = nxgetdata(handle,title)
    dummy = nxclosedata(handle)
    ;string: title
    dummy = nxopendata(handle,'unix_start_time')
    dummy = nxgetdata(handle,unix_start_time)
    dummy = nxclosedata(handle)
    ;long: unix_start_time

     ;------ open user group
    dummy = nxopengroup(handle,'user','NXuser')

    dummy = nxopendata(handle,'address')
    dummy = nxgetdata(handle,address)
    dummy = nxclosedata(handle)
    ;string: address
    dummy = nxopendata(handle,'email')
    dummy = nxgetdata(handle,email)
    dummy = nxclosedata(handle)
    ;string: email
    dummy = nxopendata(handle,'telephone_number')
    dummy = nxgetdata(handle,telephone_number)
    dummy = nxclosedata(handle)
    ;string: telephone_number
    dummy = nxclosegroup(handle)

    ;------ open instrument responsible group
    dummy = nxopengroup(handle,'instrumentresponsible','NXuser')
    dummy = nxopendata(handle,'name')
    dummy = nxgetdata(handle,instrumentresponsible)
    dummy = nxclosedata(handle)
    ;string: instrumentresponsible
    dummy = nxclosegroup(handle)

     ;------ open sample group
    dummy = nxopengroup(handle,'sample','NXsample')
    dummy = nxopendata(handle,'environment')
    dummy = nxgetdata(handle,environment)
    dummy = nxclosedata(handle)
    ;string: environment
    dummy = nxopendata(handle,'name')
    dummy = nxgetdata(handle,SampleName)
    dummy = nxclosedata(handle)
    ;string: SampleName
    dummy = nxopendata(handle, 'temperature')

    if dummy then begin
    dummy = nxgetdata(handle, temp)
    dummy = nxclosedata(handle)
    endif else begin
;    temp_float = opan_Temperature_widget(filename,group_leader = event.top)
;    temp=MAKE_ARRAY(1, /float, value=temp_float)
     temp=2.0
    endelse
    if temp[0] lt 0 then begin
    print,'temp ',temp
    temp_float = opan_Temperature_widget(filename,group_leader = event.top)
    temp=MAKE_ARRAY(1, /float, value=temp_float)
    endif
    dummy = nxclosegroup(handle)


    ;------ open MARS group
    dummy = nxopengroup(handle,'MARS','NXInstrument')

    ;------ open snail_chopper group
    dummy = nxopengroup(handle,'snail_chopper','NXdisk_chopper')

    dummy = nxopendata(handle,'rotation_speed')
    dummy = nxgetdata(handle,SnailSpeed)
    dummy = nxclosedata(handle)
    ;float: SnailSpeed

    dummy = nxopendata(handle,'phase')
    dummy = nxgetdata(handle,SnailPhase)
    dummy = nxclosedata(handle)
    ;float: SnailPhase
    dummy = nxclosegroup(handle)

    ;------ open rabbit_chopper group
    dummy = nxopengroup(handle,'rabbit_chopper','NXdisk_chopper')

    dummy = nxopendata(handle,'rotation_speed')
    dummy = nxgetdata(handle,RabbitSpeed)
    dummy = nxclosedata(handle)
    ;float: RabbitSpeed

    dummy = nxopendata(handle,'phase')
    dummy = nxgetdata(handle,RabbitPhase)
    dummy = nxclosedata(handle)
    ;float: RabbitPhase
    dummy = nxclosegroup(handle)

    ;------ open master_chopper group
    dummy = nxopengroup(handle,'pulse_producing_chopper','NXdisk_chopper')

    dummy = nxopendata(handle,'rotation_speed')
    dummy = nxgetdata(handle,MasterSpeed)
    dummy = nxclosedata(handle)
    ;float: MasterSpeed

    dummy = nxopendata(handle,'phase')
    dummy = nxgetdata(handle,MasterPhase)
    dummy = nxclosedata(handle)
    ;float: MasterPhase
    dummy = nxclosegroup(handle)

    ;------ open frame1_chopper group
    dummy = nxopengroup(handle,'frame1_chopper','NXdisk_chopper')

    dummy = nxopendata(handle,'rotation_speed')
    dummy = nxgetdata(handle,Chopper4Speed)
    dummy = nxclosedata(handle)
    ;float: Chopper4Speed

    dummy = nxopendata(handle,'phase')
    dummy = nxgetdata(handle,Chopper4Phase)
    dummy = nxclosedata(handle)
    ;float: Chopper4Phase
    dummy = nxclosegroup(handle)

    ;------ open frame2_chopper group
    dummy = nxopengroup(handle,'frame2_chopper','NXdisk_chopper')

    dummy = nxopendata(handle,'rotation_speed')
    dummy = nxgetdata(handle,Chopper5Speed)
    dummy = nxclosedata(handle)
    ;float: Chopper5Speed

    dummy = nxopendata(handle,'phase')
    dummy = nxgetdata(handle,Chopper5Phase)
    dummy = nxclosedata(handle)
    ;float: Chopper5Phase
    dummy = nxclosegroup(handle)

    dummy = nxclosegroup(handle) ;close MARS group


    ;------ open integrated TOF monitor group
    dummy = nxopengroup(handle,'proton_beam_monitor','NXmonitor')
    dummy = nxopendata(handle,'integral')
    dummy = nxgetdata(handle,DataMonitor1)
    dummy = nxclosedata(handle)
    ;long64: DataMonitor1
    dummy = nxclosegroup(handle)

    ;------ open pre-sample TOF monitor group
    dummy = nxopengroup(handle,'pre_sample_monitor','NXmonitor')
    dummy = nxopendata(handle,'time_of_flight')
    dummy = nxgetdata(handle,tof) ; need only get this once as array is common to all detectors
    dummy = nxclosedata(handle)
    ;fltarr tof
    dummy = nxopendata(handle,'data')
    dummy = nxgetdata(handle,DataMonitor2)
    dummy = nxclosedata(handle)
    ;fltarr DataMonitor2
    dummy = nxopendata(handle,'preset')
    dummy = nxgetdata(handle,PresetMonitor2)
    dummy = nxclosedata(handle)
    ;long64 PresetMonitor2
    dummy = nxclosegroup(handle)

    ;------ open post-sample TOF monitor group
    dummy = nxopengroup(handle,'after_sample_monitor','NXmonitor')
    dummy = nxopendata(handle,'data')
    dummy = nxgetdata(handle,DataMonitor3)
    dummy = nxclosedata(handle)
    ;fltarr DataMonitor3
    dummy = nxclosegroup(handle)

    ;------ open elastic bank group
    dummy = nxopengroup(handle,'elastic_bank','NXdata')
    dummy = nxopendata(handle,'data')
    dummy = nxgetdata(handle,DataElastic)
    dummy = nxclosedata(handle)
    ;2dfltarr DataElastic
    dummy = nxopendata(handle,'scattering_angle')
    dummy = nxgetdata(handle,ElasticAngles)
    dummy = nxclosedata(handle)
    ;fltarr ElasticAngles
    dummy = nxclosegroup(handle)

    dummy = nxclosegroup(handle) ; close elastic group

    ;------ open inelastic group
    dummy = nxopengroup(handle,'inelastic','NXentry')

    ;------ open MARS group
    dummy = nxopengroup(handle,'MARS','NXInstrument')

    ;------ open inelastic_bank group
    dummy = nxopengroup(handle,'inelastic_bank','NXdetector')
    dummy = nxopendata(handle,'signal_bins')
    dummy = nxgetdata(handle,TimeBinIndices)
    dummy = nxclosedata(handle)
    ;string TimeBinIndices
    dummy = nxclosegroup(handle)

    ;------ open analyser group
    dummy = nxopengroup(handle,'analyser','NXcrystal')
    dummy = nxopendata(handle,'analyser_angle')
    dummy = nxgetdata(handle,TriffidAngles)
    dummy = nxclosedata(handle)
    ;fltarr TriffidAngles
    dummy = nxopendata(handle,'target_reflection')
    dummy = nxgetdata(handle,targetreflection)
    dummy = nxclosedata(handle)
    ;string: targetreflection

    dummy = nxclosegroup(handle)

    ;------ open inelastic bank group
    dummy = nxopengroup(handle,'inelastic_bank','NXdata')
    dummy = nxopendata(handle,'data')
    dummy = nxgetdata(handle,DataInelastic)
    dummy = nxclosedata(handle)
    ;2dfltarr DataInelastic
    dummy = nxopendata(handle,'scattering_angle')
    dummy = nxgetdata(handle,InelasticAngles)
    dummy = nxclosedata(handle)
    ;fltarr InelasticAngles
    dummy = nxclosegroup(handle)


    dummy = nxclosegroup(handle) ; close inelastic group
    dummy = nxclose(handle) ; close file


masterfundamental=fix(round(MasterSpeed/3000.0))
timeoffsets=*self.timeoffsetsPtr
offset=0.0
if masterfundamental eq 1 then offset=timeoffsets.master1_timeoffset
if masterfundamental eq 2 then offset=timeoffsets.master2_timeoffset
if masterfundamental eq 3 then offset=timeoffsets.master3_timeoffset
if masterfundamental eq 4 then offset=timeoffsets.master4_timeoffset
if masterfundamental eq 5 then offset=timeoffsets.master5_timeoffset
if masterfundamental eq 6 then offset=timeoffsets.master6_timeoffset
if masterfundamental eq 7 then offset=timeoffsets.master7_timeoffset
;print,'offset: ' ,offset
tof+=offset
;
;help,ElasticAngles
;print,ElasticAngles
;ElasticAngles[4]=45.064
;InelasticAngles=[150.0,120.0,90.0,60.0,30.0,30.0,60.0,90.0,120.0,150.0]

;print,InelasticAngles

;print,'n_elements(tof): ',n_elements(tof)
;err=1
;return
;convert to point data
tof+=(tof[1]-tof[0])/2.0




;
*self.odataPtr = float(DataInelastic)
*self.oerrorPtr = sqrt(DataInelastic)
*self.oxvalsPtr= tof
*self.oyvalsPtr = InelasticAngles


*self.oElasticDataPtr = float(DataElastic)
*self.oElasticErrorPtr = sqrt(DataElastic)
*self.oyvalsElasticPtr = ElasticAngles

;
*self.dataPtr = *self.odataPtr
*self.errorPtr = sqrt(*self.dataPtr)
*self.xvalsPtr = *self.oxvalsPtr
*self.yvalsPtr = *self.oyvalsPtr
;
*self.ElasticDataPtr = *self.oElasticDataPtr
*self.ElasticErrorPtr = *self.oElasticErrorPtr
*self.yvalsElasticPtr = *self.oyvalsElasticPtr
xvalsElastic=fltarr(n_elements(tof),12)
for i = 0,11 do begin
xvalsElastic[*,i]=tof
endfor
*self.xvalsElasticPtr = xvalsElastic
if long64(total(DataMonitor2)) eq 0 then begin
*self.Mon_cumPtr=PresetMonitor2
endif else begin
*self.Mon_cumPtr=long64(total(DataMonitor2))
endelse
*self.TOFMonitor1Ptr=float(DataMonitor1)
*self.oTOFMonitor2Ptr=float(DataMonitor2)
*self.TOFMonitor2Ptr=*self.oTOFMonitor2Ptr
*self.TOFMonitor3Ptr=float(DataMonitor3)

*self.tempPtr=temp

;
ElasticAngles=(*self.ConstantsPtr).DiffractionAngles
;print,'ElasticAngles[0] ',ElasticAngles[0]
;print,'ElasticAngles ',ElasticAngles
*self.ElasticdetPtr=ElasticAngles
;
self.ylabel = 'Group'
self.zlabel = 'Intensity'
self.ndet = n_elements(InelasticAngles)
self.nElasticdet = n_elements(ElasticAngles)


;print,'min(tof): ',min(tof)
;print,'n_elements(tof): ',n_elements(tof)
;print,'tof[1]-tof[0]: ',tof[1]-tof[0]
;print,'unix_start_time: ',unix_start_time
;print,'systime(1,unix_start_time): ',systime(0,unix_start_time)

self.unix_start_time = unix_start_time ; needed for the vanadium calibration routine

;   create structure with instrumental details needed for the data reduction
instrument_details={temp:temp,   $
              targetreflection:targetreflection,$
              timebinindices:timebinindices,    $
              TriffidAngles:TriffidAngles    $
              }
;
;print,instrument_details

*self.InstrumentPtr=instrument_details


;print,'snailphase: ',snailphase
;
;   All the information not required for the data reduction are stored in the header

header = strarr(25)

header[0]='Instrument: MARS'
header[1]='Title: '+strtrim(string(title),2)
header[2]='Sample name: '+strtrim(string(SampleName),2)
header[3]='Original file name: '+strtrim(string(FullFileName),2)
header[4]='start_time: '+strtrim(string(start_time),2)
header[5]='end_time: '+strtrim(string(end_time),2)
header[6]='User: '+strtrim(string(owner),2)
header[7]='Tel: '+strtrim(string(telephone_number),2)
header[8]='Address: '+strtrim(string(Address),2)
header[9]='Email: '+strtrim(string(Email),2)
header[10]='Instrument Responsible: '+strtrim(string(instrumentresponsible),2)
header[11]='Temperature of sample: '+strtrim(string(temp),2)
header[12]='Sample Environment: '+strtrim(string(environment),2)
header[13]='Target Reflection:'+strtrim(string(targetreflection),2)
header[14]='Analyser Scattering Angles: '+strtrim(string(TriffidAngles),2)
header[15]='Snail Chopper Speed: '+strtrim(string(SnailSpeed/60.0),2)+' Hz'
header[16]='Snail Chopper Phase: '+strtrim(string(SnailPhase),2)
header[17]='Master Chopper Speed: '+strtrim(string(MasterSpeed/60.0),2)+' Hz'
header[18]='Master Chopper Phase: '+strtrim(string(MasterPhase),2)
header[19]='Rabbit Chopper Speed: '+strtrim(string(RabbitSpeed/60.0),2)+' Hz'
header[20]='Rabbit Chopper Phase: '+strtrim(string(RabbitPhase),2)
header[21]='Chopper4 Speed: '+strtrim(string(Chopper4Speed/60.0),2)+' Hz'
header[22]='Chopper4 Phase: '+strtrim(string(Chopper4Phase),2)
header[23]='Chopper5 Speed: '+strtrim(string(Chopper5Speed/60.0),2)+' Hz'
header[24]='Chopper5 Phase: '+strtrim(string(Chopper5Phase),2)

*self.headerPtr = header

widget_control,self.TargetReflection_Field,set_value = targetreflection
;
;
END

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::subtract_bad_detectors,event = event,err = err
;return
;extract data
data=*self.dataPtr
;data[*,4]=0.0
ElasticData=*self.ElasticDataPtr
;ElasticData[*,1:*]=0.0
;help,ElasticData
;print,'total(ElasticData,1): ',total(ElasticData,1)
ndet=self.ndet
nElasticdet=self.nElasticdet
;first for the inelastic detectors
;find the mean triffid angle, excluding outliers
instrument_details=*self.InstrumentPtr
TriffidAngles=instrument_details.TriffidAngles
;print,'Original TriffidAngles: ',TriffidAngles
stats=moment(TriffidAngles,MDEV=MDEV)
AcceptanceLevel=0.5;
   CATCH, Error_status
if Error_status ne 0 then begin
AcceptanceLevel+=0.5
    if AcceptanceLevel gt 5.0 then begin
    catch, /cancel
    return
    endif
endif
while MDEV gt AcceptanceLevel do begin
AbsSD=abs(stats[0]-TriffidAngles)
WhereNotOutlier=where(AbsSD lt MDEV)
TriffidAngles=TriffidAngles[WhereNotOutlier]
stats=moment(TriffidAngles,MDEV=MDEV)
endwhile
Unique_Triffid_Angle=stats[0] ; take the average, should all be the same

widget_control,self.TriffidField,get_value = val
if val eq '' then widget_control,self.TriffidField,set_value = Unique_Triffid_Angle
;

instrument_details = create_struct(instrument_details,'Unique_Triffid_Angle',Unique_Triffid_Angle)

;print,'instrument_details.Unique_Triffid_Angle ',instrument_details.Unique_Triffid_Angle
 *self.InstrumentPtr = instrument_details
TriffidAngles=instrument_details.TriffidAngles ;reset
for i=0,ndet-1 do begin
height=max(data[*,i])-min(data[*,i])
if i eq 0 then begin
heightdet=height
endif else begin
heightdet=[heightdet,height]
endelse
;print,'height =',height
endfor
avheight=(moment(heightdet))[0]
;print,'avheight :',avheight
;
;Keep only those detectors with intensity greater than 1% of the average
;First identify those detectors
for i=0,ndet-1 do begin
    if heightdet[i] gt (0.01*avheight) then begin
       if abs(TriffidAngles[i] - Unique_Triffid_Angle) lt AcceptanceLevel then begin ;within half a degree
            if n_elements(good_det) eq 0 then begin
            good_det=i
            endif else begin
            good_det=[good_det,i]
            endelse
        endif
    endif
endfor

*self.good_detPtr=good_det

IF n_elements(good_det) NE 10 THEN BEGIN


*self.dataPtr=(*self.dataPtr)[*,good_det]
*self.errorPtr=sqrt(*self.dataPtr)
*self.yvalsPtr=(*self.yvalsPtr)[good_det]
self.ndet=n_elements(*self.yvalsPtr)
for i = 0,9 do begin
wheregood=where(i eq good_det)
    if wheregood eq -1 then begin
       if n_elements(BadDetectorsPtr) eq 0 then begin
              BadDetectorsPtr=ptr_new(i)
       endif else begin
       *BadDetectorsPtr=[*BadDetectorsPtr,i]
       endelse
    endif
endfor

InelasticDetectors=strarr(10)
InelasticDetectors[0]='Aare150'
InelasticDetectors[1]='Aare120'
InelasticDetectors[2]='Aare90'
InelasticDetectors[3]='Aare60'
InelasticDetectors[4]='Aare30'
InelasticDetectors[5]='Berg30'
InelasticDetectors[6]='Berg60'
InelasticDetectors[7]='Berg90'
InelasticDetectors[8]='Berg120'
InelasticDetectors[9]='Berg150'


for i = 0, n_elements(*BadDetectorsPtr)-1 do begin
    if i eq 0 then begin
    BadDetectorString=InelasticDetectors[(*BadDetectorsPtr)[i]]
    endif else begin
    BadDetectorString=BadDetectorString+', '+InelasticDetectors[(*BadDetectorsPtr)[i]]
    endelse
endfor
ptr_free,BadDetectorsPtr

treat=strarr(2)
treat[0] = 'Due to insufficient counts or incorrect angle, the data from the inelastic detectors '
treat[1] = BadDetectorString+' were not processed in the data reduction.'

*self.treatmentPtr = [*self.treatmentPtr,treat]

ENDIF
;now for the elastic detectors
for i=0,nElasticdet-1 do begin
height=max(ElasticData[*,i])-min(ElasticData[*,i])
if i eq 0 then begin
heightdet=height
endif else begin
heightdet=[heightdet,height]
endelse
;print,'height =',height
endfor
avheight=(moment(heightdet))[0]
;
;Keep only those detectors with intensity greater than 1% of the average
;First identify those detectors
for i=0,nElasticdet-1 do begin
    if heightdet[i] gt 0.01*avheight then begin
       if n_elements(good_Elasticdet) eq 0 then begin
       good_Elasticdet=i
       endif else begin
       good_Elasticdet=[good_Elasticdet,i]
       endelse
    endif
endfor

*self.good_ElasticdetPtr=good_Elasticdet



IF n_elements(good_Elasticdet) NE 12 THEN BEGIN
;print,'good_Elasticdet: ',good_Elasticdet
*self.ElasticDataPtr=(*self.ElasticDataPtr)[*,good_Elasticdet]
*self.ElasticErrorPtr=sqrt(*self.ElasticDataPtr)
*self.xvalsElasticPtr=(*self.xvalsElasticPtr)[*,good_Elasticdet]
*self.yvalsElasticPtr = (*self.yvalsElasticPtr)[good_Elasticdet]

*self.ElasticdetPtr=(*self.ElasticdetPtr)[good_Elasticdet]
self.nElasticdet=n_elements(*self.ElasticdetPtr)
;
for i = 0,11 do begin
wheregood=where(i eq good_Elasticdet)
    if wheregood eq -1 then begin
       if n_elements(BadElasticDetectorsPtr) eq 0 then begin
              BadElasticDetectorsPtr=ptr_new(i)
       endif else begin
       *BadElasticDetectorsPtr=[*BadElasticDetectorsPtr,i]
       endelse
    endif
endfor

ElasticDetectors=*self.ElasticDetectorsNamesPtr

for i = 0, n_elements(*BadElasticDetectorsPtr)-1 do begin
    if i eq 0 then begin
    BadDetectorString=ElasticDetectors[(*BadElasticDetectorsPtr)[i]]
    endif else begin
    BadDetectorString=BadDetectorString+', '+ElasticDetectors[(*BadElasticDetectorsPtr)[i]]
    endelse
endfor
ptr_free,BadElasticDetectorsPtr

treat=strarr(2)
treat[0] = 'Due to insufficient counts, the data from the elastic detectors '
treat[1] = BadDetectorString+' were not processed in the data reduction.'

*self.treatmentPtr = [*self.treatmentPtr,treat]

ENDIF

;print,'*self.treatmentPtr: ',*self.treatmentPtr

;print,'total(*self.ElasticDataPtr,1): ',total(*self.ElasticDataPtr,1)
;print,'total(*self.ElasticErrorPtr,1): ',total(*self.ElasticErrorPtr,1)
;woof=*self.ElasticDataPtr
;help,woof

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::sum_runs,event = event,err = err
err = 0
if n_elements(*self.sigFilePtr) eq 0 then begin
  err = -1
  return
endif

files = *self.sigFilePtr
nfiles = n_elements(files)
;print,'nfiles = ',nfiles
treat = 'Files used in sum: '
for i = 0,nfiles-1 do begin
  treat = [treat,files[i]]
  self->Nexus_read_raw_mars,files[i],event = event,err = err
  if err eq 1 then return
  if i eq 0 then begin
    data = *self.dataPtr
    DataElastic=*self.ElasticDataPtr
    temperature = *self.tempPtr
    Mon_cum = *self.Mon_cumPtr
    TOFMonitor1 = *self.TOFMonitor1Ptr
    TOFMonitor2 = *self.TOFMonitor2Ptr
    TOFMonitor3 = *self.TOFMonitor3Ptr
  endif else begin
    data+=*self.dataPtr
    DataElastic+=*self.ElasticDataPtr
    temperature = [temperature,*self.tempPtr]
    Mon_cum = [Mon_cum,*self.Mon_cumPtr]
    TOFMonitor1+= *self.TOFMonitor1Ptr
    TOFMonitor2+= *self.TOFMonitor2Ptr
    TOFMonitor3+= *self.TOFMonitor3Ptr
  endelse
endfor

*self.treatmentPtr = [*self.treatmentPtr,treat]
error = sqrt(data)
where_zero = where(data eq 0,count_zero)
if count_zero gt 0 then error[where_zero] = 1.0
*self.errorPtr = error
*self.oerrorPtr = error
*self.dataPtr = data
*self.odataPtr=data
*self.ElasticDataPtr=DataElastic
*self.oElasticDataPtr=DataElastic
ElasticError = sqrt(DataElastic)
where_zero = where(DataElastic eq 0,count_zero)
if count_zero gt 0 then ElasticError[where_zero] = 1.0
*self.ElasticErrorPtr=ElasticError
*self.oElasticErrorPtr=ElasticError
*self.Mon_cumPtr = Mon_cum
*self.TOFMonitor1Ptr = TOFMonitor1
*self.TOFMonitor2Ptr = TOFMonitor2
*self.TOFMonitor3Ptr = TOFMonitor3
*self.tempPtr = temperature



return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::subtract_background,event = event
;
; In order to subtract the background we must do a few things first.....
;
; 1.  Pull out the signal data and store it in local variables.  We are assuming
;     that the data has been converted to energy.
; 2.  Read in and sum up all of the background files.
; 3   Remove bad detectors, sort, and remove degeneracies the same way as applied for the signal data
; 4.  Convert to energy and normalize to the monitor.
; 5.  Rebin the background onto the same energy grid as the signal file.
; 6.  Perform the subtraction scaling the background up to the signal file.
;
if n_elements(*self.dataPtr) eq 0 then return
;
if n_elements(*self.bgFilePtr) eq 0 then return
nbgFiles = n_elements(*self.bgFilePtr)
bgFiles = *self.bgFilePtr

; Store the signal data locally while determining the background signal


odata = *self.odataPtr
oerror = *self.oerrorPtr
oxvals = *self.oxvalsPtr
oyvals = *self.oyvalsPtr
oElasticData = *self.oElasticDataPtr
oElasticError = *self.oElasticErrorPtr
oyvalsElastic = *self.oyvalsElasticPtr
oTOFMonitor = *self.oTOFMonitor2Ptr
sigData = *self.dataPtr
sigError = *self.errorPtr
sigx = *self.xvalsPtr
sigy = *self.yvalsPtr
sigTemp = *self.tempPtr
sigMon_cum = *self.Mon_cumPtr
sigTOFMonitor1 = *self.TOFMonitor1Ptr
sigTOFMonitor2 = *self.TOFMonitor2Ptr
sigTOFMonitor3 = *self.TOFMonitor3Ptr
signdet=self.ndet
header=*self.headerPtr
instrument_details = *self.InstrumentPtr
ElasticData=*self.ElasticDataPtr
ElasticError=*self.ElasticErrorPtr
xvalsElastic=*self.xvalsElasticPtr
ElasticAngles = *self.ElasticdetPtr




treat = 'Background file(s) used in subtraction:'
; Sum the background files if there are more than one
for i = 0,nbgfiles-1 do begin
  treat = [treat,bgfiles[i]]
    self->Nexus_read_raw_mars,bgfiles[i],event = event
  if i eq 0 then begin
    bgdata = *self.dataPtr
;    help,bgdata
    bgtemperature = *self.tempPtr
    bgMon_cum = *self.Mon_cumPtr
    bgTOFMonitor2 = *self.TOFMonitor2Ptr
  endif else begin
    bgdata = bgdata+*self.dataPtr
    bgtemperature = [bgtemperature,*self.tempPtr]
    bgMon_cum = [bgMon_cum,*self.Mon_cumPtr]
    ;bgTOFMonitor2 = [bgTOFMonitor2,*self.TOFMonitor2Ptr]
    bgTOFMonitor2 += *self.TOFMonitor2Ptr

  endelse
endfor

*self.InstrumentPtr = instrument_details




InelasticAngles=*self.yvalsPtr
good_det=*self.good_detPtr
bgData=bgData[*,good_det]
InelasticAngles=InelasticAngles[good_det]
*self.treatmentPtr = [*self.treatmentPtr,treat]
*self.dataPtr = bgData
bgError = sqrt(bgData)
*self.errorPtr = bgError
*self.yvalsPtr = InelasticAngles
*self.tempPtr = bgtemperature
*self.Mon_cumPtr = bgMon_cum
*self.TOFMonitor2Ptr = bgTOFMonitor2
; Convert the background files to energy
widget_control,self.DataOutputTypesGroup,get_value = DataOutput
;convert to energy unless the desired quqntity is S(theta,t)
widget_control,self.BackgroundSubtractionField,get_value = ScaleFactor
ScaleFactor=float(ScaleFactor[0])




if DataOutput eq 0 then begin
self->convert_to_energy,event = event,/background
endif else begin
self->Time_Bin_Grouping,event = event,/background
endelse
bgx = *self.xvalsPtr
bgData = *self.dataPtr
bgError = *self.errorPtr
sigMon = total(sigMon_cum)
bgMon = total(bgMon_cum)
sf = (ScaleFactor*sigMon/bgMon)
newData = sigData
newError = sigError




;help, newdata
;help,bgdata
; Cast the scale factor into an appropriate form
datSize = size(sigData)
nchan = datSize[1]
ndet = datSize[2]

sfm = (1+bytarr(nchan))#(1+fltarr(ndet))
newData[*,0:(ndet-1)] = 1.0*sigData[*,0:(ndet-1)] - $
                           sf*((bgData[*,0:(ndet-1)])*sfm)
newError[*,0:(ndet-1)] = sqrt(sigError[*,0:(ndet-1)]^2+ $
                                 (sf*(bgError[*,0:(ndet-1)])*sfm)^2)
*self.xvalsPtr = sigx
*self.yvalsPtr = sigy
*self.dataPtr = newData
*self.errorPtr = newError
*self.tempPtr = [sigTemp];[sigTemp,bgtemperature]
*self.Mon_cumPtr = [sigMon_cum,bgMon_cum]
*self.TOFMonitor1Ptr = sigTOFMonitor1
*self.TOFMonitor2Ptr = sigTOFMonitor2
*self.TOFMonitor3Ptr = sigTOFMonitor3
self.ndet=signdet
*self.headerPtr = header
*self.ElasticDataPtr=ElasticData
*self.ElasticErrorPtr=ElasticError
*self.xvalsElasticPtr=xvalsElastic
*self.odataPtr = odata
*self.oerrorPtr = oerror
*self.oxvalsPtr= oxvals
*self.oyvalsPtr = oyvals
*self.oElasticDataPtr = oElasticData
*self.oElasticErrorPtr = oElasticError
*self.oyvalsElasticPtr = oyvalsElastic
*self.oTOFMonitor2Ptr=oTOFMonitor
*self.ElasticdetPtr=ElasticAngles

return

end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function marsreduction::Bragg,dspace,theta
return, 2.0*dspace*sin(theta*!DTOR)
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::process_diffraction_data,event = event
;get time bin indices and constants
widget_control,self.Misc_Group1,get_value = val
normalise=val[3]
   CATCH, Error_status
if Error_status ne 0 then begin
catch, /cancel
msg=strarr(3)
msg[0]='Unable to Normalise Diffraction Data.'
msg[1]='to the Monitor Spectrum:'
msg[2]='Error Message from IDL: '+!ERROR_STATE.MSG
    void=dialog_message(dialog_parent=event.top,/error,msg)
normalise=0
endif

ElasticData_x=*self.xvalsElasticPtr
ElasticData=*self.ElasticDataPtr
ElasticError=*self.ElasticErrorPtr

;;print,'good_Elasticdet: ',good_Elasticdet
;*self.ElasticDataPtr=(*self.ElasticDataPtr)[*,good_Elasticdet]
;*self.ElasticErrorPtr=sqrt(*self.ElasticDataPtr)
;*self.xvalsElasticPtr=(*self.xvalsElasticPtr)[*,good_Elasticdet]
;*self.yvalsElasticPtr = (*self.yvalsElasticPtr)[good_Elasticdet]
;
;*self.ElasticdetPtr=(*self.ElasticdetPtr)[good_Elasticdet]
;self.nElasticdet=n_elements(*self.ElasticdetPtr)

dimensions=size(ElasticData_x)
notimebin=dimensions[1]


;good_Elasticdet=*self.good_ElasticdetPtr
n_Elasticdet=self.nElasticdet
;print,'n_Elasticdet: ',n_Elasticdet
instrument_details = *self.InstrumentPtr
timebinindices=instrument_details.timebinindices
TimeBinIndices=strsplit(TimeBinIndices,',',/extract)
TimeBinIndices=fix(TimeBinIndices)
if (TimeBinIndices[0] ge TimeBinIndices[6]) and (TimeBinIndices[1] ge TimeBinIndices[7]) then begin
TimeBinIndices[0]-=notimebin
TimeBinIndices[1]-=notimebin
endif
if (TimeBinIndices[2] ge TimeBinIndices[6]) and (TimeBinIndices[3] ge TimeBinIndices[7]) then begin
TimeBinIndices[2]-=notimebin
TimeBinIndices[3]-=notimebin
endif
constants=*self.ConstantsPtr
; at this point, this pointer is a 2d array containing the tof values for each detector
; the tof vectors for the detectors are identical
h=constants.h
mn=constants.mn
HP=constants.Histogram_Period
;diffraction detectors
lDiff=constants.lDiff
; tof monitor
lTOFMon=constants.lTOFMon

UpstreamMonitorSensitivity=float(constants.UpstreamMonitorSensitivity)
MonitorPressure=(UpstreamMonitorSensitivity/1.0e-2)*0.053 ;bars
ub=MonitorPressure*0.294 ;0.294 is the c value in Haffa's formulation
;
;
widget_control,self.MonitorSpectrumNorm,get_value = slider
slider=fix(slider[0])
;help,ElasticData_x
;help,n_Elasticdet
;print,'total(ElasticData,1)1: ',total(ElasticData,1)
;print,'total(ElasticError,1)1: ',total(ElasticError,1)
;print,total(ElasticData)
;time bin cull with errors
StartBin=TimeBinIndices[4]
EndBin=TimeBinIndices[5]
;print,StartBin
;print,EndBin
IF endbin GT startbin THEN BEGIN
ElasticData_x=ElasticData_x[StartBin:EndBin,*]
ElasticData=ElasticData[StartBin:EndBin,*]
ElasticError=ElasticError[StartBin:EndBin,*]
ENDIF ELSE BEGIN
dimensions=size(ElasticData_x)
channels=dimensions[1]
ndets=dimensions[2]
width=channels-startbin+endbin+1
firstbit=channels-startbin
secondbit=endbin+1

xdat=fltarr(width,n_Elasticdet)
ydat=fltarr(width,n_Elasticdet)
yerror=fltarr(width,n_Elasticdet)
xdat[0:firstbit-1,*]=ElasticData_x[startbin:channels-1,*]-HP
ydat[0:firstbit-1,*]=ElasticData[startbin:channels-1,*]
yerror[0:firstbit-1,*]=ElasticError[startbin:channels-1,*]
xdat[firstbit:firstbit+secondbit-1,*]=ElasticData_x[0:endbin,*]
ydat[firstbit:firstbit+secondbit-1,*]=ElasticData[0:endbin,*]
yerror[firstbit:firstbit+secondbit-1,*]=ElasticError[0:endbin,*]
ElasticData_x=xdat
ElasticData=ydat
ElasticError=yerror
ENDELSE



v=lDiff/(reform(ElasticData_x[*,0])/1.0e6)
LambdaDiff=(h*1e10)/(mn*v)
;print,'LambdaDiff: ',LambdaDiff
;;
;print,''
;
xdata=*self.oxvalsPtr
ydata=*self.oTOFMonitor2Ptr ;note the use of the original data set, which has not been culled
StartBin=TimeBinIndices[0]
EndBin=TimeBinIndices[1]

self->timebincull_Red,startbin,endbin,xdata,ydata,slider,event=event
DataMonitor2_x=xdata
DataMonitor2=ydata
;print,'min(xdata): ',min(xdata)
;print,'max(xdata): ',max(xdata)
;
;
;
v=lTOFMon/(DataMonitor2_x/1.0e6)
LambdaMon=(h*1e10)/(mn*v)
;print,'LambdaMon: ',LambdaMon
Mon_Efficiency=1-exp(-ub*LambdaMon)
DataMonitor2/=Mon_Efficiency ; DataMonitor2 now corresponds to a black detector
;extract dimension of time channels
channels_mon=n_elements(LambdaMon)
channels_diff=n_elements(LambdaDiff)
index_map=intarr(2,channels_diff)
;
index_map[0,*]=indgen(channels_diff)
udiff=1+bytarr(channels_diff)
umon=1+bytarr(channels_mon)
diff=abs(LambdaDiff#umon-udiff#LambdaMon)
for i=0,channels_diff-1 do begin
void=min(diff[i,*],ind,/absolute)
index_map[1,i]=ind
endfor
;help,ElasticData
;
;print,'min(LambdaMon): ',min(LambdaMon)
;print,'max(LambdaMon): ',max(LambdaMon)
;print,'min(LambdaDiff): ',min(LambdaDiff)
;print,'max(LambdaDiff): ',max(LambdaDiff)
;print,''
;print,'total(DataMonitor2): ',total(DataMonitor2)
;
;print,'total(ElasticData,1)2: ',total(ElasticData,1)
;print,'total(ElasticError,1)2: ',total(ElasticError,1)
;help,ElasticData
;help,ElasticError
IF normalise eq 1 THEN BEGIN
for i=0,channels_diff-1 do begin
;print,'DataMonitor2[index_map[1,i]]: ',DataMonitor2[index_map[1,i]]
    if DataMonitor2[index_map[1,i]] gt 100 then begin  ; we must have reasonable statistics in the monitor
;print,'woof'
;    ElasticError[i,*]/=DataMonitor2[index_map[1,i]]
    ElasticError[i,*]=sqrt((ElasticData[i,*]/DataMonitor2[index_map[1,i]]^2) + $
             (ElasticData[i,*]^2/DataMonitor2[index_map[1,i]]^3))  ; error treatment according to Vladamir
    ElasticData[i,*]/=DataMonitor2[index_map[1,i]]
     endif else begin
;     print,'woof'
    ElasticData[i,*]=0.0
    ElasticError[i,*]=1e-6
    endelse


if (index_map[1,i] eq 0) or (index_map[1,i] eq (n_elements(DataMonitor2)-1)) then begin
    if n_elements(reject) eq 0 then begin
    reject=i
    endif else begin
    reject=[reject,i]
    endelse
endif
endfor
;help,ElasticData
;print,'total(ElasticData,1)3: ',total(ElasticData,1)
;print,'total(ElasticError,1)3: ',total(ElasticError,1)

if n_elements(reject) ne 0 then begin
;help,reject
;print,'reject: ',reject
ElasticData_new=fltarr(channels_diff-n_elements(reject),n_Elasticdet)
ElasticError_new=fltarr(channels_diff-n_elements(reject),n_Elasticdet)
ElasticData_x_new=fltarr(channels_diff-n_elements(reject),n_Elasticdet)
;help,ElasticData_new
    j=0
    k=0
    for i=0,channels_diff-1 do begin
    whereiconrej=where(i eq reject,count)
    if count ne 0 then begin
    k+=1
    endif else begin
    ElasticData_new[j,*]=ElasticData[k,*]
    ElasticError_new[j,*]=ElasticError[k,*]
    ElasticData_x_new[j,*]=ElasticData_x[k,*]
    j+=1
    k+=1
    endelse
    endfor
;
;
ElasticData=ElasticData_new
ElasticError=ElasticError_new
ElasticData_x=ElasticData_x_new
endif
ENDIF
;apply cull
*self.ElasticDataPtr=ElasticData
*self.ElasticErrorPtr=ElasticError
*self.xvalsElasticPtr=ElasticData_x

;print,'max(ElasticData[*,0]) ',max(ElasticData[*,0])

treat='Diffraction Data have been Processed'
*self.treatmentPtr = [*self.treatmentPtr,treat]
;is d-spacing requested?
widget_control,self.DiffDataOutputTypesGroup,get_value = val
if val eq 0 then begin ; convert from tof to d-spacing
;first determine theta values for the good detectors
;good_Elasticdet=*self.good_ElasticdetPtr
;ElasticAngles=(*self.oyvalsElasticPtr)[good_Elasticdet]
ElasticAngles=*self.yvalsElasticPtr
print,'h :',h
print,'mn :',mn
print,'lDiff :',lDiff
print,'ElasticAngles :',ElasticAngles

for i = 0, n_Elasticdet-1 do begin
(*self.xvalsElasticPtr)[*,i]*=((h*1e4)/(2.0*mn*lDiff*sin((ElasticAngles[i]*!DTOR/2.0))))
endfor
treat='The TOF to the diffraction detectors has been converted to d-spacing'
*self.treatmentPtr = [*self.treatmentPtr,treat]
self.DiffractionXlabel='d-spacing / A'
endif else begin
self.DiffractionXlabel='Time / microseconds'
endelse
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::timebincull_Red,startbin,endbin,xdata,ydata,slider,MultiArray=MultiArray,event=event
;
;if slider eq 100 then print,'xdata ',xdata
constants=*self.ConstantsPtr
HP=constants.Histogram_Period
dimensions=size(xdata)
;print,'dimensions :',dimensions
;if dimensions[0] eq 1 then begin
channels=dimensions[1]
;endif else begin
;channels=dimensions[2]
;endelse
;print,'channels: ',channels
;slider=100
HP_CORMINUSFIRST=0.0
HP_CORMINUSSECOND=0.0
HP_CORADDFIRST=0.0
HP_CORADDSECOND=0.0
if startbin lt 0 then begin
startbin+=channels
endbin+=channels
HP_CORMINUSFIRST=HP
HP_CORMINUSSECOND=HP
endif
IF endbin GT startbin THEN BEGIN
width=endbin-startbin+1
newwidth=fix(width*(slider/100.0))
WidthAdjustment=fix((newwidth-width)/2) ;just in case
newwidth=width+2*WidthAdjustment
newstart=startbin-WidthAdjustment
newend=endbin+WidthAdjustment
;print,'newstart1: ',newstart
;print,'newend1: ',newend
;print,'channels: ',channels

if newstart lt 0 then begin
newstart+=channels
HP_CORMINUSFIRST=HP
endif
if newend gt (channels-1) then begin
newend-=channels
HP_CORADDSECOND=HP
endif
ENDIF ELSE BEGIN
HP_CORMINUSFIRST=HP
width=channels-startbin+endbin+1
newwidth=fix(width*(slider/100.0))
WidthAdjustment=fix((newwidth-width)/2) ;just in case
newwidth=width+2*WidthAdjustment
newstart=startbin-WidthAdjustment
newend=endbin+WidthAdjustment
if newstart gt (channels-1) then begin
newstart-=channels
HP_CORADDFIRST=HP
endif
if newend lt 0 then begin
newend+=channels
HP_CORMINUSSECOND=HP
endif
ENDELSE
;print,'channels: ' ,channels
;print,'newwidth: ' ,newwidth
;print,'newstart: ' ,newstart
;print,'newend: ' ,newend
;print,'HP_CORMINUSFIRST: ',HP_CORMINUSFIRST
;print,'HP_CORMINUSSECOND: ',HP_CORMINUSSECOND
;print,'HP_CORADDFIRST: ',HP_CORADDFIRST
;print,'HP_CORADDSECOND: ',HP_CORADDSECOND
;
IF newend GT newstart THEN BEGIN
if n_elements(MultiArray) eq 0 then begin
xdata=xdata[newstart:newend]-HP_CORMINUSFIRST+HP_CORADDFIRST
ydata=ydata[newstart:newend]
endif else begin
;print,'newstart2: ',newstart
;print,'newend2: ',newend
;help,xdata
xdata=xdata[newstart:newend,*]-HP_CORMINUSFIRST+HP_CORADDFIRST
ydata=ydata[newstart:newend,*]
endelse
ENDIF ELSE BEGIN
firstbit=channels-newstart
secondbit=newend+1
;print,'newstart: ' ,newstart
;print,'newend: ' ,newend
;print,'WidthAdjustment: ' ,WidthAdjustment
;print,'width: ' ,width
;print,'newwidth: ' ,newwidth
;print,'firstbit: ' ,firstbit
;print,'secondbit: ' ,secondbit
;print,''
if dimensions[0] eq 1 then begin
xdat=fltarr(newwidth)
ydat=fltarr(newwidth)
xdat[0:firstbit-1]=xdata[newstart:channels-1]-HP_CORMINUSFIRST+HP_CORADDFIRST
;if slider eq 100 then print,'xdat ',xdat
ydat[0:firstbit-1]=ydata[newstart:channels-1]
xdat[firstbit:firstbit+secondbit-1]=xdata[0:newend]-HP_CORMINUSSECOND+HP_CORADDSECOND
;if slider eq 100 then print,'xdat ',xdat
ydat[firstbit:firstbit+secondbit-1]=ydata[0:newend]
endif else begin
xdat=fltarr(newwidth,dimensions[2])
ydat=fltarr(newwidth,dimensions[2])
xdat[0:firstbit-1,*]=xdata[newstart:channels-1,*]-HP_CORMINUSFIRST+HP_CORADDFIRST
ydat[0:firstbit-1,*]=ydata[newstart:channels-1,*]
xdat[firstbit:firstbit+secondbit-1,*]=xdata[0:newend,*]-HP_CORMINUSSECOND+HP_CORADDSECOND
ydat[firstbit:firstbit+secondbit-1,*]=ydata[0:newend,*]
endelse
xdata=xdat
ydata=ydat
ENDELSE
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::convert_to_energy,event = event,background = background,vanadium = vanadium
;
;
widget_control,self.Misc_Group1,get_value = val
normalise=val[3]
;
   CATCH, Error_status
if Error_status ne 0 then begin
catch, /cancel
msg=strarr(3)
msg[0]='Unable to Normalise Inelastic Data.'
msg[1]='to the Monitor Spectrum:'
msg[2]='Error Message from IDL: '+!ERROR_STATE.MSG
    void=dialog_message(dialog_parent=event.top,/error,msg)
normalise=0
endif
;
;
; Get the data
sigData = *self.dataPtr
sigError = *self.errorPtr
sigx = *self.xvalsPtr
dimensions=size(sigData)
ndets=dimensions[2]
notimebin=dimensions[1]
instrument_details = *self.InstrumentPtr
timebinindices=instrument_details.timebinindices
;print,'timebinindices: ',timebinindices
TimeBinIndices=strsplit(TimeBinIndices,',',/extract)
TimeBinIndices=fix(TimeBinIndices)
if (TimeBinIndices[0] ge TimeBinIndices[6]) and (TimeBinIndices[1] ge TimeBinIndices[7]) then begin
TimeBinIndices[0]-=notimebin
TimeBinIndices[1]-=notimebin
endif
if (TimeBinIndices[2] ge TimeBinIndices[6]) and (TimeBinIndices[3] ge TimeBinIndices[7]) then begin
TimeBinIndices[2]-=notimebin
TimeBinIndices[3]-=notimebin
endif
constants=*self.ConstantsPtr
conv=constants.meVtoJoules
D=constants.D
h=constants.h
dspace_002=constants.dspace_002
mn=constants.mn
lprim=constants.lprim

;print,'D :',D
;print,'h :',h
;print,'dspace_002 :',dspace_002
;print,'mn :',mn
;print,'lprim :',lprim

UpstreamMonitorSensitivity=float(constants.UpstreamMonitorSensitivity)
MonitorPressure=(UpstreamMonitorSensitivity/1.0e-2)*0.053 ;bars
ub=MonitorPressure*0.294 ;0.294 is the c value in Haffa's formulation
;


;calculated wavelength
tr=self.WorkingReflection

widget_control,self.TriffidAngle_Group,get_value=TriffidAngle_Group
if TriffidAngle_Group eq 0 then begin
theta=instrument_details.Unique_Triffid_Angle
endif else begin
widget_control,self.TriffidField,get_value=theta
theta=float(theta[0])
endelse


;theta=50.03
;print,'theta = ',theta
;help,theta
;print,'instrument_details.TriffidAngles = ',instrument_details.TriffidAngles
if tr eq '002' then dspace=dspace_002
if tr eq '002 Assumed' then dspace=dspace_002
if tr eq '004' then dspace=dspace_002/2.0
if tr eq '006' then dspace=dspace_002/3.0
if tr eq '008' then dspace=dspace_002/4.0
lambda_analyser=self->Bragg(dspace,theta)
E_analyser=81.80321/(lambda_analyser)^2
;print,'E_analyser: ',E_analyser
v_analyser=sqrt(E_analyser*conv*2.0/mn)
t_analyser=1e6*D/v_analyser
;print,'E_analyser: ',E_analyser
widget_control,self.MonitorSpectrumNorm,get_value = monitorslider
monitorslider=fix(monitorslider[0])
;print,'monitorslider: ',monitorslider
widget_control,self.MonitorSpectrumDisplay,get_value = monitorsliderDisplay
monitorsliderDisplay=fix(monitorsliderDisplay[0])
case tr of
'002':  $
begin
startbin=TimeBinIndices[6]
endbin=TimeBinIndices[7]
end
'002 Assumed':  $
begin
startbin=TimeBinIndices[6]
endbin=TimeBinIndices[7]
end
'004':  $
begin
startbin=TimeBinIndices[8]
endbin=TimeBinIndices[9]
end
'006':  $
begin
startbin=TimeBinIndices[10]
endbin=TimeBinIndices[11]
end
'008':  $
begin
startbin=TimeBinIndices[12]
endbin=TimeBinIndices[13]
end
endcase
;startbin=0
;endbin=n_elements(sigx)-1

;print,'ndets: ',ndets
;print,'startbin: ',startbin
;print,'endbin: ',endbin

dummyx=fltarr(notimebin,ndets) ;good solution for now
dummyx[*,0]=sigx
slider=100.0
self->timebincull_Red,startbin,endbin,dummyx,sigData,slider,/MultiArray,event=event
dummyx=fltarr(notimebin,ndets) ;good solution for now
dummyx[*,0]=sigx
self->timebincull_Red,startbin,endbin,dummyx,sigError,slider,/MultiArray,event=event
tprim=reform(dummyx[*,0])-t_analyser
;
;sigData=sigData[startbin:endbin,*]
;sigError=sigError[startbin:endbin,*]
;tprim=sigx[startbin:endbin]-t_analyser
;help,sigData
;help,sigError
;help,tprim

;print,'tprim: ',tprim
;print,'t_analyser: ',t_analyser
vprim=lprim/(tprim/1.0e6)
Eprim_joules=0.5*mn*vprim^2
Eprim_meV=Eprim_joules/conv
;print,'Eprim_meV: ',Eprim_meV
Etrans_meV=Eprim_meV-E_analyser
;help,Etrans_meV
;print,'Etrans_meV: ',Etrans_meV
LambdaPrim=(h*1e10)/(mn*vprim)
;TOF Monitor
lTOFMon=constants.lTOFMon
StartBin=TimeBinIndices[0]
EndBin=TimeBinIndices[1]
slider=monitorslider ;for calibration purposes
xdata=sigx
ydata=*self.TOFMonitor2Ptr
;print,'monitor: '
self->timebincull_Red,startbin,endbin,xdata,ydata,slider,event=event
;print,' '
DataMonitor2_x=xdata
DataMonitor2=ydata
;print,'n_elements(DataMonitor2_x): ',n_elements(DataMonitor2_x)
;print,'energy'
;print,'startbin ',startbin
;print,'endbin ',endbin
;print,'sigx ',sigx
;print,'xdata ',xdata
;print,'slider ',slider

v=lTOFMon/(DataMonitor2_x/1.0e6)
LambdaMon=(h*1e10)/(mn*v)
ETOFMon_joules=0.5*mn*v^2
ETOFMon_meV=ETOFMon_joules/conv
Mon_Efficiency=1-exp(-ub*LambdaMon)

DataMonitor2/=(Mon_Efficiency*(DataMonitor2_x/1.0e6)) ; DataMonitor2 now corresponds to a normal 1/k detector
;extract dimension of time channels
channels_mon=n_elements(LambdaMon)
channels_mica=n_elements(LambdaPrim)
index_map=intarr(2,channels_mica)
index_map[0,*]=indgen(channels_mica)
umica=1+bytarr(channels_mica)
umon=1+bytarr(channels_mon)

;print,'LambdaPrim ',LambdaPrim 
;print,'LambdaMon ',LambdaMon 

diff=abs(LambdaPrim#umon-umica#LambdaMon)
for i=0,channels_mica-1 do begin
void=min(diff[i,*],ind)
index_map[1,i]=ind
endfor

IF normalise EQ 1 THEN BEGIN
;normalise to the monitor
for i=0,channels_mica-1 do begin
    if DataMonitor2[index_map[1,i]] gt 500 then begin  ; we must have reasonable statistics in the monitor
    sigError[i,*]=sqrt((sigData[i,*]/DataMonitor2[index_map[1,i]]^2) + $
             (sigData[i,*]^2/DataMonitor2[index_map[1,i]]^3))  ; error treatment according to Vladamir
    sigData[i,*]/=DataMonitor2[index_map[1,i]] ; Correction according to Dorner
;    sigError[i,*]/=DataMonitor2[index_map[1,i]]
    endif else begin
    sigData[i,*]=0.0
    sigError[i,*]=0.0
    endelse

if (index_map[1,i] eq 0) or (index_map[1,i] eq (n_elements(DataMonitor2)-1)) then begin
;print,'index_map[1,i]: ',index_map[1,i]
    if n_elements(reject) eq 0 then begin
    reject=i
    endif else begin
    reject=[reject,i]
    endelse
endif
endfor


if n_elements(reject) ne 0 then begin
;help,reject
;print,'reject: ',reject
sigData_new=fltarr(channels_mica-n_elements(reject),ndets)
sigError_new=fltarr(channels_mica-n_elements(reject),ndets)
Etrans_meV_new=fltarr(channels_mica-n_elements(reject))
    j=0
    k=0
    for i=0,channels_mica-1 do begin
    whereiconrej=where(i eq reject,count)
    if count ne 0 then begin
    k+=1
    endif else begin
    sigData_new[j,*]=sigData[k,*]
    sigError_new[j,*]=sigError[k,*]
    Etrans_meV_new[j]=Etrans_meV[k]
    j+=1
    k+=1
    endelse
    endfor
;
;
sigData=sigData_new
sigError=sigError_new
Etrans_meV=Etrans_meV_new
endif
ENDIF ;normalise to monitor endif

;;;
;for display purposes
StartBin=TimeBinIndices[0]
EndBin=TimeBinIndices[1]
slider=monitorsliderDisplay ;for display purposes
;slider=110
xdata=sigx
ydata=*self.TOFMonitor2Ptr
self->timebincull_Red,startbin,endbin,xdata,ydata,slider,event=event
DataMonitor2_x=xdata
DataMonitor2=ydata

v=lTOFMon/(DataMonitor2_x/1.0e6)
LambdaMon=(h*1e10)/(mn*v)
ETOFMon_joules=0.5*mn*v^2
ETOFMon_meV=ETOFMon_joules/conv
channels_mon=n_elements(DataMonitor2_x)

;jacobian for transformation of time to energy
norm=(total(DataMonitor2_x^3))/channels_mon
for i = 0, channels_mon-1 do begin
DataMonitor2[i,*]=DataMonitor2[i,*]*(DataMonitor2_x[i]^3)/norm
endfor


;according to Felix, the intensity should also be multiplied by ti^3 (tprim^3)

;;;;;;;;help,sigdata
;;;;;;;;help,sigError
;;;;;;;;help,tprim
;;;;;;;;for i = 0,9 do begin
;;;;;;;;sigData[*,i]*=tprim^3
;;;;;;;;sigError[*,i]*=tprim^3
;;;;;;;;endfor

;   Is Detailed balance requested:
if val[0] eq 1 then begin
c=2.0*instrument_details.temp[0]*0.08617385692
nx=n_elements(Etrans_meV)
for i = 0, nx-1 do begin
sigdata[i,*]*=exp(-Etrans_meV[i]/c)
sigerror[i,*]*=exp(-Etrans_meV[i]/c)
endfor
treat = ['Detailed Balance Correction Has Been Applied to the Data.']
*self.treatmentPtr = [*self.treatmentPtr,treat]
endif

*self.dataPtr = reverse(sigData)
*self.errorPtr = reverse(sigError)
*self.xvalsPtr = reverse(Etrans_meV)
*self.TOFMonitor2Ptr=reverse(DataMonitor2)
*self.TOFMonitor2xPtr=reverse(ETOFMon_meV)
lTOFPostMon=constants.lTOFPostMon
xdata=sigx
ydata=*self.TOFMonitor3Ptr
slider=monitorsliderDisplay ;for display purposes
StartBin=TimeBinIndices[2]
EndBin=TimeBinIndices[3]
self->timebincull_Red,startbin,endbin,xdata,ydata,slider,event=event
DataMonitor3_x=xdata
DataMonitor3=ydata
v=lTOFPostMon/(DataMonitor3_x/1.0e6)
ETOFPostMon_joules=0.5*mn*v^2
ETOFPostMon_meV=ETOFPostMon_joules/conv
channels_mon=n_elements(DataMonitor3_x)
norm=(total(DataMonitor3_x^3))/channels_mon
for i = 0, channels_mon-1 do begin
DataMonitor3[i,*]=DataMonitor3[i,*]*(DataMonitor3_x[i]^3)/norm
endfor
*self.TOFMonitor3Ptr=reverse(DataMonitor3)
*self.TOFMonitor3xPtr=reverse(ETOFPostMon_meV)
;
self.MonitorsXlabel='Energy / meV'

if keyword_set(background) or keyword_set(vanadium) then return

instrument_details = create_struct(instrument_details,'lambda',lambda_analyser)
 *self.InstrumentPtr = instrument_details
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::Time_Bin_Grouping,event = event,background = background
sigx = *self.xvalsPtr
dimensions=size(sigx)
notimebin=dimensions[1]
ndets=dimensions[2]
instrument_details = *self.InstrumentPtr
timebinindices=instrument_details.timebinindices
TimeBinIndices=strsplit(TimeBinIndices,',',/extract)
TimeBinIndices=fix(TimeBinIndices)
;print,'timebinindices :',timebinindices
;print,'sigx[timebinindices[0]]: ',sigx[timebinindices[0]]
;print,'sigx[timebinindices[1]]: ',sigx[timebinindices[1]]
;print,'sigx[timebinindices[6]]: ',sigx[timebinindices[6]]
;print,'sigx[timebinindices[7]]: ',sigx[timebinindices[7]]
widget_control,self.MonitorSpectrumDisplay,get_value = monitorsliderDisplay
monitorsliderDisplay=fix(monitorsliderDisplay[0])

if (TimeBinIndices[0] ge TimeBinIndices[6]) and (TimeBinIndices[1] ge TimeBinIndices[7]) then begin
TimeBinIndices[0]-=notimebin
TimeBinIndices[1]-=notimebin
endif
if (TimeBinIndices[2] ge TimeBinIndices[6]) and (TimeBinIndices[3] ge TimeBinIndices[7]) then begin
TimeBinIndices[2]-=notimebin
TimeBinIndices[3]-=notimebin
endif
constants=*self.ConstantsPtr
dspace_002=constants.dspace_002
tr=self.WorkingReflection
case tr of
'002':  $
begin
startbin=TimeBinIndices[6]
endbin=TimeBinIndices[7]
startbin=0
endbin=n_elements(sigx)-1
end
'002 Assumed':  $
begin
startbin=TimeBinIndices[6]
endbin=TimeBinIndices[7]
end
'004':  $
begin
startbin=TimeBinIndices[8]
endbin=TimeBinIndices[9]
startbin=0
endbin=n_elements(sigx)-1
end
'006':  $
begin
startbin=TimeBinIndices[10]
endbin=TimeBinIndices[11]
end
'008':  $
begin
startbin=TimeBinIndices[12]
endbin=TimeBinIndices[13]
startbin=0
endbin=n_elements(sigx)-1
end
endcase


;dummyx=fltarr(notimebin,ndets) ;good solution for now
;dummyx[*,0]=sigx
;slider=100.0
;self->timebincull_Red,startbin,endbin,dummyx,sigData,slider,/MultiArray,event=event
;dummyx=fltarr(notimebin,ndets) ;good solution for now
;dummyx[*,0]=sigx
;self->timebincull_Red,startbin,endbin,dummyx,sigError,slider,/MultiArray,event=event
;tprim=reform(dummyx[*,0])-t_analyser

;*self.dataPtr = (*self.dataPtr)[startbin:endbin,*]
;*self.errorPtr = (*self.errorPtr)[startbin:endbin,*]
;*self.xvalsPtr = sigx[startbin:endbin,*]
;
ydata=*self.TOFMonitor2Ptr
xdata=sigx
StartBin=TimeBinIndices[0]
EndBin=TimeBinIndices[1]
slider=monitorsliderDisplay
self->timebincull_Red,startbin,endbin,xdata,ydata,slider,event=event
DataMonitor2_x=xdata
;print,'time'
;print,'startbin ',startbin
;print,'endbin ',endbin
;print,'sigx ',sigx
;print,'xdata ',xdata
;print,'slider ',slider
DataMonitor2=ydata
*self.TOFMonitor2Ptr=DataMonitor2
*self.TOFMonitor2xPtr=DataMonitor2_x
;
ydata=*self.TOFMonitor3Ptr
xdata=sigx
StartBin=TimeBinIndices[2]
EndBin=TimeBinIndices[3]
self->timebincull_Red,startbin,endbin,xdata,ydata,slider,event=event
DataMonitor3_x=xdata
DataMonitor3=ydata
*self.TOFMonitor3Ptr=DataMonitor3
*self.TOFMonitor3xPtr=DataMonitor3_x
;
if tr eq '002' then dspace=dspace_002
if tr eq '002 Assumed' then dspace=dspace_002
if tr eq '004' then dspace=dspace_002/2.0
if tr eq '006' then dspace=dspace_002/3.0
if tr eq '008' then dspace=dspace_002/4.0
widget_control,self.TriffidAngle_Group,get_value=val
if val eq 0 then begin
theta=instrument_details.Unique_Triffid_Angle
endif else begin
widget_control,self.TriffidField,get_value=theta
theta=float(theta[0])
endelse

if keyword_set(background) or keyword_set(vanadium) then return

lambda_analyser=self->Bragg(dspace,theta)
instrument_details = create_struct(instrument_details,'lambda',lambda_analyser)
 *self.InstrumentPtr = instrument_details
self.MonitorsXlabel='Time / microseconds'
self.units=5
;print,'self.units: ',self.units
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::display,event = event
; This method plots the data (if present) to a pixmap then to the screen.
wset,self.winPix
self->plotInelasticData,event = event
self->plotElasticData,event = event
self->plotMonitorData,event = event
wset,self.winVis
device,copy = [0,0,!d.x_size,!d.y_size,0,0,self.winPix]
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::resize,event = event
; This method allows the user to resize the application interface while changing
; the size of the plot window accordingly.

ctrlgeom = widget_info(self.ctrlbase,/geometry)
tlbgeom = widget_info(self.tlb,/geometry)
xsize = event.x
ysize = event.y

; New data window dimensions
newxsize = xsize-ctrlgeom.xsize
newysize = ysize > ctrlgeom.ysize

widget_control,self.win,draw_xsize = newxsize, $
               draw_ysize = newysize
wdelete,self.winPix
window,/free,/pixmap,xsize = newxsize,ysize = newysize
self.winPix = !d.window
self->display,event = event
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::treatmentHandler,event = event
; This method responds to changes in the state of the
; treatment control by sensitizing or desensitizing appropriate
; buttons as necessary.
widget_control,self.treatGroup,get_value = vals
widget_control,self.van_Base,sensitive = vals[0]
widget_control,self.Bg_Base,sensitive = vals[1]
;
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::E_TOF_handler,event = event
; This method responds to changes in the state of the
; lambda own field by sensitizing or desensitizing according to whether
;   the own value button is selected
widget_control,self.ebin_group,get_value = val
if val eq 0 then widget_control,self.E_TOF_base1,sensitive = 0
if val eq 1 then widget_control,self.E_TOF_base1,sensitive = 1
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::q_theta_handler,event = event
widget_control,self.PhiBin_group,get_value = val
if val eq 0 then widget_control,self.q_theta_base1,sensitive = 0
if val eq 1 then widget_control,self.q_theta_base1,sensitive = 1
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::OutputName_handler,event = event
widget_control,self.Output_nameGroup,get_value = val
if val eq 0 then begin
widget_control,self.Output_name_subbase_sensitive1,sensitive = 0
widget_control,self.Output_name_subbase_sensitive2,sensitive = 0
widget_control,self.stem2,set_value=''
if n_elements(*self.sigFilePtr) eq 0 then return
files = *self.sigFilePtr
  filename_result = strsplit(files[0],path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)
  widget_control, self.runGroup, get_value=runGroup
      if runGroup eq 1 then filename+='++'   ;set to 'sum runs'
widget_control, self.stem1, set_value=filename
endif
if val eq 1 then begin
;widget_control,self.Output_name_subbase_sensitive1,sensitive = 1
widget_control,self.Output_name_subbase_sensitive2,sensitive = 0
widget_control,self.stem2,set_value=''
endif
if val eq 2 then begin
;widget_control,self.Output_name_subbase_sensitive1,sensitive = 0
widget_control,self.Output_name_subbase_sensitive2,sensitive = 1
endif
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::DiffOutputName_handler,event = event
widget_control,self.DiffOutput_nameGroup,get_value = val
if val eq 0 then begin
widget_control,self.DiffOutput_name_subbase_sensitive1,sensitive = 0
widget_control,self.DiffOutput_name_subbase_sensitive2,sensitive = 0
widget_control,self.Diffstem2,set_value=''
if n_elements(*self.sigFilePtr) eq 0 then return
files = *self.sigFilePtr
  filename_result = strsplit(files[0],path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)
  widget_control, self.runGroup, get_value=runGroup
      if runGroup eq 1 then filename+='++'   ;set to 'sum runs'
widget_control, self.Diffstem1, set_value=filename
endif
if val eq 1 then begin
;widget_control,self.DiffOutput_name_subbase_sensitive1,sensitive = 1
widget_control,self.DiffOutput_name_subbase_sensitive2,sensitive = 0
widget_control,self.Diffstem2,set_value=''
endif
if val eq 2 then begin
;widget_control,self.DiffOutput_name_subbase_sensitive1,sensitive = 0
widget_control,self.DiffOutput_name_subbase_sensitive2,sensitive = 1
endif
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::OutputFreebieName_handler,event = event
widget_control,self.FreebieOutput_nameGroup,get_value = val
if val eq 0 then begin
widget_control,self.FreebieOutput_name_subbase_sensitive1,sensitive = 0
widget_control,self.FreebieOutput_name_subbase_sensitive2,sensitive = 0
widget_control,self.Freebiestem2,set_value=''
if n_elements(*self.sigFilePtr) eq 0 then return
files = *self.sigFilePtr
  filename_result = strsplit(files[0],path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)
  widget_control, self.runGroup, get_value=runGroup
      if runGroup eq 1 then filename+='++'   ;set to 'sum runs'
index=widget_info(self.freebies,/droplist_select)
wr=(*self.wr_arrayPtr)[index]
filename+='_'+wr
widget_control, self.Freebiestem1, set_value=filename
endif
if val eq 1 then begin
;widget_control,self.FreebieOutput_name_subbase_sensitive1,sensitive = 1
widget_control,self.FreebieOutput_name_subbase_sensitive2,sensitive = 0
widget_control,self.Freebiestem2,set_value=''
endif
if val eq 2 then begin
;widget_control,self.FreebieOutput_name_subbase_sensitive1,sensitive = 0
widget_control,self.FreebieOutput_name_subbase_sensitive2,sensitive = 1
endif
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::rungrouphandler,event = event
widget_control,self.runGroup,get_value = rungroup
if rungroup eq 1 and n_elements(*self.sigFilePtr) eq 1 then begin
rungroup=0
  widget_control, self.runGroup, set_value=runGroup
endif
widget_control,self.stem1,get_value = stem1
stem1_length=strlen(stem1)
if stem1_length eq 0 then return
stem1_end=strmid(stem1,(stem1_length-2),2)
;print,stem1_end
if rungroup eq 1 and stem1_end ne '++' then stem1+='++'
if rungroup eq 0 and stem1_end eq '++' then stem1=strmid(stem1,0,(stem1_length-2))


widget_control,self.stem1,set_value = stem1

return
end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::DiffONHandler,event = event
widget_control,self.DiffONGroup,get_value=val
;print,'val =',val
if val eq 0 then widget_control,self.DiffOutput_name_Lbase,sensitive = 0
if val eq 1 then widget_control,self.DiffOutput_name_Lbase,sensitive = 1

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::TriffidValueHandler,event = event
widget_control,self.TriffidAngle_Group,get_value=val
;print,'val =',val
if val eq 0 then begin
widget_control,self.TriffidField,set_value=''
widget_control,self.misc_left_B1,sensitive = 0
endif else begin
widget_control,self.misc_left_B1,sensitive = 1
endelse
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::ChangeDefaultFreebieName_Handler,event = event
files = *self.sigFilePtr
  filename_result = strsplit(files[0],path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)
  widget_control, self.runGroup, get_value=runGroup
      if runGroup eq 1 then filename+='++'   ;set to 'sum runs'
index=widget_info(self.freebies,/droplist_select)
wr=(*self.wr_arrayPtr)[index]
filename+='_'+wr
widget_control, self.Freebiestem1, set_value=filename
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::FormatTypes,event = event
widget_control,self.FormatTypesGroup,get_value = vals
if vals eq 0 then text='dyn.dave'
if vals eq 1 then text='.itx'
if vals eq 2 then text='.txt'
widget_control, self.stem3, set_value=text
widget_control, self.freebiestem3, set_value=text
;
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::DiffFormatTypes,event = event
widget_control,self.DiffFormatTypesGroup,get_value = vals
if vals eq 0 then text='diff.txt'
if vals eq 1 then text='diff.itx'
if vals eq 2 then text='diff.gsas'
widget_control, self.Diffstem3, set_value=text
if vals eq 3 then widget_control,self.DiffDataOutputTypesGroup,set_value = 1
;
;
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::flashMessage_create,msg,tlb
; This method simply flashes a widget with a message that remains present
; until the flashMessage_destroy method is invoked.
;
; Center it.
geom = widget_info(self.tlb, /geometry)
xpos = geom.xoffset + geom.xsize/2 - 100
ypos = geom.yoffset + geom.ysize/2 - 50

tlb = widget_base(title='Reduction status:',/row,xoffset=xpos,yoffset=ypos, $
      tlb_frame_attr = 3)
void = widget_text(tlb,value = msg,xsize = strlen(msg),/editable)
widget_control,tlb,/realize
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::flashMessage_destroy,tlb
widget_control,tlb,/destroy
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::reducesecondary,event = event
self->reduce,event = event,/freebies
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::FreebieUpdate,event = event
widget_control,self.TargetReflection_Field,get_value = targetreflection
self.WorkingReflection=targetreflection
if targetreflection eq '004' then begin
FreebieString='002'
*self.wr_arrayPtr=FreebieString
widget_control,self.freebies,set_value = FreebieString
widget_control,self.Freebie_submaster_Lower,sensitive = 1
widget_control,self.SecondaryReduceButton,sensitive = 1
endif
;
if targetreflection eq '006' then begin
FreebieString=['002','004']
*self.wr_arrayPtr=FreebieString
widget_control,self.freebies,set_value = FreebieString
widget_control,self.Freebie_submaster_Lower,sensitive = 1
widget_control,self.SecondaryReduceButton,sensitive = 1
endif
if targetreflection eq '008' then begin
FreebieString=['002','004','006']
*self.wr_arrayPtr=FreebieString
widget_control,self.freebies,set_value = FreebieString
widget_control,self.Freebie_submaster_Lower,sensitive = 1
widget_control,self.SecondaryReduceButton,sensitive = 1
endif

if (targetreflection eq '004') or $
    (targetreflection eq '006') or $
    (targetreflection eq '008') then begin
files = *self.sigFilePtr
  filename_result = strsplit(files[0],path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)
  widget_control, self.runGroup, get_value=runGroup
      if runGroup eq 1 then filename+='++'   ;set to 'sum runs'
filename+='_002'
widget_control, self.Freebiestem1, set_value=filename
endif
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::reduce,event = event, freebies = freebies
;
   CATCH, Error_status
if Error_status ne 0 then begin
catch, /cancel
msg=strarr(3)
msg[0]='Unable to perform data reduction.'
msg[1]='Please report the following bug:'
msg[2]='Error Message from IDL: '+!ERROR_STATE.MSG
    void=dialog_message(dialog_parent=event.top,/error,msg)
return
endif
;
if n_elements(*self.sigFilePtr) eq 0 then return
files = *self.sigFilePtr
if n_elements(*self.treatmentPtr) ne 0 then begin
  ptr_free,self.treatmentPtr
  self.treatmentPtr = ptr_new(/allocate_heap)
;*self.treatmentPtr = 'Data reduction/treatment details:'
endif
; How do we treat the data?
widget_control,self.treatGroup,get_value = treatVal
;What is the output format of the data?
widget_control,self.FormatTypesGroup,get_value = FormatType

; Do we treat these individually or sum them?
widget_control,self.runGroup,get_value = thisValue
;
;   What quantity do we wish to calculate?
;
widget_control,self.DataOutputTypesGroup,get_value = DataOutput
;
; if DataOutput eq 2 then S(theta,t)
;
;   Do we specify a file name(1) or is the file name automatically assigned(0)
widget_control,self.Output_nameGroup,get_value = Output_name
;
;Are diffraction data requested
widget_control,self.DiffONGroup,get_value = DiffON
;
widget_control,self.Misc_Group1,get_value = Misc_Group1
;
;
if FormatType eq 0    then begin
filter = ['*.dave']
title = 'DAVE output filename'
endif
;
if FormatType eq 1    then begin
filter = ['*.itx']
title = 'IGOR output filename'
endif
;
if FormatType eq 2    then begin
filter = ['*.txt']
title = 'ASCII output filename'
endif
;
;
    if thisValue[0] eq 0 then begin   ; treat individually
  nfiles = n_elements(files)
  for i = 0,nfiles-1 do begin



   *self.treatmentPtr = 'Data reduction/treatment details:'
   msg = 'Reading in a raw mars file'
   self->flashMessage_create,msg,tlb
   self->Nexus_read_raw_mars,files[i],event = event,err = err ; always
   self->flashMessage_destroy,tlb
   if err eq 1 then return

if n_elements(freebies) eq 1 then begin
index=widget_info(self.freebies,/droplist_select)
wr=(*self.wr_arrayPtr)[index]
self.WorkingReflection=wr
endif else begin
self->FreebieUpdate,event = event
endelse
;
   msg = 'Subtracting Bad Detectors'
   self->flashMessage_create,msg,tlb
   self->subtract_bad_detectors,event = event    ; always
   self->flashMessage_destroy,tlb
;
;
;
if DataOutput ne 1 then begin
   msg = 'Converting to Energy'
   self->flashMessage_create,msg,tlb
   self->convert_to_energy,event = event
   self->flashMessage_destroy,tlb
endif else begin
   msg = 'Grouping the Time Bins'
   self->flashMessage_create,msg,tlb
   self->Time_Bin_Grouping,event = event
   self->flashMessage_destroy,tlb
endelse


if DiffON eq 1 then begin
   msg = 'Processing Diffraction Data'
   self->flashMessage_create,msg,tlb
   self->process_diffraction_data,event = event
   self->flashMessage_destroy,tlb
endif

  ;if n_elements(*self.bgFilePtr) ne 0 then begin  ; subtract background
  if (treatVal[1] eq 1)  then begin  ; subtract background
   msg = 'Subtracting Background File(s)'
   self->flashMessage_create,msg,tlb
   self->subtract_background,event = event
   self->flashMessage_destroy,tlb
  endif



;print,'treatVal[0]: ',treatVal[0]
    if treatVal[0] eq 1 then begin
     msg = 'Normalising to Vanadium Run'
     self->flashMessage_create,msg,tlb
     self->normalize_to_vanadium,event = event   ; normalize to vanadium
     self->flashMessage_destroy,tlb
    endif

    ; Do the rebinning at this point
   msg = 'Energy/TOF Rebinning    '
   self->flashMessage_create,msg,tlb
   self->ebinning,event=event
   self->flashMessage_destroy,tlb


   msg = 'Detector Grouping     '
   self->flashMessage_create,msg,tlb
   self->Detector_Grouping,event=event
   self->flashMessage_destroy,tlb

self->display,event = event

IF Misc_Group1[2] EQ 0 THEN BEGIN


    if  Output_name eq 0 then begin
  filename_result = strsplit(files[i],path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)


   fileOut = filepath(filename,root_dir = self.workDir)
   endif


       if Output_name eq 1 then begin
;
; First extract the filename
  filename_result = strsplit(files[i],path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)
  ;extPos = strpos(files[0],'.mars')
  ;filename = strmid(files[0],extPos-11,11)

  fileExample = filename
  fileOut = dialog_pickfile(dialog_parent = event.top,/write, $
  ;                          file = filename, $
                            file = filename, $ ; following IGOR
                            filter = filter,$
                            title = title,$
                            path = self.workDir)
;   fileOut = filepath(filename+'++',root_dir = self.workDir)

;
       endif

       if  Output_name eq 2 then begin
  filename_result = strsplit(files[i],path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)

   fileOut = filepath(filename,root_dir = self.workDir)
   widget_control, self.stem2, get_value=stem_add
    if strlen(stem_add) gt 0 then    fileOut+=stem_add

   endif

if n_elements(freebies) eq 1 then begin
   widget_control, self.freebiestem2, get_value=stem_add
fileout+='_'+wr+stem_add
endif

IF fileOut NE '' THEN BEGIN

    ;print,fileout
FilePar=fileout+'.par'
;
if FormatType eq 0    then begin
fileOut+= 'dyn.dave' ;Dave File
  msg = 'Writing to a DAVE file...'
  self->flashMessage_create,msg,tlb
  self->writeDave,event = event,fileout = fileout,FilePar = FilePar
  self->flashMessage_destroy,tlb
endif
;
if FormatType eq 1    then begin
fileOut+= '.itx' ; IGOR Text File
  msg = 'Writing to an IGOR Text file...'
  self->flashMessage_create,msg,tlb
  self->writeIGOR,event = event,fileout = fileout,FilePar = FilePar
  self->flashMessage_destroy,tlb
endif
;
if FormatType eq 2  then begin
fileOut+= '.txt' ; ASCII File
  msg = 'Writing to an ASCII file...'
  self->flashMessage_create,msg,tlb
  self->writeASCII,event = event,fileout = fileout,FilePar = FilePar
  self->flashMessage_destroy,tlb
endif
;
ENDIF

;Are diffraction data requested
if DiffON eq 1 then begin
widget_control,self.DiffFormatTypesGroup,get_value = DiffFormatTypes
   if DiffFormatTypes eq 0 then msg = 'Writing Diffraction Data to an ASCII File'
   if DiffFormatTypes eq 1 then msg = 'Writing Diffraction Data to an IGOR File'
   if DiffFormatTypes eq 2 then msg = 'Writing Diffraction Data to a GSAS File'
   self->flashMessage_create,msg,tlb
   self->write_diffraction_data,event = event
   self->flashMessage_destroy,tlb
endif

   treat = 'Filename: '+strtrim(files[i],2)
   *self.treatmentPtr = [*self.treatmentPtr,treat]

  ENDIF ;is output required endif

   if n_elements(*self.treatmentPtr) ne 0 then begin
      ptr_free,self.treatmentPtr
      self.treatmentPtr = ptr_new(/allocate_heap)
   endif


  endfor

    endif else begin         ; sum runs together
   *self.treatmentPtr = 'Data reduction/treatment details:'

;if n_elements(freebies) eq 0 then begin ; these first two options are skipped if freebies are requested

   msg = 'Reading in files to sum'
   self->flashMessage_create,msg,tlb
   self->sum_runs, event = event, err = err
   self->flashMessage_destroy,tlb
   if err eq 1 then return
;
if n_elements(freebies) eq 1 then begin
index=widget_info(self.freebies,/droplist_select)
wr=(*self.wr_arrayPtr)[index]
self.WorkingReflection=wr
endif else begin
self->FreebieUpdate,event = event
endelse


   msg = 'Subtracting Bad Detectors'
   self->flashMessage_create,msg,tlb
   self->subtract_bad_detectors,event = event    ; always
   self->flashMessage_destroy,tlb


;endif;
;
;
;
if DataOutput ne 1 then begin
   msg = 'Converting to Energy'
   self->flashMessage_create,msg,tlb
   self->convert_to_energy,event = event
   self->flashMessage_destroy,tlb
endif else begin
   msg = 'Grouping the Time Bins'
   self->flashMessage_create,msg,tlb
   self->Time_Bin_Grouping,event = event
   self->flashMessage_destroy,tlb
endelse

if DiffON eq 1 then begin
   msg = 'Processing Diffraction Data'
   self->flashMessage_create,msg,tlb
   self->process_diffraction_data,event = event
   self->flashMessage_destroy,tlb
endif



; Ok, we've performed all of the essential reduction treatment.  Now
; let's do any further steps that the user wishes.
 ; if n_elements(*self.bgFilePtr) ne 0 then begin  ; subtract background
  if (treatVal[1] eq 1)  then begin  ; subtract background
   msg = 'Subtracting Background File(s)'
   self->flashMessage_create,msg,tlb
   self->subtract_background,event = event
   self->flashMessage_destroy,tlb
  endif

;
  if treatVal[0] eq 1 then begin
   msg = 'Normalising to Vanadium Run'
   self->flashMessage_create,msg,tlb
   self->normalize_to_vanadium,event = event    ; normalize to vanadium
   self->flashMessage_destroy,tlb
  endif


    ; Do the rebinning at this point
   msg = 'Energy/TOF Rebinning    '
   self->flashMessage_create,msg,tlb
   self->ebinning,event=event
   self->flashMessage_destroy,tlb

   msg = 'Detector Grouping         '
   self->flashMessage_create,msg,tlb
   self->Detector_Grouping,event=event
   self->flashMessage_destroy,tlb

self->display,event = event

if Misc_Group1[2] eq 1 then return

   if  Output_name eq 0 then begin
  filename_result = strsplit(files[0],path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)


   fileOut = filepath(filename,root_dir = self.workDir)
   fileout+='++'
   endif

       if  Output_name eq 1 then begin
;
; First extract the filename
  filename_result = strsplit(files[0],path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)
  ;extPos = strpos(files[0],'.mars')
  ;filename = strmid(files[0],extPos-11,11)

  fileExample = filename
  fileOut = dialog_pickfile(dialog_parent = event.top,/write, $
  ;                          file = filename, $
                            file = filename+'++', $ ; following IGOR
                            filter = filter,$
                            title = title,$
                            path = self.workDir)
;   fileOut = filepath(filename+'++',root_dir = self.workDir)

  endif
  ;
  ;
       if  Output_name eq 2 then begin
  filename_result = strsplit(files[0],path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)

   fileOut = filepath(filename,root_dir = self.workDir)
      fileout+='++'
   widget_control, self.stem2, get_value=stem_add
    if strlen(stem_add) gt 0 then    fileOut+=stem_add
   endif

if n_elements(freebies) eq 1 then begin
   widget_control, self.freebiestem2, get_value=stem_add
fileout+='_'+wr+stem_add
endif

IF fileOut NE '' THEN BEGIN

;
FilePar=fileout+'.par'

if FormatType eq 0    then begin
fileOut+= 'dyn.dave' ;Dave File
  msg = 'Writing to a DAVE file...'
  self->flashMessage_create,msg,tlb
  self->writeDave,event = event,fileout = fileout,FilePar = FilePar
  self->flashMessage_destroy,tlb
endif
;
if FormatType eq 1    then begin
fileOut+= '.itx' ; IGOR Text File
  msg = 'Writing to an IGOR Text file...'
  self->flashMessage_create,msg,tlb
  self->writeIGOR,event = event,fileout = fileout,FilePar = FilePar
  self->flashMessage_destroy,tlb
endif
;
if FormatType eq 2  then begin
fileOut+= '.txt' ; ASCII File
  msg = 'Writing to an ASCII file...'
  self->flashMessage_create,msg,tlb
  self->writeASCII,event = event,fileout = fileout,FilePar = FilePar
  self->flashMessage_destroy,tlb
endif

ENDIF
    ;print,fileout
;
;Are diffraction data requested
if DiffON eq 1 then begin
widget_control,self.DiffFormatTypesGroup,get_value = DiffFormatTypes
   if DiffFormatTypes eq 0 then msg = 'Writing Diffraction Data to an ASCII File'
   if DiffFormatTypes eq 1 then msg = 'Writing Diffraction Data to an IGOR File'
   if DiffFormatTypes eq 2 then msg = 'Writing Diffraction Data to a GSAS File'
   self->flashMessage_create,msg,tlb
   self->write_diffraction_data,event = event
   self->flashMessage_destroy,tlb
endif

    endelse

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::write_diffraction_data,event = event
; get diffraction data
ElasticData=*self.ElasticDataPtr
ElasticError=*self.ElasticErrorPtr
sigx=*self.xvalsElasticPtr
n_sigx=(size(sigx))[1]
good_Elasticdet=*self.good_ElasticdetPtr
;output type
widget_control,self.DiffFormatTypesGroup,get_value = DiffFormatTypes
;is d-spacing requested?
widget_control,self.DiffDataOutputTypesGroup,get_value = DataOutputType
ElasticAngles=*self.ElasticdetPtr
ElasticDetectors=(*self.ElasticDetectorsNamesPtr)[good_Elasticdet]
n_header=n_elements(*self.headerPtr)
n_treatment=n_elements(*self.treatmentPtr)
constants=*self.ConstantsPtr
lDiff=constants.lDiff
; what is the filename?
widget_control,self.runGroup,get_value = rungroup
rungroup=rungroup[0]
widget_control,self.DiffOutput_nameGroup,get_value = DiffOutput_name
DiffOutput_name=DiffOutput_name[0]
;
files = *self.sigFilePtr
;help,files
    if  DiffOutput_name eq 0 then begin
  filename_result = strsplit(files[0],path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)


   fileOut = filepath(filename,root_dir = self.workDir)
    if rungroup eq 1 then  fileout+='++'
endif
;
       if DiffOutput_name eq 1 then begin


;
; Extract the filename
  filename_result = strsplit(files,path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)
  ;extPos = strpos(files[0],'.focus')
  ;filename = strmid(files[0],extPos-11,11)

   if DiffFormatTypes eq 0 then filter = '*diff.txt'
   if DiffFormatTypes eq 1 then filter = '*diff.itx'
   if DiffFormatTypes eq 2 then filter = '*diff.gsas'

  fileExample = filename
  fileOut = dialog_pickfile(dialog_parent = event.top,/write, $
                            file = filename, $ ; following IGOR
                          filter = filter ,$
                            title = 'Diffraction Output Filename',$
                            path = self.workDir)
;
       endif

       if  DiffOutput_name eq 2 then begin
  filename_result = strsplit(files,path_sep(),/extract)
  n_comp = n_elements(filename_result)
  filename = filename_result[n_comp-1] ; filename with .hdf attached
  extPos = strpos(filename,'.hdf')
  filename = strmid(filename,0,extPos)

   fileOut = filepath(filename,root_dir = self.workDir)
    if rungroup eq 1 then  fileout+='++'
  widget_control, self.Diffstem2, get_value=stem_add
    if strlen(stem_add) gt 0 then    fileOut+=stem_add

   endif

   if DiffFormatTypes eq 0 then fileout+='diff.txt'
   if DiffFormatTypes eq 1 then begin
   filepar=fileout+'diff.par'
   fileout+='diff.itx'
   endif
   if DiffFormatTypes eq 2 then fileout+='diff.gsas'

if DiffFormatTypes eq 0  then begin
openw,lun,fileout,/get_lun
printf,lun, '#DAVE ASCII OUTPUT'
printf,lun, '#Diffraction Data'
for i = 0,n_header-1 do printf,lun,'#'+(*self.headerPtr)[i]
for i = 0,n_treatment-1 do printf,lun,'#'+(*self.treatmentPtr)[i]
if DataOutputType eq 0 then begin
printf,lun, '#d-spacing / A  ','Intensity ','dIntensity'
endif else begin
printf,lun, '#TOF / us       ','Intensity ','dIntensity'
endelse
printf,lun, '#Distance from Pulse Producing Chopper to Diffraction Detectors: '+ $
         strtrim(string(lDiff),2)+' m.'
printf,lun, '#BEGIN'
for i = 0, n_elements(good_Elasticdet)-1 do begin
printf,lun, '#Detector Name: '+ElasticDetectors[i]
printf,lun, '#2Theta: '+strtrim(string(ElasticAngles[i]),2)
    for j = 0, n_sigx - 1 do begin
    printf,lun, strtrim(string(sigx[j,i]),2)+'  ',strtrim(string(ElasticData[j,i]),2)+'  ', $
    strtrim(string(ElasticError[j,i]),2)
    endfor
endfor
printf,lun, '#END'
free_lun,lun,/force
endif
;
if DiffFormatTypes eq 1  then begin

if DataOutputType eq 0 then begin
xunits= 'd-spacing / A'
endif else begin
xunits= 'TOF / us'
endelse
openw,lun,fileout,/get_lun
printf,lun, 'IGOR'
for i = 0, n_elements(good_Elasticdet)-1 do begin
xval='''XValue_'+ElasticDetectors[i]+''''+'  '
yval='''Intensity_'+ElasticDetectors[i]+''''+'  '
yval_err='''dIntensity_'+ElasticDetectors[i]+''''+'  '
printf,lun, 'WAVES/D ',xval,yval,yval_err
printf,lun, 'Begin'
z=reform(ElasticData[*,i])
dz=reform(ElasticError[*,i])
x=reform(sigx[*,i])
    for j = 0, n_sigx-1 do begin
printf,lun, strtrim(string(x[j]),1)+'  ',strtrim(string(z[j]),1)+'  ',strtrim(string(dz[j]),1)
        endfor
printf,lun, 'End'
printf, lun, 'X SetScale d 0,0,'+'"'+strtrim(string(xunits),2)+'"'+', ' +strtrim(string(xval),2)
printf, lun, 'X SetScale d 0,0,'+'"'+'Intensity'+'"'+', '+strtrim(string(yval),2)
endfor
free_lun,lun,/force

openw,lun,filepar,/get_lun
printf,lun, '#Diffraction Data'
for i = 0,n_header-1 do printf,lun,'#'+(*self.headerPtr)[i]
for i = 0,n_treatment-1 do printf,lun,'#'+(*self.treatmentPtr)[i]
printf,lun, '#Distance from Pulse Producing Chopper to Diffraction Detectors: '+ $
         strtrim(string(lDiff),2)+' m.'

free_lun,lun,/force

endif
;
if DiffFormatTypes eq 2  then begin
openw,lun,fileout,/get_lun
printf,lun, '#Sorry, but the code for creating GSAS files has yet to be written.'
printf,lun, '#For the time being, you''ll have to make do with ASCII format instead.'
printf,lun, '#DAVE ASCII OUTPUT'
printf,lun, '#Diffraction Data'
for i = 0,n_header-1 do printf,lun,'#'+(*self.headerPtr)[i]
for i = 0,n_treatment-1 do printf,lun,'#'+(*self.treatmentPtr)[i]
if DataOutputType eq 0 then begin
printf,lun, '#d-spacing / A  ','Intensity ','dIntensity'
endif else begin
printf,lun, '#TOF / us       ','Intensity ','dIntensity'
endelse
printf,lun, '#Distance from Pulse Producing Chopper to Diffraction Detectors: '+ $
         strtrim(string(lDiff),2)+' m.'
printf,lun, '#BEGIN'
for i = 0, n_elements(good_Elasticdet)-1 do begin
printf,lun, '#Detector Name: '+ElasticDetectors[i]
printf,lun, '#2Theta: '+strtrim(string(ElasticAngles[i]),2)
    for j = 0, n_sigx - 1 do begin
    printf,lun, strtrim(string(sigx[j,i]),2)+'  ',strtrim(string(ElasticData[j,i]),2)+'  ', $
    strtrim(string(ElasticError[j,i]),2)
    endfor
endfor
printf,lun, '#END'
free_lun,lun,/force
endif


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::writeDave,event = event,fileout = fileout,FilePar = FilePar
; This method populates the DAVE pointer in memory and saves the data into
; a "*.DAVE" file.
treat = 'Converted to DAVE format'
*self.treatmentPtr = [*self.treatmentPtr,treat]

n = n_elements(*self.treatmentPtr)
;for i = 0,n-1 do print,(*self.treatmentPtr)[i]
davePtr = self.davePtr

data = *self.dataPtr
error = *self.errorPtr
x = *self.xvalsPtr
y = *self.yvalsPtr
;print,'Number of groups:',self.ndet
; Ok, start filling up the dave pointer...
; First, fill up the data...



;help,data
datSize = size(data)
nchan = datSize[1]
if datSize[0] eq 2 then begin
ndet = datSize[2]
endif else begin
ndet=1
endelse
header=*self.headerPtr
Instrument_Details=*self.InstrumentPtr


nh = n_elements(*self.headerPtr)
detSize = (size(data))[2]
temperature=*self.tempPtr
;
specific = {header:header, $
            sumTOFMonitor1:*self.TOFMonitor1Ptr,$
            sumTOFMonitor2:*self.Mon_cumPtr,$
            sumTOFMonitor3:total(*self.TOFMonitor3Ptr),$
            nchan:nchan,$
            ndet:ndet,$
            phi:*self.yvalsPtr,$
            wavelength:(*self.InstrumentPtr).lambda,$
            date:systime(),$
            temp_sample:temperature $
            }


hbar_omega = '!6!sh!r!e/!n !7x!6'
xlabel=hbar_omega
if self.units eq 4 then xlabel = 'T'
if self.units eq 5 then xlabel = 't'

if self.units eq 0 then xunits = 'Energy / meV'
if self.units eq 1 then xunits = 'Energy / Wavenumbers'
if self.units eq 2 then xunits = 'Energy / GHz'
if self.units eq 3 then xunits = 'Energy /  THz'
if self.units eq 4 then xunits = 'Energy / K'
if self.units eq 5 then xunits = 'Time / Microseconds'
widget_control,self.DataOutputTypesGroup,get_value = DataOutput
if DataOutput[0] eq 0 then begin
yunits = 'wavevector:A-1'
ylabel = 'Q '
endif
if DataOutput[0] eq 1  then begin
yunits = 'Phi:degrees'
ylabel = 'Phi '
endif

histlabel = 'I (arbitrary units)'
histunits = ''

Mon_cumTreat = 'Total incident beam monitor counts: '+ $
           strtrim(string(*self.Mon_cumPtr),2)
*self.treatmentPtr = [*self.treatmentPtr,Mon_cumTreat]
msg = 'Number of channels: '+strtrim(string(nchan),2)
*self.treatmentPtr = [*self.treatmentPtr,msg]
msg = 'Number of groups: '+strtrim(string(ndet),2)
*self.treatmentPtr = [*self.treatmentPtr,msg]

if n_elements(temperature) gt 1 then temperature = (moment(temperature))[0]
retval = create_dave_pointer(self.davePtr,   $
     qty = data,   $
     err = error,    $
     xvals = x,            $
     yvals = y,      $
     specificstr = specific,      $
     instrument = 'MARS',      $
     xtype = 'POINTS',        $
     ytype = 'POINTS',        $
     xlabel = xlabel,         $
     ylabel = ylabel,         $
     qtlabel = histlabel,      $
     xunits = xunits,         $
     yunits = yunits,         $
     qtunits = histunits,      $
     dname = 'T',          $
     dunits = 'temperature:K',     $
     dlegend = 'Temperature',    $
     dqty = temperature,         $
     derr = 0.0,            $
     treatment = *self.treatmentptr,   $
     ermsg = ermsg           )

if n_elements(fileout) eq 0 then return
if (*self.daveFiles)[0] eq '' then begin
  *self.daveFiles = fileOut
endif else begin
  *self.daveFiles = [*self.daveFiles,fileOut]
endelse
save, davePtr, filename = fileout
n_header=n_elements(*self.headerPtr)
n_treatment=n_elements(*self.treatmentPtr)
openw,lun,FilePar,/get_lun
for i = 0,n_header-1 do printf,lun,(*self.headerPtr)[i]
printf,lun, 'Temperature / K: '+strtrim(string(temperature),2)
printf,lun, 'XType: Points'
printf,lun, 'Group Type: Points'
printf,lun, 'X Units: '+strtrim(string(xunits),2)
printf,lun, 'Y Units: '+strtrim(string(histlabel),2)
printf,lun, 'Group Units: '+strtrim(string(yunits),2)
printf,lun, 'Group Label: '+strtrim(string(ylabel),2)
printf,lun, 'Wavelength / A: '+strtrim(string((*self.InstrumentPtr).lambda),2)
printf,lun, 'Date This File Created: '+strtrim(string(systime()),2)
for i = 0,n_treatment-1 do printf,lun,(*self.treatmentPtr)[i]
free_lun,lun,/force

end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::writeIGOR,event = event,fileout = fileout,FilePar = FilePar
;
if n_elements(fileout) eq 0 then return
;
treat = 'Converted to IGOR Text Format'
*self.treatmentPtr = [*self.treatmentPtr,treat]

n = n_elements(*self.treatmentPtr)
;for i = 0,n-1 do print,(*self.treatmentPtr)[i]

data = *self.dataPtr
error = *self.errorPtr
x = *self.xvalsPtr
y = *self.yvalsPtr
;print,'Number of groups:',self.ndet

;help,data
datSize = size(data)
nchan = datSize[1]
if datSize[0] eq 2 then begin
ndet = datSize[2]
endif else begin
ndet=1
endelse

header=*self.headerPtr
nh = n_elements(*self.headerPtr)
detSize = (size(data))[2]
temperature=*self.tempPtr
Instrument_Details=*self.InstrumentPtr

xlabel='Energy'
if self.units eq 4 then xlabel = 'T'
if self.units eq 5 then xlabel = 't'

if self.units eq 0 then xunits = 'Energy / meV'
if self.units eq 1 then xunits = 'Energy / Wavenumbers'
if self.units eq 2 then xunits = 'Energy / GHz'
if self.units eq 3 then xunits = 'Energy /  THz'
if self.units eq 4 then xunits = 'Energy / K'
if self.units eq 5 then xunits = 'Time / Microseconds'
print,'self.units: ',self.units
widget_control,self.DataOutputTypesGroup,get_value = DataOutput
if DataOutput[0] eq 0 then begin
yunits = 'wavevector:A-1'
ylabel = 'Q '
endif
if DataOutput[0] eq 1 or DataOutput[0] eq 2 then begin
yunits = 'Phi:degrees'
ylabel = 'Phi '
endif

histlabel = 'I (arbitrary units)'
histunits = ''

Mon_cumTreat = 'Total incident beam monitor counts: '+ $
           strtrim(string(*self.Mon_cumPtr),2)
*self.treatmentPtr = [*self.treatmentPtr,Mon_cumTreat]
msg = 'Number of channels: '+strtrim(string(nchan),2)
*self.treatmentPtr = [*self.treatmentPtr,msg]
msg = 'Number of groups: '+strtrim(string(ndet),2)
*self.treatmentPtr = [*self.treatmentPtr,msg]

if n_elements(temperature) gt 1 then temperature = (moment(temperature))[0]


openw,lun,fileout,/get_lun
printf,lun, 'IGOR'
for i = 0, ndet-1 do begin
;printf,lun, '|Group Number: '+strtrim(string(i+1),2)
;printf,lun, '|Group Value: '+strtrim(string(y[i]),2)
xval='''XValue_'+strtrim(string(i),2)+'_'+strtrim(string(y[i]),2)+''''+'  '
yval='''Intensity_'+strtrim(string(i),2)+'_'+strtrim(string(y[i]),2)+''''+'  '
yval_err='''dIntensity_'+strtrim(string(i),2)+'_'+strtrim(string(y[i]),2)+''''+'  '
;print,'xval: ',xval
printf,lun, 'WAVES/D ',xval,yval,yval_err
printf,lun, 'Begin'
z=reform(data[*,i])
dz=reform(error[*,i])
newx=x
count = nchan
purged=where(z gt -1.0,count)
if count ne 0 then begin
z=z[purged]
dz=dz[purged]
newx=newx[purged]
endif

    for j = 0, count-1 do begin
printf,lun, strtrim(string(newx[j]),1)+'  ',strtrim(string(z[j]),1)+'  ',strtrim(string(dz[j]),1)
        endfor
printf,lun, 'End'
printf, lun, 'X SetScale d 0,0,'+'"'+strtrim(string(xunits),2)+'"'+', ' +strtrim(string(xval),2)
printf, lun, 'X SetScale d 0,0,'+'"'+'Intensity'+'"'+', '+strtrim(string(yval),2)
endfor

free_lun,lun,/force


n_header=n_elements(*self.headerPtr)
n_treatment=n_elements(*self.treatmentPtr)
openw,lun,FilePar,/get_lun
for i = 0,n_header-1 do printf,lun,(*self.headerPtr)[i]
printf,lun, 'Temperature / K: '+strtrim(string(temperature),2)
printf,lun, 'XType: Points'
printf,lun, 'Group Type: Points'
printf,lun, 'X Units: '+strtrim(string(xunits),2)
printf,lun, 'Y Units: '+strtrim(string(histlabel),2)
printf,lun, 'Group Units: '+strtrim(string(yunits),2)
printf,lun, 'Group Label: '+strtrim(string(ylabel),2)
printf,lun, 'Wavelength / A: '+strtrim(string((*self.InstrumentPtr).lambda),2)
printf,lun, 'Date This File Created: '+strtrim(string(systime()),2)
for i = 0,n_treatment-1 do printf,lun,(*self.treatmentPtr)[i]
free_lun,lun,/force


end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::writeASCII,event = event,fileout = fileout,FilePar = FilePar
;
if n_elements(fileout) eq 0 then return
;
treat = 'Converted to ASCII format'
*self.treatmentPtr = [*self.treatmentPtr,treat]

n = n_elements(*self.treatmentPtr)
;for i = 0,n-1 do print,(*self.treatmentPtr)[i]

data = *self.dataPtr
error = *self.errorPtr
x = *self.xvalsPtr
y = *self.yvalsPtr
;print,'Number of groups:',self.ndet

;help,data
datSize = size(data)
nchan = datSize[1]
if datSize[0] eq 2 then begin
ndet = datSize[2]
endif else begin
ndet=1
endelse

header=*self.headerPtr
nh = n_elements(*self.headerPtr)
detSize = (size(data))[2]
temperature=*self.tempPtr
Instrument_Details=*self.InstrumentPtr


;hbar_omega = '!6!sh!r!e/!n !7x!6'
;xlabel=hbar_omega
xlabel='Energy'
if self.units eq 4 then xlabel = 'T'
if self.units eq 5 then xlabel = 't'
;if self.units ne 5 then begin
;xlabel = hbar_omega
;endif else begin
;xlabel = 't'
;endelse
;xlabel=self.xlabel


if self.units eq 0 then xunits = 'Energy / meV'
if self.units eq 1 then xunits = 'Energy / Wavenumbers'
if self.units eq 2 then xunits = 'Energy / GHz'
if self.units eq 3 then xunits = 'Energy /  THz'
if self.units eq 4 then xunits = 'Energy / K'
if self.units eq 5 then xunits = 'Time / Microseconds'
widget_control,self.DataOutputTypesGroup,get_value = DataOutput
if DataOutput[0] eq 0 then begin
yunits = 'wavevector:A-1'
ylabel = 'Q '
endif
if DataOutput[0] eq 1 or DataOutput[0] eq 2 then begin
yunits = 'Phi:degrees'
ylabel = 'Phi '
endif

histlabel = 'I (arbitrary units)'
histunits = ''

Mon_cumTreat = 'Total incident beam monitor counts: '+ $
           strtrim(string(total(*self.Mon_cumPtr)),2)
*self.treatmentPtr = [*self.treatmentPtr,Mon_cumTreat]
msg = 'Number of channels: '+strtrim(string(nchan),2)
*self.treatmentPtr = [*self.treatmentPtr,msg]
msg = 'Number of groups: '+strtrim(string(ndet),2)
*self.treatmentPtr = [*self.treatmentPtr,msg]

;*(*(*davePtr).dataStrPtr).commonStr.treatmentPtr = *self.treatmentPtr
if n_elements(temperature) gt 1 then temperature = (moment(temperature))[0]


openw,lun,fileout,/get_lun
printf,lun, '#DAVE ASCII OUTPUT'
for i = 0,n_elements(header)-1 do printf,lun,'#'+header[i]
printf,lun, 'Temperature / K: '+strtrim(string(temperature),2)
printf,lun, 'XType: Points'
printf,lun, 'Group Type: Points'
printf,lun, 'X Units: '+strtrim(string(xunits),2)
printf,lun, 'Y Units: '+strtrim(string(histlabel),2)
printf,lun, 'Group Units: '+strtrim(string(yunits),2)
printf,lun, 'Group Label: '+strtrim(string(ylabel),2)
printf,lun, 'Wavelength / A: '+strtrim(string((*self.InstrumentPtr).lambda),2)
printf,lun, 'Date This File Created: '+strtrim(string(systime()),2)
for i = 0,n-1 do printf,lun,'#'+(*self.treatmentPtr)[i]
printf,lun, '#Begin'
for i = 0, ndet-1 do begin
printf,lun, '#Group Number: '+strtrim(string(i+1),2)
printf,lun, '#Group Value: '+strtrim(string(y[i]),2)
printf,lun, '#X Value    ','Intensity ','dIntensity'
z=reform(data[*,i])
dz=reform(error[*,i])
newx=x
count = nchan
purged=where(z ne -1.0,count)
if count ne 0 then begin
z=z[purged]
dz=dz[purged]
newx=newx[purged]
endif

    for j = 0, count-1 do begin
printf,lun, strtrim(string(newx[j]),1)+'  ',strtrim(string(z[j]),1)+'  ',strtrim(string(dz[j]),1)
        endfor
endfor
printf,lun, '#end'
free_lun,lun,/force
;
end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::zoomEvents,event = event
if n_elements(*self.dataPtr) eq 0 then return
case event.type of
0: begin    ; button press
     self.mouse = event.press
     if self.mouse eq 4 then begin
       self.autoscale = 1
        self->display,event = event
     endif
     if self.mouse eq 1 then begin
       self.xbox[0] = event.x
       self.ybox[0] = event.y
        self->display,event = event
       empty
       self.autoscale = 0
       widget_control,self.win,/draw_motion_events
     endif
   end
1: begin ; button release
    if self.mouse eq 1 then begin
     xll = self.xbox[0] < self.xbox[1]
     yll = self.ybox[0] < self.ybox[1]
     w = abs(self.xbox[1] - self.xbox[0])
     h = abs(self.ybox[1] - self.ybox[0])
     xur = xll + w
     yur = yll + h
     ll = convert_coord(xll,yll,/device,/to_data)
     ur = convert_coord(xur,yur,/device,/to_data)
     self.xrange = [ll[0],ur[0]]
     self.yrange = [ll[1],ur[1]]
      self->display,event = event
     self.mouse = 0B
     widget_control,self.win,draw_motion_events = 0
    endif
    if self.mouse eq 4 then begin
     self->display,event = event
     self.mouse = 0B
     widget_control,self.win,draw_motion_events = 0
    endif
   end
2: begin ; mouse motion
     if self.mouse eq 1 then begin
        self.xbox[1] = event.x
        self.ybox[1] = event.y
        xc = [self.xbox[0],event.x,event.x,$
              self.xbox[0],$
              self.xbox[0]]
        yc = [self.ybox[0],self.ybox[0],$
              event.y,event.y,$
              self.ybox[0]]
        wset,self.winVis
        device,copy = [0,0,!d.x_size,!d.y_size,0,0,self.winPix]
        plots,xc,yc,/device,color=4
        empty
     endif
   end
else:
endcase
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::reduce_help,event = event
;pdf_file = file_which('mars_data_reduction.pdf',/include_current_dir)
pdf_file = !DAVE_AUXILIARY_DIR+'\PSI\MARS\mars_data_reduction.pdf'
void = launch_help(pdf_file,tlb = event.top)
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction::createwidgets
; Widget definition method
if n_elements(*self.pgroup_leader) eq 0 then begin
  tlb = widget_base(/row, $
        title = 'Mars Data Reduction',mbar = bar,/tlb_size_events)
endif else begin
  tlb = widget_base(group_leader = *self.pgroup_leader,/row, $
        title = 'Mars Data Reduction',mbar = bar,/tlb_size_events)
endelse
self.tlb = tlb
self.ctrlBase = widget_base(self.tlb,/row)
master_button_base = widget_base(self.ctrlbase,/col,/frame)

ubase_master = widget_base(master_button_base,/col)
void=widget_label(ubase_master,/sunken_frame,value='BASIC INPUT')
ubase = widget_base(ubase_master,/row)
lbase = widget_base(master_button_base,/col)
void=widget_label(lbase,/sunken_frame,value='ADVANCED OPTIONS')
lubase_col = widget_base(ubase,/col)
rubase_col = widget_base(ubase,/col)


treatTypes = ['Vanadium Normalisation',$
              'Background Subtraction'];, $
;              'Energy binning']
treatGroup = cw_bgroup(lubase_col,treatTypes,/col,/nonexclusive,$
           set_value = [0,0],/return_index, /frame,$
           uvalue = {object:self,method:'treatmentHandler'})
self.treatGroup = treatGroup
;help,runGroup
;print,runGroup
;
sigfile_base=widget_base(lubase_col,/col,/frame)
;

self.signal_runs = cw_field(sigfile_base,/row,uvalue = {object:self,method:'selSigRuns'},$
                 title = 'Signal Run(s)',/return_events)


void = widget_button(sigfile_base,value = 'Browse for Signal File(s)', $
      uvalue = {object:self,method:'selSigFiles'})


self.van_Base=widget_base(lubase_col,/col,/frame,sensitive=0)

self.vanadium_run = cw_field(self.van_Base,/row,uvalue = {object:self,method:'selVanRun'},$
                 title = 'Van. Run(s)',value = '',/return_events)


void = widget_button(self.van_Base,value = 'Browse for Vanadium File(s)', $
               uvalue = {object:self,method:'selVanFile'})

self.Bg_Base=widget_base(lubase_col,/col,/frame,sensitive=0)

self.Background_runs = cw_field(self.Bg_Base,/row,uvalue = {object:self,method:'selEmptyRuns'},$
                 title = 'Empty Run(s)',/return_events)


void = widget_button(self.Bg_Base,value = 'Browse for Background File(s)', $
               uvalue = {object:self,method:'selBgFiles'})


runTypes = ['Single Sample Runs','Sum All Runs']
runGroup = cw_bgroup(rubase_col,runTypes,/col,/exclusive,$
           /no_release,set_value = 1,/return_index, /frame,$
           uvalue = {object:self,method:'rungroupHandler'})
self.runGroup = runGroup


void = widget_label(rubase_col,value = 'Signal Run(s)')
xtextSize = 18
self.fileText = widget_text(rubase_col,ysize = 5,xsize = xtextSize,/scroll)
void = widget_label(rubase_col,value = 'Vanadium Run(s)')
self.vanText = widget_text(rubase_col,xsize = xtextSize,/scroll,value = '')
void = widget_label(rubase_col,value = 'Background Run(s)')
self.bgText = widget_text(rubase_col,xsize = xtextSize,ysize = 4,/scroll)
void = widget_button(lubase_col,value = '?Help?', $
               uvalue = {object:self,method:'reduce_help'})
void = widget_button(lubase_col,value = 'Quit', $
       uvalue = {object:self,method:'quit'})
void = widget_button(lubase_col,value = 'REDUCE PRIMARY DATA', $
               uvalue = {object:self,method:'reduce'})

Opt_Tab=widget_Tab(lbase,uvalue={object:self,method:'doNothing'})
Output_master = widget_base(Opt_Tab,/row,title='Output')
Bin_master = widget_base(Opt_Tab,/row,title='Binning')
Freebie_master = widget_base(Opt_Tab,/col,title='Secondary Data')
Diffraction_master = widget_base(Opt_Tab,/col,title='Diffraction Data')
Misc_master = widget_base(Opt_Tab,/col,title='Misc.')


Output_name_Lbase=widget_base(Output_master,/col)

Output_name_base=widget_base(Output_name_Lbase,/col)
void=widget_label(Output_name_base,value='Output File Name for Primary Data')
Output_name_subbase=widget_base(Output_name_base,/col,/frame)

Output_nameTypes= ['Automatically Assigned',  $
          'Specify Output File Name on Prompt', $
              'Add to Stem:']

Output_nameGroup = cw_bgroup(Output_name_subbase,Output_nameTypes,/col,/exclusive, $
           /no_release,set_value = 0,/return_index, $
           uvalue = {object:self,method:'OutputName_handler'})
self.Output_nameGroup = Output_nameGroup

self.Output_name_subbase_sensitive=widget_base(Output_name_subbase,/row)

self.Output_name_subbase_sensitive1=widget_base(self.Output_name_subbase_sensitive,sensitive=0)
self.stem1 = cw_field(self.Output_name_subbase_sensitive1,title='', $
              uvalue = {object:self,method:'doNothing'},/row,value = '')

self.Output_name_subbase_sensitive2=widget_base(self.Output_name_subbase_sensitive,sensitive=0)
self.stem2 = cw_field(self.Output_name_subbase_sensitive2,title='', xsize=5, $
              uvalue = {object:self,method:'doNothing'},/row,value = '')

self.Output_name_subbase_sensitive3=widget_base(self.Output_name_subbase_sensitive,sensitive=0)
self.stem3 = cw_field(self.Output_name_subbase_sensitive3,title='', xsize=8, $
          uvalue = {object:self,method:'doNothing'},/row,value = 'dyn.dave',/noedit)

Output_name_Ubase=widget_base(Output_name_Lbase,/row)

FormatTypes = ['Dave',$
              'IGOR Text', $
              'ASCII']
FormatTypesGroup = cw_bgroup(Output_name_Ubase,FormatTypes,/col,/exclusive,label_top='Output Formats',$
           set_value = 0,/return_index, /frame,$
           uvalue = {object:self,method:'FormatTypes'})
self.FormatTypesGroup = FormatTypesGroup


;Output_name_Rbase=widget_base(Output_master,/col)


DataOutputTypes = ['S(Q,w)_phi',$
              'S(Phi,t)']

DataOutputTypesGroup = cw_bgroup(Output_name_Ubase,DataOutputTypes,/col,/exclusive,label_top='Data Output', $
           set_value = 0,/return_index,/frame, $
           uvalue = {object:self,method:'doNothing'})
self.DataOutputTypesGroup = DataOutputTypesGroup


EBin_submaster=widget_base(Bin_master,/col)
void=widget_label(EBin_submaster,value='Energy/TOF Binning')

E_TOF_base=widget_base(EBin_submaster,/col,/frame)


ebin_Types = ['No Binning','Binning and Units']
ebin_Group = cw_bgroup(E_TOF_base,ebin_Types,row=2,/exclusive,$
           /no_release,set_value = 0,/return_index,$
           uvalue = {object:self,method:'E_TOF_handler'})
self.ebin_group = ebin_Group

self.E_TOF_base1=widget_base(E_TOF_base,/col,sensitive=0)

ebin_Types1 = ['Modify Default','Modify Previous','Use Previous']
ebin_Group1 = cw_bgroup(self.E_TOF_base1,ebin_Types1,row=3,/exclusive, $
           /no_release,set_value = 0,/return_index,$
           uvalue = {object:self,method:'doNothing'})
self.ebin_group1 = ebin_Group1



PhiBin_submaster=widget_base(Bin_master,/col)
void=widget_label(PhiBin_submaster,value='Phi Grouping')

Q_Theta_base=widget_base(PhiBin_submaster,/col,/frame)


PhiBin_Types = ['Sum All','Grouping']
PhiBin_Group = cw_bgroup(Q_Theta_base,PhiBin_Types,row=2,/exclusive,$
           /no_release,set_value = 0,/return_index,$
           uvalue = {object:self,method:'Q_Theta_handler'})
self.PhiBin_group = PhiBin_Group


self.q_theta_base1=widget_base(q_theta_base,/col,sensitive=0)

PhiBin_Types1 = ['Modify Default','Modify Previous','Use Previous']
PhiBin_Group1 = cw_bgroup(self.q_theta_base1,PhiBin_Types1,row=3,/exclusive, $
           /no_release,set_value = 0,/return_index,$
           uvalue = {object:self,method:'doNothing'})
self.PhiBin_group1 = PhiBin_Group1


Freebie_submaster_Upper=widget_base(Freebie_master,/col)

self.TargetReflection_Field = cw_field(Freebie_submaster_Upper,title='Target Reflection', $
              uvalue = {object:self,method:'doNothing'},/col,value = '',/noedit)

void=widget_label(Freebie_submaster_Upper,value='Additional Inelastic Data')

self.freebies=widget_Droplist(Freebie_submaster_Upper,title='', $
              value='No Available Lower Order Reflections',/dynamic_resize, $
              uvalue = {object:self,method:'ChangeDefaultFreebieName_Handler'} )


Freebie_submaster_Lower=widget_base(Freebie_master,/col,sensitive=0)
self.Freebie_submaster_Lower=Freebie_submaster_Lower
FreebieOutput_name_base=widget_base(Freebie_submaster_Lower,/col)
void=widget_label(FreebieOutput_name_base,value='Output File Name for Secondary Data')
FreebieOutput_name_subbase=widget_base(FreebieOutput_name_base,/col,/frame)


FreebieOutput_nameGroup = cw_bgroup(FreebieOutput_name_subbase,Output_nameTypes,/col,/exclusive, $
           /no_release,set_value = 0,/return_index, $
           uvalue = {object:self,method:'OutputFreebieName_handler'})
self.FreebieOutput_nameGroup = FreebieOutput_nameGroup

self.FreebieOutput_name_subbase_sensitive=widget_base(FreebieOutput_name_subbase,/row)

self.FreebieOutput_name_subbase_sensitive1=widget_base(self.FreebieOutput_name_subbase_sensitive,sensitive=0)
self.Freebiestem1 = cw_field(self.FreebieOutput_name_subbase_sensitive1,title='', $
              uvalue = {object:self,method:'doNothing'},/row,value = '')

self.FreebieOutput_name_subbase_sensitive2=widget_base(self.FreebieOutput_name_subbase_sensitive,sensitive=0)
self.Freebiestem2 = cw_field(self.FreebieOutput_name_subbase_sensitive2,title='', xsize=5, $
              uvalue = {object:self,method:'doNothing'},/row,value = '')

self.FreebieOutput_name_subbase_sensitive3=widget_base(self.FreebieOutput_name_subbase_sensitive,sensitive=0)
self.Freebiestem3 = cw_field(self.FreebieOutput_name_subbase_sensitive3,title='', xsize=8, $
          uvalue = {object:self,method:'doNothing'},/row,value = 'dyn.dave',/noedit)

self.SecondaryReduceButton = widget_button(Freebie_master,value = 'REDUCE SECONDARY DATA', $
               uvalue = {object:self,method:'reducesecondary'},sensitive=0)


DiffONType = ['Generate Diffraction Pattern                                           '] ;adjust the length to make tabs look nice.

DiffONGroup = cw_bgroup(Diffraction_master,DiffONType,/col,/nonexclusive,$
           set_value = 0,/return_index,$
           uvalue = {object:self,method:'DiffONHandler'})


self.DiffONGroup=DiffONGroup



DiffOutput_name_Lbase=widget_base(Diffraction_master,/col,sensitive = 0)

self.DiffOutput_name_Lbase=DiffOutput_name_Lbase


DiffOutput_name_base=widget_base(DiffOutput_name_Lbase,/col)
void=widget_label(DiffOutput_name_base,value='Output File Name for Primary Data')
DiffOutput_name_subbase=widget_base(DiffOutput_name_base,/col,/frame)

DiffOutput_nameTypes= ['Automatically Assigned',  $
          'Specify Output File Name on Prompt', $
              'Add to Stem:']

DiffOutput_nameGroup = cw_bgroup(DiffOutput_name_subbase,DiffOutput_nameTypes,/col,/exclusive, $
           /no_release,set_value = 0,/return_index, $
           uvalue = {object:self,method:'DiffOutputName_handler'})
self.DiffOutput_nameGroup = DiffOutput_nameGroup

self.DiffOutput_name_subbase_sensitive=widget_base(DiffOutput_name_subbase,/row)

self.DiffOutput_name_subbase_sensitive1=widget_base(self.DiffOutput_name_subbase_sensitive,sensitive=0)
self.Diffstem1 = cw_field(self.DiffOutput_name_subbase_sensitive1,title='', $
              uvalue = {object:self,method:'doNothing'},/row,value = '')

self.DiffOutput_name_subbase_sensitive2=widget_base(self.DiffOutput_name_subbase_sensitive,sensitive=0)
self.Diffstem2 = cw_field(self.DiffOutput_name_subbase_sensitive2,title='', xsize=5, $
              uvalue = {object:self,method:'doNothing'},/row,value = '')

self.DiffOutput_name_subbase_sensitive3=widget_base(self.DiffOutput_name_subbase_sensitive,sensitive=0)
self.Diffstem3 = cw_field(self.DiffOutput_name_subbase_sensitive3,title='', xsize=8, $
          uvalue = {object:self,method:'doNothing'},/row,value = 'diff.txt',/noedit)

DiffOutput_name_Ubase=widget_base(DiffOutput_name_Lbase,/row)

DiffFormatTypes = ['ASCII',$
              'IGOR Text', $
              'GSAS']
DiffFormatTypesGroup = cw_bgroup(DiffOutput_name_Ubase,DiffFormatTypes,/col,/exclusive,label_top='Output Formats',$
           set_value = 0,/return_index, /frame,$
           uvalue = {object:self,method:'DiffFormatTypes'})
self.DiffFormatTypesGroup = DiffFormatTypesGroup


;Output_name_Rbase=widget_base(Output_master,/col)


DiffDataOutputTypes = ['d-spacing / A',$
                   'TOF / us']

DiffDataOutputTypesGroup = cw_bgroup(DiffOutput_name_Ubase,DiffDataOutputTypes,/col,/exclusive,label_top='Data Output', $
           set_value = 0,/return_index,/frame, $
           uvalue = {object:self,method:'doNothing'})
self.DiffDataOutputTypesGroup = DiffDataOutputTypesGroup


misc_submaster=widget_base(Misc_master,/row)
misc_left=widget_base(misc_submaster,/col)

Misc_Types1 = ['Detailed Balance','Display Automatic Vanadium Fits', $
          'Create No Output Files','Normalise to the Monitor']
Misc_Group1 = cw_bgroup(misc_left,Misc_Types1,/nonexclusive, $
           /no_release,set_value = [0,0,0,1],/return_index,$
           uvalue = {object:self,method:'doNothing'})
self.Misc_Group1 = Misc_Group1

void=widget_label(misc_left,value = 'Analyser Angle')
misc_left_B=widget_base(misc_left,/row,/frame)



TriffidAngle_Types = ['Automatic','Manual']


TriffidAngle_Group = cw_bgroup(misc_left_B,TriffidAngle_Types,/exclusive, $
           /no_release,set_value = 0,/return_index,/row,$
           uvalue = {object:self,method:'TriffidValueHandler'})

self.TriffidAngle_Group = TriffidAngle_Group

self.misc_left_B1=widget_base(misc_left_B,/row,sensitive=0)


self.TriffidField = cw_field(self.misc_left_B1,title='', xsize=8, $
          uvalue = {object:self,method:'doNothing'},/col,value = '')



misc_left_A=widget_base(misc_left,/col,/frame)

void=widget_label(misc_left_A,value = 'Backround Subtraction Intensity Factor')

self.BackgroundSubtractionField = cw_field(misc_left_A,title='*',$
          uvalue = {object:self,method:'doNothing'},/row,value = '1.0')


void=widget_label(misc_left_A,value = 'Monitor Spectrum Used for Normalisation')

self.MonitorSpectrumNorm = cw_field(misc_left_A,title='%',$
          uvalue = {object:self,method:'doNothing'},/row,value = '85')

void=widget_label(misc_left_A,value = 'Monitor Spectrum Used for Display')

self.MonitorSpectrumDisplay = cw_field(misc_left_A,title='%',$
          uvalue = {object:self,method:'doNothing'},/row,value = '100')


plotBase = widget_base(self.tlb,/col)
winxsize = 400 & winysize = 400
self.win = widget_draw(plotBase,xsize = winxsize,ysize = winysize, $
           /button_events,uvalue = {object:self,method:'zoomEvents'})
self.grpSlider = widget_slider(plotBase,minimum = 1,maximum = 24, $
          uvalue = {object:self,method:'display'})

; Get the vertical size right
cgeom = widget_info(self.ctrlBase,/geometry)
winysize = cgeom.ysize > winysize
winxsize = winysize
widget_control,self.win,ysize = winysize,xsize = winxsize

; Center the widget
geom = widget_info(self.tlb,/geometry)
device,get_screen_size = sz
sx = sz[0] & sy = sz[1]
xoff = fix(0.5*(sx-geom.xsize))
yoff = fix(0.5*(sy-geom.ysize))
widget_control,self.tlb,xoffset = xoff,yoffset = yoff

widget_control,self.tlb,/realize

window,/free,/pixmap,xsize = winxsize,ysize = winysize
self.winPix = !d.window
widget_control,self.win,get_value = winVis
self.winVis = winVis

widget_control,tlb,set_uvalue = self
ret = dave_set_focus(self.tlb)
xmanager,'marsreduction::createwidgets',self.tlb, $
         event_handler = 'marsReductionEvents',$
         cleanup = 'marsReductionCleanup', /no_block
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function marsreduction::init, group_leader = group_leader, $
                 notifyId = notifyId, $
                 workDir = workDir, $
                 datDir = datDir

tvlct,r,g,b,/get
self.rPtr = ptr_new(r)
self.gPtr = ptr_new(g)
self.bPtr = ptr_new(b)
;loadct,0,/silent
device, get_decomposed = old_dc
self.old_dc = old_dc
device,decomposed = 0

;loadCT,0 ,/silent
loadCT,5,NColors=12,Bottom=1 ,/silent


self.notifyIdPtr = ptr_new(/allocate_heap)
self.pgroup_leader = ptr_new(/allocate_heap)

if n_elements(notifyId) ne 0 then $
  *self.notifyIdPtr = notifyId

if n_elements(group_leader) ne 0 then begin
  *self.pgroup_leader = group_leader
  ; Get the DAVE pointer information from group leader
  ; Note that the DAVE pointer is not valid if there is no
  ; group leader specified here!
  widget_control,group_leader,get_uvalue = statePtr
  self.davePtr = (*statePtr).davePtr
  ; DO NOT FREE THE STATEPTR HERE!!!! IT BELONGS TO THE
  ; PARENT (CALLING) WIDGET!!!!
endif

cd,current = curDir
if n_elements(workDir) eq 0 then self.workDir = curDir else self.workDir = workDir
if n_elements(datDir) eq 0 then self.datDir = '' else self.datDir = datDir

self.lambda_fieldPtr = ptr_new(/allocate_heap)
delim=path_sep()


filename=!DAVE_AUXILIARY_DIR+'PSI'+delim+'MARS'+delim+'MARSConstants.txt'
constants=self->GetMARSConstants(filename)


if constants.filefound eq 0 then begin
        void=dialog_message(dialog_parent=group_leader,/error, $
    'The file '+filename+' has not been found.  The program must exit.')
return,0
endif
;help,constants,/struc



self.ConstantsPtr = ptr_new(constants)



filename=!DAVE_AUXILIARY_DIR+'PSI'+delim+'MARS'+delim+'MARS_TimeOffsets.txt'
timeoffsets=self->GetMARSTimeOffsets(filename)
;help,timeoffsets,/struc
if timeoffsets.filefound eq 0 then begin
msg=strarr(2)
msg[0]='The file '+filename
msg[1]='has not been found or the information in the file is invalid.  All time offsets will be set to zero.'
        void=dialog_message(dialog_parent=group_leader,/error,msg)
master1_timeoffset=0.0
master2_timeoffset=0.0
master3_timeoffset=0.0
master4_timeoffset=0.0
master5_timeoffset=0.0
master6_timeoffset=0.0
master7_timeoffset=0.0
timeoffsets=ptr_new({MARSTimeOffsets, $
              filefound:0, $
              master1_timeoffset:master1_timeoffset, $
              master2_timeoffset:master2_timeoffset, $
              master3_timeoffset:master3_timeoffset, $
              master4_timeoffset:master4_timeoffset, $
              master5_timeoffset:master5_timeoffset, $
              master6_timeoffset:master6_timeoffset, $
              master7_timeoffset:master7_timeoffset})
endif
self.timeoffsetsPtr=ptr_new(timeoffsets)
;
self->createwidgets
self.autoscale = 1
self.xrange = [0.0,1.0]
self.yrange = [0.0,1.0]
self.xbox = self.xrange
self.ybox = self.yrange
self.mouse = 0B

; Initialize all of the pointers
self.dataPtr = ptr_new(/allocate_heap)
self.errorPtr = ptr_new(/allocate_heap)
self.xvalsPtr = ptr_new(/allocate_heap)
self.yvalsPtr = ptr_new(/allocate_heap)
self.odataPtr = ptr_new(/allocate_heap)
self.oerrorPtr = ptr_new(/allocate_heap)
self.oxvalsPtr = ptr_new(/allocate_heap)
self.oyvalsPtr = ptr_new(/allocate_heap)
self.sigFilePtr = ptr_new(/allocate_heap)
self.bgFilePtr = ptr_new(/allocate_heap)
self.vanFilePtr = ptr_new(/allocate_heap)
self.TOFMonitor1Ptr = ptr_new(/allocate_heap)
self.oTOFMonitor2Ptr = ptr_new(/allocate_heap)
self.TOFMonitor2Ptr = ptr_new(/allocate_heap)
self.TOFMonitor3Ptr = ptr_new(/allocate_heap)
self.TOFMonitor2xPtr = ptr_new(/allocate_heap)
self.TOFMonitor3xPtr = ptr_new(/allocate_heap)
self.Mon_cumPtr = ptr_new(/allocate_heap)
self.tempPtr = ptr_new(/allocate_heap)
self.InstrumentPtr = ptr_new(/allocate_heap)
self.treatmentPtr = ptr_new(/allocate_heap)
self.headerPtr = ptr_new(/allocate_heap)
self.daveFiles = ptr_new(/allocate_heap)
self.good_detPtr = ptr_new(/allocate_heap)
self.good_ElasticdetPtr = ptr_new(/allocate_heap)
self.selDetPtr = ptr_new(/allocate_heap)
*self.daveFiles = ''
self.oElasticDataPtr = ptr_new(/allocate_heap)
self.oElasticErrorPtr = ptr_new(/allocate_heap)
self.oyvalselasticPtr = ptr_new(/allocate_heap)
self.ElasticDataPtr = ptr_new(/allocate_heap)
self.ElasticErrorPtr = ptr_new(/allocate_heap)
self.yvalselasticPtr = ptr_new(/allocate_heap)
self.Vanadium_Lambda_arrayPtr = ptr_new(/allocate_heap)
self.Vanadium_Area_ArrayPtr = ptr_new(/allocate_heap)
self.Vanadium_PolyFitArrayPtr = ptr_new(/allocate_heap)
self.Vanadium_area_calc_arrayPtr = ptr_new(/allocate_heap)
self.wr_arrayPtr = ptr_new(/allocate_heap)
self.xvalsElasticPtr = ptr_new(/allocate_heap)
self.ElasticDetectorsNamesPtr = ptr_new(/allocate_heap)


self.xlabel = ''
self.ylabel = ''
self.zlabel = ''
self.curFile = ''
self.MonitorsXlabel = ''
self.DiffractionXlabel = ''

self.ElasticdetPtr = ptr_new(/allocate_heap)

self.titlePtr = ptr_new(/allocate_heap)
unit = !dave_invAngstromSym
titleArray='woof'
*self.titlePtr = titleArray

*self.vanFilePtr = 'Automatic'

;load constants
AllElasticDetectors=strarr(12)
AllElasticDetectors[0]='Aare165'
AllElasticDetectors[1]='Aare135'
AllElasticDetectors[2]='Aare105'
AllElasticDetectors[3]='Aare75'
AllElasticDetectors[4]='Aare45'
AllElasticDetectors[5]='Aare15'
AllElasticDetectors[6]='Berg15'
AllElasticDetectors[7]='Berg45'
AllElasticDetectors[8]='Berg75'
AllElasticDetectors[9]='Berg105'
AllElasticDetectors[10]='Berg135'
AllElasticDetectors[11]='Berg165'

*self.ElasticDetectorsNamesPtr = AllElasticDetectors

return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro marsreduction__define
define = {marsreduction,      $

          tlb:0L,          $
          ctrlBase:0L,        $
          grpSlider:0L,       $
          runGroup:0L,        $
          Bad_DetectorGroup:0L,  $
          treatGroup:0L,      $
          FormatTypesGroup:0L,      $
          DataOutputTypesGroup:0L,      $
          van_Base:0L,       $
          Bg_Base:0L,        $
          grpButton:0L,       $
          fileText:0L,        $
          vanText:0L,         $
          bgText:0L,       $
          ebin_group:0L,       $
          ebin_group1:0L,       $
          PhiBin_group1:0L,       $
          E_TOF_base1:0L,       $
          q_theta_base1:0L,       $
          PhiBin_group:0L,       $
          units:0L,       $
          Output_nameGroup:0L,       $
          Output_name_subbase_sensitive:0L,       $
          Output_name_subbase_sensitive1:0L,       $
          Output_name_subbase_sensitive2:0L,       $
          Output_name_subbase_sensitive3:0L,       $
          stem1:0L,       $
          stem2:0L,       $
          stem3:0L,       $
          Signal_Runs:0L,   $
          Background_Runs:0L,   $
          Vanadium_Run:0L,   $
          old_dc:0L,   $
          BackgroundSubtractionField:0L,   $
          MonitorSpectrumNorm:0L,   $
          MonitorSpectrumDisplay:0L,   $


         ;Misc related
          Misc_Group1:0L,   $
          TriffidAngle_Group:0L,  $
          misc_left_B1:0L,  $
          TriffidField:0L,  $


         ;Diffracton related
          DiffOutput_nameGroup:0L,       $
          DiffOutput_name_subbase_sensitive:0L,       $
          DiffOutput_name_subbase_sensitive1:0L,       $
          DiffOutput_name_subbase_sensitive2:0L,       $
          DiffOutput_name_subbase_sensitive3:0L,       $
          Diffstem1:0L,       $
          Diffstem2:0L,       $
          Diffstem3:0L,       $
          DiffFormatTypesGroup:0L,      $
          DiffDataOutputTypesGroup:0L,      $
          DiffONGroup:0L,      $
          DiffOutput_name_Lbase:0L,      $
          xvalsElasticPtr:ptr_new(),    $
          ElasticDetectorsNamesPtr:ptr_new(),    $

         ;Freebie related
          TargetReflection_Field:0L,   $
          freebies:0L,   $
          FreebieOutput_nameGroup:0L,   $
          Freebie_submaster_Lower:0L,   $
          FreebieOutput_name_subbase_sensitive:0L,   $
          FreebieOutput_name_subbase_sensitive1:0L,   $
          FreebieOutput_name_subbase_sensitive2:0L,   $
          FreebieOutput_name_subbase_sensitive3:0L,   $
          Freebiestem1:0L,   $
          Freebiestem2:0L,   $
          Freebiestem3:0L,   $
          SecondaryReduceButton:0L,   $
          WorkingReflection:'', $
          wr_arrayPtr:ptr_new(),    $

          ; Window/display variables
          win:0L,          $
          winVis:0L,       $
          winPix:0L,       $
          xrange:fltarr(2),      $
          yrange:fltarr(2),      $
          xbox:fltarr(2),      $
          ybox:fltarr(2),      $
          autoscale:1,        $
          mouse:0B,         $
          xlabel:'',       $
          MonitorsXlabel:'',       $
          DiffractionXlabel:'',       $
          ylabel:'',       $
          zlabel:'',       $
          titlePtr:ptr_new(),    $
          daveFiles:ptr_new(),     $



          ; Directory variables
          workDir:'',         $
          datDir:'',       $
          ; Detector pointer
          selDetPtr:ptr_new(),     $

          ; Raw data file variables
          TOFMonitor1Ptr:ptr_new(),      $
          oTOFMonitor2Ptr:ptr_new(),      $
          TOFMonitor2Ptr:ptr_new(),      $
          TOFMonitor3Ptr:ptr_new(),      $
          TOFMonitor2xPtr:ptr_new(),      $
          TOFMonitor3xPtr:ptr_new(),      $
          Mon_cumPtr:ptr_new(),      $
          headerPtr:ptr_new(),     $
          ElasticdetPtr:ptr_new(),      $
          tempPtr:ptr_new(),   $
          instrumentPtr:ptr_new(),   $
          ConstantsPtr:ptr_new(),   $
          timeoffsetsPtr:ptr_new(),   $
          ndet:0,          $
          nElasticdet:0,          $
          curFile:'',         $
          unix_start_time:0L,         $


          ; Original inelastic data set
          odataPtr:ptr_new(),    $
          oerrorPtr:ptr_new(),     $
          oyvalsPtr:ptr_new(),     $

          ; Original elastic data set
          oElasticDataPtr:ptr_new(),    $
          oElasticErrorPtr:ptr_new(),     $
          oyvalselasticPtr:ptr_new(),     $


          ; Original tof array
          oxvalsPtr:ptr_new(),     $

          ; Working tof array after conversion to point data
          xvalsPtr:ptr_new(),     $


       ; Working inelastic data set
          dataPtr:ptr_new(),   $
          errorPtr:ptr_new(),    $
          yvalsPtr:ptr_new(),    $

       ; Working elastic data set
          ElasticDataPtr:ptr_new(),   $
          ElasticErrorPtr:ptr_new(),    $
          yvalselasticPtr:ptr_new(),    $


       ; Pointer to the lambda fields
       lambda_fieldPtr:ptr_new(),  $
       ; Good Detector Pointer
        good_detPtr:ptr_new(),   $
        good_ElasticdetPtr:ptr_new(),   $

       ; Automatic Vanadium Correction Related
        Vanadium_Lambda_arrayPtr:ptr_new(),   $
        Vanadium_Area_ArrayPtr:ptr_new(),   $
        Vanadium_PolyFitArrayPtr:ptr_new(),   $
        Vanadium_area_calc_arrayPtr:ptr_new(),   $


       ; Colors for restoration upon quitting
          rPtr:ptr_new(),      $
          gPtr:ptr_new(),      $
          bPtr:ptr_new(),      $
          ; Detector pointer
          ; Treatment pointer
          treatmentPtr:ptr_new(),   $

          ; File pointers
          sigFilePtr:ptr_new(),   $
          bgFilePtr:ptr_new(),     $
          vanFilePtr:ptr_new(),   $

          ; Dave pointer
          davePtr:ptr_new(),   $

          ; Info about parent
          notifyIdPtr:ptr_new(), $
          pgroup_leader:ptr_new()   $
          }


return
end
