!
subroutine uv_flag_comm(line,error)
  use gkernel_interfaces
  use imager_interfaces, except_this=>uv_flag_comm
  use clean_def
  use clean_arrays
  use clean_support
  use clean_types
  use gbl_message
  !----------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Support routine for command  
  !     UV_FLAG [/ANTENNA] [/DATE] [/RESET] [/FILE FileIn [FileOut]]
  !!
  !----------------------------------------------------------------------
  character(len=*), intent(in)  :: line  !! Command line
  logical,          intent(out) :: error !! Logical error flag
  !
  ! Constants
  integer, parameter :: O_RESET=4
  integer, parameter :: O_FILE=3
  integer, parameter :: O_DATE=2
  integer, parameter :: O_ANT=1
  !
  ! Local ---
  type(polygon_t), save :: flagspol      ! User defined polygon
  integer, allocatable :: iant(:)
  integer :: idate, nc, ic, nchan(2), i, narg
  integer(kind=index_length) :: iv
  real :: rflag
  real(8) :: ut1,ut2
  character(len=16) :: argum
  character(len=16) :: chain
  !
  ! Code ----
  ! Parse input line
  if (sic_present(o_file,0)) then
    call uv_flag_file(line,error)
    return
  endif
  !
  if (sic_present(O_ANT,0) ) then  ! /ANTENNA
    if (.not.associated(duv)) then
      call map_message(seve%e,'UV_FLAG','No UV data')
      error = .true.
      return
    endif
    narg = sic_narg(O_ANT)
    if (narg.eq.0) then
      call map_message(seve%e,'UV_FLAG','Missing argument of option /ANTENNA')
      error = .true.
      return
    endif
    allocate(iant(narg))
    do i=1,narg
      call sic_i4(line,O_ANT,i,iant(i),.true.,error)
      if (error) return
    enddo
    nchan = [1,huv%gil%nchan]
    rflag = -1
    if (sic_present(O_RESET,0)) rflag = 1
    call sub_doflag (duv,huv%gil%dim(1),huv%gil%nvisi,0, &
       &    iant, nchan, rflag) !! , ut1, ut2)
  else if (sic_present(O_DATE,0) ) then  ! /DATE
    allocate(iant(1))
    iant = 0
    call sub_get_datetime_range(line,ut1,ut2,error)
    if (error) return
    nchan = [1,huv%gil%nchan]
    rflag = -1
    if (sic_present(O_RESET,0)) rflag = 1
    call sub_doflag (duv,huv%gil%dim(1),huv%gil%nvisi,0,   &
       &    iant, nchan, rflag, ut1, ut2)
    if (.FALSE.) then
      flagspol%ngon = 0
      call sic_ke(line,O_DATE,1,argum,nc,.true.,error)
      call gag_fromdate(argum(1:nc),idate,error)
      if (error) return
      !
      ! Verify if data ready
      chain = 'UV'
      call display_check_uv('UV_FLAG',chain,error)
      if (error) return
      call get_uvflag_date(duvt,huvt%gil%dim(1),huvt%gil%dim(2),idate)
    endif
  else if (sic_present(O_RESET,0)) then  ! /RESET
    ! Reset flag array
    if (.not.allocated(duvt)) then
      ! No Displayed UV data, work directly
      do iv=1,huv%gil%nvisi
        do ic=1,huv%gil%nchan*huv%gil%nstokes
          duv(7+3*ic,iv) = abs( duv(7+3*ic,iv))
        enddo
      enddo
      return
    endif
    call reset_uvflag(duvt,huvt%gil%dim(1),huvt%gil%dim(2))
    flagspol%ngon = 0
  else     ! Plot data
    chain = 'UV'   !! !dtype//' '//trim(argu1)//' '//trim(argu2) First Last
    call display_uv (chain,line,error)
    if (error) return
    !
    ! Ideally, plot the previous Polygon if any
    if (flagspol%ngon.ge.2) call greg_poly_plot(flagspol,error)
    ! Make user to define a polygon from cursor
    !! call greg_poly_cursor('UV_FLAG',flagspol,error)        !! Does not set the boundaries
    !! call greg_poly_loadsub('UV_FLAG',flagspol,0,' ',error) !! That one is private
    call greg_poly_load('UV_FLAG',.false.,' ',flagspol,error) ! Public entry
    if (error) return
    ! Get flag array
    call get_uvflag(flagspol,duvt,huvt%gil%dim(1),huvt%gil%dim(2))
    ! Apply flag array to buffer
    call apply_uvflag(duvt,huvt%gil%dim(1),huvt%gil%dim(2)-3,duv)
  endif
  do_weig = .true.
  optimize(code_save_uv)%lastnc = -1 !  means UV data.
end subroutine uv_flag_comm
!
subroutine get_uvflag_ant(uvs,nv,nd,iant)
  use gildas_def
  !----------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- UV_FIT support routine  
  !   Set uvflag array from antenna number
  !!
  !----------------------------------------------------------------------
  integer(kind=index_length), intent(in) :: nv,nd !! Size of UV data
  real, intent(inout) :: uvs(nv,nd)               !! UV data
  integer, intent(in) :: iant                     !! antenna number
  !
  ! Local variables
  integer :: nf,i
  !
  nf = nd-2
  do i=1,nv
    if (uvs(i,6).eq.iant .or. uvs(i,7).eq.iant) then
      uvs(i,nf) = 0.0
    endif
  enddo
  !
end subroutine get_uvflag_ant
!
subroutine get_uvflag_date(uvs,nv,nd,idate)
  use gildas_def
  !----------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Set uvflag array from (gildas) Date number
  !----------------------------------------------------------------------
  integer(kind=index_length), intent(in) :: nv,nd  !! Size of UV data
  real, intent(inout) :: uvs(nv,nd)   !! UV Data
  integer, intent(in) :: idate        !! GILDAS Date
  !
  ! Local variables
  integer :: nf,i
  !
  nf = nd-2
  do i=1,nv
    if (uvs(i,4).eq.idate) then
      uvs(i,nf) = 0.0
    endif
  enddo
  !
end subroutine get_uvflag_date
!
subroutine get_uvflag(spol,uvs,nv,nd)
  use gildas_def
  use clean_support
  use gkernel_interfaces, only : gr4_inout
  !----------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Get uvflag array from polygon (0 => Flag, 1 => Keep)
  !!
  !----------------------------------------------------------------------
  type(polygon_t), intent(in) :: spol              !! User defined region polygon
  integer(kind=index_length), intent(in) :: nv,nd  !! Size of UV data
  real, intent(inout) :: uvs(nv,nd)                !! UV data
  !
  ! Local ---
  integer :: ne,nf, nv4
  !
  ! Code ----
  ne = nd-1
  nf = nd-2
  nv4 = nv
  !
  ! Oh gosh, all that logic assumes the plotted stuff is in
  ! ne, nd, nf ...
  call gr4_inout(spol,uvs(:,ne),uvs(:,nd),uvs(:,nf),nv4,.true.)
  !
end subroutine get_uvflag
!
subroutine reset_uvflag(uvs,nv,nd)
  use gildas_def
  !----------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Reset uvflag array to 1
  !!
  !----------------------------------------------------------------------
  integer(kind=index_length), intent(in) :: nv,nd  !! Size of UV data
  real, intent(inout) :: uvs(nv,nd)                !! UV data set
  !
  ! Local ---
  integer :: nf,i
  !
  ! Code ----
  nf = nd-2
  do i=1,nv
    uvs(i,nf) = 1.0
  enddo
end subroutine reset_uvflag
!
subroutine apply_uvflag(uvs,nv,nd,uv)
  use gildas_def
  !----------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Apply uvflag array by making negative the weight of the flagged data
  !!
  !----------------------------------------------------------------------
  integer(kind=index_length), intent(in) :: nv,nd  !! Size of UV data
  real, intent(inout) :: uvs(nv,nd+3)   !! UV data set with Flags
  real, intent(inout) :: uv(nd,nv)      !! Transposed version
  !
  ! Local ---
  real :: factor
  integer :: i,j
  !
  ! Code ----
  ! Loop on visibilities
  do i=1,nv
    ! Apply uvflag array
    factor = 2*uvs(i,nd+1)-1    ! 1 or -1 depending on selected option
    do j=10,nd,3
      uvs(i,j) = abs(uvs(i,j))*factor
    enddo
  enddo
  ! Transpose uvs completely because uv and uvs may be ordered differently...
  do i=1,nv
    uv(1:nd,i) = uvs(i,1:nd)
  enddo
end subroutine apply_uvflag
!
subroutine uv_flag_file(line,error)
  use gildas_def
  use gkernel_interfaces
  use image_def
  use gbl_message
  use imager_interfaces, only : space_nitems, map_message, sub_doflag, basant
  !---------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Support for command  
  !   UV_FLAG /File FileIn [FileOut] [/DATE] [/ANTENNA] [/RESET] 
  !!
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: line  !! Command line
  logical, intent(inout) :: error       !! Error flag
  !
  ! Constants
  character(len=*), parameter :: rname='UV_FLAG'
  real(8), parameter :: pi=3.14159265358979323846d0
  integer, parameter :: O_RESET=4
  integer, parameter :: O_FILE=3
  integer, parameter :: O_DATE=2
  integer, parameter :: O_ANT=1
  !
  ! Local ---
  integer(kind=index_length) :: nvisi, ib
  integer :: nblock, mvisi
  type(gildas) :: hiuv, houv
  character(len=80) :: uvdata, baseline, mess
  integer :: n, nc(2), i, ibase, ier, narg
  integer, allocatable :: iant(:)
  real(8) :: ut1, ut2
  real(4) :: riant, rjant, rflag
  logical :: new
  !
  ! Code ----
  call sic_ch(line,o_file,1,uvdata,n,.true.,error)
  if (error) return
  !
  if (sic_present(o_date,0)) then
    call sub_get_datetime_range(line,ut1,ut2,error)
    if (error) return
  else
    ut1 = -huge(1.d0)
    ut2 = huge(1.d0)
  endif
  !
  ! No /BASELINE option anymore...
  baseline = "ALL"
  if (baseline.eq."ALL") then
    ibase = 0
  else
    read(baseline,*,iostat=ier) riant,rjant
    if (ier.ne.0) then
      error = .true.
      return
    endif
    ibase = basant(riant,rjant)
  endif
  !
  ! /RESET
  rflag = -1
  if (sic_present(o_reset,0)) rflag = 1
  !
  ! /ANTENNA  (only one at a time)
  if (sic_present(O_ANT,0)) then
    narg = sic_narg(O_ANT)
    if (narg.eq.0) then
      call map_message(seve%e,'UV_FLAG','Missing argument of option /ANTENNA')
      error = .true.
      return
    endif
    allocate(iant(narg))
    do i=1,narg
      call sic_i4(line,O_ANT,i,iant(i),.true.,error)
      if (error) return
    enddo
  else
    allocate(iant(1))
    iant = 0
  endif
  !
  ! Input file
  n = len_trim(uvdata)
  call gildas_null(hiuv, type = 'UVT')
  call gildas_null(houv, type = 'UVT')
  call sic_parse_file(uvdata,' ','.uvt',hiuv%file)  !
  ! Open in Read/Write mode if no Output file 
  new = sic_present(o_file,2)
  if (.not.new) hiuv%loca%read = .false. ! Write in place, open in RW
  call gdf_read_header(hiuv,error)
  if (error) return
  !
  call gdf_copy_header(hiuv,houv,error)
  !
  nc = 0 ! Channel range, whole... no /RANGE option here
  ier = gdf_range(nc,hiuv%gil%nchan)
  !
  ! Set the Blocking Factor
  nblock = space_nitems('SPACE_IMAGER',hiuv,1)
  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
  !
  ! Output file if present
  if (new) then
    call sic_ch(line,o_file,2,uvdata,n,.true.,error)
    if (error) return
    call sic_parse_file(uvdata,' ','.uvt',houv%file)
    call gdf_create_image(houv,error)
    if (error) 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 sub_doflag (hiuv%r2d,hiuv%gil%dim(1),nvisi,ibase,   &
       &    iant, nc, rflag, ut1, ut2)
    !
    if (new) then
      houv%blc = hiuv%blc
      houv%trc = hiuv%trc
      call gdf_write_data (houv,hiuv%r2d,error)
    else
      call gdf_write_data (hiuv,hiuv%r2d,error)
    endif
    if (error) return
  enddo
  !
  deallocate(hiuv%r2d)  
  call gdf_close_image(hiuv,error)
  if (new) call gdf_close_image(houv,error)
  if (error) return
  !
  if (new) then
    call map_message(seve%i,rname,'Created '//trim(houv%file))
  else
    call map_message(seve%i,rname,'Updated '//trim(hiuv%file))
  endif
  !
end subroutine uv_flag_file
!
subroutine sub_doflag (out,nx,nv,ibase, iant, nc, rflag, ut_start, ut_end)
  use gildas_def
  use imager_interfaces, only : basant
  !---------------------------------------------------------------------
  ! @ private-mandatory
  !*
  ! IMAGER -- Support routine for UV_FLAG
  !
  ! Conditionally change sign of weights according to RFLAG
  !!
  !---------------------------------------------------------------------
  integer(kind=index_length) :: nx    !! Size of a visibility
  integer(kind=index_length) :: nv    !! Number of visibilities
  real :: out(nx,nv)                  !! Visibilities
  integer :: ibase                    !! Baseline number (0 = any)
  integer :: iant(:)                  !! Antenna number  (0 = any)
  integer :: nc(2)                    !! First and Last channel (0,0 = all)
  real :: rflag                       !! Flag (<0) or Unflag (>0)
  real(8), optional :: ut_start       !! Start time
  real(8), optional :: ut_end         !! End time
  !
  ! Local ---
  integer :: i,j, i1, i2, ib
  real(8) :: t, ut1, ut2
  !------------------------------------------------------------------------
  ! Code ----
  !
  if (present(ut_start).or.present(ut_end)) then
    if (present(ut_start)) then
      ut1 = ut_start
    else
      ut1 = -huge(1.d0)
    endif
    if (present(ut_end)) then
      ut2 = ut_end
    else
      ut2 = huge(1.d0)
    endif
    !
    if (iant(1).ne.0) then
      ! Antenna based
      do j=1,nv
        t = out(4,j)+out(5,j)/86400d0
        i1 = nint(out(6,j))
        i2 = nint(out(7,j))
        if (t.gt.ut1 .and. t.lt.ut2 .and.   &
         & (is_among(iant,i1) .or. is_among(iant,i2)) ) then
          do i = 3*nc(1), 3*nc(2), 3
            out(i+7,j) = sign(out(i+7,j),rflag)
          enddo
        endif
      enddo
    else if (ibase.ne.0) then 
      ! Baseline based
      do j=1,nv
        t = out(4,j)+out(5,j)/86400d0
        ib = basant(out(6,j),out(7,j))
        if (t.gt.ut1 .and. t.lt.ut2 .and.   &
         &      (ib.eq.ibase)) then
          do i = 3*nc(1), 3*nc(2), 3
            out(i+7,j) = sign(out(i+7,j),rflag)
          enddo
        endif
      enddo
    else
      ! Everything
      do j=1,nv
        t = out(4,j)+out(5,j)/86400d0
        if (t.gt.ut1 .and. t.lt.ut2) then
          do i = 3*nc(1), 3*nc(2), 3
            out(i+7,j) = sign(out(i+7,j),rflag)
          enddo
        endif
      enddo
    endif
    !
  else
    !
    !No time range
    if (iant(1).ne.0) then
      ! Antenna based
      do j=1,nv
        i1 = nint(out(6,j))
        i2 = nint(out(7,j))
        if (is_among(iant,i1) .or. is_among(iant,i2)) then
          do i = 3*nc(1), 3*nc(2), 3
            out(i+7,j) = sign(out(i+7,j),rflag)
          enddo
        endif
      enddo
    else if (ibase.ne.0) then 
      ! Baseline based
      do j=1,nv
        ib = basant(out(6,j),out(7,j))
        if (ib.eq.ibase) then
          do i = 3*nc(1), 3*nc(2), 3
            out(i+7,j) = sign(out(i+7,j),rflag)
          enddo
        endif
      enddo
    endif
  endif
  !
contains
  logical function is_among(array,value)
    integer, intent(in) :: array(:)
    integer, intent(in) :: value
    !
    integer :: i
    !
    is_among = .true.
    do i=1,size(array)
      if (array(i).eq.value) return
    enddo
    is_among = .false.
  end function is_among
end subroutine sub_doflag
!
integer function basant(ri,rj)
  ! @ private
  real, intent(in) :: ri,rj
  !
  if (ri.gt.rj) then
    basant = 256*nint(rj)+nint(ri)
  else
    basant = 256*nint(ri)+nint(rj)
  endif
end function basant
!
subroutine sub_get_datetime_range(line,ut1,ut2,error)
  use gbl_message
  use gkernel_interfaces
  use imager_interfaces, only : map_message
  ! @ private-mandatory
  !*
  ! IMAGER -- Support for command UV_FLAG 
  !
  ! Get date/time range
  !!
  character(len=*), intent(in) :: line    !! Command line
  real(8), intent(inout) :: ut1           !! Start date/time
  real(8), intent(inout) :: ut2           !! End date/time
  logical, intent(inout) :: error         !! Error flag
  !
  ! Constants
  character(len=*), parameter :: rname='UV_FLAG'
  real(8), parameter :: pi=acos(-1d0) 
  integer, parameter :: O_RESET=4
  integer, parameter :: O_FILE=3
  integer, parameter :: O_DATE=2
  integer, parameter :: O_ANT=1
  !
  ! Local ---
  character(len=80) :: ut_start, ut_end, date_start, date_end
  integer :: i,larg
  real(8) :: tt
  !
  ! Code ----
  call sic_ch(line,o_date,1,date_start,larg,.true.,error)
  call gag_fromdate(date_start(1:larg),i,error)
  if (error) then
    call map_message(seve%e,rname,'Error converting date '//date_start(1:larg))
    return
  endif
  ut1 = i
  !
  select case (sic_narg(o_date))
  case(1)
    ut2 = ut1 + 1.d0
  case (2)
    ! Start_Date End_Date
    call sic_ch(line,o_date,2,date_end,larg,.true.,error)
    call gag_fromdate(date_end(1:larg),i,error)
    if (error) then
      call map_message(seve%e,rname,'Error converting date '//date_start(1:larg))
      return
    endif
    ut2 = ut1+1.d0
    !
  case(3) 
    ! Date Start_Time End_Time
    call sic_ch(line,o_date,2,ut_start,larg,.true.,error)
    call sic_decode(ut_start,tt,24,error)    ! TT in RADIANS
    if (error) then
      call map_message(seve%e,rname,'Error converting time '//date_start(1:larg))
      return
    endif
    ut2 = ut1
    ut1 = ut1+tt/2.d0/pi
    !
    call sic_ch(line,o_date,3,ut_end,larg,.true.,error)
    call sic_decode(ut_end,tt,24,error)    ! TT in RADIANS
    if (error) then
      call map_message(seve%e,rname,'Error converting time '//ut_end(1:larg))
      return
    endif
    ut2 = ut2+tt/2.d0/pi
  case(4)
    ! Start_Date Time End_Date Time
    call sic_ch(line,o_date,2,ut_start,larg,.true.,error)
    call sic_decode(ut_start,tt,24,error)    ! TT in RADIANS
    if (error) then
      call map_message(seve%e,rname,'Error converting time '//date_start(1:larg))
      return
    endif
    ut1 = ut1+tt/2.d0/pi
    !
    call sic_ch(line,o_date,3,date_end,larg,.true.,error)
    call gag_fromdate(date_end(1:larg),i,error)
    if (error) then
      call map_message(seve%e,rname,'Error converting date '//date_start(1:larg))
      return
    endif
    ut2 = i
    !
    call sic_ch(line,o_date,4,ut_end,larg,.true.,error)
    call sic_decode(ut_end,tt,24,error)    ! TT in RADIANS
    if (error) then
      call map_message(seve%e,rname,'Error converting time '//ut_end(1:larg))
      return
    endif
    ut2 = ut2+tt/2.d0/pi
  case default
    call map_message(seve%e,rname,'Invalid syntax')
    error = .true.
    return
  end select
end subroutine sub_get_datetime_range

