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
  !
  integer :: i,j
  real :: lk,r,s2,sker
  !
  if (nk.eq.1) then
    ker(1,1) = 1.
    return
  endif
  if (smooth.eq.0) then
    ker = 1.0/(nk*nk)
    return
  endif
  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
  !   Only based on kernel size
  !-----------------------------------------------------------------------
  integer, intent(in) :: nx             !
  integer, intent(in) :: ny             !
  logical, intent(in) :: mask(nx,ny)    ! Input array
  logical, intent(out) :: smask(nx,ny)  ! Smoothed array
  integer, intent(in) :: nk             !
  !
  integer i,j,lk,lj,li
  !
  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 (beam,sbeam,nx,ny,mk,nk,ker)
  !-----------------------------------------------------------------------
  ! @ public
  !
  ! MAPPING
  !   Support for MULTISCALE clean
  !   Smooth an array using a kernel
  !
  ! Parallel programming is useful here
  !-----------------------------------------------------------------------
  integer, intent(in) :: nx             !
  integer, intent(in) :: ny             !
  real, intent(in) :: beam(nx,ny)       ! Input array
  real, intent(out) :: sbeam(nx,ny)     ! Smoothed array
  integer, intent(in) :: nk             !
  integer, intent(in) :: mk             !
  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
  !
  if (nk.eq.1) then
    sbeam = beam
  else
    nthread = ompget_inner_threads()
    sbeam = 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
            sbeam(i,j) = sbeam(i,j)+ker(li,lj)   &
    &              *beam(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,sbeam,beam,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             !
  integer, intent(in) :: ny             !
  real, intent(in) :: beam(nx,ny)       ! Input array
  real, intent(out) :: sbeam(nx,ny)     ! Smoothed array
  logical, intent(in) :: mask(nx,ny)    ! Valid area
  integer, intent(in) :: mk             !
  integer, intent(in) :: nk             !
  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
  !
  if (nk.eq.1) then
    sbeam = beam
  else
    nthread = ompget_inner_threads()
    sbeam = 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
              sbeam(i,j) = sbeam(i,j)+ker(li,lj)*beam(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
  !-----------------------------------------------------------------------
  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 size
  integer, intent(in) :: nk           ! Kernel 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,li,lj
  !
  if (nk.eq.1) then
    clean(kx,ky) = clean(kx,ky) + value
  else
    nthread = ompget_inner_threads()
    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
  !
  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, iy)
  !-----------------------------------------------------------------------
  ! @ private
  !
  !     Translate the beam to new position 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) :: iy          ! Y shift
  !
  ! Local
  integer i,j
  !
  trans = 0.0  ! That seemed to have been forgotten until 23-Sep-2009
  ! but this was only a side effect, anyway
  !
  do j=max(1,iy+1),min(ny,ny+iy)
    do i=max(1,ix+1),min(nx,nx+ix)
      trans(i,j) = in(i-ix,j-iy)
    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
  !
  integer ix,iy,j,li,lj,lk
  !
  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
