!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubemain_luminosity_total_tool
  use cubetools_parameters
  use cube_types
  use cubemain_messaging
  use cubemain_windowing
  !
  public :: luminosity_total_prog_t
  private
  !
  type luminosity_total_prog_t
     type(window_array_t)  :: wind   ! Window(s) over which to compute luminosity 
     type(cube_t), pointer :: cube   ! Signal cube
     type(cube_t), pointer :: noise  ! Noise  cube
     real(kind=real_k) :: xco        ! [---] xco conversion factor
     real(kind=real_k) :: distance   ! [pc ] Distance to the source
     real(kind=dble_k) :: lumi       ! [K.km/s.pc^2] Source Luminosity 
     real(kind=dble_k) :: dlumi      ! [K.km/s.pc^2] luminosity error
     real(kind=dble_k) :: tvolu      ! [km/s.pc^2] Total Volume
     !
   contains
     procedure, public  :: total_header => cubemain_luminosity_total_prog_header
     procedure, public  :: total_data   => cubemain_luminosity_total_prog_data
     procedure, private :: total_list   => cubemain_luminosity_total_prog_list
  end type luminosity_total_prog_t
  !
contains
  !
  subroutine cubemain_luminosity_total_prog_header(prog,error)
    !----------------------------------------------------------------------
    ! 
    !----------------------------------------------------------------------
    class(luminosity_total_prog_t), intent(inout) :: prog
    logical,                        intent(inout) :: error
    !
    character(len=*), parameter :: rname='LUMINOSITY>TOTAL>PROG>HEADER'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
  end subroutine cubemain_luminosity_total_prog_header
  !
  subroutine cubemain_luminosity_total_prog_data(prog,error)
    use cubetools_nan
    use cubeadm_opened
    use cubeadm_entryloop
    use cubemain_image_real
    !----------------------------------------------------------------------
    ! 
    !----------------------------------------------------------------------
    class(luminosity_total_prog_t), intent(inout) :: prog
    logical,                        intent(inout) :: error
    !
    integer(kind=entr_k) :: ie
    integer(kind=wind_k) :: iw
    integer(kind=pixe_k) :: ix,iy
    integer(kind=long_k) :: ngood
    type(image_t) :: signal,noise
    type(cubeadm_iterator_t) :: iter
    character(len=*), parameter :: rname='LUMINOSITY>TOTAL>PROG>DATA'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    call signal%init(prog%cube,error)
    if (error) return
    call noise%init(prog%noise,error)
    if (error) return
    !
    prog%tvolu = 0d0
    prog%lumi = 0d0
    prog%dlumi = 0d0
    !
    call cubeadm_datainit_all(iter,error)
    if (error) return
    do while (cubeadm_dataiterate_all(iter,error))
       if (error) return
       do ie=iter%first,iter%last
          call cubeadm_entryloop_iterate(ie,error)
          if (error) return
          do iw=1,prog%wind%n
             if ((prog%wind%val(iw)%o(1).le.ie).and.(ie.le.prog%wind%val(iw)%o(2))) then
                call signal%get(prog%cube,ie,error)
                if (error) return
                call noise%get(prog%noise,ie,error)
                if (error) return
                ngood = 0
                do iy=1,signal%ny
                   do ix=1,signal%nx
                      if ((.not.ieee_is_nan(noise%z(ix,iy))).and.(.not.ieee_is_nan(signal%z(ix,iy)))) then
                         ngood = ngood+1
                         prog%lumi = prog%lumi+signal%z(ix,iy)
                         prog%dlumi = prog%dlumi+noise%z(ix,iy)
                      endif
                   enddo ! ix
                enddo ! iy
                if (ngood.ge.1) then
                   prog%tvolu = prog%tvolu+real(ngood)
                endif
             endif ! Not NaN?
          enddo ! iw
       enddo ! ie
    enddo
    !
    call prog%total_list(error)
    if (error) return
  end subroutine cubemain_luminosity_total_prog_data
  !
  subroutine cubemain_luminosity_total_prog_list(prog,error)
    use phys_const
    use cubetools_header_methods
    use cubetools_beam_types
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(luminosity_total_prog_t), intent(inout) :: prog
    logical,                        intent(inout) :: error
    !
    integer(kind=chan_k) :: nf
    integer(kind=wind_k) :: iw
    real(kind=8) :: pixel_volume,total_surface,total_volume
    real(kind=8) :: xco_msolpspc,pc_per_sec,points_per_beam
    real(kind=8) :: luminosity,mass
    real(kind=8) :: dluminosity,dmass
    real(kind=coor_k) :: xres,yres,vres,vrange(2)
    real(kind=8), parameter :: sec_per_pc_per_dist = 206265
    type(beam_t) :: beam
    character(len=mess_l) :: mess
    character(len=*), parameter :: rname='LUMINOSITY>TOTAL>PROG>LIST'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    nf   = prog%cube%head%arr%n%c
    xres = prog%cube%head%spa%l%inc
    yres = prog%cube%head%spa%m%inc
    vres = prog%cube%head%spe%inc%v
    !
    call cubetools_header_get_spabeam(prog%cube%head,beam,error)
    if (error) return
    !
    pixel_volume = abs(xres*yres*vres)
    if (pixel_volume.eq.0d0) then
       call cubemain_message(seve%e,rname,'Pixel volume is zero valued')
       error=.true.
       return
    endif
    !
    pc_per_sec = prog%distance/sec_per_pc_per_dist ! pc
    pixel_volume = pixel_volume*(pc_per_sec*sec_per_rad)**2 ! km/s.pc^2
    !
    xco_msolpspc = prog%xco/4.6e19 ! Msol pc^-2 / (K.km/s)
    points_per_beam = abs((2*pi*beam%major*beam%minor)/(8d0*log(2d0)*xres*yres))
    !
    total_volume = prog%tvolu*pixel_volume
    luminosity = prog%lumi*pixel_volume
    dluminosity = sqrt(prog%dlumi/points_per_beam)*pixel_volume
    mass = luminosity*xco_msolpspc
    dmass = dluminosity*xco_msolpspc
    !
    write(mess,'(a,1pg12.4)')   '  Points per beam:      ',points_per_beam
    call cubemain_message(seve%r,rname,mess)
    write(mess,'(a,1pg12.4,a)') '  X factor:             ',prog%xco,' (H2/cm^2) / (K.km/s)'
    call cubemain_message(seve%r,rname,mess)
    write(mess,'(a,1pg12.4,a)') '  X factor:             ',xco_msolpspc,' (Msol/pc^2) / (K.km/s)'
    call cubemain_message(seve%r,rname,mess)
    write(mess,'(a,1pg12.4,a)') '  Distance:             ',prog%distance,' pc'
    call cubemain_message(seve%r,rname,mess)
    write(mess,'(a,1pg12.4,a)') '  Linear size:          ',pc_per_sec,' pc/arcsec'
    call cubemain_message(seve%r,rname,mess)
    write(mess,'(a,1pg12.4,a,1pg12.4,a,1pg12.4,a)') '  Pixel volume:         ',  &
         abs(xres)*sec_per_rad,'" x ',abs(yres)*sec_per_rad,'" x ',&
         abs(vres),'km/s'
    call cubemain_message(seve%r,rname,mess)
    write(mess,'(a,1pg12.4,a)') '  Pixel volume:         ',pixel_volume,' km/s.pc^2'
    call cubemain_message(seve%r,rname,mess)
    nf = 0
    do iw=1,prog%wind%n
       nf = nf+prog%wind%val(iw)%nc
       call prog%wind%val(iw)%chan2velo(vrange,error)
       if (error) return
       write(mess,'(a,i0,a,f9.2,a,f9.2,a)') '  Velocity range #',iw,':      [',vrange(1),',',vrange(2),'] km/s'
       call cubemain_message(seve%r,rname,mess)
    enddo ! iw
    total_surface = total_volume/abs(nf*vres)
    write(mess,'(a,1pg12.4,a,1pg12.4,a)') '  Total volume:         ',total_volume,&
         ' km/s.pc^2 or ',total_volume/pixel_volume,' voxels'
    call cubemain_message(seve%r,rname,mess)
    write(mess,'(a,1pg12.4,a,1pg12.4,a)') '  Total surface:        ',total_surface,' pc^2      or ',  &
         total_surface/(pc_per_sec*60)**2,' arcmin^2'
    call cubemain_message(seve%r,rname,mess)
    write(mess,'(a,1pg12.4,a,1pg12.4,a)') '  Total luminosity:     ',luminosity,' +/- ',&
         dluminosity,' K.km/s.pc^2'
    call cubemain_message(seve%r,rname,mess)
    write(mess,'(a,1pg12.4,a,1pg12.4,a)') '  Total mass:           ',mass,' +/- ',dmass,' Msol'
    call cubemain_message(seve%r,rname,mess)
    write(mess,'(a,1pg12.4,a,1pg12.4,a)') '  Mean brightness:      ',luminosity/total_surface,' +/- ',  &
         dluminosity/total_surface,' K.km/s'
    call cubemain_message(seve%r,rname,mess)
    write(mess,'(a,1pg12.4,a,1pg12.4,a)') '  Mass surface density: ',mass/total_surface,&
         ' +/- ',dmass/total_surface,' Msol/pc^2'
    call cubemain_message(seve%r,rname,mess)
  end subroutine cubemain_luminosity_total_prog_list
end module cubemain_luminosity_total_tool
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubemain_luminosity_labeled_tool
  use cubetools_parameters
  use cube_types
  use cubemain_messaging
  use cubemain_windowing
  use cubemain_luminosity_total_tool
  !
  public :: luminosity_labeled_prog_t
  private
  !
  type, extends(luminosity_total_prog_t) :: luminosity_labeled_prog_t
     type(cube_t), pointer :: labeled    ! Labeled cube
     type(cube_t), pointer :: luminosity ! Luminosity per island
     logical :: uselabel = .true.
     real(kind=sign_k), allocatable :: sum(:)
   contains
     procedure, public  :: labeled_header => cubemain_luminosity_labeled_prog_header
     procedure, public  :: labeled_data   => cubemain_luminosity_labeled_prog_data
     procedure, private :: labeled_act    => cubemain_luminosity_labeled_prog_act
     procedure, private :: labeled_output => cubemain_luminosity_labeled_prog_output
  end type luminosity_labeled_prog_t
  !
contains
  !
  subroutine cubemain_luminosity_labeled_prog_header(prog,error)
    use cubetools_unit
    use cubetools_axis_types
    use cubetools_arrelt_types
    use cubetools_header_methods
    use cubedag_allflags
    use cubeadm_clone
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(luminosity_labeled_prog_t), intent(inout) :: prog
    logical,                          intent(inout) :: error
    !
    type(axis_t) :: axis
    type(arrelt_t) :: min,max
    character(len=*), parameter :: rname='LUMINOSITY>LABELED>PROG>HEADER'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    call cubeadm_clone_header(prog%labeled,flag_luminosity,prog%luminosity,error,access=code_cube_speset)
    if (error) return
    call cubetools_header_nullify_axset_l(prog%luminosity%head,error)
    if (error) return
    call cubetools_header_nullify_axset_m(prog%luminosity%head,error)
    if (error) return
    call cubetools_header_get_array_minmax(prog%luminosity%head,min,max,error)
    if (error) return
    call cubetools_header_get_axis_head_c(prog%luminosity%head,axis,error)
    if (error) return
    axis%name = 'Label'
    axis%unit = 'Integer'
    axis%kind = code_unit_unk
    axis%genuine = .true.
    axis%regular = .true.
    axis%ref = 1.0
    axis%val = 1.0
    axis%inc = 1.0
    axis%n = max%val
    call cubetools_header_update_axset_c(axis,prog%luminosity%head,error)
    if (error) return
  end subroutine cubemain_luminosity_labeled_prog_header
  !
  subroutine cubemain_luminosity_labeled_prog_data(prog,error)
    use gkernel_interfaces
    use cubeadm_opened
    use cubeadm_entryloop
    use cubemain_image_real
    !----------------------------------------------------------------------
    ! Unclear whether this operation can be easily parallelized
    !----------------------------------------------------------------------
    class(luminosity_labeled_prog_t), intent(inout) :: prog
    logical,                          intent(inout) :: error
    !
    integer(kind=entr_k) :: ie
    integer(kind=4) :: ier
    type(image_t) :: signal,label
    type(cubeadm_iterator_t) :: iter
    character(len=*), parameter :: rname='LUMINOSITY>LABELED>PROG>DATA'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    call signal%init(prog%cube,error)
    if (error) return
    call label%init(prog%labeled,error)
    if (error) return
    allocate(prog%sum(prog%luminosity%head%arr%n%c),stat=ier)
    if (failed_allocate(rname,'Sum array',ier,error)) return
    prog%sum(:) = 0.0
    !
    call cubeadm_datainit_all(iter,error)
    if (error) return
    do while (cubeadm_dataiterate_all(iter,error))
       do ie=iter%first,iter%last
          call cubeadm_entryloop_iterate(ie,error)
          if (error) return
          call prog%labeled_act(ie,signal,label,prog%sum,error)
          if (error) return
       enddo ! ie
    enddo
    !
    call prog%labeled_output(error)
    if (error) return
  end subroutine cubemain_luminosity_labeled_prog_data
  !   
  subroutine cubemain_luminosity_labeled_prog_act(prog,ie,signal,label,sum,error)
    use cubetools_nan
    use cubemain_image_real
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(luminosity_labeled_prog_t), intent(inout) :: prog
    integer(kind=entr_k),             intent(in)    :: ie
    type(image_t),                    intent(inout) :: signal
    type(image_t),                    intent(inout) :: label
    real(kind=sign_k),                intent(inout) :: sum(:)
    logical,                          intent(inout) :: error
    !
    integer(kind=indx_k) :: il,nl
    integer(kind=pixe_k) :: ix,iy
    character(len=*), parameter :: rname='LUMINOSITY>LABELED>PROG>ACT'
    !
    nl = ubound(sum,1)
    call signal%get(prog%cube,ie,error)
    if (error) return
    call label%get(prog%labeled,ie,error)
    if (error) return
    do iy=1,signal%ny
       do ix=1,signal%nx
          if (.not.ieee_is_nan(signal%z(ix,iy))) then
             il = label%z(ix,iy)
             if ((0.lt.il).and.(il.le.nl)) then
                sum(il) = sum(il)+signal%z(ix,iy)
             else
                print *,ix,iy,il,nl
             endif ! Inside [1,nl]?
          endif ! Not NaN?
       enddo ! ix
    enddo ! iy
  end subroutine cubemain_luminosity_labeled_prog_act
  !
  subroutine cubemain_luminosity_labeled_prog_output(prog,error)
    use cubeadm_ioloop
    use cubemain_spectrum_real
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(luminosity_labeled_prog_t), intent(inout) :: prog
    logical,                          intent(inout) :: error
    !
    type(spectrum_t) :: luminosity
    integer(kind=indx_k) :: il,nl
    integer(kind=chan_k), parameter :: one = 1
    character(len=*), parameter :: rname='LUMINOSITY>LABELED>OUTPUT'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    call luminosity%reallocate('luminosity',prog%luminosity%head%arr%n%c,error)
    if(error) return
    call cubeadm_io_iterate(one,one,prog%luminosity,error)
    if (error) return
    nl = ubound(prog%sum,1)
    luminosity%t(1) = prog%sum(nl)
    do il=1,nl-1
       luminosity%t(il+1) = luminosity%t(il)+prog%sum(nl-il)
    enddo ! il
    call luminosity%put(prog%luminosity,one,error)
    if (error) return
  end subroutine cubemain_luminosity_labeled_prog_output
end module cubemain_luminosity_labeled_tool
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubemain_luminosity
  use cubetools_structure
  use cubetools_keyword_arg
  use cubeadm_cubeid_types
  use cubemain_messaging
  use cubemain_range
  use cubemain_auxiliary_types
  use cubemain_luminosity_labeled_tool
  !
  public :: luminosity
  public :: cubemain_luminosity_command
  private
  !
  real(kind=4), parameter :: galxco = 2e20
  !
  type :: luminosity_comm_t
     type(option_t),      pointer :: comm
     type(option_t),      pointer :: dist
     type(keyword_arg_t), pointer :: dist_unit
     type(option_t),      pointer :: xco
     type(auxiliary_opt_t) :: labeled
     type(range_opt_t)     :: range     
   contains
     procedure, public  :: register       => cubemain_luminosity_register
     procedure, private :: parse          => cubemain_luminosity_parse
     procedure, private :: parse_distance => cubemain_luminosity_parse_distance
     procedure, private :: parse_xval     => cubemain_luminosity_parse_xval
     procedure, private :: main           => cubemain_luminosity_main
  end type luminosity_comm_t
  type(luminosity_comm_t) :: luminosity
  !
  integer(kind=4), parameter :: icube  = 1
  integer(kind=4), parameter :: inoise = 2
  type luminosity_user_t
     type(cubeid_user_t)    :: cubeids
     type(auxiliary_user_t) :: labeled
     type(range_array_t)    :: range             ! Range(s) over which to compute luminosity 
     logical                :: dorange = .false. ! Was option /RANGE present 
     real(kind=real_k)      :: xco = -1.         ! [---] User xco conversion factor    
     real(kind=real_k)      :: distance          ! [pc ] Distance to the source
   contains
     procedure, private :: toprog => cubemain_luminosity_user_toprog
  end type luminosity_user_t
  !
contains
  !
  subroutine cubemain_luminosity_command(line,error)
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    character(len=*), intent(in)    :: line
    logical,          intent(inout) :: error
    !
    type(luminosity_user_t) :: user
    character(len=*), parameter :: rname='LUMINOSITY>COMMAND'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    call luminosity%parse(line,user,error)
    if (error) return
    call luminosity%main(user,error)
    if (error) continue
  end subroutine cubemain_luminosity_command
  !
  !----------------------------------------------------------------------
  !
  subroutine cubemain_luminosity_register(luminosity,error)
    use cubedag_allflags
    use cubetools_unit
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(luminosity_comm_t), intent(inout) :: luminosity
    logical,                  intent(inout) :: error
    !
    type(cubeid_arg_t) :: cubearg
    type(keyword_arg_t) :: keyarg
    type(standard_arg_t) :: stdarg
    character(len=*), parameter :: comm_abstract = &
         'Compute the total luminosity of a cube'
    character(len=*), parameter :: comm_help = &
         'The distance to the source must be given. By default&
         & LUMINOSITY uses the Galactic CO to H2 conversion factor&
         & (2e20 (H2.cm-2) / (K.km/s)) this can be changed by using&
         & of option /X.'
    character(len=*), parameter :: rname='LUMINOSITY>REGISTER'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    call cubetools_register_command(&
         'LUMINOSITY','[cube]',&
         comm_abstract,&
         comm_help,&
         cubemain_luminosity_command,&
         luminosity%comm,error)
    if (error) return
    call cubearg%register( &
         'CUBE', &
         'Input cube',  &
         strg_id,&
         code_arg_optional,  &
         [flag_cube], &
         error)
    if (error) return
    call cubearg%register( &
         'NOISE', &
         'Noise measurement',  &
         strg_id,&
         code_arg_optional,  &
         [flag_noise], &
         error)
    if (error) return
    !
    call luminosity%labeled%register(&
         'SEGMENTS','[cubeid]',&
         'Compute the luminosity per SNR segment',strg_id,&
         'SEGMENTS','Cube of segment labels',&
         [flag_segments],&
         code_arg_optional, &
         error)
    if (error) return
    !
    call luminosity%range%register('RANGE',&
         'Define the velocity range(s) over which to compute luminosity',&
         range_is_multiple,error)
    if (error) return
    !
    call cubetools_register_option(&
         'DISTANCE','dist [unit]',&
         'Define the distance do the source',&
         strg_id,&
         luminosity%dist,error)
    if (error) return
    call stdarg%register( &
         'dist',  &
         'Distance to the source', &
         strg_id,&
         code_arg_mandatory, &
         error)
    if (error) return
    call keyarg%register( &
         'unit',  &
         'Distance unit', &
         '"*" or "=" mean current distance unit is used',&
         code_arg_optional, &
         unit_dist_name, &
         .not.flexible, &
         luminosity%dist_unit,&
         error)
    if (error) return
    !
    call cubetools_register_option(&
         'X','val',&
         'Define the CO to h2 conversion factor',&
         strg_id,&
         luminosity%xco,error)
    if (error) return
    call stdarg%register( &
         'val',  &
         'CO to h2 conversion factor', &
         strg_id,&
         code_arg_mandatory, &
         error)
    if (error) return
  end subroutine cubemain_luminosity_register
  !
  subroutine cubemain_luminosity_parse(luminosity,line,user,error)
    use cubetools_parse
    !----------------------------------------------------------------------
    ! LUMINOSITY cubname
    ! [/RANGE vfirst vlast]
    ! /DISTANCE dist [unit]
    ! [/X xco ]
    !----------------------------------------------------------------------
    class(luminosity_comm_t), intent(inout) :: luminosity
    character(len=*),         intent(in)    :: line
    type(luminosity_user_t),  intent(out)   :: user
    logical,                  intent(inout) :: error
    !
    character(len=*), parameter :: rname='LUMINOSITY>PARSE'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    call cubeadm_cubeid_parse(line,luminosity%comm,user%cubeids,error)
    if (error) return
    call luminosity%labeled%parse(line,user%labeled,error)
    if (error) return
    call luminosity%range%parse(line,user%dorange,user%range,error)
    if (error) return
    call luminosity%parse_distance(line,user,error)
    if (error) return
    call luminosity%parse_xval(line,user,error)
    if (error) return
  end subroutine cubemain_luminosity_parse
  !
  subroutine cubemain_luminosity_parse_distance(luminosity,line,user,error)
    use cubetools_unit
    use cubetools_parse
    !----------------------------------------------------------------------
    ! LUMINOSITY cubname
    ! /DISTANCE dist [unit]
    !----------------------------------------------------------------------
    class(luminosity_comm_t), intent(in)    :: luminosity
    character(len=*),         intent(in)    :: line
    type(luminosity_user_t),  intent(inout) :: user
    logical,                  intent(inout) :: error
    !
    character(len=argu_l) :: userunit
    type(unit_user_t) :: unit
    logical :: present
    character(len=*), parameter :: rname='LUMINOSITY>PARSE>DISTANCE'
    !
    call luminosity%dist%present(line,present,error)
    if (error) return
    if (present) then
       call cubetools_getarg(line,luminosity%dist,1,user%distance,mandatory,error)
       if (error) return
       if (user%distance.le.0) then
          call cubemain_message(seve%e,rname,'Distance must be positive')
          error=.true.
          return
       endif
       !
       userunit = strg_star
       call cubetools_getarg(line,luminosity%dist,2,userunit,.not.mandatory,error)
       if (error) return
       call cubetools_unit_get(userunit,code_unit_dist,unit,error)
       if (error) return
       user%distance = user%distance*unit%prog_per_user
    else
       call cubemain_message(seve%e,rname,'The distance source-earth must be given')
       error=.true.
       return
    endif
  end subroutine cubemain_luminosity_parse_distance
  !
  subroutine cubemain_luminosity_parse_xval(luminosity,line,user,error)
    !----------------------------------------------------------------------
    ! LUMINOSITY cubname
    ! /X xval
    !----------------------------------------------------------------------
    class(luminosity_comm_t), intent(in)    :: luminosity
    character(len=*),         intent(in)    :: line
    type(luminosity_user_t),  intent(inout) :: user
    logical,                  intent(inout) :: error
    !
    logical :: present
    character(len=*), parameter :: rname='LUMINOSITY>PARSE>XVAL'
    !
    call luminosity%xco%present(line,present,error)
    if (error) return
    if (present) then
       call cubetools_getarg(line,luminosity%xco,1,user%xco,mandatory,error)
       if (error) return
       if (user%xco.le.0) then
          call cubemain_message(seve%e,rname,'Xco must be positive')
          error=.true.
          return
       endif
    else
       call cubemain_message(seve%w,rname,'X not given => Assumes Galactic Xco factor')
       user%xco = galxco
    endif
  end subroutine cubemain_luminosity_parse_xval
  !
  subroutine cubemain_luminosity_main(luminosity,user,error)
    use cubeadm_timing
    use cubeadm_get
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(luminosity_comm_t), intent(in)    :: luminosity
    type(luminosity_user_t),  intent(in)    :: user
    logical,                  intent(inout) :: error
    ! 
    type(luminosity_labeled_prog_t) :: prog
    character(len=*), parameter :: rname='LUMINOSITY>MAIN'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    call user%toprog(luminosity,prog,error)
    if (error) return
    call cubeadm_timing_prepro2process()
    if (prog%uselabel) then
       call prog%labeled_header(error)
       if (error) return
       call prog%labeled_data(error)
       if (error) return
    else
       call prog%total_header(error)
       if (error) return
       call prog%total_data(error)
       if (error) return
    endif
    call cubeadm_timing_process2postpro()
  end subroutine cubemain_luminosity_main
  !
  !----------------------------------------------------------------------
  !
  subroutine cubemain_luminosity_user_toprog(user,comm,prog,error)
    use cubetools_consistency_methods
    use cubeadm_get
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(luminosity_user_t),        intent(in)    :: user
    type(luminosity_comm_t),         intent(in)    :: comm
    type(luminosity_labeled_prog_t), intent(inout) :: prog
    logical,                         intent(inout) :: error
    !
    logical :: consprob
    character(len=*), parameter :: rname='LUMINOSITY>USER>TOPROG'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    call cubeadm_cubeid_get_header(comm%comm,icube,user%cubeids,&
         code_access_imaset,code_read,prog%cube,error)
    if (error) return
    !
    call user%labeled%toprog(comm%labeled,code_access_imaset,code_read,&
         prog%labeled,prog%uselabel,error)
    if (error) return
    if (prog%uselabel) then
       ! User requests to use a labeled cube
       call cubetools_consistency_spatial(&
            'Signal cube',prog%cube%head,&
            'Labeled cube',prog%labeled%head,&
            consprob,error)
       if (error) return
    endif
    !
    call cubeadm_cubeid_get_header(comm%comm,inoise,user%cubeids,&
         code_access_imaset,code_read,prog%noise,error)
    if (error) return
    consprob = .false.
    call cubetools_consistency_signal_noise(&
         'Signal cube',prog%cube%head,&
         'Noise',prog%noise%head,&
         consprob,error)
    if (error) return
    if (cubetools_consistency_failed(rname,consprob,error)) return
    !
    call luminosity%range%user2prog(prog%cube,user%range,prog%wind,error)
    if (error) return
    prog%distance = user%distance
    prog%xco = user%xco
  end subroutine cubemain_luminosity_user_toprog
end module cubemain_luminosity
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
