!
subroutine uvsort_uv (np,nv,ntrail,vin,vout,xy,cs,uvmax,uvmin,error)
  use gildas_def
  use gkernel_interfaces
  use imager_interfaces, except_this=> uvsort_uv
  !---------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER -- UV handling routine
  !
  !     Rotate, Shift and Sort a UV table for map making
  !     Differential precession should have been applied before.
  !     Single Field case
  !!
  !---------------------------------------------------------------------
  integer, intent(in) :: np        !! Size of a visibility
  integer, intent(in) :: nv        !! Number of visibilities
  integer, intent(in) :: ntrail    !! Number of trailing daps
  real, intent(in) :: vin(np,nv)   !! Input visibilities
  real, intent(out) :: vout(np,nv) !! Output visibilities
  real, intent(in) :: xy(2)        !! Phase shift
  real, intent(in) :: cs(2)        !! Frame Rotation
  real, intent(out) :: uvmax       !! Max UV value
  real, intent(out) :: uvmin       !! Min UV value
  logical, intent(out) :: error    !! Error flag
  !
  ! Local ---
  logical, allocatable :: ips(:)       ! Sign of visibility
  real, allocatable :: ipu(:), ipv(:)  ! U,V coordinates
  integer, allocatable :: ipi(:)       ! Index
  logical :: sorted
  integer :: ier
  !
  ! Code ----
  ! Load U,V coordinates, applying possible rotation (CS), and
  ! making all V negative
  allocate (ips(nv),ipu(nv),ipv(nv),ipi(nv),stat=ier)
  error = ier.ne.0
  if (error) return
  call loaduv (vin,np,nv,cs,ipu,ipv,ips,uvmax,uvmin)
  !
  ! Sort if needed
  call chksuv (nv,ipv,ipi,sorted)
  if (.not.sorted) then
    call gr4_trie (ipv,ipi,nv,error)
    if (error) return
  endif
  !
  ! Apply phase shift and copy to output visibilities
  call sub_sortuv (vin,vout,np,nv,ntrail,xy,1,0,ipu,ipv,ips,ipi)
  Print *,'Done SUB_SORTUV '
  !
  deallocate (ips,ipu,ipv,ipi,stat=ier)
end subroutine uvsort_uv
!
subroutine loaduv (visi,np,nv,cs,u,v,s,uvmax,uvmin)
  !---------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER  --   UV_SORT routines
  !
  !     Load new U,V coordinates and sign indicator into work arrays
  !     for sorting.
  !!
  !---------------------------------------------------------------------
  integer, intent(in) :: np       !! Size of a visibility
  integer, intent(in) :: nv       !! Number of visibilities
  real, intent(in) :: visi(np,nv) !! Input visibilities
  real, intent(in) :: cs(2)       !! Rotation parameter
  real, intent(out) :: u(nv)      !! Output U and V coordinates
  real, intent(out) :: v(nv)      !! Output U and V coordinates
  logical, intent(out) :: s(nv)   !! V Sign indicator
  real, intent(inout) :: uvmax    !! Maximum length
  real, intent(inout) :: uvmin    !! Minimum baseline
  !
  ! Local
  integer :: iv
  real(4) :: uv
  !
  uv = 0
  do iv=1,nv
    uv = visi(1,iv)**2 + visi(2,iv)**2
    if (uv.ne.0) exit
  enddo
  uvmax = uv
  uvmin = uv
  !
  if (cs(2).eq.0.0) then
    do iv=1,nv
      v(iv) = visi(2,iv)
      if (v(iv).gt.0) then
        u(iv) = -visi(1,iv)
        v(iv) = -v(iv)
        s(iv) = .false.
      else
        u(iv) = visi(1,iv)
        s(iv) = .true.
      endif
      uv = u(iv)*u(iv)+v(iv)*v(iv)
      if (uv.gt.uvmax) then
        uvmax = uv
      else if (uv.lt.uvmin .and. uv.ne.0) then
        uvmin = uv
      endif
    enddo
  else
    do iv=1,nv
      u(iv) = cs(1)*visi(1,iv) - cs(2)*visi(2,iv)
      v(iv) = cs(2)*visi(1,iv) + cs(1)*visi(2,iv)
      if (v(iv).gt.0) then
        u(iv) = -u(iv)
        v(iv) = -v(iv)
        s(iv) = .false.
      else
        s(iv) = .true.
      endif
      uv = u(iv)*u(iv)+v(iv)*v(iv)
      if (uv.gt.uvmax) then
        uvmax = uv
      else if (uv.lt.uvmin .and. uv.ne.0) then
        uvmin = uv
      endif
    enddo
  endif
  uvmax = sqrt(uvmax)
  uvmin = sqrt(uvmin)
end subroutine loaduv
!
subroutine chksuv (nv,v,it,sorted)
  !---------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER -- UV_SORT routines
  !
  !   Check if visibilities are sorted
  !!
  !---------------------------------------------------------------------
  integer, intent(in) :: nv      !! Number of visibilities
  real, intent(in) :: v(nv)      !! Visibilities
  integer, intent(out) :: it(nv) !! Sorting pointer
  logical, intent(out) :: sorted !! short cut
  !
  ! Local
  integer :: iv
  real(4) :: vmax
  !
  do iv=1,nv
    it(iv) = iv
  enddo
  !
  vmax = v(1)
  do iv = 1,nv
    if (v(iv).gt.0 .or. v(iv).lt.vmax) then
      sorted = .false.
      return
    endif
    vmax = v(iv)
  enddo
  sorted = .true.
end subroutine chksuv
!
subroutine sub_sortuv (vin,vout,np,nv,ntrail,xy,nf,id,u,v,s,it)
  use gbl_message
  use imager_interfaces, only : map_message
  !---------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER  --  UV_SORT routines
  !
  !     Sort an input UV table into an output one.
  !     The output UV table is a rotated, phase shifted copy of
  !     the input one, with all V negative and increasing
  !!
  !---------------------------------------------------------------------
  integer, intent(in) :: np         !! Size of a visibility
  integer, intent(in) :: nv         !! Number of visibilities
  integer, intent(in) :: ntrail     !! Number of trailing daps
  real, intent(in) :: vin(np,nv)    !! Input visibilities
  real, intent(out) :: vout(np,nv)  !! Output visibilities
  integer, intent(in) :: nf         !! Number of fields
  integer, intent(in) :: id         !! Fields ID column
  real, intent(in) :: xy(2,nf)      !! Phase shifting factors
  real, intent(in) :: u(nv)         !! New U coordinates
  real, intent(in) :: v(nv)         !! New V coordinates
  logical, intent(in) :: s(nv)      !! Sign of new visibility
  integer, intent(in) :: it(nv)     !! Pointer to old visibility
  !
  ! Local ---
  integer :: ip,iv,kv,no,idi,ifi
  real(4) :: phi, cphi, sphi
  character(len=80) :: mess
  !
  ! Code ----
  logical :: debug, error
  !
  ! There may be trailing columns in UV table
  debug = .false.
  call sic_get_logi('DEBUG',debug,error)
  !
  no = np-ntrail
  !
  if (nf.gt.1) then
    if ((id.ne.0).and.((id.le.no).or.(id.gt.np))) then
      write(mess,'(A,I0,A,I0)') 'Temporary Case (ultimately a Programming error) Fields ',nf,' ID col ',id
      call map_message(seve%w,'SUB_SORTUV',mess,seve%e)
      idi = 0
    else
      write(mess,'(A,I0,A,I0)') 'Temporary Case: Per Field shift on ',nf,' fields, ID col ',id
      call map_message(seve%w,'SUB_SORTUV',mess)
      idi = id
    endif
  else
    idi = 0   ! Ignore the ID column in this case
  endif
  !
  ! Simple case: no phase shift -- simple sort
  if (all(xy.eq.0)) then
    if (debug) Print *,'No SHIFT case '
    !$OMP PARALLEL DEFAULt(none) &
    !$OMP & SHARED(u,v,vin,vout,s,it,no,np,nv, debug) &
    !$OMP & PRIVATE(kv,iv,ip)
    !$OMP DO
    do iv=1,nv
      kv = it(iv)
      if (debug) then
        if (iv.lt.10) then
          Print *,'IV ',iv,' / ',nv
          Print *,' V ',v(iv),' KV ',it(iv)
          Print *,' U ',u(kv),' S ',s(kv)
        endif
      endif
      vout(1,iv) = u(kv)
      vout(2,iv) = v(iv)       ! This one is sorted already
      vout(3,iv) = vin(3,kv)
      vout(4,iv) = vin(4,kv)
      vout(5,iv) = vin(5,kv)
      if (s(kv)) then
        vout(6,iv) = vin(6,kv)
        vout(7,iv) = vin(7,kv)
        do ip=8,no
          vout(ip,iv) = vin(ip,kv)
        enddo
      else
        vout(6,iv) = vin(7,kv)
        vout(7,iv) = vin(6,kv)
        do ip=8,no,3
          vout(ip,iv)   =  vin(ip,kv)
          vout(ip+1,iv) = -vin(ip+1,kv)
          vout(ip+2,iv) =  vin(ip+2,kv)
        enddo
      endif
      do ip=no+1,np
        vout(ip,iv)   =  vin(ip,kv)
      enddo
    enddo
    !$OMP END DO
    !$OMP END PARALLEL
  else
    if (debug) Print *,'SHIFTing case '
    !
    ! Complex case: phase center has been shifted
    !$OMP PARALLEL DEFAULT(none) &
    !$OMP & SHARED(u,v,vin,vout,s,it,no,np,nv,xy,idi,nf, debug) &
    !$OMP & PRIVATE(kv,iv,ip, phi,cphi,sphi,ifi)
    !$OMP DO
    do iv=1,nv
      kv = it(iv)
      if (debug) then
        if (iv.lt.10) then
          Print *,'IV ',iv,' / ',nv
          Print *,' V ',v(iv),' KV ',it(iv)
          Print *,' U ',u(kv),' S ',s(kv)
        endif
      endif
      vout(1,iv) = u(kv)
      vout(2,iv) = v(iv)       ! This one is sorted already
      vout(3,iv) = vin(3,kv)
      vout(4,iv) = vin(4,kv)
      vout(5,iv) = vin(5,kv)
      !
      if (idi.eq.0) then
        ifi = 1
      else
        ifi = vin(idi,kv)
        if (ifi.gt.nf) then
          Print *,'F-UVSORT,  Programming error more Fields ',ifi,' at Visi ',kv,' than declared ',nf
          stop
        endif
      endif
      phi = xy(1,ifi)*u(kv)+xy(2,ifi)*v(iv)
      cphi = cos(phi)
      sphi = sin(phi)
      if (s(kv)) then
        vout(6,iv) = vin(6,kv)
        vout(7,iv) = vin(7,kv)
        do ip=8,no,3
          vout(ip,iv) = vin(ip,kv)*cphi - vin(ip+1,kv)*sphi
          vout(ip+1,iv) = vin(ip,kv)*sphi + vin(ip+1,kv)*cphi
          vout(ip+2,iv) = vin(ip+2,kv)
        enddo
      else
        vout(6,iv) = vin(7,kv)
        vout(7,iv) = vin(6,kv)
        do ip=8,no,3
          vout(ip,iv) = vin(ip,kv)*cphi + vin(ip+1,kv)*sphi
          vout(ip+1,iv) = vin(ip,kv)*sphi - vin(ip+1,kv)*cphi
          vout(ip+2,iv) = vin(ip+2,kv)
        enddo
      endif
      do ip=no+1,np
        vout(ip,iv)   =  vin(ip,kv)
      enddo
    enddo
    !$OMP END DO
    !$OMP END PARALLEL
    Print *,'Done loop '
  endif
end subroutine sub_sortuv
