subroutine uv_shift_header (new,ra,dec,ang,off,doit)
  use gkernel_interfaces
  use gkernel_types
  !-------------------------------------------------
  ! @ private
  !*
  ! IMAGER --   Compute position 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          !! Is shift Required ? 
  !
  real(8), parameter :: pi=3.14159265358979323846d0
  real(8), parameter :: sec_to_rad=(pi/180d0/3600d0)
  type(projection_t) :: proj
  logical :: error
  !
  off = 0.d0
  if (.not.doit) return
  call imager_tree('UV_SHIFT_HEADER',.false.)
  !
  ! Check phase center agreement to 0.001" and angle to 1"
  ! These might be customizable in IMAGER to some level
  ! but there is a limit due to the machine precision
  ! which affects abs_to_rel and rel_to_abs.
  !
  if ( abs(new(1)-ra).lt.1d-3*sec_to_rad .and.   &
     &    abs(new(2)-dec).lt.1d-3*sec_to_rad .and.   &
     &    abs(new(3)-ang).lt.sec_to_rad ) then
    ! The change is too small: it cannot be applied
    ! But we must be sure the New center reflects the actual projection
    new(1) = ra
    new(2) = dec
    new(3) = ang
    doit  = .false.
    return
  endif
  !
  off(1) = ra
  off(2) = dec
  off(3) = ang               
  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_to_rad) off(3) = 0.d0
  call imager_tree('UV_SHIFT_HEADER',.true.)
end subroutine uv_shift_header
!
subroutine shift_uvdata(hx,nu,nv,visi,cs,nc,xy)
  use image_def
  use gkernel_interfaces
  use gkernel_types
  use clean_arrays 
  use gbl_message
  use imager_interfaces, only : map_message
  use phys_const
  !$ use omp_lib
  !-------------------------------------------------------------------
  ! @ private
  !*
  !  IMAGER  --   Support routine for commands UV_SHIFT and UV_MAP
  !
  !   Shift phase center and apply U,V coordinates rotation if needed
  !   Note that Offsets are not shifted, neither rotated by this
  !   subroutine
  !-------------------------------------------------------------------
  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
  !
  ! Local ---
  integer(kind=index_length) :: i
  integer :: ix, iu, iv, jc, loff, moff, idoff, ipoint
  real(8) :: phi, sphi, cphi, freq, x, y, xoff, yoff
  real(4) :: u, v, reel, imag
  real(8), allocatable :: lm_uv(:)
  !
  ! Code ----
  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)
  idoff = hx%gil%column_pointer(code_uvt_id)
  !
  if (loff.ne.0 .and. 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
    !
    cphi = 1.0
    sphi = 0.0
    !
    !$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,jc,ix,reel,imag) &
    !$OMP FIRSTPRIVATE(cphi,sphi)    
    !
    !$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 ((themap%nfields.ne.0).and.(idoff.ne.0)) then
    if (.not.allocated(hx%mos%fields)) then
      call map_message(seve%e,'SHIFT_UV','Programming error, no Mosaic Header',1)
      return
    else
      call map_message(seve%w,'SHIFT_UV','Mosaic UV Table with ID should not be shifted',1)
      ! return ?
    endif
    !
    ! Shift and Rotation of an arbitrary 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
    !
    cphi = 1.0
    sphi = 0.0
    !
    !$OMP PARALLEL DEFAULT(none) &
    !$OMP SHARED(hx,nv,nc,cs,xy,idoff,loff,moff,lm_uv,visi,iu,iv) &
    !$OMP PRIVATE(i,u,v,x,y,phi,jc,ix,reel,imag,xoff,yoff,ipoint) &
    !$OMP FIRSTPRIVATE(cphi,sphi)    
    !
    !$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
      !
      ipoint = nint(visi(idoff,i))
      xoff = hx%mos%fields(ipoint)%ophase(1)
      yoff = hx%mos%fields(ipoint)%ophase(2)
      if (nc.eq.1) then
        x = xy(1,1) + lm_uv(1) * xoff
        y = xy(2,1) + lm_uv(1) * yoff
        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) * xoff
          y = xy(2,jc) + lm_uv(jc) * yoff
          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
    !
    cphi = 1.0
    sphi = 0.0
    !
    !$OMP PARALLEL DEFAULT(none) &
    !$OMP SHARED(hx,nv,nc,cs,xy,visi,iu,iv) &
    !$OMP PRIVATE(i,u,v,x,y,phi,jc,ix,reel,imag) &
    !$OMP FIRSTPRIVATE(cphi,sphi) 
    !
    !$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
