;+
; PROJECT:
;	SDAC
; NAME:
;	GET_DISCSP511
;
; PURPOSE:
;	Return linear channel number of the 511 line for a given time for
;	the 8 BATSE detectors.  Returns value of 0. for times and channel
;       if error.
;
; CATEGORY:
;	BATSE, SPEC, calibration

; CALLING SEQUENCE:
;	get_discsp511, intime, times, chans
;
; METHOD:
;	Reads one of two databases of BATSE SPEC calibration lines:
;
;	1.Reads compacted calibration line database. From calib_line files
;	created at MSFC with fitted channel number for 511 keV line sampled
;	several times per orbit for each detector.  Data has been filtered,
;	smoothed, and compacted before entering secondary database in perm_data.
;	If the time requested is beyond the end of the file, then database 2 is used.
;
;	2.Extracted from IBDBs submitted to GSFC BSAS Processed Data Base
;	Reads an ASCII file created by the routine mk_discsp_cal.  The file
;	contains a time and the linear channel numbers for 8 detectors on
;	each line.  mk_discsp_cal creates this file from a file created by 
;	Sandhia.  The file will have to be updated at regular intervals 
;	to contain the latest information.
;	Each line may not contain information for every detector. For each
;	detector, GET_DISCSP511 finds the closest time that is before the
;	requested time that contains non-zero information for that det.
;	If there is no calibration data within the gain interval, then
;	the database is searched for the closest calibration data within
;	a common gain interval
;
; INPUTS:
;	Intime - Time to retrieve 511 line channels for in standard 
;		"anytim" format seconds since 79/1/1.  
;		GET_DISCSP511 will find the closest 
;		time in the file that is after INTIME in method 2
;		while in method 1, the closest time before the requested
;		one is used.
;		If INTIME is before start of file, earliest data in file
;		will be returned.  If after last time of file, last data
;		will be returned.
;
; KEYWORDS:
;	BSASPDB - use database assembled from BSAS PDB, line numbers for
;		  triggered events corresponding to the gain record.
;	DET_ID  - Just return the calibration line for this SPEC DET ID.
;	LASTTIMESTOP - If set and time entered after the BSASPDB and compressed 511 line
;	databases then set error flag and return zeroes.
;		  
;
; OUTPUTS:
;	Outtimes - Times associated with the data returned
;	Outchans - Linear channel number of the 511 line for 8 detectors
;	
;
; SAMPLE CALL:  get_discsp511, '92/4/5,1200', times, chans
;
; MODIFICATION HISTORY:
;	Written:  Kim Tolbert  11/29/93
;	Mod:      ras, 18-jan-94 changed requirement to select values
;		                 after the input time.
;       ras, 13-aug-95, increased search range for calibration line data
;	ras, 30-nov-95, make calib_line database the default database
;	ras, 29-dec-95, allow optional search for 1 detector values
;	ras, 15-apr-96, make sure it uses bsaspdb when necessary
;       RAS, 7-Jul-1997, changed PERM_DATA to SSWDB_BATSE
;	ras, 14-sep-1997, made routine more robust past the normal database.
;	richard.schwartz@gsfc.nasa.gov, 30-mar-1998. added LASTTIMESTOP
;-
;  ---------------------------------------------------------------------

        
pro GET_DISCSP511, Intime, Outtimes, Outchans, BSASPDB=BSASPDB, DET_ID=DET_ID, $
	LASTTIMESTOP=LASTTIMESTOP

outtimes = dblarr(8)
outchans = fltarr(8)
lasttime = dblarr(8)
if not keyword_set(bsaspdb) then begin
	mjd = (anytim( intime, /mjd))(0)
	tjd = mjd.mjd-4d4 + mjd.time/8.64d7
	anypast  = 0
	for id=0,7 do begin
  	 if fcheck(det_id,id) eq id then begin
	  outchans(id) = rd_batse_511cal( tjd, id, tjd_found=tjd_found, $
	  past = past)
  	  outtimes(id) = tjd2ymd( tjd_found )
	if past then lasttime(id) = outtimes(id)
	  anypast      = anypast or past
	 endif
	endfor

	if not anypast then return else begin

	  message, /continue, 'Time is after compressed MSFC calib line database.'
	  message, /continue, 'Using BSASPDB database info.'	
	  get_discsp511, intime, outtimes, outchans, /bsaspdb, lasttimestop=lasttimestop, det_id=det_id	
	  
	endelse
endif

common d511_lines, d511_times, d511_chans


; Get the gain command values and time ranges 
;
; get_spec_gain uses anytim, so all formats safe
;
get_spec_gain, intime, gaintimes, gains  

; Read calibration file if haven't already.  
if n_elements(d511_times) eq 0 then begin
   ; LINES will contain lines that look like:
   ; 92/09/25, 2145:10.  402.375    0.000    0.000    0.000   67.842  423.804 ...  
   read_seqfile, lines, CONCAT_DIR(getenv('SSWDB_BATSE'),'discsp_cal.dat')

   lines = lines(where(lines ne ''))
   nlines = n_elements(lines)
   d511_times = utime(strmid(lines, 0, 18))
   d511_chans = fltarr(8, nlines)
   reads, strmid(lines, 19, 99), d511_chans
endif

; User's time may be any format.  Convert to seconds.
usertime = anytim (intime, /sec)
if keyword_set(lasttimestop) and  usertime(0) gt max(d511_times) then begin
	;Set the error condition, outtimes and outchans zeroed.
	error=1
	outtimes = 0
	outchans = 0
	return
	endif
		

; For each detector, find closest time to USERTIME that contains non-zero
; data.
for idet = 0,7 do begin
  if fcheck(det_id,idet) eq fcheck(det_id, idet) then begin
   widet = where( d511_chans(idet,*) gt 0. and $
                (d511_times gt gaintimes(0,idet) and $
                 d511_times lt gaintimes(1,idet)), nidet)
   if nidet ne 0 then begin
      itimes = d511_times(widet)
      ichans = d511_chans(*,widet)
      q = min (abs(usertime - itimes), min_index)
      outtimes(idet) = itimes(min_index)
      outchans(idet) = ichans(idet,min_index)
   endif else begin
   ;There were no 511 line measurements during this gain interval, return the intervals
   ;with this gain
   get_spec_gain, intime, gain_intrvls, gains(idet), det=idet
   ;extract all the 511 line numbers from all of the intervals
   itimes = [0]
   test_chan = [0]
   test_times = [0.d0]
   for j=0,n_elements(gain_intrvls(0,*))-1 do begin
	test_time = avg(gain_intrvls(*,j))
	if test_time lt lasttime(idet) then begin
		get_discsp511, avg(gain_intrvls(*,j)), testouttimes, testoutchans,  det_id=idet	
        	test_chan = [test_chan,testoutchans]
		test_times = [test_times, testouttimes]
	endif
	widet = where( d511_chans(idet,*) gt 0. and $
                (d511_times gt gain_intrvls(0,j) and $
                 d511_times lt gain_intrvls(1,j)), nidet)
	if nidet ge 1 then itimes=[itimes, widet]	
   endfor
   if n_elements(itimes) gt 1 then begin
	itimes = itimes(1:*)
	q = min( abs(usertime - d511_times(itimes)), min_index)
	outtimes(idet) = d511_times(itimes(min_index))
	outchans(idet) = d511_chans(idet, itimes(min_index))
   endif else begin
	wtest = where( test_chan ne 0, ntest)
	if ntest <1 then begin
		outtimes(idet) = test_times(wtest(0))
		outchans(idet) = test_chan(wtest(0))
	endif
	endelse
   endelse   
  endif
endfor


return&end
