subroutine extract_comm(line,error)
  use image_def
  use gkernel_interfaces
  use gkernel_types
  use gbl_message
  use iso_c_binding
  use clean_default
  use imager_interfaces, only : map_message
  !---------------------------------------------------------------------
  ! @ private  
  !*
  ! IMAGER -- Support for command EXTRACT Name [BLC TRC]
  ! 
  !	  Extract a subset from an input n-Dim image (n<4)  
  !   Uses specified BLC TRC or SIZE, CENTER and RANGE
  !!
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: line   !! Command line
  logical, intent(out) :: error         !! Logical error flag
  !
  character(len=*), parameter :: rname='EXTRACT'
  real(8), parameter :: pi=acos(-1.D0)
  ! Local ---
  integer :: i, ier, nc
  integer(kind=index_length) :: iblc(4),itrc(4),iout(4),pin(4)
  integer(kind=index_length) :: oblc(4),otrc(4)
  character(len=80) :: cinp
  type(sic_descriptor_t) :: desc
  type(gildas) :: hin
  type(gildas), save :: hou
  real, allocatable, save, target :: extract_data(:,:,:,:)
  type(c_ptr) :: cptr
  real, pointer :: r4ptr(:,:,:,:)
  real(4) :: x(2),xsize,ysize,xcent,ycent,xvelo,yvelo
  real(8) :: xref, factor
  integer :: ia(2)
  logical :: expand_size, expand_velo
  integer :: ndef, def(4), j
  character(len=132) :: mess
  !
  ! Code ----
  ! Input 3-D array: Locate the header and data area
  call sic_ch(line,0,1,cinp,nc,.true.,error)
  if (error) return
  call get_gildas(rname,cinp,desc,hin,error)
  if (error) return
  call gdf_copy_header(desc%head,hin,error)
  if (error) return
  !
  ! Expand to 4-D
  hin%gil%dim(1:4) = max(1,hin%gil%dim(1:4))
  !
  iblc = 0
  itrc = 0
  expand_size = .false.
  expand_velo = .false.
  !
  if (sic_narg(0).gt.1) then
    ! Have BLC TRC
    iblc = 1
    call sic_i4(line,0,2,i,.true.,error)
    iblc(1) = i
    call sic_i4(line,0,3,i,.true.,error)
    iblc(2) = i
    call sic_i4(line,0,4,i,.true.,error)
    iblc(3) = i
    itrc = 1
    call sic_i4(line,0,5,i,.true.,error)
    itrc(1) = i
    call sic_i4(line,0,6,i,.true.,error)
    itrc(2) = i
    call sic_i4(line,0,7,i,.true.,error)
    itrc(3) = i
    if (error) return
  else
    ! Derive from SIZE, CENTER and RANGE
    if (hin%gil%ptyp.ne.p_none) then
      call get_size_factor(factor)
    else
      factor = 1
    endif
    xsize = area_size(1)*factor
    ysize = area_size(2)*factor
    xcent = area_center(1)*factor
    ycent = area_center(2)*factor
    !
    call sic_get_real('RANGE[1]',xvelo,error)
    call sic_get_real('RANGE[2]',yvelo,error)
    !
    if (xsize.eq.0 .and. ysize.eq.0 .and. xvelo.eq.0 .and. yvelo.eq.0) then
      call map_message(seve%e,rname,'SIZE and RANGE undefined, please specify BLC TRC')
      error = .true.
      return
    else
      call map_message(seve%i,rname,'Using SIZE, CENTER and RANGE to define subset')
    endif
    if (xsize.ne.0) then
      x(1) = xcent-xsize/2
      x(2) = xcent+xsize/2
      ia(:)  = nint((x-hin%gil%val(1))/hin%gil%inc(1) + hin%gil%ref(1) )
      iblc(1) = minval(ia)
      itrc(1) = maxval(ia)
    endif
    if (ysize.ne.0) then
      x(1) = ycent-ysize/2
      x(2) = ycent+ysize/2
      ia(:)  = nint((x-hin%gil%val(2))/hin%gil%inc(2) + hin%gil%ref(2) )
      iblc(2) = minval(ia)
      itrc(2) = maxval(ia)
    endif
    if (xvelo.ne.0.or.yvelo.ne.0) then
      x(1) = xvelo
      x(2) = yvelo
      if ((hin%gil%faxi.eq.3).and.(hin%char%code(3).eq.'FREQUENCY')) then
        ! Use VELOCITY if it is a Frequency axis
        ! but find out at which pixel is the Rest Frequency
        xref = (hin%gil%freq-hin%gil%val(3))/hin%gil%inc(3) + hin%gil%ref(3)
        ia(:)  = nint( (x-hin%gil%voff)/hin%gil%vres + xref)
      else
        ! Use default axis unit,
        ia(:)  = nint( (x-hin%gil%val(3))/hin%gil%inc(3) + hin%gil%ref(3) )
      endif
      iblc(3) = minval(ia)
      itrc(3) = maxval(ia)
    endif
    !
    ! Now anything about enlarging the Output image...
    if ( xsize.gt.abs(hin%gil%dim(1)*hin%gil%inc(1)) .or. &
      &  ysize.gt.abs(hin%gil%dim(2)*hin%gil%inc(2)) ) then
      expand_size = .true.
    endif
    if ( abs(xvelo-yvelo).gt.abs(hin%gil%dim(3)*hin%gil%inc(3)) ) then
      expand_velo = .true.
    endif    
  endif
  !
  if (allocated(extract_data)) then
    deallocate(extract_data)
    call sic_delvariable('EXTRACTED',.false.,error)
  endif
  !
  call gildas_null(hou)
  call gdf_copy_header(hin,hou,error)
  !
  ! If any "expand_stuff" is set, the corresponding IBLC and ITRC can exceed the allowed range. 
  ! They  are used to define the span of the output data.
  ! Otherwise, usual defaults apply and must fit in the input range.
  ndef = 0
  if (expand_size) then
    oblc(1:2) = 1
    otrc(1:2) = itrc(1:2)-iblc(1:2)+1
  else
    ndef = 2
    def(1:2) = [1,2]
  endif
  if (expand_velo) then
    oblc(3) = 1
    otrc(3) = itrc(3)-iblc(3)+1
  else
    ndef = ndef+1
    def(ndef) = 3
  endif
  ndef = ndef+1
  def(ndef) = 4
  !
  do j=1,ndef
    i = def(j)
    if (iblc(i).eq.0) then
      oblc(i) = 1
      iblc(i) = 1
    else
      oblc(i) = iblc(i)  ! No min-max
      iblc(i) = max(iblc(i),1)
    endif
    if (itrc(i).eq.0) then
      otrc(i) = hin%gil%dim(i)
      itrc(i) = hin%gil%dim(i)
    else
      otrc(i) = itrc(i)  ! No min-max
      itrc(i) = min(itrc(i),hin%gil%dim(i))
    endif
    if (iblc(i).gt.itrc(i)) then
      write(mess,'(A,6(1X,I0))') 'Invalid subset ',iblc(1:3), itrc(1:3)
      call map_message(seve%e,rname,mess)
      error = .true.
      return
    endif
  enddo
  !
  if (sic_narg(0).le.1) then
    write(mess,'(A,I0,A,I0,A,I0,A,I0,A,I0,A,I0,A)') 'Selecting pixel range (',iblc(1),',',iblc(2),',',iblc(3), &
      & ')  - (',itrc(1),',',itrc(2),',',itrc(3),') '
    call map_message(seve%i,rname,mess)
  endif
  !
  do i=1,ndef
    if (iblc(i).gt.hin%gil%dim(i).or.itrc(i).lt.1) then
      call map_message(seve%e,rname,'Subset is out of data')
      return
    endif
  enddo
  !
  ! Get the true size
  hou%gil%dim(1:4) = itrc-iblc+1
  !
  pin = iblc
  ! Now restrict IBLC and ITRC to allowed range
  iblc = max(1,iblc)
  itrc = min(hin%gil%dim(1:4),itrc)
  !
  ! Initial PIN always moves at POUT = 1, so New IBLC moves at 
  iout = iblc-pin+1
  !
  ! Create output image
  hou%gil%extr_words = 0
  !
  ! Put pixel IMIN,JMIN at IOUT of output image
  hou%gil%ref = hin%gil%ref + iout - iblc
  !
  !
  allocate (extract_data(hou%gil%dim(1), hou%gil%dim(2), hou%gil%dim(3), hou%gil%dim(4)), stat=ier)
  if (ier.ne.0) then
    call map_message(seve%e,rname,'Output memory allocation error')
    error = .true.
    return
  endif
  !
  ! Adapt output Blanking if needed
  if (ndef.ne.4) then
    if (hou%gil%eval.lt.0) hou%gil%bval = 0
    extract_data = hou%gil%bval
  endif
  !
  ! ! hou%gil%eval = max(hou%gil%eval,0.0)
  hou%r4d => extract_data
  call adtoad(desc%addr,cptr,1)
  call c_f_pointer(cptr,r4ptr,hou%gil%dim(1:4))
  call sub_extract (   &
   &      r4ptr,hin%gil%dim(1),hin%gil%dim(2),hin%gil%dim(3),hin%gil%dim(4),   &
   &      extract_data,hou%gil%dim(1),hou%gil%dim(2),hou%gil%dim(3),hou%gil%dim(4),   &
   &      iblc,itrc,iout,hou%gil%bval)
  !
  ! Post the result as a SIC Image variable
  if (hou%gil%ndim.eq.2) then
    call sic_mapgildas('EXTRACTED',hou,error,extract_data(:,:,1,1))
  else if (hou%gil%ndim.eq.3) then
    call sic_mapgildas('EXTRACTED',hou,error,extract_data(:,:,:,1))
  else if (hou%gil%ndim.eq.4) then
    call sic_mapgildas('EXTRACTED',hou,error,extract_data)
  endif
end subroutine extract_comm
!
subroutine old_slice_comm(line,error)
  use image_def
  use gkernel_interfaces
  use gkernel_types
  use gbl_message
  use iso_c_binding
  use imager_interfaces, only : map_message
  !---------------------------------------------------------------------
  ! @ private  
  !*
  ! IMAGER -- Support routine for command SLICE  
  !   SLICE  DataSet  Xblc Xtrc Yblc Ytrc Type  
  !     or  
  !   SLICE  Dataset  Xc Yc Unit ANGLE PosAngle  
  !
  !   Arbitrary slice in a 3-D data set, using bilinear interpolation
  !!
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: line  !! Command line
  logical, intent(out) :: error         !! Logical error flag
  !
  ! Constants
  integer, external :: pix_axis
  character(len=*), parameter :: rname='SLICE'
  real(kind=8), parameter :: pi=3.14159265358979323846d0
  character(len=6), parameter :: cangle='ANGLE '
  character(len=8) :: unit_type(6)
  data unit_type /'ABSOLUTE','SECONDS','MINUTES','DEGREES','RADIANS','PIXELS'/
  !
  ! Local ---
  character(len=256) :: cinp
  integer :: nc
  integer :: axe,ier
  real(4), allocatable :: lgu(:), mgu(:)
  ! !real(8), allocatable :: ii(:), rr(:), xx(:), yy(:)
  real(8) :: Startx,Starty,Endx,Endy,Centerx,Centery
  real(8) :: aa, bb, xmin, ymin
  !
  integer :: istart(2), iend(2)
  integer :: npoints 
  real(8) :: dstart(2), dend(2), dl, dm, dx, dy, ang, dd
  real(8) :: user1,user2
  character(len=24) :: ra_start, dec_start, ra_end, dec_end
  character(len=24) :: ra_center, dec_center
  real(8) :: ustart(2), uend(2)
  type(gildas) :: hin
  type(gildas), save :: hou
  type(sic_descriptor_t) :: desc
  real, allocatable, target, save :: slice_data(:,:)
  type(projection_t) :: proj
  integer :: itype
  character(len=8) :: ctype, ktype
  character(len=64) :: dtype
  real(kind=8) :: angle_scale(6), angle, length
  type(c_ptr) :: cptr
  !
  ! Code ----
  !
  ! Get name of data file/buffer
  call sic_ch(line,0,1,cinp,nc,.true.,error)
  if (error) return
  !
  ! Incarnate the SIC variable into a local header
  call get_gildas(rname,cinp,desc,hin,error)
  if (error) return
  call adtoad(desc%addr,cptr,1)
  call c_f_pointer(cptr,hin%r3d,hin%gil%dim(1:3))
  !
  call sic_ke(line,0,5,dtype,nc,.true.,error)
  if (error) return
  !
  nc = min(nc,6)
  ctype = dtype
  if (ctype(1:nc).eq.cangle(1:nc)) then
    ! ANGLE Keyword found
    !
    call sic_r8(line,0,6,angle,.true.,error)
    if (error) return
    ! Angle is in Degree North from East - Bring it in range [-180,180[
    ! Define Slice Length according to appropriate Image size in selected
    ! direction.
    if (angle.gt.180) angle = angle-360
    !
    ! The test should also consider the Projection Angle hin%gil%pang
    ! Ignore it so far
    if (abs(angle).lt.22.5) then
      length = abs(hin%gil%inc(1)*hin%gil%dim(1))
    else if (abs(angle).lt.67.5) then    
      length = min(abs(hin%gil%inc(1)*hin%gil%dim(1)),abs(hin%gil%inc(2))*hin%gil%dim(2))
    else if (abs(angle).lt.112.5) then
      length = abs(hin%gil%inc(2)*hin%gil%dim(2))
    else if (abs(angle).lt.157.5) then    
      length = min(abs(hin%gil%inc(1)*hin%gil%dim(1)),abs(hin%gil%inc(2))*hin%gil%dim(2))
    else
      length = abs(hin%gil%inc(1)*hin%gil%dim(1))    
    endif
    length = length/2
    angle = 90-angle ! North towards East in sky...
    angle = angle*pi/180    ! Convert to Radian
    !
    !   SLICE  Dataset  Xc Yc Unit ANGLE PosAngle
    call sic_ke(line,0,4,ctype,nc,.false.,error)
    call sic_ambigs(rname,ctype,ktype,itype,unit_type,6,error)
    if (error) return
    angle_scale = [0.d0,pi/180d0/3600d0,pi/180d0/60d0,pi/180d0,1.d0,-1.d0]  
    !
    call gwcs_projec(hin%gil%a0,hin%gil%d0,hin%gil%pang,hin%gil%ptyp,proj,error)
    if (error) return
    select case (ktype)
    case ('ABSOLUTE')
      call sic_ch(line,0,2,ra_center,nc,.true.,error)
      call sic_ch(line,0,3,dec_center,nc,.true.,error)
      call sic_decode(ra_center,ustart(1),24,error)
      if (error) then
        call map_message(seve%e,rname,'Error in SIC_DECODE RA Start')
        return
      endif
      call sic_decode(dec_center,ustart(2),360,error)
      if (error) then
        call map_message(seve%e,rname,'Error in SIC_DECODE Dec Start')
        return
      endif
      call abs_to_rel(proj,ustart(1), ustart(2), CenterX, CenterY, 1)
      user1 = CenterX - length * cos(angle)
      user2 = CenterY - length * sin(angle)
      istart(1) = pix_axis(hin,user1,1)
      istart(2) = pix_axis(hin,user2,2)
      user1 = CenterX + length * cos(angle)
      user2 = CenterY + length * sin(angle)
      iend(1) = pix_axis(hin,user1,1)
      iend(2) = pix_axis(hin,user2,2)
    case ('PIXELS')
      if (mod(angle,90*pi/180).ne.0) then
        if (abs(hin%gil%inc(1)).ne.abs(hin%gil%inc(2))) then
          call map_message(seve%e,rname,'Cannot specify rotated direction with non square pixels')
          return
        endif
      endif
      call sic_i4(line,0,2,istart(1),.true.,error)
      call sic_i4(line,0,3,istart(2),.true.,error)
      iend(1) = istart(1) + length*cos(angle)/hin%gil%inc(1)
      iend(2) = istart(2) + length*sin(angle)/hin%gil%inc(2)
      istart(1) = istart(1) - length*cos(angle)/hin%gil%inc(1)
      istart(2) = istart(2) - length*sin(angle)/hin%gil%inc(2)
    case default
      call sic_r8(line,0,2,user1,.true.,error)
      call sic_r8(line,0,3,user2,.true.,error)
      CenterX = user1*angle_scale(itype)
      CenterY = user2*angle_scale(itype)
      !
      user1 = CenterX - length * cos(angle)
      user2 = CenterY - length * sin(angle)
      istart(1) = pix_axis(hin,user1,1)
      istart(2) = pix_axis(hin,user2,2)
      user1 = CenterX + length * cos(angle)
      user2 = CenterY + length * sin(angle)
      iend(1) = pix_axis(hin,user1,1)
      iend(2) = pix_axis(hin,user2,2)
    end select
  else    
    ctype = 'ABSOLUTE'
    call sic_ke(line,0,6,ctype,nc,.false.,error)
    call sic_ambigs(rname,ctype,ktype,itype,unit_type,6,error)
    if (error) return
    angle_scale = [0.d0,pi/180d0/3600d0,pi/180d0/60d0,pi/180d0,1.d0,-1.d0]  
    !
    ! Prepare the output
    !
    call gwcs_projec(hin%gil%a0,hin%gil%d0,hin%gil%pang,hin%gil%ptyp,proj,error)
    if (error) return
    select case (ktype)
    case ('ABSOLUTE')
      call sic_ch(line,0,2,ra_start,nc,.true.,error)
      call sic_ch(line,0,3,dec_start,nc,.true.,error)
      call sic_ch(line,0,4,ra_end,nc,.true.,error)
      call sic_ch(line,0,5,dec_end,nc,.true.,error)
      if (error) return
      call sic_decode(ra_start,ustart(1),24,error)
      if (error) then
        call map_message(seve%e,rname,'Error in SIC_DECODE RA Start')
        return
      endif
      call sic_decode(dec_start,ustart(2),360,error)
      if (error) then
        call map_message(seve%e,rname,'Error in SIC_DECODE Dec Start')
        return
      endif
      call sic_decode(ra_end,uend(1),24,error)
      if (error) then
        call map_message(seve%e,rname,'Error in SIC_DECODE RA End')
        return
      endif
      call sic_decode(dec_end,uend(2),360,error)
      if (error) then
        call map_message(seve%e,rname,'Error in SIC_DECODE Dec End')
        return
      endif
      call abs_to_rel(proj,ustart(1), ustart(2), user1, user2, 1)
      istart(1) = pix_axis(hin,user1,1)
      istart(2) = pix_axis(hin,user2,2)
      call abs_to_rel(proj,uend(1), uend(2), user1, user2, 1)
      iend(1) = pix_axis(hin,user1,1)
      iend(2) = pix_axis(hin,user2,2)
    case ('PIXELS')
      call sic_i4(line,0,2,istart(1),.true.,error)
      call sic_i4(line,0,3,istart(2),.true.,error)
      call sic_i4(line,0,4,iend(1),.true.,error)
      call sic_i4(line,0,5,iend(2),.true.,error)
    case default
      call sic_r8(line,0,2,user1,.true.,error)
      call sic_r8(line,0,3,user2,.true.,error)
      user1 = user1*angle_scale(itype)
      user2 = user2*angle_scale(itype)
      istart(1) = pix_axis(hin,user1,1)
      istart(2) = pix_axis(hin,user2,2)
      call sic_r8(line,0,4,user1,.true.,error)
      call sic_r8(line,0,5,user2,.true.,error)
      user1 = user1*angle_scale(itype)
      user2 = user2*angle_scale(itype)
      iend(1) = pix_axis(hin,user1,1)
      iend(2) = pix_axis(hin,user2,2)
    end select
  endif
  !
  if (allocated(slice_data)) then
    error = .false.
    call sic_delvariable('SLICED',.false.,error)
    deallocate (slice_data)
  endif
  call gildas_null(hou)
  !
  call gdf_copy_header(hin,hou,error)
  !
  dstart(1) = dble(istart(1))
  dstart(2) = dble(istart(2))
  dend(1) = dble(iend(1))
  dend(2) = dble(iend(2))
  !
  ! Define number of points
  ang = 0.0
  if (dstart(1).eq.dend(1)) then
    axe = 2
    dx = 0.
    dy = 1.
    npoints = dabs(dend(2) - dstart(2)) + 1.
  elseif (dstart(2).eq.dend(2)) then
    axe = 1
    dx = 1.
    dy = 0.
    npoints = dabs(dend(1) - dstart(1)) + 1.
  else
    axe = 0
    dl = dabs(dend(1)-dstart(1)) + 1.
    dm = dabs(dend(2)-dstart(2)) + 1.
    npoints = sqrt(dl*dl + dm*dm)
    dx = dl/dble(npoints)
    dy = dm/dble(npoints)
  endif
  !
  allocate (lgu(npoints), mgu(npoints), stat=ier)
  if (ier.ne.0) then
    call map_message(seve%e,rname,'Memory allocation error')
    error = .true.
    return
  endif
  !
  ! Why do not we simply exchange at this stage ?
  ! Because we want to keep the order specified by the user...
  if (dend(1).lt.dstart(1)) then
    dx = -dx
  endif
  if (dend(2).lt.dstart(2)) then
    dy = -dy
  endif
  if (axe.eq.0) then
    ang = atan2(dx*hin%gil%inc(1),dy*hin%gil%inc(2))
  else if (axe.eq.1) then
    dd = dx
  else
    dd = dy
  endif
  !
  ! !Print *,'Axe ',axe,'DX ',dx,' DY ',dy,' ANGLE ',ang 
  !
  !     Allocate arrays for slice coordinates
  call fill_gu(lgu, dstart(1), dx, npoints)
  call fill_gu(mgu, dstart(2), dy, npoints)
  !
  ! Now we would like to know where is the closest point to the (0,0)
  !
  ! We have a straight line dermined by two points: Startx,Starty and Endx,Endy
  Startx = (dstart(1)-hin%gil%ref(1))*hin%gil%inc(1) + hin%gil%val(1)
  Starty = (dstart(2)-hin%gil%ref(2))*hin%gil%inc(2) + hin%gil%val(2)
  Endx = (dend(1)-hin%gil%ref(1))*hin%gil%inc(1) + hin%gil%val(1)
  Endy = (dend(2)-hin%gil%ref(2))*hin%gil%inc(2) + hin%gil%val(2)
  !
  ! Find out the nearest point to (0,0) 
  if (abs(Endx-Startx).gt.abs(Endy-Starty)) then
    ! The line equation is 
    !   y(x) = (x-Startx)/(Endx-Startx)*(Endy-Starty) + Starty
    ! which I write y(x) = aa * x + bb
    aa = (Endy-Starty)/(Endx-Startx) 
    bb = -aa * Startx + Starty
    !
    ! and the distance to (0,0) is sqrt(x^2+y2), whose minimum is obtained
    ! for d(x^2+y^2)/dx = 0 or 
    xmin = -aa*bb/(aa**2+1.d0)
    !
    ! We now want AA and BB to be the (x,y) of the closest point
    BB = xmin*aa+bb
    AA = xmin
  else
    !
    ! As above, but swapping (x,y)
    aa = (Endx-Startx)/(Endy-Starty) 
    bb = -aa * Starty + Startx
    ymin = -aa*bb/(aa**2+1.d0)
    !
    ! We now want AA and BB to be the (x,y) of the closest point
    AA = ymin*aa+bb
    BB = ymin
  endif
  !
  ! !Print *,' AA ',aa*180*3600/pi,' BB ',bb*180*3600/pi
  !
  ! Prepare the header
  hou%gil%dim(1) = npoints
  hou%gil%dim(2) = hin%gil%dim(3)
  hou%gil%dim(3) = 1
  hou%gil%ndim = 2
  hou%loca%size = hou%gil%dim(1)*hou%gil%dim(2)
  hou%char%code(2) = hin%char%code(3)
  hou%gil%yaxi = 3
  hou%gil%faxi = 2
  hou%char%code(3) = 'ANGLE'
  !
  hou%gil%convert(:,2) = hin%gil%convert(:,3)
  !
  user1 = (lgu(1)-hin%gil%ref(1))*hin%gil%inc(1) + hin%gil%val(1)
  user2 = (mgu(1)-hin%gil%ref(2))*hin%gil%inc(2) + hin%gil%val(2)
  !
  if (axe.ne.0) then
    hou%char%code(1) = hin%char%code(axe)
    hou%gil%inc(1) =  dd*hin%gil%inc(axe)
    hou%gil%xaxi = hin%gil%xaxi
    hou%gil%val(1) = 0.
    !
    ! Here we would like to put the other axis information as 3rd
    ! degenerate axis
    hou%char%code(3) = hin%char%code(3-axe)
    hou%gil%inc(3) =  hin%gil%inc(3-axe)
    hou%gil%ref(3) = hin%gil%ref(3-axe)
  else
    hou%char%code(1) = 'ANGLE'
    hou%gil%xaxi = 1
    hou%gil%pang = ang
    ! The pixel size is also different - pixels have orthogonal sides,
    ! and this is the hypotenuse of the right-angled triangle.
    hou%gil%inc(1) = sqrt((dx*hin%gil%inc(1))**2 + (dy*hin%gil%inc(2))**2)
    if (abs(dx).gt.abs(dy)) then
      if (dx.lt.0) hou%gil%inc(1) = -hou%gil%inc(1)
    else
      if (dy.lt.0) hou%gil%inc(1) = -hou%gil%inc(1)
    endif
    !
    hou%gil%ref(3) = 1.0
    hou%gil%val(3) = sqrt(AA**2+bb**2)  ! Distance to (0,0) 
    hou%gil%inc(3) = hou%gil%inc(1)
    hou%gil%pang = ang
  endif
  !
  ! First axis
  hou%gil%val(1) = 0.0
  ! But now, we have our Reference pixel that has an X value of
  ! AA and an YY value of BB - We take the most precise
  if (abs(dx).gt.abs(dy)) then
    hou%gil%ref(1) = (AA-user1)/(hin%gil%inc(1)*dx) + 1.0
  else
    hou%gil%ref(1) = (BB-user2)/(hin%gil%inc(2)*dy) + 1.0
  endif
  !
  hou%gil%ndim = 3
  hou%gil%dim(3) = 1
  hou%gil%extr_words = 0
  !
  ! Allocate the data
  allocate(slice_data(hou%gil%dim(1),hou%gil%dim(2)), stat=ier)
  if (ier.ne.0) then
    call map_message(seve%e,rname,'Output memory allocation error')
    error = .true.
    return
  endif
  hou%r2d => slice_data
  !
  ! Compute the slice
  call do_sliceb(hin%r3d, hin%gil%dim(1), hin%gil%dim(2), hin%gil%dim(3),   &
   &      lgu, mgu, hou%r2d, npoints, hin%gil%bval, hin%gil%eval)
  hou%gil%eval = max(hin%gil%eval,0.)
  !
  ! Post the result as a SIC Image variable
  error = .false.
  call sic_mapgildas('SLICED',hou,error,slice_data)
  !
end subroutine old_slice_comm
!
subroutine slice_comm(line,error)
  use image_def
  use gkernel_interfaces
  use gkernel_types
  use gbl_message
  use iso_c_binding
  use imager_interfaces, only : map_message, slice_sub
  !---------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Support routine for command SLICE  
  !   SLICE  DataSet  Xblc Xtrc Yblc Ytrc Type  
  !     or  
  !   SLICE  Dataset  Xc Yc Unit ANGLE PosAngle  
  !
  !   Arbitrary slice in a 3-D data set, using bilinear interpolation
  !!
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: line  !! Command line
  logical, intent(out) :: error         !! Logical error flag
  !
  ! Constants
  integer, external :: pix_axis
  character(len=*), parameter :: rname='SLICE'
  real(kind=8), parameter :: pi=3.14159265358979323846d0
  character(len=6), parameter :: cangle='ANGLE '
  integer, parameter :: munit=6
  character(len=8) :: unit_type(munit)
  data unit_type /'ABSOLUTE','SECONDS','MINUTES','DEGREES','RADIANS','PIXELS'/
  real(8), parameter :: angle_scale(munit) = [0.d0,pi/180d0/3600d0,pi/180d0/60d0,pi/180d0,1.d0,-1.d0]
  ! Local
  character(len=256) :: cinp
  integer :: nc
  !
  real(8) :: Centerx,Centery
  !
  integer :: istart(2), iend(2)
  real(8) :: user1,user2
  character(len=24) :: ra_start, dec_start, ra_end, dec_end
  character(len=24) :: ra_center, dec_center
  real(8) :: ustart(2), uend(2)
  type(gildas) :: hin
  type(gildas), save :: hou
  type(sic_descriptor_t) :: desc
  real, allocatable, target, save :: slice_data(:,:)
  type(projection_t) :: proj
  integer :: itype
  character(len=64) :: dtype
  character(len=8) :: ctype, ktype
  real(kind=8) :: angle, length
  type(c_ptr) :: cptr
  !
  ! Code ----
  if (sic_narg(0).eq.0) then
    call sic_get_char('LAST_SHOWN',cinp,nc,error)
  else
    ! Get name of data file/buffer
    call sic_ch(line,0,1,cinp,nc,.true.,error)
  endif
  if (error) return
  !
  ! Incarnate the SIC variable into a local header
  call get_gildas(rname,cinp,desc,hin,error)
  if (error) return
  call adtoad(desc%addr,cptr,1)
  call c_f_pointer(cptr,hin%r3d,hin%gil%dim(1:3))
  !
  if (sic_narg(0).eq.0) then
    !
    ! Call the cursor if it is a 2-D array
    call exec_program('@ p_slice_corner 1')
    call sic_get_inte('PIX_CURS[1]',istart(1),error)
    call sic_get_inte('PIX_CURS[2]',istart(2),error)
    if (istart(1).eq.0 .and. istart(2).eq.0) then
      call map_message(seve%e,rname,'No available 2-D display for SLICE /CURSOR')
      error = .true.
      return
    endif
    call exec_program('@ p_slice_corner 2')
    call sic_get_inte('PIX_CURS[1]',iend(1),error)
    call sic_get_inte('PIX_CURS[2]',iend(2),error)
  else
    call sic_ke(line,0,5,dtype,nc,.true.,error)
    if (error) return
    !
    nc = min(nc,6)
    ctype = dtype
    if (ctype(1:nc).eq.cangle(1:nc)) then
      ! ANGLE Keyword found
      !
      call sic_r8(line,0,6,angle,.true.,error)
      if (error) return
      ! Angle is in Degree North from East - Bring it in range [-180,180[
      ! Define Slice Length according to appropriate Image size in selected
      ! direction.
      if (angle.gt.180) angle = angle-360
      !
      ! The test should also consider the Projection Angle hin%gil%pang
      ! Ignore it so far
      if (abs(angle).lt.22.5) then
        length = abs(hin%gil%inc(1)*hin%gil%dim(1))
      else if (abs(angle).lt.67.5) then
        length = min(abs(hin%gil%inc(1)*hin%gil%dim(1)),abs(hin%gil%inc(2))*hin%gil%dim(2))
      else if (abs(angle).lt.112.5) then
        length = abs(hin%gil%inc(2)*hin%gil%dim(2))
      else if (abs(angle).lt.157.5) then
        length = min(abs(hin%gil%inc(1)*hin%gil%dim(1)),abs(hin%gil%inc(2))*hin%gil%dim(2))
      else
        length = abs(hin%gil%inc(1)*hin%gil%dim(1))
      endif
      length = length/2
      angle = 90-angle ! North towards East in sky...
      angle = angle*pi/180    ! Convert to Radian
      !
      !   SLICE  Dataset  Xc Yc Unit ANGLE PosAngle
      call sic_ke(line,0,4,ctype,nc,.false.,error)
      call sic_ambigs(rname,ctype,ktype,itype,unit_type,6,error)
      if (error) return
      !
      call gwcs_projec(hin%gil%a0,hin%gil%d0,hin%gil%pang,hin%gil%ptyp,proj,error)
      if (error) return
      select case (ktype)
      case ('ABSOLUTE')
        call sic_ch(line,0,2,ra_center,nc,.true.,error)
        call sic_ch(line,0,3,dec_center,nc,.true.,error)
        call sic_decode(ra_center,ustart(1),24,error)
        if (error) then
          call map_message(seve%e,rname,'Error in SIC_DECODE RA Start')
          return
        endif
        call sic_decode(dec_center,ustart(2),360,error)
        if (error) then
          call map_message(seve%e,rname,'Error in SIC_DECODE Dec Start')
          return
        endif
        call abs_to_rel(proj,ustart(1), ustart(2), CenterX, CenterY, 1)
        user1 = CenterX - length * cos(angle)
        user2 = CenterY - length * sin(angle)
        istart(1) = pix_axis(hin,user1,1)
        istart(2) = pix_axis(hin,user2,2)
        user1 = CenterX + length * cos(angle)
        user2 = CenterY + length * sin(angle)
        iend(1) = pix_axis(hin,user1,1)
        iend(2) = pix_axis(hin,user2,2)
      case ('PIXELS')
        if (mod(angle,90*pi/180).ne.0) then
          if (abs(hin%gil%inc(1)).ne.abs(hin%gil%inc(2))) then
            call map_message(seve%e,rname,'Cannot specify rotated direction with non square pixels')
            return
          endif
        endif
        call sic_i4(line,0,2,istart(1),.true.,error)
        call sic_i4(line,0,3,istart(2),.true.,error)
        iend(1) = istart(1) + length*cos(angle)/hin%gil%inc(1)
        iend(2) = istart(2) + length*sin(angle)/hin%gil%inc(2)
        istart(1) = istart(1) - length*cos(angle)/hin%gil%inc(1)
        istart(2) = istart(2) - length*sin(angle)/hin%gil%inc(2)
      case default
        call sic_r8(line,0,2,user1,.true.,error)
        call sic_r8(line,0,3,user2,.true.,error)
        CenterX = user1*angle_scale(itype)
        CenterY = user2*angle_scale(itype)
        !
        user1 = CenterX - length * cos(angle)
        user2 = CenterY - length * sin(angle)
        istart(1) = pix_axis(hin,user1,1)
        istart(2) = pix_axis(hin,user2,2)
        user1 = CenterX + length * cos(angle)
        user2 = CenterY + length * sin(angle)
        iend(1) = pix_axis(hin,user1,1)
        iend(2) = pix_axis(hin,user2,2)
      end select
    else
      ctype = 'ABSOLUTE'
      call sic_ke(line,0,6,ctype,nc,.false.,error)
      call sic_ambigs(rname,ctype,ktype,itype,unit_type,6,error)
      if (error) return
      !
      ! Prepare the output
      !
      call gwcs_projec(hin%gil%a0,hin%gil%d0,hin%gil%pang,hin%gil%ptyp,proj,error)
      if (error) return
      select case (ktype)
      case ('ABSOLUTE')
        call sic_ch(line,0,2,ra_start,nc,.true.,error)
        call sic_ch(line,0,3,dec_start,nc,.true.,error)
        call sic_ch(line,0,4,ra_end,nc,.true.,error)
        call sic_ch(line,0,5,dec_end,nc,.true.,error)
        if (error) return
        call sic_decode(ra_start,ustart(1),24,error)
        if (error) then
          call map_message(seve%e,rname,'Error in SIC_DECODE RA Start')
          return
        endif
        call sic_decode(dec_start,ustart(2),360,error)
        if (error) then
          call map_message(seve%e,rname,'Error in SIC_DECODE Dec Start')
          return
        endif
        call sic_decode(ra_end,uend(1),24,error)
        if (error) then
          call map_message(seve%e,rname,'Error in SIC_DECODE RA End')
          return
        endif
        call sic_decode(dec_end,uend(2),360,error)
        if (error) then
          call map_message(seve%e,rname,'Error in SIC_DECODE Dec End')
          return
        endif
        call abs_to_rel(proj,ustart(1), ustart(2), user1, user2, 1)
        istart(1) = pix_axis(hin,user1,1)
        istart(2) = pix_axis(hin,user2,2)
        call abs_to_rel(proj,uend(1), uend(2), user1, user2, 1)
        iend(1) = pix_axis(hin,user1,1)
        iend(2) = pix_axis(hin,user2,2)
      case ('PIXELS')
        call sic_i4(line,0,2,istart(1),.true.,error)
        call sic_i4(line,0,3,istart(2),.true.,error)
        call sic_i4(line,0,4,iend(1),.true.,error)
        call sic_i4(line,0,5,iend(2),.true.,error)
      case default
        call sic_r8(line,0,2,user1,.true.,error)
        call sic_r8(line,0,3,user2,.true.,error)
        user1 = user1*angle_scale(itype)
        user2 = user2*angle_scale(itype)
        istart(1) = pix_axis(hin,user1,1)
        istart(2) = pix_axis(hin,user2,2)
        call sic_r8(line,0,4,user1,.true.,error)
        call sic_r8(line,0,5,user2,.true.,error)
        user1 = user1*angle_scale(itype)
        user2 = user2*angle_scale(itype)
        iend(1) = pix_axis(hin,user1,1)
        iend(2) = pix_axis(hin,user2,2)
      end select
    endif
  endif
  !
  if (allocated(slice_data)) then
    error = .false.
    call sic_delvariable('SLICED',.false.,error)
    deallocate (slice_data)
  endif
  !
  call slice_sub(hin,hou,slice_data,istart,iend,error)
  if (error) return
  ! Post the result as a SIC Image variable
  call sic_mapgildas('SLICED',hou,error,slice_data)
  !
end subroutine slice_comm
!
subroutine slice_sub(hin,hou,slice_data,istart,iend,error)
  use image_def
  use gkernel_types
  use gkernel_interfaces
  use gbl_message
  use imager_interfaces, only : map_message
  !---------------------------------------------------
  ! @ private-mandatory
  !*
  ! IMAGER -- Internal routine for command SLICE
  !!
  !---------------------------------------------------
  type(gildas), intent(in) :: hin     !! Input cube header
  type(gildas), intent(out) :: hou    !! Output slice header
  real, allocatable, intent(inout), target :: slice_data(:,:)  !! Slice data
  integer, intent(in) :: istart(2)    !! Starting pixel
  integer, intent(in) :: iend(2)      !! Ending pixel
  logical, intent(inout) :: error     !! Logical error flag
  !
  ! Constants
  character(len=*), parameter :: rname='SLICE'
  real(8), parameter :: pi=acos(-1d0)
  !
  ! Local ---
  integer :: axe,ier
  real(4), allocatable :: lgu(:), mgu(:)
  real(8) :: Startx,Starty,Endx,Endy
  real(8) :: aa, bb, xmin, ymin
  !
  integer :: npoints
  real(8) :: dstart(2), dend(2), dl, dm, dx, dy, ang, dd
  real(8) :: user1,user2
  !
  ! Code ----
  call gildas_null(hou)
  call gdf_copy_header(hin,hou,error)
  !
  dstart(1) = dble(istart(1))
  dstart(2) = dble(istart(2))
  dend(1) = dble(iend(1))
  dend(2) = dble(iend(2))
  !
  ! Define number of points
  ang = 0.0
  if (dstart(1).eq.dend(1)) then
    axe = 2
    dx = 0.
    dy = 1.
    npoints = dabs(dend(2) - dstart(2)) + 1.
  elseif (dstart(2).eq.dend(2)) then
    axe = 1
    dx = 1.
    dy = 0.
    npoints = dabs(dend(1) - dstart(1)) + 1.
  else
    axe = 0
    dl = dabs(dend(1)-dstart(1)) + 1.
    dm = dabs(dend(2)-dstart(2)) + 1.
    npoints = sqrt(dl*dl + dm*dm)
    dx = dl/dble(npoints)
    dy = dm/dble(npoints)
  endif
  !
  allocate (lgu(npoints), mgu(npoints), stat=ier)
  if (ier.ne.0) then
    call map_message(seve%e,rname,'Memory allocation error')
    error = .true.
    return
  endif
  !
  ! Why do not we simply exchange at this stage ?
  ! Because we want to keep the order specified by the user...
  if (dend(1).lt.dstart(1)) then
    dx = -dx
  endif
  if (dend(2).lt.dstart(2)) then
    dy = -dy
  endif
  if (axe.eq.0) then
    ang = atan2(dx*hin%gil%inc(1),dy*hin%gil%inc(2))
  else if (axe.eq.1) then
    dd = dx
  else
    dd = dy
  endif
  !
  !     Allocate arrays for slice coordinates
  call fill_gu(lgu, dstart(1), dx, npoints)
  call fill_gu(mgu, dstart(2), dy, npoints)
  !
  ! Now we would like to know where is the closest point to the (0,0)
  !
  ! We have a straight line dermined by two points: Startx,Starty and Endx,Endy
  Startx = (dstart(1)-hin%gil%ref(1))*hin%gil%inc(1) + hin%gil%val(1)
  Starty = (dstart(2)-hin%gil%ref(2))*hin%gil%inc(2) + hin%gil%val(2)
  Endx = (dend(1)-hin%gil%ref(1))*hin%gil%inc(1) + hin%gil%val(1)
  Endy = (dend(2)-hin%gil%ref(2))*hin%gil%inc(2) + hin%gil%val(2)
  !
  ! Find out the nearest point to (0,0)
  if (abs(Endx-Startx).gt.abs(Endy-Starty)) then
    ! The line equation is
    !   y(x) = (x-Startx)/(Endx-Startx)*(Endy-Starty) + Starty
    ! which I write y(x) = aa * x + bb
    aa = (Endy-Starty)/(Endx-Startx)
    bb = -aa * Startx + Starty
    !
    ! and the distance to (0,0) is sqrt(x^2+y2), whose minimum is obtained
    ! for d(x^2+y^2)/dx = 0 or
    xmin = -aa*bb/(aa**2+1.d0)
    !
    ! We now want AA and BB to be the (x,y) of the closest point
    BB = xmin*aa+bb
    AA = xmin
  else
    !
    ! As above, but swapping (x,y)
    aa = (Endx-Startx)/(Endy-Starty)
    bb = -aa * Starty + Startx
    ymin = -aa*bb/(aa**2+1.d0)
    !
    ! We now want AA and BB to be the (x,y) of the closest point
    AA = ymin*aa+bb
    BB = ymin
  endif
  !
  ! Prepare the header
  hou%gil%dim(1) = npoints
  hou%gil%dim(2) = hin%gil%dim(3)
  hou%gil%dim(3) = 1
  hou%gil%ndim = 2
  hou%loca%size = hou%gil%dim(1)*hou%gil%dim(2)
  hou%char%code(2) = hin%char%code(3)
  hou%gil%yaxi = 3
  hou%gil%faxi = 2
  hou%char%code(3) = 'ANGLE'
  !
  hou%gil%convert(:,2) = hin%gil%convert(:,3)
  !
  user1 = (lgu(1)-hin%gil%ref(1))*hin%gil%inc(1) + hin%gil%val(1)
  user2 = (mgu(1)-hin%gil%ref(2))*hin%gil%inc(2) + hin%gil%val(2)
  !
  if (axe.ne.0) then
    hou%char%code(1) = hin%char%code(axe)
    hou%gil%inc(1) =  dd*hin%gil%inc(axe)
    hou%gil%xaxi = hin%gil%xaxi
    hou%gil%val(1) = 0.
    !
    ! Here we would like to put the other axis information as 3rd
    ! degenerate axis
    hou%char%code(3) = hin%char%code(3-axe)
    hou%gil%inc(3) =  hin%gil%inc(3-axe)
    hou%gil%ref(3) = hin%gil%ref(3-axe)
  else
    hou%char%code(1) = 'ANGLE'
    hou%gil%xaxi = 1
    hou%gil%pang = ang
    ! The pixel size is also different - pixels have orthogonal sides,
    ! and this is the hypotenuse of the right-angled triangle.
    hou%gil%inc(1) = sqrt((dx*hin%gil%inc(1))**2 + (dy*hin%gil%inc(2))**2)
    if (abs(dx).gt.abs(dy)) then
      if (dx.lt.0) hou%gil%inc(1) = -hou%gil%inc(1)
    else
      if (dy.lt.0) hou%gil%inc(1) = -hou%gil%inc(1)
    endif
    !
    hou%gil%ref(3) = 1.0
    hou%gil%val(3) = sqrt(AA**2+bb**2)  ! Distance to (0,0) 
    hou%gil%inc(3) = hou%gil%inc(1)
    hou%gil%pang = ang
  endif
  !
  ! First axis
  hou%gil%val(1) = 0.0
  ! But now, we have our Reference pixel that has an X value of
  ! AA and an YY value of BB - We take the most precise
  if (abs(dx).gt.abs(dy)) then
    hou%gil%ref(1) = (AA-user1)/(hin%gil%inc(1)*dx) + 1.0
  else
    hou%gil%ref(1) = (BB-user2)/(hin%gil%inc(2)*dy) + 1.0
  endif
  !
  hou%gil%ndim = 3
  hou%gil%dim(3) = 1
  hou%gil%extr_words = 0
  !
  ! Allocate the data
  allocate(slice_data(hou%gil%dim(1),hou%gil%dim(2)), stat=ier)
  if (ier.ne.0) then
    call map_message(seve%e,rname,'Output memory allocation error')
    error = .true.
    return
  endif
  hou%r2d => slice_data
  !
  ! Compute the slice
  call do_sliceb(hin%r3d, hin%gil%dim(1), hin%gil%dim(2), hin%gil%dim(3),   &
   &      lgu, mgu, hou%r2d, npoints, hin%gil%bval, hin%gil%eval)
  hou%gil%eval = max(hin%gil%eval,0.)
  !
end subroutine slice_sub
!
subroutine do_sliceb(in, nx, ny, nc, x, y, out, np, blank, eblank)
  use gildas_def
  !---------------------------------------------------------------------
  ! @ public
  !*
  ! IMAGER -- Support routine for command SLICE
  !
  !   Arbitrary slice in a 3-D data set, using bilinear interpolation
  !   Compute the slice, with blanking
  !!
  !---------------------------------------------------------------------  
  integer(kind=index_length), intent(in) :: nx    !! Number of X pixels
  integer(kind=index_length), intent(in) :: ny    !! Number of Y pixels
  integer(kind=index_length), intent(in) :: nc    !! Number of channels
  real, intent(in) :: in(nx,ny,nc)                !! Input cube
  integer :: np                                   !! Number of points
  real, intent(in) :: x(np)                       !! X coordinates
  real, intent(in) :: y(np)                       !! Y coordinates
  real, intent(out) :: out(np,nc)                 !! Output slice
  real, intent(in) :: blank                       !! Blanking
  real, intent(in) :: eblank                      !! and tolerance
  !
  ! Local ---
  real :: dx,dy,coeff(4),weight
  integer :: ic,n,i,j
  !
  if (eblank.lt.0.) then
    do n=1,np
      i = int(x(n))
      j = int(y(n))
      if((i.lt.1).or.(j.lt.1).or.(i.ge.nx).or.(j.ge.ny))then
        !              Interpolated point outside input image
        out(n, 1:nc) = blank
      else
        dx = x(n) - float(i)
        dy = y(n) - float(j)
        do ic=1,nc
              out(n,ic) = dx * dy * in(i+1, j+1, ic)   &
           &          + (1.0 - dx) * dy * in(i, j+1, ic)   &
           &          + (1.0 - dx) * (1.0 - dy) * in(i, j, ic)   &
           &          + dx * (1.0 - dy) * in(i+1, j, ic)
        enddo
      endif
    enddo
  else  
    do n=1,np
      i = int(x(n))
      j = int(y(n))
      if((i.lt.1).or.(j.lt.1).or.(i.ge.nx).or.(j.ge.ny))then
        !             Interpolated point outside input image
        out(n, 1:nc) = blank
      else
        dx = x(n) - float(i)
        dy = y(n) - float(j)
        do ic=1,nc
          coeff(1:4) = 1.0
          if (abs(in(i, j, ic)-blank).le.eblank) then
            coeff(1) = 0.
          else
            coeff(1) = (1.0 - dx) * (1.0 - dy)
          endif
          if (abs(in(i+1, j, ic)-blank).le.eblank) then
            coeff(2) = 0.
          else
            coeff(2) = dx * (1.0 - dy) 
          endif
          if (abs(in(i, j+1, ic)-blank).le.eblank) then
            coeff(3) = 0. 
          else
            coeff(3) = (1.0 - dx) * dy
          endif
          if (abs(in(i+1, j+1, ic)-blank).le.eblank) then
            coeff(4) = 0.
          else
            coeff(4) = dx * dy
          endif
          weight = sum(coeff)
          if (weight.gt.0) then
            weight = 1.0/weight
            out(n,ic) =   weight * ( & 
         &          coeff(1) * in(i, j, ic)   +  &
         &          coeff(2) * in(i+1, j, ic) +  &
         &          coeff(3) * in(i, j+1, ic) +  &
         &          coeff(4) * in(i+1, j+1, ic) ) 
          else
            out(n,ic) = blank
          endif
        enddo
      endif
    enddo
  endif
end subroutine do_sliceb
!
subroutine fill_gu(ipgu, ds, dt, np)
  ! @ private
  !! IMAGER - Utility routine: Fill a real grid
  integer, intent(in) :: np                        !! Number of points
  real, intent(out) :: ipgu(np)                    !! Output grid
  real(8), intent(in) :: ds                        !! Starting value
  real(8), intent(in) :: dt                        !! Step
  !
  ! Local ---
  integer :: n
  real(8) :: t
  !
  ! Code ----
  t = ds
  do n=1,np
    ipgu(n) = t
    t = t + dt
  enddo
end subroutine fill_gu
!
!
function pix_axis (head, user, iaxis)
  use image_def
  ! @ private
  !! IMAGER -- Utility routine: Get pixel corresponding to a 
  !!! user coordinate along the specified axis.
  real(8), intent(in) :: user         !! User coordinates
  type(gildas), intent(in) :: head    !! Image header
  integer, intent(in) :: iaxis        !! Axis
  integer :: pix_axis ! intent(out)   !! corresponding pixel 
  !
  ! Test error...
  if ((iaxis.lt.1).or.(iaxis.gt.gdf_maxdims)) then
    pix_axis = 0
  else
    pix_axis = nint( (user - head%gil%val(iaxis)) /  &
        head%gil%inc(iaxis) + head%gil%ref(iaxis) )
  endif
end function pix_axis
!
subroutine sub_extract(a,na1,na2,na3,na4,   &
     &    b,nb1,nb2,nb3,nb4,ni,nu,np,blank)
  use gildas_def
  ! @ private
  !! IMAGER -- Utility routine: 4-D extraction
  integer(kind=index_length) :: na1                    !
  integer(kind=index_length) :: na2                    !
  integer(kind=index_length) :: na3                    !
  integer(kind=index_length) :: na4                    !
  real, intent(in) :: a(na1,na2,na3,na4)               !
  integer(kind=index_length) :: nb1                    !
  integer(kind=index_length) :: nb2                    !
  integer(kind=index_length) :: nb3                    !
  integer(kind=index_length) :: nb4                    !
  real, intent(inout) :: b(nb1,nb2,nb3,nb4)            !
  integer(kind=index_length) :: ni(4)                  !
  integer(kind=index_length) :: nu(4)                  !
  integer(kind=index_length) :: np(4)                  !
  real, intent(in) :: blank                            !
  ! Local
  integer :: ia,ja,ka,la, ib,jb,kb,lb
  !
  do lb=1,nb4
    la = lb+ni(4)-np(4)
    if (la.ge.ni(4) .and. la.le.nu(4)) then
      do kb=1,nb3
        ka = kb+ni(3)-np(3)
        if (ka.ge.ni(3) .and. ka.le.nu(3)) then
          do jb=1,nb2
            ja = jb+ni(2)-np(2)
            if (ja.ge.ni(2) .and. ja.le.nu(2)) then
              do ib=1,nb1
                ia = ib+ni(1)-np(1)
                if (ia.ge.ni(1) .and. ia.le.nu(1)) then
                  b(ib,jb,kb,lb) = a(ia,ja,ka,la)
                else
                  b(ib,jb,kb,lb) = blank
                endif
              enddo
            else
              do ib=1,nb1
                b(ib,jb,kb,lb) = blank
              enddo
            endif
          enddo
        else
          do jb=1,nb2
            do ib=1,nb1
              b(ib,jb,kb,lb) = blank
            enddo
          enddo
        endif
      enddo
    else
      do kb=1,nb3
        do jb=1,nb2
          do ib=1,nb1
            b(ib,jb,kb,lb) = blank
          enddo
        enddo
      enddo
    endif
  enddo
end subroutine sub_extract 
!
subroutine parabola_3pt8(x,y,aa,bb,cc) 
  !----------------------------------------------------------------------
  ! @ private
  !* 
  ! IMAGER -- Utility routine  
  !	Solve for Y = aa*x^2 + bb*x + cc with 3 points input data
  !!
  !----------------------------------------------------------------------
  real(8), intent(in) :: x(3)  !! Abscissa
  real(8), intent(in) :: y(3)  !! Ordinate
  real(8), intent(out) :: cc,bb,aa  !! 3rd order polynom coefficients
  !
  aa = (y(3)-y(2))*(x(2)-x(1))-(y(2)-y(1))*(x(3)-x(2))
  bb = (x(2)-x(1))*(x(3)*x(3)-x(2)*x(2))-(x(2)*x(2)-x(1)*x(1))*(x(3)-x(2))
  aa = aa/bb
  bb = (y(2)-y(1))-aa*(x(2)*x(2)-x(1)*x(1))
  bb = bb/(x(2)-x(1))
  cc = y(1)-aa*x(1)*x(1)-bb*x(1)
end subroutine parabola_3pt8
