subroutine uv_squeeze_clean(nc,ccin,ccou, mic, first, last)
  use image_def
  !$ use omp_lib
  !-----------------------------------------------------------------
  ! @ private-mandatory
  !*
  ! IMAGER --  Support for UV_RESTORE
  !
  !   Compact the component list by summing up all values at the
  !   same position in a range of channels.
  !   The output list has a transposed order
  !!
  !-----------------------------------------------------------------
  integer, intent(in) :: nc           !! Number of channels
  real, intent(in) :: ccin(:,:,:)     !! Initial Clean Component List
  real, intent(out) :: ccou(:,:,:)    !! Resulting list
  integer, intent(inout) :: mic(:)    !! Number of Clean component per channel
  integer, intent(in) :: first        !! First channel
  integer, intent(in) :: last         !! Last channel
  !
  ! Local ---
  integer :: ii,jj,ic,jc,kc, scc
  integer :: ki    ! Number of different components per channel
  integer :: nin   ! Number of input channels
  logical :: doit, do_size
  integer :: ithread
  !
  ! Code ----
  ccou = 0
  !
  scc = size(ccin,1)    ! Size of a Clean Component (3 or 4)
  nin = size(ccin,2)    ! That is the number of channels
  do_size = scc.eq.4    ! Check size if needed
  !
  if (nin.eq.1) then
    ki = 0
    do ii=1,mic(1)
      if (ccin(3,1,ii).eq.0) then
        exit
      else
        doit = .true.
        do jj=1,ki
          if (ccou(1,jj,1).eq.ccin(1,1,ii)) then
            if (ccou(2,jj,1).eq.ccin(2,1,ii)) then
              if (do_size) then
                if (ccou(4,jj,1).eq.ccin(4,1,ii)) then
                  doit = .false.
                  ccou(3,jj,1) = ccou(3,jj,1) + ccin(3,1,ii)
                  exit
                endif
              else
                doit = .false.
                ccou(3,jj,1) = ccou(3,jj,1) + ccin(3,1,ii)
                exit
              endif
            endif
          endif
        enddo
        if (doit) then
          ki = ki+1
          ccou(1:scc,ki,1) = ccin(1:scc,1,ii)
        endif
      endif
    enddo
    mic(1) = ki
    !
    ! Then duplicate 
    do ic=2,last-first+1
      ccou(:,:,ic) = ccou(:,:,1)
    enddo
  else
    !
    !$OMP PARALLEL DEFAULT(none) SHARED(ccin,ccou) &
    !$OMP    & SHARED(first,last, mic, nin, do_size) &
    !$OMP    & PRIVATE(ic,jc,kc,ki, ii, doit, ithread)   
    !
    ithread = 1
    !$ ithread = omp_get_thread_num()+1
    !$OMP DO
    do ic=first,last
      jc = ic-first+1
      ki = 0
      do ii=1,mic(jc)
        kc = min(ic,nin)
        if (ccin(3,kc,ii).eq.0) then
          exit
        else
          doit = .true.
          do jj=1,ki
            if (ccou(1,jj,jc).eq.ccin(1,kc,ii)) then
              if (ccou(2,jj,jc).eq.ccin(2,kc,ii)) then
                if (do_size) then
                  if (ccou(4,jj,1).eq.ccin(4,1,ii)) then
                    doit = .false.
                    ccou(3,jj,jc) = ccou(3,jj,jc) + ccin(3,kc,ii)
                    exit
                  endif
                else
                  doit = .false.
                  ccou(3,jj,jc) = ccou(3,jj,jc) + ccin(3,kc,ii)
                  exit
                endif
              endif
            endif
          enddo
          if (doit) then
            ki = ki+1
            ccou(:,ki,jc) = ccin(:,ic,ii)
          endif
        endif
      enddo
      mic(jc) = ki
    enddo
    !$OMP END DO
    !$OMP END PARALLEL
  endif
end subroutine uv_squeeze_clean
!
subroutine uv_extract_clean(visi,ouv,nv,nc,first,last)
  !-----------------------------------------------------------------
  ! @ private-mandatory
  !*
  ! IMAGER  --  Support for UV_MAP,  UV_RESTORE and others  
  !     Extract a subset of visibilities
  !!
  !-----------------------------------------------------------------
  integer, intent(in) :: nc           !! Number of channels
  real, intent(in) :: visi(:,:)       !! Input visbilities
  real, intent(out) :: ouv(:,:)       !! Output visibilities
  integer, intent(in) :: nv           !! Number of visibilities
  integer, intent(in) :: first        !! First channel
  integer, intent(in) :: last         !! Last channel
  !
  ! Local --
  integer :: iv
  !
  ! Code ---
  do iv=1,nv
    ouv(1:7,iv) = visi(1:7,iv)
    ouv(8:,iv) = visi(5+3*first:7+3*last,iv)
  enddo
end subroutine uv_extract_clean
!
subroutine uv_clean_sizes(hcct,ccin, mic, first, last)
  use image_def
  !-----------------------------------------------------------------
  ! @ private-mandatory
  !*
  ! IMAGER  -- Support for UV_RESTORE
  !
  !   Compute the actual number of components by locating the first
  !   null. Note that if storage after that was all zeros, a
  !   dichotomic search could do that faster.
  !!
  !-----------------------------------------------------------------
  type(gildas), intent(in) :: hcct    !! header of CCT data set
  real, intent(in) :: ccin(:,:,:)     !! Clean component table
  integer, intent(out) :: mic(:)      !! Number of iterations per channel
  integer, intent(in) :: first        !! First
  integer, intent(in) :: last         !! and last channel
  !
  ! Local ---
  integer :: nc
  integer :: ni, ki
  integer :: i,ic,jc, mi
  !
  ! Code ----
  nc = hcct%gil%dim(2)  ! Number of channels
  ni = hcct%gil%dim(3)  ! Maximum number of Clean Components
  ! 
  if (nc.eq.1) then
    mi = ni
    do i=1,ni
      if (ccin(3,1,i).eq.0) then
        mi = i-1
        exit
      endif
    enddo
    mic(:) = mi
  else
    !
    mic(:) = ni ! Up to the last one
    do ic=first,last
      jc = ic-first+1
      ki = 0
      do i=1,ni
        if (ccin(3,ic,i).eq.0) then
          mic(jc) = i-1
          exit
        endif
      enddo
    enddo
  endif
end subroutine uv_clean_sizes
!
subroutine do_smodel (nc,visi,nu,nv,a,nx,ny,nf,freq,xinc,yinc,factor,mthread,subtract)
  !$ use omp_lib
  !-----------------------------------------------------------------
  ! @ private-mandatory
  !*
  ! IMAGER  --  Support for UV_RESTORE
  !
  !     Remove model visibilities from UV data set.
  !     Interpolate from a grid of values obtained by FFT before.
  !
  !     This neglects the different angular scales as a function of 
  !   frequency. It should thus be used only on a narrow frequency range.
  !!
  !-----------------------------------------------------------------
  integer, intent(in) :: nc             !! Number of channels
  integer, intent(in) :: nu             !! Visibility size
  integer, intent(in) :: nv             !! Number of visibilities
  integer, intent(in) :: nx             !! X size
  integer, intent(in) :: ny             !! Y size
  integer, intent(in) :: nf             !! Number of frequencies in FFT
  real, intent(inout) :: visi(:,:)      !! Computed visibilities
  real(8), intent(in) :: freq           !! Effective frequency
  real, intent(in)  :: factor           !! Flux factor
  complex, intent(in) ::  a(:,:,:)      !! FFT
  real(8), intent(in) :: xinc,yinc      !! Pixel sizes
  integer, intent(in) :: mthread        !! Thread number (for messages)
  logical, intent(in) :: subtract       !! Compute Diff or Model
  !
  real(8), parameter :: clight=299792458d0
  !
  ! Local ---
  real(8) :: kwx,kwy,stepx,stepy,lambda,xr,yr
  complex(8) :: aplus,amoin,azero,afin
  integer :: i,if,ic,ia,ja,old_if,izero,ithread
  !
  ! Code ----
  lambda = clight/(freq*1d6)
  stepx = 1.d0/(nx*xinc)*lambda
  stepy = 1.d0/(ny*yinc)*lambda
  !
  ! Print *,'NChannel oout ',nc,' Nchan CCT ',nf
  !
  ! Loop on visibility
  !$OMP PARALLEL DEFAULT(none) NUM_THREADS(mthread) private(izero,ithread) &
  !$OMP   SHARED(visi,a, factor,nc,nu,nv,nf,nx,ny,stepx,stepy,subtract) &
  !$OMP   PRIVATE(kwx,ia,kwy,ja,xr,yr,aplus,azero,amoin,afin,if,ic,old_if) 
  !$ ithread = omp_get_thread_num()+1
  izero = 1
  !$OMP DO
  do i = 1, nv
    !if (izero.eq.1) then
    !  Print *,'Thread ',ithread,' iv ',i
    !  izero = 0
    !endif
    kwx =  visi(1,i) / stepx + dble(nx/2 + 1)
    ia = int(kwx)
    if (ia.le.1) cycle
    if (ia.ge.nx) cycle
    kwy =  visi(2,i) / stepy + dble(ny/2 + 1)
    ja = int(kwy)
    if (ja.le.1) cycle
    if (ja.ge.ny) cycle
    !
    xr = kwx - ia
    yr = kwy - ja
    old_if = 0
    afin = 0.  ! To avoid initialization warning
    do ic=1,nc
      if = min(ic,nf)     ! If only Continuum, use it for all Planes.
      if (if.ne.old_if) then
        !
        ! Interpolate (X or Y first, does not matter in this case)
        aplus = ( (a(ia+1,ja+1,if)+a(ia-1,ja+1,if)   &
     &          - 2.d0*a(ia,ja+1,if) )*xr   &
     &          + a(ia+1,ja+1,if)-a(ia-1,ja+1,if) )*xr*0.5d0   &
     &          + a(ia,ja+1,if)
        azero = ( (a(ia+1,ja,if)+a(ia-1,ja,if)   &
     &          - 2.d0*a(ia,ja,if) )*xr   &
     &          + a(ia+1,ja,if)-a(ia-1,ja,if) )*xr*0.5d0   &
     &          + a(ia,ja,if)
        amoin = ( (a(ia+1,ja-1,if)+a(ia-1,ja-1,if)   &
     &          - 2.d0*a(ia,ja-1,if) )*xr   &
     &          + a(ia+1,ja-1,if)-a(ia-1,ja-1,if) )*xr*0.5d0   &
     &          + a(ia,ja-1,if)
        ! Then Y (or X)
        afin = ( (aplus+amoin-2.d0*azero)   &
     &          *yr + aplus-amoin )*yr*0.5d0 + azero
      endif
      old_if = if
      !
      if (subtract) then
        visi(5+3*ic,i) =  visi(5+3*ic,i) - real(afin)*factor
        visi(6+3*ic,i) =  visi(6+3*ic,i) - imag(afin)*factor
      else
        visi(5+3*ic,i) =  real(afin)*factor
        visi(6+3*ic,i) =  imag(afin)*factor
      endif
    enddo
  enddo
  !$OMP ENDDO
  !$OMP END PARALLEL
end subroutine do_smodel
! 
subroutine cube_flag_extrema(huv_call,varname,mcol,hvar)
  use clean_arrays
  use gbl_message
  use imager_interfaces, only : map_message
  !------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Utility routine
  !   Set flagged channels to Zero and re-compute extrema
  !!
  !------------------------------------------------------------
  type(gildas), intent(in) :: huv_call !! Initial UV data
  integer, intent(in) :: mcol(2)  !! First and last channel
  character(len=*), intent(in) :: varname !! Variable name
  type(gildas), intent(inout) :: hvar     !! Data Header 
  !! data itself is in the %r3d pointer)
  !
  ! Local ---
  integer :: ic
  logical :: error
  !
  ! Code ----
  ! 1 channel only means Continuum data
  if (huv_call%gil%nchan.ne.1) then
    if (any(huv_call%img%flags.eq.0)) then
      !!Print *,'MCOL ',mcol,' Nchan ',nchan
      !!Print *,'Nullifying Filtered Channels ',huv_call%img%flags(mcol(1):mcol(2)) 
      call map_message(seve%i,'UV_MAP','Nullifying Filtered Channels ')
      do ic=1,hvar%gil%dim(3)
        if (huv_call%img%flags(ic+mcol(1)-1).eq.0) then
          hvar%r3d(:,:,ic) = 0
        endif
      enddo
    endif
  endif
  !
  ! Compute extrema
  error = .false.
  call cube_minmax(varname,hvar,error)
end subroutine cube_flag_extrema
!
subroutine cct_fft_size(mx,my,nx,ny)
  !*
  ! IMAGER -- Utility routine 
  !   Get best FFT size given the data size
  !!
  integer, intent(in) :: mx,my   !! Data size
  integer, intent(out) :: nx,ny  !! FFT Size
  !
  ! Local ---
  integer :: kx,ky
  real :: rx,ry
  !
  ! Code -- just works with powers of 2
  !
  ! Define the image size
  rx = log(float(mx))/log(2.0)
  kx = nint(rx)
  if (kx.lt.rx) kx = kx+1
  nx = 2**kx
  ry = log(float(my))/log(2.0)
  ky = nint(ry)
  if (ky.lt.ry) ky = ky+1
  ny = 2**ky
  kx = max(nx,ny)
  kx = min(4*kx,4096)
  !
  ! If the image is already fine enough, use it "as is"
  !    even if it is not a power of two...
  nx = max(kx,mx)  ! max(kx,nx) for power of two
  ny = max(kx,my)  ! max(kx,ny) for power of two
end subroutine cct_fft_size
!
