subroutine uv_map_mosaic(line,comm,error)
  use clean_arrays
  use clean_default
  use gbl_message
  use gkernel_interfaces
  use imager_interfaces, except_this => uv_map_mosaic
  !---------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Support for commands
  ! UV_MAP or UV_RESTORE /FIELDS /RANGE /TRUNCATE  /CONTINUUM /INDEX  
  !   or  
  ! UV_SELF /RANGE /RESTORE
  !!
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: comm     !! Caller name
  character(len=*), intent(inout) :: line  !! Command line
  logical, intent(inout) :: error          !! Logical error flag
  !
  ! Constants
  real(kind=8), parameter :: pi=3.14159265358979323846d0
  real(kind=4), parameter :: sec_to_rad=pi/3600.0/180.0
  character(len=1), parameter :: question_mark='?'
  ! ' UV_MAP', '/TRUNCATE',  '/FIELDS', '/RANGE', '/CONTINUUM', '/INDEX'
  integer, parameter :: o_trunc=1
  integer, parameter :: o_field=2
  integer, parameter :: o_range=3
  integer, parameter :: o_cont=4
  integer, parameter :: o_index=5
  ! ' UV_SELF', '/RANGE', '/RESTORE'
  integer, parameter :: opt_rang=1  ! /RANGE Option for UV_SELF
  integer, parameter :: opt_rest=2  ! /RESTORE Option for UV_SELF
  ! Memories ...
  logical, save :: use_cont=.false.
  !
  ! Local ---
  type(imaging_mode) :: tmp_mode
  logical :: do_cct
  integer :: ier
  character(len=2) :: code, new_code
  type(gildas) :: huv_local
  logical :: err, goon
  character(len=80) :: chain, string
  integer :: debug
  !
  ! Code ----
  code = ' '
  new_code = ' '
  call imager_tree('UV_MAP_MOSAIC',.false.)
  debug = 0
  call sic_get_inte('DEBUG_UVMAP',debug,error)
  error = .false.
  !
  ! Check command line syntax
  call map_query (line,comm,themap,goon,error) 
  if ((.not.goon).or.error) return
  !
  err = .false.
  if (comm.eq.'UV_SELF') then
    ! Self Calibration image !
    if (huv_current%gil%column_pointer(code_uvt_if).ne.0) then
      call map_message(seve%e,comm, &
      & 'This UV table (probably a result of UV_CONTINUUM) is not suited for self-calibration')
      error = .true.
      return
    endif
    call map_message(seve%w,'UV_SELF','not fully tested for Mosaics')
    call uv_self_mosaic(line,comm,error)
    return
  endif
  !
  ! Normal Mosaic imaging: UV_MAP or UV_RESTORE, Cube or /CONTINUUM mode
  string = defmap_center
  !
  ! Select current data set or possibly its Continuum sibbling 
  do_cct = comm.eq.'UV_RESTORE'
  ! In a UV_RESTORE command, USE_CONT is remembered from last UV_MAP command
  ! In a UV_MAP command, USE_CONT is defined by the /CONT option
  if (.not.do_cct) use_cont = sic_present(o_cont,0)
  !
  if (comm.eq.'UV_MAP') then
    ! UV_MAP only
    if (huv_current%gil%column_pointer(code_uvt_xoff).ne.0) then
      call map_message(seve%i,'UV_MOSAIC','UV data is a Pointing Mosaic',seve%w)
    else if (huv_current%gil%column_pointer(code_uvt_loff).ne.0) then
      call map_message(seve%i,'UV_MOSAIC','UV data is a Phase Mosaic',seve%w)
    else if (huv_current%gil%column_pointer(code_uvt_id).ne.0) then
      call map_message(seve%i,'UV_MOSAIC','UV data is a Mosaic with field ID',seve%w)
    else
      call map_message(seve%w,'UV_MOSAIC','UV data is a Mosaic of unknown type',seve%e)
    endif
  endif
  !
  if (use_cont) then
    !
    ! Select Continuum data set (UV_MAP /CONT or UV_RESTORE after a UV_MAP /CONT)
    if (do_cct) then
      call print_imaging(comm,' -- DO_CCT Current ',huv_current%img) 
      !
      if (.not.associated(huv_cont%r2d,duvc)) then
        call map_message(seve%w,comm,'HUV_Cont Pointer was incorrectly associated',seve%e)
        huv_cont%r2d => duvc
      endif
      tmp_mode = huv_current%img ! Save the initial imaging mode
    else
      call print_imaging(comm,' -- UV_MAP Current ',huv_current%img) 
      call switch_uv_cont(line,comm,do_cct,error)
      if (error) return
      tmp_mode = huv_cont%img ! Save the initial imaging mode
    endif
    !
    ! Perform the imaging
    if (do_cct) then
      call print_imaging(comm,' -- DO_CCT Cont ',huv_cont%img) 
      defmap_center = ' '   ! The Continuum UV data has already been shifted
    else
      call print_imaging(comm,' -- UV_MAP Current ',huv_current%img)     
    endif
    if (do_cct) then
      call mosaic_restore(line,huv_cont,error)     ! Image
      call print_imaging(comm,'-- DO_CCT Restore ',huv_cont%img) 
    else
      call mosaic_uvmap('UV_MOSAIC',line,huv_cont,error)     ! Image Continuum one...
      call print_imaging(comm,'UV_MAP Continuum ',huv_cont%img) 
    endif
    defmap_center = string 
    if (error) return
    !
    if (do_cct) then    ! Use DSKY instead of DCLEAN ?...
      ! There can be a size mis-match here ...
      if (any(hcont%gil%dim(1:2).ne.hsky%gil%dim(1:2))) then
        write(chain,'(A,I0,A,I0,A)') 'Re-sizing continuum image to [', &
          &   hsky%gil%dim(1),',',hsky%gil%dim(2),']'
        call map_message(seve%w,comm,chain)
        deallocate(dcont,stat=ier)
        allocate(dcont(hsky%gil%dim(1),hsky%gil%dim(2)),stat=ier)
        call gdf_copy_header(hsky,hcont,error)
        hcont%gil%ndim = 2
        hcont%loca%size = hcont%gil%dim(1)*hcont%gil%dim(2)
        call sic_delvariable('CONTINUUM',.false.,error)
        call sic_mapgildas ('CONTINUUM',hcont,error,dcont)
      endif          
      !
      dcont(:,:) = dsky(:,:,1) ! Update CONTINUUM image too
      hcont%gil%minloc = hsky%gil%minloc
      hcont%gil%maxloc = hsky%gil%maxloc
      hcont%gil%rmin = hsky%gil%rmin
      hcont%gil%rmax = hsky%gil%rmax
    else
      do_continuum = .true.  ! Next CLEAN, there will be a CONTINUUM image
    endif
    saved_chan = tmp_mode    ! Restore the proper imaging mode
    huv_current%img = saved_chan
    huv_current%img%mode = code_img_cont
  else
    ! Cube Mode ---
    ! Select the data set. Can be UV_DATA, UV_MODEL, or UV_RESIDUAL
    if (current_uvdata.eq.'DATA_UV') then
      if (do_cct) then
        defmap_center = ' '
        call mosaic_restore(line,huv_current,error)     ! Image 
        defmap_center = string
      else
        call mosaic_uvmap('UV_MOSAIC',line,huv_current,error)     ! Image  
        huv_current%img%bounds = saved_chan%bounds
        huv_current%img%mode = code_img_line 
      endif        
    else 
      call gildas_null (huv_local,type='UVT')
      call uv_select_data(comm,huv_local,error)
      if (do_cct) then
        defmap_center = ' '
        call mosaic_restore(line,huv_local,error)     ! Image 
        defmap_center = string
      else
        call mosaic_uvmap('UV_MOSAIC',line,huv_local,error)     ! Image  
        huv_local%img%bounds = saved_chan%bounds
        huv_local%img%mode = code_img_line !! This may not work...
      endif        
    endif
    do_continuum = .false.  ! Next CLEAN will be no CONTINUUM
  endif
  if (error) return
  !
  call imager_tree('UV_MAP_MOSAIC',.true.)
end subroutine uv_map_mosaic
!
subroutine uv_self_mosaic(line,comm,error)
  use clean_arrays
  use clean_default
  use gbl_message
  use gkernel_interfaces
  use imager_interfaces, except_this => uv_self_mosaic
  !---------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Support for command  
  !   UV_SELF /RANGE /RESTORE
  !!
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: comm     !! Caller name
  character(len=*), intent(inout) :: line  !! Command line
  logical, intent(inout) :: error          !! Logical error flag
  !
  ! Constants
  real(kind=8), parameter :: pi=3.14159265358979323846d0
  real(kind=4), parameter :: sec_to_rad=pi/3600.0/180.0
  character(len=1), parameter :: question_mark='?'
  ! ' UV_MAP', '/TRUNCATE',  '/FIELDS', '/RANGE', '/CONTINUUM', '/INDEX'
  integer, parameter :: o_trunc=1
  integer, parameter :: o_field=2
  integer, parameter :: o_range=3
  integer, parameter :: o_cont=4
  integer, parameter :: o_index=5
  ! ' UV_SELF', '/RANGE', '/RESTORE'
  integer, parameter :: opt_rang=1  ! /RANGE Option for UV_SELF
  integer, parameter :: opt_rest=2  ! /RESTORE Option for UV_SELF
  ! Memories ...
  logical, save :: do_self=.false.
  !
  ! Local ---
  logical :: do_cct, do_init
  integer :: saved_nfields ! Also used to distinguish Mosaic mode
  integer :: nline
  character(len=2) :: code, new_code
  character(len=16) :: acomm
  type(gildas) :: huv_tmp
  logical :: err, goon
  character(len=80) :: string
  integer :: debug
  !
  ! Code ----
  call map_message(seve%t,comm,'Uv_Self_Mosaic starting ',seve%e)
  code = ' '
  new_code = ' '
  call imager_tree('UV_SELF_MOSAIC',.false.)
  debug = 0
  call sic_get_inte('DEBUG_UVMAP',debug,error)
  error = .false.
  !
  ! Check command line syntax
  call map_query (line,comm,themap,goon,error) 
  if ((.not.goon).or.error) return
  !
  err = .false.
  if (comm.ne.'UV_SELF') then
    call map_message(seve%e,comm, &
    & 'Programming error - Expected UV_SELF command',seve%e)
    error = .true.
    return
  endif
  !
  do_init = hself_self%loca%size.eq.0 .or. sic_present(opt_rang,0)
  !
  saved_nfields = themap%nfields
  !
  ! Mosaic case
  call map_message(seve%w,'UV_SELF','not fully tested for Mosaics')
  error = .false.
  string = defmap_center
  if (.not.do_self) do_weig = .true.
  !
  ! Self-calibrated data
  do_cct = sic_present(opt_rest,0) ! /RESTORE option
  if (.not.do_cct) then
    if (do_init) then
      if (hself_self%loca%size.ne.0) call uvdebug_pointers(comm,'hself_self' ,hself_self)
      call init_selfcal('UV_SELF',line,error)
      if (error) return
        if (debug.gt.0) call uvdebug_pointers(comm,'hself_self ',hself_self)
      !! call uv_dump_buffers('UV_SELF *')
      line = 'UV_SELF'
      nline = len_trim(line)
      call sic_analyse(acomm,line,nline,error)
    endif
  else
    if (hself_self%loca%size.eq.0) then
      call map_message(seve%e,comm,'/RESTORE  Self calibrated UV data not defined')
      error = .true.
    else if (sic_narg(opt_rang).ge.0) then
      call map_message(seve%e,comm,'/RESTORE  conflicts with /RANGE')
      error = .true.
    endif
  endif
  if (error) return
  call gildas_null(huv_tmp,type='UVT')
  call uv_buffer_finduv(code)
  call gdf_copy_header(huv_current,huv_tmp,error)
  call gdf_copy_header(hself_self,huv_current,error)
    if (debug.gt.0) then
      call uvdebug_pointers(comm,'hself_self ',hself_self)
      call uvdebug_pointers(comm,'hself_raw  ',hself_raw)
      call uvdebug_pointers(comm,'Huv    ',huv_current)
    endif
  duv => duvself ! SG Probably WRONG 
  ! ! call uv_dump_buffers('SELFCAL')
  !
  if (.not.do_cct) then ! UV_SELF only case
    if (huv_current%gil%column_pointer(code_uvt_xoff).ne.0) then
      call map_message(seve%i,'UV_MOSAIC','UV data is a Pointing Mosaic',seve%e)
    else if (huv_current%gil%column_pointer(code_uvt_loff).ne.0) then
      call map_message(seve%i,'UV_MOSAIC','UV data is a Phase Mosaic',seve%e)
    else if (huv_current%gil%column_pointer(code_uvt_id).ne.0) then
      call map_message(seve%i,'UV_MOSAIC','UV data is a Mosaic with field ID',seve%e)
    else
      call map_message(seve%w,'UV_MOSAIC','UV data is a Mosaic of unknown type',seve%e)
    endif
    !
    ! Shift and Convert to Pointing offsets only (common Phase center) if needed
    if ((huv_current%gil%column_pointer(code_uvt_id).eq.0).and.(do_init)) then
      ! The question is which UV data is being shifted ? 
      ! The RAW one ?  The Line one ? The compressed one ? 
      call sub_shift_mosaic(line,comm,hself_self,themap,error)
      if (error) then
        themap%nfields = saved_nfields
        return
      endif
      !
      ! Copy back headers since Column types may have changed
      call gdf_copy_header(huv_current,hself_self,error)
      call uv_buffer_finduv(new_code)
    endif
    !
    ! This should be done on the HRAW data also if different from the HSELF one
    if (hself_raw%gil%nchan.ne.1) then
      call map_message(seve%w,comm,'Shifting RAW mosaic also ',seve%e)
      call sub_shift_mosaic(line,comm,hself_raw,themap,error)
    endif
    call mosaic_uvmap('UV_MOSAIC',line,hself_self,error)     ! Image
    do_continuum = .false.  ! Next CLEAN will be no CONTINUUM
    !
  else ! UV_SELF /RESTORE case
    !
    ! Here, MOSAIC_RESTORE should work because the UV table is already sorted...
    call map_message(seve%w,comm,'UV data is a Mosaic, under test...')
    !   The UV table is a priori already sorted & shifted
    !        call uv_shift_mosaic(line,'UV_MOSAIC',error)  ! Convert to Pointing offsets
    !        if (error) return
    call mosaic_restore(line,hself_self,error)
  endif
  defmap_center = string          ! Restore MAP_CENTER
  if (debug.gt.1) call uv_dump_buffers('UV_SELF_MOSAIC -- Before reset')
  call uv_buffer_resetuv(code)
  ! ! call gdf_print_header(huv_current)
  ! ! Print *,'UVSELF Header '
  if (debug.gt.1) call uv_dump_buffers('UV_SELF_MOSAIC -- At end')
  call gdf_copy_header(huv_tmp,huv_current,err)
  if (debug.gt.0) call uvdebug_pointers(comm,'hself_self ',hself_self)
  !
  themap%nfields = saved_nfields ! Restore the initial status of UV data
  if (error) return
  do_self = .true.
  !
  call map_message(seve%t,comm,'Uv_Self_Mosaic Ending',-2)
end subroutine uv_self_mosaic
