;+
;*****************************************************************************
; NAME: 
;	TEST_CAL
; PURPOSE:
;     This subroutine calculates the energies corresponding to the channel
; boundaries for the BATSE Spectral Detectors.  The calibration is assumed
; to consist of two parts:  a calculation of the light output from the NaI
; crystal from the channel number, and a calculation of the energy loss in
; the crystal that produces that light.  In this routine, there is no
; SLED or MQT correction.  This routine is used to recalibate after a primary
; calibration has set the values in common.
;
;  There are calibration fiducials for the lld's, those obtained by schwartz
;  are the defaults.  To change to the Preece fiducials, set which_fiducials
;  to 0 in  read_coef_com, spec_lld_old, which_fiducials
;
;   Input:
;      ndet---the detector number
;      width64---the variable width of the 64th channel
;      spec_lld---LLD settings for all 8 detectors
;      nlines---the number of lines used for calibration
;      chan---vector of location of calibration lines in uncompressed channels
;      en---vector of location of calibration lines in energy
;
; Keyword Inputs:
;	MAXCHAN - test_cal only up to this channel to save time.
;      /discsp - edges are only those needed for discsp edges, lld/2, lld, max(evec)
;      /use_calibration if set then the input arguments
;	are set from the common block cal_sher_com and the outputs are 
;	calculated
;      /noevec - don't compute the evec for output, just go as far as xvec
;
;   Output:
;      evec---the vector of energies, 257 values normally, 3 for /discsp
;      unevec - energies w/o sled correction
;      xvec---the vector of effective uncompressed channel boundaries
;      pre_olight - vector of light outputs/channel before sled amp correction
;      olight     - vector of light outputs/channel after sled
;
;   Common blocks:
;     common spline_com, break,c0,c1,c2,c3
;      common sled_com, sb,sc,sd,scut
;      common fiducial_com,af,bf,cf,xf
;      common read_coef_com, spec_lld_old, which_fiducials
;	;common block for passing 511 line position out to the top level
;	common cal_sher_com, pass511, w64_used, spec_lld_used
;
; Category: CGRO/BATSE
;
; Calls:
;	READ_COEF, SLED, EDGE_PRODUCTS, FCRYSTAL, DELTA_CONTROL, FCHECK
;	GAIN_COR, CHANNELS, LLD_CHAN
; History:
;   Version 1, ras, 11-apr-1997
;-

;
pro test_cal, ndet, width64, spec_lld, nlines, chan, en, evec, xvec, $
	pre_olight=pre_olight, olight=olight, unevec=unevec, discsp=discsp,$
	use_calibration=use_calibration, noevec=noevec, $
	maxchan=maxchan, error=error, date=date


error = 1
;common block for passing 511 line position, width of channel 64, and 
;the spec lower-level discriminator settings out to the top level.
;This facilitates adjusting the calibration in the top-level routines.

common cal_sher_com, ndet_used, chan_used, en_used, w64_used, spec_lld_used
                                        

common sled_com, sb,sc,sd,scut
common fiducial_com,af,bf,cf,xf
common read_coef_com, spec_lld_old

if keyword_set(use_calibration) or n_elements(ndet) eq 0 or fcheck(chan(0),0) eq 0 then begin
	if n_elements(ndet_used) eq 0 then return
	ndet = ndet_used
	chan = chan_used
	nlines = n_elements(chan)
	en   = en_used
	width64 = w64_used
	spec_lld=spec_lld_used
endif
;                                                                               
; Read in coefficients if the first time through

checkvar,spec_lld_old, intarr(8)
new = where( spec_lld eq spec_lld_old, ncount)

if total(abs(spec_lld-spec_lld_old)) ne 0 then begin
  read_coef,spec_lld
  spec_lld_old=spec_lld
endif
;
; Set up an array of channel boundaries
channel,width64,xvec

if keyword_set(noevec) then return

;Make the routine more tolerant of non-vector arguments for the cal line
chan = fltarr(nlines) + chan
en   = fltarr(nlines) + en

;
; Get gain corrected coefficients

gain_cor,ndet,nlines,chan,en,a,b,c,x_0

;
; Loop over all channel boundaries
; First calculate the light from the NaI crystal

olight = a+b*xvec
iless = where(xvec lt x_0, ncount)
;if ncount ge 1 then $
;  olight(iless)=olight(iless)  + c*(xvec(iless)-x_0)^2

pre_olight = olight ;olight prior to sled correction
;
; Make correction for SLED
;sled,ndet,b,xvec,olight

; Finally, calculate the energy
evec = olight(0:fcheck(maxchan,256))*0.0
unevec = evec
case keyword_set(discsp) of
	0: begin
	if fcheck(maxchan,256) gt 100 then begin
	   for i=0,n_elements(evec)-1 do begin
	   	evec(i) = fcrystal(olight(i))
	   	unevec(i) = fcrystal(pre_olight(i))
	   endfor
	endif else begin    ;Use fast interpolation scheme!!!
	  evec = fcrystal1(olight)
	  unevec = fcrystal1(pre_olight)
	endelse
	end
	1: begin ;3 values for discsp
	   fratio = (fast_ratio(spec_lld))(ndet)
	   nval   = [lld_chan( date, ndet, /skelton), n_elements(evec)-1]
	;Something happened to SPEC1 during reboost on 3-Oct-1993 that changed
	;the slld->lld_chan conversion
           if ndet eq 1 then if anytim(fcheck(date,0.0),/sec) gt anytim('3-oct-1993',/sec) then $
		nval(0)=nval(0)-4
	   nval = [nval(0)/2,nval]  ; > 0.01
	   evec = evec(nval)
	   evec(2) = fcrystal(pre_olight(nval(2)))
           olight1 = a + b*nval(1)
	   if nval(1) lt x_0 then olight1 = olight1 + c*(nval(1)-x_0)^2
           if olight1 le 0 then printx,'Danger in DISCSP calibration!!! Test_cal.pro'
	   pre_olight1=olight1
	   sled, ndet, b, nval(1), olight1
	   unevec(1) = fcrystal(pre_olight1)
           unevec(0) = fcrystal(pre_olight1/fratio)
	   evec(1) = fcrystal(olight1)
           evec(0) = fcrystal(olight1/fratio)
	;print, 'olight1, evec(0:2)', olight1, evec(0:2)

	end
endcase

;if delta_control is set to 0, then the pha energy widths are in energy loss units
;which is the bdas analysis standard, the spex default is to use the light widths

if not delta_control() then begin
  olight = evec
  if fcheck(ndet,1) eq 0 and not keyword_set(discsp) then $
    printx,'Channel widths set to Energy loss units, BDAS standard.'
endif else if fcheck(ndet,1) eq 0 and not keyword_set(discsp) then $
    printx,'Channel widths set to PHA widths, SPEX SHERB standard.'

;save the current arguments in common to be able to report them
ndet_used = ndet
en_used = en
chan_used = chan
w64_used = width64
spec_lld_used = spec_lld
error=0
return

end
