!
subroutine uv_baseline_comm(line,error)
  use gkernel_interfaces
  use gbl_message
  use clean_arrays
  use uvsplit_mod
  use imager_interfaces, only : uv_filter_base, opt_filter_base, &
    map_message
  !---------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Support routine for command UV_BASELINE
  !
  !   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'
  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
  ! Argument ZERDEG is set to the specified Degree
  call uv_filter_base ('UV_BASELINE',line,error,rname,degree)
  ! 
  if (sic_present(opt_file,0)) return
  ! Reset Channel Flags
  huv_current%img%flags = 1
end subroutine uv_baseline_comm
!
subroutine uv_filter_comm(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 command UV_FILTER
  !
  !   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'
  !
  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    ! /ZERO   Nullify data
  else if (sic_present(opt_reset,0)) then
    zero = -1   ! /RESET  Unflag
  else
    zero = 1    ! Flag data
  endif
  !
  call opt_filter_base(line,rname,error)
  if (error) return
  ! ZERDEG is set to ZERO, which is -1,0,1 according to options.
  call uv_filter_base ('UV_FILTER',line,error,rname,zero)
end subroutine uv_filter_comm
!
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 command UV_SPLIT 
  !
  !   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 ('UV_SPLIT',line,error,rname,degree)
end subroutine uv_split_comm
!
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
  !
  ! Constants
  real(kind=8), parameter :: pi=3.14159265358979323846d0
  real(kind=8), parameter :: f_to_k = 2.d0*pi/299792458.d-6
  !
  ! Local ---
  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
  !
  ! Code ----
  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 if (rname.eq.'UV_FILTER') then
      ou_file = trim(in_file)//'-noline'
    else
      ou_file = trim(in_file)//'-nocont'
    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_current,htmp,err)
          call gdf_copy_header(hfuv,huv_current,err)
          call map_parameters(rname,map,huv_current,freq,uvmax,uvmin,error)
          call gdf_copy_header(htmp,huv_current,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) + huvf%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_current%loca%size.eq.0) then
      call map_message(seve%e,rname,'No UV data loaded')
      error = .true.
      return
    endif
    if (huv_current%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_current,hiuv,error)
    !
    use_file = .false.
  endif
end subroutine opt_filter_base
!
subroutine uv_filter_base(comm,line,error,rname,zerdeg)
  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, out_range
  !---------------------------------------------------------------------
  ! @ 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(in) :: comm     !! Command name
  character(len=*), intent(inout) :: line  !! Command line
  logical, intent(out) :: error            !! Error flag
  character(len=*), intent(in) :: rname    !! Caller name
  integer, intent(in) :: zerdeg            !! Flag or Degree
  !
  ! Constants
  real(kind=8), parameter :: pi=3.14159265358979323846d0
  real(kind=8), parameter :: f_to_k = 2.d0*pi/299792458.d-6
  !
  ! Local ---
  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(:)
  real(kind=8), pointer :: freqs(:)
  integer :: na, nstyle
  integer, parameter :: mstyle=3
  character(len=12) :: vstyle(mstyle), astyle, argu
  data vstyle/'CHANNEL','FREQUENCY','VELOCITY'/
  !
  ! Code ----
  select case(comm)
  case ('UV_BASELINE')
    code_routine = code_baseline
  case ('UV_FILTER')
    code_routine = code_filter
  case ('UV_SPLIT')
    code_routine = code_split
  case default
    call map_message(seve%e,comm,'Unsupported command at this stage')
    error = .true.
    return
  end select
  !
  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,zerdeg,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
    !
    found = .false.
    if (narg.eq.1) then
      call sic_ke(line,opt_freq,1,listname,na,.true.,error)
      call sic_descriptor(listname,desc,found)
      if (found) then
        call adtoad(desc%addr,cptr,1)
        nf = desc%dims(1)
        call c_f_pointer(cptr,freqs,desc%dims(1:1))
      endif
    endif
    !
    if (.not.found) then
      allocate(freqs(narg),stat=ier)
      do i=1,narg
        call sic_r8(line,opt_freq,i,freqs(i),.true.,error)
        if (error) return
      enddo
      nf = narg
    endif
    !
    ! call freq_to_channel(hiuv,nf,freqs,k,channels)
    !
    do i=1,nf
      freq = freqs(i)
      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,zerdeg,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,zerdeg,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,zerdeg,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 (zerdeg.eq.-1) then  
        ! Reset everything
        if (allocated(huv_current%img%flags)) huv_current%img%flags = 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,zerdeg,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_routine(mf,channels,zero,error)
  use gildas_def
  use uvsplit_mod
  use imager_interfaces, only : t_baseline, t_filter, t_split
  !---------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Support routine for UV_BASELINE, UV_FILTER, UV_SPLIT
  !
  ! Dispatch according to "code_routine" (in uvsplit_mode)
  !!
  !---------------------------------------------------------------------
  integer, intent(in) :: mf           !! Number of channels
  integer, intent(in) :: channels(mf) !! Channels
  integer, intent(in) :: zero         !! Zero or not
  logical, intent(inout) :: error     !! Error flag
  !
  if (code_routine.eq.code_baseline) then
    call t_baseline(mf,channels,zero,error)
  else if (code_routine.eq.code_split) then
    call t_split(mf,channels,zero,error)
  else if (code_routine.eq.code_filter) then
    call t_filter(mf,channels,zero,error)
  else
    Print *,'invalid code in T_ROUTINE ',code_routine
    error = .true.
  endif
end subroutine t_routine
!
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      !! Error flag
  !
  character(len=*), parameter :: rname='UV_FILTER'
  !
  ! Local ---
  integer :: nf, nv, nc, i, ier, nfi, ndrop
  integer, allocatable :: filtre(:)
  integer :: nvisi, mvisi, ib
  character(len=120) :: mess
  !
  ! Code ---
  nc = hiuv%gil%nchan
  ndrop = nint(edge_drop*nc)
  nfi = mf + 2*ndrop
  allocate(filtre(nfi),stat=ier)
  if (ier.ne.0) then
    call map_message(seve%e,rname,'Memory allocation error')
    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,ndrop
      nf = nf+1
      filtre(nf) = i
    enddo
    do i=nc-ndrop+1,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" 
    if (allocated(huv_current%img%flags)) then 
      !
      ! Just remember the status of each channel
      do i=1,nf
        if ((filtre(i).gt.0).and.(filtre(i).le.huv_current%gil%nchan)) &
          & huv_current%img%flags(filtre(i)) = -zero  ! -1,0,1 
      enddo
    else
      call map_message(seve%w,rname,'No Channel Mask associated to UV data')
      !
      ! 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,visi,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)  !! List of channels
  real, intent(inout) :: visi(:,:)   !! Visibilities
  !
  ! Local ---
  integer :: iv,i
  !
  ! Code ----
  select case (zero)
  case (1)
    !$OMP PARALLEL DEFAULT(none)  &
    !$OMP & SHARED(visi,nv,nf,filtre) &
    !$OMP & PRIVATE(iv,i)
    !$OMP DO
    do iv=1,nv
      do i=1,nf
        visi(7+3*filtre(i),iv) = -abs(visi(7+3*filtre(i),iv))
      enddo
    enddo  
    !$OMP END DO
    !$OMP END PARALLEL
  case (0)
    !$OMP PARALLEL DEFAULT(none) &
    !$OMP & SHARED(visi,nv,nf,filtre) &
    !$OMP & PRIVATE(iv,i)
    !$OMP DO
    do iv=1,nv
      do i=1,nf
        visi(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(visi,nv,nf,filtre) &
    !$OMP & PRIVATE(iv,i)
    !$OMP DO
    do iv=1,nv
      do i=1,nf
        visi(7+3*filtre(i),iv) =  abs(visi(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      !! Error flag
  !
  character(len=*), parameter :: rname='UV_BASELINE'
  !
  ! Local ---
  integer :: nf, nv, nc, i, j, ier
  integer, allocatable :: filtre(:)
  integer :: nvisi, mvisi, ib, fc, lc
  character(len=120) :: mess
  !
  ! Code ----
  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,visi,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) :: visi(:,:)    !! Visibilities
  logical, intent(out) :: error       !! Error flag
  !
  ! Local ---
  real, allocatable :: wreal(:), wimag(:), wx(:), wxx(:), wxy(:)
  integer :: iv,i,ier, enf
  real :: mreal, mimag, sx, sy, sxx, sxy, delta, a, b, w
  !
  ! Code ----
  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,visi,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) = visi(5+3*filtre(i),iv)
      wimag(i) = visi(6+3*filtre(i),iv)
      ! Reset the Weights to > 0 (un-flagged) if any channel is unflagged
      if (visi(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
        visi(5+3*i,iv) = visi(5+3*i,iv)-mreal
        visi(6+3*i,iv) = visi(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
        visi(5+3*i,iv) = visi(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
        visi(6+3*i,iv) = visi(6+3*i,iv)-(a+b*i)
      enddo
      !
    endif
    !
    ! Remove the filter
    if (w.gt.0) then
      do i=1,nb
        visi(7+3*filter(i),iv) = abs(visi(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      !! Error flag
  !
  character(len=*), parameter :: rname='UV_SPLIT'
  !
  ! Local ---
  integer :: nf, nv, nc, i, j, ier
  integer, allocatable :: filtre(:)
  integer :: nvisi, mvisi, ib, fc, lc, mc
  character(len=120) :: mess
  !
  ! Code ----
  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,visi,mc,cuv,degree,filtre,error)
  use uvsplit_mod
  use imager_interfaces, only : compress_uv
  !---------------------------------------------------------------------
  ! @ 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) :: visi(:,:)  !! Input line + continuum, output line
  real, intent(out) :: cuv(:,:)     !! Output continuum
  logical, intent(out) :: error     !! Error flag
  !
  ! Local ---
  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(:,:)
  !
  ! Code ----
  lt = ubound(visi,1)   ! Size of line visibility
  kt = ubound(cuv,1)    ! Size of continuum visibility
  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) = visi(5+3*filtre(i),iv)
      wimag(i) = visi(6+3*filtre(i),iv)
      xuv(5+3*filtre(i):7+3*filtre(i),1) = visi(5+3*filtre(i):7+3*filtre(i),iv)
    enddo
    if (trail) xuv(lc:,1) = visi(lc:,iv) 
    if (ncompr.eq.1) then
      cuv(1:7,iv) = visi(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) = visi(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
        visi(5+3*i,iv) = visi(5+3*i,iv)-mreal
        visi(6+3*i,iv) = visi(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
        visi(5+3*i,iv) = visi(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
        visi(6+3*i,iv) = visi(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 -- Utility routine
  !
  !   Returns the number of blocks in the last dimension
  !   according to the NAME logical name
  !!
  !--------------------------------------------------------------------- 
  character(len=*), intent(in) :: name  !! Caller name
  integer ::space_nitems           !! intent(out) function value
  type(gildas), intent(in) :: head !! Input Gildas header
  integer, intent(in) :: last      !! Last blocked dimension
  !
  ! Local ---
  integer :: nblock, mblock, i 
  integer(kind=8) :: dims     ! Size of a "row"
  integer(kind=8) :: rows     ! Number of "rows"
  !
  ! Code ----
  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

