; $Id: dave_rebindave.pro,v 1.15 2005/02/03 18:04:12 azuah Exp $
;###############################################################################
;
; 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.
;
;###############################################################################
;
; Written by J.R.D. Copley.
;************************************************************************************************
pro dave_rebinDAVE_handler,event
;************************************************************************************************
;
compile_opt strictarr
;
widget_control,event.top,get_uvalue=pstate,/no_copy
;
; Respond to "Cancel" button.
if (event.id eq (*pstate).can) then begin
	(*(*pstate).info).break=1
	widget_control,event.top,set_uvalue=pstate,/no_copy
	widget_control,event.top,/destroy
	return
endif
;
; Respond to text entry in "Output file name" field.
if (event.id eq (*pstate).fn) then begin
	widget_control,(*pstate).fn,get_value=newfile
	(*(*pstate).info).newfile=newfile
	(*(*pstate).info).break=0
endif
;
ok=1
point_to_point=(*pstate).point_to_point
;
; Respond to modification of number of output channels, or to the "Proceed" button.
if (event.id eq (*pstate).nx or event.id eq (*pstate).go) then begin
	widget_control,(*pstate).nx,get_value=abscdims
	abscdims=fix(abscdims[0])
	if (abscdims lt 1) then begin
		widget_control,(*pstate).nx,set_value=(*(*pstate).info).abscdims
		res=dialog_message("The number of output channels must be positive.")
		ok=0
	endif else begin
		(*(*pstate).info).abscdims=abscdims
	endelse
	if (point_to_point) then begin
		dabsc=((*(*pstate).info).abscz_out-(*(*pstate).info).absc0_out)/((*(*pstate).info).abscdims-1)
	endif else begin
		dabsc=((*(*pstate).info).abscz_out-(*(*pstate).info).absc0_out)/(*(*pstate).info).abscdims
	endelse
	widget_control,(*pstate).dd,set_value=strcompress(dabsc)
	(*(*pstate).info).break=0
endif
;
; Respond to modification of first output channel, or to the "Proceed" button.
if (event.id eq (*pstate).x1 or event.id eq (*pstate).go) then begin
	widget_control,(*pstate).x1,get_value=absc0_out
	absc0_out=float(absc0_out[0])
	widget_control,(*pstate).x2,get_value=abscz_out
	abscz_out=float(abscz_out[0])
	if (absc0_out ge abscz_out) then begin
		widget_control,(*pstate).x1,set_value=(*(*pstate).info).absc0_out
		res=dialog_message("The first channel must start before the final channel")
		ok=0
	endif
	if (absc0_out lt abscz_out) then begin
		if ((*pstate).histogrammed) then begin
			if (absc0_out+(*pstate).epsilon lt (*pstate).absc0_in) then begin
				widget_control,(*pstate).x1,set_value=(*(*pstate).info).absc0_out
				res=dialog_message("The first channel must start at at least"+$
					strcompress((*pstate).absc0_in))
				ok=0
			endif else begin
				if (absc0_out lt (*pstate).absc0_in) then begin
					absc0_out=absc0_out+(*pstate).epsilon
					widget_control,(*pstate).x1,set_value=(*(*pstate).info).absc0_out
				endif
				(*(*pstate).info).absc0_out=absc0_out
			endelse
		endif else begin
			(*(*pstate).info).absc0_out=absc0_out
		endelse
	endif
	if (point_to_point) then begin
		dabsc=((*(*pstate).info).abscz_out-(*(*pstate).info).absc0_out)/((*(*pstate).info).abscdims-1)
	endif else begin
		dabsc=((*(*pstate).info).abscz_out-(*(*pstate).info).absc0_out)/(*(*pstate).info).abscdims
	endelse
	widget_control,(*pstate).dd,set_value=strcompress(dabsc)
	(*(*pstate).info).break=0
endif
;
; Respond to modification of final output channel, or to the "Proceed" button.
if (event.id eq (*pstate).x2 or event.id eq (*pstate).go) then begin
	widget_control,(*pstate).x2,get_value=abscz_out
	abscz_out=float(abscz_out[0])
	widget_control,(*pstate).x1,get_value=absc0_out
	absc0_out=float(absc0_out[0])
	if (abscz_out le absc0_out) then begin
		widget_control,(*pstate).x2,set_value=(*(*pstate).info).abscz_out
		res=dialog_message("The final channel must start after the first channel")
		ok=0
	endif
	if (abscz_out gt absc0_out) then begin
		if ((*pstate).histogrammed) then begin
			if (abscz_out-(*pstate).epsilon gt (*pstate).abscz_in) then begin
				widget_control,(*pstate).x2,set_value=(*(*pstate).info).abscz_out
				res=dialog_message("The final channel must end at at most"+$
					strcompress((*pstate).abscz_in))
				ok=0
			endif else begin
				if (abscz_out gt (*pstate).abscz_in) then begin
					abscz_out=abscz_out-(*pstate).epsilon
					widget_control,(*pstate).x2,set_value=(*(*pstate).info).abscz_out
				endif
				(*(*pstate).info).abscz_out=abscz_out
			endelse
		endif else begin
			(*(*pstate).info).abscz_out=abscz_out
		endelse
	endif
	if (point_to_point) then begin
		dabsc=((*(*pstate).info).abscz_out-(*(*pstate).info).absc0_out)/((*(*pstate).info).abscdims-1)
	endif else begin
		dabsc=((*(*pstate).info).abscz_out-(*(*pstate).info).absc0_out)/(*(*pstate).info).abscdims
	endelse
	widget_control,(*pstate).dd,set_value=strcompress(dabsc)
	(*(*pstate).info).break=0
endif
;
go=event.id eq (*pstate).go
widget_control,event.top,set_uvalue=pstate,/no_copy
if (ok and go) then widget_control,event.top,/destroy
;
end


;************************************************************************************************
pro dave_rebinDAVE,event
;************************************************************************************************
;
compile_opt strictarr
;
widget_control,event.top,get_uvalue=statePtr
davePtr=(*statePtr).davePtr
;
files=dialog_pickfile(title="Select DAVE data file(s) to be rebinned:",$
	filter=["*.dave"],/multiple_files,/must_exist,path=(*!dave_defaults).workdir)
files=files[sort(files)]
nruns=n_elements(files)
if (files[0] eq "") then begin
	x=dialog_message(["No files selected.","Exiting ..."])
	(*statePtr).davePtr=davePtr
	return
endif
;
for irun=0,nruns-1 do begin
	filename=files[irun]
	if (not file_test(filename)) then begin
		message,filename+": there is no such file name."
		(*statePtr).davePtr=davePtr
		return
	endif
;
	restore,filename=filename
;
; Determine whether x and/or y are vectors or arrays.
	x_is_v=$
		size((*(*(*davePtr).dataStrPtr).commonStr.histPtr).x,/n_dimensions) eq 1
	y_is_v=$
		size((*(*(*davePtr).dataStrPtr).commonStr.histPtr).y,/n_dimensions) eq 1
	x_is_a=not x_is_v
	y_is_a=not y_is_v
;
	if (x_is_a and y_is_a) then begin
		res=dialog_message(['File '+filename+"."," ","Data cannot be rebinned."],/error)
		break
	endif
;
	if (x_is_v or y_is_v) then begin
;
; This section defines rebin_x and rebin_y.
		if (x_is_v and y_is_a) then begin
			rebin_x=1
			rebin_y=0
		endif
;
		if (x_is_a and y_is_v) then begin
			rebin_x=0
			rebin_y=1
		endif
;
		xlabel=(*(*davePtr).dataStrPtr).commonStr.xlabel
		ylabel=(*(*davePtr).dataStrPtr).commonStr.ylabel
		xtype=strupcase((*(*davePtr).dataStrPtr).commonStr.xtype)
		ytype=strupcase((*(*davePtr).dataStrPtr).commonStr.ytype)
;
		if (x_is_v and y_is_v) then begin
			x_is_h=strcmp(xtype,"HISTOGRAM",/fold_case)
			y_is_h=strcmp(ytype,"HISTOGRAM",/fold_case)
			res=dialog_message(['File '+filename+"."," ",$
				"Data can be rebinned in "+strcompress(xlabel)+" ("+xtype+$
				") and/or in "+strcompress(ylabel)+" ("+ytype+$
				")."," ","Do you wish to rebin in "+strcompress(xlabel)+"?"],/question)
			rebin_x=res eq "Yes"
			if (rebin_x) then res=$
				dialog_message("Do you also wish to rebin in "+strcompress(ylabel)+"?",/question) else $
				res=$
				dialog_message("Do you wish to rebin in "+strcompress(ylabel)+"?",/question)
			rebin_y=res eq "Yes"
		endif
	;
		if (rebin_x) then kks=1 else kks=2
		if (rebin_y) then kke=2 else kke=1
	;
		if (kks gt kke) then break
;
		if (rebin_x) then begin
;			if (x_is_h) then x_topoints='No' else x_topoints=$
;			dialog_message("Do you wish to rebin "+strcompress(xlabel)+" to points?",/question)
			if (x_is_h) then x_topoints='No' else x_topoints='Yes'
		endif
		if (rebin_y) then begin
;			if (y_is_h) then y_topoints='No' else y_topoints=$
;			dialog_message("Do you wish to rebin "+strcompress(ylabel)+" to points?",/question)
			if (y_is_h) then y_topoints='No' else y_topoints='Yes'
		endif
;
		len=strlen(filename)
		newfile=strmid(filename,0,len-5)+"_rb.dave"

		for kk=kks,kke do begin
			binning_x=(kk eq 1)
			binning_y=(kk eq 2)
			if (binning_x) then begin
				qty_in=(*(*(*davePtr).dataStrPtr).commonStr.histPtr).qty
				err_in=(*(*(*davePtr).dataStrPtr).commonStr.histPtr).err
				absc_in=(*(*(*davePtr).dataStrPtr).commonStr.histPtr).x
				why=(*(*(*davePtr).dataStrPtr).commonStr.histPtr).y
				units=(*(*davePtr).dataStrPtr).commonStr.xunits
				label=xlabel
				histogrammed=strcmp((*(*davePtr).dataStrPtr).commonStr.xtype,"histogram",/fold_case)
				topoints=x_topoints eq 'Yes'
			endif
;
			if (binning_y) then begin
				qty_in=transpose((*(*(*davePtr).dataStrPtr).commonStr.histPtr).qty)
				err_in=transpose((*(*(*davePtr).dataStrPtr).commonStr.histPtr).err)
				eks=(*(*(*davePtr).dataStrPtr).commonStr.histPtr).x
				absc_in=(*(*(*davePtr).dataStrPtr).commonStr.histPtr).y
				units=(*(*davePtr).dataStrPtr).commonStr.yunits
				label=ylabel
				histogrammed=strcmp((*(*davePtr).dataStrPtr).commonStr.ytype,"histogram",/fold_case)
				topoints=y_topoints eq 'Yes'
			endif
;
			points=not histogrammed
			if (points) then begin
				abscdims_in=n_elements(absc_in)
				absc0_in=absc_in[0]
				abscz_in=absc_in[abscdims_in-1]
				units=strmid(units,strpos(units,":")+1)
				inlabel=$
					"The "+strcompress(abscdims_in)+" input POINTS range from "+$
					strmid(strcompress(absc0_in),0,8)+" to "+strmid(strcompress(abscz_in),0,8)+$
					' '+units
			endif
;
			if (histogrammed) then begin
				abscdims_in=n_elements(absc_in)-1
				absc0_in=absc_in[0]
				abscz_in=absc_in[abscdims_in]
				units=strmid(units,strpos(units,":")+1)
				inlabel=$
					"The "+strcompress(abscdims_in)+" input CHANNELS range from "+$
					strmid(strcompress(absc0_in),0,8)+" to "+strmid(strcompress(abscz_in),0,8)+$
					' '+units
			endif
;
			epsilon=(abscz_in-absc0_in)*1.e-5
;
			point_to_point=points and topoints
;
			if (point_to_point) then begin
				abscdims=20 < abscdims_in
				dabsc=(abscz_in-absc0_in)/abscdims
				absc0_out=absc0_in+dabsc*0.5
				abscz_out=abscz_in-dabsc*0.5
			endif else begin
				abscdims=20 < abscdims_in
				dabsc=(abscz_in-absc0_in)/abscdims
				absc0_out=absc0_in
				abscz_out=abscz_in
			endelse
;
			if (topoints) then begin
				outlabel1='output point centers span '
				outlabel2='Point separation is '
			endif else begin
				outlabel1='output channels range from '
				outlabel2='Channel width is '
			endelse
;
			tlb=widget_base(/col,title='As required, edit output channel '+$
				'specs and/or file name.',group_leader=event.top,/modal)
				vd=widget_label(tlb,value='File '+filename+".")
				vd=widget_label(tlb,value="Data from this file will be rebinned in "+$
					strcompress(label)+".")
				vd=widget_label(tlb,value='')
				vd=widget_label(tlb,value=inlabel)
				butbase1=widget_base(tlb,/row,/align_center)
					nx=cw_field(butbase1,title='The ',value=abscdims,$
						/string,/return_events,xsize=4)
					x1=cw_field(butbase1,title=outlabel1,value=absc0_out,/string,$
						/return_events,xsize=6)
					x2=cw_field(butbase1,title='to ',value=abscz_out,/string,$
						/return_events,xsize=6)
					vd=widget_label(butbase1,value=units)
				butbase2=widget_base(tlb,/row,/align_center)
					vd=widget_label(butbase2,value=outlabel2)
					dd=widget_text(butbase2,value=strcompress(dabsc),xsize=6)
					vd=widget_label(butbase2,value=' '+units+'.   ')
					can=widget_button(butbase2,value='Cancel')
					go=widget_button(butbase2,value='Proceed')
				butbase3=widget_base(tlb,/row,/align_center)
					fn=cw_field(butbase3,title='Output file name',value=newfile,/column,$
						/return_events,xsize=strlen(filename)+6)
			centertlb,tlb
			widget_control,tlb,/realize
			info=ptr_new({abscdims:abscdims,absc0_out:absc0_out,abscz_out:abscz_out,$
				newfile:newfile,break:1})
			state={info:info,can:can,go:go,nx:nx,x1:x1,x2:x2,dd:dd,fn:fn,$
				epsilon:epsilon,absc0_in:absc0_in,abscz_in:abscz_in,$
				histogrammed:histogrammed,point_to_point:point_to_point}
			ppstate=ptr_new(state,/no_copy)
			widget_control,tlb,set_uvalue=ppstate
			xmanager,'dave_rebinDAVE',tlb,event_handler='dave_rebinDAVE_handler'
			ptr_free,ppstate
;
			donotsave=(*info).break
			if (donotsave) then break
;
			abscdims=(*info).abscdims
			absc0_out=(*info).absc0_out
			abscz_out=(*info).abscz_out
			filename=(*info).newfile
			ptr_free,info
;
			if (point_to_point) then begin
				dabsc=(abscz_out-absc0_out)/(abscdims-1)
				absc_out=absc0_out+findgen(abscdims)*dabsc
			endif else begin
				dabsc=(abscz_out-absc0_out)/abscdims
				absc_out=absc0_out+findgen(abscdims+1)*dabsc
			endelse
;
;			tlb=widget_base(title="Rebinning calculation",/col)
;				void=widget_label(tlb,value="",/align_center)
;				void=widget_label(tlb,value='File '+filename+".",/align_center)
;				void=widget_label(tlb,value="",/align_center)
;				void=widget_label(tlb,value="THE CALCULATION IS PROCEEDING",/align_center)
;				void=widget_label(tlb,value="",/align_center)
;				void=widget_label(tlb,value="PLEASE BE PATIENT",/align_center)
;				void=widget_label(tlb,value="",/align_center)
;			centertlb,tlb
;			widget_control,tlb,/realize
;
;			t0=systime(1)
;
			if (points) then begin
				if (topoints) then begin
					drebin,$
						absc_in,qty_in,err_in,absc_out,qty_out,err_out,err=err,emsg=emsg,$
						histogram=0,to_histogram=0,points=1,to_points=1
				endif else begin
;					drebin,$
;						absc_in,qty_in,err_in,absc_out,qty_out,err_out,err=err,emsg=emsg,$
;						histogram= ,to_histogram= ,points= ,to_points=
				endelse
			endif
;
			if (histogrammed) then drebin,$
				absc_in,qty_in,err_in,absc_out,qty_out,err_out,err=err,emsg=emsg,$
				histogram=1,to_histogram=1,points=0,to_points=0
;
			donotsave=(err ne 0)
			if (donotsave) then begin
				res=dialog_message(emsg,/error)
				break
			endif
;
;			t1=systime(1)
;
;			widget_control,tlb,/destroy
;
			ptr_free,(*(*davePtr).dataStrPtr).commonStr.histPtr
			if (binning_x) then begin
				(*(*davePtr).dataStrPtr).commonStr.histPtr=$
					ptr_new({qty:qty_out,err:err_out,x:absc_out,y:why})
;				(*(*davePtr).dataStrPtr).commonStr.xtype="HISTOGRAM"
			endif
			if (binning_y) then begin
				(*(*davePtr).dataStrPtr).commonStr.histPtr=$
					ptr_new({qty:transpose(qty_out),err:transpose(err_out),x:eks,y:absc_out})
;				(*(*davePtr).dataStrPtr).commonStr.ytype="HISTOGRAM"
			endif
		endfor
;
		if (not donotsave) then begin
			if (not lmgr(/demo)) then begin
				save,davePtr,filename=filename
				print,"File ",filename," has been saved."
			endif
			if (lmgr(/demo)) then print,"File ",filename," has NOT ACTUALLY been saved."
			free_all_ptrs,davePtr
		endif
	endif
endfor
;
dave_makeDavePtr,davePtr=davePtr
(*statePtr).davePtr=davePtr
;
end
