subroutine uv_shift (new,ra,dec,ang,off,doit)
  use gkernel_interfaces
  use gkernel_types
  !-------------------------------------------------
  ! @ private
  !
  ! MAPPING
  !   Compute shift parameters
  !-------------------------------------------------
  real(kind=8), intent(inout) :: new(3)   ! New phase center and angle
  real(kind=8), intent(in) :: ra,dec,ang  ! Old center and angle
  real(kind=8), intent(out) :: off(3)     ! Required Offsets and Angle
  logical, intent(inout) :: doit          ! Do shift
  !
  real(8), parameter :: pi=3.14159265358979323846d0
  real(8), parameter :: sec=(pi/180d0/3600d0)
  type(projection_t) :: proj
  logical :: error
  !
  if (.not.doit) return
  !
  ! Check phase center agreement to 0.001" and angle to 1"
  ! These should be customizable in MAPPING
  !
  if ( abs(new(1)-ra).lt.1d-3*sec .and.   &
     &    abs(new(2)-dec).lt.1d-3*sec .and.   &
     &    abs(new(3)-ang).lt.sec ) then
    new(1) = ra
    new(2) = dec
    new(3) = ang
    doit  = .false.
    return
  endif
  !
  off(1) = ra
  off(2) = dec
  off(3) = -ang                ! GreG convention
  error = .false.
  call gwcs_projec(ra,dec,-ang,3,proj,error)  ! Previous projection system
  call abs_to_rel (proj,new(1),new(2),off(1),off(2),1)  ! Offsets of new center
  off(3) = new(3)-ang          ! Additional rotation required
  if (abs(off(3)).lt.sec) off(3) = 0.d0
end subroutine uv_shift
!
subroutine shift_uvdata(hx,nu,nv,visi,cs,nc,xy)
  use image_def
  use gkernel_interfaces
  use gkernel_types
  use phys_const
  !$ use omp_lib
  !-------------------------------------------------------------------
  ! @ private
  !  MAPPING
  !   Support routine for commands UV_SHIFT and UV_MAP
  !   Shift phase center and apply U,V coordinates rotation if needed
  !-------------------------------------------------------------------
  type(gildas), intent(inout) :: hx   ! Input UV header
  integer, intent(in) :: nu           ! Size of a visibility
  integer, intent(in) :: nv           ! Number of visibilities
  real, intent(inout) :: visi(nu,nv)  ! Visibilities
  real, intent(in) :: cs(2)           ! Cos/Sin of Rotation
  integer, intent(in) :: nc           ! Number of Channels
  real(8), intent(in) :: xy(2,nc)     ! Position Shift per channel
  !
  integer(kind=index_length) :: i
  integer :: ix, iu, iv, jc, loff, moff
  real(8) :: phi, sphi, cphi, freq, x, y
  real :: u, v, reel, imag
  real(8), allocatable :: lm_uv(:)
  !
  iu = hx%gil%column_pointer(code_uvt_u)
  iv = hx%gil%column_pointer(code_uvt_v)
  !
  ! If there is a Phase offset column, use it
  !  integer(kind=4), parameter :: code_uvt_loff = 10 ! Phase center Offset
  !  integer(kind=4), parameter :: code_uvt_moff = 11 ! Phase center Offset
  loff = hx%gil%column_pointer(code_uvt_loff)
  moff = hx%gil%column_pointer(code_uvt_moff)
  !
  if (loff.ne.0 .or. moff.ne.0) then
    !
    ! Shift and Rotation of a per-field phase center to a common one
    !
    allocate(lm_uv(nc))
    if (nc.eq.1) then
      freq = gdf_uv_frequency(hx)
      lm_uv(1) = freq * f_to_k
    else
      do i=1,hx%gil%nchan
        freq = gdf_uv_frequency(hx,dble(i))
        lm_uv(i) = freq * f_to_k
      enddo
    endif
    !
    !$OMP PARALLEL DEFAULT(none) &
    !$OMP SHARED(hx,nv,nc,cs,xy,loff,moff,lm_uv,visi,iu,iv) &
    !$OMP PRIVATE(i,u,v,x,y,phi,cphi,sphi,jc,ix,reel,imag)
    !
    !$OMP DO
    do i = 1,nv
      u = visi(iu,i)
      v = visi(iv,i)
      visi(iu,i) = cs(1)*u - cs(2)*v
      visi(iv,i) = cs(2)*u + cs(1)*v
      !
      if (nc.eq.1) then
        x = xy(1,1) + lm_uv(1) * visi(loff,i)
        y = xy(2,1) + lm_uv(1) * visi(moff,i)
        phi = x*u + y*v
        cphi = cos(phi)
        sphi = sin(phi)
      endif
      !
      do jc=1,hx%gil%nchan
        ix = hx%gil%fcol+(jc-1)*hx%gil%natom
        if (nc.gt.1) then
          x = xy(1,jc) + lm_uv(jc) * visi(loff,i)
          y = xy(2,jc) + lm_uv(jc) * visi(moff,i)
          phi = x*u + y*v
          cphi = cos(phi)
          sphi = sin(phi)
        endif
        reel = visi(ix,i) * cphi - visi(ix+1,i) * sphi
        imag = visi(ix,i) * sphi + visi(ix+1,i) * cphi
        visi(ix,i) = reel
        visi(ix+1,i) = imag
      enddo
    enddo
    !$OMP END DO
    !$OMP END PARALLEL
    !
  else if (xy(1,1).eq.0. .and. xy(2,1).eq.0.) then
    !
    ! No shift, only rotation of U,V coordinates
    !
    if (cs(1).eq.1.0) return  ! No rotation either
    !
    !$OMP PARALLEL DEFAULT(none) &
    !$OMP SHARED(nv,cs,visi,iu,iv) &
    !$OMP PRIVATE(i,u,v)
    !
    !$OMP DO
    do i = 1,nv
      u = visi(iu,i)
      v = visi(iv,i)
      visi(iu,i) = cs(1)*u - cs(2)*v
      visi(iv,i) = cs(2)*u + cs(1)*v
    enddo
    !$OMP END DO
    !$OMP END PARALLEL
  else
    !
    ! Shift and rotation of a common phase center
    !
    !$OMP PARALLEL DEFAULT(none) &
    !$OMP SHARED(hx,nv,nc,cs,xy,visi,iu,iv) &
    !$OMP PRIVATE(i,u,v,x,y,phi,cphi,sphi,jc,ix,reel,imag)
    !
    !$OMP DO
    do i = 1,nv
      u = visi(iu,i)
      v = visi(iv,i)
      visi(iu,i) = cs(1)*u - cs(2)*v
      visi(iv,i) = cs(2)*u + cs(1)*v
      !
      if (nc.eq.1) then
        phi = xy(1,1)*u + xy(2,1)*v
        cphi = cos(phi)
        sphi = sin(phi)
      endif
      !
      do jc=1,hx%gil%nchan
        ix = hx%gil%fcol+(jc-1)*hx%gil%natom
        if (nc.gt.1) then
          phi = xy(1,jc)*u + xy(2,jc)*v
          cphi = cos(phi)
          sphi = sin(phi)
        endif
        reel = visi(ix,i) * cphi - visi(ix+1,i) * sphi
        imag = visi(ix,i) * sphi + visi(ix+1,i) * cphi
        visi(ix,i) = reel
        visi(ix+1,i) = imag
      enddo
    enddo
    !$OMP END DO
    !$OMP END PARALLEL
  endif
end subroutine shift_uvdata
