; $Id: fcs_reduction.pro,v 1.4 2005/02/08 17:20:27 azuah Exp $
;+
; NAME:
;       FCS_REDUCTION
;
; PURPOSE: 
;
;       Widget application for the reduction of TOF data from the
;		Fermi Chopper Spectrometer (FCS).
;
; AUTHOR:
;
;       Robert M. Dimeo, Ph.D.
;		NIST Center for Neutron Research
;       100 Bureau Drive
;		Gaithersburg, MD 20899
;       Phone: (301) 975-8135
;       E-mail: robert.dimeo@nist.gov
;       http://www.ncnr.nist.gov/staff/dimeo
;
; CATEGORY:
;
;       Widgets, data reduction, neutron scattering
;
; CALLING SEQUENCE:
;
;       FCS_REDUCTION,	GROUP_LEADER = group_leader, $
;						DATADIRECTORY = datadirectory
; INPUT PARAMETERS:
;
;			NONE
;
; INPUT KEYWORDS:
;
;			FILENAME
;			DATADIRECTORY
;
; REQUIRED PROGRAMS:
;
;			XCOLORS.PRO
;			FCSDATA__DEFINE.PRO
;			FCS_REDUCE_PREFS.PRO
;
; COMMON BLOCKS:
;
;			NONE
;
; RESTRICTIONS
;
;			NONE
;
; MODIFICATION HISTORY:
;
;       Written by Rob Dimeo, September 2, 2002.
;		01/20/03 (RMD):	Extended and modified substantially.
;		01/21/03 (CRAIG BROWN): ADDED ERROR BAR PLOT OPTION.
;		01/21/03 (Craig Brown): added vanadium reduction (doesnt scale bad detectors!).
;		01/27/03 (CB): Added detector efficiency and half height detector correction
;		01/31/03 (CB): Added Summing of files from raw tof data
;		02/05/03 (CB): Added Subtracting two files from raw tof data
;		02/05/03 (CB): Added write and read DAVE files for the above. has to be raw data
;		02/14/03 (CB): Added treatment tracker and info text widget
;		02/27/03 (CB): Started detector choice and grouping
;		03/31/03 (CB): Fixed group slider sensitive with SQW indept rest plot options
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;###############################################################################
; 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.
;
;###############################################################################
pro fcs_reduction_cleanup,tlb
widget_control,tlb,get_uvalue = pState
wdelete,(*pState).winPix
ptr_free,(*pState).prefsPtr
ptr_free,(*pState).incdetptr
if obj_valid((*pState).o) then obj_destroy,(*pState).o
if obj_valid((*pState).v) then obj_destroy,(*pState).v
if (*pState).group_leader eq 0 then begin
   ptr_free,(*(*(*pState).davePtr).datastrptr).commonstr.histptr
   ptr_free,(*(*(*pState).davePtr).datastrptr).commonstr.commonstrptr
   ptr_free,(*(*(*pState).davePtr).datastrptr).commonstr.treatmentptr
   ptr_free,(*(*(*(*pState).davePtr).datastrptr).specificptr).dettypeptr
   ptr_free,(*(*(*(*pState).davePtr).datastrptr).specificptr).detectoranglesptr
   ptr_free,(*(*(*(*pState).davePtr).datastrptr).specificptr).distptr
   ptr_free,(*(*(*(*pState).davePtr).datastrptr).specificptr).monptr
   ptr_free,(*(*(*pState).davePtr).datastrptr).specificptr
   ptr_free,(*(*pState).davePtr).datastrptr
   ptr_free,(*(*pState).davePtr).descriptr
   ptr_free,(*pState).davePtr
endif
ptr_free,pState
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_reduction_loadvan,event
widget_control,event.top,get_uvalue = pState
v = obj_new('fcsdata',dataDirectory = (*pState).dataDirectory)
	msg = 'Load a Vanadium file'
	fcs_flashMessage_create,msg,base,event
test = v->loaddata(group_leader = event.top)
if test eq -1 then begin
  obj_destroy,v
  return
endif
if obj_valid((*pState).v) then obj_destroy,(*pState).v
(*pState).v = v
	fcs_flashMessage_destroy,base
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_reduction_load_DAVE,event
widget_control,event.top,get_uvalue = pState

o = obj_new('fcsdata',dataDirectory = (*pState).dataDirectory)
test = o->loaddave(group_leader = event.top)
if test eq -1 then begin
  obj_destroy,o
  return
endif

o->getproperty,ndets = ndets, $
			wavelength = wavelength, $
            detectors = detectors, $
            filename = filename, $
            rawdata = rawdata, $
            rawerror = rawerror, $
            alldata = alldata, $
            error = error, $
            temperature = temperature, $
			dettype = dettype,$
			time = time,$
			dist = dist,$
			;mon = mon,$
			nchan = nchan,$
			run = run,$
			rtime = rtime,$
			user = user,$
			comments = comments,$
			chanwidth = chanwidth,$
			chop_pulses = chop_pulses,$
			chop_freq = chop_freq ,$
			totalmonitor = totalmonitor,$
			date = date,$
			treatment=treatment

mon=rawdata[*,0]
OBJ_DESTROY,o

if obj_valid((*pState).o) then begin
  obj_destroy,(*pState).o
  (*pState).o= obj_new('fcsdata',dataDirectory = (*pState).dataDirectory)
endif else begin
   (*pState).o= obj_new('fcsdata',dataDirectory = (*pState).dataDirectory)
endelse

(*pState).o-> setproperty,ndets=ndets, $
			wavelength=wavelength, $
			detectors=detectors, $
			filename=filename, $
			rawdata=rawdata, $
			alldata=rawdata,$
			mon=mon, $
			rawerror=rawerror, $
			error=rawerror, $
			temperature=temperature, $
			dettype=dettype, $
			time=time, $
			dist=dist, $
 			nchan=nchan, $
			run=run, $
			rtime=rtime, $
			user=user, $
			comments=comments, $
			chanwidth=chanwidth, $
			chop_pulses=chop_pulses, $
			chop_freq =chop_freq, $
			totalmonitor =totalmonitor, $
			date = date, $
			treatment=treatment,$
			loaded=1,$
			incdet=*(*pstate).incdetptr

(*(*pState).prefsPtr).T = temperature
; Do we need to update an existing PREFERENCES dialog?
if xregistered('fcs_reduce_prefs') then begin
; Ok create a pseudo-event and send it to the preferences
; dialog (actually we are sending the event to a base within
; the dialog).
  TInfo = {TEvent,$
                  ID:(*pState).outputID,$
                  Top:(*pState).outputTOP,$
                  Handler:0l,$
                  temperature:temperature}
  if widget_info((*pState).outputID,/valid_id) then begin $
    widget_control,(*pState).outputID,send_event = TInfo
  endif
endif else begin
  (*pState).outputID = 0L
  (*pState).outputID = 0L
endelse
end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_reduction_load,event
widget_control,event.top,get_uvalue = pState
o = obj_new('fcsdata',dataDirectory = (*pState).dataDirectory)
test = o->loaddata(group_leader = event.top)
if test eq -1 then begin
  obj_destroy,o
  return
endif
if obj_valid((*pState).o) then obj_destroy,(*pState).o
(*pState).o = o
(*pState).o->setProperty,incdet=*(*pstate).incdetptr
(*pState).o->getProperty,temperature = temperature
(*(*pState).prefsPtr).T = temperature
; Do we need to update an existing PREFERENCES dialog?
if xregistered('fcs_reduce_prefs') then begin
; Ok create a pseudo-event and send it to the preferences
; dialog (actually we are sending the event to a base within
; the dialog).
  TInfo = {TEvent,$
                  ID:(*pState).outputID,$
                  Top:(*pState).outputTOP,$
                  Handler:0l,$
                  temperature:temperature}
  if widget_info((*pState).outputID,/valid_id) then begin $
    widget_control,(*pState).outputID,send_event = TInfo
  endif
endif else begin
  (*pState).outputID = 0L
  (*pState).outputID = 0L
endelse
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_reduction_plot,event,_Extra = extra
widget_control,event.top,get_uvalue = pState
if not(obj_valid((*pState).o)) then return

uname = 'FCS_PLOT_SEL'
id = widget_info(event.top,find_by_uname = uname)
widget_control,id,get_value = val

uname = 'FCS_DESIRED_GRPS'
id = widget_info(event.top,find_by_uname = uname)
widget_control,id,get_value = nogrps
idslider=widget_info(event.top,find_by_uname = 'FCS_GROUP_SLIDER')
if val[0] ne 3 then begin
if nogrps eq 1 then begin
  widget_control,idslider,sensitive=0
  widget_control,idslider,set_slider_max = 1
  widget_control,idslider,set_value = 0
endif else begin
   widget_control,idslider,sensitive=1
endelse
endif


uname = 'FCS_PLOT_TYPE'
plot_id = widget_info(event.top,find_by_uname = uname)
widget_control,plot_id,get_value = plot_type

uname = 'FCS_PLOT_ERRORS'
plot_id = widget_info(event.top,find_by_uname = uname)
widget_control,plot_id,get_value = anyerrors
anyerrors=anyerrors[0]			; 0 means supress errors


wset,(*pState).winPix
case val[0] of
	0:	$	; N(phi,t)
		begin
		if plot_type eq 1 then begin	; CUT
			uname = 'FCS_GROUP_SLIDER'
			id = widget_info(event.top,find_by_uname = uname)
			(*pState).o->getProperty,detectors = detectors
			ndets = n_elements(detectors)
			widget_control,id,set_slider_max = ndets-1
			widget_control,id,get_value = detIndex & detIndex = fix(detIndex[0])
			(*pState).o->draw_n_phi_t,detector = detIndex, $
				autoScale = (*pState).autoScale, $
				xrange = (*pState).xrange,	$
				yrange = (*pState).yrange,      $
				errorflag=anyerrors
		endif else begin				; IMAGE
			uname = 'FCS_DESIRED_IMAGE_MAX'
			id = widget_info(event.top,find_by_uname = uname)
			widget_control,id,get_value = ivalue
			(*pState).o->getProperty,n_phi_t_max = thisMax
			uname = 'FCS_IMAGE_MAX'
			thisId = widget_info(event.top,find_by_uname = uname)
			widget_control,thisId,set_value = string(thisMax)
			(*pState).o->image_n_phi_t,image_max = float(ivalue[0]), $
				autoScale = (*pState).autoScale, xrange = (*pState).xrange, $
				yrange = (*pState).yrange
		endelse
		end
	1:	$	; N(phi,E)
		begin
		if plot_type eq 1 then begin	; CUT
			uname = 'FCS_GROUP_SLIDER'
			id = widget_info(event.top,find_by_uname = uname)
			(*pState).o->getProperty,detectors = detectors
			ndets = n_elements(detectors)
			widget_control,id,set_slider_max = ndets-1
			widget_control,id,get_value = detIndex & detIndex = fix(detIndex[0])

			(*pState).o->draw_n_phi_e,detector = detIndex, $
				autoScale = (*pState).autoScale, $
				xrange = (*pState).xrange,	$
				yrange = (*pState).yrange,      $
				errorflag=anyerrors
		endif else begin				; IMAGE
			uname = 'FCS_DESIRED_IMAGE_MAX'
			id = widget_info(event.top,find_by_uname = uname)
			widget_control,id,get_value = ivalue
			(*pState).o->getProperty,n_phi_e_max = thisMax
			uname = 'FCS_IMAGE_MAX'
			thisId = widget_info(event.top,find_by_uname = uname)
			widget_control,thisId,set_value = string(thisMax)
			(*pState).o->image_n_phi_e,image_max = float(ivalue[0]), $
				autoScale = (*pState).autoScale,xrange = (*pState).xrange, $
				yrange = (*pState).yrange
		endelse
		end
	2:	$	; S(phi,E)
		begin
		if plot_type eq 1 then begin	; CUT
			uname = 'FCS_GROUP_SLIDER'
			id = widget_info(event.top,find_by_uname = uname)
			(*pState).o->getProperty,detectors = detectors
			ndets = n_elements(detectors)
			widget_control,id,set_slider_max = ndets-1
			widget_control,id,get_value = detIndex & detIndex = fix(detIndex[0])
			(*pState).o->draw_s_phi_e,detector = detIndex, $
				autoScale = (*pState).autoScale, $
				xrange = (*pState).xrange,	$
				yrange = (*pState).yrange,      $
				errorflag=anyerrors
		endif else begin				; IMAGE
			uname = 'FCS_DESIRED_IMAGE_MAX'
			id = widget_info(event.top,find_by_uname = uname)
			widget_control,id,get_value = ivalue
			(*pState).o->getProperty,s_phi_e_max = thisMax
			uname = 'FCS_IMAGE_MAX'
			thisId = widget_info(event.top,find_by_uname = uname)
			widget_control,thisId,set_value = string(thisMax)
			(*pState).o->image_s_phi_e,image_max = float(ivalue[0]), $
				colorTable = (*pState).colorTable,xrange = (*pState).xrange, $
				yrange = (*pState).yrange,autoScale = (*pState).autoScale
		endelse
		end
	3:	$	; S(Q,E)
		begin
;		if (*(*pState).prefsPtr).Q_APP ne 1 then return
		if plot_type eq 1 then begin	; CUT
			if (*(*pState).prefsPtr).Q_APP ne 1 then return
			uname = 'FCS_GROUP_SLIDER'
			id = widget_info(event.top,find_by_uname = uname)
			(*pState).o->getProperty,nqbins = nqbins
			if nqbins gt 1 then widget_control,id,sensitive=1
			widget_control,id,get_value = detIndex & detIndex = fix(detIndex[0])
			widget_control,id,set_slider_max = (nqbins-1)
			widget_control,id,set_value = (nqbins-1) < detIndex
			widget_control,id,get_value = detIndex
			detIndex = fix(detIndex[0])

			(*pState).o->draw_s_q_e,detector = detIndex, $
				autoScale = (*pState).autoScale, $
				xrange = (*pState).xrange,	$
				yrange = (*pState).yrange,      $
				errorflag=anyerrors
		endif else begin				; IMAGE
			uname = 'FCS_DESIRED_IMAGE_MAX'
			id = widget_info(event.top,find_by_uname = uname)
			widget_control,id,get_value = ivalue
			(*pState).o->getProperty,s_q_e_max = thisMax
			uname = 'FCS_IMAGE_MAX'
			thisId = widget_info(event.top,find_by_uname = uname)
			widget_control,thisId,set_value = string(thisMax)
			(*pState).o->image_s_q_e,image_max = float(ivalue[0]), $
				autoScale = (*pState).autoScale,xrange = (*pSTate).xrange, $
				yrange = (*pState).yrange
		endelse
		end
	4:	$	; G(E)
		begin
			(*pState).o->draw_dos, $
				autoScale = (*pState).autoScale, $
				xrange = (*pState).xrange,	$
				yrange = (*pState).yrange,      $
				errorflag=anyerrors
		end
	5:	$	; Elastic
		begin
			(*pState).o->draw_elastic, $
				autoScale = (*pState).autoScale, $
				xrange = (*pState).xrange,	$
				yrange = (*pState).yrange,      $
				errorflag=anyerrors
		end
else:
endcase
wset,(*pState).winVis
device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_reduction_resize,event
widget_control,event.top,get_uvalue = pState
colGeom = widget_info((*pState).colBase,/geom)
wxsize = event.x-colGeom.xsize
wysize = event.y > colGeom.ysize
wdelete,(*pState).winPix
window,/free,/pixmap,xsize = wxsize,ysize = wysize
(*pState).winPix = !d.window
widget_control,(*pState).win,draw_xsize = wxsize,draw_ysize = wysize
fcs_reduction_plot,event
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_reduction_draw,event
; Handle zooming events
widget_control,event.top,get_uvalue = pState
if not(obj_valid((*pState).o)) then return
case event.type of
0:	begin		; button press
	  (*pState).mouse = event.press
	  if (*pState).mouse eq 4 then begin
	    (*pState).autoscale = 1
        fcs_reduction_plot,event
	  endif
	  if (*pState).mouse eq 1 then begin
	    (*pState).xbox[0] = event.x
	    (*pState).ybox[0] = event.y
        fcs_reduction_plot,event
	    (*pState).autoscale = 0
	    empty
	    widget_control,(*pState).win,/draw_motion_events
	  endif
	end
1:	begin	; button release
	 if (*pState).mouse eq 1 then begin
	  xll = (*pState).xbox[0] < (*pState).xbox[1]
	  yll = (*pState).ybox[0] < (*pState).ybox[1]
	  w = abs((*pState).xbox[1] - (*pState).xbox[0])
	  h = abs((*pState).ybox[1] - (*pState).ybox[0])
	  xur = xll + w
	  yur = yll + h
	  ll = convert_coord(xll,yll,/device,/to_data)
	  ur = convert_coord(xur,yur,/device,/to_data)
	  (*pState).xrange = [ll[0],ur[0]]
	  (*pState).yrange = [ll[1],ur[1]]
      fcs_reduction_plot,event
	  (*pState).mouse = 0B
	  widget_control,(*pState).win,draw_motion_events = 0
	 endif
	 if (*pState).mouse eq 4 then begin
	  fcs_reduction_plot,event
	  (*pState).mouse = 0B
	  widget_control,(*pState).win,draw_motion_events = 0
	 endif
	end
2:	begin	; mouse motion
	  if (*pState).mouse eq 1 then begin
	  	(*pState).xbox[1] = event.x
	  	(*pState).ybox[1] = event.y
	  	xc = [(*pState).xbox[0],event.x,event.x,$
	  	      (*pState).xbox[0],$
	  	      (*pState).xbox[0]]
	  	yc = [(*pState).ybox[0],(*pState).ybox[0],$
	  	      event.y,event.y,$
	  	      (*pState).ybox[0]]
	  	wset,(*pState).winVis
	  	device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]
	  	plots,xc,yc,/device
	  	empty
	  endif
	end
else:
endcase
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_reduction_reduce_van,event
widget_control,event.top,get_uvalue = pState
if not(obj_valid((*pState).v)) then return
	msg = 'Fit Elastic Line for Detector Response'
	fcs_flashMessage_create,msg,base,event
elchan=(*pState).v->findelastic()
if elchan eq -1 then elchan = 400

print,'The vanadium elastic channel is: ',elchan

(*pState).v->getProperty,wavelength = wavelength

;print,'based on wavelength, choose a typical width to fit a gaussian over'
if (wavelength eq '6.0') then begin
	print,wavelength
	print, '6.0A has nominal FWHM of ~6 timechannels (8mus)'
        width=6.0
	void=(*pState).v->fitvanelastic($
	      elastic_channel = elchan, width = width, dt = 8.0)
endif
if (wavelength eq '4.8') then begin
	print,wavelength
	print, '4.8A has nominal FWHM of ~12 timechannels (6mus)'
	width=12.0
        void=(*pState).v->fitvanelastic($
              elastic_channel = elchan, width = width, dt=6.0)
endif

fcs_flashMessage_destroy,base

if void eq -1 then begin
	(*pState).v->getProperty,vanefficiency=vanefficiency
	print,'Your vanadium efficiency per detector are: '
	print,vanefficiency
endif

end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_reduction_groups,event
widget_control,event.top,get_uvalue = pState
uname = 'FCS_DESIRED_GRPS'
id = widget_info(event.top,find_by_uname = uname)
widget_control,id,get_value = nogrps
if (nogrps le 0) then nogrps = 1
if (nogrps gt 63) then nogrps = 63
widget_control,id,set_value = nogrps

idslider=widget_info(event.top,find_by_uname = 'FCS_GROUP_SLIDER')
   widget_control,idslider,set_slider_max = nogrps-1
   widget_control,idslider,sensitive=1
if nogrps eq 1 then begin
  widget_control,idslider,set_slider_max = 1
  widget_control,idslider,set_value = 0
  widget_control,idslider,sensitive=0
endif

detarrin=(*(*pstate).incdetptr)
nodets=n_elements(detarrin)

if nogrps gt nodets then begin
  nogrps=nodets
  widget_control,id,set_value = nogrps
  widget_control,idslider,set_slider_max = nogrps-1
endif

;determine the groups from this and from incdetptr..


dstep=float(nodets)/float(nogrps)
;determine how many detectors left
left=fix(nodets-fix(dstep)*float(nogrps))
dstep=fix(dstep)

;print,'detectors = ',nodets,' groups=',nogrps,' step= ',dstep,' and ',left,'left'

array=intarr(nogrps,63)
array=array*0
if fix(left) gt 0 then ll = 1
if fix(left) eq 0 then ll = 0
start=0
for i=0,nogrps-1 do begin
   for j=start,(start+dstep+ll-1) do begin
          array(i,detarrin(j))=1
   endfor
   start=start+dstep+ll
   if (left) ne 0 then left=left-1
   if (left) eq 0 then ll = 0
endfor
if obj_valid((*pstate).o) then (*pstate).o->setproperty,grpdet=array
widget_control,event.top,set_uvalue = pState
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_reduction_detectors,event
widget_control,event.top,get_uvalue = pState
;need to analyse the string to get the values
uname = 'FCS_DESIRED_DETS'
id = widget_info(event.top,find_by_uname = uname)
widget_control,id,get_value = detstring

detarr=opan_selectgroups(detstring)
if n_elements(detarr) eq 1 then begin
    if detarr eq 0 then return
endif

;if any element is over 63 make it 63:
over=where(detarr ge 62,count)
if (count ge 1) then detarr[over]=62

;need to check this array for duplicated values,max value and maximum array size

detarr=detarr[sort(detarr)]			;put them in order
detarr=detarr[uniq(detarr)]			;remove duplicates

if n_elements(detarr) ge 64 then begin		;make 63 elements
   detarr1 = detarr
   detarr =detarr1[0:62]
endif

*(*pstate).incdetptr=detarr


if (obj_valid((*pState).o)) then begin
	(*pstate).o->setproperty,incdet=detarr
endif

widget_control,event.top,set_uvalue = pState
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_reduction_reduce,event
widget_control,event.top,get_uvalue = pState
if not(obj_valid((*pState).o)) then return


msg = 'Converting from time to energy'
fcs_flashMessage_create,msg,base,event
slider_id = widget_info(event.top,find_by_uname = 'FCS_GROUP_SLIDER')
(*pState).o->getProperty,detectors = detectors
ndets = n_elements(detectors)
;widget_control,slider_id,set_slider_max = ndets-1,set_value = 0

if (*(*pState).prefsPtr).ELCH_APP eq 1 then begin
	dummy = (*pState).o->timeToEnergy(	$
			lo_chan = (*(*pState).prefsPtr).BGLO, $
			hi_chan = (*(*pState).prefsPtr).BGHI, $
			elastic_channel = (*(*pState).prefsPtr).ELCH, $
			sigma = (*(*pState).prefsPtr).sigma	)
endif else begin
	dummy = (*pState).o->timeToEnergy(	$
			lo_chan = (*(*pState).prefsPtr).BGLO, $
			hi_chan = (*(*pState).prefsPtr).BGHI, $
			sigma = (*(*pState).prefsPtr).sigma	)
endelse
fcs_flashMessage_destroy,base

if dummy eq -1 then return

;   Account for Energy dependent detector efficiency
dummy = (*pState).o->detectoreff()


; if vannorm flag set AND vanadium is loaded
;       Normalize the function

if (*(*pState).prefsPtr).VAN_NORM then begin
  if (obj_valid((*pState).v)) then begin
     msg = 'Normalize to fitted vanadium'
     fcs_flashMessage_create,msg,base,event
     (*pState).v->getProperty,vanefficiency=vanefficiency
     dummy = (*pState).o->normalize(factor=vanefficiency)
     fcs_flashMessage_destroy,base
   endif
endif


; Symmetrize function?
if (*(*pState).prefsPtr).SYMM_APP then begin
	(*pState).o->symmetrize
endif

; Rebin in energy?
if (*(*pState).prefsPtr).E_APP then begin
	msg = 'Rebinning in energy'
	fcs_flashMessage_create,msg,base,event
	elo = (*(*pState).prefsPtr).ELO
	ehi = (*(*pState).prefsPtr).EHI
	nbins = (*(*pState).prefsPtr).NEBINS
	(*pState).o->energy_rebin,elo = elo, ehi = ehi, nbins = nbins
	fcs_flashMessage_destroy,base
endif


; Calculate the density of states
msg = 'Calculating the density of states'
fcs_flashMessage_create,msg,base,event
(*pState).o->calcDOS
fcs_flashMessage_destroy,base

; Rebin in Q?
if (*(*pState).prefsPtr).Q_APP then begin
	msg = 'Rebinning in Q'
	fcs_flashMessage_create,msg,base,event
	qlo = (*(*pState).prefsPtr).QLO
	qhi = (*(*pState).prefsPtr).QHI
	nqbins = (*(*pState).prefsPtr).NQBINS
	(*pState).o->phi_to_q,nqbins = nqbins,qrange = [qlo,qhi]
	fcs_flashMessage_destroy,base
       ; Adjust the maximum value for the slider
	slider_id = widget_info(event.top,find_by_uname = 'FCS_GROUP_SLIDER')
	widget_control,slider_id,set_slider_max = nqbins-1,set_value = 0
endif

; NEED TO ADD IN FUNCTIONS TO AVERAGE OVER DETECTORS IF NEED BE
; COPY THE USEFUL DATA OVER TO THE NEW gp GROUPS AND WORK FROM THERE.

(*pState).o->average_dets

fcs_reduction_plot,event
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro launch_fcs_prefs,event
widget_control,event.top,get_uvalue = pState
thisEvent = tag_names(event,/structure_name)
case thisEvent of
'WIDGET_BUTTON': $
 	begin
		fcs_reduce_prefs,	group_leader = event.top,	$
							notifyIDs = [event.id,event.top], $
							prefs = *(*pState).prefsPtr,	$
							outputID = outputID,			$
							outputTOP = outputTOP,	$
							err = err

		if err then return
		(*pState).outputTOP = outputTOP
		(*pState).outputID = outputID
	end
'FCSEVENT': $
  begin
	*(*pState).prefsPtr = event.prefs
	fcs_reduction_reduce,event
  end
else:
endcase
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro launch_fcs_gettof,event
thisEvent = tag_names(event,/structure_name)
case thisEvent of
'WIDGET_BUTTON': $
 	begin
		widget_control,event.top,get_uvalue = pState
		fcs_get_files,group_leader = event.top,	$
				savetodir=(*!dave_defaults).datdir,$
				err=err
			if err then return
		end
else:
endcase

end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro launch_fcs_manip,event
thisEvent = tag_names(event,/structure_name)
case thisEvent of
'WIDGET_BUTTON': $
 	begin
		widget_control,event.top,get_uvalue = pState
		fcs_reduce_manip,	group_leader = event.top,	$
							notifyIDs = [event.id,event.top], $
							err = err,$
							datadirectory=(*pstate).datadirectory,$
							daveptr=(*pstate).daveptr
		if err then return

	end
'FCSEVENT': $
  begin
	widget_control,event.top,get_uvalue = pState
	*(*pState).prefsPtr = event.prefs
        fcs_reduction_detectors,event
        fcs_reduction_groups,event
	fcs_reduction_reduce,event
  end
else:
endcase
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_file_details_dismiss,event
widget_control,event.top,/destroy
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_file_details,event
	;want to get the file name and list the
	;temperature
	;treatment info
	;in a single  text widget, non-editable and a dismiss button.

widget_control,event.top,get_uvalue=pstate
if obj_valid((*pstate).o) eq 0 then begin
  return
endif

(*pstate).o->getproperty,treatment=treatment,filename=filename,user=user,comments=comments,$
		wavelength=wavelength,rtime=rtime

text=['filename: '+filename,'Comments: '+comments,'User: '+user,'Wavelength: '+string(wavelength),$
	'Run Time: '+string(rtime),treatment]

ysize=15
if n_elements(text) le 15 then ysize = n_elements(text)

tlb2 = widget_base(group_leader = event.top,/col, $
	title = 'File Information', $
	/base_align_left,/tlb_frame_attr,modal=1)
base1 = widget_base(tlb2,/col,frame=2)
void=widget_text(base1,/scroll,value=text,ysize=ysize)

void = widget_button(Base1,value = 'Dismiss',event_pro='fcs_file_details_dismiss')

widget_control,tlb2,/realize
xmanager,'info',tlb2

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_flashMessage_create,msg,base,event
; This method simply flashes a widget with a message that remains present
; until the flashMessage_destroy method is invoked.
;
; Center it.
geom = widget_info(event.top, /geometry)
xpos = geom.xoffset + geom.xsize/2 - 100
ypos = geom.yoffset + geom.ysize/2 - 50

base = widget_base(title='Please wait:',/row,xoffset=xpos,yoffset=ypos, $
      tlb_frame_attr = 3,group_leader = event.top)
void = widget_text(base,value = msg,xsize = strlen(msg),/editable)
widget_control,base,/realize
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_flashMessage_destroy,base
widget_control,base,/destroy
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_reduction_save_dave,event
widget_control,event.top,get_uvalue = pState
if not(obj_valid((*pState).o)) then return
(*pState).o->saveDave,	group_leader = event.top,	$
						davePtr = (*pState).davePtr,	$
						n_phi_t = (*(*pState).prefsPtr).DAVE_OUT[0], $
						n_phi_e = (*(*pState).prefsPtr).DAVE_OUT[1], $
						s_phi_e = (*(*pState).prefsPtr).DAVE_OUT[2], $
						s_q_e = (*(*pState).prefsPtr).DAVE_OUT[3], $
						g_e = (*(*pState).prefsPtr).DAVE_OUT[4],$
						raw=(*(*pState).prefsPtr).DAVE_OUT[5],$
						file=''
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_reduction_change_colors,event
widget_control,event.top,get_uvalue = pState
thisEvent = Tag_Names(event, /Structure_Name)
CASE thisEvent OF
	'WIDGET_BUTTON':	BEGIN
							XColors, Group_Leader=event.top, $
							         NotifyID=[event.id, event.top],$
							         title = 'Colors for FCS image display'
					 	ENDCASE

    'XCOLORS_LOAD': 	BEGIN
    							(*pState).colorTable = event.index
								fcs_reduction_plot,event
                 		ENDCASE

ENDCASE
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_reduction_event,event
thisevent= tag_names(event,/structure_name)


if strupcase(thisevent) eq 'FCSINFOEVENT' then begin
	widget_control,event.top,get_uvalue=pstate

        if obj_valid((*pstate).o) eq 0 then begin
   		(*pstate).o = obj_new('fcsdata',dataDirectory = (*pState).dataDirectory)
	endif else begin
		obj_destroy,(*pstate).o
		(*pstate).o = obj_new('fcsdata',dataDirectory = (*pState).dataDirectory)
	endelse
		event.obj->getproperty,ndets = ndets1, $
			wavelength = wavelength1, $
          	  	detectors = detectors1, $
           	 	filename = filename1, $
           	 	alldata = alldata1, $
			rawdata=rawdata1,$
			rawerror=rawerror1,$
           	 	error = error1, $
           	 	temperature = temperature1, $
			dettype = dettype1,$
			time = time1,$
			dist = dist1,$
			;mon = mon1,$
			nchan = nchan1,$
			run = run1,$
			rtime = rtime1,$
			user = user1,$
			comments = comments1,$
			chanwidth = chanwidth1,$
			chop_pulses = chop_pulses1,$
			chop_freq = chop_freq1 ,$
			totalmonitor = totalmonitor1,$
			date = date1,$
			treatment=treatment

mon1=alldata1[*,0]

		(*pstate).o->setproperty,ndets=ndets1, $
			wavelength=wavelength1, $
			detectors=detectors1, $
			filename=filename1, $
			alldata=alldata1, $
			rawdata=rawdata1,$
			rawerror=rawerror1,$
			mon=mon1, $
			error=error1, $
			temperature=temperature1, $
			dettype=dettype1, $
			time=time1, $
			dist=dist1, $
 			nchan=nchan1, $
			run=run1, $
			rtime=rtime1, $
			user=user1, $
			comments=comments1, $
			chanwidth=chanwidth1, $
			chop_pulses=chop_pulses1, $
			chop_freq =chop_freq1, $
			totalmonitor =totalmonitor1, $
			date = date1, $
			treatment=treatment,$
			loaded=1

		temperature = temperature1
		(*(*pState).prefsPtr).T = temperature
		; Do we need to update an existing PREFERENCES dialog?
		if xregistered('fcs_reduce_prefs') then begin
		; Ok create a pseudo-event and send it to the preferences
		; dialog (actually we are sending the event to a base within
		; the dialog).
		  TInfo = {TEvent,$
		                  ID:(*pState).outputID,$
 		                 Top:(*pState).outputTOP,$
  		                Handler:0l,$
  		                temperature:temperature}
  		if widget_info((*pState).outputID,/valid_id) then begin $
   		 widget_control,(*pState).outputID,send_event = TInfo
		  endif
		endif else begin
  		(*pState).outputID = 0L
  		(*pState).outputID = 0L
		endelse
        	widget_control,event.top,set_uvalue=pstate
                fcs_reduction_detectors,event
		fcs_reduction_groups,event
        	fcs_reduction_reduce,event
        	return

endif

uname = widget_info(event.id,/uname)
case uname of
'QUIT':	$
	begin
		widget_control,event.top,/destroy
	end
'FCS_GET_TOF':	$
	begin
		launch_fcs_gettof,event
	end
'FCS_MANIP_TOF':	$
	begin
		launch_fcs_manip,event
	end
'SAVE_DAVE':	$
	begin
		fcs_reduction_save_dave,event
	end
'FCS_LOAD_DAVE':	$
	begin
		fcs_reduction_load_dave,event
                fcs_reduction_detectors,event
		fcs_reduction_groups,event
		fcs_reduction_reduce,event
	end
'FCS_RED_PREFS':	$
	begin
		launch_fcs_prefs,event
	end
'FCS_PLOT_SEL':	$
	begin
		widget_control,event.top,get_uvalue = pState
		if not(obj_valid((*pState).o)) then return
		fcs_reduction_plot,event,_Extra = extra
	end
'FCS_PLOT_TYPE':	$
	begin
		widget_control,event.top,get_uvalue = pState
		if not(obj_valid((*pState).o)) then return
		fcs_reduction_plot,event
	end
'FCS_PLOT_ERRORS':	$
	begin
		widget_control,event.top,get_uvalue = pState
		if not(obj_valid((*pState).o)) then return
		fcs_reduction_plot,event
	end
'FCS_GROUP_SLIDER':	$
	begin
		widget_control,event.top,get_uvalue = pState
		if not(obj_valid((*pState).o)) then return
		fcs_reduction_plot,event
	end
'FCS_DESIRED_IMAGE_MAX':	$
	begin
		widget_control,event.top,get_uvalue = pState
		if not(obj_valid((*pState).o)) then return
		fcs_reduction_plot,event
	end
'FCS_DESIRED_DETS':	$
	begin
		fcs_reduction_detectors,event
		fcs_reduction_groups,event
		fcs_reduction_reduce,event
	end
'FCS_DESIRED_GRPS':	$
	begin
		fcs_reduction_detectors,event
		fcs_reduction_groups,event
		fcs_reduction_reduce,event
	end
'FCS_LOAD_TOF':	$
	begin
		fcs_reduction_load,event
                fcs_reduction_detectors,event
		fcs_reduction_groups,event
		fcs_reduction_reduce,event
	end
'FCS_LOAD_VAN':	$
	begin
		fcs_reduction_loadvan,event
		fcs_reduction_reduce_van,event
	end
'FILE_DETAILS':$
	begin
		fcs_file_details,event
	end
'FCS_RESTORE':	$
	begin
		widget_control,event.top,get_uvalue = pState
		(*(*pState).prefsPtr).Q_APP = 0
		(*(*pState).prefsPtr).E_APP = 0
                fcs_reduction_detectors,event
		fcs_reduction_groups,event
		fcs_reduction_reduce,event
	end
'TOP':	$
	begin
		fcs_reduction_resize,event
	end
'COLORS':	$
	begin
		fcs_reduction_change_colors,event
	end
else:
endcase
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro fcs_reduction,group_leader = group_leader,dataDirectory = dataDirectory
if n_elements(group_leader) eq 0 then begin
    group_leader = 0L
    commonstr={instrument:'',$
		histptr:ptr_new(/allocate_heap) , $
		xlabel:'',$
		ylabel:'',$
		xtype:'',$
		ytype:'',$
		xunits:'',$
		yunits:'',$
		histlabel:'',$
		histunits:'',$
		treatmentptr:ptr_new(/allocate_heap) , $
		commonstrptr:ptr_new(/allocate_heap)}

		dettypeptr=ptr_new(/allocate_heap)
		detectoranglesptr=ptr_new(/allocate_heap)
		distptr=ptr_new(/allocate_heap)
		monptr=ptr_new(/allocate_heap)

		specificstr={dettypeptr:dettypeptr,$
			detectoranglesptr:detectoranglesptr,$
			wavelength:0D,$
			distptr:distptr,$
			monptr:monptr ,$
 			run : 0L,$
			  time : 0D,$
 			 user : "",$
 			 comments: "",$
 			 chanwidth: 0D,$
 			 chop_pulses: 0D,$
 			 chop_freq: 0D,$
 			 monitor : 0D,$
 			 date : '' $
			}
    	datastr= {commonstr:commonstr, specificptr:ptr_new(specificstr,/no_copy)}
    	datastrptr=ptr_new(datastr,/no_copy)

        descriptrstr={descriptrstr,$
			name:'',$
			units:'',$
			legend:'',$
			qty:0.0,$
			err:0.0}

	davestr={daveptrstr,$
		datastrptr:datastrptr, descriptr:ptr_new(descriptrstr)}
        davePtr=ptr_new(davestr,/no_copy)


endif

if (group_leader ne 0) then begin
	widget_control,group_leader,get_uvalue = statePtr
	if ptr_valid(daveptr) eq 0 then  davePtr = (*statePtr).davePtr
	descriptrstr={descriptrstr,$
			name:'',$
			units:'',$
			legend:'',$
			qty:0.0,$
			err:0.0}
	(*daveptr).descriptr=ptr_new(descriptrstr)

		dettypeptr=ptr_new(/allocate_heap)
		detectoranglesptr=ptr_new(/allocate_heap)
		distptr=ptr_new(/allocate_heap)
		monptr=ptr_new(/allocate_heap)
	specificstr={dettypeptr:dettypeptr,$
			detectoranglesptr:detectoranglesptr,$
			wavelength:0D,$
			distptr:distptr,$
			monptr:monptr ,$
 			run : 0L,$
			  time : 0D,$
 			 user : "",$
 			 comments: "",$
 			 chanwidth: 0D,$
 			 chop_pulses: 0D,$
 			 chop_freq: 0D,$
 			 monitor : 0D,$
 			 date : '' $
			}
          *(*(*davePtr).dataStrPtr).specificPtr=specificstr

endif
if n_elements(dataDirectory) eq 0 then dataDirectory = ''
device,decomposed = 0
loadct,15,/silent
!except = 0

; Widget definition module
xsize = 400 & ysize = 400
tlb = widget_base(/row,title = 'FCS Data Reduction Utility',mbar = bar, $
	/tlb_size_events,uname = 'TOP')



filemenu = widget_button(bar,value = 'FILE',/menu)
void = widget_button(filemenu,value = 'Load TOF file',uname = 'FCS_LOAD_TOF')
void = widget_button(filemenu,value = 'Load Vanadium',uname = 'FCS_LOAD_VAN')
void = widget_button(filemenu,value = 'Load _raw.dave',uname = 'FCS_LOAD_DAVE')
void = widget_button(filemenu,value = 'Save as DAVE',uname = 'SAVE_DAVE')
void = widget_button(filemenu,value = 'File Info',uname = 'FILE_DETAILS')
void = widget_button(filemenu,value = 'Quit',uname = 'QUIT')

datamenu = widget_button(bar,value = 'DATA',/menu)
void = widget_button(datamenu,value = 'Get TOF files',uname = 'FCS_GET_TOF')
void = widget_button(datamenu,value = 'ADD/SUB TOF files',uname = 'FCS_MANIP_TOF')


colBase = widget_base(tlb,/col)
colbasegeom=widget_info(colbase,/geometry)
;void = widget_button(colBase,value = 'Restore data', $
;	uname = 'FCS_RESTORE')
void = widget_button(colBase,value = 'Reduction Preferences', $
	uname = 'FCS_RED_PREFS')
colBase2 = widget_base(colbase,/row)
colBase3 = widget_base(colbase2,/col)
colBase4 = widget_base(colbase2,/col)

output = ['I(phi,t)','I(phi,E)','S(phi,E)','S(Q,E)','G(E)','Elastic']
void = cw_bgroup(colBase3, output, /col, /exclusive,$
         label_top='Plot selection',/no_release,$
         frame=1,set_value=2,/return_index, $
         uname = 'FCS_PLOT_SEL')


type = ['Image','Cut']
void = cw_bgroup(colBase4, type, /col, /exclusive,$
         label_top='Plot type',/no_release,$
         frame=1,set_value=1,/return_index, $
         uname = 'FCS_PLOT_TYPE')

suppress = ['Yes','No']
void = cw_bgroup(colBase4, suppress, /col, /exclusive,$
         label_top='Suppress Errs',/no_release,$
         frame=1,set_value=1,/return_index, $
         uname = 'FCS_PLOT_ERRORS')


void = cw_field(colBase,/row,value = '1.0',title = 'Image Max', $
	uname = 'FCS_IMAGE_MAX',/noedit,xsize = 8)
void = cw_field(colBase,/row,value = '1.0',title = 'Desired Image Max', $
	uname = 'FCS_DESIRED_IMAGE_MAX',/return_events,xsize = 8,/floating)

colbasegeom=widget_info(colbase,/geometry)
void = widget_slider(colBase,title = 'Group selection',min = 0, max = 62, $
	value = 0,uname = 'FCS_GROUP_SLIDER',scr_xsize=colbasegeom.scr_xsize)

void = cw_field(colBase,/row,value = '10-36,38-62',title = 'inc. detectors', $
	uname = 'FCS_DESIRED_DETS',/return_events,xsize = 15)
void = cw_field(colBase,/row,value = '63',/integer,title = 'Number of groups', $
	uname = 'FCS_DESIRED_GRPS',/return_events,xsize = 13)

void = widget_button(colBase,value = 'Image colors',uname = 'COLORS')
win = widget_draw(tlb,xsize = xsize,ysize = ysize,/button_events, $
	event_pro = 'fcs_reduction_draw')


widget_control,tlb,/realize
widget_control,win,get_value = winVis
window,/free,/pixmap,xsize = xsize,ysize = ysize
winPix = !d.window
if n_elements(dataDirectory) eq 0 then dataDirectory = 'c:\bhd\data'
datDir = dataDirectory

prefs=		{	MYPREFS,			$
				ELCH:405,			$
  				ELCH_APP:0,			$
  				BGLO:950,			$
  				BGHI:960,			$
  				T:300.0,			$
  				SIGMA:1.0,			$
  				ELO:-20.0,			$
  				EHI:2.0,			$
  				NEBINS:100,			$
  				E_APP:0,			$
  				QLO:0.25,			$
  				QHI:2.5,			$
  				NQBINS:25,			$
  				Q_APP:0,			$
  				SYMM_APP:0,			$
  				VAN_NORM:0,			$
				DAVE_OUT:intarr(6)	$
  			}

state = 	{	davePtr:davePtr,	$
				group_leader:group_leader, $   ;possible to remove in dave?
				win:win,		$
				winVis:winVis,	$
				winPix:winPix,	$
				prefsID:0L,		$
				outputTOP:0L,	$
				outputID:0L,	$
				prefsTOP:0L,	$
				dataDirectory:datDir,	$
				colorTable:5,	$
				prefsPtr:ptr_new(prefs),	$
				o:obj_new(),	$			;data object
				v:obj_new(),	$			;vanadium object
				mouse:0B,		$
				autoscale:1,	$
				xrange:[0.,1.],	$
				yrange:[0.,1.],	$
				xbox:[0.,1.],	$
				ybox:[0.,1.],	$
				incdetptr:ptr_new(indgen(63)),$
				colBase:colBase	}
pState = ptr_new(state,/no_copy)

widget_control,tlb,set_uvalue = pState
xmanager,'fcs_reduction',tlb,/no_block,cleanup = 'fcs_reduction_cleanup'
end
