!*
! Tools to Sort UV data in V order
!!
subroutine check_order(visi,np,nv,sorted)
  !----------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Utility routine  
  !   Check if visibilites are sorted.
  !   Chksuv does a similar job, but using V values and an index.
  !!
  !----------------------------------------------------------
  integer, intent(in) :: np         !! Size of a visibility
  integer, intent(in) :: nv         !! Number of visibilities
  real, intent(in) :: visi(np,nv)   !! Visibilities
  logical, intent(out) :: sorted    !! Is data sorted ?
  !
  real vmax
  integer iv
  !
  vmax = visi(2,1)
  do iv=1,nv
    if (visi(2,iv).lt.vmax) then
      sorted = .false.
      return
    endif
    vmax = visi(2,iv)
  enddo
  sorted = .true.
end subroutine check_order
!
subroutine uv_sort (huvx,duvx,error,sorted,shift,newabs,uvmax,uvmin,needed)
  use gkernel_interfaces
  use imager_interfaces, except_this=>uv_sort
  use clean_def
  use clean_arrays
  use gbl_message
  !----------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER --  Sort the input UV table
  !!
  !----------------------------------------------------------------------
  type(gildas), intent(inout) :: huvx        !! UV Header
  real, intent(inout) :: duvx(:,:)           !! Data to be sorted
  logical, intent(out) :: error              !! Logical error flag
  logical, intent(inout) :: sorted           !! Is table sorted ?
  logical, intent(inout) :: shift            !! Do we shift phase center ?
  logical, intent(in) :: needed              !! Is sorting mandatory ?
  real(kind=8), intent(inout) :: newabs(3)   !! New phase center and PA
  real, intent(out) :: uvmin                 !! Min baseline
  real, intent(out) :: uvmax                 !! Max baseline
  !
  ! Constants
  real(8), parameter :: pi=3.14159265358979323846d0
  real(8), parameter :: f_to_k = 2.d0*pi/299792458.d-6
  character(len=*), parameter :: rname='UV_SORT'
  !
  ! Local ---
  real, allocatable :: duv_tmp(:,:)
  real(kind=8) :: freq, off(3)
  real(kind=4) :: pos(2), cs(2)
  integer :: nu,nv,ier
  !
  ! Code ----
  call imager_tree('UV_SORT',.false.)
  !
  ! The UV table is available in HUVT%
  if (huvx%loca%size.eq.0) then
    call map_message(seve%e,rname,'No UV data loaded')
    error = .true.
    return
  endif
  nu = huvx%gil%dim(1)
  nv = huvx%gil%nvisi
  !
  ! Correct for new phase center if required
  if (shift) then
    if (huvx%gil%ptyp.eq.p_none) then
      call map_message(seve%w,rname,'No previous phase center info')
      huvx%gil%a0 = huvx%gil%ra
      huvx%gil%d0 = huvx%gil%dec
      huvx%gil%pang = 0.d0
      huvx%gil%ptyp = p_azimuthal
    elseif (huvx%gil%ptyp.ne.p_azimuthal) then
      call map_message(seve%w,rname,'Previous projection type not SIN')
      huvx%gil%ptyp = p_azimuthal
    endif
    call uv_shift_header (newabs,huvx%gil%a0,huvx%gil%d0,huvx%gil%pang,   &
        &      off,shift)
    huvx%gil%posi_words = def_posi_words
    huvx%gil%proj_words = def_proj_words
  endif
  if (shift) then
    sorted = .false.
  else
    sorted = .true.
    if (needed) then 
      call check_order (duvx,nu,nv,sorted)
    else
      call map_message(seve%i,rname,'Sorting UV table is not needed...')
    endif
  endif
  !
  ! Get center frequency
  freq = gdf_uv_frequency(huvx,huvx%gil%ref(1))
  !
  ! If already sorted, use it
  if (sorted) then
    if (needed) call map_message(seve%i,rname,'UV table is already sorted')
    !
    ! Compute UVMAX
    call uvgmax (huvx,duvx,uvmax,uvmin)
    !
    ! Else, create another copy
  else
    call map_message(seve%i,rname,'Sorting UV table...',seve%w)
    !
    ! Compute observing frequency, and new phase center in wavelengths
    if (shift) then
      huvx%gil%a0 = newabs(1)
      huvx%gil%d0 = newabs(2)
      huvx%gil%pang = newabs(3)
      cs(1)  =  cos(off(3))
      cs(2)  = -sin(off(3))
      ! Note that the new phase center is counter-rotated because rotations
      ! are applied before phase shift.
      pos(1) = - freq * f_to_k * ( off(1)*cs(1) - off(2)*cs(2) )
      pos(2) = - freq * f_to_k * ( off(2)*cs(1) + off(1)*cs(2) )
    else
      pos(1) = 0.0
      pos(2) = 0.0
      cs(1) = 1.0
      cs(2) = 0.0
    endif
    !
    ! OK, rotate, shift, copy and sort ...
    call map_message(seve%d,rname,'Sorting DUVT ')
    allocate(duv_tmp(nu,nv),stat=ier)
    duv_tmp(:,:) = duvx(:,:)    ! Copy
    call uvsort_uv (nu,nv,huvx%gil%ntrail,duv_tmp,duvx,   &
         &        pos,cs,uvmax,uvmin,error) ! Sort
    deallocate(duv_tmp)
    huvx%gil%basemax = uvmax
    huvx%gil%basemin = uvmin
  endif
  !
  ! Now transform UVMAX in kiloWavelength (including 2 pi factor)
  uvmax = uvmax*freq*f_to_k
  uvmin = uvmin*freq*f_to_k
  error = .false.
  call imager_tree('UV_SORT',.true.)
end subroutine uv_sort
