;+
; NAME:
;	mk_bsa_interv
; PURPOSE:
;      define accumulation time intervals for BSC data
; CALLING SEQUENCE:
;	mk_bsa_interv,bda_index,bsa_index,trange=trange
; INPUTS:
;	BDA_INDEX    - an array of BDA index (or roadmap) structures
;       BSA_INDEX    - an array of initial BSC index structures with fields
;                      set according to user specifications.
;
; OUTPUTS:          
;       BSA_INDEX    - modified with start/stop intervals for accumulation
;
; KEYWORDS:
;       ERR          - 1 if BSA_INTERV failed else 0
;       TRANGE       - [TSTART,TEND] time range to confine processing,
;                      where TSTART.TIME=MSOD, TSTART.DAY=DS79, etc.
;                      Default is to process all data times in BDA_INDEX.
; PROCEDURE:
;                      Uses TOTAL_CNTS in index to determine start and end
;                      times for integration in each channel. Counts in each
;                      channel will be integrated until summed accumulation
;                      time is greater than or equal to specified  ACCUM.
;                      If THRESH is set, then counts will be integrated until
;                      summed counts are greater than or equal to specified THRESH.
;                      If THRESH and ACCUM are both set, then accumulation is
;                      increased until THRESH and ACCUM are reached.
;                      (N.B. different channels can end up with different 
;                      total numbers of accumulated samples).
; HISTORY:
;                      - Written Apr'93 by D. Zarro (Applied Research Corp).
;                      - removed concatanation to alleviate speed/memory probs.
;                      - 12-Apr-94, Zarro, improved error checking
;                      - 19-May-94, Zarro, added check for nonexistent channels
;                      - 20-Jun-94, fixed potential overflow bug in total_cnts
;                      - 26-Jan-95, added facility to flag BLOCKID change
;                      - Apr'95   , switched off SAA/NIGHT check
;-

pro mk_bsa_interv,bda_index,bsa_index,trange=trange,verbose=verbose,err=err

on_error,1

if keyword_set(verbose) then verbose=1 else verbose=0
err=1
if n_elements(bda_index) eq 0 or (not bsc_check(bsa_index)) then begin
 message,'usage --> MK_BSA_INTERV,BDA_INDEX,BSA_INDEX,TRANGE=TRANGE'
endif

;
;-- Check if INDEX or ROADMAP was entered
;

tags=strupcase(tag_names(bda_index))
yes_index=(tags(1) EQ 'BCS')
if yes_index then begin
 temp=bda_index.bcs
 nsamppchan=temp.nsamppchan
endif else begin
 ndset=n_elements(bda_index)
 temp=bda_index
 nsamppchan=intarr(4,ndset)+1
endelse

;
;-- Prepare times
;

dmsec=86400000L
time=gt_time(bda_index) & day=gt_day(bda_index)
btime=time+dmsec*(day-day(0))
ndset=n_elements(temp)
istart=0 & iend=ndset-1
if keyword_set(trange) then begin
 print,'- START TIME FOR PROCESSING DATA: '+FMT_TIM(TRANGE(0),/MSEC)
 print,'- END TIME FOR PROCESSING DATA: '+FMT_TIM(TRANGE(1),/MSEC)
 diff=(trange.day)(1)-(trange.day)(0)
 tstart=(trange.time)(0)
 tend=(trange.time)(1)+dmsec*diff
 cfind=where( (btime ge tstart) and (btime le tend), count)
 if count eq 0 then begin
  message,'NO DATA DURING SPECIFIED TIME RANGE',/CONTIN
  return
 endif
 istart=cfind(0) & iend=cfind(count-1)
endif
 
;-- Save arrays to pass onto BSC fields 

dgi=temp.dgi
dp_flags=temp.dp_flags
bcs_status=temp.bcs_status
nbins_chan=nsamppchan

;
;-- Get all the lightcurve arrays (these are not deadtime corrected)
;

y=temp.total_cnts*10.

;
;-- Flag SAA/Night and block/mode change records
;-- temporarily switched off
;

bits=2^indgen(8)
saa_or_night=bytarr(ndset) 
message,'--- SAA/Night checks switched off ---',/cont

;for i=0,ndset-1 do begin
; on_bits=bcs_status(i) and bits
; saa_or_night(i)=(on_bits(4) ne 0) or (on_bits(5) ne 0) 
;endfor

invalid=saa_or_night

;-- Message settings

chans=bsa_index.bsc.chan & nchans=n_elements(chans)
thresh=bsa_index.bsc.cnt_thresh
accum=bsa_index.bsc.actim/1000.
deadtime=bsa_index(0).bsc.deadtime_ans
fluxcal=bsa_index(0).bsc.physunits_ans
wavecal=bsa_index(0).bsc.wavedisp_ans
xcorr=bsa_index(0).bsc.curve_ans


if !quiet eq 0 then begin
 print,'- REQUESTED CHANNEL(S): ' & print,chans
 print,'- REQUESTED ACCUMULATION TIMES (S): ' & print,accum
endif

no_thresh=where(thresh eq 0,count)
if count ne nchans then message,'COUNT LEVEL THRESHOLDS REQUESTED',/info
if deadtime gt 0 then message,'DEADTIME CORRECTION REQUESTED',/info
if xcorr then message,'CRYSTAL CURVATURE CORRECTION REQUESTED',/info
if fluxcal then message,'FLUX CALIBRATION REQUESTED',/info
if wavecal then message,'WAVELENGTH CALIBRATION REQUESTED',/info

;-- Start accumulating total counts (do this by channel) and
;   exit each accumulation loop when desired threshold and/or accumulation time
;   is reached, or SAA/Night or blockid/modeid change is reached. 
;   Make end time of accumulation interval equal to start of last record + dgi

message,'creating BSA Index structures...',/continue
i_bsa_index=bsa_index(0)
nmax=long(nchans)*long(ndset)
bsc_index=replicate(i_bsa_index,nmax)
ncount=-1L

for i=0,nchans-1 do begin
 ysum=0. & yaccum=0. & nspec=0L & tstart=0L & dstart=0 & chan=chans(i)
 summed=0 & mod_change=0 & blk_change=0 & saa_night=0
 cnt_thresh=thresh(i)
 
;-- CHANNEL check

 nsamp=nsamppchan(chan-1,*)
 chck=where(nsamp gt 0,count)
 if count eq 0 then begin
  message,'NO DATA IN CHANNEL '+string(chan,'(i3)'),/contin
 endif else begin
  for k=istart,iend do begin
   
   if invalid(k) then begin    
    if (tstart gt 0) or (k eq iend) then summed=1
   endif else begin

;-- DGI check

    if (dgi(k) gt 0) and (nsamp(k) gt 0) then begin      ;-- SKIP NULL MODES

     if tstart eq 0 then begin      
      tstart=time(k) & dstart=day(k) & dp_start=dp_flags(k)
      bcs_start=bcs_status(k) & dgi_start=dgi(k) 
      mode_start=temp(k).modeid
      block_start=temp(k).blockid 
     endif

     ysum=ysum+y(chan-1,k) & yaccum=yaccum+dgi(k)*.125 
     tend=time(k)+dgi(k)*125l
     nspec=nspec+1 
     if (k lt iend) then begin

;-- MODE check

      if temp(k+1).modeid ne mode_start then begin
       mod_change=1
       if keyword_set(verbose) then begin
        message,'mode change at '+fmt_tim(bda_index(k+1)),/contin
        message,string(mode_start,'(i3)')+' ---> '+string(temp(k+1).modeid,'(i3)'),/noname,/contin
       endif
      endif 

;-- BLOCK check

      if temp(k+1).blockid ne block_start then begin
       blk_change=1
       if keyword_set(verbose) then begin
        message,'block change at '+fmt_tim(bda_index(k+1)),/contin
        message,string(block_start,'(i2)')+' ---> '+string(temp(k+1).blockid,'(i2)'),/noname,/contin
       endif
      endif

;-- SAA/NIGHT check

      if saa_or_night(k+1) eq 1 then begin
       saa_night=1
       if keyword_set(verbose) then begin
        message,'SAA/NIGHT change at '+fmt_tim(bda_index(k+1)),/contin
       endif
      endif

     endif

;-- THRESH check

     if thresh(i) eq 0. then begin
      if (yaccum ge accum(i)) or (k eq iend) or $
         mod_change or blk_change or saa_night then summed=1
     endif else begin
      reached=0
      if (yaccum ge accum(i)) then reached=1
      if (ysum lt thresh(i)) and (yaccum ge accum(i)) then reached=0
      if (ysum ge thresh(i)) then reached=1

      if (k eq iend) or reached or $
         mod_change or blk_change or saa_night then summed=1
     endelse

    endif 

;else if keyword_set(verbose) then $
;              MESSAGE,'null mode at '+fmt_tim(bda_index(k)),/contin

   endelse

;-- Update BSA index with start and accumulation times.
;   Throw in duration, total counts, and total spectra during interval.
;

   if summed then begin
    if invalid(k) and keyword_set(verbose) then begin
     message,'accumulation cut short at '+fmt_tim(bda_index(k))+' because of:',/contin
     if blk_change then message,'BCS block ID change',/noname,/contin
     if mod_change then message,'BCS mode ID change',/noname,/contin
     if saa_night then message,'SAA/Night transition',/noname,/contin
    endif

    if (tstart gt 0) then begin
     i_bsa_index.gen.time=long(tstart)           ;-- SAVE START TIME OF INTERVAL
     i_bsa_index.gen.day=fix(dstart)             ;-- SAVE START DAY OF INTERVAL
     i_bsa_index.bsc.blockid=block_start
     i_bsa_index.bsc.modeid=mode_start
     i_bsa_index.bsc.dp_flags=dp_start           ;-- SAVE INITIAL dp_flag
     i_bsa_index.bsc.bcs_status=bcs_start        ;-- SAVE INITIAL bcs_status
     i_bsa_index.bsc.chan=byte(chan)
     i_bsa_index.bsc.actim=long(yaccum*1000l)
     i_bsa_index.bsc.dgi=dgi_start               ;-- SAVE INITIAL dgi
     i_bsa_index.bsc.interval=long(tend-tstart)
     i_bsa_index.bsc.nspec=fix(nspec)
     i_bsa_index.bsc.total_cnts=ysum
     i_bsa_index.bsc.nbin=nbins_chan(chan-1,k)
     i_bsa_index.bsc.cnt_thresh=cnt_thresh

     ncount=ncount+1
     bsc_index(ncount)=i_bsa_index 
    endif

;-- Initialize and go back for more

    ysum=0. & yaccum=0. & nspec=0L & summed=0 & tstart=0L & mod_change=0
    blk_change=0 & saa_night=0
   endif

  endfor
 endelse
 if i eq 0 then verbose_sav=verbose else verbose=0
endfor
verbose=verbose_sav

;
;-- what happened?
;


if ncount EQ -1 then begin
 message,'No valid BDA data for requested channel(s)',/contin
 return
endif else bsa_index=bsc_index(0:NCOUNT)

err=0

return & end



