subroutine gdf_uv_size(huvl,nc)
  use image_def
  !
  type(gildas), intent(inout) :: huvl
  integer, intent(in) :: nc(2)
  !
  ! Local ---
  integer :: loff,moff, xoff,yoff, lid
  integer :: nchan, nstok
  !
  ! Code ----
  nchan = nc(2)-nc(1)+1
  huvl%gil%ref(1) = huvl%gil%ref(1)-nc(1)+1
  nstok = max(1,huvl%gil%nstokes)
  huvl%gil%dim(1) = huvl%gil%nlead+huvl%gil%natom*nchan*nstok+huvl%gil%ntrail
  if (huvl%gil%ntrail.eq.0) return
  !
  ! If Mosaic with no Source_ID, add the Source_ID column
  lid  = huvl%gil%column_pointer(code_uvt_id)
  if (lid.ne.0) return
  !
  loff = huvl%gil%column_pointer(code_uvt_loff)
  moff = huvl%gil%column_pointer(code_uvt_moff)
  xoff = huvl%gil%column_pointer(code_uvt_xoff)
  yoff = huvl%gil%column_pointer(code_uvt_yoff)
  if (loff.ne.0) then
    if (moff.eq.0) then
      huvl%gil%column_pointer(code_uvt_moff) = huvl%gil%dim(1)+1
      huvl%gil%column_pointer(code_uvt_id) = huvl%gil%dim(1)+2
      huvl%gil%ntrail = huvl%gil%ntrail+2
    else
      huvl%gil%column_pointer(code_uvt_id) = huvl%gil%dim(1)+1
      huvl%gil%ntrail = huvl%gil%ntrail+1
    endif
  else if (moff.ne.0) then
    huvl%gil%column_pointer(code_uvt_loff) = huvl%gil%dim(1)+1
    huvl%gil%column_pointer(code_uvt_id) = huvl%gil%dim(1)+2
    huvl%gil%ntrail = huvl%gil%ntrail+2
  else if (xoff.ne.0) then
    if (yoff.eq.0) then
      huvl%gil%column_pointer(code_uvt_yoff) = huvl%gil%dim(1)+1
      huvl%gil%column_pointer(code_uvt_id) = huvl%gil%dim(1)+2
      huvl%gil%ntrail = huvl%gil%ntrail+2
    else
      huvl%gil%column_pointer(code_uvt_id) = huvl%gil%dim(1)+1
      huvl%gil%ntrail = huvl%gil%ntrail+1
    endif
  else if (yoff.ne.0) then
    huvl%gil%column_pointer(code_uvt_xoff) = huvl%gil%dim(1)+1
    huvl%gil%column_pointer(code_uvt_id) = huvl%gil%dim(1)+2
    huvl%gil%ntrail = huvl%gil%ntrail+2
  endif
  !  
  huvl%gil%dim(1) = huvl%gil%nlead+huvl%gil%natom*nchan*nstok+huvl%gil%ntrail
end subroutine gdf_uv_size
!
subroutine getset_uvdata(rname,head,datauv,fd,fits_fmt,nc,pcount,error)
  use clean_def
  use clean_arrays
  use clean_types
  use clean_beams
  use clean_default
  use uvfit_data
  use gbl_message
  use gkernel_interfaces
  use imager_interfaces, except_this=>getset_uvdata
  !
  !------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Read UV_DATA or get it from another buffer
  !!
  !------------------------------------------------------------------
  type (gildas), intent(inout) :: head    !! Header of input data
  character(len=*), intent(in) :: rname   !! Caller name
  real(kind=4), intent(in) :: datauv(head%gil%dim(1),head%gil%dim(2)) !! Data used to fill the values
  type(gfits_hdesc_t), intent(in) :: fd   !! FITS descriptor 
  integer, intent(in) :: fits_fmt         !! Input FITS file format
  integer, intent(in) :: nc(2)            !! Channel range
  integer, intent(in) :: pcount           !! Fits PCOUNT
  logical, intent(out) :: error
  !
  ! Constants
  integer, parameter :: o_trail=5
  !
  ! Local ---
  integer :: local_nc(2)
  type(gildas) :: htmp
  integer :: ioff, joff, itel
  integer :: i, ier, nchan, insize_uv
  character(len=80) :: mess
  integer :: ram_need
  logical :: readit
  logical :: ismosaic
  logical :: sorted
  !
  ! Code ----
  if (head%char%type(1:9).ne.'GILDAS_UV') then
    call map_message(seve%e,rname,'Input data is not a UV data set')
    error = .true.
    return
  endif
  readit = rname.eq."READ"
  !
  ! Free the previous zone
  call uv_free_buffers
  save_data(code_save_uv) = .false.
  ! No UV_PREVIEW done, then...
  call sic_delvariable('PREVIEW',.false.,error)
  call reset_fields(themap)
  !
  error = .false.
  !
  call gildas_null (huvi, type= 'UVT')
  call gildas_null (htmp, type= 'UVT')
  call gdf_copy_header(head, htmp, error)
  ! Check appropriate order
  if (head%char%code(1).eq."RANDOM") then
    call map_message(seve%w,rname,'UV data is transposed')
    call gdf_transpose_header (htmp, huvi, '21', error)
  else
    call gdf_copy_header(head, huvi, error)    
  endif
  if (error)  return
  htmp%loca = head%loca
  huvi%loca  = head%loca   ! Why : to get the image slot !...
  !
  call sic_delvariable ('UV',.false.,error)
  call sic_delvariable ('UVS',.false.,error)
  call sic_delvariable ('DCHANFLAG',.false.,error)
  !
  ! Extract desired channels
  nchan = huvi%gil%nchan
  !
  if (readit) then
    local_nc = nc
    ier = gdf_range (local_nc, nchan)
    call gdf_uv_size(huvi,local_nc)
    nchan = local_nc(2)-local_nc(1)+1
    ! 
    ! Ntrail is manipulated by the /NOTRAIL option
    huvi%gil%dim(1) = huvi%gil%dim(1)-huvi%gil%ntrail
    insize_uv = huvi%gil%dim(1)
    if (fits_fmt.eq.1) then
      insize_uv = huvi%gil%nlead+huvi%gil%natom*nchan
    endif
    !
    ! Only for READ command
    if (huvi%gil%ntrail.gt.0) then
      if (sic_present(o_trail,0).or.(.not.read_trail)) then    ! /NOTRAIL option
        do i=1,code_uvt_last
          if (huvi%gil%column_pointer(i).gt.huvi%gil%dim(1)) then
            call map_message(seve%w,rname,'Found column '//uv_column_name(i))
            huvi%gil%column_size(i) = 0
            huvi%gil%column_pointer(i) = 0
          endif
        enddo
        huvi%gil%ntrail = 0
      endif
      ! use them according to user selection
      huvi%gil%dim(1) = huvi%gil%dim(1) + huvi%gil%ntrail
    endif
    insize_uv = insize_uv+huvi%gil%ntrail
    !
    huvi%gil%nchan = nchan
    !
    ram_need = (huvi%gil%dim(1)*huvi%gil%dim(2))/(512*512)   ! Size of RAM requested
    if (ram_need.gt.sys_ramsize) then
      write(mess,'(A,F8.1,A,F8.1,A)') 'Data size (',1d-3*ram_need, &
        & 'GB) exceeds available RAM (',1d-3*sys_ramsize,' GB)'
      call map_message(seve%e,rname,mess,1)
      error = .true.
      return
    else if (ram_need.gt.sys_ramsize/3) then
      write(mess,'(A,F8.1,A,F8.1,A)') 'Data size (',1d-3*ram_need, &
        & 'GB) exceeds 1/3rd  of available RAM (',1d-3*sys_ramsize,' GB)'
      call map_message(seve%w,rname,mess,3)
    endif
    !
    allocate(duvi(insize_uv,huvi%gil%dim(2)),stat=ier)
    call map_read_uvdataset(fd,fits_fmt,pcount,htmp,huvi,local_nc,duvi,error)
    if (error) then
      deallocate(duvi,stat=ier)
      return
    endif
    ! Additional information if any
    huvi%r2d => duvi     ! Set the pointer towards the UV data area
    call get_more_header(fits_fmt,head%file,huvi)
    !
    ! Check the type and number of fields
    call check_uvdata_type(rname,huvi,duvi,themap,error)
    if (error) return
    !
    ! Automatically sort the UV data by fields if it is a Mosaic
    if (abs(themap%nfields).ne.0) then
      !
      ! Sort the DUV array if needed
      huvi%r2d => duvi
      call get_mosaic_cols(huvi,ioff,joff,itel,ismosaic)  
      call uvsort_check_fields(huvi,ioff,joff,itel,sorted)
      if (.not.sorted) then
        call map_message(seve%w,rname,'Sorting Mosaic UV Table',3)
        call gildas_null(htmp,type='UVT')
        call gdf_copy_header(huvi,htmp,error)
        allocate(htmp%r2d(huvi%gil%dim(1),huvi%gil%dim(2)),stat=ier) 
        htmp%r2d = duvi
        call uvsort_mosaic_mem(htmp,huvi,'FIELDS',ioff,joff,itel,error)
        deallocate(htmp%r2d)
      endif 
    endif
  else
    ! Do not read it, just come back to data specified in call sequence
    allocate(duvi(huvi%gil%dim(1),huvi%gil%dim(2)),stat=ier)
    duvi(:,:) = datauv(:,:)
    ! Check the type and number of fields
    call check_uvdata_type(rname,huvi,duvi,themap,error)
    if (error) return
    !
  endif
  ! Erase undefined part of visibility data
  if (huvi%gil%nvisi.lt.huvi%gil%dim(2)) then
    duvi(:,huvi%gil%nvisi+1:huvi%gil%dim(2)) = 0.
  endif
  !
  ! Set the Channel Flags to 1 (good)
  allocate(dchanflag(nchan),stat=ier)
  dchanflag = 1
  call sic_def_inte('DCHANFLAG',dchanflag,1,nchan,.false.,error)
  !
  ! Finalize
  call gildas_null (huv, type = 'UVT')
  call gdf_copy_header(huvi,huv, error)
  huv%file = huvi%file     ! Transmit File name
  huv%r2d => duvi
  duv => duvi              ! Point on original data
  duvr => duvi             ! Point on original data
  !
  call map_uvgildas('UV',huv,error,duvi) 
  !
  ! Undo the Weights buffers also
  if (allocated(g_weight)) deallocate(g_weight)
  if (allocated(g_v)) deallocate(g_v)
  do_weig = .true.
  !
  ! Unload the PRIMARY array if defined
  call sic_delvariable ('PRIMARY',.false.,error)
  if (allocated(dprim)) deallocate(dprim,stat=ier)
  hprim%loca%size = 0
  !
  ! Delete the BEAM_RANGES array if any
  nbeam_ranges = -1    ! Beam ranges unchecked
  call sic_delvariable ('BEAM_RANGES',.false.,error)
  !
  ! Delete the SELF array if defined
  call sic_delvariable ('UVSELF',.false.,error)
  if (associated(duvself)) then
    if (associated(duvself,duvcalib)) then
      nullify(duvself)
    else
      deallocate(duvself,stat=ier)
    endif 
    hself%loca%size = 0
  endif
  call sic_delvariable('UVCALIB',.false.,error)
  if (allocated(duvcalib)) deallocate(duvcalib,stat=ier)
  hcalib%loca%size = 0
  !
  ! Delete the CONTINUUM array if defined
  call sic_delvariable ('UVCONT',.false.,error)
  if (allocated(duvc)) deallocate(duvc,stat=ier)
  huvc%loca%size = 0
  ! Delete the CONTINUUM image if defined
  call sic_delvariable ('CONTINUUM',.false.,error)
  if (allocated(dcont)) deallocate(dcont,stat=ier)
  hcont%loca%size = 0
  !
  ! Final warning for POLARIZATION
  if (huv%gil%nstokes.gt.1) then
    write(mess,'(A,I0,A)') 'UV data has ',huv%gil%nstokes,' polarization states, use STOKES command'
    call map_message(seve%w,rname,mess,1)
  endif
  !
  ! Final message
  if (readit) then  
    call map_message(seve%i,rname,'UV Data read')
  else
    call map_message(seve%i,rname,'UV Data loaded')
  endif
  !
  ! Finalize the %mos structure
  if (abs(themap%nfields).gt.1) call mosaic_set_header(' ',.false.,error)
end subroutine getset_uvdata
!
subroutine check_uvdata_type(rname,huvl,visi,map,error)
  use image_def
  use clean_def
  use gbl_message
  use gkernel_interfaces
  use gkernel_types
  use imager_interfaces, only : mosaic_getfields, map_message,  &
    & get_bsize, define_fields
  !-------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Internal routine: Check number and types of fields
  !-------------------------------------------------------
  character(len=*), intent(in) :: rname     !! Calling command  
  type(gildas), intent(inout) :: huvl       !! UV header
  real, intent(inout) :: visi(:,:)          !! UV data
  type(uvmap_par), intent(inout) :: map     !! Map parameters (for the fields)
  logical, intent(inout) :: error           !! Logical error flag
  !
  ! Local ---
  type(projection_t) :: uv_proj
  integer :: np, nv, nf
  integer :: loff, moff, xoff, yoff, lid, itel, i, ier
  character(len=12) :: chain
  real :: value
  real :: bsize(10)
  ! real, allocatable :: doffxy(:,:) !Test SG
  !
  ! Code ----
  huvl%loca%size = huvl%gil%dim(1)*huvl%gil%dim(2)
  call reset_fields(map)
  ! 
  if (huvl%gil%ntrail.eq.0) return
  !
  np = huvl%gil%dim(1)
  nv = huvl%gil%nvisi
  !
  loff = huvl%gil%column_pointer(code_uvt_loff)
  moff = huvl%gil%column_pointer(code_uvt_moff)
  !
  xoff = huvl%gil%column_pointer(code_uvt_xoff)
  yoff = huvl%gil%column_pointer(code_uvt_yoff)
  !
  lid  = huvl%gil%column_pointer(code_uvt_id)
  itel = huvl%gil%column_pointer(code_uvt_tele)
  !
  if (lid.ne.0 .and. (loff.eq.0.or.moff.eq.0) .and. (xoff.eq.0.or.yoff.eq.0)) then
    value = visi(lid,1)
    if (any(visi(lid,:).ne.value)) then 
      nf = maxval(visi(lid,:))
      write(chain,'(I12)') nf
      call map_message(seve%e,rname,'Mosaic of '//adjustl(trim(chain))//' fields with only Source ID column')
      call map_message(seve%w,rname,'Use command UV_FIELDS to specify field coordinates')
      ! Ignore error to be able to patch file...
      ! huvl%loca%size = 0 ! Set UV as undefined
      ! error = .true.
      return
    else
      map%nfields = 0
      call map_message(seve%w,rname,'Degenerate mosaic of 1 field with Source ID column')
    endif    
  else if (loff.ne.0 .or. moff.ne.0) then
    ! Mosaic_GetFields allocates the %offxy arrays
    call mosaic_getfields (visi,np,nv,loff,moff,itel,nf,map%offxy,map%teles)  ! doffxy
    if (nf.gt.1) then
      map%nfields = -nf
      write(chain,'(I12)') nf
      call map_message(seve%i,rname,'Raw mosaic of '//adjustl(trim(chain))//' fields')
    else
      map%nfields = 0
      call map_message(seve%w,rname,'Degenerate raw mosaic of 1 field')
    endif
  else if (xoff.ne.0 .or. yoff.ne.0) then
    call mosaic_getfields (visi,np,nv,xoff,yoff,itel,nf,map%offxy,map%teles) ! doffxy)
    if (nf.gt.1) then
      map%nfields = nf
      write(chain,'(I12)') nf
      call map_message(seve%i,rname,'Phase shifted mosaic of '//adjustl(trim(chain))//' fields')
    else
      map%nfields = 0
      call map_message(seve%w,rname,'Degenerate phase shifted mosaic of 1 field')
    endif
  endif
  !
  if (map%nfields.eq.0) return
  !
  ! Convention for Rotated UV data is still pending for Mosaics
  if (huvl%gil%pang.ne.0.) then
    call map_message(seve%e,rname,'Rotated UV data not yet supported for Mosaics (no convention defined by IRAM)')
    huvl%loca%size = 0 ! Set UV as undefined
    error = .true.
    return
  endif
  !
  if (huvl%gil%nteles.le.0) then
    call map_message(seve%w,rname,'No Telescope section in data') 
    call map_message(seve%r,rname, &
      &   '         Use command "SPECIFY TELESCOPE Name" to add one') 
  endif
  ! 
  nf = abs(map%nfields)
  allocate(map%centers(2,nf),map%bsize(nf),map%teles(nf),stat=ier)
  bsize = 0     ! Must be initialized
  call get_bsize(huvl,rname,' ',bsize,error)  ! Compute the primary beams
  !
  !! call init_fields(.false.,error)
  !
  ! Compute the Pointing Centers
  call gwcs_projec(huvl%gil%a0, huvl%gil%d0, huvl%gil%pang, huvl%gil%ptyp, uv_proj, error)
  !
  do i=1,nf
    call rel_to_abs(uv_proj, dble(map%offxy(1,i)), dble(map%offxy(2,i)), &
      & map%centers(1,i), map%centers(2,i), 1)
    if (itel.ne.0) then
	  map%bsize(i) = bsize(map%teles(i))
	else
	  map%bsize(i) = bsize(1)
	endif
  enddo
  !
  call define_fields(map,error)
end subroutine check_uvdata_type
!
subroutine define_fields(map,error)  
  use image_def
  use clean_def
  use gkernel_interfaces
  !---------------------------------------------------
  ! @ private
  !*
  !   IMAGER -- Define the FIELDS% structure for Mosaics
  !!
  !---------------------------------------------------
  type(uvmap_par), intent(in) :: map  !! Mapping structure
  logical, intent(inout) :: error     !! Logical error flag
  !
  ! Local ---
  integer(kind=index_length) :: dim(2)
  !
  ! Code ----
  error = .false.
  call sic_defstructure('FIELDS',.true.,error)
  call sic_def_inte('FIELDS%N',map%nfields,0,dim,.false.,error)
  dim(1:2) = [2,abs(map%nfields)]
  call sic_def_real('FIELDS%OFFSETS',map%offxy,2,dim,.false.,error) 
  call sic_def_dble('FIELDS%CENTERS',map%centers,2,dim,.false.,error) 
  dim(1) = abs(map%nfields)
  call sic_def_real('FIELDS%PRIMARY',map%bsize,1,dim,.false.,error)
  call sic_def_inte('FIELDS%TELESCOPE',map%teles,1,dim,.false.,error)
end subroutine define_fields
!
subroutine reset_fields(map)
  use clean_def
  use clean_arrays
  use clean_default
  use gkernel_interfaces, only : sic_delvariable
  !-------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Internal routine: Reset Fields in Mapping structure
  !!
  !-------------------------------------------------------
  type(uvmap_par), intent(inout) :: map  !! Parameter structure
  !
  logical :: error
  !
  error = .false.
  map%nfields = 0
  if (allocated(map%centers)) deallocate(map%centers)
  if (allocated(map%offxy)) deallocate(map%offxy)
  if (allocated(map%bsize)) deallocate(map%bsize)
  mosaic_mode = 'NONE'
  ! Delete the FIELDS variable in all cases...
  call sic_delvariable('FIELDS',.false.,error)
end subroutine reset_fields
