subroutine uv_merge_comm(line,error)
  use gkernel_interfaces
  use gkernel_types
  use gbl_message
  use imager_interfaces, only : map_message, sub_uv_merge_block
  use iso_c_binding
  !---------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Support for command
  !
  ! UV_MERGE OutFile /FILES In1 In2 ... Inn  
  !   /WEIGHTS W1 ... Wn /SCALES F1 ... Fn  
  !   /MODE STACK|CONTINUUM|CONCATENATE|INTERSECT|LINE|STITCH  
  !   [Index [Frequency]]  
  !   /IGNORE  TRAIL|POSITION|PROPER  
  !
  ! Merge many UV data files, with calibration factor and weight factors
  ! and spectral resampling as in the first  one.
  !
  ! With /CONTINUUM option, merge continuum UV Tables. A spectral index
  ! can then be automatically applied to the scales and weights.
  !!
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: line !! Command line
  logical, intent(out) :: error           !! Error flag
  !
  ! Constants
  integer, parameter :: o_files=1, o_no=2, o_mode=3, o_factor=4, o_weight=5 
  character(len=*), parameter :: rname='UV_MERGE'
  real(8), parameter :: clight_kms=229792.458d0
  integer, parameter :: mmode=6
  character(len=12) :: vmode(mmode)
  data vmode/'CONCATENATE','CONTINUUM','INTERSECT','LINE','STACKING','STITCHING'/
  !
  ! Local ---
  character(len=12)  :: cmode, argum
  type(c_ptr) :: cptr
  real(4), pointer :: r1ptr(:)
  real(8), pointer :: d1ptr(:)
  integer(kind=address_length) :: addr
  character(len=varname_length) :: listname
  character(len=filename_length) :: table_out
  character(len=filename_length), allocatable :: table_in(:)
  type(sic_descriptor_t) :: desc
  real, allocatable :: weight(:), factor(:)
  integer :: mode, i, n, nt, ier, ignore
  character(len=80) :: mess
  real :: sw
  real :: spindex   ! Spectral index
  real :: freqref   ! Reference Frequency
  logical :: err, found, notrail
  !
  ! Code ----
  error = .true.
  nt = sic_narg(o_files)
  notrail = sic_present(o_no,0)
  !
  if (nt.lt.2) then
    ! This may be a character array handling the file names
    call sic_ch(line,o_files,1,listname,n,.true.,error)
    if (error) return
    !
    call sic_descriptor(listname,desc,found)
    if (.not.found) then
      nt = 1
    else
      !
      ! Check the Descriptor: it must be a character array
      if (desc%type.lt.1 .or. desc%ndim.ne.1) then
        call map_message(seve%e,rname,trim(listname)//' is not a character array')
        error = .true.
        return
      endif
      nt = desc%dims(1)
    endif
  endif
  !
  if (nt.lt.2) then
    if (sic_present(o_mode,0)) then
      call sic_ke(line,o_mode,1,argum,n,.false.,error)
      call sic_ambigs(rname,argum,cmode,i,vmode,mmode,error)
      if (error) return
      select case(cmode)
      case ('STITCHING')
        continue
      case default
        call map_message(seve%e,rname,'Require at least 2 input tables')
        error = .true.
        return
      end select
    else
      call map_message(seve%e,rname,'Require at least 2 input tables')
      return
    endif
  endif
  !
  allocate(table_in(nt),weight(nt),factor(nt),stat=ier)
  if (ier.ne.0) then
    call map_message(seve%e,rname,'Memory allocation error')
    return
  endif
  !
  freqref = 0.0             ! Must be initialized in all cases
  weight = 1.0              !
  factor = 1.0              ! 
  !
  if (sic_present(o_weight,0)) then
    if (sic_narg(o_weight).ne.nt) then
      if (sic_narg(o_weight).eq.1) then
        ! Should be a SIC array variable in this case
        call sic_ch(line,o_weight,1,listname,n,.true.,err)
        if (err) return
        !
        call sic_descriptor(listname,desc,found)
        if (.not.found) then
          call map_message(seve%e,rname,'Number of Files and Weights mismatch')
          return
        else
          !
          ! Check the Descriptor and copy if possible
          if ( (desc%ndim.ne.1).or.(desc%dims(1).ne.nt) ) then
            call map_message(seve%e,rname,'Number of Files and Weights mismatch')
            return
          endif
          if (desc%type.eq.fmt_r4) then
            call adtoad(desc%addr,cptr,1)
            call c_f_pointer(cptr,r1ptr,[nt])
            weight(:) = r1ptr
          else if (desc%type.eq.fmt_r8) then
            call adtoad(desc%addr,cptr,1)
            call c_f_pointer(cptr,d1ptr,[nt])
            weight(:) = d1ptr
          else
            call map_message(seve%e,rname,trim(listname)//' is not a real array')
            error = .true.
            return
          endif
        endif
      else
        call map_message(seve%e,rname,'Number of Files and Weights mismatch')
        return
      endif
    else
      do i=1,nt
        call sic_r4(line,o_weight,i,weight(i),.true.,err)
        if (err) return
      enddo
      if (any(weight.le.0.)) then
        call map_message(seve%e,rname,'Weights must be positive')
        return
      endif
    endif
    !
    ! Normalize the Weights
    sw = sum(weight(1:nt))
    weight = weight/sw
  endif
  !
  if (sic_present(o_factor,0)) then
    if (sic_narg(o_factor).ne.nt) then
      if (sic_narg(o_weight).eq.1) then
        ! Should be a SIC array variable in this case
        call sic_ch(line,o_factor,1,listname,n,.true.,err)
        if (err) return
        !
        call sic_descriptor(listname,desc,found)
        if (.not.found) then
          call map_message(seve%e,rname,'Number of Files and Factors mismatch')
          return
        else
          ! Check the Descriptor and copy if possible
          if ( (desc%ndim.ne.1).or.(desc%dims(1).ne.nt) ) then
            call map_message(seve%e,rname,'Number of Files and Factors mismatch')
            return
          endif
          if (desc%type.eq.fmt_r4) then
            call adtoad(desc%addr,cptr,1)
            call c_f_pointer(cptr,r1ptr,[nt])
            factor(:) = r1ptr
          else if (desc%type.eq.fmt_r8) then
            call adtoad(desc%addr,cptr,1)
            call c_f_pointer(cptr,d1ptr,[nt])
            factor(:) = d1ptr
          else
            call map_message(seve%e,rname,trim(listname)//' is not a real array')
            error = .true.
            return
          endif
        endif
      else
        call map_message(seve%e,rname,'Number of Files and Factors mismatch')
        return
      endif
    else
      do i=1,nt
        call sic_r4(line,o_factor,i,factor(i),.true.,err)
        if (err) return
      enddo
      if (any(factor.le.0.)) then
        call map_message(seve%e,rname,'factors must be positive')
        return
      endif
    endif
  endif  
  !
  if (sic_narg(o_files).eq.1) then
    ! This may be a character array handling the file names
    call sic_ch(line,o_files,1,listname,n,.true.,error)
    if (error) return
    call sic_descriptor(listname,desc,found)    
    ! Names from Character array
    addr = desc%addr
    do i=1,nt
      call destoc(desc%type,addr,table_in(i))
      addr = addr + desc%type
    enddo
  else
    ! Names from Command line
    do i=1,nt
      call sic_ch(line,o_files,i,table_in(i),n,.true.,err)
      if (err) return
    enddo
  endif
  error = .false.
  !
  call sic_ch(line,0,1,table_out,n,.true.,error)
  if (error) return
  !
  mode = 0    ! Simple line merge
  ignore = 0  ! Check all Leading & Trailing columns
  if (sic_present(o_mode,0)) then
    call sic_ke(line,o_mode,1,argum,n,.false.,error)
    call sic_ambigs(rname,argum,cmode,i,vmode,mmode,error) 
    if (error) return   
    select case(cmode)
    case ('CONTINUUM')   ! For CONTinuum
      ! Continuum mode
      spindex = 0.
      call sic_r4(line,o_mode,2,spindex,.false.,error)
      freqref = 0.
      call sic_r4(line,o_mode,3,freqref,.false.,error)
      mode = 1
      write(mess,'(A,F6.2,A,F8.0,A)') 'Selected continuum mode, Spectral index ', &
        & spindex,' Reference frequency ',freqref,' MHz'
      ignore = code_uvt_if
      call map_message(seve%i,rname,mess)
    case ('STACKING')   ! For STACking  
      ! Line-Stacking mode
      call map_message(seve%w,rname,'Selected Line Stacking mode',3)
      mode = 2
    case ('CONCATENATE') 
      ! Simple concatenat
      call map_message(seve%w,rname,'Selected Line Concatenation mode',3)
      mode = -1  ! Use full bandwidth
    case ('LINE')
      mode = 0
    case ('INTERSECT')
      call map_message(seve%i,rname,'Selected Line Intersection mode',3)
      mode = -3
    case ('STITCHING')
      mode = -2
      call map_message(seve%w,rname,'Mode STITCHING under test '//cmode)
      call sub_uv_stitch(nt, table_in, table_out, &
        & weight, factor, mode, spindex, freqref, error)
      return
    case default
      call map_message(seve%e,rname,'No such mode '//cmode)
      error = .true.
      return
    end select
  endif    
  !
  call sub_uv_merge_block(nt, table_in, table_out, &
    & weight, factor, mode, spindex, freqref, error, & 
    & ignore, notrail)
  return
  !
end subroutine uv_merge_comm
!
subroutine sub_uv_merge_block(n_in, table_in, table_out, &
     weight, factor, mode, spindex, freqref, error, & 
     ignore, notrail)
  use gildas_def
  use gkernel_interfaces
  use image_def
  use gbl_message
  use clean_def
  use clean_default
  use imager_interfaces, except_this => sub_uv_merge_block
  !---------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER  -- Merge an arbitray number of UV tables;
  !
  ! with the first one used as a reference, and all other resampled
  ! accordingly. Calibration and weight factors are applied to all
  ! data, as well as a UV scaling factor when reference frequencies
  ! are modified.
  !
  !!
  !---------------------------------------------------------------------
  integer, intent(in) :: n_in           !! Number of input tables
  character(len=*), intent(in) :: table_out   !! Output Table name
  character(len=*), intent(in) :: table_in(*) !! Other tables names
  real, intent(in)  :: weight(*)        !! Weight factors   
  real, intent(in)  :: factor(*)        !! Scale factors
  integer, intent(in)  :: mode          !! Selected mode
  logical, intent(out) :: error         !! Error flag
  real, intent(in) :: spindex           !! Spectral index
  real, intent(in) :: freqref           !! Reference Frequency
  integer, intent(in) :: ignore         !! /IGNORE option
  logical, intent(in) :: notrail        !! Ignore trailing columns
  !
  ! Constants
  real(8), parameter :: clight_kms=229792.458d0
  character(len=*), parameter :: rname='UV_MERGE'
  integer, parameter :: code_line=0
  integer, parameter :: code_cont=1
  integer, parameter :: code_stack=2
  integer, parameter :: code_concat=-1
  integer, parameter :: code_stitch=-2
  integer, parameter :: code_inter=-3
  real(kind=8), parameter :: pi=3.14159265358979323846d0
  real(kind=8), parameter :: f_to_k = 2.d0*pi/299792458.d-6
  !
  ! Local ---
  character(len=256) :: table_ref   ! Reference Table name
  type(gildas) :: in,inref,out,hraw,htmp
  integer, allocatable :: iwork(:,:)
  real(4), allocatable :: rwork(:,:)
  real :: scale_uv(3), noscale_uv(3)
  real(8) :: rfreq
  real :: fact, weig
  integer :: nblock, i, ier, im
  character(len=80) :: mess
  character(len=40) :: cmes
  integer :: code
  integer(kind=size_length) :: in_gil_dim1,in_gil_dim2, nvisi
  integer, allocatable :: chflag(:)
  integer, allocatable :: channels(:,:) ! Channel range for each Table
  !
  real(4) :: velos
  real(8) :: freqs
  character(len=12) :: cline
  real(8) :: ctol=0.1
  real(8) :: freq, vinf, vsup, vmin, vmax, vres, cfreq
  integer :: im_first
  real :: uvmax, uvmin, basemin, basemax
  integer :: msize, multiplier, iv, ic, sever
  type (uvmap_par) :: map
  integer, allocatable :: multis(:)    ! Each file has its own multiplier
  logical, allocatable :: resample(:)  ! and its own resampling
  logical :: new=.true.
  !
  ! Code ----
  error = .true.
  if (n_in.eq.0) return
  if (len_trim(table_out).eq.0) return
  !
  table_ref = table_in(1)
  if (len_trim(table_ref).eq.0) return
  error = .false.
  !
  ! Input file TABLE_REF  (INREF) is the reference one
  call gildas_null(inref, type = 'UVT')
  call gildas_null(in, type = 'UVT')
  call gildas_null(out, type = 'UVT')
  call gildas_null(hraw, type = 'UVT')
  !     
  multiplier = 1 ! Number of output visibilities per input one
  scale_uv = 1.0 ! UV scale by default
  allocate(resample(n_in),multis(n_in),channels(3,n_in),stat=ier)
  if (ier.ne.0) then
    call map_message(seve%e,rname,'Memory allocation error')
    error = .true.
    return
  endif
  resample = .false.
  multis(:) = 1
  !
  basemin = 1E38
  basemax = 0.0
  !
  ! Dummy initialization to avoid messages
  in_gil_dim1 = 1
  in_gil_dim2 = 1
  rfreq = 1.d0
  cfreq = 0.d0
  !
  if (mode.eq.code_stitch) then
    !
    ! Pure Stitching -
    ! All UV tables must have the same Time-Baseline ordering
    !   Channels are "glued" together, using a Random Frequency axis
    !
    im_first = 0
  else if ((mode.eq.code_concat).or.(mode.eq.code_inter)) then
    !
    ! Figure out the Central frequency
    cfreq = 0d0
    do im=1,n_in    ! This loop must execute sequentially
      call gdf_read_gildas (hraw, table_in(im), '.uvt', error, data=.false.)
      if (error) then
        write(mess,'(A,I0)') 'Cannot read input UV table #',im
        call map_message(seve%e,rname,mess)
        return
      endif
      call gdf_close_image(hraw,error)
      cfreq = cfreq+hraw%gil%freq
    enddo
    cfreq = cfreq/n_in
    write(mess,'(A,F10.3,A)') 'Using center frequency ',cfreq,' MHz'
    call map_message(seve%i,rname,mess)
    !
    ! Figure out the Frequency / Velocity span
    if (mode.eq.code_concat) then
      vinf = 3E9    ! Faster than light...
      vsup = -3E9
    else
      vinf = -3E9
      vsup =  3E9
    endif
    vres = 3E9
    do im=1,n_in    ! This loop must execute sequentially
      call gdf_read_gildas (hraw, table_in(im), '.uvt', error, data=.false.)
      call gdf_close_image (hraw,error)
      ! Reset the common Frequency scale
      call gdf_modify(hraw,hraw%gil%voff,cfreq,error=error)
      !
      call gdf_copy_header(hraw,in,error)
      if (in%gil%vres .gt. 0) then
        vmin = (1-in%gil%ref(1))*in%gil%vres  + in%gil%voff
        vmax = (in%gil%nchan-in%gil%ref(1))*in%gil%vres  + in%gil%voff
        vres = min(vres,in%gil%vres)
      else
        vmin = (in%gil%nchan-in%gil%ref(1))*in%gil%vres  + in%gil%voff
        vmax = (1-in%gil%ref(1))*in%gil%vres  + in%gil%voff
        vres = min(vres,-in%gil%vres)
      endif
      !
      if (mode.eq.code_concat) then
        vinf = min(vmin,vinf)
        vsup = max(vmax,vsup)
      else
        vinf = max(vmin,vinf)
        vsup = min(vmax,vsup)
      endif
    enddo
    !
    ! Setup the Outer UV table
    call gdf_copy_header(in,inref,error)
    !
    ! Compute the number of channels
    inref%gil%nchan = int(vsup-vinf)/vres + 1
    ! vinf = (1-ref)*vinc + voff ==>  ref = (voff-vinf)/vinc + 1.
    inref%gil%vres = vres
    inref%gil%voff = in%gil%voff
    inref%gil%ref(1) = (in%gil%voff - vinf)/vres + 1.d0
    inref%gil%fres = -vres * in%gil%val(1) / 299792.458d0
    resample(:) = .true.
    !
    inref%gil%dim(1) = in%gil%dim(1) + 3*(inref%gil%nchan-in%gil%nchan)
    !
    in_gil_dim1 = inref%gil%dim(1)  ! Must be the HRAW one
    in_gil_dim2 = inref%gil%dim(2)  ! idem
    !
    im_first = 0
    ! Do not forget trailing columns
    call gdf_uv_shift_columns(in,inref)
    call gdf_setuv (inref, error)
    call gdf_copy_header (inref, out, error)
    call sic_parse_file(table_out,' ','.uvt',out%file)
    !
    if (cfreq.eq.0) then
      !!Print *,'Setting RFREQ for ',im,' From Header ',inref%gil%freq
      rfreq = inref%gil%freq
    else
      !!Print *,'Setting RFREQ for ',im,' From Reference ',freqref
      rfreq = cfreq
    endif
    out%gil%freq = rfreq
    out%gil%dim(2) = 0 ! To get started
    !
    !!call gdf_print_header(out)
    !!read(5,*) idum
    !!if (idum.lt.0) then
    !!  error = .true.
    !!  return
    !!endif
    cmes = ' on the concatenated spectral axis'
  else if (mode.eq.code_cont) then
    if (freqref.eq.0) then
      ! Figure out the Central frequency
      cfreq = 0d0
      do im=1,n_in    ! This loop must execute sequentially
        call gdf_read_gildas (hraw, table_in(im), '.uvt', error, data=.false.)
        if (error) then
          write(mess,'(A,I0)') 'Cannot read input UV table #',im
          call map_message(seve%e,rname,mess)
          return
        endif
        call gdf_close_image(hraw,error)
        cfreq = cfreq+hraw%gil%freq
      enddo
      cfreq = cfreq/n_in
      write(mess,'(A,F10.3,A)') 'Using center frequency ',cfreq,' MHz'
      call map_message(seve%i,rname,mess,3)
    else
      cfreq = freqref
    endif
    im_first = 1
  else
    cmes = ' on the spectral axis  of first UV table'
    im_first = 1
  endif
  !
  ! Loop over tables to be merged
  do im=1,n_in    ! This loop must execute sequentially
    call gdf_read_gildas (hraw, table_in(im), '.uvt', error, data=.false.)
    if (error) then
      write(mess,'(A,I0)') 'Cannot read input UV table # ',im
      call map_message(seve%e,rname,mess)
      return
    endif
    call gdf_close_image(hraw,error)
    !
    ! Verify Baseline lengths are present
    if (hraw%gil%basemax.le.hraw%gil%basemin) then
      call map_message(seve%e,rname,'Missing baseline lengths range in file '//trim(table_in(im)))
      call map_message(seve%i,rname,'Use command HEADER '//trim(table_in(im))//' /EXTREMA to set them')
      error = .true.
      return
    endif
    !
    call gdf_copy_header(hraw,in,error)
    !
    if (mode.eq.code_cont) then
      if (in%gil%nchan.ne.1) then
        channels(1:3,im) = 0
        !
        msize = maxval(default_map%size)
        if (msize.eq.0) then
          map = default_map
          freq = gdf_uv_frequency(in)
          uvmax = in%gil%basemax
          uvmin = in%gil%basemin
          !            call uvgmax (huv,duv,uvmax,uvmin)
          ! Now transform UVMAX in kiloWavelength (including 2 pi factor)
          uvmax = uvmax*freq*f_to_k
          uvmin = uvmin*freq*f_to_k
          error = .false.
          call map_parameters(rname,map,in,freq,uvmax,uvmin,error)
          if (error) return
          msize = maxval(map%size)
        endif
        channels(1,im) = 1
        channels(2,im) = in%gil%nchan
        call t_channel_sampling (rname,in,channels(3,im),msize)
        !
        call map_message(seve%w,rname,'Converting UV Table into CONTINUUM mode')
        !
        ! Compute the corresponding Continuum Header that we put at "in"
        call uv_cont_header(rname,hraw,in,channels(1:3,im),multis(im),error)
        multis(im) = max(in%gil%nvisi/hraw%gil%nvisi,multis(im))
      endif
    endif
    !
    if (im.eq.im_first) then
      ! Prepare output table: compute number of visibilities
      call gdf_copy_header (in, inref, error)
      !
      call gdf_copy_header (inref, out, error)
      call sic_parse_file(table_out,' ','.uvt',out%file)
      !
      in_gil_dim1 = hraw%gil%dim(1)  ! Must be the HRAW one
      in_gil_dim2 = hraw%gil%dim(2)  ! idem
      !
      if (cfreq.eq.0) then
        !!Print *,'Setting RFREQ for ',im,' From Header ',inref%gil%freq
        rfreq = inref%gil%freq
      else
        !!Print *,'Setting RFREQ for ',im,' From Reference ',freqref
        rfreq = cfreq
      endif
      ! Reset frequency and Reference channel
      if (mode.eq.code_cont) then
        rfreq  = rfreq / (1.d0+in%gil%dopp - in%gil%voff/clight_kms)
        call gdf_modify(out,out%gil%voff,rfreq,error=error)
        out%gil%ref(1) = 1.d0
      endif
    else
      !
      ! Verify Proper Motion & Epoch match
      if ((in%gil%mura.ne.out%gil%mura).or.(in%gil%mudec.ne.out%gil%mudec)) then
        call map_message(seve%e,rname,'Proper Motions do not match')
        error = .true.
      else if ((in%gil%mura.ne.0.).or.(in%gil%mudec.ne.0.)) then
        if (in%gil%epoc.ne.out%gil%epoc) then
          call map_message(seve%e,rname,'Proper Motions match, but Epochs do not match')
          error = .true.
        endif
      endif
      if (error) return
      !
      out%gil%dim(2) = in%gil%dim(2) + out%gil%dim(2)
      out%gil%nvisi = out%gil%dim(2)  ! Set the number of visibilities
      in_gil_dim1 = max(in_gil_dim1,hraw%gil%dim(1))
      in_gil_dim2 = max(in_gil_dim2,hraw%gil%dim(2))
      !
      ! Verify if trailing columns do match
      call gdf_uvmatch_codes(inref,in,code,ignore)
      if (code.eq.3) then
        ! Column # 3 has a mismatch - Make sure the Ref is now SCAN
        inref%gil%column_pointer(code_uvt_w) = 0
        inref%gil%column_size(code_uvt_w) = 0
        inref%gil%column_pointer(code_uvt_scan) = 3
        inref%gil%column_size(code_uvt_scan) = 1
      else if (code.lt.0) then
        if (notrail) then
          sever = seve%w
          error = .false.
        else
          sever = seve%e
          error = .true. 
        endif
        if (code.eq.-1) then
          call map_message(sever,rname,'Leading columns do not match')
        else if (code.eq.-2) then
          call map_message(sever,rname,'Trailing columns do not match')
        else
          call map_message(sever,rname,'Leading columns do not match')
        endif
        call gdf_print_header(inref)
        call gdf_print_header(in)
        if (error) return
      endif
      !
      !
      if (mode.ne.code_cont) then
        ! LINE or STACK modes: verify compliant spectral axes
        !
        if (mode.eq.code_line) then
          if (abs(out%gil%freq-in%gil%freq).gt.0.01*abs(out%gil%fres)) then
            write (mess,'(A,I0,A)') 'UV table ',im,' does not align in Frequency with first UV table'
            call map_message(seve%w,rname,mess,3)
            !
            ! Modify the OUT Reference frequency & Velocities to get the same values
            freqs = in%gil%freq
            velos = in%gil%voff
            cline = in%char%line
            call gdf_modify(out,velos,freqs,error=error)
            out%char%line = cline
          endif
        endif
        !
        call shouldresample( rname, &
          & out%gil%nchan, out%gil%ref(1), dble(out%gil%voff), dble(out%gil%vres), &
          & in%gil%nchan, in%gil%ref(1), dble(in%gil%voff), dble(in%gil%vres),    &
          & ctol,resample(im),error)
        !
        if (resample(im)) then
          if (error) then
            write (mess,'(A,I0,A)') 'UV table ',im,' does not overlap with first UV table'
            call map_message(seve%w,rname,mess,3)
            return
          else
            write (mess,'(A,I0,A)') 'Resampling UV table ',im,cmes
            call map_message(seve%i,rname,mess,3)
          endif
        else
          write (mess,'(A,I0,A)') 'Adding UV table ',im,' without resampling'
          call map_message(seve%i,rname,mess)
        endif
      endif
    endif
    !
    ! Update baseline lengths
    if (out%gil%nchan.eq.1 .and. in%gil%nchan.eq.1) then
      scale_uv = in%gil%freq / rfreq
    else if  (mode.eq.code_cont) then
      scale_uv = in%gil%freq / rfreq
    else if  (mode.eq.code_stack) then
      scale_uv = in%gil%freq / inref%gil%freq
    else
      scale_uv = 1.0
    endif
    ! Do not scale the SCAN numbers...
    if (inref%gil%column_pointer(code_uvt_scan).eq.3) scale_uv(3) = 1.0
    !
    basemin = min(basemin,in%gil%basemin*scale_uv(1))
    basemax = max(basemax,in%gil%basemax*scale_uv(1))
    !
  enddo
  !
  ! Update Baselines
  out%gil%basemin = basemin
  out%gil%basemax = basemax
  !
  if (mode.eq.code_cont .and. out%gil%nchan.ne.1) then
    call map_message(seve%w,rname,'CONTINUUM mode is only valid for 1 channel')
    error = .true.
    return
  endif
  !
  ! Finished preparatory work, and create the OUT table
  call map_message(seve%i,rname,'Creating UV table '//trim(out%file))
  call gdf_create_image(out, error)
  if (error) then
    call map_message(seve%e,rname,'Cannot create output UV table')
    return
  endif
  !
  ! Define blocking factor on input file
  call gdf_nitems('SPACE_GILDAS',nblock,in_gil_dim1) ! Visibilities at once
  nblock = min(nblock,in_gil_dim2)
  multiplier = maxval(multis)
  allocate (out%r2d(out%gil%dim(1),nblock*multiplier), stat=ier)
  if (ier.ne.0) then
    write(mess,*) 'Memory allocation error OUT ',out%gil%dim(1), nblock, multiplier
    call map_message(seve%e,rname,mess)
    call gdf_close_image(out, error)
    error = .true.
    return
  endif
  !
  if (out%gil%nchan.eq.1 .and. in%gil%nchan.eq.1) then
    call map_message(seve%i,rname,'Merging continuum tables')
  else if (mode.eq.code_cont) then
    call map_message(seve%i,rname,'Merging line tables in continuum mode')  
  else 
    allocate (iwork(2,out%gil%nchan), rwork(4,out%gil%nchan), stat=ier)
    if (ier.ne.0) then
      write(mess,*) 'Memory allocation error WORK ',6,out%gil%nchan
      call map_message(seve%e,rname,mess)
      call gdf_close_image(out, error)
      error = .true.
      return
    endif
    call map_message(seve%i,rname,'Merging line tables')
  endif
  !
  ! Append INs to OUT with resampling and rescaling when needed
  out%blc(2) = 0    ! Get started
  call gildas_null(htmp,type='UVT')
  call gdf_copy_header(out,htmp,error)
  !
  do im = 1,n_in
    mess = 'Reading '//trim(table_in(im))
    call map_message(seve%i,rname,mess)
    call gdf_read_gildas (in, table_in(im), '.uvt', error, data=.false.)
    if (error) then
      write(mess,*) 'Cannot read input UV table #',im
      call map_message(seve%e,rname,mess)
      goto 98
    endif
    !
    allocate (in%r2d(in%gil%dim(1),nblock), stat=ier)
    if (ier.ne.0) then
      write(mess,*) 'Memory allocation error IN ',in%gil%dim(1), nblock
      call map_message(seve%e,rname,mess)
      goto 98
    endif
    !
    if (mode.eq.code_concat) call gdf_modify(in,in%gil%voff,cfreq,error=error)
    !
    if (out%gil%nchan.eq.1 .and. in%gil%nchan.eq.1) then
      scale_uv = in%gil%freq / rfreq
      !!Print *,'1 CHANNEL Frequencies ',in%gil%freq,rfreq,' Scale ',scale_uv
    else if (mode.eq.code_cont) then
      !
      ! Compute the output header
      call uv_cont_header(rname,in,hraw,channels(1:3,im),multis(im),error)
      !
      ! Allocate the appropriate work-space
      allocate (hraw%r2d(hraw%gil%dim(1),nblock*multiplier),chflag(in%gil%nchan),stat=ier)
      if (ier.ne.0) then
        write(mess,*) 'Memory allocation error IN ',in%gil%dim(1), nblock
        call map_message(seve%e,rname,mess)
        goto 98
      endif
      scale_uv = in%gil%freq / rfreq
      chflag = 1
      !!Print *,'CONTINUUM Frequencies ',in%gil%freq,rfreq,' Scale ',scale_uv
    else
      if (mode.eq.code_stack) then
        !   In Stacking Mode, Lambda/D is conserved, so the UV length
        ! must be scaled by FreqIn/ FreqRef
        scale_uv = in%gil%freq / inref%gil%freq
        !!Print *,'STACK Frequencies ',in%gil%freq,rfreq,' Scale ',scale_uv
      else
        scale_uv = 1.0
      endif
    endif
    fact = factor(im)
    weig = weight(im)
    if (out%gil%nchan.eq.1 .and. in%gil%nchan.eq.1) then
      if (spindex.ne.0) then
        fact = factor(im) / (scale_uv(1))**spindex
        weig = weight(im) * (scale_uv(1))**(2*spindex)
      endif
    endif    
    ! Do not scale the SCAN numbers...
    if (inref%gil%column_pointer(code_uvt_scan).eq.3) scale_uv(3) = 1.0
    write(mess,'(A,F8.2,A,F8.2,A,F8.4)') 'Factors: Flux ',fact, &
      & ', Weight ',weig,' UV ',scale_uv(1)
    call map_message(seve%i,rname,mess)
    !
    out%blc(2) = out%trc(2)+1
    !
    in%blc = 0
    in%trc = 0
    !
    ! Block loop on current input file
    do i=1,in%gil%dim(2),nblock
      if (sic_ctrlc()) goto 98
      !
      write(mess,*) i,' / ',in%gil%dim(2),min(100,nint((i+nblock-1)*100./in%gil%dim(2))),' %'
      call map_message(seve%i,rname,mess)
      in%blc(2) = i
      in%trc(2) = min(in%gil%dim(2),i-1+nblock)
      call gdf_read_data(in,in%r2d,error)
      if (error) goto 98
      !
      if (out%gil%nchan.eq.1 .and. in%gil%nchan.eq.1) then
        !
        ! Simple continuum mode
        nvisi = in%trc(2)-in%blc(2)+1
        out%trc(2) = out%blc(2)+nvisi-1
        call uvmergec (nvisi, out%gil%dim(1), out%r2d,  &
       &       in%gil%dim(1),in%r2d,weig,fact,      &
       &       scale_uv)
      else if (mode.eq.code_cont) then
        !
        ! Put the data into "hraw" as a working buffer now...
        nvisi = in%gil%nvisi
        in%gil%nvisi = in%trc(2)-in%blc(2)+1
        in%trc = 0  !
        in%blc = 0  ! Use everything in the block
        call t_continuum(in,hraw,channels(1:3,im),chflag,1,error,spindex,rfreq)
        if (error) goto 98
        in%gil%nvisi = nvisi
        nvisi = hraw%gil%nvisi 
        out%trc(2) = out%blc(2)+nvisi-1
        noscale_uv = [1.0,1.0,1.0]
        call uvmergec (nvisi, out%gil%dim(1), out%r2d,  &
       &       hraw%gil%dim(1),hraw%r2d,weig,fact,noscale_uv)
      else
        !      
        ! Line mode
        nvisi = in%trc(2)-in%blc(2)+1
        out%trc(2) = out%blc(2)+nvisi-1
        !
        if (new) then
          ! No scaling factor so far...
          if (resample(im)) then
            call resample_uv(in,htmp,in%r2d,out%r2d,nvisi,out%gil%ntrail) 
          else
            out%r2d(:,:) = in%r2d(:,:)
          endif
          !
          ! Apply scaling factors
          if (any(scale_uv.ne.1) .or. weig.ne.1 .or. fact.ne.1) then
            do iv=1,nvisi
              out%r2d(1:3,iv) = scale_uv * out%r2d(1:3,iv)
              if (weig.ne.1 .or. fact.ne.1) then
                do ic=1,out%gil%nchan
                  out%r2d(5+3*ic:6+3*ic,iv) = fact*out%r2d(5+3*ic:6+3*ic,iv)
                  out%r2d(7+3*ic,iv) = weig*out%r2d(7+3*ic,iv)
                enddo
              endif
            enddo
          endif
        else
          ! Bugged code, non parallel also
          !		Print *,'Line mode ',nvisi, out%trc
          !		Print *,'Nchan ',out%gil%nchan
          call uvmergel (nvisi, out%gil%nchan, out%r2d,    &
         &       in%gil%nchan,in%r2d,weig,fact, scale_uv,  &
         &       iwork, rwork, &
         &       out%gil%ref(1), dble(out%gil%voff), dble(out%gil%vres), &
         &       in%gil%ref(1), dble(in%gil%voff), dble(in%gil%vres),    &
         &       resample(im))
        endif
        !
      endif
      call gdf_write_data(out,out%r2d,error)
      if (error) goto 98
      out%blc(2) = out%trc(2)+1
    enddo     ! Block loop
    !
    call gdf_close_image(in,error)
    deallocate (in%r2d,stat=ier)
    if (associated(hraw%r2d)) deallocate (hraw%r2d,stat=ier)
    if (allocated(chflag)) deallocate (chflag)
  enddo       ! File loop
  !
  call gdf_close_image(out,error)
  deallocate(out%r2d)
  return
  !
  ! Error handling
98      continue
  call gdf_close_image(out, error)
  call gdf_close_image(in, error)
  error = .true.
  return
end subroutine sub_uv_merge_block
!
subroutine old_uvmergel (nv,ncx,x,ncz,z,weight,factor,scaleuv,iwork,rwork &
  & ,xref,xval,xinc,zref,zval,zinc)
  use gildas_def
  !------------------------------------------------------------------------
  ! @ private
  !
  ! Merge two line data sets:  Append them after interpolation (if needed)
  !------------------------------------------------------------------------
  integer(kind=size_length), intent(in) :: nv   !! Number of visibilities
  integer, intent(in) :: ncx                    !! Number of channels
  real, intent(inout) :: x(:,:)                 !! Merged UV table
  integer, intent(in) :: ncz                    !! Number of channels
  real, intent(in) :: z(:,:)                    !! Input UV table
  real, intent(in) :: weight                    !! Weight scale factor
  real, intent(in) :: factor                    !! Intensity scale factor
  real, intent(in) :: scaleuv                   !! UV scale factor
  integer, intent(inout) :: iwork(2,*)          !! Work array
  real, intent(inout) :: rwork(4,*)             !! Work array
  real(8), intent(in) :: xref,xval,xinc         !! Input velocity sampling
  real(8), intent(in) :: zref,zval,zinc         !! Output velocity sampling
  !------------------------------------------------------------------------
  !
  ! Local ---
  integer :: i, j, k, iv
  real :: poids
  !
  ! iwork = imin,imax
  ! rwork = rmin_1, rmin, rmax, rmax_1
  !
  integer imax,imin, ix,iy, jxmin, jymin, jxmax, jymax
  integer :: mcx, mcz, lcx, lcz, mtrail
  real(8) minpix, maxpix, pix, val, expand
  real rmin_1, rmin, rmax_1, rmax, smin, smax
  real scale
  !------------------------------------------------------------------------
  ! Code ----
  !
  mcx = ubound(x,1)
  mcz = ubound(z,1)
  lcx = 3*ncx+7
  lcz = 3*ncz+7
  mtrail = mcx-lcx
  ! Setup interpolation scheme
  ! Interpolate first (Z) Table on X grid
  !
  expand = abs(xinc/zinc)
  scale  = factor/expand
  !
  ! Initialize workspace
  iwork(:,1:ncx) = 0
  rwork(:,1:ncx) = 0.0
  do i = 1, ncx
    !
    ! Compute interval
    val = xval + (i-xref)*xinc
    pix = (val-zval)/zinc + zref
    maxpix = pix + 0.5d0*expand
    minpix = pix - 0.5d0*expand
    imin = int(minpix+1.0d0)
    imax = int(maxpix)
    iwork(1,i) = imin
    iwork(2,i) = imax
    if (imax.eq.imin .and. expand.eq.1.0) then
      ! Shifted grid or not actually
      rwork(1,i) = (imin-pix)
      rwork(2,i) = 1.0-rwork(1,i)
    else if (imax.ge.imin) then
      ! Lower end
      if (imin.gt.1) then
        !
        ! ZMIN = Z(IMIN-1)*(IMIN-MINPIX)+Z(IMIN)*(MINPIX-IMIN+1)
        !     and
        ! X(I) = X(I) + 0.5 * ( (IMIN-MINPIX)*(ZMIN+Z(IMIN)) )
        !
        !     RMIN_1 = 0.5 * (IMIN-MINPIX)*(IMIN-MINPIX)     ! Coefficient de IMIN-1
        !     RMIN   = 0.5 * (MINPIX-IMIN+2)*(IMIN-MINPIX)   ! Coefficient de IMIN
        !
        smin = imin-minpix
        rwork(1,i) = 0.5*smin*smin
        rwork(2,i) = smin-rwork(1,i)
      else
        !     RMIN   = (IMIN-MINPIX)                          ! Coefficient de IMIN
        !     RMIN_1 = 0                                      ! Coefficient de IMIN-1
        rwork(1,i) = 0.0
        rwork(2,i) = imin-minpix
      endif
      ! Upper end
      if (imax.lt.ncz) then
        smax = maxpix-imax
        rwork(4,i) = 0.5*smax*smax
        rwork(3,i) = smax-rwork(4,i)
      else
        rwork(3,i) = maxpix-imax
        rwork(4,i) = 0.0
      endif
      if (imax.eq.imin) then
        ! 3 Point Case
        rwork(2,i) = rwork(2,i)+rwork(3,i)
        rwork(3,i) = 0.0
      else
        ! General Case: Add 1/2 of IMIN & IMAX + 1 of all intermediate channels
        rwork(2,i) = rwork(2,i)+0.5
        rwork(3,i) = rwork(3,i)+0.5
      endif
    else
      if (imin.gt.1) then
        rwork(1,i) = (imin-pix)
        rwork(2,i) = 1.0-rwork(1,i)
      else
        rwork(1,i) = 0.0
        rwork(2,i) = 1.0
      endif
    endif
  enddo
  Print *,'IWORK 1 ',iwork(1,1:NCX)
  Print *,'RWORK 1 ',rwork(1,1:NCX)
  Print *,'IWORK 2 ',iwork(2,1:NCX)
  Print *,'RWORK 2 ',rwork(2,1:NCX)
  !
  ! OK, now do it for all visibilities
  do iv=1,nv
    !
    ! Coordinates
    do j=1, 3
      x(j,iv) = z(j,iv)*scaleuv
    enddo
    do j=4, 7
      x(j,iv) = z(j,iv)
    enddo
    !
    ! Channels
    do i=1,ncx
      imin = iwork(1,i)
      imax = iwork(2,i)
      jxmin = 5+3*imin
      jymin = jxmin+1
      jxmax = 5+3*imax
      jymax = jxmax+1
      rmin_1 = rwork(1,i)
      rmin   = rwork(2,i)
      rmax   = rwork(3,i)
      rmax_1 = rwork(4,i)
      ix = 5+3*i
      iy = ix+1
      !
      if (imax.ge.imin) then
        ! Print *,'IMAX ',imax,' => ',imin,' IMIN, NCZ ',ncz
        ! General Trapezium integration
        if (imin.gt.1) then
          x(ix,iv) = z(jxmin-3,iv)*rmin_1+z(jxmin,iv)*rmin
          x(iy,iv) = z(jymin-3,iv)*rmin_1+z(jymin,iv)*rmin
        else
          x(ix,iv) = z(jxmin,iv)*rmin
          x(iy,iv) = z(jymin,iv)*rmin
        endif
        if (imax.gt.imin) then
          do k = 5+3*(imin+1),5+3*(imax-1),3
            x(ix,iv) = x(ix,iv) + z(k,iv)
            x(iy,iv) = x(iy,iv) + z(k+1,iv)
          enddo
        endif
        x(ix,iv) = x(ix,iv) + z(jxmax,iv)*rmax
        x(iy,iv) = x(iy,iv) + z(jymax,iv)*rmax
        if (imax.lt.ncz) then
          x(ix,iv) = x(ix,iv) + z(jxmax+3,iv)*rmax_1
          x(iy,iv) = x(iy,iv) + z(jymax+3,iv)*rmax_1
        endif
        x(ix,iv) = x(ix,iv)*scale
        x(iy,iv) = x(iy,iv)*scale
      else
        !
        ! Interpolation
        if (imin.gt.1) then
          x(ix,iv) = z(jxmin-3,iv)*rmin_1+z(jxmin,iv)*rmin
          x(iy,iv) = z(jymin-3,iv)*rmin_1+z(jymin,iv)*rmin
        else
          x(ix,iv) = z(jxmin,iv)
          x(iy,iv) = z(jymin,iv)
        endif
        x(ix,iv) = x(ix,iv)*factor
        x(iy,iv) = x(iy,iv)*factor
      endif
    enddo
    !
    ! Weight
    ! Same weight for all channels.. One should do better here.
    !
    poids = z(10+3*(ncz/2),iv)*weight
    if (poids.eq.0) then  ! May happen with Widex spectra
      poids = z(10+3*(ncz/3),iv)*weight
    endif
    do j=10, 3*ncx+7, 3
      x(j,iv) = poids
    enddo
    !
    ! Trailing columns if any
    do j=1,mtrail
      x(lcx+j,iv) = z(lcz+j,iv)
    enddo
  enddo
end subroutine old_uvmergel
!
subroutine uvmergec (nv,ndx,x,ndz,z,weight,factor,scaleuv)
  use gildas_def
  !------------------------------------------------------------------------
  !*
  ! IMAGER -- Support routine for Continuum handling
  !
  ! Append a Continuum Data set
  !!
  !------------------------------------------------------------------------
  integer(kind=size_length), intent(in) :: nv   !! Number of visibilities
  integer(kind=size_length), intent(in) :: ndx  !!                  !!
  real, intent(inout) :: x(ndx,nv)              !! Merged UV table
  integer(kind=size_length), intent(in) :: ndz  !!
  real, intent(in) :: z(ndz,nv)                 !! Input UV table
  real, intent(in) :: weight                    !! Weight scale factor
  real, intent(in) :: factor                    !! Intensity scale factor
  real, intent(in) :: scaleuv(3)                !! Baseline length scale
  !
  ! Local ---
  integer :: j, iv, n
  !
  ! Code ----
  n = min(ndx,ndz)
  do iv=1,nv
    !
    ! Coordinates
    x(1:3,iv) = scaleuv*z(1:3,iv)
    do j=4, 7
      x(j,iv) = z(j,iv)
    enddo
    !
    ! Visibilities
    x(8,iv) = z(8,iv)*factor
    x(9,iv) = z(9,iv)*factor
    ! Weight
    x(10,iv) = z(10,iv)*weight
    ! Other (if any)
    do j=11,n
      x(j,iv) = z(j,iv)
    enddo
  enddo
end subroutine uvmergec
!
subroutine uvmergef (nv,ndx,x,ndz,z,weight,factor,w1,w2,error)
  use gildas_def
  !------------------------------------------------------------------------
  !*
  ! IMAGER -- Support routine for Continuum handling
  !
  ! Merge two Continuum Data Set: Average visibilities
  !!
  !------------------------------------------------------------------------
  integer(kind=size_length), intent(in) :: nv   !! Number of visibilities
  integer(kind=size_length), intent(in) :: ndx  !!
  real, intent(inout) :: x(ndx,nv)              !! Merged UV table
  integer(kind=size_length), intent(in) :: ndz  !!
  real, intent(in) :: z(ndz,nv)                 !! Input UV table
  real, intent(in) :: weight                    !! Weight scale factor
  real, intent(in) :: factor                    !! Intensity scale factor
  real(8), intent(out) :: w1,w2                 !! Relative weights
  logical, intent(out) :: error                 !! Error flag
  !
  ! Local ---
  integer :: iv, n, j
  real :: ww
  !
  ! Code ----
  error = .false.
  n = min(ndx,ndz)
  w1 = 0.d0
  w2 = 0.d0
  ! OK, now do it for all visibilities
  do iv=1,nv
    !
    ! U and V Coordinates
    if (x(1,iv).ne.z(1,iv)) then
      print *,'U iv ',iv,x(1,iv),z(1,iv), x(10,iv), z(10,iv)
      print *,'Out ',z(1:10,iv)
      error = .true.
      return
    endif
    if (x(2,iv).ne.z(2,iv)) then
      print *,'V iv ',iv,x(2,iv),z(2,iv), x(10,iv), z(10,iv)
      error = .true.
      return
    endif
    !
    ! Visibilities
    ww = x(10,iv)
    if (x(10,iv).gt.0) w1 = w1+x(10,iv)
    !
    if (z(10,iv).gt.0) then
      w2 = w2+z(10,iv)
      if (x(10,iv).gt.0) then
        ww = x(10,iv)+weight*z(10,iv)
        x(8,iv) = (x(8,iv)*x(10,iv) + z(8,iv)*z(10,iv)*weight*factor ) / ww
        x(9,iv) = (x(9,iv)*x(10,iv) + z(9,iv)*z(10,iv)*weight*factor ) / ww
      else
        ww = weight*z(10,iv)
        x(8,iv) = z(8,iv)*factor
        x(9,iv) = z(9,iv)*factor
      endif
    endif
    ! Weight
    x(10,iv) = ww
    ! Trailing columns if any
    do j=11,n
      x(j,iv) = z(j,iv)
    enddo
  enddo
end subroutine uvmergef
!
!
subroutine uvmergel (nv,ncx,x,ncz,z,weight,factor,scaleuv,iwork,rwork &
  & ,xref,xval,xinc,zref,zval,zinc,resample)
  use gildas_def
  use gbl_message
  !------------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Support routine for UV_MERGE
  !
  ! Merge two Line Data Set: Average visibilities
  !!
  !------------------------------------------------------------------------
  integer(kind=size_length), intent(in) :: nv   !! Number of visibilities
  integer, intent(in) :: ncx                    !! Number of channels
  real, intent(inout) :: x(:,:)                 !! Merged UV table
  integer, intent(in) :: ncz                    !! Number of channels
  real, intent(in) :: z(:,:)                    !! Input UV table
  real, intent(in) :: weight                    !! Weight scale factor
  real, intent(in) :: factor                    !! Intensity scale factor
  real, intent(in) :: scaleuv(3)                !! Baseline Scale factor
  integer, intent(inout) :: iwork(2,*)          !! Work array
  real, intent(inout) :: rwork(4,*)             !! Work array
  real(8), intent(in) :: xref,xval,xinc         !! Input velocity sampling
  real(8), intent(in) :: zref,zval,zinc         !! Output velocity sampling
  logical, intent(in) :: resample
  !
  ! Constant
  real(kind=8),parameter      :: ctol = 0.1     ! Spectral tolerance over all spectrum
  character(len=*), parameter :: rname='UV_MERGE'
  !
  ! Local ---
  integer :: i, j, k, iv
  real :: poids
  !
  ! iwork = imin,imax
  ! rwork = rmin_1, rmin, rmax, rmax_1
  !
  integer imax,imin, ix,iy, jxmin, jymin, jxmax, jymax
  integer :: mcx, mcz, lcx, lcz, mtrail
  real(8) minpix, maxpix, pix, val, expand
  real rmin_1, rmin, rmax_1, rmax, smin, smax
  real scale
  !
  ! Code ----
  if (.not.resample) then
    do iv=1,nv   
      x(1:3,iv) = scaleuv*z(1:3,iv)
      x(4:,iv)  = z(4:,iv)
    end do
  else
    !
    ! Interpolate first (Z) Table on X grid
    !
    mcx = ubound(x,1)
    mcz = ubound(z,1)
    lcx = 3*ncx+7
    lcz = 3*ncz+7
    mtrail = mcx-lcx
    ! Setup interpolation scheme
    !
    expand = abs(xinc/zinc)
    scale  = factor/expand
    !! Print *,'NCX ',ncx,' NCZ ',ncz,' Expand ',expand
    !
    ! Initialize workspace
    iwork(:,1:ncx) = 0
    rwork(:,1:ncx) = 0.0
    do i = 1, ncx
      !
      ! Compute interval
      val = xval + (i-xref)*xinc
      pix = (val-zval)/zinc + zref
      maxpix = pix + 0.5d0*expand
      minpix = pix - 0.5d0*expand
      imin = int(minpix+1.0d0)
      imax = int(maxpix)
      iwork(1,i) = imin
      iwork(2,i) = imax
      !
      ! Test out of bound conditions
      if (imax.lt.0) then
        !! Print *,'Out of bound MAX ',imax, iwork(:,i)
        iwork(:,i) = 1
        rwork(:,i) = 0. ! Nothing to be added
      else if (imin.gt.ncz) then
        !! Print *,'Out of bound MIN ',imax, iwork(:,i)
        iwork(:,i) = 1
        rwork(:,i) = 0. ! Nothing to be added
      else if (imax.eq.imin .and. expand.eq.1.0) then
        ! Shifted grid or not actually
        rwork(1,i) = (imin-pix)
        rwork(2,i) = 1.0-rwork(1,i)
      else if (imax.ge.imin) then
        ! Lower end
        if (imin.gt.1) then
          !
          ! ZMIN = Z(IMIN-1)*(IMIN-MINPIX)+Z(IMIN)*(MINPIX-IMIN+1)
          !     and
          ! X(I) = X(I) + 0.5 * ( (IMIN-MINPIX)*(ZMIN+Z(IMIN)) )
          !
          !     RMIN_1 = 0.5 * (IMIN-MINPIX)*(IMIN-MINPIX)     ! Coefficient de IMIN-1
          !     RMIN   = 0.5 * (MINPIX-IMIN+2)*(IMIN-MINPIX)   ! Coefficient de IMIN
          !
          smin = imin-minpix
          rwork(1,i) = 0.5*smin*smin
          rwork(2,i) = smin-rwork(1,i)
        else
          !     RMIN   = (IMIN-MINPIX)                          ! Coefficient de IMIN
          !     RMIN_1 = 0                                      ! Coefficient de IMIN-1
          rwork(1,i) = 0.0
          rwork(2,i) = imin-minpix
        endif
        ! Upper end
        if (imax.lt.ncz) then
          smax = maxpix-imax
          rwork(4,i) = 0.5*smax*smax
          rwork(3,i) = smax-rwork(4,i)
        else
          rwork(3,i) = maxpix-imax
          rwork(4,i) = 0.0
        endif
        if (imax.eq.imin) then
          ! 3 Point Case
          rwork(2,i) = rwork(2,i)+rwork(3,i)
          rwork(3,i) = 0.0
        else
          ! General Case: Add 1/2 of IMIN & IMAX + 1 of all intermediate channels
          rwork(2,i) = rwork(2,i)+0.5
          rwork(3,i) = rwork(3,i)+0.5
        endif
      else
        if (imin.gt.1) then
          rwork(1,i) = (imin-pix)
          rwork(2,i) = 1.0-rwork(1,i)
        else
          rwork(1,i) = 0.0
          rwork(2,i) = 1.0
        endif
      endif
    enddo
    ! Test
    !do i=1,ncx
    !  Print *,i,'IWORK ',iwork(:,i),' RWORK ',rwork(:,i)
    !enddo
    !
    ! OK, now do it for all visibilities
    do iv=1,nv
      !
      ! Coordinates                
      do j=1, 3
        x(j,iv) = z(j,iv)*scaleuv(j)
      enddo
      do j=4, 7
        x(j,iv) = z(j,iv)
      enddo
      !
      ! Channels
      do i=1,ncx
        imin = iwork(1,i)
        imax = iwork(2,i)
        jxmin = 5+3*imin
        jymin = jxmin+1
        jxmax = 5+3*imax
        jymax = jxmax+1
        rmin_1 = rwork(1,i)
        rmin   = rwork(2,i)
        rmax   = rwork(3,i)
        rmax_1 = rwork(4,i)
        ix = 5+3*i
        iy = ix+1
        !
        if (imax.ge.imin) then
          ! General Trapezium integration
          if (imin.gt.1) then
            x(ix,iv) = z(jxmin-3,iv)*rmin_1+z(jxmin,iv)*rmin
            x(iy,iv) = z(jymin-3,iv)*rmin_1+z(jymin,iv)*rmin
          else
            x(ix,iv) = z(jxmin,iv)*rmin
            x(iy,iv) = z(jymin,iv)*rmin
          endif
          if (imax.gt.imin) then
            do k = 5+3*(imin+1),5+3*(imax-1),3
              x(ix,iv) = x(ix,iv) + z(k,iv)
              x(iy,iv) = x(iy,iv) + z(k+1,iv)
            enddo
          endif
          x(ix,iv) = x(ix,iv) + z(jxmax,iv)*rmax
          x(iy,iv) = x(iy,iv) + z(jymax,iv)*rmax
          if (imax.lt.ncz) then
            x(ix,iv) = x(ix,iv) + z(jxmax+3,iv)*rmax_1
            x(iy,iv) = x(iy,iv) + z(jymax+3,iv)*rmax_1
          endif
          x(ix,iv) = x(ix,iv)*scale
          x(iy,iv) = x(iy,iv)*scale
        else
          !
          ! Interpolation
          if (imin.gt.1) then
            x(ix,iv) = z(jxmin-3,iv)*rmin_1+z(jxmin,iv)*rmin
            x(iy,iv) = z(jymin-3,iv)*rmin_1+z(jymin,iv)*rmin
          else
            x(ix,iv) = z(jxmin,iv)
            x(iy,iv) = z(jymin,iv)
          endif
          x(ix,iv) = x(ix,iv)*factor
          x(iy,iv) = x(iy,iv)*factor
        endif
      enddo
      !
      ! Weight
      ! Same weight for all channels...
      !
      poids = z(10+3*(ncz/2),iv)*weight
      if (poids.eq.0) then  ! May happen with Widex spectra
         poids = z(10+3*(ncz/3),iv)*weight
      endif
      do j=10, 3*ncx+7, 3
         x(j,iv) = poids
      enddo
      !
      ! Trailing columns if any
      do j=1,mtrail
         x(lcx+j,iv) = z(lcz+j,iv)
      enddo
    enddo
  endif
end subroutine uvmergel
!
subroutine shouldresample(rname,xnc,xref,xval,xinc, &
  & znc,zref,zval,zinc,ctol, resample,error)
  !
  use gbl_message
  use imager_interfaces, only : map_message
  !------------------------------------------------------------------------
  !*
  ! IMAGER -- Support routine for UV_MERGE
  !
  ! Merge two Line Data Set: Average visibilities
  !!
  !------------------------------------------------------------------------
  character(len=*), intent(in) :: rname   !! Command name
  integer(kind=4),intent(in) :: xnc       !! Size of X velocity axis
  real(kind=8),   intent(in) :: xref      !! X reference channel
  real(kind=8),   intent(in) :: xval      !! X Value at reference
  real(kind=8),   intent(in) :: xinc      !! X increment
  integer(kind=4),intent(in) :: znc       !! Size of Z velocity axis
  real(kind=8),   intent(in) :: zref      !! Z reference channel
  real(kind=8),   intent(in) :: zval      !! Z Value at reference
  real(kind=8),   intent(in) :: zinc      !! Z increment
  real(kind=8),   intent(in) :: ctol      !! Match tolerancs
  logical, intent(out) :: resample        !! Should we resample ?
  logical, intent(out) :: error           !! Error flag
  !
  ! Local ---
  real(kind=8) :: xleft,xright,zleft,zright,vtol
  character(len=64) :: mess
  !
  ! Code ----
  vtol = abs(zinc*ctol)
  !
  resample = .false.
  error = .false.
  if (xnc.ne.znc) then
    mess = 'Different channel numbers '
    resample = .true.
  else if (xinc*zinc.lt.0.d0) then
    resample = .true.
    mess = 'Different sign of increment '
  else
    xleft  = (0.5-xref)*xinc+xval    
    xright = (xnc+0.5-xref)*xinc+xval 
    zleft  = (0.5-zref)*zinc+zval    
    zright = (znc+0.5-zref)*zinc+zval
    !
    if (abs(xleft-zleft).gt.vtol) then
      mess = 'Channel mismatch on left side'
      resample = .true.
    else if (abs(xright-zright).gt.vtol) then
      mess = 'Channel mismatch on right side'
      resample = .true.
    endif
    xleft = (zleft-xval)/xinc+xref
    xright = (zright-xval)/xinc+xref
    if ((xleft.gt.znc).or.(xright.lt.1)) then
      mess = 'Axes do not overlap'
      error = .true.
      call map_message(seve%e,rname,mess)
      return
    endif
    !Print *,'XLEFT ',xleft,' XRIGHT ',xright,' NC', xnc, znc
    !Print *,'ZLEFT ',zleft,' ZRIGHT' ,xright---
  endif
  if (resample) call map_message(seve%w,rname,mess)
  !
end subroutine shouldresample
!
! Others
subroutine gdf_uvmatch_codes(a,b,code,ignore)
  use image_def
  use imager_interfaces, only : gdf_uvcolumn_codes
  !---------------------------------------------------------------------
  ! @ public
  !*
  ! GIO     Compare layout of UV tables for description columns  
  ! Code = 0    Same layout  
  ! Code = -1   Different layout  
  ! Code = 3    Similar layout, except that Col.3 is SCAN in one,
  !             and W in the other.
  !!
  !---------------------------------------------------------------------
  type(gildas), intent(in) :: a       !! Input Header
  type(gildas), intent(in) :: b       !! Input Header
  integer, intent(out)     :: code    !! Returned code
  integer, intent(in) :: ignore       !! Which code_uvt is ignored ?
  !
  ! Local ---
  integer :: k, nlt, ier, tole, ka, kb
  integer, allocatable :: a_codes(:,:), b_codes(:,:)
  !
  ! Code ----
  code = -1
  ! If # number of leading : no match
  if (a%gil%nlead.ne.b%gil%nlead) return
  !
  ! If # number of trailing : no match, except if Ignore == 0
  code = -2
  if (ignore.eq.0) then
    tole = 0
  else
    tole = 1
  endif
  if (abs(a%gil%ntrail-b%gil%ntrail).gt.tole) return
  !
  ! Else, compare columns, but make a specific provision
  ! for SCAN and W (both of which may happen in Col 3)
  ! and for the "ignore" code
  !
  nlt = a%gil%nlead + max(a%gil%ntrail,b%gil%ntrail)
  allocate(a_codes(2,nlt),b_codes(2,nlt),stat=ier)
  call gdf_uvcolumn_codes(a,a_codes)
  call gdf_uvcolumn_codes(b,b_codes)
  !
  code = 0
  if (ignore.eq.0) then
    do k = 1,nlt
      if (a_codes(1,k).ne.b_codes(1,k)) then
        if (code.eq.0 .and. k.eq.3) then
          code = 3
          if (a_codes(1,k).eq.code_uvt_scan .and. b_codes(1,k).eq.code_uvt_w) cycle
          if (b_codes(1,k).eq.code_uvt_scan .and. a_codes(1,k).eq.code_uvt_w) cycle
        endif
        code = -3
      else if (a_codes(2,k).ne.b_codes(2,k)) then
        Print *,'Code length mismatch at Col. ',k, a_codes(1:2,k), b_codes(1:2,k), ' Ntrail ',nlt
      endif
    enddo
  else
    ka = 1
    kb = 1
    !
    do k = 1,nlt
      if (a_codes(1,ka).eq.0 .or. a_codes(1,ka).eq.ignore) ka = ka+1
      if (b_codes(1,kb).eq.0 .or. b_codes(1,kb).eq.ignore) kb = kb+1
      if (ka.gt.nlt) exit
      if (kb.gt.nlt) exit
      !
      if (a_codes(1,ka).ne.b_codes(1,kb)) then
        if (code.eq.0 .and. ka.eq.3) then
          code = 3
          if (a_codes(1,ka).eq.code_uvt_scan .and. b_codes(1,kb).eq.code_uvt_w) cycle
          if (b_codes(1,ka).eq.code_uvt_scan .and. a_codes(1,kb).eq.code_uvt_w) cycle
        endif
        code = -3
      else if (a_codes(2,ka).ne.b_codes(2,kb)) then
        Print *,'Code length mismatch at Col. ',k, a_codes(1:2,k), b_codes(1:2,k), ' Ntrail ',nlt
      endif
    enddo
  endif
end subroutine gdf_uvmatch_codes
!
subroutine gdf_uvcolumn_codes(h,column_codes)
  use image_def
  !---------------------------------------------------------------------
  ! @ public-mandatory
  !*
  ! GIO     Return the column codes and sizes of the Leading and Trailing
  !         columns
  !!
  !---------------------------------------------------------------------
  type (gildas), intent(in) :: h                !! Input header
  integer, intent(inout) :: column_codes(:,:)   !! Column codes
  !
  integer :: nlt, i, j, itrail
  !
  nlt = h%gil%nlead + h%gil%ntrail
  !
  do j = 1,nlt
    do i = 1, code_uvt_last
      if (h%gil%column_pointer(i).lt.h%gil%fcol) then
        if (h%gil%column_pointer(i).eq.j) then
          column_codes(1,j) = i
          column_codes(2,j) = h%gil%column_size(i)
          exit
        endif
      else if (h%gil%column_pointer(i).gt.h%gil%lcol) then
         ! A little more vicious if > nlead
        itrail = h%gil%column_pointer(i)-h%gil%lcol+h%gil%nlead
        !! Print *,'Trail ',j,i,itrail
        if (itrail.eq.j) then
          column_codes(1,j) = i
          column_codes(2,j) = h%gil%column_size(i)
          exit
        endif
      else
        Print *,'Inconsistent Column Pointer #',i,' = ', h%gil%column_pointer(i), &
        &   ' in data range',h%gil%fcol,h%gil%lcol
      endif
    enddo
  enddo
end subroutine gdf_uvcolumn_codes
!
