subroutine uv_resample_comm(line,comm,error)
  use gbl_message
  use gkernel_types
  use gkernel_interfaces
  use imager_interfaces, except_this=>uv_resample_comm
  !---------------------------------------------------------------------
  ! @ private
  !
  ! IMAGER
  !   Resample in velocity UV Tables or compress them
  !   Support for commands
  !     UV_RESAMPLE NC [Ref Val Inc] [/FILE FileIn FileOut]
  !     UV_COMPRESS NC [/FILE FileIn FileOut]
  !     UV_HANNING     [/FILE FileIn FileOut]
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: line  ! Command line
  character(len=*), intent(in) :: comm  ! Calling command
  logical, intent(out) :: error         ! Error flag
  !
  integer, parameter :: o_file=1
  character(len=filename_length) :: in_file, ou_file
  character(len=120) :: mess
  integer :: n
  type(gildas) :: hiuv, houv
  integer :: nblock
  integer :: nu, nv, ni, nt, nchan, nc, ier
  integer(kind=index_length)  :: ib           ! Blocked visibility counter
  integer(kind=index_length)  :: mvisi        ! Number of blocked visibilities
  integer(kind=index_length)  :: nvisi        ! Number of visibilities
  !
  if (.not.sic_present(o_file,0)) then
    call uv_resample_mem(line,comm,error)
  else
    !
    call sic_ch(line,o_file,1,in_file,n,.true.,error)
    if (error) return
    call sic_ch(line,o_file,2,ou_file,n,.true.,error)
    if (error) return
    !
    call gildas_null(hiuv,type='UVT')
    call gildas_null(houv,type='UVT')
    !
    call sic_parse_file(in_file,' ','.uvt',hiuv%file)
    call gdf_read_header(hiuv,error)
    if (error) return
    !
    call gdf_copy_header(hiuv,houv,error)
    Print *,'Input ',hiuv%gil%dim(1:2), hiuv%gil%ntrail
    call sic_parse_file(ou_file,' ','.uvt',houv%file)
    !
    call uv_resample_args(line,comm,hiuv,houv,error)
    if (error) return
    call gdf_create_image(houv,error)
    if (error) return
    !
    ! Set the Blocking Factor
    nblock = imager_nitems(hiuv,1)
    mvisi = nblock
    !
    allocate(hiuv%r2d(hiuv%gil%dim(1),mvisi),houv%r2d(houv%gil%dim(1),mvisi),stat=ier)
    if (ier.ne.0) then
      call map_message(seve%e,comm,'Memory allocation error')
      error = .true.
      return
    endif
    !
    !! Print *,'Trailings ',hiuv%gil%ntrail, houv%gil%ntrail
    call gdf_print_header(houv)
    !
    do ib=1,hiuv%gil%dim(2),mvisi
      !
      ! Read the data
      write(mess,*) ib,' / ',hiuv%gil%dim(2),mvisi
      call map_message(seve%i,comm,mess)
      hiuv%blc(2) = ib
      hiuv%trc(2) = min(hiuv%gil%dim(2),ib-1+mvisi)
      nvisi = hiuv%trc(2)-hiuv%blc(2)+1
      call gdf_read_data(hiuv,hiuv%r2d,error)
      if (error) return
      !
      ni = hiuv%gil%dim(1)
      nu = houv%gil%dim(1)
      nv = nvisi  ! Not houv%gil%dim(2)
      nt = houv%gil%ntrail
      nc = nint(real(hiuv%gil%nchan)/real(houv%gil%nchan))  ! Compression factor
      nchan = houv%gil%nchan
      !
      ! Now resample
      if (comm.eq.'UV_RESAMPLE') then
        hiuv%gil%nvisi = nvisi
        houv%gil%nvisi = nvisi
        call resample_uv (hiuv,houv,hiuv%r2d,houv%r2d,nt)
      else if (comm.eq.'UV_COMPRESS') then
        call compress_uv (houv%r2d,nu,nv,nchan,hiuv%r2d,ni,nc,nt) 
      else if (comm.eq.'UV_HANNING') then
        call hanning_uv (houv%r2d,nu,nv,nchan,hiuv%r2d,ni,nt)
      endif
      !
      houv%blc = hiuv%blc
      houv%trc = hiuv%trc
      call gdf_write_data (houv,houv%r2d,error)
      if (error) return
    enddo
    !
    deallocate(hiuv%r2d,houv%r2d)  
    call gdf_close_image(hiuv,error)
    call gdf_close_image(houv,error)
    if (error) return
    !
    call map_message(seve%i,comm,'Created '//trim(houv%file))
    !        
  endif
end subroutine uv_resample_comm
!
subroutine uv_resample_args(line,comm,hiuv,houv,error)
  use gkernel_types
  use gkernel_interfaces
  use gbl_message
  use imager_interfaces, except_this=>uv_resample_args
  !---------------------------------------------------------------------
  ! @ private
  !
  ! IMAGER
  !   Resample in velocity UV Tables or compress them
  !   Support for commands
  !     UV_RESAMPLE NC [Ref Val Inc] [/FILE FileIn FileOut]
  !     UV_COMPRESS NC [/FILE FileIn FileOut]
  !     UV_HANNING     [/FILE FileIn FileOut]
  !
  !   Decode the arguments and fill the output header accordingly
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: line  ! Command line
  character(len=*), intent(in) :: comm  ! Calling command
  logical, intent(out) :: error         ! Error flag
  type(gildas), intent(in) :: hiuv
  type(gildas), intent(inout) :: houv
  !
  character(len=4) :: arg(4)
  real(8) :: convert(3), velo
  integer :: nc, na, i
  character(len=120) :: chain
  !
  if (hiuv%gil%nstokes.gt.1) then
    call map_message(seve%e,comm,'Only single polarization data supported')
    error = .true.
    return
  endif
  !
  select case (comm)
  case ('UV_RESAMPLE')
    nc = 0
    !    SIC__CH would complain if argument is too long, SIC_KE is silent
    call sic_ke(line,0,1,arg(1),na,.true.,error)
    error = .false.
    if (arg(1).ne.'*') call sic_i4(line,0,1,nc,.true.,error)
    if (error) return
    !
    ! Set default resampling in Velocity
    convert(1) = hiuv%gil%ref(1)
    convert(2) = hiuv%gil%voff
    convert(3) = hiuv%gil%vres
    ! Get new one
    do i=2,sic_narg(0)
      call sic_ke(line,0,i,arg(i),na,.false.,error)
      error = .false.
      if (arg(i).ne.'*') call sic_r8(line,0,i,convert(i-1),.false.,error)
      if (error) return
    enddo
    !
    ! Fill missing arguments
    if (nc.eq.0) then
      nc = nint(abs(hiuv%gil%nchan*hiuv%gil%vres/convert(3)))
      if (arg(2).eq.'*') then
        ! Keep the middle channel in the middle
        velo = (0.5d0*hiuv%gil%nchan-hiuv%gil%ref(1))*hiuv%gil%vres + hiuv%gil%voff
        convert(1) = 0.5d0*nc - (velo-convert(2))/convert(3)
      endif
    endif
    !
    call getuv_conversion(houv,nc,convert)
    !
  case ('UV_COMPRESS') 
    call sic_i4(line,0,1,nc,.true.,error)
    if (error) return
    if (nc.gt.hiuv%gil%nchan) nc = hiuv%gil%nchan
    write(chain,'(A,I6,A)') 'Averaging by chunks of ',nc,' channels'
    call map_message(seve%i,comm,chain)
    houv%gil%inc(1) = houv%gil%inc(1)*nc
    houv%gil%ref(1) = (2.0d0*houv%gil%ref(1)+nc-1.0)/(2*nc)
    houv%gil%vres = nc*houv%gil%vres
    houv%gil%fres = nc*houv%gil%fres
    ! Change the number of channels
    houv%gil%nchan = houv%gil%nchan/nc
  case ('UV_HANNING')
    ! Drop the edge channels
    houv%gil%ref(1) = houv%gil%ref(1)+1
    houv%gil%nchan = houv%gil%nchan-2
  case default
    call map_message(seve%e,comm,'Unrecognized choice '//comm)
    error = .true.
    return
  end select
  !
  ! Work with complete structure
  houv%gil%dim(1) = 3*houv%gil%nchan + 7 + houv%gil%ntrail ! and nothing more ...
  if (houv%gil%ntrail.ne.0) then
    do i=1,code_uvt_last
      if (houv%gil%column_pointer(i).gt.houv%gil%lcol)  &
        houv%gil%column_pointer(i) =  houv%gil%column_pointer(i) + houv%gil%dim(1) - hiuv%gil%dim(1)
    enddo
  endif
end subroutine uv_resample_args
!
subroutine uv_resample_mem(line,comm,error)
  use gkernel_interfaces
  use imager_interfaces, except_this=>uv_resample_mem
  use clean_def
  use clean_arrays
  use clean_types
  use gbl_message
  use phys_const
  !---------------------------------------------------------------------
  ! @ private
  !
  ! IMAGER
  !   Resample in velocity the UV Table or compress it
  !   Support for commands
  !     UV_RESAMPLE NC [Ref Val Inc] 
  !     UV_COMPRESS [NC] 
  !     UV_HANNING     
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: line  ! Command line
  character(len=*), intent(in) :: comm  ! Calling command
  logical, intent(out) :: error         ! Error flag
  !
  real, pointer :: duv_previous(:,:), duv_next(:,:)
  character(len=80) :: chain
  character(len=4) :: arg(4)
  real(8) :: convert(3), velo
  integer :: nt, nc, nchan, na
  type (gildas) :: uvout
  integer :: nu, nv, ni, i
  !
  if (huv%loca%size.eq.0) then
    call map_message(seve%e,comm,'No UV data loaded')
    error = .true.
    return
  endif
  if (huv%gil%nstokes.gt.1) then
    call map_message(seve%e,comm,'Only single polarization data supported')
    error = .true.
    return
  endif
  !
  error = .false.
  ! No argument: get back to the original UV data
  if ((sic_narg(0).eq.0).and.(comm.ne.'UV_HANNING')) then
    call uv_reset_buffer(comm)
    call map_uvgildas('UV',huv,error,duv)
    do_weig = .true.
    return
  endif
  !
  ! Compute the Frequency Conversion from the Velocity Conversion
  call gildas_null(uvout, type = 'UVT')
  call gdf_copy_header(huv,uvout,error)
  !
  if (comm.eq.'UV_RESAMPLE') then
    nc = 0
    !    SIC__CH would complain if argument is too long, SIC_KE is silent
    call sic_ke(line,0,1,arg(1),na,.true.,error)
    error = .false.
    if (arg(1).ne.'*') call sic_i4(line,0,1,nc,.true.,error)
    if (error) return
    !
    ! Set default resampling in Velocity
    convert(1) = huv%gil%ref(1)
    convert(2) = huv%gil%voff
    convert(3) = huv%gil%vres
    ! Get new one
    do i=2,sic_narg(0)
      call sic_ke(line,0,i,arg(i),na,.false.,error)
      error = .false.
      if (arg(i).ne.'*') call sic_r8(line,0,i,convert(i-1),.false.,error)
      if (error) return
    enddo
    !
    ! Fill missing arguments
    if (nc.eq.0) then
      nc = nint(abs(huv%gil%nchan*huv%gil%vres/convert(3)))
      if (arg(2).eq.'*') then
        ! Keep the middle channel in the middle
        velo = (0.5d0*huv%gil%nchan-huv%gil%ref(1))*huv%gil%vres + huv%gil%voff
        convert(1) = 0.5d0*nc - (velo-convert(2))/convert(3)
      endif
    endif
    !
    call getuv_conversion(uvout,nc,convert)
    !
  else if (comm.eq.'UV_COMPRESS') then
    call sic_i4(line,0,1,nc,.true.,error)
    if (error) return
    if (nc.gt.huv%gil%nchan) nc = huv%gil%nchan
    write(chain,'(A,I6,A)') 'Averaging by chunks of ',nc,' channels'
    call map_message(seve%i,comm,chain)
    uvout%gil%inc(1) = uvout%gil%inc(1)*nc
    uvout%gil%ref(1) = (2.0d0*uvout%gil%ref(1)+nc-1.0)/(2*nc)
    uvout%gil%vres = nc*uvout%gil%vres
    uvout%gil%fres = nc*uvout%gil%fres
    ! Change the number of channels
    uvout%gil%nchan = uvout%gil%nchan/nc
  else if (comm.eq.'UV_HANNING') then
    ! Drop the edge channels
    uvout%gil%ref(1) = uvout%gil%ref(1)+1
    uvout%gil%nchan = uvout%gil%nchan-2
    continue
  else
    call map_message(seve%e,comm,'Unrecognized choice '//comm)
    error = .true.
    return
  endif
  !
  ! Work with complete structure
  uvout%gil%dim(1) = 3*uvout%gil%nchan + 7 + uvout%gil%ntrail ! and nothing more ...
  if (uvout%gil%ntrail.ne.0) then
    do i=1,code_uvt_last
      if (uvout%gil%column_pointer(i).gt.uvout%gil%lcol) uvout%gil%column_pointer(i) =  &
        & uvout%gil%column_pointer(i) + uvout%gil%dim(1) - huv%gil%dim(1)
    enddo
  endif
  !
  ni = huv%gil%dim(1)
  nu = uvout%gil%dim(1)
  nv = uvout%gil%dim(2)
  nt = uvout%gil%ntrail
  nchan = uvout%gil%nchan
  !
  ! Prepare appropriate array...
  nullify (duv_previous, duv_next)
  call uv_find_buffers (comm,nu,nv,duv_previous, duv_next,error)
  if (error) then
    call map_message(seve%e,comm,'Cannot set buffer pointers')
    return
  endif
  !
  ! Now resample
  if (comm.eq.'UV_RESAMPLE') then
    call resample_uv (huv,uvout,duv_previous,duv_next,nt)
  else if (comm.eq.'UV_COMPRESS') then
    call compress_uv (duv_next,nu,nv,nchan,duv_previous,ni,nc,nt)
  else if (comm.eq.'UV_HANNING') then
    call hanning_uv (duv_next,nu,nv,nchan,duv_previous,ni,nt)
  endif
  !
  ! Set header
  call gdf_copy_header(uvout,huv,error)
  !
  ! Reset proper pointers
  call uv_clean_buffers (duv_previous, duv_next,error)
  if (error) return
  !
  ! Indicate UV data has changed, and weight must be computed
  call uv_new_data(weight=.true.)
end subroutine uv_resample_mem
!
subroutine hanning_uv (duvout, nu, nv, nchan, duvin, ni, ntrail) 
  use gildas_def
  ! @ private
  integer, intent(in) :: nu           ! Ouput Visibility size
  integer, intent(in) :: nv           ! Number of visibilities
  integer, intent(in) :: nchan        ! Number of ouput channels
  integer, intent(in) :: ntrail       ! Trailing columns
  integer, intent(in) :: ni           ! Input Visibility size
  real, intent(in) :: duvin(ni,nv)    ! Input visibilities
  real, intent(out) :: duvout(nu,nv)  ! Output visibilities
  ! Local
  integer :: nlead
  integer :: i,j,k,kk
  real :: a,b,c,w(3),r
  data w/0.5,1.0,0.5/
  !
  nlead = 7
  !
  duvout = 0
  !
  do j=1,nv
    duvout (1:nlead,j) =  duvin (1:nlead,j)  
    do i=1,nchan
      a = 0
      b = 0
      c = 0
      do k=1,3
        kk = nlead+3*(i+k-1)  ! i=1, k=1, ==> kk=10
        if (duvin(kk,j).ne.0) then
          r = duvin(kk,j)*w(k)
          a = a+duvin(kk-2,j)*r
          b = b+duvin(kk-1,j)*r
          c = c+r
        endif
      enddo
      kk = nlead+3*i-2  ! i=1 ==> kk=8
      if (c.ne.0) then
        duvout(kk,j) = a/c
        duvout(kk+1,j) = b/c
        duvout(kk+2,j) = c         ! time*band
      else
        duvout(kk,j) = 0
        duvout(kk+1,j) = 0
        duvout(kk+2,j) = 0
      endif
    enddo
    if (ntrail.gt.0) then
      duvout(nu-ntrail+1:nu,j) = duvin(ni-ntrail+1:ni,j)
    endif
  enddo
end subroutine hanning_uv
