subroutine uv_shift_mosaic(line,comm,error)
  use clean_def
  use clean_default
  use clean_arrays
  use phys_const
  use gkernel_types
  use gkernel_interfaces
  use gbl_message
  use imager_interfaces, except_this => uv_shift_mosaic
  !-------------------------------------------------------------------
  ! @ private
  !
  !  IMAGER 
  !   Support routine for command
  !       UV_SHIFT  MAP_CENTER 
  !                 Xpos Ypos UNIT [Angle]
  !
  !   Phase shift a Mosaic or Single Dish UV Table to a new
  !   common phase center and orientation
  !     Offx OffY are offsets in Angle UNIT 
  !               (default 0,0)
  !     Angle     is the final position angle from North in Degree
  !               (default: no change)
  !
  !   Also called implicitely (with no command line arguments, i.e.
  !   no change of Phase Center unless the UV Table is with Phase Offsets)
  !   by command UV_MAP for Mosaics
  !-------------------------------------------------------------------
  character(len=*), intent(in) :: line  ! Command line
  character(len=*), intent(in) :: comm  ! Command name 
  logical error                         ! Logical error flag
  !
  character(len=*), parameter :: rname='UV_SHIFT'
  character(len=80) :: mess
  type(projection_t) :: proj, old_proj, new_proj
  real(8) :: newoff(3), newabs(3), oldabs(3)
  real(4) :: cs(2), angold
  real(8), allocatable :: rpos(:,:)
  real(8) :: freq
  logical :: precise=.true.
  logical :: shift, doit, lshift
  integer :: nc,nu,nv,i,ier,loff,moff,xoff,yoff
  !
  real(8) :: old(2), new(2), tabs(2), off(2)
  integer :: iv,ip
  !
  loff = huv%gil%column_pointer(code_uvt_loff)
  moff = huv%gil%column_pointer(code_uvt_moff)
  xoff = huv%gil%column_pointer(code_uvt_xoff)
  yoff = huv%gil%column_pointer(code_uvt_yoff)
  !
  oldabs = [huv%gil%a0,huv%gil%d0,huv%gil%pang]   !!! Remember map_center
  newabs = oldabs
  newoff = 0.d0
  !
  if (themap%nfields.eq.0) then
    call map_message(seve%i,rname,'UV data is a single field') 
    shift = .false.
  else if (themap%nfields.gt.0) then
    if (xoff.ne.0 .or. yoff.ne.0) then
      call map_message(seve%i,rname,'Mosaic UV data is already in Pointing offsets')
    else
      call map_message(seve%e,rname,'Mosaic UV data is already in Pointing offsets')
      call map_message(seve%e,rname,'Mosaic UV data has no Pointing columns')
      error = .true.
      return
    endif
    shift = .false.
  else
    call map_message(seve%w,rname,'Mosaic UV data is in Phase offsets')
    !
    write(mess,'(A,I0,A)') 'Mosaic UV data has ',abs(themap%nfields),' fields'
    call map_message(seve%i,rname,mess)
    !
    ! Compute the mean offset as phase center position
    newoff(1) = minval(themap%offxy(1,:)) + maxval(themap%offxy(1,:))
    newoff(2) = minval(themap%offxy(2,:)) + maxval(themap%offxy(2,:))
    newoff = newoff*0.5d0
    !
    Print *,'NEWOFF ',newoff
    call gwcs_projec(huv%gil%a0,huv%gil%d0,huv%gil%pang,huv%gil%ptyp,proj,error)
    if (error)  return
    call rel_to_abs(proj,newoff(1),newoff(2),newabs(1),newabs(2),1)
    !
    shift = .true.
    call print_change_header('PHASE_TO_POINT',huv,newabs,shift)
    !
    ! Set the new center so that the Offsets are relative to this one now
    huv%gil%a0 = newabs(1)
    huv%gil%d0 = newabs(2)
  endif                  
  !
  ! Check if command line specifies another center and/or orientation
  call map_center(line,rname,huv,lshift,newabs,error)
  if (error) return
  !
  ! Restore the original Projection 
  huv%gil%a0 = oldabs(1)
  huv%gil%d0 = oldabs(2)
  huv%gil%pang = oldabs(3)
  !
  ! Shifting is the Combination of Phase-->Pointing conversion
  ! and User requested shift through MAP_CENTER or command line arguments
  shift = shift .or. lshift 
  doit = .false.
  !
  if (.not.shift) then
    call map_message(seve%w,rname,'No shift required')
  else
    if (newabs(3).ne.0.0) then
      call map_message(seve%w,rname,'Rotated UV Mosaic cannot be saved -- No convention adopted by IRAM')
    endif      
    !
    doit = .true.   ! Make absolutely sure we do the shift ...
    call uv_shift (newabs,huv%gil%a0,huv%gil%d0,huv%gil%pang,newoff,doit)
    !
    if (.not.doit) then
      call map_message(seve%w,rname,'Shift is below possible precision')
      ! So, no change of Phase Center and Orientation, but the conversion
      ! from Phase to Pointing centers remains to be done.
      !
    else
      !
      ! Compute observing frequency, and new phase center in wavelengths
      !
      if (precise) then
        nc = huv%gil%nchan
        allocate(rpos(2,nc),stat=ier)
        do i=1,huv%gil%nchan
          freq = gdf_uv_frequency(huv,dble(i))
          rpos(1:2,i) = - freq * f_to_k * newoff(1:2)
        enddo
      else
        nc = 1
        allocate(rpos(2,1),stat=ier)
        freq = gdf_uv_frequency(huv)
        rpos(1:2,1) = - freq * f_to_k * newoff(1:2)
      endif
      !
      ! Define the rotation
      cs  = [1.0,0.0]
      angold = huv%gil%pang
      huv%gil%pang = newabs(3)
      cs(1)  =  cos(huv%gil%pang-angold)
      cs(2)  = -sin(huv%gil%pang-angold) !! This sign MAY BE WRONG
      !
      ! Recenter all channels, Loop over line table
      ! We work in place - We do not play with UV buffers
      !
      nu = huv%gil%dim(1)
      nv = huv%gil%nvisi
      !
      ! This rotates the U,V coordinates and Shift the Phases
      call shift_uvdata (huv,nu,nv,duv,cs,nc,rpos)
      !
      ! Set the new Phase center and Orientation
      huv%gil%a0 = newabs(1)
      huv%gil%d0 = newabs(2)  
      huv%gil%pang = newabs(3)
    endif
  endif
  !
  ! Done if Single Field (0) or already Pointing columns (>0)
  if (themap%nfields.eq.0) return ! Single Field
  !
  ! Convert the LOFF - MOFF columns into Pointing columns if needed
  if (themap%nfields.lt.0) then
    ! "Phase" columns
    huv%gil%column_pointer(code_uvt_xoff) = loff
    huv%gil%column_pointer(code_uvt_yoff) = moff
    huv%gil%column_size(code_uvt_xoff) = 1
    huv%gil%column_size(code_uvt_yoff) = 1
    !
    huv%gil%column_pointer(code_uvt_loff) = 0
    huv%gil%column_pointer(code_uvt_moff) = 0
    huv%gil%column_size(code_uvt_loff) = 0
    huv%gil%column_size(code_uvt_moff) = 0
    !
    themap%nfields = abs(themap%nfields)
  endif
  !
  ! And now convert the Offset values to new Coordinate system
  ! 
  ! Before: it was Relative to "OLDABS"
  ! Now it is Relative to "NEWABS"
  !
  if (doit) then
    ! A common, modified, Phase center and "Pointing Offsets"
    !
    ! The whole question is whether the "Pointing Offsets" are
    ! relative to the "Pointing Center" (with no rotation Angle)
    ! or to the "Phase Center" (with a rotation Angle)
    !
    ! The code below assumes everything is relative to the Phase Center.
    !
    xoff = huv%gil%column_pointer(code_uvt_xoff) 
    yoff = huv%gil%column_pointer(code_uvt_yoff)
    !
    old(1) = duv(xoff,1)
    old(2) = duv(yoff,1)
    call gwcs_projec(oldabs(1),oldabs(2),oldabs(3),huv%gil%ptyp,old_proj,error)  ! Previous projection system
    call gwcs_projec(newabs(1),newabs(2),newabs(3),huv%gil%ptyp,new_proj,error)  ! New projection system
    call rel_to_abs(old_proj,old(1),old(2),tabs(1),tabs(2),1)
    call abs_to_rel(new_proj,tabs(1),tabs(2),new(1),new(2),1)
    !
    do iv=1,nv
      off(1) = duv(xoff,iv)
      off(2) = duv(yoff,iv)
      if (any(off.ne.old)) then
        old(1) = duv(xoff,iv)
        old(2) = duv(yoff,iv)
        call rel_to_abs(old_proj,old(1),old(2),tabs(1),tabs(2),1)
        call abs_to_rel(new_proj,tabs(1),tabs(2),new(1),new(2),1)
      endif
      duv(xoff,iv) = new(1)
      duv(yoff,iv) = new(2)
    enddo
    !
    ! And for convenience, to avoid any ambiguity, we set the
    ! Pointing center equal to the Phase center
    !
    huv%gil%ra = huv%gil%a0
    huv%gil%dec = huv%gil%d0 
    !
    ! And we also correct the FIELDS%OFFSET values
    do ip=1,abs(themap%nfields)
      off = themap%offxy(:,ip)
      call rel_to_abs(old_proj,off(1),off(2),tabs(1),tabs(2),1)
      call abs_to_rel(new_proj,tabs(1),tabs(2),off(1),off(2),1)
      themap%offxy(:,ip) = off
    enddo
  endif
  !
end subroutine uv_shift_mosaic
!
