subroutine dofft (np,nv,visi,jx,jy,jo   &
     &    ,nc,nx,ny,map,mapx,mapy,sup,cell,taper,we  &
     &    ,ubias,vbias,ubuff,vbuff,ctype)
  use gildas_def
  use gkernel_interfaces
  use clean_default
  !$ use omp_lib
  !----------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER  --   Support for UV_MAP and UV_RESTORE
  !
  !   Compute FFT of image by gridding UV data
  !   Select basic routine according to OMP_MAP%GRID
  !!
  !----------------------------------------------------------------------
  integer, intent(in) :: nv                   !! number of values
  integer, intent(in) :: np                   !! Number of "visibilities", normally 7+3*nc
  real, intent(in) :: visi(np,nv)             !! values
  integer, intent(in) :: nc                   !! number of channels
  integer, intent(in) :: jx                   !! X coord location in VISI
  integer, intent(in) :: jy                   !! Y coord location in VISI
  integer, intent(in) :: jo                   !! first channel to map
  integer, intent(in) :: nx                   !! X map size
  integer, intent(in) :: ny                   !! Y map size
  complex, intent(out) :: map(nc+1,nx,ny)     !! gridded visibilities
  real, intent(in) :: mapx(nx)                !! X Coordinates of grid
  real, intent(in) :: mapy(ny)                !! Y Coordinates of grid
  real, intent(in) :: sup(2)                  !! Support of convolving function in Meters
  real, intent(in) :: cell(2)                 !! cell size in Meters
  real, intent(in) :: taper(4)                !! 1/e taper in Meters + Angle in Radians
  real, intent(in) :: we(nv)                  !! Weight array
  real, intent(in) :: ubias                   !! U gridding offset
  real, intent(in) :: vbias                   !! V gridding offset
  real, intent(in) :: ubuff(4096)             !! U gridding buffer
  real, intent(in) :: vbuff(4096)             !! V gridding buffer
  integer, intent(in) :: ctype                !! type of gridding
  !
  integer, external :: ompget_grid_code
  !
  ! Local ---
  integer :: ipara
  real, allocatable :: vv(:)                  ! V Values
  !
  ! Code ----
  call imager_tree('DOFFT '//char(ctype+ichar('0')),.false.)
  !
  ! Initialize
  map = 0.0
  ipara = ompget_grid_code()  
  !
  if (ctype.eq.1) then  ! Simple nearest cell
    call dofft_fast (np,nv,visi,jx,jy,jo,   &
     &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we)
  else                  ! Gridding with extended support
    if (ipara.eq.0) then
      !
      ! This is the Default algorithm - Others are for test only.
      !
      ! The OMP version would work for several channels, but the 
      ! required image storage may become quite large. One could
      ! think of adjusting the number of Threads to the Problem size
      !   On the other hand, the number of visibilities is small,
      ! so sequential programming is enough
      if (nc.ne.1) then
        call dofft_quick (np,nv,visi,jx,jy,jo,   &
     &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,   &
     &      ubias,vbias,ubuff,vbuff)
      else
        ! Continuum images are "small", but number of visibilities
        ! can be large in this case, so OMP is useful
        call dofft_quick_omp (np,nv,visi,jx,jy,jo,   &
     &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,   &
     &      ubias,vbias,ubuff,vbuff,ipara)     
      endif
    else if (ipara.gt.4) then
      !$ Print *,'OMP in parallel ',omp_in_parallel()
      ! This could be the Default algorithm for small number
      ! of channels -- under test.
      Print *,'CASE 42 DOFFT_QUICK_OMP'
      call dofft_quick_omp (np,nv,visi,jx,jy,jo,   &
     &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,   &
     &      ubias,vbias,ubuff,vbuff,ipara) 
    else
      ! Setup VV as V Values
      allocate(vv(nv))
      vv = visi(2,1:nv)
      !
      select case(ipara)
      case(-1)
        call dofft_parallel_v_pseudo (np,nv,visi,jx,jy,jo,   &
       &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv,   &
       &      ubias,vbias,ubuff,vbuff)
      case(-2)
        call dofft_parallel_v_true (np,nv,visi,jx,jy,jo,   &
       &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv,   &
       &      ubias,vbias,ubuff,vbuff)
      case(-3)
        call dofft_quick_para (np,nv,visi,jx,jy,jo,   &
       &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv,   &
       &      ubias,vbias,ubuff,vbuff)
      case(-4)
        call dofft_quick_debug (np,nv,visi,jx,jy,jo,   &
       &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv,   &
       &      ubias,vbias,ubuff,vbuff)
      case(-11)
        call dofft_parallel_v_pseudo_out (np,nv,visi,jx,jy,jo,   &
       &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv,   &
       &      ubias,vbias,ubuff,vbuff)
      case(-12)
        call dofft_parallel_v_true_out (np,nv,visi,jx,jy,jo,   &
       &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv,   &
       &      ubias,vbias,ubuff,vbuff)
      case(1)
        call dofft_slow (np,nv,visi,jx,jy,jo,   &
       &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv,   &
       &      ubias,vbias,ubuff,vbuff)
      case(2)
        call dofft_parallel_x (np,nv,visi,jx,jy,jo,   &
       &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv,   &
       &      ubias,vbias,ubuff,vbuff)
      case(3)
        call dofft_parallel_y (np,nv,visi,jx,jy,jo,   &
       &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv,   &
       &      ubias,vbias,ubuff,vbuff)
      end select 
    endif
  endif
  call imager_tree('DOFFT '//char(ctype+ichar('0')),.false.)
end subroutine dofft
!
