subroutine init_kernel(ker,mk,nk,smooth)
  !-----------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER --  Support for MULTISCALE clean
  !
  !   Initialize a smoothing Kernel by a Gaussian shape
  !!
  !-----------------------------------------------------------------------
  integer, intent(in) :: mk            !! Kernel size
  integer, intent(in) :: nk            !! Kernel size
  real(4), intent(inout) :: ker(mk,mk) !! Kernel, centered on (NK+1)/2
  real(4), intent(in) :: smooth        !! Smoothing factor
  !
  ! Local ---
  integer :: i,j
  real :: lk,r,s2,sker
  !
  ! Code ----
  if (nk.eq.1) then     ! Dirac
    ker(1,1) = 1.
    return
  endif
  if (smooth.eq.0) then ! Constant box
    ker = 1.0/(nk*nk)
    return
  endif
  !
  ! Discret Gaussian kernel
  lk = (nk+1.0)/2.0
  s2 = 1.0/smooth**2
  sker = 0.0
  ker = 0.0
  do j=1,nk
    do i=1,nk
      r = (i-lk)**2 + (j-lk)**2
      r = r*s2
      ker(i,j) = exp(-r)
      sker = sker+ker(i,j)
    enddo
  enddo
  sker = 1.0/sker
  ker = ker * sker
  !! Print *,'Kernel ratio ',minval(ker)/maxval(ker)
end subroutine init_kernel
!
subroutine smooth_mask (mask,smask,nx,ny,nk)
  !-----------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER --  Support for MULTISCALE clean
  !
  !   Enlarge a mask using a kernel, based only on kernel size
  !!
  !-----------------------------------------------------------------------
  integer, intent(in) :: nx             !! X size
  integer, intent(in) :: ny             !! Y size
  logical, intent(in) :: mask(nx,ny)    !! Input array
  logical, intent(out) :: smask(nx,ny)  !! Smoothed array
  integer, intent(in) :: nk             !! kernel size
  !
  ! Local ---
  integer i,j,lk,lj,li
  !
  ! Code ----
  if (nk.eq.1) then
    smask = mask
  else
    smask = mask
    lk = (nk+1)/2
    do j=lk,ny-lk+1
      do i=lk,nx-lk+1
        if (.not.smask(i,j)) then
          do lj=1,nk
            do li=1,nk
              if (mask(i-li+lk,j-lj+lk)) then
                smask(i,j) = .true.
              endif
            enddo
          enddo
        endif
      enddo
    enddo
  endif
end subroutine smooth_mask
!
subroutine smooth_kernel (array,sarray,nx,ny,mk,nk,ker)
  !-----------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER --  Support for MULTISCALE clean
  !
  !   Smooth an array using a kernel.
  ! Parallel programming is useful here
  !!
  !-----------------------------------------------------------------------
  integer, intent(in) :: nx             !! X size
  integer, intent(in) :: ny             !! Y size
  real, intent(in) :: array(nx,ny)      !! Input array
  real, intent(out) :: sarray(nx,ny)    !! Smoothed array
  integer, intent(in) :: nk             !! Actual Kernel size
  integer, intent(in) :: mk             !! Kernel dimensions
  real, intent(in) :: ker(mk,mk)        !! Smoothing kernel, centered on (nk+1)/2
  !
  integer, external :: ompget_inner_threads
  !
  ! Local ---
  integer nthread
  integer i,j,lk,lj,li
  !
  ! Code ----
  if (nk.eq.1) then
    sarray = array
  else
    nthread = ompget_inner_threads()
    sarray = 0.      ! Mandatory
    lk = (nk+1)/2
    !$OMP PARALLEL PRIVATE(lj,j,li,i) NUM_THREADS(nthread)
    !$OMP DO COLLAPSE(2)
    do j=lk,ny-lk+1
      do i=lk,nx-lk+1
        do lj=1,nk
          do li=1,nk
            sarray(i,j) = sarray(i,j)+ker(li,lj)   &
    &              *array(i-li+lk,j-lj+lk)
          enddo
        enddo
      enddo
    enddo
    !$OMP END DO
    !$OMP END PARALLEL
  endif
end subroutine smooth_kernel
!
subroutine smooth_masked (nx,ny,sarray,array,mask,mk,nk,ker)
  !-----------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER -- Support for MULTISCALE
  !
  !   Smooth an array using a kernel, but only in a mask.
  ! Parallel programming is useful here
  !!
  !-----------------------------------------------------------------------
  integer, intent(in) :: nx             !! X size
  integer, intent(in) :: ny             !! Y size
  real, intent(in) :: array(nx,ny)      !! Input array
  real, intent(out) :: sarray(nx,ny)    !! Smoothed array
  logical, intent(in) :: mask(nx,ny)    !! Valid area
  integer, intent(in) :: mk             !! Kernel array size
  integer, intent(in) :: nk             !! Kernel actual size
  real, intent(in) :: ker(mk,mk)        !! Smoothing kernel, centered on (nk+1)/2
  !
  integer, external :: ompget_inner_threads
  !
  ! Local
  integer nthread
  integer i,j,lk,lj,li,ii,jj
  !
  ! Code
  if (nk.eq.1) then
    sarray = array
  else
    nthread = ompget_inner_threads()
    sarray = 0.0  ! Mandatory
    !
    lk = (nk+1)/2
    !$OMP PARALLEL PRIVATE(i,j,lj,jj,li,ii) NUM_THREADS(nthread)
    !$OMP DO COLLAPSE(2)
    do j=lk,ny-lk+1
      do i=lk,nx-lk+1
        if (mask(i,j)) then
          do lj=1,nk
            jj = j-lj+lk
            do li=1,nk
              ii = i-li+lk
              sarray(i,j) = sarray(i,j)+ker(li,lj)*array(ii,jj)
            enddo
          enddo
        endif
      enddo
    enddo
    !$OMP END DO
    !$OMP END PARALLEL
  endif
end subroutine smooth_masked
!
subroutine add_kernel (clean,nx,ny,value,kx,ky,mk,nk,ker)
  !-----------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER  -- Support for MULTISCALE Clean
  !
  !   Spread a value using a Kernel and add it to result
  ! 
  !   Parallel programming does not help here, as the Kernel is small
  !!
  !-----------------------------------------------------------------------
  integer, intent(in) :: nx           !! X Image size
  integer, intent(in) :: ny           !! Y Image size
  real, intent(inout) :: clean(nx,ny) !! Summed output array
  real, intent(in) :: value           !! Input value
  integer, intent(in) :: kx           !! X Center of value
  integer, intent(in) :: ky           !! Y Center of value
  integer, intent(in) :: mk           !! Kernel  array size
  integer, intent(in) :: nk           !! Kernel actual size
  real, intent(in) :: ker(mk,mk)      !! Smoothing kernel, centered on (nk+1)/2
  !
  ! Local ---
  integer i,j,lk,li,lj
  !
  ! Code ----
  if (nk.eq.1) then
    clean(kx,ky) = clean(kx,ky) + value
  else
    lk = (nk-1)/2
    do j=ky-lk,ky+lk
      lj = j-ky+lk+1
      do i=kx-lk,kx+lk
        li = i-kx+lk+1
        clean(i,j) = clean(i,j) + ker (li,lj) * value
      enddo
    enddo
  endif
end subroutine add_kernel
!
subroutine amaxmask (a,mask,nx,ny,ix,iy)
  !-----------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER -- Support for deconvolution
  !
  !     Search the absolute maximum, in a masked region
  !
  ! Parallel programming does not help  here.
  !!
  !-----------------------------------------------------------------------
  integer, intent(in) :: nx           !! X size
  integer, intent(in) :: ny           !! Y size
  real, intent(in) :: a(nx,ny)        !! Values
  logical, intent(in) :: mask(nx,ny)  !! Mask
  integer, intent(out) :: ix          !! X position of max
  integer, intent(out) :: iy          !! Y position of max
  !
  ! Local ---
  real rmax
  integer i,j
  !
  ! Code ----
  rmax = -1.0
  ix = 1
  iy = 1
  do j=1,ny
    do i=1,nx
      if (mask(i,j)) then
        if (abs(a(i,j)).gt.rmax) then
          rmax = abs(a(i,j))
          ix = i
          iy = j
        endif
      endif
    enddo
  enddo  
end subroutine amaxmask
!
subroutine translate (in, nx, ny, trans, ix, jy)
  !-----------------------------------------------------------------------
  ! @ private
  !
  !!     Translate an Array by IX, IY
  !-----------------------------------------------------------------------
  integer, intent(in) :: nx          !! X size
  integer, intent(in) :: ny          !! Y size
  real, intent(in) :: in(nx,ny)      !! Input beam
  real, intent(out) :: trans(nx,ny)  !! Translated beam
  integer, intent(in) :: ix          !! X shift
  integer, intent(in) :: jy          !! Y shift
  !
  ! Local ---
  integer :: i,j
  !
  ! Code ----
  trans = 0.0  
  do j=max(1,jy+1),min(ny,ny+jy)
    do i=max(1,ix+1),min(nx,nx+ix)
      trans(i,j) = in(i-ix,j-jy)
    enddo
  enddo
end subroutine translate
!
subroutine spread_kernel (nx,ny,ip,nc,dcct,value,kx,ky,nk,ker)
  !-----------------------------------------------------------------------
  ! @ public-mandatory
  !
  ! IMAGER -- Support for MULTISCALE Clean
  !
  !   Spread a value using a Kernel and add it to result
  !!
  !-----------------------------------------------------------------------
  integer, intent(in) :: nx           !! X Image size
  integer, intent(in) :: ny           !! Y Image size
  integer, intent(in) :: ip           !! Plane number 
  integer, intent(inout) :: nc        !! Number of clean components
  real, intent(out) :: dcct(:,:,:)    !! Expanded Clean Components 
  real, intent(in) :: value           !! Input value
  integer, intent(in) :: kx           !! X Center of value
  integer, intent(in) :: ky           !! Y Center of value
  integer, intent(in) :: nk           !! Actual Kernel size
  real, intent(in) :: ker(:,:)        !! Smoothing kernel, centered on (nk+1)/2
  !
  ! Local ---
  integer :: ix,iy,j,li,lj,lk
  !
  ! Code ----
  j = nc 
  if (nk.eq.1) then
    j = j+1
    dcct(1,ip,j) = kx
    dcct(2,ip,j) = ky
    dcct(3,ip,j) = value 
  else
    lk = (nk-1)/2
    do lj=-lk,lk
      iy = ky+lj
      if (iy.gt.0 .and. iy.le.ny) then
        do li=-lk,lk
          ix = kx+li
          if (ix.gt.0 .and. ix.le.nx) then
            j = j+1
            dcct(1,ip,j) = ix
            dcct(2,ip,j) = iy
            dcct(3,ip,j) = value * ker(li+(nk+1)/2,lj+(nk+1)/2)
          endif
        enddo
      endif
    enddo
  endif
  !
  nc = j
end subroutine spread_kernel
!
subroutine multi_shift(ip,ox,oy,px,py)
  use clean_arrays
  !------------------------------------------------------
  ! @ private
  !*
  !   IMAGER -- Support for Mosaics
  !
  !     Temporary routine to define the pixel offsets.
  !   The relevant information may have to go into a module
  !   
  !   No longer used ...
  !!
  !------------------------------------------------------
  integer, intent(in) :: ip   !! Field number
  integer, intent(out) :: ox  !! Offset in X
  integer, intent(out) :: oy  !! Offset in Y
  integer, intent(out) :: px  !! Offset in X
  integer, intent(out) :: py  !! Offset in Y
  !!
  ox = 0
  oy = 0
  px = hprim%gil%dim(2)
  py = hprim%gil%dim(3)
  !
  if (.not.allocated(huv_current%mos%fields)) return
  ox = huv_current%mos%fields(ip)%jxy(1)
  oy = huv_current%mos%fields(ip)%jxy(2)
end subroutine multi_shift
  
