subroutine get_gildas(rname,cinp,desc,hin,error)
  use gkernel_types
  use gkernel_interfaces
  use gbl_message
  use imager_interfaces, only : map_message
  !---------------------------------------------------------------------
  ! IMAGER
  ! @ public
  !   General tool to incarnate the SIC variable into a Gildas 
  !   derived type Fortran variable
  ! 
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: rname         ! Input caller name
  character(len=*), intent(in) :: cinp          ! Input variable name
  type(sic_descriptor_t), intent(out) :: desc   ! Descriptor
  type(gildas), intent(inout) :: hin            ! Gildas header 
  logical, intent(inout) :: error               ! Error flag 
  !
  logical :: found
  !
  ! Look at the SIC variable
  call sic_descriptor(cinp,desc,found)  
  if (.not.found) then
    call map_message(seve%e,rname,'No such SIC variable '//cinp)
    error = .true.
    return
  endif
  !
  ! If the descriptor is here, copy the Header in HIN
  if (.not.associated(desc%head)) then
    call map_message(seve%w,rname,  &
      'Variable '//trim(cinp)//' does not provide a header')
    call gildas_null(hin)
    ! This will be a simple Table
    hin%gil%form = desc%type              ! Variable type
    hin%gil%ndim = desc%ndim
    hin%gil%dim(1:desc%ndim) = desc%dims(1:desc%ndim)
  else
    !
    ! Locate the header - data area is given by desc%addr
    if (abs(desc%head%gil%type_gdf).eq.abs(code_gdf_uvt)) then
      call gildas_null(hin,type='UVT')
    else
      call gildas_null(hin)
    endif
    call gdf_copy_header(desc%head,hin,error)
  endif
end subroutine get_gildas
!
subroutine com_modify(line,error)
  use gkernel_interfaces
  use imager_interfaces, only : map_message 
  use phys_const
  use clean_arrays
  use clean_types
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  !
  ! IMAGER   Support for command
  !   SPECIFY KeyWord Value [/FOR ImageVariable] 
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: line
  logical, intent(out) :: error
  !
  integer, parameter :: o_for=1
  character(len=*), parameter :: rname = 'SPECIFY'
  integer, parameter :: icode_uv=1, icode_dirty=2, icode_clean=3, icode_sky=4, icode_all=5
  !
  integer, parameter :: nterm=5
  integer, parameter :: ncode=5
  character(len=varname_length) :: arg
  character(len=12) :: term(nterm),chain,key,cline,clines(ncode)
  data term/'FREQUENCY', 'LINENAME', 'TELESCOPE', 'VELOCITY','BLANKING'/
  integer :: i, iterm, narg, nc
  real(8) :: freq, freq_a,freq_b,value(3)
  real(4) :: velo, bval
  real(8) :: freqs(ncode)
  real(4) :: velos(ncode)
  logical :: do_freq, do_line, do_velo, found
  logical :: do_uv, do_dirty, do_clean, do_sky, do_one, do_blank
  type(sic_descriptor_t) :: desc   ! Descriptor
  !
  freq = 0.d0
  velo = -1.e9                     ! An impossible velocity
  do_freq = .false.
  do_line = .false.
  do_velo = .false.
  do_dirty = .false.
  do_clean = .false.
  do_sky = .false.
  do_uv = .false.
  do_one = .false.
  do_blank = .false.
  !
  if (sic_present(o_for,0)) then
    ! /FOR option - Get variable name
    call sic_ch(line,o_for,1,arg,nc,.true.,error)
    if (error) return
    !
    ! Look at the SIC variable
    call sic_descriptor(arg,desc,found)  
    if (.not.found) then
      call map_message(seve%e,rname,'No such SIC variable '//arg(1:nc))
      error = .true.
      return
    endif
    !
    ! There must be a Header in the descriptor... 
    if (.not.associated(desc%head)) then
      call map_message(seve%w,rname,  &
        'Variable '//arg(1:nc)//' does not provide a header')
      error = .true.
      return
    endif
    freq = desc%head%gil%freq
    velo = desc%head%gil%voff
    cline = desc%head%char%line
    clines(icode_all) = desc%head%char%line
    freqs(icode_all) = freq
    velos(icode_all) = velo
    do_one = .true.
  else
    if (hdirty%loca%size.ne.0) then
      freq = hdirty%gil%freq
      velo = hdirty%gil%voff
      cline = hdirty%char%line
      clines(icode_dirty) = hdirty%char%line
      freqs(icode_dirty) = freq
      velos(icode_dirty) = velo
      do_dirty = .true.
    endif
    if (hclean%loca%size.ne.0) then
      freq = hclean%gil%freq
      velo = hclean%gil%voff
      cline = hclean%char%line
      clines(icode_clean) = hclean%char%line
      freqs(icode_clean) = freq
      velos(icode_clean) = velo
      do_clean = .true.
    endif
    if (hsky%loca%size.ne.0) then
      freq = hsky%gil%freq
      velo = hsky%gil%voff
      cline = hsky%char%line
      clines(icode_sky) = hsky%char%line
      freqs(icode_sky) = freq
      velos(icode_sky) = velo
      do_sky = .true.
    endif
    !
    ! UV data must be last, to be pre-dominant in case
    ! a new UV table is read, but Images are not recomputed.
    !
    ! Some warning should be given then
    if (huv%loca%size.ne.0) then
      if (freq.ne.0 .and. abs(freq-huv%gil%freq).gt.1.d0) then  ! MHz
        call map_message(seve%w,rname,'Images and UV data have different frequencies')
      endif
      freq = huv%gil%freq
      if (velo.ne.-1e9 .and. abs(velo-huv%gil%voff).gt.1.d-3) then ! km/s
        call map_message(seve%w,rname,'Images and UV data have different velocity frames')
      endif
      velo = huv%gil%voff
      cline = huv%char%line
      clines(icode_uv) = huv%char%line
      freqs(icode_uv) = freq
      velos(icode_uv) = velo
      do_uv = .true.
    endif
  endif
  !
  narg = sic_narg(0)
  do i = 1, narg, 2
    call sic_ke(line,0,i,chain,nc,.true.,error)
    if (error) return
    call sic_ambigs(rname,chain,key,iterm,term,nterm,error)
    if (error) return
    !
    select case (key)
    case ('FREQUENCY')
      ! Modify velocity scale according to new rest frequency [MHz]
      call sic_r8(line,0,i+1,freq,.true.,error)
      do_freq = .true.
      !
    case ('VELOCITY')
      ! Modify Frequency scale according to new velocity (km/s)
      call sic_r4(line,0,i+1,velo,.true.,error)
      do_velo = .true.
      !
    case ('LINENAME')
      call sic_ch(line,0,i+1,cline,nc,.true.,error)
      do_line = .true.
    case ('TELESCOPE')
      call sic_ke(line,0,i+1,chain,nc,.true.,error)
      if (error) return
      !
      ! Update current UV and Initial UV data set if needed
      if (do_uv) then
        if (huv%gil%nteles.ge.1) then
          if (huv%gil%teles(1)%ctele .ne. chain(1:nc)) then
            call map_message(seve%i,rname,'Telescope ' &
            & //trim(huv%gil%teles(1)%ctele) &
            & //' in UV data overwritten by SPECIFY TELESCOPE '//chain(1:nc)) 
            ! Undefine the telescope so that all characteristics
            ! are re-defined by gdf_addteles after
            huv%gil%teles(1)%ctele = ' '
            huvi%gil%teles(1)%ctele = ' '
          endif
        endif
        call gdf_addteles(huv,'TELE',chain(1:nc),value,error)
        call gdf_addteles(huvi,'TELE',chain(1:nc),value,error)
      endif
    case ('BLANKING') 
      call sic_r4(line,0,i+1,bval,.true.,error)
      do_blank = .true.
    end select
    if (error) return
  enddo
  !
  ! Syntax check
  if (do_blank.and..not.do_one) then
    call map_message(seve%e,rname,'Option /FOR required for SPECIFY BLANKING')
    error = .true.
    return
  endif
  !
  ! Now which ones ...
  if (do_freq) freqs = freq
  if (do_velo) velos = velo
  if (do_line) clines = cline
  !
  if (do_one) then
    call gdf_modify(desc%head,velos(icode_all),freqs(icode_all),error=error)
    desc%head%char%line = clines(icode_all)
    if (do_blank) then
      call modify_blanking(desc,bval,error)
      if (error) return
    endif
  else 
    if (do_uv) then  !!  if (huv%loca%size.ne.0) then
      freq_b = gdf_uv_frequency(huv,1.d0)
      call gdf_modify(huv,velos(icode_uv),freqs(icode_uv),error=error)
      freq_a = gdf_uv_frequency(huv,1.d0)
      if (abs(freq_a-freq_b).gt.10.0) then
        Print *,'Frequency Before ',freq_b
        Print *,'Frequency After ',freq_a
        Print *,'Frequency Difference ',freq_a-freq_b
      endif
      huv%char%line = clines(icode_uv)
    endif
    if (do_dirty) then
      call gdf_modify(hdirty,velos(icode_dirty),freqs(icode_dirty),error=error)
      hdirty%char%line = clines(icode_dirty)
    endif
    if (do_clean) then
      call gdf_modify(hclean,velos(icode_clean),freqs(icode_clean),error=error)
      hclean%char%line = clines(icode_clean)
    endif
    if (do_sky) then
      call gdf_modify(hsky,velos(icode_sky),freqs(icode_sky),error=error)
      hsky%char%line = clines(icode_sky)
    endif
  endif
  !
end subroutine com_modify
!
subroutine modify_blanking(desc,bval,error)
  use gkernel_types
  use gkernel_interfaces
  use gbl_message
  use imager_interfaces, only : map_message
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  type(sic_descriptor_t), intent(inout) :: desc
  real, intent(in) :: bval
  logical, intent(out) :: error
  !
  include 'gbl_memory.inc'
  integer(kind=address_length) :: ipa
  !
  if (desc%head%gil%eval.lt.0) return
  !
  if (desc%head%gil%form.eq.fmt_r4) then
    ipa = gag_pointer(desc%addr,memory)
    !
    call submod_blanking(memory(ipa),desc%size, &
      & desc%head%gil%bval,desc%head%gil%eval,bval)
    desc%head%gil%bval = bval
    desc%head%gil%eval = 0.0 
  else
    call map_message(seve%e,'SPECIFY','Unsupported data format for BLANKING')
    error = .true.
    return
  endif
end subroutine modify_blanking
!
subroutine submod_blanking(array,n,ibval,ieval,obval)
  use gkernel_types
  integer(kind=size_length) :: n
  real(4), intent(inout) :: array(n)
  real(4), intent(in) :: ibval,ieval,obval
  !---------------------------------------------------------------------
  ! @ no-interfaces
  !     Change the Blanked values
  !---------------------------------------------------------------------
  integer(kind=index_length) :: i
  !
  do i=1,n
    if (abs(array(i)-ibval).le.ieval) array(i) = obval
  enddo
end subroutine submod_blanking
