!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubemain_aperture
  use cubetools_structure
  use cube_types
  use cubeadm_cubeid_types
  use cubeadm_cubeprod_types
  use cubemain_range
  use cubemain_windowing
  use cubemain_messaging
  use cubemain_spaelli_types
  use cubetopology_spapos_types
  !
  public :: aperture
  private
  !
  type :: aperture_comm_t
     type(option_t),     pointer :: comm
     type(cubeid_arg_t), pointer :: cube
     type(range_opt_t)           :: range
     type(option_t),     pointer :: sum
     type(option_t),     pointer :: mean
     type(ellipse_opt_t)         :: size
     type(spapos_comm_t)         :: center
     type(cube_prod_t),  pointer :: aperture
   contains
     procedure, public  :: register     => cubemain_aperture_register
     procedure, private :: parse        => cubemain_aperture_parse
     procedure, private :: main         => cubemain_aperture_main
  end type aperture_comm_t
  type(aperture_comm_t) :: aperture
  !
  type aperture_user_t
     type(cubeid_user_t)    :: cubeids           ! Input Cube
     type(range_array_t)    :: range             ! range
     character(len=argu_l)  :: wei               ! Weight scheme
     logical                :: domean  = .false. ! Output is a mean spectrum
     logical                :: dosum   = .false. ! Output is a sum spectrum
     type(ellipse_user_t)   :: size              ! Aperture size
     type(spapos_user_t)    :: center            ! Aperture center
   contains
     procedure, private :: toprog => cubemain_aperture_user_toprog
  end type aperture_user_t
  type aperture_prog_t
     type(window_array_t) :: wind               ! Window to be spectrally apertureed
     type(cube_t),pointer :: cube               ! Input cube
     type(cube_t),pointer :: aperture           ! Output spectrum
     type(ellipse_prog_t) :: size               ! Aperture size
     type(spapos_prog_t)  :: center             ! Aperture center
     logical              :: domean = .false.   ! Output is a mean spectrum
  end type aperture_prog_t
  !
contains
  !
  subroutine cubemain_aperture_command(line,error)
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    character(len=*), intent(in)    :: line
    logical,          intent(inout) :: error
    !
    type(aperture_user_t) :: user
    character(len=*), parameter :: rname='APERTURE>COMMAND'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    call aperture%parse(line,user,error)
    if (error) return
    call aperture%main(user,error)
    if (error) continue
  end subroutine cubemain_aperture_command
  !
  !----------------------------------------------------------------------
  !
  subroutine cubemain_aperture_register(aperture,error)
    use cubedag_allflags
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(aperture_comm_t), intent(inout) :: aperture
    logical,                intent(inout) :: error
    !
    type(cubeid_arg_t) :: cubearg
    type(cube_prod_t) :: oucube
    character(len=*), parameter :: comm_abstract = &
         'Stack spectra within an Aperture'
    character(len=*), parameter :: comm_help = &
         'By default the Aperture has the size and shape of the beam&
         & and is centered at the projection center, this can be&
         & changed by using options /CENTER and /SIZE. The aperture&
         & can be compute either as a mean (/MEAN) or a sum (/SUM),&
         & if not specified the program will choose which case base&
         & on the input cube unit. If it is in K (Tmb), the aperture&
         & will be a mean in K (Tmb) and if it is in Jy/beam the&
         & aperture will be a sum in Jy.'
    !
    character(len=*), parameter :: rname='APERTURE>REGISTER'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    call cubetools_register_command(&
         'APERTURE','[cube]',&
         comm_abstract,&
         comm_help,&
         cubemain_aperture_command,&
         aperture%comm,error)
    if (error) return
    call cubearg%register( &
         'CUBE', &
         'Signal cube',  &
         strg_id,&
         code_arg_optional,  &
         [flag_cube], &
         code_read, &
         code_access_imaset, &
         aperture%cube, &
         error)
    if (error) return
    !
    call aperture%range%register(&
         'RANGE',&
         'Define the velocity range(s) over which to compute aperture',&
         range_is_multiple,error)
    if (error) return
    !
    call aperture%center%register(&
         'CENTER',&
         'Define aperture center',&
         error)
    if (error) return
    !
    call aperture%size%register(&
         'SIZE',&
         'Define aperture size',&
         error)
    if (error) return
    !
    call cubetools_register_option(&
         'SUM','',&
         'Aperture is a sum',&
         'Output unit is Jy',&
         aperture%sum,error)
    if (error) return
    !
    call cubetools_register_option(&
         'MEAN','',&
         'Aperture is a mean',&
         'Output unit is K(Tmb)',&
         aperture%mean,error)
    if (error) return
    !
    ! Product
    call oucube%register(&
         'APERTURE',&
         'The aperture spectrum',&
         strg_id,&
         [flag_aperture,flag_spectrum],&
         aperture%aperture,&
         error,&
         access=code_access_imaset)
    if (error) return
  end subroutine cubemain_aperture_register
  !
  subroutine cubemain_aperture_parse(aperture,line,user,error)
    use gkernel_interfaces
    !----------------------------------------------------------------------
    ! APERTURE 
    !----------------------------------------------------------------------
    class(aperture_comm_t), intent(in)    :: aperture
    character(len=*),       intent(in)    :: line
    type(aperture_user_t),  intent(out)   :: user
    logical,                intent(inout) :: error
    !
    logical :: dorange,domean,dosum
    character(len=*), parameter :: rname='APERTURE>PARSE'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    call cubeadm_cubeid_parse(line,aperture%comm,user%cubeids,error)
    if (error) return
    call aperture%range%parse(line,dorange,user%range,error)
    if (error) return
    call aperture%center%parse(line,user%center,error)
    if (error) return
    call aperture%size%parse(line,user%size,error)
    if (error) return
    !
    call aperture%mean%present(line,domean,error)
    if (error) return
    call aperture%sum%present(line,dosum,error)
    if (error) return
    !
    if (domean.and.dosum)then
       call cubemain_message(seve%e,rname,'Options /MEAN and /SUM are incompatible')
       error = .true.
       return
    else if (dosum) then
       user%domean = .false.
       user%dosum  = .true.
    else if (domean) then
       user%domean = .true.
       user%dosum  = .false.
    else
       user%domean = .false.
       user%dosum  = .false.
    endif
  end subroutine cubemain_aperture_parse
  !
  subroutine cubemain_aperture_main(aperture,user,error)
    use cubemain_stack_spectral
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(aperture_comm_t), intent(in)    :: aperture
    type(aperture_user_t),  intent(in)    :: user
    logical,             intent(inout) :: error
    !
    type(aperture_prog_t) :: prog
    character(len=*), parameter :: rname='APERTURE>MAIN'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    call user%toprog(prog,error)
    if (error) return
    call cubemain_stack_spectral_aperture(prog%domean,prog%wind,prog%cube,&
         prog%center,prog%size,aperture%aperture,prog%aperture,error)
    if (error) return
  end subroutine cubemain_aperture_main
  !
  !----------------------------------------------------------------------
  !
  subroutine cubemain_aperture_user_toprog(user,prog,error)
    use cubeadm_get
    use cubemain_stack_spectral
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(aperture_user_t), intent(in)    :: user
    type(aperture_prog_t),  intent(inout) :: prog
    logical,                intent(inout) :: error
    !
    character(len=*), parameter :: rname='APERTURE>USER>TOPROG'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    call cubeadm_get_header(aperture%cube,user%cubeids,prog%cube,error)
    if (error) return
    call aperture%range%user2prog(prog%cube,user%range,prog%wind,error)
    if (error) return
    call user%center%toprog(prog%cube,prog%center,error)
    if (error) return
    call user%size%toprog(prog%cube,prog%size,error)
    if (error) return
    !
    if (.not.user%domean.and..not.user%dosum) then
       call cubemain_stack_spectral_domean(prog%cube,prog%domean,error)
       if (error) return
    else if (user%domean.and.user%dosum) then
       call cubemain_message(seve%e,rname,'User%domean and user%dosum are both true')
       error = .true.
       return
    else
       prog%domean = user%domean
    endif
    !
  end subroutine cubemain_aperture_user_toprog
end module cubemain_aperture
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
