; $Id: dave_rebin.pro,v 1.7 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_rebin,x_in,y_in,dy_in,x_out,y_out,dy_out,silent=silent,nanch=nanch
;************************************************************************************************
; This procedure rebins 1-dimensional data. The data to be rebinned are described by the
; arrays x_in, which is dimensioned n_in+1, and by y_in and dy_in, both of which are dimensioned
; [n_in,ng], where n_in is the number of channels and ng is the number of groups, i.e. sets of
; data. The grid onto which the data are to be rebinned is defined by the array x_out and the
; results are placed in y_out and dy_out; x_out is dimensioned n_out+1 and y_out and dy_out are
; dimensioned [n_out,ng] where n_out is the number of output channels. It is up to the user of
; this procedure to ensure that the input arrays are properly dimensioned.
; The keyword silent, if true, suppresses a warning message that is issued if the output
; channels span a range that is outside the range of the input channels. If this occurs,
; regardless of the keyword setting, output channels wholly or partially outside are assigned
; the value "NaN". The keyword nanch contains the 2-element array [nlch,nrch] where nlch (nrch)
; is the number of left (right) channels assigned the value "NaN".
;
compile_opt strictarr
;
;
; Generate number, left limit, right limit and width in x of input channels.
n_in=n_elements(x_in)-1
l_in=x_in[0:n_in-1]
r_in=x_in[1:n_in]
w_in=r_in-l_in
;
; Generate number, left limit, right limit and width in x of output channels.
n_out=n_elements(x_out)-1
l_out=x_out[0:n_out-1]
r_out=x_out[1:n_out]
w_out=r_out-l_out
;
; Test to see whether any output channel lies outside the input range.
lch=where(l_out lt l_in[0],nlch)
rch=where(r_out gt r_in[n_in-1],nrch)
if (not keyword_set(silent)) then silent=0
;
; If so, unless the keyword "silent" is set, issue a warning.
if (nlch gt 0 or nrch gt 0 and not silent) then begin
	result=dialog_message(['The first'+strcompress(nlch)+' rebin channels',$
		'and the final'+strcompress(nrch)+' rebin channels',$
		'are outside the input range of channels.',$
		'Their contents will be set to "NaN".'],title="Rebin warning message.")
endif
;
; Determine the number of sets of input data.
ng=n_elements(y_in)/n_in
;
; Create unit vectors for later use.
uvec_nout=intarr(n_out)+1
uvec_nin=intarr(n_in)+1
uvec_ng=intarr(ng)+1
;
;	Calculate integrated counts and associated errors for input channels.
t_in=y_in*(w_in#uvec_ng)
dt_in=dy_in*(w_in#uvec_ng)
;
;	The array element (*f_limPtr)[i,j] gives the fraction of input channel j
;		that contributes to output channel i.
r_limPtr=ptr_new((r_out#uvec_nin) < (uvec_nout#r_in),/no_copy)
l_limPtr=ptr_new((l_out#uvec_nin) > (uvec_nout#l_in),/no_copy)
d_limPtr=ptr_new((*r_limPtr-*l_limPtr) > 0,/no_copy)
f_limPtr=ptr_new(*d_limPtr/(uvec_nout#w_in),/no_copy)
;
;	Do the actual rebinning.
; Integrated counts and associated errors are computed for all output channels.
t_out=(*f_limPtr)#t_in
dt_out=sqrt((*f_limPtr)#dt_in^2)
;
;	Hence count rate and associated error for output channels.
y_out=t_out/(w_out#uvec_ng)
dy_out=dt_out/(w_out#uvec_ng)
;
; Free some pointers.
ptr_free,r_limPtr
ptr_free,l_limPtr
ptr_free,d_limPtr
ptr_free,f_limPtr
;
; If any output channels lie outside the range of the input channels, they are
; assigned the value "NaN".
if (nlch gt 0) then begin
	y_out[lch,*]=!VALUES.F_NAN
	dy_out[lch,*]=!VALUES.F_NAN
endif
;
if (nrch gt 0) then begin
	y_out[rch,*]=!VALUES.F_NAN
	dy_out[rch,*]=!VALUES.F_NAN
endif
;
nanch=[nlch,nrch]
;
end

