subroutine uv_line2cont(line,error)
  use gkernel_interfaces
  use imager_interfaces, except_this=>uv_line2cont
  use clean_def
  use clean_default
  use clean_types
  use clean_arrays
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  !
  ! IMAGER  Support routine for command 
  !     UV_CONT [Step] [/RANGE Start End TYPE] /INDEX Alpha [Frequency]
  !
  ! Create a continuum UV table from a Line one
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: line  ! Command line
  logical, intent(out) :: error            ! Error flag
  !
  character(len=*), parameter :: rname='UV_CONT'
  integer, parameter :: o_naver=0
  integer, parameter :: o_index=1
  integer, parameter :: o_range=2
  !
  real, pointer :: duv_previous(:,:), duv_next(:,:)
  integer :: nu, nv
  type (gildas) :: hcuv
  integer :: channels(3)
  !
  ! Define the Header
  call sub_uvcont_header(line,error,hcuv,channels,o_naver,o_index,o_range)
  if (error) return
  !
  ! Define the Data
  nu = hcuv%gil%dim(1)
  nv = hcuv%gil%dim(2)
  nullify (duv_previous, duv_next)
  call uv_find_buffers (rname,nu,nv,duv_previous,duv_next,error)
  if (error) return
  !
  hcuv%r2d => duv_next
  huv%r2d => duv_previous
  call sub_uvcont_data(line,hcuv,huv,channels,dchanflag,o_index,error)
  !
  call uv_clean_buffers (duv_previous, duv_next,error)
  if (error) return
  !
  ! Copy back to UV data set
  call gdf_copy_header(hcuv,huv,error)  
  !
  ! Indicate UV data has changed, and weight must be computed
  call uv_new_data(weight=.true.)
end subroutine uv_line2cont
!
subroutine sub_uvcont_header(line,error,hcuv,channels,o_step,o_index,o_range)
  use gkernel_interfaces
  use imager_interfaces, except_this=>sub_uvcont_header
  use clean_def
  use clean_default
  use clean_types
  use clean_arrays
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  !
  ! IMAGER  Support routine for commands 
  !   UV_CONT [Step] /INDEX Alpha [Frequency] [/RANGE Min Max Type]
  ! and
  !   UV_MAP [Map Center Args] /CONT [Step] /INDEX Alpha [Frequency] [/RANGE Min Max Type]
  !
  ! Create a continuum UV table from the Line one
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: line  ! Command line
  logical, intent(out) :: error            ! Error flag
  type (gildas), intent(inout) :: hcuv     ! UV header
  integer, intent(out) :: channels(3)      ! Channels (first, last, step)
  integer, intent(in) :: o_step            ! Location of channel step
  integer, intent(in) :: o_index           ! Location of /INDEX option
  integer, intent(in) :: o_range           ! Location of /RANGE option
  !
  character(len=*), parameter :: rname='UV_CONT'
  real(kind=8), parameter :: pi=3.14159265358979323846d0
  real(kind=8), parameter :: f_to_k = 2.d0*pi/299792458.d-6
  !
  integer :: nchan
  character(len=80) :: mess
  real :: uvmax, uvmin
  integer :: msize
  type (uvmap_par) :: map
  !
  real(8) :: drange(2), freq
  character(len=12) :: csort
  integer :: isort, n
  integer :: nc(2)
  integer(kind=4), parameter :: msort=3
  character(len=12) :: types(msort),mysort
  data types /'CHANNEL','VELOCITY','FREQUENCY'/
  !
  !
  if (huv%loca%size.eq.0) then
    call map_message(seve%e,rname,'No UV data loaded')
    error = .true.
    return
  endif
  if (huv%gil%nstokes.gt.1) then
    call map_message(seve%e,rname,'Only single polarization data supported',1)
    error = .true.
    return
  endif
  !
  channels = 0
  !
  msize = maxval(default_map%size)
  if (msize.eq.0) then
    map = default_map
    freq = gdf_uv_frequency(huv)
    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,huv,freq,uvmax,uvmin,error)
    if (error) return
    msize = maxval(map%size)
  endif
  channels = 0
  call t_channel_sampling (rname,huv,channels(3),msize)
  !
  if (sic_present(o_step,1)) then
    call sic_i4(line,o_step,1,channels(3),.false.,error)
  else
    write(mess,'(A,I0,A)') 'Averaging by ',channels(3),' original channels'
    call map_message(seve%i,rname,mess)
  endif
  !
  if (sic_present(o_range,0)) then
    ! Get channel range from /RANGE option
    call sic_r8 (line,o_range,1,drange(1),.true.,error)
    if (error) return
    call sic_r8 (line,o_range,2,drange(2),.true.,error)
    if (error) return
    call sic_ke (line,o_range,3,csort,n,.true.,error)
    if (error) return
    error = .false.
    call sic_ambigs(rname,csort,mysort,isort,types,msort,error)
    if (error)  return    
    ! Define the input range
    call out_range(rname,mysort,drange,nc,huv,error)
    if (error) return
    channels(1:2) = nc
  else
    !
    nchan = huv%gil%nchan
    channels(1) = 1
    channels(2) = nchan
  endif
  !
  call uv_cont_header(rname,huv,hcuv,channels,error)
  !
end subroutine sub_uvcont_header
!
subroutine uv_cont_header(rname,hluv,hcuv,channels,error)
  use gbl_message
  use gkernel_interfaces
  use image_def
  use imager_interfaces, only : map_message
  !-----------------------------------------------------------------------------
  ! @ private
  !   Derive the Continuum UV header from the Line UV header
  !   once the channel range has been specified
  !-----------------------------------------------------------------------------
  character(len=*), intent(in) :: rname ! Caller name
  type(gildas), intent(in) :: hluv      ! Line UV header
  type(gildas), intent(inout) :: hcuv   ! Continuum UV header
  integer, intent(in) :: channels(3)    ! Channel range
  logical, intent(out) :: error
  !
  integer :: i, mc, nchan
  character(len=80) :: mess
  !
  nchan = channels(2)-channels(1)+1
  !
  ! Make sure things remain tractable for "random" Frequency axis...
  if (hluv%gil%nfreq.ne.0 .and. nchan.ne.1) then
    if (channels(3).ne.1) then
      !
      ! Ultimately, one may check here pseudo-linear axes...
      call map_message(seve%e,rname,'UV tables with random Frequency axis ' &
      & //' can only be converted with channel step = 1',1)
      error = .true.
      return
    endif
  endif
  !
  error = .false.
  call gildas_null(hcuv, type = 'UVT')
  call gdf_copy_header(hluv,hcuv,error)
  !
  mc = nchan/channels(3)
  if (mc*channels(3).ne.nchan) mc = mc+1
  write(mess,'(A,I0,A)') 'Generating visibilities for ',mc,' frequencies' 
  call map_message(seve%i,rname,mess)
  hcuv%gil%dim(2) = hluv%gil%dim(2)*mc
  hcuv%gil%dim(1) = 10+hluv%gil%ntrail
  hcuv%gil%nchan = 1
  hcuv%gil%nvisi = hcuv%gil%dim(2)
  hcuv%gil%inc(1) = hluv%gil%inc(1)*mc
  !
  ! The effective bandwidth does not account for blanked channels
  ! in the range
  hcuv%gil%fres = (channels(2)-channels(1)+1)*hcuv%gil%fres
  hcuv%gil%vres = (channels(2)-channels(1)+1)*hcuv%gil%vres
  !
  hcuv%gil%nfreq = 0 ! Reset this
  !
  ! Shift trailing columns to handle Mosaicing
  do i=1,code_uvt_last
    if (hluv%gil%column_pointer(i).gt.hluv%gil%lcol) then
      hcuv%gil%column_pointer(i) = hluv%gil%column_pointer(i)-hluv%gil%lcol+10
    endif
  enddo
  hcuv%gil%lcol = 10
  !
end subroutine uv_cont_header
!
subroutine sub_uvcont_data(line,hcuv,hiuv,channels,chflag,o_index,error)
  use image_def
  use gkernel_interfaces
  use imager_interfaces, except_this=>sub_uvcont_data
  !---------------------------------------------------------------------
  ! @ private-mandatory
  !
  !   IMAGER
  !     Transform the Line UV data into a Continuum UV data
  !---------------------------------------------------------------------  
  character(len=*), intent(in) :: line
  type(gildas), intent(inout) :: hcuv
  type(gildas), intent(inout) :: hiuv
  integer, intent(in) :: channels(3)
  integer, intent(in) :: chflag(:)
  integer, intent(in) :: o_index
  logical, intent(inout) :: error
  !
  real :: alpha
  real(8) :: ofreq
  integer :: uvcode=1
  !
  if (sic_present(o_index,0)) then
    call sic_r4(line,o_index,1,alpha,.true.,error)
    if (error) return
    ofreq = 0.D0
    call sic_r8(line,o_index,2,ofreq,.false.,error)
    if (error) return
    call t_continuum(hiuv,hcuv,channels,chflag,uvcode,error,alpha,ofreq)
  else
    call t_continuum(hiuv,hcuv,channels,chflag,uvcode,error)
  endif
  !
end subroutine sub_uvcont_data
!
subroutine opt_filter_base(line,rname,error)
  use gkernel_interfaces
  use uvsplit_mod
  use clean_def
  use clean_arrays
  use clean_default
  use clean_types
  use gbl_message
  use imager_interfaces, except_this => opt_filter_base
  !---------------------------------------------------------------------
  ! @ private
  !
  ! IMAGER  support routine for
  !   UV_FILTER  /CHANNEL ListVariable [/ZERO]
  !   UV_FILTER  /FREQUENCIES ListFreq /WIDTH Width [UNIT]
  !   UV_FILTER  /VELOCITY ListVelo /WIDTH Width [UNIT]
  !   UV_FILTER  /RANGE Min Max [TYPE]
  !      [/FILE FileIn [FileOut]]
  !
  ! Parse the /FILE option
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: line  ! Command line
  character(len=*), intent(in) :: rname    ! Command name
  logical, intent(out) :: error            ! Error flag
  !
  real(kind=8), parameter :: pi=3.14159265358979323846d0
  real(kind=8), parameter :: f_to_k = 2.d0*pi/299792458.d-6
  !
  type(gildas) :: htmp
  real :: uvmax, uvmin
  real(8) :: freq
  integer :: msize, mc, nchan
  type (uvmap_par) :: map
  integer :: n
  integer :: channels(3)
  logical :: present, err
  !
  !
  if (sic_present(opt_file,0)) then
    call gildas_null(hiuv,type='UVT')
    call gildas_null(houv,type='UVT')
    call sic_ch(line,opt_file,1,in_file,n,.true.,error)
    if (error) return
    call sic_parse_file(in_file,' ','.uvt',hiuv%file)
    !
    ! Strip extension if present
    call sic_parsef(in_file,ou_file,' ','.uvt')
    ou_file = in_file
    !
    ! Line (continuum-Free) UV table
    if (sic_present(2,opt_file)) then
      call sic_ch(line,opt_file,2,ou_file,n,.true.,error)
    else
      ou_file = trim(in_file)//'-line'
    endif
    call sic_parse_file(ou_file,' ','.uvt',houv%file)
    !
    call gdf_read_header(hiuv,error)
    if (error) return
    !
    call gdf_copy_header(hiuv,houv,error)
    !
    call gdf_create_image(houv,error)
    if (error) return
    !
    ! Set the Blocking Factor
    nblock = space_nitems('SPACE_IMAGER',hiuv,1)
    use_file = .true.
    !
    ! Continuum (line-Free) UV table
    if (rname.eq.'UV_SPLIT') then
      call gildas_null(hfuv,type='UVT')
      call gdf_copy_header(hiuv,hfuv,error)
      if (sic_present(3,opt_file)) then
        call sic_ch(line,opt_file,3,ou_file,n,.true.,error)
      else
        ou_file = trim(in_file)//'-cont'
      endif
      call sic_parse_file(ou_file,' ','.uvt',hfuv%file)
      !
      ! Define the compression factor
      channels = 0
      ncompr = 1
      !
      msize = maxval(default_map%size)
      present = .false.
      if (msize.eq.0) then
        map = default_map
        if (hfuv%gil%basemax.eq.0) then
          call map_message(seve%w,rname,'No Baseline extrema') 
          present = .true.
        else
          uvmax = hfuv%gil%basemax
          uvmin = hfuv%gil%basemin
          ! Now transform UVMAX in kiloWavelength (including 2 pi factor)
          freq = gdf_uv_frequency(hfuv)
          !! Print *,'UVmax min freq ',uvmax, uvmin, freq
          uvmax = uvmax*freq*f_to_k
          uvmin = uvmin*freq*f_to_k
          error = .false.
          ! This works on HUV only unfortunately - The call sequence
          ! should be changed at some time
          call gildas_null(htmp,type='UVT')
          call gdf_copy_header(huv,htmp,err)
          call gdf_copy_header(hfuv,huv,err)
          call map_parameters(rname,map,huv,freq,uvmax,uvmin,error)
          call gdf_copy_header(htmp,huv,err)
          if (error) return
          msize = maxval(map%size)
        endif
      endif
      call t_channel_sampling (rname,hiuv,channels(3),msize)
      !
      call sic_i4(line,0,2,channels(3),present,error)
      if (error) return
      !
      ! Ignore these for the time being
      !!call sic_i4(line,0,3,channels(1),.false.,error)
      !!call sic_i4(line,0,4,channels(2),.false.,error)
      !
      nchan = hfuv%gil%nchan
      ! Use the <0 convention to start from the end
      if (channels(1).lt.0) then
         channels(1) = max(1,nchan+channels(1))
      else
         channels(1) = min(max(1,channels(1)),nchan)
      endif
      if (channels(2).lt.0) then
         channels(2) = max(channels(1),nchan+channels(2))
      else if (channels(2).eq.0) then
         channels(2) = nchan
      else
         channels(2) = max(channels(1),min(nchan,channels(2)))
      endif
      nchan = channels(2)-channels(1)+1
      !
      ncompr = channels(3)
      mc = nchan/ncompr 
      if (mc*ncompr.ne.nchan) mc = mc+1
      !
      ! Edge of channel 0.5
      ! - before
      !! fmin = (0.5-oldref)*hfuv%gil%inc(1) + hfuv%gil%val(1)
      ! - after
      !! fmin = (0.5-newref)*ncompr*hfuv%gil%inc(1) + huv%gil%val(1)
      ! so
      !  (0.5-newref)*ncompr*hfuv%gil%inc(1) = (0.5-hfuv%gil%ref(1))%hfuv%gil%inc(1)
      !  (0.5-newref)*ncompr = (0.5-oldref)
      ! newref = (oldref-0.5)/ncompr + 0.5
      hfuv%gil%ref(1) = (hfuv%gil%ref(1)-0.5d0)/ncompr + 0.5d0
      hfuv%gil%dim(1) = 7+3*mc+hfuv%gil%ntrail
      hfuv%gil%nchan = mc
      hfuv%gil%inc(1) = hfuv%gil%inc(1)*ncompr
      hfuv%gil%fres = ncompr*hfuv%gil%fres
      hfuv%gil%vres = ncompr*hfuv%gil%vres
      !
      call gdf_create_image(hfuv,error)
      if (error) return
    endif
  else
    call gildas_null(hiuv,type='UVT')
    if (huv%loca%size.eq.0) then
      call map_message(seve%e,rname,'No UV data loaded')
      error = .true.
      return
    endif
    if (huv%gil%nstokes.gt.1) then
      call map_message(seve%e,rname,'Only single polarization data supported')
      error = .true.
      return
    endif
    call gdf_copy_header(huv,hiuv,error)
    !
    use_file = .false.
  endif
end subroutine opt_filter_base
!
subroutine uv_split_comm(line,error)
  use gkernel_interfaces
  use gbl_message
  use imager_interfaces, only : uv_filter_base, opt_filter_base, &
    & map_message
  !---------------------------------------------------------------------
  ! @ private
  !
  ! IMAGER support routine for commands
  !   UV_SPLIT [Degree] /CHANNEL ListVariable [/ZERO]
  !   UV_SPLIT [Degree] /FREQUENCIES ListFreq /WIDTH Width
  !   UV_SPLIT [Degree] /VELOCITIES ListVelo /WIDTH Width
  !   UV_SPLIT [Degree] /RANGE Min Max [TYPE]
  !      /FILE FileIn [FileLine [FileCont]
  !
  ! Subtract a continuum baseline, ignoring a list of channels
  ! in UV data set. Create two output UV tables from this:
  !   - a line free one
  !   - a continuum free one
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: line  ! Command line
  logical, intent(out) :: error            ! Error flag
  !
  character(len=*), parameter :: rname='UV_SPLIT'
  external :: t_split
  integer :: degree
  !
  degree = 0
  call sic_i4(line,0,1,degree,.false.,error)
  if (error) return
  if (degree.ne.0 .and. degree.ne.1) then
    call map_message(seve%e,rname,'Only degree 0 or 1 supported')
    error = .true.
    return
  endif
  !
  call opt_filter_base(line,rname,error)
  if (error) return
  call uv_filter_base (line,error,rname,t_split,degree)
end subroutine uv_split_comm
!
subroutine uv_baseline(line,error)
  use gkernel_interfaces
  use gbl_message
  use imager_interfaces, only : uv_filter_base, opt_filter_base, &
    map_message
  !---------------------------------------------------------------------
  ! @ private
  !
  ! IMAGER support routine for commands
  !   UV_BASELINE [Degree] /CHANNEL ListVariable [/ZERO]
  !   UV_BASELINE [Degree] /FREQUENCIES ListFreq /WIDTH Width
  !   UV_BASELINE [Degree] /VELOCITIES ListVelo /WIDTH Width
  !   UV_BASELINE [Degree] /RANGE Min Max [TYPE]
  !      [/FILE FileIn [FileOut]]
  !
  ! Subtract a continuum baseline, ignoring a list of channels
  ! in the current UV data set.
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: line  ! Command line
  logical, intent(out) :: error            ! Error flag
  !
  character(len=*), parameter :: rname='UV_BASELINE'
  external :: t_baseline
  integer :: degree
  !
  degree = 0
  call sic_i4(line,0,1,degree,.false.,error)
  if (error) return
  if (degree.ne.0 .and. degree.ne.1) then
    call map_message(seve%e,rname,'Only degree 0 or 1 supported')
    error = .true.
    return
  endif
  !
  call opt_filter_base(line,rname,error)
  if (error) return
  call uv_filter_base (line,error,rname,t_baseline,degree)
end subroutine uv_baseline
!
subroutine uv_filter(line,error)
  use gkernel_interfaces
  use imager_interfaces, only : uv_filter_base, map_message
  use gbl_message
  use uvsplit_mod
  !---------------------------------------------------------------------
  ! @ private
  !
  ! IMAGER  support routine for
  !   UV_FILTER  /CHANNEL ListVariable [/ZERO]
  !   UV_FILTER  /FREQUENCIES ListFreq /WIDTH Width [UNIT]
  !   UV_FILTER  /VELOCITY ListVelo /WIDTH Width [UNIT]
  !   UV_FILTER  /RANGE Min Max [TYPE]
  !      [/FILE FileIn [FileOut]]
  !
  ! "Filter", i.e. flag, a list of channels in the current UV
  ! data set. Flagging is reversible, unless the /ZERO option is
  ! present. With /ZERO, the "filtered" visibilities are set to zero.
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: line  ! Command line
  logical, intent(out) :: error            ! Error flag
  !
  character(len=*), parameter :: rname='UV_FILTER'
  external :: t_filter
  !
  integer :: zero
  !
  if (sic_present(opt_zero,0)) then
    if (sic_present(opt_reset,0)) then
      call map_message(seve%e,rname,'Incompatible options /ZERO and /RESET')
      error = .true.
      return
    endif
    zero = 0
  else if (sic_present(opt_reset,0)) then
    zero = -1
  else
    zero = 1
  endif
  !
  call opt_filter_base(line,rname,error)
  if (error) return
  call uv_filter_base (line,error,rname,t_filter,zero)
end subroutine uv_filter
!
subroutine t_channel_sampling(rname,huv,nident,msize)
  use image_def
  use clean_default
  use gbl_message
  use imager_interfaces, only : map_message
  !---------------------------------------------------------------------
  ! @ public-mandatory
  !
  ! IMAGER
  !   Check how many channels can share the same beam with a user
  !   specified accuracy
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: rname      ! Caller name
  type(gildas), intent(in) :: huv            ! UV data header
  integer, intent(out) :: nident             ! returned step
  integer, intent(in) :: msize               ! Current map_size
  !
  real :: df, dc, r
  integer :: q
  character(len=80) :: chain
  !
  !
  ! Allow Cell_Precis (default 10 %) pixel difference at map edge
  !
  ! Relative Delta Frequency per channel is
  df = abs(huv%gil%fres/huv%gil%freq)
  !
  ! so scale error at map edge is, in pixel units
  dc = df * msize / 2
  !
  ! so allowed number of channels with same beam is
  nident = max(nint(default_map%precis/dc),1)
  nident = min(nident,huv%gil%nchan)
  !
  write(chain,'(A,I6,A,F10.1)') 'Maximum number of channels '// &
    & 'for same beam ',nident,' Bandwidth ',abs(nident*huv%gil%fres)
  call map_message(seve%i,rname,chain)
  !
  ! With random Frequency axis, use only 1 channel
  if (huv%gil%nfreq.gt.1) nident = 1
  !
  ! Equalize the number of averaged channels to get channels of similar widths. 
  r = real(huv%gil%nchan)/real(nident)
  if (r.lt.10.0) then
    q = int(r)
    if (real(q).ne.r) q = q+1
    nident = int((huv%gil%nchan+q-1.)/real(q))
  endif
  !  
end subroutine t_channel_sampling
!
!
subroutine t_continuum(hluv,hcuv,channels,chflag,uvcode,error,spindex,ofreq)
  use gkernel_interfaces
  use gildas_def
  use image_def
  use uvmap_def
  use gbl_message
  use imager_interfaces, only : map_message
  !$ use omp_lib
  !---------------------------------------------------------------------
  ! @ public-mandatory
  !
  ! IMAGER
  !   Support routine for UV_CONTINUUM 
  !
  !   Create a continuum UV table from a Line one
  !---------------------------------------------------------------------
  !
  type (gildas), intent(in) :: hluv       ! Line UV header
  type (gildas), intent(inout) :: hcuv    ! Continuum UV header
  integer, intent(in) :: channels(3)      ! Channel selection
  integer, intent(in) :: chflag(:)        ! Channel Flags
  integer, intent(in) :: uvcode           ! Type of UV data
  logical, intent(out) :: error
  real, intent(in), optional :: spindex   ! Spectral index
  real(8), intent(in), optional :: ofreq  ! Reference Frequency
  !
  character(len=*), parameter :: rname='UV_CONT'
  character(len=80) :: mess
  real(8) :: freq,fval,scale_uv,scale_flux,scale_w
  real, allocatable :: are(:), aim(:), awe(:), adw(:)
  real :: re, im, we, dw, alpha
  integer :: ifi,ila,nv,ic,jc,kc,ier
  integer :: iv,ov,nt,ft
  integer :: othread, nthread, ov_num, env
  real(8), allocatable :: uv_scale(:)
  real(8), parameter :: clight_kms = 299792.458d0   ! [km/s] Light velocity
  !
  error = .false.
  !
  ! Define number of Visibilities and Channels...
  nv = hluv%gil%nvisi
  nt = hluv%gil%ntrail
  ft = hluv%gil%lcol+1
  !
  ov_num =  (channels(2)-channels(1))/channels(3)+1
  !
  allocate(uv_scale(channels(2)),stat=ier)
  if (ier.ne.0) then
    call map_message(seve%e,rname,'Memory allocation error')
    error = .true.
    return
  endif
  !
  ! The problem is to define the effective "mean" frequency of the observation.  
  !
  !! fval = hluv%gil%val(hluv%gil%faxi)    ! This is not correct... 
  ! For linear sampling this is
  !! fval = fval + ((channels(1)+channels(2))*0.5d0-hluv%gil%ref(hluv%gil%faxi)) * hluv%gil%inc(hluv%gil%faxi)  
  ! or more precisely
  !! fval = gdf_uv_frequency(hluv, dble (channels(1)+channels(2))/2.d0 )
  !
  ! In general, including irregular sampling
  fval = 0d0
  do ic=channels(1),channels(2)
    fval = fval+gdf_uv_frequency(hluv, dble (ic))
  enddo
  fval = fval/dble(channels(2)-channels(1)+1)
  if (present(spindex)) then
    alpha = spindex    
    if (ofreq.ne.0D0) then
      if (abs(fval-ofreq)/fval.gt.0.3) then
        write (mess,'(A,F10.0,A)') 'Specified frequency is too far from mean frequency ',fval,' MHz'
        call map_message(seve%e,rname,mess,3)
        error = .true.
        return
      endif
      fval = ofreq
    endif
  else
    alpha = 0.
  endif
  !
  ! All these assume similar weights for all channels
  !
  do ic=channels(1),channels(2),channels(3)
    freq = gdf_uv_frequency(hluv, dble (2*ic+channels(3)-1)/2.d0 )
    !
    ! The angular scale goes as Lambda/B, i.e. 1/(B nu)
    ! so to preserve a constant angular scale, the "apparent"
    ! B must scale as \nu
    !
    ! so
    uv_scale(ic) = freq/fval ! This is the right formula...
    scale_uv = uv_scale(ic)
    !!Print *,'Scale UV ',ic, (ic+channels(3))/2.0, scale_uv, fval, freq
  enddo
  !  
  if (alpha.ne.0.) then
    !
    ! Spectral index code
    if (uvcode.eq.code_uvt) then  ! UVT order
      !
      !$OMP PARALLEL DEFAULT(none) &
      !$OMP   & SHARED(nv, ov_num, uv_scale, hluv, hcuv, channels) &
      !$OMP   & SHARED(chflag, alpha, nt, ft) &
      !$OMP   & PRIVATE(iv,ov,fval,ic,freq,re,im,we,kc,jc,dw) &
      !$OMP   & PRIVATE(scale_uv,scale_flux,scale_w)
      !
      !$OMP DO
      do iv=1,nv
        ov = (iv-1)*ov_num+1
        !
        ! Fill in, channel after channel
        do ic=channels(1),channels(2),channels(3)
          scale_uv = uv_scale(ic)
          scale_flux = scale_uv**(-alpha)
          scale_w = scale_uv**(2*alpha)
          !
          hcuv%r2d(1:3,ov) = hluv%r2d(1:3,iv)*scale_uv
          hcuv%r2d(4:7,ov) = hluv%r2d(4:7,iv)
          !
          ! Compact the channels first
          if (channels(3).gt.1) then
            re = 0
            im = 0
            we = 0
            kc = 5+3*ic
            do jc = ic,min(ic+channels(3)-1,channels(2))
              if (chflag(jc).eq.1) then
                ! Here we use the Channel mask defined by UV_FILTER in addition
                ! to any previous flag.   UV_FILTER /RESET would then work in all cases
                dw = max(0.,hluv%r2d(kc+2,iv))
                !
                re = re + hluv%r2d(kc,iv)*dw
                kc = kc+1
                im = im + hluv%r2d(kc,iv)*dw
                we = we+dw
                kc = kc+2
              else
                kc = kc+3   ! Skip channel
              endif
            enddo
            if (we.ne.0.0) then
              re = re/we
              im = im/we
            end if
            hcuv%r2d(8,ov) = re*scale_flux
            hcuv%r2d(9,ov) = im*scale_flux
            hcuv%r2d(10,ov) = we
          else
            if (chflag(ic).eq.1) then
              ! Here we use the Channel mask defined by UV_FILTER in addition
              ! to any previous flag.   UV_FILTER /RESET would then work in all cases
              hcuv%r2d(8:9,ov)  = hluv%r2d(5+3*ic:6+3*ic,iv)*scale_flux
              hcuv%r2d(10,ov)  = hluv%r2d(7+3*ic,iv)*scale_w
            else
              hcuv%r2d(8:10,ov) = 0.0
            endif
          endif
          if (nt.gt.0) then
            hcuv%r2d(11:,ov) = hluv%r2d(ft:,iv)
          endif
          ov = ov+1
        enddo
        if (ov.ne.iv*ov_num+1) print *,'Programming error ',iv,ov,ov_num
      enddo
      !$OMP END DO
      !$OMP END PARALLEL
      !
    else if (uvcode.eq.code_tuv) then ! TUV order
      !
      Print *,'TUV order '
      if (channels(3).gt.1) then
        env = nv  ! Work arrays per visibility
      else
        env = 1   ! Dummies
      endif
      allocate (are(env),aim(env),awe(env),adw(env),stat=ier)
      if (ier.ne.0) then
        call map_message(seve%e,rname,'Channels allocation error')
        error = .true.
        return
      endif
      !
      ! Fill in, channel after channel
      othread = 1
      nthread = 1
      !$ othread = omp_get_max_threads()
      !$ nthread = min(othread,ov_num)
      !$ call omp_set_num_threads(nthread)
      !
      !$OMP PARALLEL DEFAULT(none) &
      !$OMP   & SHARED(nv,uv_scale,hluv,hcuv,channels,alpha,nt,ft,chflag) &
      !$OMP   & PRIVATE(ic,ifi,ila,freq) &
      !$OMP   & PRIVATE(are,aim,awe,jc,adw) &
      !$OMP   & PRIVATE(scale_uv,scale_flux,scale_w)
      !
      !$OMP DO
      do ic=channels(1),channels(2),channels(3)
        ifi = (ic-1)*nv+1
        ila = ifi+nv-1
        scale_uv = uv_scale(ic)
        scale_flux = scale_uv**(-alpha)
        scale_w = scale_uv**(2*alpha)
        !
        hcuv%r2d(ifi:ila,1:3) = hluv%r2d(1:nv,1:3)*scale_uv
        hcuv%r2d(ifi:ila,4:7) = hluv%r2d(1:nv,4:7)
        !
        ! Compact the channels first
        if (channels(3).gt.1) then
          are = 0
          aim = 0
          awe = 0
          do jc = ic,min(ic+channels(3)-1,channels(2))
            if (chflag(jc).eq.1) then
              ! Here we use the Channel mask defined by UV_FILTER in addition
              ! to any previous flag.   UV_FILTER /RESET would then work in all cases
              adw(:) = max(0.,hluv%r2d(1:nv,7+3*jc))
              are(:) = are + hluv%r2d(1:nv,5+3*jc)*adw
              aim(:) = aim + hluv%r2d(1:nv,6+3*jc)*adw
              awe(:) = awe+adw
            endif
          enddo
          where (awe.ne.0.)
            are(:) = are/awe
            aim(:) = aim/awe
          end where
          hcuv%r2d(ifi:ila,8) = are*scale_flux
          hcuv%r2d(ifi:ila,9) = aim*scale_flux
          hcuv%r2d(ifi:ila,10) = awe*scale_w
        else
          if (chflag(ic).eq.1) then
            hcuv%r2d(ifi:ila,8:9) = hluv%r2d(1:nv,5+3*ic:6+3*ic)*scale_flux
            ! Here we use the Channel mask defined by UV_FILTER in addition
            ! to any previous flag.   UV_FILTER /RESET would then work in all cases
            hcuv%r2d(ifi:ila,10) = hluv%r2d(1:nv,7+3*ic)*scale_w
          else
            hcuv%r2d(ifi:ila,8:10) = 0.
          endif
        endif
        if (nt.gt.0) then
          hcuv%r2d(ifi:ila,11:) = hluv%r2d(1:nv,ft:)
        endif
      enddo
      !$OMP END DO
      !$OMP END PARALLEL
      !$ call omp_set_num_threads(othread)
      deallocate (are,aim,awe,stat=ier)
    endif
    !
  else
    ! Simple code with no spectral index
    if (uvcode.eq.code_uvt) then  ! UVT order
      !
      !$OMP PARALLEL DEFAULT(none) &
      !$OMP   & SHARED(nv, ov_num, uv_scale, hluv, hcuv, channels, nt, ft, chflag) &
      !$OMP   & PRIVATE(iv,ov,fval,ic,freq,scale_uv,re,im,we,kc,jc,dw)
      !
      !$OMP DO
      do iv=1,nv
        ov = (iv-1)*ov_num+1
        !
        ! Fill in, channel after channel
        do ic=channels(1),channels(2),channels(3)
          scale_uv = uv_scale(ic)
          !
          hcuv%r2d(1:3,ov) = hluv%r2d(1:3,iv)*scale_uv
          hcuv%r2d(4:7,ov) = hluv%r2d(4:7,iv)
          !
          ! Compact the channels first
          if (channels(3).gt.1) then
            re = 0
            im = 0
            we = 0
            kc = 5+3*ic
            do jc = ic,min(ic+channels(3)-1,channels(2))
              if (chflag(jc).eq.1) then
                ! Here we use the Channel mask defined by UV_FILTER in addition
                ! to any previous flag.   UV_FILTER /RESET would then work in all cases
                dw = max(0.,hluv%r2d(kc+2,iv))
                re = re + hluv%r2d(kc,iv)*dw
                kc = kc+1
                im = im + hluv%r2d(kc,iv)*dw
                we = we+dw
                kc = kc+2
              else
                kc = kc+3
              endif
            enddo
            if (we.ne.0.0) then
              re = re/we
              im = im/we
            end if
            hcuv%r2d(8,ov) = re
            hcuv%r2d(9,ov) = im
            hcuv%r2d(10,ov) = we
          else
            if (chflag(ic).eq.1) then
              ! Here we use the Channel mask defined by UV_FILTER in addition
              ! to any previous flag.   UV_FILTER /RESET would then work in all cases
              hcuv%r2d(8:10,ov)  = hluv%r2d(5+3*ic:7+3*ic,iv)
            else
              hcuv%r2d(8:10,ov)  = 0.
            endif            
          endif
          if (nt.gt.0) then
            hcuv%r2d(11:,ov) = hluv%r2d(ft:,iv)
          endif
          ov = ov+1
        enddo
        if (ov.ne.iv*ov_num+1) print *,'Programming error ',iv,ov,ov_num
      enddo
      !$OMP END DO
      !$OMP END PARALLEL
      !
    else if (uvcode.eq.code_tuv) then ! TUV order
      Print *,'TUV order '
      if (channels(3).gt.1) then
        env = nv
      else 
        env = 1
      endif
      allocate (are(env),aim(env),awe(env),adw(env),stat=ier)
      if (ier.ne.0) then
        call map_message(seve%e,rname,'Channels allocation error')
        error = .true.
        return
      endif
      !
      ! Fill in, channel after channel
      othread = 1
      nthread = 1
      !$ othread = omp_get_max_threads()
      !$ nthread = min(othread,ov_num)
      !$ call omp_set_num_threads(nthread)
      !
      !$OMP PARALLEL DEFAULT(none) &
      !$OMP   & SHARED(nv,uv_scale,hluv,hcuv,channels,nt,ft,chflag) &
      !$OMP   & PRIVATE(ic,ifi,ila,freq,scale_uv) &
      !$OMP   & PRIVATE(are,aim,awe,jc,adw)
      !
      !$OMP DO
      do ic=channels(1),channels(2),channels(3)
        ifi = (ic-1)*nv+1
        ila = ifi+nv-1
        scale_uv = uv_scale(ic)
        !
        hcuv%r2d(ifi:ila,1:3) = hluv%r2d(1:nv,1:3)*scale_uv
        hcuv%r2d(ifi:ila,4:7) = hluv%r2d(1:nv,4:7)
        !
        ! Compact the channels first
        if (channels(3).gt.1) then
          are = 0
          aim = 0
          awe = 0
          do jc = ic,min(ic+channels(3)-1,channels(2))
            if (chflag(jc).eq.1) then
              ! Here we use the Channel mask defined by UV_FILTER in addition
              ! to any previous flag.   UV_FILTER /RESET would then work in all cases
              adw(:) = max(0.,hluv%r2d(1:nv,7+3*jc))
              are(:) = are + hluv%r2d(1:nv,5+3*jc)*adw
              aim(:) = aim + hluv%r2d(1:nv,6+3*jc)*adw
              awe(:) = awe+adw
            endif
          enddo
          where (awe.ne.0.)
            are(:) = are/awe
            aim(:) = aim/awe
          end where
          hcuv%r2d(ifi:ila,8) = are
          hcuv%r2d(ifi:ila,9) = aim
          hcuv%r2d(ifi:ila,10) = awe
        else
          if (chflag(ic).eq.1) then
            ! Here we use the Channel mask defined by UV_FILTER in addition
            ! to any previous flag.   UV_FILTER /RESET would then work in all cases
            hcuv%r2d(ifi:ila,8:10) = hluv%r2d(1:nv,5+3*ic:7+3*ic)
          else
            hcuv%r2d(ifi:ila,8:10) = 0.
          endif
        endif
        if (nt.gt.0) then
          hcuv%r2d(ifi:ila,11:) = hluv%r2d(1:nv,ft:)
        endif
      enddo
      !$OMP END DO
      !$OMP END PARALLEL
      !$ call omp_set_num_threads(othread)
      deallocate (are,aim,awe,stat=ier)
    endif
    !
  endif
  !
  ! FVAL should be the new Rest Frequency
  fval = fval / (1.d0 + hcuv%gil%dopp - hcuv%gil%voff/clight_kms)
  call gdf_modify(hcuv,hcuv%gil%voff,fval,error=error)
  hcuv%gil%ref(1) = 1.D0 
  !
end subroutine t_continuum
!
subroutine uv_filter_base(line,error,rname,t_routine,zero)
  use gkernel_interfaces
  use gildas_def
  use gkernel_types
  use gbl_format
  use clean_types
  use clean_arrays
  use uvsplit_mod
  use gbl_message
  use iso_c_binding
  use imager_interfaces, only : map_message
  !---------------------------------------------------------------------
  ! @ private
  !
  ! IMAGER  support for
  !   UV_FILTER or UV_BASELINE  /CHANNEL ListVariable [/ZERO]
  !   UV_FILTER or UV_BASELINE  /FREQUENCIES ListFreq /WIDTH Width [UNIT]
  !   UV_FILTER or UV_BASELINE  /VELOCITY ListVelo /WIDTH Width [UNIT]
  !   UV_FILTER or UV_BASELINE  /RANGE Min Max [TYPE]
  !      [/FILE FileIn [FileOut]]
  !
  ! "Filter", i.e. flag, a list of channels in the current UV
  ! data set. Flagging is reversible, using the /RESET option
  ! With /ZERO, the "filtered" visibilities are set to zero.
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: line  ! Command line
  logical, intent(out) :: error            ! Error flag
  external :: t_routine
  character(len=*), intent(in) :: rname
  integer, intent(in) :: zero
  !
  real(kind=8), parameter :: pi=3.14159265358979323846d0
  real(kind=8), parameter :: f_to_k = 2.d0*pi/299792458.d-6
  !
  real(8) :: drange(2)
  integer :: nn, nc(2)
  character(len=64) :: listname
  logical :: found
  type(sic_descriptor_t) :: desc
  integer :: nf, k, i, j, l, m, ichan, jchan, narg, ier
  real(8) :: freq, velo
  real(4) :: width
  type(c_ptr) :: cptr
  integer, pointer :: channels(:)
  integer :: na, nstyle
  integer, parameter :: mstyle=3
  character(len=12) :: vstyle(mstyle), astyle, argu
  data vstyle/'CHANNEL','FREQUENCY','VELOCITY'/
  !
  !
  if (sic_present(opt_chan,0)) then
    narg = sic_narg(opt_chan)
    if (narg.gt.0) then
      call sic_ke(line,opt_chan,1,listname,na,.true.,error)
    else
      listname = 'PREVIEW%CHANNELS'
      na = len_trim(listname)
    endif
    !
    call sic_ch(line,opt_chan,1,listname,na,.false.,error)
    call sic_descriptor(listname,desc,found)
    if (.not.found) then
      desc%ndim = 1
      desc%dims(1) = 1
      desc%addr = locwrd(ichan)
      desc%type = fmt_i4
      if (narg.eq.0) then
        ichan = 0 
      else
        call sic_i4(line,opt_chan,1,ichan,.true.,error)
        if (error) then
          call map_message(seve%e,rname,'Variable '//trim(listname)//' does not exists')
          error = .true.
          return
        endif
      endif
    endif
    if (desc%type.ne.fmt_i4) then
      call map_message(seve%e,rname,'Variable '//trim(listname)//' must be Integer ')
      error = .true.
      return
    endif
    if (desc%ndim.ne.1) then
      call map_message(seve%e,rname,'Variable '//trim(listname)//' must have rank 1')
      error = .true.
      return
    endif
    call adtoad(desc%addr,cptr,1)
    nf = desc%dims(1)
    call c_f_pointer(cptr,channels,desc%dims(1:1))
    call t_routine (nf,channels,zero,error)
    !
  else if (sic_present(opt_freq,0)) then
    width = abs(hiuv%gil%fres)  ! In MHz
    call sic_r4(line,opt_width,1,width,.false.,error)
    if (sic_present(opt_width,2)) then
      call sic_ke(line,opt_width,2,argu,na,.true.,error)
      call sic_ambigs (rname,argu,astyle,nstyle,vstyle,mstyle,error)
      select case(astyle)
        case ('CHANNEL')
          width = width*abs(hiuv%gil%fres)
        case ('VELOCITY')
          width = width*abs(hiuv%gil%fres/hiuv%gil%vres)
      end select
    endif
    width = 0.5*width
    !
    narg = sic_narg(opt_freq)
    allocate(channels(hiuv%gil%nchan),stat=ier)
    if (ier.ne.0) then
      call map_message(seve%e,rname,'Channels allocation error')
      error = .true.
      return
    endif
    k = 0
    !
    do i=1,narg
      call sic_r8(line,opt_freq,i,freq,.true.,error)
      if (error) return
      if (hiuv%gil%fres.gt.0) then
        ichan = (freq-hiuv%gil%freq-width)/hiuv%gil%fres + hiuv%gil%ref(1)
        jchan = (freq-hiuv%gil%freq+width)/hiuv%gil%fres + hiuv%gil%ref(1)
      else
        ichan = (freq-hiuv%gil%freq+width)/hiuv%gil%fres + hiuv%gil%ref(1)
        jchan = (freq-hiuv%gil%freq-width)/hiuv%gil%fres + hiuv%gil%ref(1)
      endif
      !
      ! Set channels only once...
      do j=ichan,jchan
        if (j.lt.0 .or. j.gt.hiuv%gil%nchan) then
          cycle
        else
          m = 0
          do l=1,k
            if (channels(l).eq.j) then
              m = l
              exit
            endif
          enddo
          if (m.eq.0) then
            k = k+1
            channels(k) = j
          endif
        endif
      enddo
    enddo
    call t_routine(k,channels,zero,error)
    deallocate(channels)
    !
  else if (sic_present(opt_velo,0)) then
    width = abs(hiuv%gil%vres)  ! In km/s
    call sic_r4(line,opt_width,1,width,.false.,error)
    if (sic_present(opt_width,2)) then
      call sic_ke(line,opt_width,2,argu,na,.true.,error)
      call sic_ambigs (rname,argu,astyle,nstyle,vstyle,mstyle,error)
      select case(astyle)
        case ('CHANNEL')
          width = width*abs(hiuv%gil%vres)
        case ('FREQUENCY')
          width = width*abs(hiuv%gil%vres/hiuv%gil%fres)
      end select
    endif
    width = 0.5*width
    !
    narg = sic_narg(opt_velo)
    allocate(channels(hiuv%gil%nchan),stat=ier)
    if (ier.ne.0) then
      call map_message(seve%e,rname,'Channels allocation error')
      error = .true.
      return
    endif
    k = 0
    !
    do i=1,narg
      call sic_r8(line,opt_velo,i,velo,.true.,error)
      if (error) return
      if (hiuv%gil%vres.gt.0) then
        ichan = (velo-hiuv%gil%voff-width)/hiuv%gil%vres + hiuv%gil%ref(1)
        jchan = (velo-hiuv%gil%voff+width)/hiuv%gil%vres + hiuv%gil%ref(1)
      else
        ichan = (velo-hiuv%gil%voff+width)/hiuv%gil%vres + hiuv%gil%ref(1)
        jchan = (velo-hiuv%gil%voff-width)/hiuv%gil%vres + hiuv%gil%ref(1)
      endif
      !
      ! Set channels only once...
      do j=ichan,jchan
        if (j.lt.0 .or. j.gt.hiuv%gil%nchan) then
          cycle
        else
          m = 0
          do l=1,k
            if (channels(l).eq.j) then
              m = l
              exit
            endif
          enddo
          if (m.eq.0) then
            k = k+1
            channels(k) = j
          endif
        endif
      enddo
    enddo
    call t_routine(k,channels,zero,error)
    deallocate(channels)
    !
  else if (sic_present(opt_range,0)) then
    call sic_r8 (line,opt_range,1,drange(1),.true.,error)
    if (error) return
    call sic_r8 (line,opt_range,2,drange(2),.true.,error)
    if (error) return
    call sic_ke (line,opt_range,3,argu,nn,.true.,error)
    if (error) return
    error = .false.
    call sic_ambigs (rname,argu,astyle,nstyle,vstyle,mstyle,error)
    if (error)  return
    call out_range(rname,astyle,drange,nc,hiuv,error)
    if (error) return
    narg = nc(2)-nc(1)+1
    allocate(channels(narg),stat=ier)
    if (ier.ne.0) then
      call map_message(seve%e,rname,'Channels allocation error')
      error = .true.
      return
    endif
    do i=1,narg
      channels(i) = i+nc(1)-1
    enddo
    call t_routine (narg,channels,zero,error)
  else
    ! If no option, try as if /CHANNEL with no Arguments...
    listname = 'PREVIEW%CHANNELS'
    call sic_descriptor(listname,desc,found)
    if (.not.found) then
      if (zero.eq.-1) then  
        ! Reset everything
        if (allocated(dchanflag)) dchanflag = 1
      else
        ! But to set it, we must have some information
        call map_message(seve%e,rname,'No PREVIEW and '// &
          &  ' missing option /CHANNEL, /FREQUENCY, /RANGE or /VELOCITY')
        error = .true.
      endif
      return
    endif
    if (desc%type.ne.fmt_i4) then
      call map_message(seve%e,rname,'Variable '//trim(listname)//' must be Integer ')
      error = .true.
      return
    endif
    if (desc%ndim.ne.1) then
      call map_message(seve%e,rname,'Variable '//trim(listname)//' must have rank 1')
      error = .true.
      return
    endif
    call adtoad(desc%addr,cptr,1)
    nf = desc%dims(1)
    call c_f_pointer(cptr,channels,desc%dims(1:1))
    call t_routine (nf,channels,zero,error)
  endif
  !
  save_data(code_save_uv) = .true.
  !
  ! We do not use Buffers here - Need to play safe to force re-reading
  optimize(code_save_uv)%change = optimize(code_save_uv)%change+100
  !
end subroutine uv_filter_base
!
subroutine t_filter(mf,filter,zero,error)
  use gildas_def
  use image_def
  use clean_arrays
  use uvsplit_mod
  use gbl_message
  use imager_interfaces, only : filter_line, map_message
  !---------------------------------------------------------------------
  ! @ private
  !
  ! IMAGER
  !   Support routine for UV_FILTER
  !
  !   Filter / Flag a list of channels
  !---------------------------------------------------------------------
  integer, intent(in) :: mf          ! Number of values
  integer, intent(in) :: filter(mf)  ! Channel list
  integer, intent(in) :: zero        ! Zero or not
  logical, intent(out) :: error
  !
  character(len=*), parameter :: rname='UV_FILTER'
  !
  integer :: nf, nv, nc, i, ier
  integer, allocatable :: filtre(:)
  integer :: nvisi, mvisi, ib
  character(len=120) :: mess
  !
  nc = hiuv%gil%nchan
  !
  allocate(filtre(mf+nc/10),stat=ier)
  if (ier.ne.0) then
    error = .true.
    return
  endif
  !
  nf = 0
  do i=1,mf
    if (filter(i).gt.0 .and. filter(i).le.nc) then
      nf = nf+1
      filtre(nf) = filter(i)
    endif
  enddo
  !
  if (use_file) then
    !
    ! Drop EDGE_DROP at each edge
    do i=1,nint(edge_drop*nc)
      nf = nf+1
      filtre(nf) = i
    enddo
    do i=nint(nc*(1.0-edge_drop)),nc
      nf = nf+1
      filtre(nf) = i
    enddo
    !
    mvisi = nblock
    !
    allocate(hiuv%r2d(hiuv%gil%dim(1),mvisi),stat=ier)
    if (ier.ne.0) then
      call map_message(seve%e,rname,'Memory allocation error')
      error = .true.
      return
    endif
    !
    do ib=1,hiuv%gil%dim(2),mvisi
      !
      ! Read the data
      write(mess,*) ib,' / ',hiuv%gil%dim(2),mvisi
      call map_message(seve%i,rname,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
      !
      call filter_line(nc,nf,nvisi,hiuv%r2d,filtre,0)
      if (error) return
      !
      houv%blc = hiuv%blc
      houv%trc = hiuv%trc
      call gdf_write_data (houv,hiuv%r2d,error)
      if (error) return
    enddo
    call gdf_close_image(houv,error)
    if (error) return
    !
    call gdf_close_image(hiuv,error)
    if (error) return
    !
    call map_message(seve%i,rname,'Created '//trim(houv%file))
    error = .false.
    !
  else
    ! Just set the channel mask according to the "filtre" 
    ier = 0
    if (allocated(dchanflag)) then
      if (size(dchanflag).lt.nc) then
        deallocate(dchanflag)
        allocate(dchanflag(nc),stat=ier)
        if (ier.eq.0) dchanflag = 1
      endif
    else
      allocate(dchanflag(nc),stat=ier)
      if (ier.eq.0) dchanflag = 1
    endif
    !
    if (ier.eq.0) then
      !
      ! Just remember the status of each channel
      do i=1,nf
        dchanflag(filtre(i)) = -zero  ! -1,0,1 
      enddo
    else
      call map_message(seve%w,rname,'Channel Mask allocation error')
      !
      ! If we cannot, apply it here on the data
      nv = hiuv%gil%dim(2)
      call filter_line(nc,nf,nv,duv,filtre,zero)
    endif
  endif
  !
  deallocate (filtre)
end subroutine t_filter
!
subroutine filter_line(nc,nf,nv,duv,filtre,zero)
  !---------------------------------------------------------------------
  ! @ private-mandatory
  !
  ! IMAGER
  !   Support routine for UV_FILTER 
  !
  !   Flag or set to Zero the line regions
  !---------------------------------------------------------------------
  integer, intent(in) :: nf ! Number of good channels
  integer, intent(in) :: nv ! Number of visibilities
  integer, intent(in) :: nc ! Number of channels
  integer, intent(in) :: zero  ! Set to zero or Flag ?
  integer, intent(in) :: filtre(nf)
  real, intent(inout) :: duv(:,:)
  !
  integer :: iv,i
  !
  select case (zero)
  case (1)
    !$OMP PARALLEL DEFAULT(none)  &
    !$OMP & SHARED(duv,nv,nf,filtre) &
    !$OMP & PRIVATE(iv,i)
    !$OMP DO
    do iv=1,nv
      do i=1,nf
        duv(7+3*filtre(i),iv) = -abs(duv(7+3*filtre(i),iv))
      enddo
    enddo  
    !$OMP END DO
    !$OMP END PARALLEL
  case (0)
    !$OMP PARALLEL DEFAULT(none) &
    !$OMP & SHARED(duv,nv,nf,filtre) &
    !$OMP & PRIVATE(iv,i)
    !$OMP DO
    do iv=1,nv
      do i=1,nf
        duv(5+3*filtre(i):7+3*filtre(i),iv) = 0
      enddo
    enddo
    !$OMP END DO
    !$OMP END PARALLEL
  case(-1)
    !$OMP PARALLEL DEFAULT(none) &
    !$OMP & SHARED(duv,nv,nf,filtre) &
    !$OMP & PRIVATE(iv,i)
    !$OMP DO
    do iv=1,nv
      do i=1,nf
        duv(7+3*filtre(i),iv) =  abs(duv(7+3*filtre(i),iv))
      enddo
    enddo
    !$OMP END DO
    !$OMP END PARALLEL
  end select
end subroutine filter_line
!
subroutine t_baseline(mf,filter,degree,error)
  use gildas_def
  use image_def
  use clean_arrays
  use uvsplit_mod
  use gbl_message
  use imager_interfaces, only : remove_base, map_message
  !---------------------------------------------------------------------
  ! @ private
  !
  ! IMAGER
  !    Support routine for UV_BASELINE
  !
  !    Subtract a baseline with a list of channels to be ignored
  !---------------------------------------------------------------------
  integer, intent(in) :: mf          ! Number of values
  integer, intent(in) :: filter(mf)  ! Channel list
  integer, intent(in) :: degree      ! Polynomial degree
  logical, intent(out) :: error
  !
  character(len=*), parameter :: rname='UV_BASELINE'
  !
  integer :: nf, nv, nc, i, j, ier
  integer, allocatable :: filtre(:)
  integer :: nvisi, mvisi, ib, fc, lc
  character(len=120) :: mess
  !
  error = .false.
  nv = hiuv%gil%nvisi ! not %dim(2)
  nc = hiuv%gil%nchan
  !
  ! FILTER contains the ones to be ignored.
  ! We must build the list of valid continuum channels...
  allocate(filtre(nc),stat=ier)
  if (ier.ne.0) then
    error = .true.
    return
  endif
  !
  nf = 0
  if (use_file) then
    fc = edge_drop*nc
    lc = (1.0-edge_drop)*nc
  else
    fc = 1
    lc = nc
  endif
  do i=1,nc
    nf = nf+1
    filtre(nf) = i
    do j=1,mf
      if (filter(j).eq.i) then
        nf = nf-1
        exit
      endif
    enddo
  enddo
  !
  if (use_file) then
    !
    mvisi = nblock
    !
    allocate(hiuv%r2d(hiuv%gil%dim(1),mvisi),stat=ier)
    if (ier.ne.0) then
      call map_message(seve%e,rname,'Memory allocation error')
      error = .true.
      return
    endif
    !
    do ib=1,hiuv%gil%nvisi,mvisi
      !
      ! Read the data
      write(mess,*) ib,' / ',hiuv%gil%nvisi,mvisi
      call map_message(seve%i,rname,mess)
      hiuv%blc(2) = ib
      hiuv%trc(2) = min(hiuv%gil%nvisi,ib-1+mvisi)
      nvisi = hiuv%trc(2)-hiuv%blc(2)+1
      call gdf_read_data(hiuv,hiuv%r2d,error)
      if (error) return
      !
      ! From data file, normally no need to unflag anything
      call remove_base(nf,nvisi,nc,hiuv%r2d,degree,filtre,mf,filter,error)
      if (error) return
      !
      houv%blc = hiuv%blc
      houv%trc = hiuv%trc
      call gdf_write_data (houv,hiuv%r2d,error)
      if (error) return
    enddo
    call gdf_close_image(houv,error)
    if (error) return
    !
    call gdf_close_image(hiuv,error)
    if (error) return
    !
    call map_message(seve%i,rname,'Created '//trim(houv%file))
    error = .false.
    !
  else
    call remove_base(nf,nv,nc,duv,degree,filtre,mf,filter,error)
  endif
  deallocate (filtre)
end subroutine t_baseline
!
subroutine remove_base(nf,nv,nc,duv,degree,filtre,nb,filter,error)
  !---------------------------------------------------------------------
  ! @ private-mandatory  
  !
  ! IMAGER
  !   Support routine for UV_BASELINE
  !
  !   Remove a baseline in a UV data
  !---------------------------------------------------------------------
  integer, intent(in) :: nf ! Number of good channels
  integer, intent(in) :: nv ! Number of visibilities
  integer, intent(in) :: nc ! Number of channels
  integer, intent(in) :: degree ! Degree of polynomial
  integer, intent(in) :: filtre(:)    ! The channels to be considered
  integer, intent(in) :: nb           ! Number of filtered channels
  integer, intent(in) :: filter(:)    ! The filtered channels
  real, intent(inout) :: duv(:,:)
  logical, intent(out) :: error
  !
  real, allocatable :: wreal(:), wimag(:), wx(:), wxx(:), wxy(:)
  integer :: iv,i,ier, enf
  real :: mreal, mimag, sx, sy, sxx, sxy, delta, a, b, w
  !
  error = .true.
  if (degree.eq.0) then
    enf = 1
  else
    enf = nf
  endif
  allocate(wreal(nf),wimag(nf),wx(enf),wxx(enf),wxy(enf),stat=ier)
  if (ier.ne.0) return
  !
  if (enf.eq.nf) then
    wx(:) = filtre(1:nf)
  endif
  error = .false.
  !
  !$OMP PARALLEL DEFAULT(none) &
  !$OMP & SHARED(nv,nf,duv,degree,nc,nb,filtre,filter) &
  !$OMP & PRIVATE(iv,w,wreal,wimag,mreal,mimag,i) &
  !$OMP & PRIVATE(sx,sy,sxx,sxy,wx,wxx,wxy,delta,a,b)
  !$OMP DO
  do iv=1,nv
    w = 0
    do i=1,nf
      wreal(i) = duv(5+3*filtre(i),iv)
      wimag(i) = duv(6+3*filtre(i),iv)
      ! Reset the Weights to > 0 (un-flagged) if any channel is unflagged
      if (duv(7+3*i,iv).gt.0) w = 1
    enddo
    !
    ! Compute the fitting polynomials.
    ! Filtre(:) is the channel number which can be used as abscissa
    ! For the time being, only mean value...
    if (degree.eq.0) then
      mreal = sum(wreal)/nf
      mimag = sum(wimag)/nf
      !
      ! Subtract
      do i=1,nc
        duv(5+3*i,iv) = duv(5+3*i,iv)-mreal
        duv(6+3*i,iv) = duv(6+3*i,iv)-mimag
      enddo
    else if (degree.eq.1) then
      ! This code actually does a poor job. There is not enough
      ! Signal to noise ratio to fit a linear baseline per Visibility
      sx = sum(wx)
      sy = sum(wreal)
      wxx(:) = wx**2
      sxx = sum(wxx)
      wxy(:) = wx*wreal
      sxy = sum(wxy)
      delta = (nf*sxx-sx**2)
      a = (sxx*sy-sx*sxy)/delta
      b = (nf*sxy-sx*sy)/delta
      do i=1,nc
        duv(5+3*i,iv) = duv(5+3*i,iv)-(a+b*i)
      enddo
      !
      sy = sum(wimag)
      wxx(:) = wx**2
      sxx = sum(wxx)
      wxy(:) = wx*wimag 
      sxy = sum(wxy)
      delta = (nf*sxx-sx**2)
      a = (sxx*sy-sx*sxy)/delta
      b = (nf*sxy-sx*sy)/delta
      do i=1,nc
        duv(6+3*i,iv) = duv(6+3*i,iv)-(a+b*i)
      enddo
      !
    endif
    !
    ! Remove the filter
    if (w.gt.0) then
      do i=1,nb
        duv(7+3*filter(i),iv) = abs(duv(7+3*filter(i),iv))
      enddo
    endif      
  enddo
  !$OMP END DO
  !$OMP END PARALLEL
  !
  if (degree.eq.0) then
    deallocate (wreal,wimag)
  else
    deallocate (wreal,wimag,wx,wxx,wxy)
  endif
  error = .false.
end subroutine remove_base
!
subroutine t_split(mf,filter,degree,error)
  use gildas_def
  use image_def
  use clean_arrays
  use gbl_message
  use uvsplit_mod
  use imager_interfaces, only : split_base_line, map_message
  !---------------------------------------------------------------------
  ! @ private
  !
  ! IMAGER
  !    Support routine for UV_SPLIT
  !
  !    Subtract a baseline with a list of channels to be ignored
  !---------------------------------------------------------------------
  integer, intent(in) :: mf          ! Number of values
  integer, intent(in) :: filter(mf)  ! Channel list
  integer, intent(in) :: degree      ! Polynomial degree
  logical, intent(out) :: error
  !
  character(len=*), parameter :: rname='UV_SPLIT'
  !
  integer :: nf, nv, nc, i, j, ier
  integer, allocatable :: filtre(:)
  integer :: nvisi, mvisi, ib, fc, lc, mc
  character(len=120) :: mess
  !
  error = .false.
  nv = hiuv%gil%nvisi !! not %dim(2)
  nc = hiuv%gil%nchan
  mc = hfuv%gil%nchan
  !
  ! FILTER contains the ones to be ignored.
  ! We must build the list of valid continuum channels...
  allocate(filtre(nc),stat=ier)
  if (ier.ne.0) then
    error = .true.
    return
  endif
  !
  nf = 0
  if (use_file) then
    fc = edge_drop*nc
    lc = (1.0-edge_drop)*nc
  else
    fc = 1
    lc = nc
  endif
  do i=fc,lc
    nf = nf+1
    filtre(nf) = i
    do j=1,mf
      if (filter(j).eq.i) then
        nf = nf-1
        exit
      endif
    enddo
  enddo
  !
  if (use_file) then
    !
    mvisi = nblock
    !
    allocate(hiuv%r2d(hiuv%gil%dim(1),mvisi),hfuv%r2d(hfuv%gil%dim(1),mvisi),stat=ier)
    if (ier.ne.0) then
      call map_message(seve%e,rname,'Memory allocation error')
      error = .true.
      return
    endif
    !
    do ib=1,hiuv%gil%nvisi,mvisi
      !
      ! Read the data
      write(mess,*) ib,' / ',hiuv%gil%nvisi,mvisi
      call map_message(seve%i,rname,mess)
      hiuv%blc(2) = ib
      hiuv%trc(2) = min(hiuv%gil%nvisi,ib-1+mvisi)
      nvisi = hiuv%trc(2)-hiuv%blc(2)+1
      call gdf_read_data(hiuv,hiuv%r2d,error)
      if (error) return
      !
      call split_base_line(nf,nvisi,nc,hiuv%r2d,mc,hfuv%r2d,degree,filtre,error)
      if (error) return
      !
      houv%blc = hiuv%blc
      houv%trc = hiuv%trc
      call gdf_write_data (houv,hiuv%r2d,error)
      if (error) return
      !
      hfuv%blc = hiuv%blc
      hfuv%trc = hiuv%trc
      call gdf_write_data (hfuv,hfuv%r2d,error)
    enddo
    call gdf_close_image(houv,error)
    if (error) return
    !
    call gdf_close_image(hiuv,error)
    if (error) return
    !
    call map_message(seve%i,rname,'Created '//trim(houv%file))
    call map_message(seve%i,rname,'Created '//trim(hfuv%file))
    !
    deallocate(hiuv%r2d,hfuv%r2d)
  else
    call map_message(seve%e,rname,'Programming error: SPLIT only valid with files')
    error = .true.
  endif
  deallocate (filtre)
end subroutine t_split
!
subroutine split_base_line(nf,nv,nc,duv,mc,cuv,degree,filtre,error)
  use uvsplit_mod
  use imager_interfaces, except_this => split_base_line
  !---------------------------------------------------------------------
  ! @ private-mandatory
  !
  ! IMAGER
  !   Support routine for UV_SPLIT
  !
  !   Remove a baseline in a UV data, and produce the
  !   Continuum free and Line free UV tables from it.
  !   The Spectral Windows can be indicated by the options, including
  !   the default one derived by UV_PREVIEW.
  !---------------------------------------------------------------------
  integer, intent(in) :: nf         ! Number of good channels
  integer, intent(in) :: nv         ! Number of visibilities
  integer, intent(in) :: nc         ! Number of line channels
  integer, intent(in) :: mc         ! Number of continuum channels
  integer, intent(in) :: degree     ! Degree of polynomial
  integer, intent(in) :: filtre(nf) ! Channels with line
  real, intent(inout) :: duv(:,:)   ! Input line + continuum, output line
  real, intent(out) :: cuv(:,:)     ! Output continuum
  logical, intent(out) :: error
  !
  real, allocatable :: wreal(:), wimag(:), wx(:), wxx(:), wxy(:)
  integer :: iv,i,ier, lc, lt, kt, nt, nstart, enf
  logical :: trail
  real :: mreal, mimag, sx, sy, sxx, sxy, delta, a, b
  real, allocatable :: xuv(:,:)
  !
  !
  lt = ubound(duv,1)
  kt = ubound(cuv,1)
  lc = 7+3*NC
  nt = lt-lc
  !!Print *,' IN LC ',lc,' LT ',lt,' NT ',nt
  !!Print *,' OUT MC ',mc,' LT ',kt,' NT ',nt
  trail = nt.ne.0
  !
  if (degree.eq.0) then
    enf = 1
  else
    enf = nf
  endif
  allocate(wreal(nf),wimag(nf),xuv(lt,1),wx(enf),wxx(enf),wxy(enf),stat=ier)
  if (ier.ne.0) then
    error = .true.
    return
  endif
  if (enf.eq.nf) wx(1:nf) = filtre(1:nf)
  !
  !
  nstart = 1
  !
  do iv=1,nv
    !
    ! Copy  continuum and compress it if needed
    xuv = 0.0
    do i=1,nf
      wreal(i) = duv(5+3*filtre(i),iv)
      wimag(i) = duv(6+3*filtre(i),iv)
      xuv(5+3*filtre(i):7+3*filtre(i),1) = duv(5+3*filtre(i):7+3*filtre(i),iv)
    enddo
    if (trail) xuv(lc:,1) = duv(lc:,iv) 
    if (ncompr.eq.1) then
      cuv(1:7,iv) = duv(1:7,iv)
      cuv(8:,iv) = xuv(8:,1)
    else
      cuv(:,iv:iv) = 0.0
      call compress_uv(cuv(:,iv:iv), &
        & kt,     & ! Output visibility size
        & 1,      & ! Number of output visibilities
        & mc,     & ! Number of output channels
        & xuv,    & ! Input visibilities
        & lt,     & ! Input visibility size
        & ncompr, & ! Compression factor
        & nt)       ! Number of trailing columns
      cuv(1:7,iv) = duv(1:7,iv)
    endif
    !
    ! Compute the fitting polynomials.
    ! Filtre(:) is the channel number which can be used as abscissa
    if (degree.eq.0) then
      ! For the time being, only mean value...
      mreal = sum(wreal)/nf
      mimag = sum(wimag)/nf
      !
      ! Subtract
      do i=1,nc
        duv(5+3*i,iv) = duv(5+3*i,iv)-mreal
        duv(6+3*i,iv) = duv(6+3*i,iv)-mimag
      enddo
    else if (degree.eq.1) then
      ! This code actually does a poor job. There is not enough
      ! Signal to noise ratio to fit a linear baseline per Visibility
      sx = sum(wx)
      sy = sum(wreal)
      wxx(:) = wx**2
      sxx = sum(wxx)
      wxy(:) = wx*wreal
      sxy = sum(wxy)
      delta = (nf*sxx-sx**2)
      a = (sxx*sy-sx*sxy)/delta
      b = (nf*sxy-sx*sy)/delta
      do i=1,nc
        duv(5+3*i,iv) = duv(5+3*i,iv)-(a+b*i)
      enddo
      !
      sy = sum(wimag)
      wxx(:) = wx**2
      sxx = sum(wxx)
      wxy(:) = wx*wimag 
      sxy = sum(wxy)
      delta = (nf*sxx-sx**2)
      a = (sxx*sy-sx*sxy)/delta
      b = (nf*sxy-sx*sy)/delta
      do i=1,nc
        duv(6+3*i,iv) = duv(6+3*i,iv)-(a+b*i)
      enddo
    endif
  enddo
  !
  if (degree.eq.0) then
    deallocate (wreal,wimag)
  else
    deallocate (wreal,wimag,wx,wxx,wxy)
  endif
  error = .false.
end subroutine split_base_line
!
function space_nitems(name,head,last)
  use image_def
  use gkernel_interfaces, only: gdf_nitems
  !---------------------------------------------------------------------
  ! @ public
  !
  ! IMAGER
  !   Returns the number of blocks in the last dimension
  !   according to the NAME logical name
  !--------------------------------------------------------------------- 
  character(len=*), intent(in) :: name
  integer ::space_nitems         ! intent(out) function value
  type(gildas), intent(in) :: head ! Input Gildas header
  integer, intent(in) :: last      ! Last blocked dimension
  !
  integer :: nblock, mblock, i 
  integer(kind=8) :: dims     ! Size of a "row"
  integer(kind=8) :: rows     ! Number of "rows"
  !
  dims = 1
  do i=1,min(last,head%gil%ndim)
    if (head%gil%dim(i).gt.0) dims =dims*head%gil%dim(i)
  enddo
  !
  rows = 1
  do i=last,head%gil%ndim 
    if (head%gil%dim(i).gt.0) rows = rows*head%gil%dim(i)
  enddo
  !
  call gdf_nitems(name,nblock,dims)  ! "Rows" at once
  nblock = min(nblock,rows)
  mblock = (head%gil%dim(2)+nblock-1)/nblock   ! Number of blocks
  nblock = (head%gil%dim(2)+mblock-1)/mblock   ! Uniform block size
  !
  space_nitems = nblock
end function space_nitems

