!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module uv_restore
  use gbl_message
  !
  public :: uv_restore_comm
  private
  !
contains
  !
  subroutine uv_restore_comm(line,error)
    use uvmap_tool
    use uvmap_buffers, only: uvmap_prog
    use clean_types, only: beam_unit_conversion
    use clean_buffers, only: clean_user,clean_prog
    !-------------------------------------------------------------------
    ! Support routine for command
    !     UV_RESTORE
    !-------------------------------------------------------------------
    character(len=*), intent(in)    :: line
    logical,          intent(inout) :: error
    !
    if (uvmap_prog%nfields.ne.0) then
       call map_message(seve%w,'UV_RESTORE','UV data is a Mosaic, under test...')
       call uv_restore_mosaic(line,error)
    else
       call beam_unit_conversion(clean_user)
       call clean_user%copyto(clean_prog)
       call uvmap_main('UV_RESTORE',line,error)
    endif
  end subroutine uv_restore_comm
    !
  subroutine uv_restore_mosaic(line,error)
    use image_def
    use gkernel_interfaces
    use uv_residual, only: uv_residual_main
    use uvmosaic_tool, only: uvmosaic_main
    use file_buffers
    use uv_buffers
    use uvmap_buffers
    use clean_buffers
    !---------------------------------------------------------------------
    ! Restore a mosaic image
    !
    ! Required input
    !   the CCT table
    !   the RESIDUAL image (obtained by imaging the UV table obtained by UV_RESIDUAL)
    !   the PRIMARY beams
    ! Output 
    !   the restored CLEAN image
    !---------------------------------------------------------------------
    character(len=*), intent(in)    :: line
    logical,          intent(inout) :: error
    !
    logical :: zero,err
    integer :: nx,ny,np,nc,ic,ip,ier
    real :: wr2,ws2,wmin
    real, pointer :: prima(:,:,:)
    real, pointer :: myresid(:,:)
    real, pointer :: myclean(:,:)
    real, pointer :: duv_previous(:,:), duv_next(:,:)
    real, allocatable :: response(:,:)
    type(gildas) :: huv_save
    character(len=*), parameter :: rname='MOSAIC_RESTORE'
    !
    ! Compute the primary beams if not done
    if (primbeam%head%loca%size.eq.0) then
       call map_message(seve%e,rname,'Primary beams undefined')
       error = .true.
       return
    endif
    !
    call gildas_null(huv_save,type='UVT')
    call gdf_copy_header(huv, huv_save, error)
    !
    ! Compute the UV Residual and the pure CLEAN part
    nullify (duv_previous, duv_next)
    call uv_residual_main(rname,line,duv_previous,duv_next,.true.,error)
    if (error) return
    !
    ! Associate DUV and HUV to the UV Residual
    duv => duv_next
    ! Resize UV data  
    huv%gil%nvisi = ubound(duv,2)
    huv%gil%dim(2) = huv%gil%nvisi
    !
    ! Perform the Imaging
    call uvmosaic_main(rname,line,error)
    if (error) return
    !
    ! At this stage : DIRTY is the RESIDUAL...
    call gdf_copy_header(dirty%head,resid%head,error)
    if (error) return
    resid%head%r3d => resid%data
    !
    prima => primbeam%data(:,:,:,1)
    np = primbeam%head%gil%dim(1)
    nc = resid%head%gil%dim(3)
    ny = resid%head%gil%dim(2)
    nx = resid%head%gil%dim(1)
    !
    ! Compute the "weight" function 1/N
    wmin = 0.01    ! Hum ?
    ws2 =  0.0     ! Search weight
    wr2 =  0.04    ! Restore weight 20 % level of primary beam
    allocate(response(nx,ny),stat=ier)
    !
    response = 0
    do ip=1,np
       response(:,:) = response(:,:)+prima(ip,:,:)**2
    enddo
    where (response.gt.wr2) 
       response = 1.0/response
    else where
       response = 0.0
    end where
    !
    ! For test, can reset DCLEAN or RESID
    zero = .false.
    call sic_get_logi('ZERO_CLEAN',zero,err)
    if (zero) clean%data = 0.0
    zero = .false.
    call sic_get_logi('ZERO_RESID',zero,err)
    if (zero) resid%data = 0.0
    !
    ! Loop on channels
    do ic=1,nc
       myresid => resid%head%r3d(:,:,ic)
       myclean => clean%head%r3d(:,:,ic)
       ! Mosaic case
       myclean = myclean + myresid*response
       where (response.eq.0) myclean = clean%head%gil%bval ! Undefined pixel there
    enddo
    !
    call sic_delvariable('CLEAN',.false.,error)
    ! Redefine CLEAN data set 
    call sic_mapgildas('CLEAN',clean%head,error,clean%data)! Clean buffers
    clean%head%loca%size = dirty%head%loca%size
    !
    ! 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(rname//' before')
       !print *,'Discarding UV buffers '
       call uv_discard_buffers(duv_previous, duv_next, error)
       !call uv_dump_buffers(rname//' after')
       call gdf_copy_header(huv_save,huv,error)
       !
    else
       call map_message(seve%w,rname,'Keeping UV residuals')
       call uv_clean_buffers(duv_previous, duv_next,error)
       if (error) return
       !
       if (allocated(uvtb%data)) deallocate (uvtb%data)            ! UV data not plotted
       uv_plotted = .false.
       !
       ! Indicate optimization and save status
       optimize(code_save_uv)%change = optimize(code_save_uv)%change + 1
       save_data(code_save_uv) = .true.
       !
       ! Not needed here: weights are unchanged
       ! do_weig = .true.  ! Recompute weight 
       !
       ! Resize UV data and redefine SIC variables 
       huv%gil%nvisi = ubound(duv,2)
       huv%gil%dim(2) = huv%gil%nvisi
       !
       call sic_delvariable('UV',.false.,error)
       call sic_mapgildas('UV',huv,error,duv) 
    endif
  end subroutine uv_restore_mosaic
end module uv_restore
! 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
