subroutine sic_diff(line,error)
  use gildas_def
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff
  use sic_dictionaries
  !---------------------------------------------------------------------
  ! @ private
  !  Support routine for command
  !    SIC\DIFF Header1 Header2
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   !
  logical,          intent(inout) :: error  !
  ! Local
  character(len=*), parameter :: rname='DIFF'
  integer(kind=4), parameter :: typenone=0,typevar=1,typefile=2
  integer(kind=4) :: type1,type2
  type(sic_descriptor_t) :: desc1,desc2
  real(kind=4) :: datatol
  logical, save :: differ
  logical, save :: first=.true.
  !
  type1 = typenone
  type2 = typenone
  !
  call getarg(1,type1,desc1,error)
  if (error)  return
  call getarg(2,type2,desc2,error)
  if (error)  goto 10
  datatol = 1e-6
  !
  call sic_diff_descriptors(desc1,desc2,datatol,differ,error)
  if (error)  goto 10
  !
  if (first) then
    call sic_def_logi('SIC%DIFF',differ,.true.,error)
    if (error)  return
    first = .false.
  endif
  !
10 continue
  ! Cleaning
  call closearg(type1,desc1)
  call closearg(type2,desc2)
  !
contains
  !
  subroutine getarg(iarg,argtype,desc,error)
    use sic_types
    !-------------------------------------------------------------------
    ! If the argument provides a header, return a pointer to this
    ! header, or return a null pointer if not.
    !-------------------------------------------------------------------
    integer(kind=4),        intent(in)    :: iarg     ! Argument number on command line
    integer(kind=4),        intent(inout) :: argtype  !
    type(sic_descriptor_t), intent(out)   :: desc     !
    logical,                intent(inout) :: error    !
    ! Local
    character(len=filename_length) :: name
    integer(kind=4) :: nc,ier,ivar
    type(sic_identifier_t) :: var
    !
    call sic_ch(line,0,iarg,name,nc,.true.,error)
    if (error) return
    !
    ! Guess if a Variable or a File
    var%name = name
    var%lname = len_trim(name)
    var%level = var_level
    ier = sic_hasfin(maxvar,pfvar,pnvar,dicvar,var,ivar)
    if (ier.ne.1) then
      var%level = 0
      ier = sic_hasfin(maxvar,pfvar,pnvar,dicvar,var,ivar)
    endif
    if (ier.eq.1) then
      ! Found a variable
      argtype = typevar
      call copy_descr(dicvar(ivar)%desc,desc,error)
      if (error)  return
    else
      ! Must be a file name. Will raise an error if not.
      ! Build a hand-made descriptor, will need special cleaning later on
      !
      allocate(desc%head)           ! Allocated, will be cleaned after use
      call gildas_null(desc%head)
      call gdf_read_gildas(desc%head,name,'.gdf',error,data=.true.,rank=0)
      if (error) then
        deallocate(desc%head)
        return
      endif
      desc%addr = desc%head%loca%addr
      desc%type = desc%head%gil%form
      desc%ndim = desc%head%gil%ndim
      desc%dims(1:desc%ndim) = desc%head%gil%dim(1:desc%ndim)
      ! Other elements not needed in sic_diff_datadescr
      !
      argtype = typefile
      !
    endif
  end subroutine getarg
  !
  subroutine closearg(argtype,desc)
    !-------------------------------------------------------------------
    ! Perform the necessary cleaning depending on argument type
    !-------------------------------------------------------------------
    integer(kind=4),        intent(in)    :: argtype  !
    type(sic_descriptor_t), intent(inout) :: desc     !
    ! Local
    logical :: error2
    !
    select case (argtype)
    case (typefile)
      error2 = .false.
      call gdf_close_image(desc%head,error2)
      if (error2) continue
      if (associated(desc%head%r1d))  deallocate(desc%head%r1d)
      ! ZZZ if image format is not R*4, we have a leak here.
      deallocate(desc%head)  ! Trick here: was allocated
    end select
    !
  end subroutine closearg
  !
end subroutine sic_diff
!
subroutine sic_diff_descriptors(desc1,desc2,datatol,differ,error)
  use gbl_message
  use sic_types
  use sic_interfaces, except_this=>sic_diff_descriptors
  !---------------------------------------------------------------------
  ! @ private
  ! Show the differences between two SIC variables
  !---------------------------------------------------------------------
  type(sic_descriptor_t), intent(in)    :: desc1,desc2
  real(kind=4),           intent(in)    :: datatol
  logical,                intent(out)   :: differ
  logical,                intent(inout) :: error
  ! Local
  logical :: do1,do2
  !
  differ = .false.  ! Default
  !
  do1 = associated(desc1%head)
  do2 = associated(desc2%head)
  if (do1 .and. do2) then
    call sic_diff_headers(desc1%head,desc2%head,differ,error)
  elseif (do1 .and. .not.do2) then
    call sic_message(seve%r,'DIFF','Only first argument provides a header')
    differ = .true.
  elseif (.not.do1 .and. do2) then
    call sic_message(seve%r,'DIFF','Only second argument provides a header')
    differ = .true.
  endif  ! Else both have no header => no message
  !
  do1 = desc1%addr.ne.ptr_null
  do2 = desc2%addr.ne.ptr_null
  if (do1 .and. do2) then
    call sic_diff_datadescr(desc1,desc2,datatol,differ,error)
  elseif (do1 .and. .not.do2) then
    call sic_message(seve%r,'DIFF','Only first argument provides data')
    differ = .true.
  elseif (.not.do1 .and. do2) then
    call sic_message(seve%r,'DIFF','Only second argument provides data')
    differ = .true.
  endif  ! Else both have no data => no message
  !
  if (.not.differ) then
    call sic_message(seve%i,'DIFF','Arguments have no difference')
  endif
  !
end subroutine sic_diff_descriptors
!
subroutine sic_diff_headers(h1,h2,differ,error)
  use image_def
  use sic_interfaces, except_this=>sic_diff_headers
  !---------------------------------------------------------------------
  ! @ private
  ! Show the differences between two GDF headers
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: h1,h2
  logical,      intent(inout) :: differ
  logical,      intent(inout) :: error
  !
  call sic_diff_general(h1,h2,differ,error)
  if (error)  return
  call sic_diff_dimension(h1,h2,differ,error)
  if (error)  return
  call sic_diff_blanking(h1,h2,differ,error)
  if (error)  return
  call sic_diff_extrema(h1,h2,differ,error)
  if (error)  return
  call sic_diff_coordinate(h1,h2,differ,error)
  if (error)  return
  call sic_diff_description(h1,h2,differ,error)
  if (error)  return
  call sic_diff_position(h1,h2,differ,error)
  if (error)  return
  call sic_diff_projection(h1,h2,differ,error)
  if (error)  return
  call sic_diff_spectroscopy(h1,h2,differ,error)
  if (error)  return
  call sic_diff_resolution(h1,h2,differ,error)
  if (error)  return
  call sic_diff_noise(h1,h2,differ,error)
  if (error)  return
  call sic_diff_astrometry(h1,h2,differ,error)
  if (error)  return
  call sic_diff_telescope(h1,h2,differ,error)
  if (error)  return
  call sic_diff_uvdescr(h1,h2,differ,error)
  if (error)  return
  !
end subroutine sic_diff_headers
!
subroutine sic_diff_general(h1,h2,differ,error)
  use gbl_message
  use image_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_general
  !---------------------------------------------------------------------
  ! @ private
  !  Print the differences between 2 headers (section GENERAL)
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: h1,h2
  logical,      intent(inout) :: differ
  logical,      intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='DIFF'
  character(len=*), parameter :: secname='General'
  logical :: secwarned
  !
  secwarned = .false.
  call gag_diff_elem(rname,secname,secwarned,'TYPE:',       h1%char%type,      h2%char%type)
  call gag_diff_elem(rname,secname,secwarned,'VERSION_GDF:',h1%gil%version_gdf,h2%gil%version_gdf)
  call gag_diff_elem(rname,secname,secwarned,'TYPE_GDF:',   h1%gil%type_gdf,   h2%gil%type_gdf)
  call gag_diff_elem(rname,secname,secwarned,'FORMAT:',     h1%gil%form,       h2%gil%form)
  if (secwarned)  differ = .true.
  !
end subroutine sic_diff_general
!
subroutine sic_diff_dimension(h1,h2,differ,error)
  use gbl_message
  use image_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_dimension
  !---------------------------------------------------------------------
  ! @ private
  !  Print the differences between 2 headers (section DIMENSION)
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: h1,h2
  logical,      intent(inout) :: differ
  logical,      intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='DIFF'
  character(len=*), parameter :: secname='Dimension'
  logical :: secwarned
  character(len=64) :: elname
  integer(kind=4) :: idime
  !
  if (sic_diff_presec(secname,h1%gil%dim_words,h2%gil%dim_words,differ))  return
  !
  secwarned = .false.
  call gag_diff_elem(rname,secname,secwarned,'NDIM:',h1%gil%ndim,h2%gil%ndim)
  do idime=1,min(h1%gil%ndim,h2%gil%ndim)
    write(elname,'(A,I0,A)') 'DIM[',idime,']:'
    call gag_diff_elem(rname,secname,secwarned,elname,h1%gil%dim(idime),h2%gil%dim(idime))
  enddo
  if (secwarned)  differ = .true.
  !
end subroutine sic_diff_dimension
!
subroutine sic_diff_blanking(h1,h2,differ,error)
  use gbl_message
  use image_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_blanking
  !---------------------------------------------------------------------
  ! @ private
  !  Print the differences between 2 headers (section BLANKING)
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: h1,h2
  logical,      intent(inout) :: differ
  logical,      intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='DIFF'
  character(len=*), parameter :: secname='Blanking'
  logical :: secwarned
  !
  if (sic_diff_presec(secname,h1%gil%blan_words,h2%gil%blan_words,differ))  return
  !
  secwarned = .false.
  call gag_diff_elem(rname,secname,secwarned,'BLANK[1]:',h1%gil%bval,h2%gil%bval)
  call gag_diff_elem(rname,secname,secwarned,'BLANK[2]:',h1%gil%eval,h2%gil%eval)
  if (secwarned)  differ = .true.
  !
end subroutine sic_diff_blanking
!
subroutine sic_diff_extrema(h1,h2,differ,error)
  use gbl_message
  use image_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_extrema
  !---------------------------------------------------------------------
  ! @ private
  !  Print the differences between 2 headers (section EXTREMA)
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: h1,h2
  logical,      intent(inout) :: differ
  logical,      intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='DIFF'
  character(len=*), parameter :: secname='Extrema'
  logical :: secwarned
  character(len=64) :: elname
  integer(kind=4) :: idime
  !
  if (sic_diff_presec(secname,h1%gil%extr_words,h2%gil%extr_words,differ))  return
  !
  secwarned = .false.
  call gag_diff_elem(rname,secname,secwarned,'MIN:',h1%gil%rmin,h2%gil%rmin)
  call gag_diff_elem(rname,secname,secwarned,'MAX:',h1%gil%rmax,h2%gil%rmax)
  do idime=1,min(h1%gil%ndim,h2%gil%ndim)
    write(elname,'(A,I0,A)') 'MINLOC[',idime,']:'
    call gag_diff_elem(rname,secname,secwarned,elname,h1%gil%minloc(idime),h2%gil%minloc(idime))
    write(elname,'(A,I0,A)') 'MAXLOC[',idime,']:'
    call gag_diff_elem(rname,secname,secwarned,elname,h1%gil%maxloc(idime),h2%gil%maxloc(idime))
  enddo
  if (secwarned)  differ = .true.
  !
end subroutine sic_diff_extrema
!
subroutine sic_diff_coordinate(h1,h2,differ,error)
  use gbl_message
  use image_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_coordinate
  !---------------------------------------------------------------------
  ! @ private
  !  Print the differences between 2 headers (section COORDINATE)
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: h1,h2
  logical,      intent(inout) :: differ
  logical,      intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='DIFF'
  character(len=*), parameter :: secname='Coordinate'
  logical :: secwarned
  character(len=64) :: elname
  integer(kind=4) :: idime
  !
  if (sic_diff_presec(secname,h1%gil%coor_words,h2%gil%coor_words,differ))  return
  !
  secwarned = .false.
  do idime=1,min(h1%gil%ndim,h2%gil%ndim)
    write(elname,'(A,I0,A,I0,A)') 'CONVERT[1,',idime,'] (REF',idime,'):'
    call gag_diff_elem(rname,secname,secwarned,elname,h1%gil%convert(1,idime),h2%gil%convert(1,idime))
    write(elname,'(A,I0,A,I0,A)') 'CONVERT[2,',idime,'] (VAL',idime,'):'
    call gag_diff_elem(rname,secname,secwarned,elname,h1%gil%convert(2,idime),h2%gil%convert(2,idime))
    write(elname,'(A,I0,A,I0,A)') 'CONVERT[3,',idime,'] (INC',idime,'):'
    call gag_diff_elem(rname,secname,secwarned,elname,h1%gil%convert(3,idime),h2%gil%convert(3,idime))
  enddo
  if (secwarned)  differ = .true.
  !
end subroutine sic_diff_coordinate
!
subroutine sic_diff_description(h1,h2,differ,error)
  use gbl_message
  use image_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_description
  !---------------------------------------------------------------------
  ! @ private
  !  Print the differences between 2 headers (section DESCRIPTION)
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: h1,h2
  logical,      intent(inout) :: differ
  logical,      intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='DIFF'
  character(len=*), parameter :: secname='Description'
  logical :: secwarned
  character(len=64) :: elname
  integer(kind=4) :: idime
  !
  if (sic_diff_presec(secname,h1%gil%desc_words,h2%gil%desc_words,differ))  return
  !
  secwarned = .false.
  call gag_diff_elem(rname,secname,secwarned,'UNIT:',h1%char%unit,h2%char%unit)
  do idime=1,min(h1%gil%ndim,h2%gil%ndim)
    write(elname,'(A,I0,A)') 'UNIT',idime,':'
    call gag_diff_elem(rname,secname,secwarned,elname,h1%char%code(idime),h2%char%code(idime))
  enddo
  if (secwarned)  differ = .true.
  !
end subroutine sic_diff_description
!
subroutine sic_diff_position(h1,h2,differ,error)
  use gbl_message
  use image_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_position
  !---------------------------------------------------------------------
  ! @ private
  !  Print the differences between 2 headers (section POSITION)
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: h1,h2
  logical,      intent(inout) :: differ
  logical,      intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='DIFF'
  character(len=*), parameter :: secname='Position'
  logical :: secwarned
  !
  if (sic_diff_presec(secname,h1%gil%posi_words,h2%gil%posi_words,differ))  return
  !
  secwarned = .false.
  call gag_diff_elem(rname,secname,secwarned,'SOURCE:', h1%char%name,h2%char%name)
  call gag_diff_elem(rname,secname,secwarned,'SYSTEM:', h1%char%syst,h2%char%syst)
  call gag_diff_elem(rname,secname,secwarned,'RA:',     h1%gil%ra,   h2%gil%ra)
  call gag_diff_elem(rname,secname,secwarned,'DEC:',    h1%gil%dec,  h2%gil%dec)
  call gag_diff_elem(rname,secname,secwarned,'LII:',    h1%gil%lii,  h2%gil%lii)
  call gag_diff_elem(rname,secname,secwarned,'BII:',    h1%gil%bii,  h2%gil%bii)
  call gag_diff_elem(rname,secname,secwarned,'EQUINOX:',h1%gil%epoc, h2%gil%epoc)
  if (secwarned)  differ = .true.
  !
end subroutine sic_diff_position
!
subroutine sic_diff_projection(h1,h2,differ,error)
  use gbl_message
  use image_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_projection
  !---------------------------------------------------------------------
  ! @ private
  !  Print the differences between 2 headers (section PROJECTION)
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: h1,h2
  logical,      intent(inout) :: differ
  logical,      intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='DIFF'
  character(len=*), parameter :: secname='Projection'
  logical :: secwarned
  !
  if (sic_diff_presec(secname,h1%gil%proj_words,h2%gil%proj_words,differ))  return
  !
  secwarned = .false.
  call gag_diff_elem(rname,secname,secwarned,'A0:',    h1%gil%a0,  h2%gil%a0)
  call gag_diff_elem(rname,secname,secwarned,'D0:',    h1%gil%d0,  h2%gil%d0)
  call gag_diff_elem(rname,secname,secwarned,'ANGLE:', h1%gil%pang,h2%gil%pang)
  call gag_diff_elem(rname,secname,secwarned,'PTYPE:', projnam(h1%gil%ptyp),projnam(h2%gil%ptyp))
  call gag_diff_elem(rname,secname,secwarned,'X_AXIS:',h1%gil%xaxi,h2%gil%xaxi)
  call gag_diff_elem(rname,secname,secwarned,'Y_AXIS:',h1%gil%yaxi,h2%gil%yaxi)
  if (secwarned)  differ = .true.
  !
end subroutine sic_diff_projection
!
subroutine sic_diff_spectroscopy(h1,h2,differ,error)
  use gbl_message
  use image_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_spectroscopy
  !---------------------------------------------------------------------
  ! @ private
  !  Print the differences between 2 headers (section SPECTROSCOPY)
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: h1,h2
  logical,      intent(inout) :: differ
  logical,      intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='DIFF'
  character(len=*), parameter :: secname='Spectroscopy'
  logical :: secwarned
  !
  if (sic_diff_presec(secname,h1%gil%spec_words,h2%gil%spec_words,differ))  return
  !
  secwarned = .false.
  call gag_diff_elem(rname,secname,secwarned,'LINE:',   h1%char%line,h2%char%line)
  call gag_diff_elem(rname,secname,secwarned,'FREQRES:',h1%gil%fres, h2%gil%fres)
  call gag_diff_elem(rname,secname,secwarned,'IMAGFRE:',h1%gil%fima, h2%gil%fima)
  call gag_diff_elem(rname,secname,secwarned,'RESTFRE:',h1%gil%freq, h2%gil%freq)
  call gag_diff_elem(rname,secname,secwarned,'VELRES:', h1%gil%vres, h2%gil%vres)
  call gag_diff_elem(rname,secname,secwarned,'VELOFF:', h1%gil%voff, h2%gil%voff)
  call gag_diff_elem(rname,secname,secwarned,'F_AXIS:', h1%gil%faxi, h2%gil%faxi)
  call gag_diff_elem(rname,secname,secwarned,'DOPPLER:',h1%gil%dopp, h2%gil%dopp)
  call gag_diff_elem(rname,secname,secwarned,'VTYPE:',  h1%gil%vtyp, h2%gil%vtyp)
  if (secwarned)  differ = .true.
  !
end subroutine sic_diff_spectroscopy
!
subroutine sic_diff_resolution(h1,h2,differ,error)
  use gbl_message
  use image_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_resolution
  !---------------------------------------------------------------------
  ! @ private
  !  Print the differences between 2 headers (section RESOLUTION)
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: h1,h2
  logical,      intent(inout) :: differ
  logical,      intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='DIFF'
  character(len=*), parameter :: secname='Resolution'
  logical :: secwarned
  !
  if (sic_diff_presec(secname,h1%gil%reso_words,h2%gil%reso_words,differ))  return
  !
  secwarned = .false.
  call gag_diff_elem(rname,secname,secwarned,'MAJOR:',h1%gil%majo,h2%gil%majo)
  call gag_diff_elem(rname,secname,secwarned,'MINOR:',h1%gil%mino,h2%gil%mino)
  call gag_diff_elem(rname,secname,secwarned,'PA:',   h1%gil%posa,h2%gil%posa)
  if (secwarned)  differ = .true.
  !
end subroutine sic_diff_resolution
!
subroutine sic_diff_noise(h1,h2,differ,error)
  use gbl_message
  use image_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_noise
  !---------------------------------------------------------------------
  ! @ private
  !  Print the differences between 2 headers (section NOISE)
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: h1,h2
  logical,      intent(inout) :: differ
  logical,      intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='DIFF'
  character(len=*), parameter :: secname='Noise'
  logical :: secwarned
  !
  if (sic_diff_presec(secname,h1%gil%nois_words,h2%gil%nois_words,differ))  return
  !
  secwarned = .false.
  call gag_diff_elem(rname,secname,secwarned,'NOISE:',h1%gil%noise,h2%gil%noise)
  call gag_diff_elem(rname,secname,secwarned,'RMS:',  h1%gil%rms,  h2%gil%rms)
  if (secwarned)  differ = .true.
  !
end subroutine sic_diff_noise
!
subroutine sic_diff_astrometry(h1,h2,differ,error)
  use gbl_message
  use image_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_astrometry
  !---------------------------------------------------------------------
  ! @ private
  !  Print the differences between 2 headers (section ASTROMETRY)
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: h1,h2
  logical,      intent(inout) :: differ
  logical,      intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='DIFF'
  character(len=*), parameter :: secname='Astrometry'
  logical :: secwarned
  !
  if (sic_diff_presec(secname,h1%gil%astr_words,h2%gil%astr_words,differ))  return
  !
  secwarned = .false.
  call gag_diff_elem(rname,secname,secwarned,'MU[1]:',   h1%gil%mura,    h2%gil%mura)
  call gag_diff_elem(rname,secname,secwarned,'MU[2]:',   h1%gil%mudec,   h2%gil%mudec)
  call gag_diff_elem(rname,secname,secwarned,'PARALLAX:',h1%gil%parallax,h2%gil%parallax)
  if (secwarned)  differ = .true.
  !
end subroutine sic_diff_astrometry
!
subroutine sic_diff_telescope(h1,h2,differ,error)
  use gbl_message
  use image_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_telescope
  !---------------------------------------------------------------------
  ! @ private
  !  Print the differences between 2 headers (section TELESCOPE)
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: h1,h2
  logical,      intent(inout) :: differ
  logical,      intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='DIFF'
  character(len=*), parameter :: secname='Telescope'
  logical :: secwarned
  character(len=64) :: elname
  integer(kind=4) :: itel
  !
  if (sic_diff_presec(secname,h1%gil%tele_words,h2%gil%tele_words,differ))  return
  !
  secwarned = .false.
  call gag_diff_elem(rname,secname,secwarned,'NTEL:',h1%gil%nteles,h2%gil%nteles)
  do itel=1,min(h1%gil%nteles,h2%gil%nteles)
    write(elname,'(A,I0,A)') 'TEL',itel,'%NAME:'
    call gag_diff_elem(rname,secname,secwarned,elname,h1%gil%teles(itel)%ctele,h2%gil%teles(itel)%ctele)
  enddo
  if (secwarned)  differ = .true.
  !
end subroutine sic_diff_telescope
!
subroutine sic_diff_uvdescr(h1,h2,differ,error)
  use gbl_message
  use image_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_uvdescr
  !---------------------------------------------------------------------
  ! @ private
  !  Print the differences between 2 headers (section UV_DATA
  ! description)
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: h1,h2
  logical,      intent(inout) :: differ
  logical,      intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='DIFF'
  character(len=*), parameter :: secname='UV Description'
  logical :: secwarned
  !
  if (sic_diff_presec(secname,h1%gil%uvda_words,h2%gil%uvda_words,differ))  return
  !
  secwarned = .false.
  call gag_diff_elem(rname,secname,secwarned,'VERSION_UV:',h1%gil%version_uv,h2%gil%version_uv)
  call gag_diff_elem(rname,secname,secwarned,'NCHAN:',     h1%gil%nchan,     h2%gil%nchan)
  call gag_diff_elem(rname,secname,secwarned,'NVISI:',     h1%gil%nvisi,     h2%gil%nvisi)
  call gag_diff_elem(rname,secname,secwarned,'NSTOKES:',   h1%gil%nstokes,   h2%gil%nstokes)
  call gag_diff_elem(rname,secname,secwarned,'NATOM:',     h1%gil%natom,     h2%gil%natom)
  call gag_diff_elem(rname,secname,secwarned,'BASEMIN:',   h1%gil%basemin,   h2%gil%basemin)
  call gag_diff_elem(rname,secname,secwarned,'BASEMAX:',   h1%gil%basemax,   h2%gil%basemax)
  if (secwarned)  differ = .true.
  !
end subroutine sic_diff_uvdescr
!
function sic_diff_presec(secname,len1,len2,differ)
  use gbl_message
  use sic_interfaces, except_this=>sic_diff_presec
  !---------------------------------------------------------------------
  ! @ private
  ! Return .true. if the section is absent from 1 or from the 2 headers
  !---------------------------------------------------------------------
  logical :: sic_diff_presec
  character(len=*), intent(in)    :: secname    ! Section name
  integer(kind=4),  intent(in)    :: len1,len2  ! Section lengths
  logical,          intent(inout) :: differ     !
  !
  if (len1.le.0 .and. len2.le.0) then
    sic_diff_presec = .true.
  elseif (len1.gt.0 .and. len2.le.0) then
    call sic_message(seve%r,'DIFF','Only in first header: '//(secname)//' section')
    sic_diff_presec = .true.
  elseif (len1.le.0 .and. len2.gt.0) then
    call sic_message(seve%r,'DIFF','Only in second header: '//(secname)//' section')
    sic_diff_presec = .true.
  else
    sic_diff_presec = .false.
  endif
  if (len1.le.0 .neqv. len2.le.0)  differ = .true.
  !
end function sic_diff_presec
!
subroutine sic_diff_datadescr(desc1,desc2,datatol,differ,error)
  use sic_interfaces, except_this=>sic_diff_datadescr
  use sic_types
  !---------------------------------------------------------------------
  ! @ private
  ! Show the differences between the data of two SIC variables
  !---------------------------------------------------------------------
  type(sic_descriptor_t), intent(in)    :: desc1,desc2
  real(kind=4),           intent(in)    :: datatol
  logical,                intent(inout) :: differ
  logical,                intent(inout) :: error
  ! Local
  logical :: isuvt1,istuv1,isuvt2,istuv2
  !
  isuvt1 = isuv(desc1,1)
  istuv1 = isuv(desc1,2)
  isuvt2 = isuv(desc2,1)
  istuv2 = isuv(desc2,2)
  !
  if (isuvt1.and.isuvt2) then
    ! Both are UVT tables
    call sic_diff_uvt(desc1,desc2,datatol,differ,error)
! elseif (istuv1.and.istuv2) then
!   ! Both are UVT tables
!   call sic_diff_tuv(desc1,desc2,datatol,error) => to be implemented
  else
    ! Maybe be non-gdf or images or mix of inconsistant data: basic comparison
    call sic_diff_image(desc1,desc2,datatol,differ,error)
  endif
  !
contains
  logical function isuv(desc,idime)
    type(sic_descriptor_t), intent(in) :: desc
    integer(kind=4),        intent(in) :: idime
    isuv = associated(desc%head) .and. &
          (desc%head%char%code(idime).eq.'UV-DATA' .or. &
           desc%head%char%code(idime).eq.'UV-RAW')
  end function isuv
  !
end subroutine sic_diff_datadescr
!
subroutine sic_diff_uvt(desc1,desc2,datatol,differ,error)
  use gbl_message
  use sic_interfaces, except_this=>sic_diff_uvt
  use sic_types
  !---------------------------------------------------------------------
  ! @ private
  ! Show the differences between the data of two UVT variables
  !---------------------------------------------------------------------
  type(sic_descriptor_t), intent(in)    :: desc1,desc2
  real(kind=4),           intent(in)    :: datatol
  logical,                intent(inout) :: differ
  logical,                intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='DIFF'
  integer(kind=4) :: icol
  logical :: secwarned
  !
  if (desc1%head%gil%nvisi.ne.desc2%head%gil%nvisi) then
    call sic_message(seve%w,rname,  &
      'Number of visibilities do not match, can not compare UV data')
    differ = .true.
    return
  endif
  !
  secwarned = .false.
  do icol=1,code_uvt_last
    call sic_diff_uvtcolumn(desc1,desc2,icol,datatol,secwarned,error)
    if (error)  return
  enddo
  if (secwarned)  differ = .true.
  !
  ! And now compare the UV data itself
  call sic_diff_uvtdata(desc1,desc2,datatol,differ,error)
  if (error)  return
  !
end subroutine sic_diff_uvt
!
subroutine sic_diff_uvtcolumn(desc1,desc2,colid,datatol,secwarned,error)
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_uvtcolumn
  use sic_types
  !---------------------------------------------------------------------
  ! @ private
  ! Show the differences between the data of two UV columns variables
  !---------------------------------------------------------------------
  type(sic_descriptor_t), intent(in)    :: desc1,desc2
  integer(kind=4),        intent(in)    :: colid
  real(kind=4),           intent(in)    :: datatol
  logical,                intent(inout) :: secwarned
  logical,                intent(inout) :: error
  ! Global
  include 'gbl_memory.inc'
  ! Local
  character(len=*), parameter :: rname='DIFF'
  logical :: hascol1,hascol2,same
  integer(kind=address_length) :: ipnt1,ipnt2
  integer(kind=4) :: colptr1,colptr2,ndata1,ndata2,nvisi1,nvisi2
  character(len=8) :: colname
  character(len=message_length) :: mess
  ! UV column names must match UV column codes
  !
  colname = uv_column_name(colid)
  hascol1 = desc1%head%gil%column_size(colid).gt.0
  hascol2 = desc2%head%gil%column_size(colid).gt.0
  if (hascol1 .and. .not.hascol2) then
    same = .false.
    mess = 'Only in first UV table: '//(colname)//' column'
  elseif (.not.hascol1 .and. hascol2) then
    same = .false.
    mess = 'Only in second UV table: '//(colname)//' column'
  elseif (hascol1.and.hascol2) then
    ipnt1 = gag_pointer(desc1%addr,memory)
    ipnt2 = gag_pointer(desc2%addr,memory)
    ndata1 = desc1%head%gil%dim(1)
    ndata2 = desc2%head%gil%dim(1)
    nvisi1 = desc1%head%gil%nvisi
    nvisi2 = desc2%head%gil%nvisi
    colptr1 = desc1%head%gil%column_pointer(colid)
    colptr2 = desc2%head%gil%column_pointer(colid)
    call sic_diff_uvtcolumn_ptr(memory(ipnt1),ndata1,nvisi1,colptr1,  &
                                memory(ipnt2),ndata2,nvisi2,colptr2,  &
                                datatol,same)
    mess = colname//' column data'
  else
    ! If both absent => no message
    same = .true.
  endif
  !
  if (.not.same) then
    if (.not.secwarned) then
      call sic_message(seve%r,rname,'UV DAPS differ')
      secwarned = .true.
    endif
    call sic_message(seve%r,rname,'  '//mess)
  endif
  !
end subroutine sic_diff_uvtcolumn
!
subroutine sic_diff_uvtcolumn_ptr(data1,ndata1,nvisi1,colptr1,  &
                                  data2,ndata2,nvisi2,colptr2,  &
                                  datatol,same)
  use sic_dependencies_interfaces
  !---------------------------------------------------------------------
  ! @ no-interface
  ! Show the differences between the data of two UV columns variables
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)  :: ndata1,ndata2
  integer(kind=4), intent(in)  :: nvisi1,nvisi2
  real(kind=4),    intent(in)  :: data1(ndata1,nvisi1)
  real(kind=4),    intent(in)  :: data2(ndata2,nvisi2)
  integer(kind=4), intent(in)  :: colptr1,colptr2
  real(kind=4),    intent(in)  :: datatol
  logical,         intent(out) :: same
  ! Local
  integer(kind=4) :: ivisi
  !
  same = .true.
  do ivisi=1,min(nvisi1,nvisi2)
    if (.not.nearly_equal(data1(colptr1,ivisi),data2(colptr2,ivisi),datatol)) then
      same = .false.
      return
    endif
  enddo
  !
end subroutine sic_diff_uvtcolumn_ptr
!
subroutine sic_diff_uvtdata(desc1,desc2,datatol,differ,error)
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_uvtdata
  use sic_types
  !---------------------------------------------------------------------
  ! @ private
  ! Show the differences between the data of two UV columns variables
  !---------------------------------------------------------------------
  type(sic_descriptor_t), intent(in)    :: desc1,desc2
  real(kind=4),           intent(in)    :: datatol
  logical,                intent(inout) :: differ
  logical,                intent(inout) :: error
  ! Global
  include 'gbl_memory.inc'
  ! Local
  character(len=*), parameter :: rname='DIFF'
  logical :: same
  integer(kind=address_length) :: ipnt1,ipnt2
  integer(kind=4) :: fcol1,lcol1,ndata1,nvisi1
  integer(kind=4) :: fcol2,lcol2,ndata2,nvisi2
  !
  fcol1 = desc1%head%gil%fcol
  lcol1 = desc1%head%gil%lcol
  fcol2 = desc2%head%gil%fcol
  lcol2 = desc2%head%gil%lcol
  !
  if (lcol1-fcol1.ne.lcol2-fcol2) then
    ! UV data block sizes differ. It might be different number of channels,
    ! different number of atoms per channel, or stokes, etc...
    call sic_message(seve%w,rname,'UV data block sizes differ, can not compare UV data')
    differ = .true.
    return
  endif
  !
  ipnt1 = gag_pointer(desc1%addr,memory)
  ipnt2 = gag_pointer(desc2%addr,memory)
  ndata1 = desc1%head%gil%dim(1)
  ndata2 = desc2%head%gil%dim(1)
  nvisi1 = desc1%head%gil%nvisi
  nvisi2 = desc2%head%gil%nvisi
  !
  call sic_diff_uvtdata_ptr(memory(ipnt1),ndata1,nvisi1,fcol1,lcol1,  &
                            memory(ipnt2),ndata2,nvisi2,fcol2,lcol2,  &
                            datatol,same)
  if (.not.same) then
    call sic_message(seve%r,rname,'UV DATA differ')
    differ = .true.
  endif
  !
end subroutine sic_diff_uvtdata
!
subroutine sic_diff_uvtdata_ptr(data1,ndata1,nvisi1,fcol1,lcol1,  &
                                data2,ndata2,nvisi2,fcol2,lcol2,  &
                                datatol,same)
  use gildas_def
  use sic_dependencies_interfaces
  !---------------------------------------------------------------------
  ! @ no-interface
  ! Show the differences between the data of two UV variables
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)  :: ndata1,ndata2
  integer(kind=4), intent(in)  :: nvisi1,nvisi2
  real(kind=4),    intent(in)  :: data1(ndata1,nvisi1)
  real(kind=4),    intent(in)  :: data2(ndata2,nvisi2)
  integer(kind=4), intent(in)  :: fcol1,fcol2
  integer(kind=4), intent(in)  :: lcol1,lcol2
  real(kind=4),    intent(in)  :: datatol
  logical,         intent(out) :: same
  ! Local
  integer(kind=4) :: ivisi
  integer(kind=size_length) :: ncol
  !
  same = .true.
  ncol = lcol1-fcol1+1
  do ivisi=1,min(nvisi1,nvisi2)
    if (.not.nearly_equal(data1(fcol1:lcol1,ivisi),  &
                          data2(fcol2:lcol2,ivisi),  &
                          ncol,datatol)) then
      same = .false.
      return
    endif
  enddo
  !
end subroutine sic_diff_uvtdata_ptr
!
subroutine sic_diff_image(desc1,desc2,datatol,differ,error)
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_diff_image
  use sic_types
  !---------------------------------------------------------------------
  ! @ private
  ! Show the differences between the data of two SIC variables
  !---------------------------------------------------------------------
  type(sic_descriptor_t), intent(in)    :: desc1,desc2
  real(kind=4),           intent(in)    :: datatol
  logical,                intent(inout) :: differ
  logical,                intent(inout) :: error
  ! Global
  include 'gbl_memory.inc'
  ! Local
  character(len=*), parameter :: rname='DIFF'
  character(len=*), parameter :: secname='Data descriptor'
  logical :: secwarned,same
  integer(kind=4) :: idime
  character(len=64) :: elname
  integer(kind=size_length) :: ndata1,ndata2
  integer(kind=address_length) :: ipnt1,ipnt2
  !
  secwarned = .false.
  call gag_diff_elem(rname,secname,secwarned,'TYPE:',desc1%type,desc2%type)
  call gag_diff_elem(rname,secname,secwarned,'NDIM:',desc1%ndim,desc2%ndim)
  do idime=1,min(desc1%ndim,desc2%ndim)
    write(elname,'(A,I0,A)') 'DIM[',idime,']:'
    call gag_diff_elem(rname,secname,secwarned,elname,desc1%dims(idime),desc2%dims(idime))
  enddo
  ndata1 = desc_nelem(desc1)
  ndata2 = desc_nelem(desc2)
  !
  if (desc1%type.ne.desc2%type .or. ndata1.ne.ndata2) then
    ! Only compare same data kind and size
    call sic_message(seve%w,rname,'Data not compared (incompatible data type or size)')
    differ = .true.
    return
  endif
  !
  ipnt1 = gag_pointer(desc1%addr,memory)
  ipnt2 = gag_pointer(desc2%addr,memory)
  select case (desc1%type)
  case (fmt_r4)
    ! ZZZ pass custom 'datatol'
    call gag_diff_datar4(rname,memory(ipnt1),memory(ipnt2),ndata1,same)
    if (.not.same)  differ = .true.
  case default
    call sic_message(seve%w,rname,'Data not compared (only R*4 implemented)')
  end select
  if (error)  return
  !
end subroutine sic_diff_image
