module mapping_interfaces_public
  interface
    subroutine dofft (np,nv,visi,jx,jy,jo   &
         &    ,nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv   &
         &    ,ubias,vbias,ubuff,vbuff,ctype)
      use gildas_def
      use omp_buffers
      !----------------------------------------------------------------------
      ! @ public
      !
      ! GILDAS  UV_MAP
      !   Compute FFT of image by gridding UV data
      !   Operational version using the fastest method.
      !----------------------------------------------------------------------
      integer, intent(in) :: nv                   ! number of values
      integer, intent(in) :: np                   ! Number of "visibilities", normally 7+3*nc
      real, intent(in) :: visi(np,nv)             ! values
      integer, intent(in) :: nc                   ! number of channels
      integer, intent(in) :: jx                   ! X coord location in VISI
      integer, intent(in) :: jy                   ! Y coord location in VISI
      integer, intent(in) :: jo                   ! first channel to map
      integer, intent(in) :: nx                   ! X map size
      integer, intent(in) :: ny                   ! Y map size
      complex, intent(out) :: map(nc+1,nx,ny)     ! gridded visibilities
      real, intent(in) :: mapx(nx)                ! X Coordinates of grid
      real, intent(in) :: mapy(ny)                ! Y Coordinates of grid
      real, intent(in) :: sup(2)                  ! Support of convolving function in Meters
      real, intent(in) :: cell(2)                 ! cell size in Meters
      real, intent(in) :: taper(4)                ! 1/e taper in Meters + Angle in Radians
      real, intent(in) :: we(nv)                  ! Weight array
      real, intent(in) :: vv(nv)                  ! V Values
      real, intent(in) :: ubias                   ! U gridding offset
      real, intent(in) :: vbias                   ! V gridding offset
      real, intent(in) :: ubuff(4096)             ! U gridding buffer
      real, intent(in) :: vbuff(4096)             ! V gridding buffer
      integer, intent(in) :: ctype                ! type of gridding
    end subroutine dofft
  end interface
  !
  interface
    subroutine doself (model,resul,itype,self,weight)
      !---------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING   UV Tools
      !   Compute self calibraton factor
      !---------------------------------------------------------------------
      complex, intent(in) :: model   ! Model visibility
      complex, intent(in) :: resul   ! Actual observation
      integer, intent(in) :: itype   ! Type of self calibration
      complex, intent(out) :: self   ! Self calibration factor
      real, intent(out) :: weight    ! Weight scaling factor
    end subroutine doself
  end interface
  !
  interface
    subroutine doscal (nc,visi,cosi,sinu,sreel,simag,weight)
      !---------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING   UV Tools
      !	  Apply the self-calibration factor to the current visibility
      !	  Set weight to zero if no self-cal factor
      !---------------------------------------------------------------------
      integer, intent(in) :: nc           !  Number of channels
      real, intent(inout) :: visi(*)      !  Visibility
      real, intent(in) :: sreel           !  Real part to subtract
      real, intent(in) :: simag           !  Imaginary part to subtract
      real, intent(in) :: cosi            !  Phase rotation cos
      real, intent(in) :: sinu            !  Phase rotation sin
      real, intent(in) :: weight          !  Scaling factor of weight
    end subroutine doscal
  end interface
  !
  interface
    subroutine dosubt (nc,visi,sreel,simag)
      !---------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING   UV Tools
      !   Subtract a continuum value from a line visibility
      !---------------------------------------------------------------------
      integer, intent(in) :: nc           !  Number of channels
      real, intent(inout) :: visi(*)      !  Visibility
      real, intent(in) :: sreel           !  Real part
      real, intent(in) :: simag           !  Imaginary part
    end subroutine dosubt
  end interface
  !
  interface
    subroutine doflag (nc,visi)
      !---------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING   UV Tools
      !   Flag (by zero) a line visibility
      !---------------------------------------------------------------------
      integer, intent(in) :: nc           !  Number of channels
      real, intent(inout) :: visi(*)      !  Visibility
    end subroutine doflag
  end interface
  !
  interface
    subroutine getiba (visi,stime,time,base,uv)
      !---------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING   UV Tools
      !   Get baseline and time information
      !---------------------------------------------------------------------
      real, intent(in)  :: visi(*)                   ! Visibility
      real(8), intent(in) :: stime                   ! Reference time
      real(8), intent(out) :: time                   ! Time offset
      real, intent(out)  :: base(2)                  ! First and Last antenna
      real, intent(out)  :: uv(2)                    ! U and V
    end subroutine getiba
  end interface
  !
  interface
    subroutine dotime (mv,nv,visi,wtime,it,stime)
      !---------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING   UV Tools
      !	  Compute the observing times of the data, 
      !	  sort it and return sorting index
      !---------------------------------------------------------------------
      integer, intent(in) :: mv           ! Size of visibility
      integer, intent(in) :: nv           ! Number of visibilities
      real, intent(in) :: visi(mv,nv)     ! Visibilities
      real(8), intent(out) :: wtime(nv)   ! Sorted times
      integer, intent(inout) :: it(nv)    ! Sorting index
      real(8), intent(out) :: stime       ! Reference time
    end subroutine dotime
  end interface
  !
  interface
    subroutine geself (mv,nv,iw,visi,time,ftime,wtime,it,   &
         &    rbase,complx,uv)
      !---------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING   UV Tools
      !	  Compute the Observed Visibility of the "model source"
      !---------------------------------------------------------------------
      integer, intent(in) :: mv           ! Size of visibility
      integer, intent(in) :: nv           ! Number of visibilities
      real, intent(in) :: visi(mv,nv)     ! Visibilities
      real(8), intent(out) :: wtime(nv)   ! Sorted times
      integer, intent(in) :: iw(2)        ! First and Last channel
      real(8), intent(in) :: time         ! Time of observation
      real(8), intent(in) :: ftime        ! Tolerance on time +/-
      integer, intent(in) :: it(nv)       ! Ordering of visibilities
      real, intent(in) :: rbase(2)        ! Antennas
      real, intent(in) :: uv(2)           ! U and V
      complex, intent(out) :: complx      ! Result
    end subroutine geself
  end interface
  !
  interface
    subroutine findr (np,x,xlim,nlim)
      !---------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING   UV Tools
      !	  Find NLIM such as
      !	 	    X(NLIM-1) < XLIM <= X(NLIM)
      !	  for input data ordered.
      !	  Use a dichotomic search for that
      !---------------------------------------------------------------------
      integer, intent(in) :: np          ! Number of data points
      real(8), intent(in) :: x(np)       ! Data values
      real(8), intent(in) :: xlim        ! Value to be localized
      integer, intent(out) :: nlim       ! Found position
    end subroutine findr
  end interface
  !
  interface
    subroutine extracs (np,nx,ny,ip,in,out,lx,ly)
      !----------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING
      !     Extract a Fourier plane from the FFT cube
      !     Plane and Cube may have different X,Y dimensions
      !----------------------------------------------------------------------
      integer,intent(in) :: np  ! Number of planes
      integer,intent(in) :: nx  ! output FFT X plane size
      integer,intent(in) :: ny  ! output FFT Y plane size
      integer,intent(in) :: ip  ! Plane to be extracted
      integer,intent(in) :: lx  ! input FFT cube X plane size
      integer,intent(in) :: ly  ! input FFT cube Y plane size
      complex,intent(in) :: in(np,lx,ly) ! Input FFT cube
      complex,intent(out) :: out(nx,ny)  ! Output 2-D FFT
    end subroutine extracs
  end interface
  !
  interface
    subroutine extrac (np,nx,ny,ip,in,out)
      !----------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING
      !     Extract a Fourier plane from an FFT cube
      !     Plane and Cube must have same X,Y dimensions
      !----------------------------------------------------------------------
      integer,intent(in) :: np  ! Number of planes
      integer,intent(in) :: nx  ! FFT X plane size
      integer,intent(in) :: ny  ! FFT Y plane size
      integer,intent(in) :: ip  ! Plane to be extracted
      complex,intent(in) :: in(np,nx,ny) ! Input FFT cube
      complex,intent(out) :: out(nx,ny)  ! Output 2-D FFT
    end subroutine extrac
  end interface
  !
  interface
    subroutine dovisi (np,nv,visi,vv,ww,jw)
      !----------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING
      !   Extract V coordinate and Weight value
      !----------------------------------------------------------------------
      integer, intent(in) :: np        ! Size of visibilities
      integer, intent(in) :: nv        ! Number of visibilities
      real, intent(in) :: visi(np,nv)  ! Visibilities
      real, intent(out) :: vv(nv)      ! V values
      real, intent(out) :: ww(nv)      ! Weight values
      integer, intent(in) :: jw        ! Weight column
    end subroutine dovisi
  end interface
  !
  interface
    subroutine dogrid (corr,corx,cory,nx,ny,beam)
      !----------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING
      !   Compute grid correction array, with normalisation
      !   of beam to 1.0 at maximum pixel
      !----------------------------------------------------------------------
      integer, intent(in) :: nx     ! X size
      integer, intent(in) :: ny     ! Y size
      real, intent(in) :: beam(nx,ny) ! Denormalized beam
      real, intent(in) :: corx(nx)    ! X grid correction
      real, intent(in) :: cory(ny)    ! Y Grid correction
      real, intent(out) :: corr(nx,ny) ! Final grid correction and beam normalization
    end subroutine dogrid
  end interface
  !
  interface
    subroutine docorr (map,corr,nd)
      !----------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING
      !   Apply grid correction to map
      !----------------------------------------------------------------------
      integer, intent(in) :: nd
      real, intent(inout) :: map(nd)
      real, intent(in) :: corr(nd)
    end subroutine docorr
  end interface
  !
  interface
    subroutine docoor (n,xinc,x)
      !----------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING
      !   Compute FFT grid coordinates in U or V
      !----------------------------------------------------------------------
      integer,intent(in) :: n
      real, intent(out) :: x(n)
      real, intent(in) :: xinc
    end subroutine docoor
  end interface
  !
  interface
    subroutine findp (nv,xx,xlim,nlim)
      !----------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING  Utility
      !   Find NLIM such as
      !   XX(NLIM-1) < XLIM < XX(NLIM)
      !   for input data ordered, retrieved from memory
      !   Assumes NLIM already preset so that XX(NLIM-1) < XLIM
      !----------------------------------------------------------------------
      integer, intent(in) :: nv       ! Number of values
      integer, intent(inout) :: nlim  ! Preset Position
      real, intent(in) :: xx(nv)  ! Input order value
      real, intent(in) :: xlim    ! Value to be located
    end subroutine findp
  end interface
  !
  interface
    subroutine findm (nv,xx,xlim,nlim)
      !----------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING  Utility
      !   Find NLIM such as
      !     XX(NLIM-1) < XLIM < XX(NLIM)
      !   for input data ordered, retrieved from memory
      !   Assumes NLIM already preset so that XLIM < XX(NLIM)
      !----------------------------------------------------------------------
      integer, intent(in) :: nv       ! Number of values
      integer, intent(inout) :: nlim  ! Preset Position
      real, intent(in) :: xx(nv)  ! Input order value
      real, intent(in) :: xlim    ! Value to be located
    end subroutine findm
  end interface
  !
  interface
    subroutine grdtab (n, buff, bias, corr)
      !----------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING  Utility
      !   Compute fourier transform of gridding function
      !----------------------------------------------------------------------
      integer, intent(in) :: n     ! Number of pixels, assuming center on N/2+1
      real, intent(in) :: buff(*)  ! Gridding function, tabulated every 1/100 cell
      real, intent(in) :: bias     ! Center of gridding function
      real, intent(out) :: corr(n) ! Gridding correction FT
    end subroutine grdtab
  end interface
  !
  interface
    subroutine retocm(r,z,nx,ny)
      !------------------------------------------------------------------------
      ! @  public
      ! MAPPING
      !   Convert real to complex, with Shifting in corners for FFT
      !------------------------------------------------------------------------
      integer, intent(in) :: nx, ny         ! Problem size
      real, intent(in) :: r(nx,ny)          ! Real values
      complex, intent(out) :: z(nx, ny)     ! Complex shifted values
    end subroutine retocm
  end interface
  !
  interface
    subroutine cmtore (in,out,nx,ny)
      !----------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING Utility
      !   Extract Real image from Fourier Transform of its complex FFT
      !   with appropriate recentering
      !----------------------------------------------------------------------
      integer, intent(in) :: nx         ! Size of map
      integer, intent(in) :: ny         ! Size of map
      complex, intent(in) :: in(nx,ny)  ! Complex FFT
      real, intent(out) :: out(nx,ny)   ! Extracted real image
    end subroutine cmtore
  end interface
  !
  interface
    subroutine convfn (ctype, parm, buffer, bias)
      use gildas_def
      use gbl_message
      !----------------------------------------------------------------------
      ! @ public-mandatory
      !
      ! MAPPING
      !   CONVFN computes the convolving functions and stores them in
      !   the supplied buffer. Values are tabulated every 1/100 cell.
      !----------------------------------------------------------------------
      integer, intent(inout) :: ctype
      real(4), intent(inout) :: parm(10)
      real(4), intent(out)   :: buffer(:)
      real(4), intent(out)   :: bias
    end subroutine convfn
  end interface
  !
  interface
    subroutine grdflt (ctypx, ctypy, xparm, yparm)
      !----------------------------------------------------------------------
      ! @ public
      !
      !     GRDFLT determines default parameters for the convolution functions
      !     If no convolving type is chosen, an Spheroidal is picked.
      !     Otherwise any unspecified values ( = 0.0) will be set to some
      !     value.
      ! Arguments:
      !     CTYPX,CTYPY           I  Convolution types for X and Y direction
      !                                1 = pill box
      !                                2 = exponential
      !                                3 = sinc
      !                                4 = expontntial * sinc
      !                                5 = spheroidal function
      !     XPARM(10),YPARM(10)   R*4  Parameters for the convolution fns.
      !                                (1) = support radius (cells)
      !
      !----------------------------------------------------------------------
      integer, intent(inout) :: ctypx,ctypy
      real(4), intent(inout) :: xparm(10), yparm(10)
    end subroutine grdflt
  end interface
  !
  interface
    subroutine uvgmax(huv,visi,uvmax,uvmin)
      use image_def
      !----------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING Support for UV_MAP
      !       Get the Min Max of UV distances
      !----------------------------------------------------------------------
      type (gildas), intent(inout) :: huv
      real, intent(in) ::  visi(:,:) ! Visibilities
      real, intent(out) :: uvmax ! Max baseline
      real, intent(out) :: uvmin ! Min baseline
    end subroutine uvgmax
  end interface
  !
  interface
    function sump(n,a)
      !----------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING   Support for UV_MAP
      !       Return the sum of positive values in array
      !----------------------------------------------------------------------
      real :: sump    ! Return value, intent(out)
      integer, intent(in) :: n   ! Number of values
      real, intent(in) :: a(n)   ! Values
    end function sump
  end interface
  !
  interface
    subroutine dotape (jc,nv,visi,jx,jy,taper,we)
      use gildas_def
      !----------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING  Support for UV_MAP
      !     Apply taper to the weights of the visibility points.
      !----------------------------------------------------------------------
      integer, intent(in) :: nv          ! number of values
      integer, intent(in) :: jc          ! Size of a visibility
      integer, intent(in) :: jx          ! X coord location in VISI
      integer, intent(in) :: jy          ! Y coord location in VISI
      real, intent(in) :: visi(jc,nv)    ! Visibilities
      real, intent(in) :: taper(4)       ! Taper definition
      real, intent(inout) :: we(nv)      ! Weights
    end subroutine dotape
  end interface
  !
  interface
    subroutine doweig (jc,nv,visi,jx,jy,jw,unif,we,wm,vv,error,code)
      use gildas_def
      use gbl_message
      !----------------------------------------------------------------------
      ! @ public-mandatory
      !
      ! MAPPING   Support for UV_MAP
      !     Compute weights of the visibility points.
      !----------------------------------------------------------------------
      integer, intent(in) ::  nv          ! number of values
      integer, intent(in) ::  jc          ! Number of "visibilities"
      integer, intent(in) ::  jx          ! X coord location in VISI
      integer, intent(in) ::  jy          ! Y coord location in VISI
      integer, intent(in) ::  jw          ! Location of weights. If .LE.0, uniform weight
      real, intent(in) ::  visi(jc,nv)    ! Visibilities
      real, intent(in) ::  unif           ! uniform cell size in Meters
      real, intent(inout) ::  we(nv)      ! Weight array
      real, intent(in) ::  wm             ! on input: % of uniformity
      real, intent(in) ::  vv(nv)         ! V values, pre-sorted
      logical, intent(inout) :: error
      integer, intent(in), optional :: code
    end subroutine doweig
  end interface
  !
  interface
    subroutine doweig_sph (jc,nv,visi,jx,jy,jw,unif,we,wm,vv,error,code)
      use gildas_def
      use gbl_message
      !----------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING   Support for UV_MAP
      !     Compute weights of the visibility points.
      !----------------------------------------------------------------------
      integer, intent(in) ::  nv          ! number of values
      integer, intent(in) ::  jc          ! Number of "visibilities"
      integer, intent(in) ::  jx          ! X coord location in VISI
      integer, intent(in) ::  jy          ! Y coord location in VISI
      integer, intent(in) ::  jw          ! Location of weights. If .LE.0, uniform weight
      real, intent(in) ::  visi(jc,nv)    ! Visibilities
      real, intent(in) ::  unif           ! uniform cell size in Meters
      real, intent(inout) ::  we(nv)      ! Weight array
      real, intent(in) ::  wm             ! on input: % of uniformity
      real, intent(in) ::  vv(nv)         ! V values, pre-sorted
      logical, intent(inout) :: error
      integer, intent(in), optional :: code  ! Number of sub-cells per UV uniform cell size
    end subroutine doweig_sph
  end interface
  !
  interface
    subroutine scawei (nv,uni,ori,wall)
      !---------------------------------------------------------
      ! @ public
      !
      ! MAPPING
      !   Scale the weights
      !---------------------------------------------------------
      integer, intent(in) :: nv     ! Number of visibilities
      real, intent(out) :: uni(nv)  ! Re-weighted weights
      real, intent(in)  :: ori(nv)  ! Original weights
      real, intent(out) :: wall     ! Sum of weights
    end subroutine scawei
  end interface
  !
  interface
    subroutine map_message(mkind,procname,message)
      !---------------------------------------------------------------------
      ! @ public
      !
      ! MAPPING
      !   Messaging facility for the current library. Calls the low-level
      !   (internal) messaging routine with its own identifier.
      !---------------------------------------------------------------------
      integer,          intent(in) :: mkind     ! Message kind
      character(len=*), intent(in) :: procname  ! Name of calling procedure
      character(len=*), intent(in) :: message   ! Message string
    end subroutine map_message
  end interface
  !
end module mapping_interfaces_public
