module classmap_interfaces_private
  interface
    subroutine dosmoo(raw,gwe,nc,nx,ny,map,mapx,mapy,sup,cell)
      !---------------------------------------------------------------------
      ! @ private
      ! Smooth an input data cube in VLM along L and M by convolution
      ! with a gaussian...
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)  :: nc,nx,ny       ! Cube size
      real(kind=4),    intent(in)  :: raw(nc,nx,ny)  ! Raw cube
      real(kind=4),    intent(in)  :: gwe(nx,ny)     ! Gridded weights Not used ???? JP
      real(kind=4),    intent(out) :: map(nc,nx,ny)  ! Smoothed cube
      real(kind=4),    intent(in)  :: mapx(nx)       ! Arrays of gridded coordinates
      real(kind=4),    intent(in)  :: mapy(ny)       ! Arrays of gridded coordinates
      real(kind=4),    intent(in)  :: sup(2)         ! Convolving function support size in user unit
      real(kind=4),    intent(in)  :: cell(2)        ! Pixel size in user unit
    end subroutine dosmoo
  end interface
  !
  interface
    subroutine doapod(xmin,xmax,ymin,ymax,tole,beam, &
         nc,nx,ny,map,raw,mapx,mapy,gweight,wmin)
      !---------------------------------------------------------------------
      ! @ private
      ! Replace the original (RAW) data by an apodized version
      !   - outside of the sampled region (map edges to smoothly go to zero)
      !   - and where the weight is below the minimum value (bad data points)
      !---------------------------------------------------------------------
      real(kind=4),    intent(in)    :: xmin,xmax       ! Boundary of sampled region
      real(kind=4),    intent(in)    :: ymin,ymax       ! Boundary of sampled region
      real(kind=4),    intent(in)    :: tole            ! X-Y position tolerance
      real(kind=4),    intent(in)    :: beam            ! Beam size
      integer(kind=4), intent(in)    :: nc,nx,ny        ! Cube size
      real(kind=4),    intent(in)    :: map(nc,nx,ny)   ! Smoothed cube
      real(kind=4),    intent(inout) :: raw(nc,nx,ny)   ! Original cube
      real(kind=4),    intent(in)    :: mapx(nx)        ! Arrays of gridded coordinates
      real(kind=4),    intent(in)    :: mapy(ny)        ! Arrays of gridded coordinates
      real(kind=4),    intent(in)    :: gweight(nx,ny)  ! Gridded weights
      real(kind=4),    intent(in)    :: wmin            ! Minimum weight
    end subroutine doapod
  end interface
  !
  interface
    function nearest_power_of_two(n)
      !---------------------------------------------------------------------
      ! @ private
      !
      !---------------------------------------------------------------------
      integer(kind=4) :: nearest_power_of_two  ! Function value on return
      integer(kind=4), intent(in) :: n          !
    end function nearest_power_of_two
  end interface
  !
  interface
    subroutine dosdft(hout,beam,diam,f,nx,ny,dx,dy)
      use gildas_def
      use image_def
      use phys_const
      !---------------------------------------------------------------------
      ! @ private
      ! Computes Inverse of FT of single-dish beam
      ! (uses a Gaussian truncated at dish size)
      ! Not used in this version, since we have the explicit convolution
      ! kernel in a sampled way
      !---------------------------------------------------------------------
      type (gildas)                  :: hout      ! Header of output cube
      real(kind=4),    intent(in)    :: beam      ! Beam size in radian
      real(kind=4),    intent(in)    :: diam      ! Diameter in meter
      integer(kind=4), intent(in)    :: nx,ny     ! Map size
      real(kind=4),    intent(out)   :: f(nx,ny)  ! Multiplication factor
      real(kind=8),    intent(inout) :: dx,dy     !
    end subroutine dosdft
  end interface
  !
  interface
    subroutine sdcorr(z,f,nxy)
      !---------------------------------------------------------------------
      ! @ private
      ! Correct for single dish beam
      !---------------------------------------------------------------------
      complex,         intent(inout) :: z(*)  !
      real(kind=4),    intent(in)    :: f(*)  !
      integer(kind=4), intent(in)    :: nxy   ! Problem size
    end subroutine sdcorr
  end interface
  !
  interface
    subroutine retocm(r,z,nx,ny)
      !---------------------------------------------------------------------
      ! @ private
      ! Real to complex conversion
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)  :: nx,ny     !
      real(kind=4),    intent(in)  :: r(nx,ny)  !
      complex,         intent(out) :: z(nx,ny)  !
    end subroutine retocm
  end interface
  !
  interface
    subroutine cmtore(z,r,nx,ny)
      !---------------------------------------------------------------------
      ! @ private
      ! Complex to real conversion
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)  :: nx,ny     !
      complex,         intent(in)  :: z(nx,ny)  !
      real(kind=4),    intent(out) :: r(nx,ny)  !
    end subroutine cmtore
  end interface
  !
  interface
    subroutine grdtab(n,buff,bias,corr)
      use phys_const
      !---------------------------------------------------------------------
      ! @ private
      ! Compute fourier transform of gridding function
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)  :: n        ! Number of pixels, assuming center on N/2+1
      real(kind=4),    intent(in)  :: buff(*)  ! Gridding function, tabulated every 1/100th of a pixel
      real(kind=4),    intent(in)  :: bias     ! Center of gridding function
      real(kind=4),    intent(out) :: corr(n)  ! Gridding correction FT
    end subroutine grdtab
  end interface
  !
  interface
    subroutine dogrid(corr,corx,cory,nx,ny,beam)
      !---------------------------------------------------------------------
      ! @ private
      ! Compute grid correction array, with normalisation of beam to 1.0 at
      ! maximum pixel
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)  :: nx,ny        ! Map size
      real(kind=4),    intent(out) :: corr(nx,ny)  ! Final grid correction and beam normalization
      real(kind=4),    intent(in)  :: corx(nx)     ! X Grid correction
      real(kind=4),    intent(in)  :: cory(ny)     ! Y Grid correction
      real(kind=4),    intent(in)  :: beam(nx,ny)  ! Denormalized Beam
    end subroutine dogrid
  end interface
  !
  interface
    subroutine docorr(map,corr,nd)
      !---------------------------------------------------------------------
      ! @ private
      ! Apply grid correction to map
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: nd        ! Map size
      real(kind=4),    intent(inout) :: map(nd)   ! Map to be corrected
      real(kind=4),    intent(in)    :: corr(nd)  ! Grid correction
    end subroutine docorr
  end interface
  !
  interface
    subroutine dotrunc(hout,diam,f,nx,ny)
      use gildas_def
      use image_def
      use phys_const
      !---------------------------------------------------------------------
      ! @ private
      ! Truncate the Fourier Transform beyond the physical disk size
      !---------------------------------------------------------------------
      type (gildas)                :: hout      ! Header of output data cube
      real(kind=4),    intent(in)  :: diam      ! Diameter in meter
      integer(kind=4), intent(in)  :: nx,ny     ! Map size
      real(kind=4),    intent(out) :: f(nx,ny)  ! Multiplication factor
    end subroutine dotrunc
  end interface
  !
  interface
    subroutine run_map(line,comm,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ private
      ! MAP Main library entry point
      !     Call appropriate subroutine according to COMM
      !---------------------------------------------------------------------
      character(len=*), intent(in)  :: line   ! Command line
      character(len=*), intent(in)  :: comm   ! Command name
      logical,          intent(out) :: error  ! Error status
    end subroutine run_map
  end interface
  !
  interface
    subroutine doconv(ncol,nlin,table,xp,yp,we,gwe,nx,ny,map,mapx,mapy,sup,  &
      cell,conv,time,error)
      use gildas_def
      use gbl_message
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      !   Grid (i.e. convolve data from input table columns by a gridding
      ! function)
      !---------------------------------------------------------------------
      integer(kind=index_length), intent(in)  :: ncol      ! Number of table column / Nchan
      integer(kind=index_length), intent(in)  :: nlin      ! Number of table line
      real(kind=4),         intent(in)    :: table(ncol,nlin)  ! The table array
      real(kind=4),         intent(in)    :: xp(nlin)          ! X coordinates
      real(kind=4),         intent(in)    :: yp(nlin)          ! Y coordinates
      real(kind=4),         intent(in)    :: we(nlin)          ! The table weights
      integer(kind=index_length), intent(in)  :: nx,ny         ! Map size
      real(kind=4),         intent(out)   :: gwe(nx,ny)        ! Gridded weights
      real(kind=4),         intent(out)   :: map(ncol,nx,ny)   ! Gridded cube
      real(kind=4),         intent(in)    :: mapx(nx)          ! Arrays of gridded coordinates
      real(kind=4),         intent(in)    :: mapy(ny)          ! Arrays of gridded coordinates
      real(kind=4),         intent(in)    :: sup(2)            ! Convolving function support size in user unit
      real(kind=4),         intent(in)    :: cell(2)           ! Pixel size in user unit
      type(xymap_conv2d_t), intent(in)    :: conv              ! Buffer for the convolution kernel
      type(time_t),         intent(inout) :: time              ! Timer
      logical,              intent(inout) :: error             !
    end subroutine doconv
  end interface
  !
  interface
    subroutine findr(xx,nv,xlim,nlim)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ private
      !  Find nlim such as
      !    xx(nlim-1) < xlim < xx(nlim)
      !  for input data ordered, retrieved from memory
      !  Assume that nlim is already preset so that xx(ic,nlim-1) < xlim
      !---------------------------------------------------------------------
      integer(kind=index_length), intent(in)    :: nv
      real(kind=4),               intent(in)    :: xx(nv)
      real(kind=4),               intent(in)    :: xlim
      integer(kind=index_length), intent(inout) :: nlim
    end subroutine findr
  end interface
  !
  interface
    subroutine convol(conv,dx,dy,resu)
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      ! Compute value of bi-dimensional convolving function in (dx,dy) point
      ! Takes into account the fact that the 1-D convolving functions are
      ! tabulated every 1/100th of pixel
      !---------------------------------------------------------------------
      type(xymap_conv2d_t), intent(in)  :: conv   !
      real(kind=4),         intent(in)  :: dx,dy  ! Point where to compute the convolving function
      real(kind=4),         intent(out) :: resu   ! Resulting value
    end subroutine convol
  end interface
  !
  interface
    subroutine conv_fn_computation(conv,error)
      use phys_const
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      ! CONVFN computes the convolving functions and stores them in the
      ! supplied buffer. Values are tabulated every 1/100th of pixel
      ! CONV%PARM(1) = radius of support in pixel unit
      !---------------------------------------------------------------------
      type(xymap_conv1d_t), intent(inout) :: conv   ! Convolution description
      logical,              intent(out)   :: error  !
    end subroutine conv_fn_computation
  end interface
  !
  interface
    subroutine sphfn(ialf,im,iflag,eta,psi,ier)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ private
      !  SPHFN is a subroutine to evaluate rational approximations to selected
      !  zero-order spheroidal functions, psi(c,eta), which are, in a
      !  sense defined in VLA Scientific Memorandum No. 132, optimal for
      !  gridding interferometer data.  The approximations are taken from
      !  VLA Computer Memorandum No. 156.  The parameter c is related to the
      !  support width, m, of the convoluting function according to c=
      !  pi*m/2.  The parameter alpha determines a weight function in the
      !  definition of the criterion by which the function is optimal.
      !  SPHFN incorporates approximations to 25 of the spheroidal functions,
      !  corresponding to 5 choices of m (4, 5, 6, 7, or 8 cells)
      !  and 5 choices of the weighting exponent (0, 1/2, 1, 3/2, or 2).
      !
      !  Input:
      !    IALF    I*4   Selects the weighting exponent, alpha.  IALF =
      !                  1, 2, 3, 4, and 5 correspond, respectively, to
      !                  alpha = 0, 1/2, 1, 3/2, and 2.
      !    IM      I*4   Selects the support width m, (=IM) and, correspond-
      !                  ingly, the parameter c of the spheroidal function.
      !                  Only the choices 4, 5, 6, 7, and 8 are allowed.
      !    IFLAG   I*4   Chooses whether the spheroidal function itself, or
      !                  its Fourier transform, is to be approximated.  The
      !                  latter is appropriate for gridding, and the former
      !                  for the u-v plane convolution.  The two differ on-
      !                  by a factor (1-eta**2)**alpha.  IFLAG less than or
      !                  equal to zero chooses the function appropriate for
      !                  gridding, and IFLAG positive chooses its F.T.
      !    ETA     R*4   Eta, as the argument of the spheroidal function, is
      !                  a variable which ranges from 0 at the center of the
      !                  convoluting function to 1 at its edge (also from 0
      !                  at the center of the gridding correction function
      !                  to unity at the edge of the map).
      !
      !  Output:
      !    PSI      R*4  The function value which, on entry to the subrou-
      !                  tine, was to have been computed.
      !    IER      I*4  An error flag whose meaning is as follows:
      !                     IER = 0  =>  No evident problem.
      !                           1  =>  IALF is outside the allowed range.
      !                           2  =>  IM is outside of the allowed range.
      !                           3  =>  ETA is larger than 1 in absolute
      !                                     value.
      !                          12  =>  IALF and IM are out of bounds.
      !                          13  =>  IALF and ETA are both illegal.
      !                          23  =>  IM and ETA are both illegal.
      !                         123  =>  IALF, IM, and ETA all are illegal.
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)  :: ialf   !
      integer(kind=4), intent(in)  :: im     !
      integer(kind=4), intent(in)  :: iflag  !
      real(kind=4)                 :: eta    !
      real(kind=4),    intent(out) :: psi    !
      integer(kind=4), intent(out) :: ier    !
    end subroutine sphfn
  end interface
  !
  interface
    subroutine conv_fn_default(ctypx,ctypy,xparm,yparm)
      !---------------------------------------------------------------------
      ! @ private
      !   Determine default parameters for the convolution functions when
      ! they are not specified. Default convolving type is a spheroidal
      ! function. Any other unspecified values (= 0.0) will be set to
      ! some value.
      !---------------------------------------------------------------------
      integer(kind=4), intent(inout) :: ctypx      ! Convolution types for X direction
      integer(kind=4), intent(inout) :: ctypy      ! Convolution types for Y direction
      real(kind=4),    intent(inout) :: xparm(10)  ! Parameters for the convolution fns (1) = support radius (cells)
      real(kind=4),    intent(inout) :: yparm(10)  ! Parameters for the convolution fns (1) = support radius (cells)
    end subroutine conv_fn_default
  end interface
  !
  interface
    subroutine doplace(map,table,cube,gweight,time,error)
      use gbl_message
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      !---------------------------------------------------------------------
      type(xymap_prog_t), intent(in)    :: map ! Gridding description
      real(kind=4),       intent(in)    :: table(map%tab%nchan,map%tab%nposi)
      real(kind=4),       intent(inout) :: cube(map%cub%nchan,map%cub%nx,map%cub%ny)
      real(kind=4),       intent(inout) :: gweight(map%cub%nx,map%cub%ny)
      type(time_t),       intent(inout) :: time
      logical,            intent(inout) :: error
    end subroutine doplace
  end interface
  !
  interface
    subroutine docoor(n,xref,xval,xinc,x)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ private
      ! Compute coordinate array from conversion formula
      !---------------------------------------------------------------------
      integer(kind=index_length), intent(in)  :: n     ! Number of pixel
      real(kind=8),               intent(in)  :: xref  ! Reference pixel
      real(kind=8),               intent(in)  :: xval  ! Value at reference pixel
      real(kind=8),               intent(in)  :: xinc  ! Pixel size
      real(kind=4),               intent(out) :: x(n)  ! Axis coordinate
    end subroutine docoor
  end interface
  !
  interface
    subroutine gag_cputime_add(sum,last)
      use gkernel_types
      !---------------------------------------------------------------------
      ! @ private
      !   Get the times since last call for 'last', and add the times to
      ! the structure 'sum'. Note that the reference times in 'sum' have
      ! not much meaning in this context.
      ! ---
      !   This subroutine is helpful to add non-contiguous time counts,
      ! while the official cputime_t is made to count times from a reference
      ! or from last call. Should this be merged in gsys?
      !---------------------------------------------------------------------
      type(cputime_t), intent(inout) :: sum
      type(cputime_t), intent(inout) :: last
    end subroutine gag_cputime_add
  end interface
  !
  interface
    subroutine print_cputime_feedback(time)
      use gbl_message
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      !---------------------------------------------------------------------
      type(xymap_time_t), intent(in) :: time
    end subroutine print_cputime_feedback
  end interface
  !
  interface
    subroutine reallocate_tab(array,n1,n2,error)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ private
      !  Reallocate a 2D table
      !---------------------------------------------------------------------
      real(kind=4),               allocatable   :: array(:,:)
      integer(kind=index_length), intent(in)    :: n1,n2
      logical,                    intent(inout) :: error
    end subroutine reallocate_tab
  end interface
  !
  interface
    subroutine reallocate_cub(array,n1,n2,n3,error)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ private
      !  Reallocate a 3D cube
      !---------------------------------------------------------------------
      real(kind=4),               allocatable   :: array(:,:,:)
      integer(kind=index_length), intent(in)    :: n1,n2,n3
      logical,                    intent(inout) :: error
    end subroutine reallocate_cub
  end interface
  !
  interface
    function pretty_size(nwords)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ private
      !  Return a string describing the input size (words) in a bytes
      ! multiple
      !---------------------------------------------------------------------
      character(len=20) :: pretty_size     ! Function value on return
      integer(kind=size_length) :: nwords  ! [words]
    end function pretty_size
  end interface
  !
  interface
    subroutine sort_xyw(tab,error)
      use gbl_message
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      !  Sort the X Y W buffers by ascending Y, and fill the sorting array
      !---------------------------------------------------------------------
      type(xymap_tab_t), intent(inout) :: tab
      logical,           intent(inout) :: error
    end subroutine sort_xyw
  end interface
  !
  interface
    subroutine sort_tab(table,ncol,nlin,key,work,error)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ private
      !  Sort the input table according to the sorting array
      !---------------------------------------------------------------------
      integer(kind=index_length), intent(in)    :: ncol              ! Table column number
      integer(kind=index_length), intent(in)    :: nlin              ! Table line number
      real(kind=4),               intent(inout) :: table(ncol,nlin)  ! Table to be sorted
      integer(kind=4),            intent(in)    :: key(nlin)         ! Sorting array
      real(kind=4),               allocatable   :: work(:,:)         ! Working buffer
      logical,                    intent(inout) :: error             ! Returned status
    end subroutine sort_tab
  end interface
  !
  interface
    subroutine gr4_sort2d(x,xwork,key,nc,nl)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ private
      !  Reorder a real*4 2D array by increasing order using the sorted
      ! indexes computed by a G*_TRIE subroutine
      !---------------------------------------------------------------------
      integer(kind=index_length), intent(in)    :: nl,nc         ! N lines and N columns
      real(kind=4),               intent(inout) :: x(nc,nl)      ! The data to be sorted
      real(kind=4)                              :: xwork(nc,nl)  ! Working buffer
      integer(kind=4),            intent(in)    :: key(nl)       ! Sorting array
    end subroutine gr4_sort2d
  end interface
  !
  interface
    function trione(x,nd,n,ix,work)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ private
      ! 	Sorting an input table (i.e. 2D array) according to column ix in
      !     increasing order. The quicksort algorithm is used.
      !---------------------------------------------------------------------
      integer(kind=4) :: trione                   !
      integer(kind=4), intent(in)    :: nd        ! Table column number
      integer(kind=4), intent(in)    :: n         ! Table line number
      real(kind=4),    intent(inout) :: x(nd,n)   ! Unsorted table
      integer(kind=4), intent(in)    :: ix        ! Column serving as key for sorting
      real(kind=4),    intent(inout) :: work(nd)  ! Work space for exchange
    end function trione
  end interface
  !
  interface
    subroutine define_sic_xymap(error)
      use gildas_def
      use xymap_def
      !---------------------------------------------------------------------
      ! @ private
      ! MAP Internal routine
      !---------------------------------------------------------------------
      logical, intent(out) :: error     ! Error status
    end subroutine define_sic_xymap
  end interface
  !
  interface
    subroutine init_xymap_struct(xymap)
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      ! MAP Internal routine
      !---------------------------------------------------------------------
      type(xymap_user_t), intent(out) :: xymap  !
    end subroutine init_xymap_struct
  end interface
  !
  interface
    subroutine xymap(line,error)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ private
      ! MAP Support routine for command
      !     XY_MAP [TableName]
      ! 1          [/NOGRID]
      ! 2          [/TYPE LMV|VLM|...]
      !---------------------------------------------------------------------
      character(len=*), intent(in)  :: line   ! Command line
      logical,          intent(out) :: error  ! Logical error flag
    end subroutine xymap
  end interface
  !
  interface
    subroutine sub_xymap(tablename,cubename,nogrid,lmvcode,error)
      use gbl_message
      use gildas_def
      use image_def
      use xymap_def
      !---------------------------------------------------------------------
      ! @ private
      ! Do the job
      !------------------------------------------------------------------------
      character(len=*), intent(in)  :: tablename  ! Name of input table
      character(len=*), intent(in)  :: cubename   ! Name of output cube
      logical,          intent(in)  :: nogrid     ! Do not convolve, just place
      character(len=*), intent(in)  :: lmvcode    ! LMV or VLM or any...
      logical,          intent(out) :: error      ! Logical error flag
    end subroutine sub_xymap
  end interface
  !
  interface
    subroutine table_open(tablename,prefixname,tab,error)
      use image_def
      use gbl_message
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      !  Read the table header
      !---------------------------------------------------------------------
      character(len=*),  intent(in)    :: tablename   ! Table name e.g. 'foo.tab'
      character(len=*),  intent(out)   :: prefixname  ! Prefix shared with the cube e.g. 'foo'
      type(xymap_tab_t), intent(inout) :: tab         !
      logical,           intent(inout) :: error       !
    end subroutine table_open
  end interface
  !
  interface
    subroutine table_read_xyw(tab,time,error)
      use gbl_message
      use gkernel_types
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      !  Fill the X, Y, and weights arrays
      !---------------------------------------------------------------------
      type(xymap_tab_t), intent(inout) :: tab
      type(cputime_t),   intent(inout) :: time
      logical,           intent(inout) :: error
    end subroutine table_read_xyw
  end interface
  !
  interface
    subroutine table_read_data(tab,v1,v2,time,error)
      use gbl_message
      use gkernel_types
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      ! Read the data in order VELOCITY - POSITION
      !---------------------------------------------------------------------
      type(xymap_tab_t),          intent(inout) :: tab
      integer(kind=index_length), intent(in)    :: v1,v2  ! [chan] Range to read
      type(xymap_time_t),         intent(inout) :: time   !
      logical,                    intent(inout) :: error
    end subroutine table_read_data
  end interface
  !
  interface
    subroutine my_close_image(h,error)
      use image_def
      !---------------------------------------------------------------------
      ! @ private
      !  GDF-close the input GDF image, if it is opened
      !  Input error status is also preserved on output
      !---------------------------------------------------------------------
      type(gildas), intent(inout) :: h
      logical,      intent(inout) :: error
    end subroutine my_close_image
  end interface
  !
  interface
    subroutine check_table_format(xymap_user,map,error)
      use gbl_message
      use image_def
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      ! MAP internal routine
      !---------------------------------------------------------------------
      type(xymap_user_t), intent(in)    :: xymap_user  ! Input user parameters
      type(xymap_prog_t), intent(inout) :: map         ! Gridding parameters
      logical,            intent(out)   :: error       ! Return status
    end subroutine check_table_format
  end interface
  !
  interface
    subroutine reproject_table(tab,system,                        &
                               oldproj,olda0,oldd0,oldangle,      &
                               newproj,newa0,newd0,newangle,error)
      use phys_const
      use gbl_constant
      use gbl_message
      use gkernel_types
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      ! Shift-rotate-reproject the table coordinates with a new projection
      ! type and/or new projection center and/or new projection angle.
      !---------------------------------------------------------------------
      type(xymap_tab_t), intent(inout) :: tab          !
      character(len=*),  intent(in)    :: system       ! Coordinate system (for feedback)
      integer(kind=4),   intent(in)    :: oldproj      ! Table projection code
      real(kind=8),      intent(in)    :: olda0,oldd0  ! Table projection center
      real(kind=8),      intent(in)    :: oldangle     ! Table projection angle
      integer(kind=4),   intent(in)    :: newproj      ! Map projection code
      real(kind=8),      intent(in)    :: newa0,newd0  ! Map projection center
      real(kind=8),      intent(in)    :: newangle     ! Map projection angle
      logical,           intent(inout) :: error        ! Returned status
    end subroutine reproject_table
  end interface
  !
  interface
    subroutine define_gridding_parameters(xymap_user,map,hin,nogrid,error)
      use phys_const
      use image_def
      use gbl_message
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      ! MAP internal routine
      ! Compute the map characterictics:
      !  - resolution
      !  - position angle
      !  - pixel size
      !  - gridding function (if not placing)
      !  - map size
      !  - axes
      ! either from (in priority order):
      !  - xymap_user% (i.e. elements of SIC structure map% customized by user)
      !  - xymap_user%like (another map used as reference)
      !  - data positions (if placing is used)
      !  - defaults
      !---------------------------------------------------------------------
      type(xymap_user_t), intent(inout) :: xymap_user  ! Input user parameters
      type(xymap_prog_t), intent(inout) :: map         ! Gridding parameters
      type(gildas),       intent(in)    :: hin         ! Input table header
      logical,            intent(in)    :: nogrid      ! Use placing instead of gridding
      logical,            intent(out)   :: error       ! Return status
    end subroutine define_gridding_parameters
  end interface
  !
  interface
    subroutine find_xy_range(tab,xmin,xmax,ymin,ymax,error)
      use gbl_message
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      !     Search for the limits of the x and y coordinates.
      !     The algorithm assumes that the input table is sorted in increasing
      !     order according to the Y coordinate.
      !---------------------------------------------------------------------
      type(xymap_tab_t), intent(in)    :: tab    !
      real(kind=4),      intent(out)   :: xmin   ! Minimum of X coordinates
      real(kind=4),      intent(out)   :: xmax   ! Maximum of X coordinates
      real(kind=4),      intent(out)   :: ymin   ! Minimum of Y coordinates
      real(kind=4),      intent(out)   :: ymax   ! Maximum of Y coordinates
      logical,           intent(inout) :: error  !
    end subroutine find_xy_range
  end interface
  !
  interface
    subroutine find_xy_increment(tab,xinc,yinc,tole)
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      ! Find minimum increment in the X and Y coordinates.
      ! If this minimum is lower than the X-Y position tolerance, then send
      ! back this tolerance instead.
      ! Warning: xinc and yinc are assumed to be initialized outside this
      !          subroutine.
      ! *** JP ***
      ! The current algorithm takes forever when the number of table lines
      ! increases. A better way would be to assume that the data coordinates
      ! are indeed already on a grid (this is the use case in which to call
      ! this subroutine!). In this case, finding first the equivalent classes
      ! of the x offsets will be extremely fast because there is not so many
      ! different x offsets! We can then sort them and find the minimum
      ! distance between them. Once this is done, we use exactly the same
      ! algorithm but for the y offsets. To be fully generic, we can use the
      ! same positioning tolerance as used in other parts of this code. Hence,
      ! if the data offsets are not already positioned on a grid, we still
      ! limit the number of equivalence classes and the algorithm should stay fast.
      ! *** JP ***
      !---------------------------------------------------------------------
      type(xymap_tab_t), intent(in)    :: tab   !
      real(kind=4),      intent(inout) :: xinc  ! X minimum increment (initialized to xmax-xmin)
      real(kind=4),      intent(inout) :: yinc  ! Y minimum increment (initialized to ymax-ymin)
      real(kind=4),      intent(in)    :: tole  ! X-Y position tolerance
    end subroutine find_xy_increment
  end interface
  !
  interface
    subroutine print_gridding_parameters(map)
      use gbl_message
      use phys_const
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      ! MAP internal routine
      !---------------------------------------------------------------------
      type(xymap_prog_t), intent(inout) :: map  ! Cube description
    end subroutine print_gridding_parameters
  end interface
  !
  interface
    subroutine table_to_cube_headers(map,basename,lmvcode,error)
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      ! Set up the headers for the output data cube and weight image
      !---------------------------------------------------------------------
      type(xymap_prog_t), intent(inout) :: map
      character(len=*),   intent(in)    :: basename
      character(len=*),   intent(in)    :: lmvcode
      logical,            intent(inout) :: error
    end subroutine table_to_cube_headers
  end interface
  !
  interface
    subroutine table_to_cube_header(filename,hin,map,trcode,hout,error)
      use image_def
      use gbl_message
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      !  Fill the output cube (header part)
      !---------------------------------------------------------------------
      character(len=*),   intent(in)    :: filename  !
      type(gildas),       intent(in)    :: hin       !
      type(xymap_prog_t), intent(in)    :: map       !
      character(len=*),   intent(in)    :: trcode    ! Transposition code e.g. '231'
      type(gildas),       intent(inout) :: hout      !
      logical,            intent(inout) :: error     !
    end subroutine table_to_cube_header
  end interface
  !
  interface
    subroutine table_to_cube_data(map,nogrid,error)
      use gbl_message
      use gildas_def
      use gkernel_types
      use image_def
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      !  Fill the output cube and weight (data part)
      !---------------------------------------------------------------------
      type(xymap_prog_t), intent(inout) :: map     ! Gridding parameters
      logical,            intent(in)    :: nogrid  ! Do not convolve, just place
      logical,            intent(out)   :: error   ! Return status
    end subroutine table_to_cube_data
  end interface
  !
  interface
    subroutine table_to_cube_datasub(map,firstblock,fc,lc,nogrid,xcoord,ycoord,  &
      time,error)
      use gildas_def
      use gbl_message
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      !  Process 1 block of channels
      !---------------------------------------------------------------------
      type(xymap_prog_t),         intent(inout) :: map             !
      logical,                    intent(in)    :: firstblock      ! First block written?
      integer(kind=index_length), intent(in)    :: fc,lc           ! First and last channels
      logical,                    intent(in)    :: nogrid          !
      real(kind=4)                              :: xcoord(map%cub%nx)  ! Working buffer
      real(kind=4)                              :: ycoord(map%cub%ny)  ! Working buffer
      type(time_t),               intent(inout) :: time            !
      logical,                    intent(inout) :: error           !
    end subroutine table_to_cube_datasub
  end interface
  !
  interface
    subroutine cube_write_data(cub,firstblock,fc,lc,time,error)
      use gbl_message
      use xymap_types
      !---------------------------------------------------------------------
      ! @ private
      !  Write the block of data, either directly on disk, either in memory
      ! depending on the cube order and memory size.
      !---------------------------------------------------------------------
      type(xymap_cub_t),          intent(inout) :: cub         !
      logical,                    intent(in)    :: firstblock  ! First block written?
      integer(kind=index_length), intent(in)    :: fc,lc       ! First and last channels
      type(xymap_time_t),         intent(inout) :: time        !
      logical,                    intent(inout) :: error       !
    end subroutine cube_write_data
  end interface
  !
end module classmap_interfaces_private
