subroutine mos_primary (prim,primary,bsize)
  !
  ! Mosaic and Primary beam support
  ! Compute a Gaussian primary beam
  !
  use image_def
  use gkernel_interfaces
  use gkernel_types
  type(gildas), intent(in) :: prim         ! Primary beam header
  real, intent(inout) :: primary(prim%gil%dim(1),prim%gil%dim(2)) ! Values
  real, intent(in) :: bsize                ! Primary beam size in radian
  !
  ! Local
  real :: offx,offy,beamx,beamy
  real, allocatable :: factorx(:),factory(:)
  real(8) :: doffx, doffy
  integer :: j, ier
  type(projection_t) :: proj
  logical :: error
  !
  allocate (factory(prim%gil%dim(2)), factorx(prim%gil%dim(1)), stat=ier)
  !
  error = .false.
  call gwcs_projec(prim%gil%a0,prim%gil%d0,prim%gil%pang,prim%gil%ptyp,proj,error)
  call abs_to_rel(proj,prim%gil%ra,prim%gil%dec,doffx,doffy,1)
  offx = doffx/prim%gil%inc(1)
  offy = doffy/prim%gil%inc(2)
  !
  beamx = prim%gil%inc(1)/bsize*2.0*sqrt(log(2.0))
  beamy = prim%gil%inc(2)/bsize*2.0*sqrt(log(2.0))
  !
  do j=1,prim%gil%dim(2)
     factory(j) = exp(-((j-prim%gil%ref(2)-offy)*beamy)**2)
  enddo
  !
  do j=1,prim%gil%dim(1)
     factorx(j) = exp(-((j-prim%gil%ref(1)-offx)*beamx)**2)
  enddo
  !
  do j=1,prim%gil%dim(2)
     primary(:,j) = factorx * factory(j)
  enddo
  deallocate (factorx, factory)
end subroutine mos_primary
!
subroutine mos_inverse (n,weight,thre)
  integer, intent(in) :: n
  real, intent(inout) :: weight(n)
  real, intent(in) :: thre
  ! Local
  integer :: i
  !
  do i=1,n
    if (weight(i).ge.thre) then
      weight(i) = 1.0/weight(i)
    else
      weight(i) = 10.0
    endif
  enddo
end subroutine mos_inverse
!
subroutine mos_addsq (n,nf,weight,lobe)
  integer, intent(in) :: n                      ! Size of arrays
  integer, intent(in) :: nf                     ! Number of fields
  real, intent(inout) :: weight(n)              ! Total weight
  real, intent(in) :: lobe(nf,n)                ! Primary beam array
  ! Local
  integer :: i,if
  !
  do i=1,n
    do if=1,nf
      weight(i) = weight(i)+lobe(if,i)*lobe(if,i)
    enddo
  enddo
end subroutine mos_addsq
!
subroutine mosaic_loadfield (visi,np,nv,ixoff,iyoff,nf,doff,voff,uvmax,uvmin)
  !----------------------------------------------------------------------
  ! @ public-mandatory
  !
  ! MAP    MOSAIC routines
  !     Load field coordinates into work arrays after sorting.
  !----------------------------------------------------------------------
  integer, intent(in)  :: np                   ! Size of a visibility
  integer, intent(in)  :: nv                   ! Number of visibilities
  real, intent(in) :: visi(np,nv)              ! Input visibilities
  integer, intent(in)  :: ixoff                ! X pointer
  integer, intent(in)  :: iyoff                ! Y pointer
  integer, intent(out) :: nf                   ! Number of fields
  real(kind=4), intent(out), allocatable :: doff(:,:)  ! Fields offsets
  integer, intent(out), allocatable :: voff(:)  ! Fields visibility offsets
  real, intent(inout) :: uvmax    ! Maximum length
  real, intent(inout) :: uvmin    ! Minimum baseline
  !
  integer :: iv, mfi, nfi, ier
  real(4) :: uv
  real(kind=4), allocatable :: dtmp(:,:)
  integer, allocatable :: vtmp(:)
  !
  ! Scan how many fields
  nfi = 1
  mfi = 100
  uvmax = 0
  uvmin = 1e36
  !
  allocate(dtmp(2,mfi),vtmp(mfi),stat=ier)
  dtmp(1,1) = visi(ixoff,1)
  dtmp(2,1) = visi(iyoff,1)
  vtmp(1) = 1
  nfi = 1
  !
  ! Fields are ordered here, so any change is a new one
  do iv=2,nv
    if (visi(ixoff,iv).ne.dtmp(1,nfi) .or. &
      & visi(iyoff,iv).ne.dtmp(2,nfi) ) then
      !
      ! New field
      if (nfi.eq.mfi) then
        allocate(doff(2,nfi),voff(nfi),stat=ier)
        doff(:,:) = dtmp(:,:)
        voff(:) = vtmp(:)
        deallocate(dtmp,vtmp)
        mfi = 2*mfi
        allocate(dtmp(2,mfi),vtmp(mfi),stat=ier)
        dtmp(:,1:nfi) = doff(:,:)
        vtmp(1:nfi) = voff
        deallocate(doff,voff)
      endif
      !
      nfi = nfi+1
      dtmp(1,nfi) = visi(ixoff,iv)
      dtmp(2,nfi) = visi(iyoff,iv)
      vtmp(nfi) = iv
    endif
    !
    uv = visi(1,iv)**2 + visi(2,iv)**2
    if (uv.ne.0) then
      uvmax = max(uv,uvmax)
      uvmin = min(uv,uvmin)
    endif
    !
  enddo
  !
  ! And put everything in place
  nf = nfi
  allocate(doff(2,nf),voff(nf+1),stat=ier)
  doff(:,:) = dtmp(:,1:nfi)
  voff(1:nfi) = vtmp(1:nfi)
  ! And set the last one
  voff(nfi+1) = nv+1
  deallocate(dtmp)
  !
  uvmax = sqrt(uvmax)
  uvmin = sqrt(uvmin)
end subroutine mosaic_loadfield
!
subroutine mosaic_getfields (visi,np,nv,ixoff,iyoff,nf,doff)
  !----------------------------------------------------------------------
  ! @ public-mandatory
  !
  ! MAP    MOSAIC routines
  !     Count number of fields and Get their coordinates
  !----------------------------------------------------------------------
  integer, intent(in)  :: np                   ! Size of a visibility
  integer, intent(in)  :: nv                   ! Number of visibilities
  real, intent(inout)  :: visi(np,nv)              ! Input visibilities
  integer, intent(in)  :: ixoff                ! X pointer
  integer, intent(in)  :: iyoff                ! Y pointer
  integer, intent(out) :: nf                   ! Number of fields
  real, intent(out), allocatable :: doff(:,:)  ! Field offsets
  !
  integer :: iv, mfi, nfi, kfi, ifi, ier
  real(kind=4), allocatable :: dtmp(:,:)
  real(kind=4) :: off_tol
  !
  if (nv.le.0) then
    nf = 0
    return
  endif
  !
  ! Scan how many fields
  !
  off_tol = 1E-2*acos(-1.0)/180.0/3600.0       ! 0.01 sec is enough
  nfi = 1
  mfi = 100
  !
  allocate(dtmp(2,mfi),stat=ier)
  dtmp(1,1) = visi(ixoff,1)
  dtmp(2,1) = visi(iyoff,1)
  nfi = 1
  !
  ! Fields are not ordered here
  do iv=2,nv
    kfi = 0
    do ifi=1,nfi
      if (abs(visi(ixoff,iv)-dtmp(1,ifi)).le.off_tol .and. &
        & abs(visi(iyoff,iv)-dtmp(2,ifi)).le.off_tol ) then
        visi(ixoff,iv) = dtmp(1,ifi)
        visi(iyoff,iv) = dtmp(2,ifi)
        kfi = ifi
        exit
      endif
    enddo
    !
    ! New field
    if (kfi.eq.0) then
      if (nfi.eq.mfi) then
        allocate(doff(2,mfi),stat=ier)
        doff(:,:) = dtmp(:,:)
        deallocate(dtmp)
        allocate(dtmp(2,2*mfi),stat=ier)
        dtmp(:,1:mfi) = doff
        deallocate(doff)
        mfi = 2*mfi
      endif
      nfi = nfi+1
      dtmp(1,nfi) = visi(ixoff,iv)
      dtmp(2,nfi) = visi(iyoff,iv)
    endif
  enddo
  !
  nf = nfi
  allocate(doff(2,nf),stat=ier)
  doff(:,:) = dtmp(1:2,1:nf)
end subroutine mosaic_getfields

