program uv_timebase
  use gkernel_interfaces
!
! Re-order a UV table according to a Time-Baseline
! Sequence, in order to create an ensemble of
! values to be plotted per baseline as function of time
! Values = (Real, Imag) == (Amp, Phase)
!
  character*256 nami,namo
  logical error
!
  call gildas_open
  call gildas_char('INPUT$',nami)
  call gildas_char('OUTPUT$',namo)
  call gildas_close
  call sub_timebase(nami,namo,error)
  call gagout('I-UV_TIMEBASE,  Successful completion')
end program uv_timebase
!<ff>
subroutine sub_timebase(nami,namo,error)
  use image_def
  use gkernel_interfaces
  character*(*) nami,namo
  logical error
!
  type (gildas) :: hin,hout
  real, allocatable :: din(:,:),dout(:,:,:)
  integer nt,nv,nbas,ntime,ier
  real*8, allocatable :: altimes(:), intimes(:)
  character*60 chain
!
! Read Header of a sorted, UV table
  call sic_parsef (nami,hin%file,' ','.uvt')
  call gdf_read_header (hin,error)
  if (error) return
  allocate (din(hin%gil%dim(1),hin%gil%dim(2)),stat=ier)
  call gdf_read_data (hin,din,error)
  if (error) return
  nt = hin%gil%dim(1)
  nv = hin%gil%dim(2)
!
! Define the problem size
  allocate (intimes(nv),altimes(nv),stat=ier)
  call analyze_uvtable(din,nt,nv,intimes,altimes,nbas,ntime)
!
! Define the image header
  call gdf_copy_header (hin,hout,error)
  call sic_parsef (namo,hout%file,' ','.uvp')
  hout%gil%ndim = 3
  hout%gil%dim(1) = ntime
  hout%gil%dim(2) = nbas
  hout%gil%dim(3) = 4 ! real, imag, weight, time
  hout%gil%convert(:,1:3) = 1.d0
#if defined(gildas_v1)
  hout%gil%extr = 0
#else
  hout%gil%extr_words = 0
#endif

  allocate(dout(ntime,nbas,4),stat=ier)
!
! Load the sorted data
  call load_uvtable (din,nt,nv,intimes,altimes,nbas,ntime,dout)
!
  call gdf_write_image(hout,dout,error)
  if (gildas_error(hout,'timebase',error)) call sysexi(fatale)
  deallocate (intimes,altimes)
  deallocate (dout)
  call gagout('I-TIMEBASE,  Successful completion')
  return
end subroutine sub_timebase
!
subroutine analyze_uvtable(din,nt,nv,intimes,altimes,nbas,ntime)
  use gkernel_interfaces
  integer nv,nt,nbas,ntime
  real din(nt,nv)
  real*8 intimes(nv), altimes(nv)
  logical error
!
  integer, allocatable :: it(:)
  integer nd,iv,ii
  logical ok
  character*60 chain
!
  error = .false.
!
! Scan how many dates
  nd = 1
  altimes(nd) = din(4,1)
  do iv=1,nv
     intimes(iv) = 0
     do ii=1,nd
        if (din(4,iv).eq.altimes(ii)) then
           intimes(iv) = ii
        endif
     enddo
     if (intimes(iv).eq.0) then
        nd = nd+1
        altimes(nd) = din(4,iv)
        intimes(iv) = nd
     endif
  enddo
  write(chain,*) 'Found ',nd,' dates '
  call gagout(chain(2:))
!
! Time compacted value
  do iv=1,nv
     intimes(iv) = intimes(iv)-1.d0+din(5,iv)/86400d0
  enddo
!
! Find out how many times...
  altimes = 0.0
  altimes(1) = intimes(1)
  ntime = 1
  do iv=2,nv
     ok = .false.
     ii = 1
     do while (.not.ok.and.ii.le.ntime)
        if (intimes(iv).eq.altimes(ii)) then
           ok = .true.
        else
           ii = ii+1
        endif
     enddo
     if (.not.ok) then
        ntime = ntime+1
        altimes(ntime) = intimes(iv)
     endif
  enddo
!
  write(chain,*) 'I-UV,  Found ',ntime,' times '
  call gagout(chain(2:))
!
! Pending nightmare: are the times sorted ?
! Answer: of course not, let us do it now...
  allocate(it(nv))
  do ii=1,ntime
     it(ii) = ii
  enddo
  call gr8_trie(altimes,it,ntime,error)
!
! Find out how many antennas
  nd = 1
  it(nd) = din(6,1)
  do iv=1,nv
     ok = .false.
     do ii=1,nd
        if (din(6,iv).eq.it(ii)) then
           ok = .true.
        endif
     enddo
     if (.not.ok) then
        nd = nd+1
        it(nd) = din(6,iv)
     endif
  enddo
  nd = nd+1  ! Add the first antenna
  deallocate(it)
  write(chain,*) 'I-UV,  Found ',nd,' antennas '
  call gagout(chain(2:))
  nbas = nd*(nd-1)/2
  write(chain,*) 'I-UV,  Found ',nbas,' baselines'
  call gagout(chain(2:))
end subroutine analyze_uvtable
!
!<FF>
subroutine load_uvtable (din,nt,nv,intimes,altimes,nbas,ntime,dout)
  integer nv,nt,nbas,ntime
  real din(nt,nv)
  real*8 intimes(nv)
  real*8 altimes(ntime)
  real dout(ntime,nbas,4)
!
  integer iv,itime,ibas
!
! Assume things are already time-baseline sorted
! So, just scan and put at the appropriate times
!
  dout = 0.0 ! Reset all to Zero, specially the weights
!
  itime = 1
  ibas = 1
  do iv=1,nv
!
! Check next time match
     do while (altimes(itime).ne.intimes(iv))
        if (itime.eq.ntime) then
           ibas = ibas+1
           itime = 0
        endif
        itime = itime+1
     enddo
!
! Put in place
     dout(itime,ibas,1) = din(8,iv)      ! Real
     dout(itime,ibas,2) = din(9,iv)      ! Imag
     dout(itime,ibas,3) = din(10,iv)     ! Weight
     dout(itime,ibas,4) = altimes(itime) ! Time
  enddo
end subroutine load_uvtable
