;+
; NAME:
;     GET_TIMING
; PURPOSE:
;     Determine time offsets [msec] from center of each observing cycle, for
;     each sample and channel within the sample.
; CATEGORY:
;     OVRO APC TIME
; CALLING SEQUENCE:
;     msoff = get_timing(pol,header,cfg,obseq)
; INPUTS:
;     pol      A byte array giving the polarization state
;                for each channel and each observing sequence entry.
;                The polarization is coded as 0 = RCP, 1 = LCP, 3 = LIN
;     header   The HEADER structure corresponding to the data.
;     cfg      The CONFIG structure corresponding to the data.
;     obseq    The OBSEQ structure corresponding to the data.
; OPTIONAL (KEYWORD) INPUT PARAMETERS:
; ROUTINES CALLED:
; OUTPUTS:
;     msoff    A long array of size [NCHAN,NFRQ,NPOL] giving the time offsets
;                [msec] for each sample and each channel within the sample,
;                relative to the center of a cycle.
; COMMENTS:
;     Timing is complicated for OVSA data, since we have only three correlators
;     and do time-multiplexing of baselines, frequencies and poln.  Thus, each datum
;     is obtained at slightly different times within a cycle.  To keep careful
;     track of timing, it is necessary to have the information provided by this
;     routine.  Note that if a particular frequency/baseline/poln combination is
;     measured twice in a cycle (the usual case) then the time indicated in MSOFF
;     is the center time between the two measurements.
; SIDE EFFECTS:
; RESTRICTIONS:
; MODIFICATION HISTORY:
;     Written 03-Apr-2001 by Dale Gary
;     14-Dec-2001  DG
;       Changed to reflect new 2 and 4 polarization flags, used for
;       2m TP channels to indicate that data should be saved in RCP and
;       LCP channels as well.
;-

function get_timing,pol,header,cfg,obseq

   nant = header.nant                     ; Number of antennas
   nchan = nant^2                         ; Number of data channels
   nbl  = (nchan-nant)/2                  ; Number of baselines
   nndw = 1 + header.ndbw + header.nfgw   ; Number of non-data words in sample
   if (keyword_set(ndon)) then offidx = where(*obseq.pnd eq 1) $
                          else offidx = where(*obseq.pnd eq 2)
   hp = (*obseq.pharm)(offidx)
   hpx = hp(sort(hp))                 ; Intermediate step--sort the harmonics
   hlist = hpx(uniq(hpx))             ; Form a list of uniq harmonics
   hlist = hlist(sort(hlist))         ; Sort in ascending order
   nfrq = n_elements(hlist)
   nfp = n_elements(offidx)
;   fp = hp*0.2
   poln = pol(nndw:*,offidx)
   nsamp = obseq.nx                   ; Number of samples in one cycle
   data    = fltarr(nchan,nfp)
   smldata = fltarr(nchan,nfrq,3)

   ; Get index of active antennas IANTS (e.g. [1,2] => [0,1], [4,5,6] => [2,3,4]
   antlist = [1,2,4,5,6,7,8]   ; Translation from antenna number to index
   aa = header.aatab(where(header.aatab ne 255))
   iants = intarr(nant)
   for i = 0, nant-1 do begin
      iants[i] = where(antlist eq aa[i])
   endfor

   ; Nant x nant matrix of time offsets for each channel, in msec,
   ; and corresponding channel offsets.  Also FG pointer array.
   msoff = (choff = intarr(nant,nant))
   for i = 0, nant-1 do begin
      for j = 0, nant-1 do begin
         msoff[i,j]  = cfg.msoff(iants[i],iants[j])
         choff[i,j]  = header.lchoff(iants[i],iants[j])
      endfor
   endfor

   ; Due to a bug in FASAR (CPC program) the channels for baseline 46 and 56
   ; were swapped.  This was fixed on day 303 of 1999, but prior data must
   ; have their channels swapped before analysis.  NB: All data before this
   ; date were taken in 5-element mode, so it is okay to give explicit indexes.
   if (header.tls.yrday lt 1999.303) then begin
      choff(4,2) = 28
      choff(4,3) = 26
      choff(2,4) = 28
      choff(3,4) = 26
   endif

   ; Form array representing the indexes of upper part of matrix
   upper = intarr(nbl)
   k = 0
   for i = 0, nant-2 do begin
      for j = i+1, nant-1 do begin
         upper[k] = i*nant+j
         k = k + 1
      endfor
   endfor
   choff(upper) = choff(upper)+1  ; Trick to put cos channel numbers into choff

   cycledur = nsamp*cfg.sampintms           ; Duration of a cycle, in msec
   tsample = indgen(nsamp)*cfg.sampintms    ; Time offsets [msec] corresponding
                                            ;   to each sample in one cycle
   ; Shift by 1/2 cycle so that TSAMPLE is relative to middle of the cycle
   tsample = tsample-cycledur/2
   tsample = tsample(offidx)                ; Reduce to only "good" samples

   ; Create a parallel flag array with zeroes
   smlflag = byte(data)*0                      ; Start with all zeroes

   ; More complicated POLN flags now--0 => RCP, 1=> LCP, >1=>LIN, but
   ; for small dishes, as a way to keep full time resolution of data,
   ; use 2=> put LIN also into RCP, 4=> put LIN also into LCP
   rcpflag = (lcpflag = (linflag = smlflag + 1))   ; Parallel arrays for each poln, all set to 1
   notr = where(poln ne 0 and poln ne 2)
   if (notr(0) ne -1) then rcpflag(notr) = 0   ; Set non-RCP to 0
   notl = where(poln ne 1 and poln ne 4)
   if (notl(0) ne -1) then lcpflag(notl) = 0   ; Set non-LCP to 0
   noti = where(poln le 1)   ; Small dish total power are flagged with -3 for I, so use abs(poln)
   if (noti(0) ne -1) then linflag(noti) = 0   ; Set non-LIN to 0

   ; Create a flag array parallel to smldata (reuse SMLFLAG variable)
   smlflag = bytarr(nchan,nfrq,3)
   ; Create a time array parallel to smldata
   smltime = lonarr(nchan,nfrq,3)

   toff = msoff(sort(choff))
   ; Loop over each "good" sample, doing the 25 channels all at once
   ; for each sample
   for i = 0, nfp-1 do begin

      ; Index into smldata for frequency
      fidx = where(hlist eq (*obseq.pharm)(offidx(i)))

      ; Accumulate sums into appropriate columns of smldata array
      smlflag(*,fidx,0) = smlflag(*,fidx,0) + rcpflag(*,i)
      smlflag(*,fidx,1) = smlflag(*,fidx,1) + lcpflag(*,i)
      smlflag(*,fidx,2) = smlflag(*,fidx,2) + linflag(*,i)

      ; Determine time offsets corresponding to each sample/channel
      smltime(*,fidx,0) = smltime(*,fidx,0) + (tsample(i)+toff)*rcpflag(*,i)
      smltime(*,fidx,1) = smltime(*,fidx,1) + (tsample(i)+toff)*lcpflag(*,i)
      smltime(*,fidx,2) = smltime(*,fidx,2) + (tsample(i)+toff)*linflag(*,i)

   endfor

   ; Do average of smldata, according to how many good values were
   ; summed in each array location
   smltime = smltime/(smlflag>1)   ; Contains average time for each element of SMLDATA

return,smltime
end