;
pro calibrate, ndet, width64, spec_lld, nlines, chan, en, evec, xvec, $
pre_olight=pre_olight, olight=olight, unevec=unevec, discsp=discsp,$
report_calibration=report_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(report_calibration) 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, spec_lld=spec_lld, /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!!! Calibrate.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


end