subroutine mosaic_restore(line,huv_call,error)
  use clean_arrays
  use clean_types
  use clean_default
  use gbl_message
  use gkernel_interfaces
  use imager_interfaces, except_this => mosaic_restore
  !-------------------------------------int--------------------------------
  ! @ private
  !*
  ! IMAGER - Restore (like in UV_RESTORE) a mosaic image
  !
  ! Required input: 
  !   the CCT table  
  !   the RESIDUAL image, obtained either
  !       by imaging the UV table obtained by UV_RESIDUAL,
  !    or by using UV_MAP, computing the residuals "on-the-fly" in the
  !       Sault et al method.
  !   the PRIMARY beams  
  ! Output  
  !   the restored SKY image
  !!
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: line   !! Command line
  type(gildas), intent(inout) :: huv_call   !! UV Header & Data
  logical, intent(inout) :: error           !! Logical error flag
  !
  character(len=*), parameter :: task='MOSAIC_RESTORE'
  type(gildas) :: huv_tmp
  real, pointer :: prima(:,:,:)
  real, pointer :: resid(:,:)
  real, pointer :: clean(:,:)
  real, allocatable, target :: duv_tmp(:,:)
  real, allocatable :: response(:,:)
  integer :: nx,ny,np,nc,ic,ip,ier,nu,nv
  real :: wr, wr2, wmax, outside, old_bmin
  logical :: zero, err
  !
  logical, parameter :: do_clean=.true.
  logical, parameter :: subtract=.true.
  logical, parameter :: use_file=.false.
  integer, parameter :: nblock=1
  logical :: do_resi
  !
  integer :: mcol(2), nb, wcol
  integer :: debug
  !
  call imager_tree('MOSAIC_RESTORE',.false.)
  ! Code ----
  debug = 0
  call sic_get_inte('DEBUG_RESTORE',debug,error)
  if (debug.ne.0) call map_message(seve%i,task,'Calling MOSAIC_RESTORE in mosaic_restore.f90',seve%e)
  if (mosaic_mode.eq.'SAULT') &
    & call map_message(seve%e,task,'Cannot restore Mosaic in SAULT mode (incorrect result)',seve%e)
  !
  error = .false.
  ! Compute the primary beams if not done
  if (hprim%loca%size.eq.0) then
    call map_message(seve%e,task,'Primary beams undefined')
    error = .true.
    return
  endif
  !
  ! At this stage, we may not have a CLEAN image, so we  may derive the stuff from 
  ! the PRIMARY beam, but the CLEAN beam can be undefined
  call sky_as_clean(task,error)
  if (error) return
  if (debug.gt.0) call map_message(seve%i,'MOSAIC_RESTORE','Done SKY_AS_CLEAN',seve%e)
  !
  ! Find out how many beams are required
  call print_buffer_asso('UV Call before UVMAP_COLS',huv_call)
  mcol = huv_call%img%bounds
  wcol = huv_call%img%weight
  nx = hsky%gil%dim(1)
  ny = hsky%gil%dim(2)
  call print_buffer_asso('UV Call before DEFINE_BEAMS',huv_call)
  call define_beams(task,themap%beam,nx,ny,huv_call,mcol,nb,error)
  if (error) return
  !
  call gildas_null(huv_tmp,type='UVT')
  call gdf_copy_header(huv_call, huv_tmp, error)
  !
  ! Compute the UV Residual (if needed) and the pure CLEAN part
  do_resi = huv_call%gil%column_pointer(code_uvt_id).eq.0   &
    & .or. mosaic_mode.eq.'GUETH'
  do_resi = .TRUE.  ! Test -  mosaic_uvmap does the job in all cases...
  !
  ! Extract the range of channels
  call uv_extract_header(huv_tmp, mcol)
  nu = huv_tmp%gil%dim(1)
  nv = huv_tmp%gil%nvisi
  allocate(huv_tmp%r2d(nu,nv),duv_tmp(nu,nv),stat=ier)
  if (ier.ne.0) then
    call map_message(seve%e,task,'UV Tmp allocation error')
    error = .true.
    return
  endif
  call uv_extract_sub(huv_call,huv_tmp,use_file,nblock,mcol,error)
  if (error) return
  !
  huv_tmp%img%bounds = [1,huv_tmp%gil%nchan]
  mcol = huv_tmp%img%bounds
  wcol = huv_call%img%weight-huv_call%img%bounds(1)
  !
  call map_message(seve%i,task,'Computing UV residuals')
  call print_buffer_asso('UV Call before SUB_UV_RESIDUAL',huv_call)
  !
  ! As do_clean is TRUE, Clean components are added to the Residual
  call sub_uv_residual(task,line,0,huv_tmp,huv_tmp%r2d, &
    & duv_tmp,do_clean,do_resi,subtract,error)
  if (error) return
  deallocate(huv_tmp%r2d,stat=ier)
  huv_tmp%r2d => duv_tmp 
  if (debug.gt.0) call map_message(seve%i,task,'Done SUB_UV_RESIDUAL',seve%e)
  !
  call map_message(seve%i,task,'Imaging residuals')
  !
  ! Perform the Imaging
  old_bmin = default_map%truncate
  default_map%truncate = hprim%gil%inc(1)
  !
  ! We use the default "mosaic_uvmap" routine, but use the RESIDUAL image 
  !
  ! We should apply the JvM factor per beam and per field at this stage
  !
  call define_beams(task,themap%beam,nx,ny,huv_tmp,mcol,nb,error)
  if (error) return
  !
  call mosaic_uvmap(task,line,huv_tmp,error)
  if (debug.gt.0) call map_message(seve%i,task,'Done MOSAIC_UVMAP',seve%e)
  nullify(huv_tmp%r2d)
  deallocate(duv_tmp,stat=ier)
  !
  default_map%truncate = old_bmin
  !
  ! At this stage : DIRTY is the RESIDUAL...
  call gdf_copy_header(hdirty,hresid,error)
  hresid%r3d => dresid 
  !
  prima => dprim(:,:,:,1)
  np = hprim%gil%dim(1)
  nc = hresid%gil%dim(3)
  ny = hresid%gil%dim(2)
  nx = hresid%gil%dim(1)
  !
  ! Compute the "weight" function 1/N
  !
  ! Restore weight (default 20 % level of peak response)
  wr = 0.2       !Just in case this is not initialized
  call sic_get_real('CLEAN_TRUNCATE',wr,error)
  wr2 = wr**2 
  allocate(response(nx,ny),stat=ier)
  if (ier.ne.0) then
    call map_message(seve%e,task,'Memory allocation error')
    error = .true.
    return
  endif
  ! This allows CLEAN_TRUNCATE to be negative for tests, so that
  ! noise amplification is limited outside of -CLEAN_TRUNCATE
  if (wr.ge.0.) then  
    outside = 0.0
  else 
    outside = 1.0/wr2 
  endif
  !
  response = 0
  do ip=1,np
    response(:,:) = response(:,:)+prima(ip,:,:)**2
  enddo
  !
  ! The default normalization is to the peak of a single beam,
  ! so that the peak response is in general > 1
  !
  ! We assume WR (CLEAN_TRUNCATE) refers to the peak response
  ! Setting WM = 1 would assume it refers to one Field only, i.e.
  ! the level of one primary beam.
  wmax = maxval(response)
  where (response.gt.wr2*wmax) 
    response = 1./response 
  else where
    response = outside
  end where
  !
  ! For test, can reset CLEAN or RESID, as well as keeping UV residual if needed
  ! This is controlled by user_method%residual (SIC variable CLEAN_RESIDUAL)
  !
  ! Loop on channels
  do ic=1,nc
    resid => hresid%r3d(:,:,ic)
    clean => hsky%r3d(:,:,ic)
    ! Mosaic case
    ! We should apply the JvM factor per beam and per field
    ! This is not possible at this stage, it should be done before
    if (user_method%residual.ne.1) clean = clean + resid*response
    where (response.eq.0) clean = hsky%gil%bval ! Undefined pixel there
  enddo
  !
  call sic_delvariable ('SKY',.false.,error)
  ! Redefine CLEAN data set 
  call sic_mapgildas('SKY',hsky,error,dsky)       ! Clean buffers
  hsky%loca%size = hdirty%loca%size
  !
  if (debug.gt.0) call map_message(seve%i,task,'Done adding residuals',seve%e)
  call cube_minmax('SKY',hsky,error)
  !
  ! Must clean in some way the intermediate UV_BUFFERS and
  ! re-associate the HUV header - Use a new UV_DISCARD_BUFFER tool
  ! to factorize that.
  !
  zero = .false. 
  call sic_get_logi('ZERO_KEEPUV',zero,err)
  !
  if (.not.zero) then
    !call uv_dump_buffers(task//' before')
    !Print *,'Discarding UV buffers '
!!    call uv_discard_buffers(duv_previous, duv_next, error)
    !call uv_dump_buffers(task//' after')
!!    call gdf_copy_header(huv_save,huv_current,error)
    !
  else
    call map_message(seve%w,task,'Keeping UV residuals')
!!    call uv_clean_buffers (duv_previous, duv_next,error)
    if (error) return
    !
    ! Resize UV data and redefine SIC variables 
!!    huv_current%gil%nvisi = ubound(duv,2)
!!    huv_current%gil%dim(2) = huv_current%gil%nvisi
    !
    ! UV data has changed, but no new Weights
!!    call uv_new_data
    !
  endif
  !
!  ! Some how, CLEAN does not work properly after this
! No longer true as far as I know -25-May-2022
!  call map_message(seve%w,task,'--- Temporary: please repeat UV_MAP if a new CLEAN is needed ---')
  call imager_tree('MOSAIC_RESTORE',.true.)
  !  
end subroutine mosaic_restore

subroutine sky_as_clean(rname,error)
  use clean_arrays
  use gbl_message
  use imager_interfaces, only : map_message
  !---------------------------------------------------------------------
  ! @ private
  !
  !! IMAGER --  Create the SKY brightness like the CLEAN image
  !---------------------------------------------------------------------  
  character(len=*), intent(in) :: rname   !! Caller name
  logical, intent(inout) :: error         !! Logical error flag
  !
  integer :: ier
  !
  if (allocated(dsky)) then
    if (any(hsky%gil%dim.ne.hdirty%gil%dim)) then
      ! That may happen if some READ SKY has been done
      ! Print *,'Programming error - Sky & Dirty mismatch'
      deallocate(dsky)
    else
      call map_message(seve%i,rname,'Re-using sky memory')
    endif
    call sic_delvariable('SKY',.false.,error)
  endif
  !
  call gdf_copy_header(hdirty,hsky,error) 
  if (error) return
  hsky%gil%bval = 1.234567E38
  hsky%gil%eval = 0
  hsky%gil%blan_words = 2
  !
  ! Allocate if needed
  if (.not.allocated(dsky)) then
    allocate (dsky(hsky%gil%dim(1), hsky%gil%dim(2), hsky%gil%dim(3)), stat=ier)
    if (ier.ne.0) then
      call map_message(seve%e,rname,'Memory allocation error')
      error = .true.
      return
    endif
  endif
  !
  ! Set the proper pointer
  hsky%r3d => dsky 
  !
end subroutine sky_as_clean

