!>
! This file is a collection of PUBLIC entries of IMAGER 
! which must not refer to any SIC-GREG-GTV routines
!!
subroutine telescope_beam(rname,bsize,head)
  use gkernel_interfaces
  use imager_interfaces, only: map_message
  use image_def
  use gbl_message
  !---------------------------------------------------------------------
  ! @ public
  !
  !! IMAGER --  Get telescope beamsize for the frequency of a GILDAS data set
  !---------------------------------------------------------------------  
  character(len=*), intent(in) :: rname !! Caller name
  real, intent(inout) :: bsize(:)       !! Primary beam size
  type(gildas), intent(in) :: head      !! Gildas header
  !
  ! Constants
  integer, parameter :: mteles=7
  real(8), parameter :: clight=299792458d0
  real(8), parameter :: pi=3.14159265358979323846d0
  character(len=12) :: vteles(mteles)
  data vteles /'ACA','ALMA','ATCA','NOEMA','SMA','JVLA','VELETA'/
  real :: factors(mteles), diams(mteles)
  data diams  /7.,12.,20.,15.,6.,25.,30.0/
  ! These factors depend on dish illumination 
  !   Validated for NOEMA and VELETA
  !   Validated for ALMA
  ! unclear for ATCA, SMA and JVLA
  data factors /1.13,1.13,1.13,1.22,1.13,1.13,1.20/
  !
  ! 
  character(len=12) :: cteles,kteles
  character(len=120) :: chain
  integer :: iteles, it
  logical :: error
  real :: diamet, factor, beamsize
  !
  beamsize = 0.0
  !
  if (head%gil%nteles.ne.0) then
    do it=1,head%gil%nteles
      !
      cteles = head%gil%teles(it)%ctele
      if (cteles.eq.'30M') cteles = 'VELETA'
      diamet = head%gil%teles(it)%diam
      kteles = cteles
      call sic_ambigs(' ',cteles,kteles,iteles,vteles,mteles,error)
      call map_message(seve%i,rname,'Found telescope '//trim(kteles)//' from data')
      if (error) then
        factor = 1.13
        call map_message(seve%w,rname,'Using default Beam size 1.13 Lambda/D')
        error = .false.
      else
        factor = factors(iteles)
      endif
      beamsize = factor*(clight/head%gil%freq/1d6)/diamet
      bsize(it) = beamsize
    enddo
  endif
  !
  if (head%gil%nteles.le.1) then
    if (abs(head%gil%type_gdf).eq.abs(code_gdf_uvt)) then
      ! This is to handle old UVT files in which the primary beam size was
      ! given in the "Beam" parameters
      if (head%gil%majo.ne.0) then    
        if (head%gil%mino.eq.0 .or. head%gil%mino.eq.head%gil%majo) then
          bsize(1) = head%gil%majo
          if (beamsize.ne.0) then
            if (abs(beamsize-bsize(1)).gt.0.02*beamsize) then
              write(chain,'(A,F8.1,A,F8.1,A)') 'Using major axis ', &
              &	bsize(1)*180*3600/pi, &
              &   '" instead of Beam size ',beamsize*180*3600/pi,'"'
              call map_message(seve%w,rname,chain)
            endif
          endif
        else if (beamsize.eq.0) then
            write(chain,'(A,F8.1,A,F8.1,A)') & 
            & 'Inconsistent primary beam major axis (', & 
            & head%gil%majo*180*3600/pi,'") and minor axis ', &
            & head%gil%mino*180*3600/pi,'")'
            call map_message(seve%w,rname,chain)
        endif
      endif
    endif
  endif
  !
end subroutine telescope_beam
!
subroutine no_major_plot (method,head   &
     &    ,conv,niter,nx,ny,np,tcc  &
     &    ,clean,resid,poids)
  use clean_def
  use image_def
  !---------------------------------------------------------------------
  ! @ public
  !!
  ! IMAGER  -- Support for CLEAN
  !
  !   Dummy replacement of "major_plot". 
  !   Do not Plot result of Major Cycle
  !!
  !---------------------------------------------------------------------
  type (clean_par), intent(inout) :: method
  type (gildas), intent(in) :: head
  !
  logical, intent(in) ::  conv          !! Convergence status
  integer, intent(in) ::  niter         !! Number of iterations
  integer, intent(in) ::  nx            !! X size
  integer, intent(in) ::  ny            !! Y size
  integer, intent(in) ::  np            !! Number of planes
  real, intent(in) :: clean(nx,ny)      !! Clean image
  real, intent(in) :: resid(nx,ny)      !! Residuals
  real, intent(in) :: poids(nx,ny)      !! Weight image
  type (cct_par), intent(in) :: tcc(niter)
  !
  return
end subroutine no_major_plot
!
subroutine no_next_flux(niter,cum,is)
  !---------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER -- Support for Clean 
  !
  !   Dummy replacement of "next_flux". 
  !   Do not draw in the <FLUX window
  !!
  !---------------------------------------------------------------------
  integer, intent(in) :: niter
  real, intent(in) :: cum
  integer :: is
end subroutine no_next_flux
!
!
subroutine no_remask(method,head,nl,error)
  use clean_def
  use image_def
  !---------------------------------------------------------------------
  ! @ public
  !
  ! IMAGER -- Support for Clean 
  !
  ! Dummy replacement of "remask"
  !!
  !---------------------------------------------------------------------
  type (clean_par), intent(in) :: method
  type (gildas), intent(in) :: head
  integer, intent(in) :: nl
  logical, intent(in) :: error
  !
end subroutine no_remask
!
!
subroutine get_maskplane(amethod,hmask,hdirty,mask,list)
  use clean_def
  use image_def
  use gbl_message
  use clean_support
  use gkernel_interfaces
  use imager_interfaces, except_this => get_maskplane 
  !---------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Support for CLEAN
  !
  !   Get mask plane method%imask corresponding to current channel, as 
  !   defined in method%iplane
  !!
  !---------------------------------------------------------------------
  type (clean_par), intent(inout) :: amethod     !! Clean method parameters
  type (gildas), intent(in) :: hmask             !! Mask Header
  type (gildas), intent(in) :: hdirty            !! Used to figure out which plane
  logical, intent(inout) :: mask(:,:)            !! Current logical mask
  integer, intent(inout) :: list(:)              !! Selected list of pixels
  !
  ! Local ---
  integer :: iplane, nxy
  real(8) :: i_freq
  !
  ! Code ----
  if (support_type.ne.support_mask) return
  !
  if (hmask%gil%dim(3).le.1) then
    !!Print *,'Only one mask Plane '
    amethod%imask = 1
    return ! 
  else 
    i_freq = (amethod%iplane-hdirty%gil%ref(3))*hdirty%gil%fres + hdirty%gil%freq
    iplane = nint((i_freq-hmask%gil%freq)/hmask%gil%fres + hmask%gil%ref(3))
    iplane = min(max(1,iplane),hmask%gil%dim(3)) ! Just  in case
    !!Print *,'IPLANE ',iplane,' IMASK ',method%imask
    !
    ! Should also work in OMP mode...
    if (amethod%imask.ne.iplane) then
      !
      ! Optimize: only re-define if needed...
      nxy = hdirty%gil%dim(1)*hdirty%gil%dim(2)
      call get_lmask (hmask,hmask%r3d(:,:,iplane:iplane),hdirty,mask,amethod%box)
      call lmask_to_list(mask,nxy,list,amethod%nlist)
      amethod%imask = iplane
    endif
  endif
end subroutine get_maskplane
!
subroutine get_rlist (rmsk,nx,ny,box,list,nl)
  !---------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER -- Utility routine
  !
  !     Return a List of selected pixels from a (0 - non zero) real mask, 
  ! and also computes its boundaries
  !!
  !---------------------------------------------------------------------
  integer, intent(in) :: nx                       !! X size
  integer, intent(in) :: ny                       !! Y size
  real(kind=4), intent(in) :: rmsk(nx,ny)         !! Real mask
  integer, intent(out) :: box(4)                  !! Mask Boundary
  integer, intent(out) :: list(nx*ny)             !! List of pixels in mask
  integer, intent(out) :: nl          !! Number of selected pixels in list
  !
  ! Local ---
  integer :: i,j,k,l
  !
  ! Code ----
  box(1) = nx
  box(2) = ny
  box(3) = 1
  box(4) = 1
  !
  l = 0
  k = 0
  do j=1,ny
    do i=1,nx
      k = k+1
      if (rmsk(i,j).ne.0) then
        box(1) = min(i,box(1))
        box(2) = min(j,box(2))
        box(3) = max(i,box(3))
        box(4) = max(j,box(4))
        l = l+1
        list(l) = k
      endif
    enddo
  enddo
  nl = l
end subroutine get_rlist
!
subroutine gr4_slmsk (rmsk,lmsk,nx,ny,box)
  !---------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER -- Utility routine
  !
  !     Return a LOGICAL mask from the a (0 - non zero) mask, and also
  !       computes its boundaries
  !!
  !---------------------------------------------------------------------
  integer, intent(in) :: nx                  !! X size
  integer, intent(in) :: ny                  !! Y size
  real(kind=4), intent(in) :: rmsk(nx,ny)    !! Real mask
  logical, intent(out) :: lmsk(nx,ny)        !! Logical mask
  integer, intent(out) :: box(4)             !! Mask boundary (xblc,yblc,xtrc,ytrc)
  !
  ! Local ---
  integer :: i,j
  !
  ! Code ----
  box(1) = nx
  box(2) = ny
  box(3) = 1
  box(4) = 1
  !
  do j=1,ny
    do i=1,nx
      if (rmsk(i,j).ne.0) then
        lmsk(i,j) = .true.
        box(1) = min(i,box(1))
        box(2) = min(j,box(2))
        box(3) = max(i,box(3))
        box(4) = max(j,box(4))
      else
        lmsk(i,j) = .false.
      endif
    enddo
  enddo
end subroutine gr4_slmsk
!
subroutine get_lmask(hmask,rmask,hmap,lmask,box)
  use image_def
  !---------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER -- Support routine for Mask operations
  !
  !     Return a LOGICAL mask from the a (0 - non zero) possibly 3-D mask, 
  !   and also computes its boundaries.
  !     The initial mask (=0 or #0) does not need to match the data: pixel
  !   correspondances is derived from relative coordinates (not absolute).
  !   The LOGICAL mask matches the data pixel per pixel, and is a 2-D mask
  !   resulting from collapsing of the initial 3-D mask 
  !---------------------------------------------------------------------
  type(gildas), intent(in) :: hmask          !! Mask header
  type(gildas), intent(in) :: hmap           !! Map header  
  real(kind=4), intent(in) :: rmask(:,:,:)   !! Real mask
  logical, intent(out) :: lmask(:,:)         !! Logical mask
  integer, intent(out) :: box(4)             !! Mask boundary (xblc,yblc,xtrc,ytrc)
  !
  ! Local ---
  integer :: nx,ny,nz                      ! X,Y,Z size of mask
  integer :: i,j,k,ier
  integer, allocatable :: im(:),jm(:)      ! Pixels in mask matching image pixels
  real(kind=8) :: r
  !
  ! Code ----
  ! We may simplify the call sequence by using size(rmask,A) where A=1,2,3
  nx = hmap%gil%dim(1)
  ny = hmap%gil%dim(2)
  nz = ubound(rmask,3)
  !
  allocate(im(nx),jm(ny),stat=ier)
  !
  do i=1,nx
    r = (i-hmap%gil%ref(1))*hmap%gil%inc(1) + hmap%gil%val(1)
    im(i) = (r-hmask%gil%val(1))/hmask%gil%inc(1) + hmask%gil%ref(1)
    im(i) = max(1,im(i))
    im(i) = min(hmask%gil%dim(1),im(i))
  enddo
  !
  do i=1,ny
    r = (i-hmap%gil%ref(2))*hmap%gil%inc(2) + hmap%gil%val(2)
    jm(i) = (r-hmask%gil%val(2))/hmask%gil%inc(2) + hmask%gil%ref(2)
    jm(i) = max(1,jm(i))
    jm(i) = min(hmask%gil%dim(2),jm(i))
  enddo
  !
  box(1) = nx
  box(2) = ny
  box(3) = 1
  box(4) = 1
  !
  lmask = .false.
  do j=1,ny
    do i=1,nx
      do k=1,nz
        if (rmask(im(i),jm(j),k).ne.0) then
          lmask(i,j) = .true.
          box(1) = min(i,box(1))
          box(2) = min(j,box(2))
          box(3) = max(i,box(3))
          box(4) = max(j,box(4))
        endif
      enddo
    enddo
  enddo
  deallocate(im,jm)
end subroutine get_lmask
