;+
; PROJECT:
;	SDAC
; NAME: 
;	FS_READ_DD
; CATEGORY:
;	BATSE
;
; PURPOSE:
;
; 	FS_READ_DD reads records from the input file in blocks of 1000 records at 
; 	a time and saves fluxes, times, and position and pointing data.
;
;       read_dd and fs_read_dd are similar.  The main difference is that
;       fs_read_dd saves data into pre-defined arrays in common fs_saveaccum,
;       while read_dd constructs the arrays and returns them in output args.
;
;       Select input file either by calling fs_open before calling fs_read_dd
;       and passing the dd_open structure that fs_open sets up to fs_read_dd
;       or
;       pass a filename, or dd_type and flare or startt keywords to fs_read_dd.
;               e.g.:
;		fs_open,flare=12,dd_open=dd_open
;		fs_read_dd,dd_open=dd_open
;			or
;		fs_read_dd,flare=12	(type defaults to fdb)
;
;	The data is saved in pre-defined arrays (set up by 
; 	setup_arrays) in common fs_saveaccum so that we will use the same 
; 	space over and over instead of creating new arrays every time we read 
; 	in a new set of data.  
;
; 	Depending on the type of data file opened by fs_open, fs_read_dd saves
; 	discla (fdb or bdb), cont, or discsp data at the highest time resolution
; 	available.
;	
; 	maxindex, maxcindex, maxspindex, maxposindex (in common fs_saveaccum)
; 	indicate the highest element number filled in those arrays.  
;
; 	If the times requested are not in the file, maxindex is returned as 0.
;
; 	If the time extends beyond the end of the input file (and the input is
; 	bdb), the next day's bdb file is read up to the end time requested. 
;
; 	Output arrays are filled by computing the index into the array from the
; 	time of the data.  Arrays are first initialized to an appropriate value 
; 	indicating a gap, and this way, gaps will be left as gaps.  In FSPLOT,
; 	the time array will be filled in later in the gap intervals to contain 
; 	continuously increasing times.
;
; CALLING SEQUENCE:
;	fs_read_dd, [file=infile, flare=flare, dd_open=dd_open, $
;	  dd_type=dd_type, startt=startt, endt=endt, $
;	  verbose=verbose, error=error]
;
; OPTIONAL KEYWORD INPUTS:
;       file -  string name of file. If no disk or directory is specified,
;               BATSE_DATA is the default.
;       flare - BATSE flare number.  FS_OPEN will find file containing FLARE.
; 	dd_open - structure set by fs_open containing information about input 
;           file (see dd_init for contents of structure)
;       dd_type - Type of data as string or number:
;               'BDB', 'FDB', CONT', or 'DISCSP'  or
;               0/1/2/3 = discla bdb, discla fdb, cont, discsp
;               Unless the FILE or DD_OPEN keywords are passed, will find this
;               type of file for the flare or time requested.  Default is FDB.
; 	startt - start time to read in r*8 seconds relative to 79/1/1,0 or ASCII
;          string in format yy/mm/dd,hhmm:ss.xxx.  If dd_open, flare, and
;	   file keywords are NOT specified, then finds file containing
;	   this time.
; 	endt - end time of interval to read.  See startt description.
;	verbose - 0/1 means don't/do print start/end times of accumulation

; OPTIONAL KEYWORD OUTPUTS:
; 	error - 0/1 indicates no error/error reading file
;
; SAMPLE CALL:  
;	fs_read_dd, dd_open, err=err
;	fs_read_dd, dd_open, startt='93/10/18,1230',endt='93/10/18,1235',$
;	  error=error         
;	fs_read_dd, dd_open, err=err
; 
; MODIFICATION HISTORY:
;	Written by Kim Tolbert  10/93
;	ras, 26-mar-1996, allow variable buffer size in common, cleaned up max*index
;	Version 3, richard.schwartz@gsfc.nasa.gov, 4-sep-1997,  check for pad_byte
;-
pro fs_read_dd, file=infile, flare=flare, dd_open=dd_open, dd_type=dd_type,$
   startt=startt, endt=endt, verbose=verbose, error=error
;
; common containing pre-defined arrays we will save data in
@fs_saveaccum

error = 0

; initialize variables if not passed in calling arguments
checkvar, startt, 0.d0
checkvar, endt, 0.d0
checkvar, verbose, 1


startt = anytim(startt,/sec)
endt = anytim(endt,/sec)

; if user didn't set end time, set to a big end time
if endt eq 0.d0 then endt = sys2ut()

; if dd_open isn't a structure call fs_open to get new file.
if (size(dd_open))(2) ne 8 then $
   fs_open, file=infile, flare=flare, dd_open=dd_open, $
   dd_type=dd_type, time=startt, error=error
if error then goto,getout


; if data storage arrays in common fs_saveaccum are too short, then
; extend them by some bulk amount for the datatype in question.
setup_batse, dd_open, endt

; initialize output arrays to zero if they have values already stored 
; (maxindex gt 0), and this is the type of data we're getting.

if (maxindex gt 0) and (dd_open.type le 1) then begin
   discla (*,*,0:maxindex) = 0.
   seconds(0:maxindex) = 0.d0
   maxindex = 0
endif
if (maxcindex gt 0) and (dd_open.type eq 2) then begin
   cont (*,*,0:maxcindex) = 0.
   cseconds(0:maxcindex) = 0.d0
   maxcindex = 0
endif
if (maxspindex gt 0) and (dd_open.type eq 3) then begin
   discsp (*,*,0:maxspindex) = 0.
   spseconds(0:maxspindex) = 0.d0
   maxspindex = 0
endif

if (maxposindex gt 0) then begin
   pseconds (0:maxposindex) = 0.d0
   xpos (0:maxposindex) = 0
   ypos (0:maxposindex) = 0
   zpos (0:maxposindex) = 0
   zra (0:maxposindex) = 0
   zdec (0:maxposindex) = 0
   xra (0:maxposindex) = 0
   xdec (0:maxposindex) = 0
   maxposindex = 0
endif
      
; locate first record in file to read (record containing startt)
find_packet, startt, dd_open, first_rec, error = error
if error then goto,getout

; maximum number of points allowed (determined by size of arrays we set
; up in common fs_savaccum) depends on type of data we're reading
case 1 of 
dd_open.type le 1: total_max = n_elements(seconds)
dd_open.type eq 2: total_max = n_elements(cseconds)
dd_open.type eq 3: total_max = n_elements(spseconds)
else: begin
   print, 'Invalid data type.'
   goto, getout
   end
endcase
total_maxpack = n_elements(pseconds)

;
; position file to record containing requested start time
fstat = fstat(dd_open.lun)
pad_byte = getenv('pad_byte_'+dd_open.filename)
if pad_byte eq '' then pad_byte = 0 else pad_byte=fix(pad_byte)
point_lun, dd_open.lun, first_rec * (size_struct(dd_open.data)+pad_byte)
;point_lun, dd_open.lun, first_rec * size_struct( dd_open.data ) 

max_sofar = 0     ; number of data points accumulated so far
latest_time = 0.  ; latest time accumulated so far
rec_left = dd_open.numrec - first_rec + 1  ; numbers of records left in file


; read loop  -  read 1000 records at a time. 
read:
while (latest_time + 2.048 lt endt) and (rec_left ge 1) and $
   (max_sofar lt total_max) do begin

   nreps = (1000 < rec_left)     ; number of records to read
   ;print,'nreps,rec_left,max_sofar', nreps, rec_left, max_sofar
   if n_elements(data) eq 0 then data = bytarr(size_struct( dd_open.data )+pad_byte, nreps) $
   else if n_elements(data(0,*)) eq nreps then data(0) = 0b*data else $
   data = bytarr(size_struct( dd_open.data )+pad_byte, nreps)
   readu, dd_open.lun, data
   
   rec_left = rec_left - nreps
   rec_time = sc_seconds_ed(conv_vax_unix(fix(data(0:5,0:nreps-1),0,3,nreps)))
   ;print,'rec_time = ',atime(rec_time(0))

   wuse = where (rec_time lt endt, nreps)
   ;print,'nreps after checking for end time = ', nreps
   if nreps eq 0 then goto, done
   
   if max_sofar eq 0 then first_sec = rec_time(wuse(0))
   indpack = long ((rec_time(wuse) - first_sec)/2.048 + 0.5)
   q = where (indpack le total_maxpack-1, nreps)
   ;print,'nreps after checking for total_maxpack = ', nreps
   if nreps eq 0 then goto, reachedmax

   indpack = indpack(q)
   wuse = wuse(q)
   latest_time = rec_time(max(wuse)) 
   indices = indpack * 2
   case 1 of 

   (dd_open.type le 1): begin
      discla(*,*,indices) =1.*(65535L and conv_vax_unix(fix (data(10:105,wuse),0,6,8,nreps)))
      discla(*,*,indices+1)=1.*(65535L and conv_vax_unix(fix (data(106:201,wuse),0,6,8,nreps)))
      
      seconds(indices) = rec_time(wuse) + .512
      seconds(indices+1) = rec_time(wuse) + 1.536
      max_sofar = indices(n_elements(indices)-1)+2
      end

   (dd_open.type eq 2): begin
      cont(*,*,indpack) = 1.*(65535L and conv_vax_unix( fix (data(10:265,wuse),0,16,8,nreps)))
      cseconds(indpack) = rec_time(wuse) + 1.024d0
      max_sofar = indpack(n_elements(indpack)-1)+1
      end

   (dd_open.type eq 3): begin
      discsp(*,*,indpack) = 1.*(65535L and conv_vax_unix(fix (data(10:73,wuse),0,4,8,nreps)))
      spseconds(indpack) = rec_time(wuse) + 1.024d0
      max_sofar = indpack(n_elements(indpack)-1)+1
      end
;
;	If running out of room, increase the array size!
;
	
   else: begin
      print, 'Invalid data type.'
      goto, getout
      end
   endcase

   pseconds(indpack) = rec_time(wuse) + 1.024
   s = size (dd_open.data.(2))  ; compute where position data starts
   j1 = 2.* s(n_elements(s)-1) + 10

   xpos(indpack) = conv_vax_unix(fix(data(j1:j1+1,wuse), 0 , nreps))
   ypos(indpack) = conv_vax_unix(fix(data(j1+2:j1+3,wuse), 0 , nreps))
   zpos(indpack) = conv_vax_unix(fix(data(j1+4:j1+5,wuse), 0 , nreps))
   if dd_open.type le 1 then j1 = j1 + 4
   zra(indpack) = conv_vax_unix(fix(data(j1+6:j1+7,wuse), 0 , nreps))
   zdec(indpack) = conv_vax_unix(fix(data(j1+8:j1+9,wuse), 0 , nreps))
   xra(indpack) = conv_vax_unix(fix(data(j1+10:j1+11,wuse), 0 , nreps))
   xdec(indpack) = conv_vax_unix(fix(data(j1+12:j1+13,wuse), 0 , nreps))
   
   maxposindex = indpack(n_elements(indpack)-1)
endwhile   ; end of read loop



if (latest_time+2.048 lt endt) then begin
   if max_sofar eq total_max then begin
      reachedmax:
      print, 'Stopping accumulation because reached ',$
      'maximum allowed points (', total_max, ')'
      goto, done
   endif else begin

   ; if we're reading a bdb file and we didn't reach the end time, 
   ; open the next day's file and continue reading.
      if dd_open.type eq 0 then begin
         nextbdb, startt=startt, dd_open, error = errnext
         ; if didn't get an error, set first_rec and nrec so that we'll start
         ; reading at beginning of new file (after header record)
         if not errnext then begin
            first_rec = 1 + dd_open.num_audit_rec
            rec_left = dd_open.numrec - first_rec + 1
            fstat = fstat(dd_open.lun)
            point_lun, dd_open.lun, first_rec * (size_struct( dd_open.data )+pad_byte) 
            goto,read
         endif
      endif
   endelse
endif

done:
case 1 of 
dd_open.type le 1: begin
   maxindex = max_sofar-1
   if verbose then begin
      print, 'DISCLA accumulation: Start time = ',atime(seconds(0),/hxr)
      print,'                     End time   = ',atime(seconds(maxindex),/hxr)
      print,'                     Total points = ', maxindex+1
   endif
   end
dd_open.type eq 2: begin
   maxcindex = max_sofar-1
   if verbose then begin
      print, 'CONT accumulation: Start time = ',atime(cseconds(0),/hxr)
      print,'                   End time   = ',atime( cseconds(maxcindex),/hxr)
      print,'                   Total points = ', maxcindex + 1
   endif
   end
dd_open.type eq 3: begin
   maxspindex = max_sofar-1
   if verbose then begin
      print, 'DISCSP accumulation: Start time = ',atime(spseconds(0),/hxr)
      print,'                     End time   = ', $
            atime(spseconds(maxspindex),/hxr)
      print,'                     Total points = ', maxspindex + 1
   endif
   end
endcase

goto,getout

getout:
end
