subroutine map_continuum(line,error)
  use image_def
  use clean_def
  use clean_arrays
  use clean_types
  use gkernel_interfaces
  use imager_interfaces, except_this => map_continuum 
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  !   IMAGER
  !
  !   Support for MAP_CONTINUUM command
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: line  ! command line
  logical, intent(inout) :: error       ! logical error flag
  ! Local
  real(kind=8), parameter :: pi=3.14159265358979323846d0
  character(len=*), parameter :: rname='MAP_CONTINUUM'
  !! logical :: debug=.false.
  character(len=16) :: name
  character(len=80) :: chain
  integer :: n, nchan, ier
  integer(kind=index_length) :: nhist, mhist, dim(2)
  real :: clip_value 
  type(gildas) :: hmap
  real, allocatable, target, save :: spectrum(:,:)
  real :: xsize, ysize, factor
  integer :: imin,imax,jmin,jmax,i1,i2, box(4), nx,ny
  logical :: do_mask
  !
  call sic_delvariable('CONTINUUM',.false.,error)
  if (allocated(dcont)) deallocate(dcont)
  call sic_delvariable('CLIPPED',.false.,error)
  if (allocated(spectrum)) deallocate(spectrum)
  !
  error = .false.
  call gildas_null(hmap)
  call gildas_null(hcont)
  !
  name = 'CLEAN'
  call sic_ke(line,0,1,name,n,.false.,error)
  select case (name)
  case ('CLEAN')
    if (hclean%loca%size.eq.0) then
      call map_message(seve%e,rname,'No CLEAN data loaded')
      error = .true.
      return
    endif
    call gdf_copy_header(hclean,hmap,error)
    hmap%r3d => dclean
    ! Number of pixels per beam
    factor = abs(pi*hmap%gil%majo*hmap%gil%mino/hmap%gil%inc(1)/hmap%gil%inc(2))
  case ('SKY')
    if (hsky%loca%size.eq.0) then
      call map_message(seve%e,rname,'No SKY data loaded')
      error = .true.
      return
    endif
    call gdf_copy_header(hsky,hmap,error)
    hmap%r3d => dsky
    ! Number of pixels per beam
    factor = abs(pi*hmap%gil%majo*hmap%gil%mino/hmap%gil%inc(1)/hmap%gil%inc(2))
  case ('DIRTY')
    if (hdirty%loca%size.eq.0) then
      call map_message(seve%e,rname,'No DIRTY data loaded')
      error = .true.
      return
    endif
    call gdf_copy_header(hdirty,hmap,error)
    hmap%r3d => ddirty
    factor = 1.0
  case default
    call map_message(seve%e,rname,'Only work on CLEAN or DIRTY images')
    error = .true.
    return
  end select
  !
  ! Copy header to Continuum
  call gdf_copy_header(hmap,hcont,error)
  !
  ! Define continuum data
  hcont%gil%ndim = 2
  hcont%gil%dim(3) = 1
  allocate(dcont(hcont%gil%dim(1),hcont%gil%dim(2)), &
    &   spectrum(hmap%gil%dim(3),4),stat=ier)
  if (ier.ne.0) then
    call map_message(seve%e,rname,'Memory allocation error')
    error = .true.
    return
  endif
  hcont%r2d => dcont
  !
  clip_value = 2.5
  call sic_r4(line,0,2,clip_value,.false.,error)
  if (clip_value.lt.1.0 .or. clip_value.gt.5.0) then
    call map_message(seve%e,rname,'Clipping value outside of recommended [1-5] range')
    error = .true.
    return
  endif
  !
  nchan = hmap%gil%dim(3)
  !
  mhist = max(8,nint(sqrt(real(nchan))))
  mhist = min(mhist,32)
  nhist = max(8,mhist)
  call sic_i8(line,0,3,nhist,.false.,error) 
  if (nchan.lt.32) then
    write(chain,'(A,I0,A)') 'Too few channels [',nchan,'], display only'
    call map_message(seve%w,rname,chain)
    nhist = 1
  else if (nhist.lt.8 .or. nhist.gt.max(8,nchan/8)) then
    write(chain,'(A,I0,A)') 'Histogram size out of allowed range [8-',nchan/8,']'
    call map_message(seve%e,rname,chain)
    error = .true.
    return
  else if (nhist.gt.mhist)  then
    write(chain,'(A,I0,A)') 'Histogram size out of recommended range [8-',mhist,']'
    call map_message(seve%w,rname,chain)
  endif
  ! 
  !
  ! We use the mechanics of MASK and SUPPORT as in the STATISTIC command
  nx = hmap%gil%dim(1)
  ny = hmap%gil%dim(2)
  do_mask = user_method%do_mask
  !
  if (do_mask) then
    call copy_method(user_method,method)
    !
    if (.not.allocated(d_mask)) then
      allocate(d_mask(nx,ny),d_list(nx*ny),stat=ier)
      if (ier.ne.0) then
        call map_message(seve%e,rname,'Error getting support memory')
        error = .true.
        return
      endif
      method%do_mask = .true.
      method%nlist = 0
    endif
    box = [nx,ny,1,1] 
    call check_area(method,hmap,.true.) ! Needed ?
    call check_mask(method,hmap)
    box(1) = min(box(1),method%box(1))
    box(2) = min(box(2),method%box(2))
    box(3) = max(box(3),method%box(3))
    box(4) = max(box(4),method%box(4))
    call map_message(seve%i,rname,'Using current support')
    !
    call compute_continuum(hmap,hcont,spectrum,nhist,clip_value,error,box,d_mask)
    if (error) return  
  else
    !
    xsize = 0.
    ysize = 0.
    call sic_get_real('SIZE[1]',xsize,error)
    call sic_get_real('SIZE[2]',ysize,error)
    !
    if (xsize.eq.0. .and. ysize.eq.0.) then
      box = [1,1,nx,ny]
    else
      call map_message(seve%i,rname,'Using current SIZE')
      xsize = xsize*pi/180.d0/3600d0
      ysize = ysize*pi/180.d0/3600d0
      i1 = (-0.5*xsize-hmap%gil%val(1))/hmap%gil%inc(1) + hmap%gil%ref(1)
      i2 = (0.5*xsize-hmap%gil%val(1))/hmap%gil%inc(1) + hmap%gil%ref(1)
      imin = min(i1,i2)
      imax = max(i1,i2)
      imin = max(1,imin)
      i1 = (-0.5*ysize-hmap%gil%val(2))/hmap%gil%inc(2) + hmap%gil%ref(2)
      i2 = (0.5*ysize-hmap%gil%val(2))/hmap%gil%inc(2) + hmap%gil%ref(2)
      jmin = min(i1,i2)
      jmax = max(i1,i2)
      jmin = max(1,jmin)
      !
      imin = min(imin,hmap%gil%dim(1))
      imax = min(imax,hmap%gil%dim(1))
      jmin = min(jmin,hmap%gil%dim(2))
      jmax = min(jmax,hmap%gil%dim(2))
      !
      box(1) = imin
      box(2) = jmin
      box(3) = imax
      box(4) = jmax
    endif
    !
    call compute_continuum(hmap,hcont,spectrum,nhist,clip_value,error,box)
    if (error) return  
  endif
  !
  hcont%loca%addr = locwrd(hcont%r2d) 
  hcont%loca%size = hcont%gil%dim(1) * hcont%gil%dim(2)
  call gdf_get_extrema (hcont,error)
  !
  call sic_mapgildas('CONTINUUM',hcont,error,dcont)
  dim(1) = hmap%gil%dim(3)
  dim(2) = 4
  !
  ! Scale to Jy if possible (CLEAN data)
  Print *,'Normalizing by ',factor
  spectrum(:,2) = spectrum(:,2)/factor
  spectrum(:,3) = spectrum(:,3)/factor
  where(spectrum(:,4).ne.0) 
    spectrum(:,4) = 1.0
  end where
  call sic_def_real('CLIPPED',spectrum,2,dim,.false.,error)
  !
  call exec_program('@ p_continuum')   
  !
end subroutine map_continuum
!
subroutine compute_continuum(hmap,hcont,spectrum,nhist,clip_value,error,box,mask)
  use image_def
  use gbl_message
  use gkernel_interfaces
  use imager_interfaces, except_this => compute_continuum
  !---------------------------------------------------------------------
  ! @ public-mandatory
  !
  !   IMAGER
  !
  !     Support routine to derive the continuum image
  !   The method is to find a global set of windows (along 3rd axis)
  !   based on the mean spectrum in a selected region (defined by 
  !   a mask), and to compute the continuum as the average
  !   of the "line-free" channels outside of these windows. 
  !---------------------------------------------------------------------
  type(gildas), intent(in) :: hmap      ! Input data cube
  type(gildas), intent(inout) :: hcont  ! Output continuum image
  real, intent(out) :: spectrum(:,:)    ! Output spectrum
  integer(kind=index_length), intent(in) :: nhist ! Number of Histograms
  real, intent(in) :: clip_value        ! Clipping value
  logical, intent(out) :: error         ! Error flag
  integer(kind=4), intent(in) :: box(4) ! Bounding box of mask
  logical, intent(in), optional :: mask(:,:)  ! Optional mask
  !
  character(len=*), parameter :: rname='MAP_CONTINUUM'
  integer, allocatable :: mylines(:), oulines(:)
  real, pointer :: rmask(:,:)
  real :: blank, val
  integer(kind=index_length) :: nchan,kxy
  integer :: nx,ny,ix,iy,ier,ic,kc,ib,nb,inb,iextent
  logical :: debug=.false.
  !
  error = .false.
  !
  nchan = hmap%gil%dim(3)
  nx = hmap%gil%dim(1)
  ny = hmap%gil%dim(2)
  !
  allocate(mylines(nchan),oulines(nchan),stat=ier)
  if (ier.ne.0) then
    call map_message(seve%e,rname,'Memory allocation error')
    error = .true.
    return
  endif
  spectrum = 0.0
  do ic=1,nchan
    spectrum(ic,1) = (ic-hmap%gil%ref(3))*hmap%gil%vres + hmap%gil%voff
  enddo
  ! 
  if (hcont%gil%blan_words.ne.2 .or. hcont%gil%eval.lt.0) then
    !    
    ! We need to define a Blanking value outside of the range
    blank = minval(hmap%r3d)
    if (blank.gt.0) then
      hcont%gil%bval = -2.0*blank*nchan
      hcont%gil%eval = 0.0
    else if (blank.lt.0) then
      hcont%gil%bval = 3.0*blank*nchan
      hcont%gil%eval = 0.0
    else
      hcont%gil%bval = -1.0
      hcont%gil%eval = 0.0
    endif
  endif
  !
  ! Compute the mean spectrum
  !
  if (present(mask)) then
    !
    if (hmap%gil%eval.ge.0.0) then
      kxy = 0
      do iy=box(2),box(4)
        do ix=box(1),box(3)
          if (mask(ix,iy)) then
            kxy = kxy+1
            do ic=1,nchan
              val = hmap%r3d(ix,iy,ic)
              if (abs(val-hmap%gil%bval).gt.hmap%gil%eval) then
                spectrum(ic,2) = spectrum(ic,2) + val
              endif
            enddo
          endif
        enddo
      enddo
    else
      kxy = 0
      do iy=box(2),box(4)
        do ix=box(1),box(3)
          if (mask(ix,iy)) then
            kxy = kxy+1
            do ic=1,nchan
              spectrum(ic,2) = spectrum(ic,2) + hmap%r3d(ix,iy,ic)
            enddo
          endif
        enddo
      enddo
    endif
  else
    if (all(box.eq.0)) then
      kxy =nx*ny
      !
      do ic = 1,nchan
        call gr4_mean(hmap%r3d(:,:,ic),hmap%gil%dim(1)*hmap%gil%dim(2),  &
          & hmap%gil%bval,hmap%gil%eval,spectrum(ic,2)) 
      enddo
    else
      kxy =(box(4)-box(2)+1)*(box(3)-box(1)+1)
      !
      if (hmap%gil%eval.ge.0.0) then
        do ic=1,nchan
          do iy=box(2),box(4)
            do ix=box(1),box(3)
              val = hmap%r3d(ix,iy,ic)
              if (abs(val-hmap%gil%bval).gt.hmap%gil%eval) then
                spectrum(ic,2) = spectrum(ic,2) + val
              endif
            enddo
          enddo
        enddo
      else
        do ic=1,nchan
          do iy=box(2),box(4)
            do ix=box(1),box(3)
              spectrum(ic,2) = spectrum(ic,2) + hmap%r3d(ix,iy,ic)
            enddo
          enddo
        enddo
      endif
    endif
  endif
  !
  spectrum(:,3) = spectrum(:,2)
  !
  if (nhist.gt.1) then
    !
    ! Find out the line free regions
    call clip_lineregions(rname,spectrum(:,3),nchan,nhist,  &
      & hcont%gil%bval,hcont%gil%eval,clip_value,debug,0.0,1.0)
    nb = 0
    call guess_lineregions(spectrum(:,3),nchan,       &
      & hcont%gil%bval,hcont%gil%eval,            &
      & mylines,nb)
    !
    ! Expand line regions by continuity
    inb = nb
    iextent = 8
    call clip_expand(hmap%gil%dim(3),mylines,inb,oulines,nb,iextent)
    !
    ! These are the line-contaminated channels
    do ib=1,nb
      spectrum(oulines(ib),4) = 1
    enddo
  endif
  !
  ! Compute the continuum image 
  kc = 0
  do ic=1,nchan
    if (spectrum(ic,4).ne.0) cycle ! Skip the Line Contaminated channels
    kc = kc+1
    if (kc.eq.1) then
      hcont%r2d = hmap%r3d(:,:,ic)
    else
      rmask => hmap%r3d(:,:,ic)
      if (hmap%gil%eval.ge.0) then
        where ( (abs(rmask-hmap%gil%bval).gt.hmap%gil%eval).and. &
          & (abs(hcont%r2d-hmap%gil%bval).gt.hmap%gil%eval) ) &
          & hcont%r2d = hcont%r2d + rmask
      else
        hcont%r2d = hcont%r2d + rmask
      endif
    endif
  enddo
  !
  if (kc.ne.0) then
    where (abs(hcont%r2d-hcont%gil%bval).gt.hcont%gil%eval) hcont%r2d = hcont%r2d/kc
    hcont%gil%rms = hmap%gil%rms /sqrt(real(kc))
    hcont%gil%noise = hmap%gil%noise /sqrt(real(kc))
  endif
  !
  ! Return the number of pixels here. It will serve
  ! to normalize the spectrum after that.
  spectrum(:,4) = kxy*spectrum(:,4)
end subroutine compute_continuum
