!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubetools_unit
  use phys_const
  use cubetools_parameters
  use cubetools_messaging
  !
  public :: unit_user_t,unitkinds,nunitkinds
  public :: code_unit_uv,unit_uv_name
  public :: code_unit_fov,code_unit_pang,code_unit_beam,code_unit_freq,code_unit_velo,code_unit_dist
  public :: code_unit_unk,code_unit_chan,code_unit_pixe,code_unit_wave,code_unit_brig,code_unit_flux
  public :: unit_fov_name,unit_pang_name,unit_beam_name,unit_freq_name,unit_velo_name,unit_dist_name
  public :: unit_unk_name,unit_chan_name,unit_pixe_name,unit_wave_name
  public :: cubetools_unit_print,cubetools_unit_defaults
  public :: cubetools_unit_get,cubetools_unit_set
  public :: cubetools_unit_get_kind
  !
  private
  !
  ! *** JP: Should unit_l also be defined here?
  integer(kind=4), parameter :: unit_k = 4
  !
  integer(kind=unit_k),  parameter :: nunitkinds = 11
  !
  ! Brightness and Flux units codes are included here as negative
  ! indexes because they are treated in a separate module
  ! (cubetools_brightness). Hence All loops from 1 to nunitkinds will
  ! treat only statical units, i.e. units whose convertions do not
  ! depend on cube information.
  !
  character(len=unit_l), parameter :: unitkinds(-1:nunitkinds) = [&
       'FLUX      ','BRIGHTNESS','UV        ','FOV       ','POSANGLE  ',&
       'BEAM      ','FREQUENCY ','VELOCITY  ','WAVELENGTH','CHANNEL   ',&
       'PIXEL     ','DISTANCE  ','UNKNOWN   ']
  !
  integer(kind=code_k), parameter :: code_unit_flux = -1
  integer(kind=code_k), parameter :: code_unit_brig = 0
  !
  integer(kind=code_k),  parameter :: code_unit_uv = 1
  integer(kind=unit_k),  parameter :: nunit_uv = 1
  character(len=unit_l), parameter :: unit_uv_name(nunit_uv)  = ['meter']
  character(len=unit_l), parameter :: unit_uv_keys(nunit_uv)  = ['METER']
  real(kind=coor_k),     parameter :: unit_uv_pperu(nunit_uv) = [    1d0]
  integer(kind=code_k),  parameter :: code_unit_uv_user = 1
  integer(kind=code_k),  parameter :: code_unit_uv_prog = 1
  !
  integer(kind=code_k),  parameter :: code_unit_fov = 2
  integer(kind=unit_k),  parameter :: nunit_fov = 4
  character(len=unit_l), parameter :: unit_fov_name(nunit_fov)  = ['radian',   'degree',   'minute',   'second']
  character(len=unit_l), parameter :: unit_fov_keys(nunit_fov)  = ['RADIAN',   'DEGREE',   'MINUTE',   'SECOND']
  real(kind=coor_k),     parameter :: unit_fov_pperu(nunit_fov) = [     1d0,rad_per_deg,rad_per_min,rad_per_sec]
  integer(kind=code_k),  parameter :: code_unit_fov_user = 4
  integer(kind=code_k),  parameter :: code_unit_fov_prog = 1
  !
  integer(kind=code_k),  parameter :: code_unit_pang = 3
  integer(kind=unit_k),  parameter :: nunit_pang = 2
  character(len=unit_l), parameter :: unit_pang_name(nunit_pang)  = ['radian',   'degree']
  character(len=unit_l), parameter :: unit_pang_keys(nunit_pang)  = ['RADIAN',   'DEGREE']
  real(kind=coor_k),     parameter :: unit_pang_pperu(nunit_pang) = [     1d0,rad_per_deg]
  integer(kind=code_k),  parameter :: code_unit_pang_user = 2
  integer(kind=code_k),  parameter :: code_unit_pang_prog = 1
  !
  integer(kind=code_k),  parameter :: code_unit_beam = 4
  integer(kind=unit_k),  parameter :: nunit_beam = 4
  character(len=unit_l), parameter :: unit_beam_name(nunit_beam)  = ['radian ',   'minute ',  'second ',   'msecond']
  character(len=unit_l), parameter :: unit_beam_keys(nunit_beam)  = ['RADIAN ',   'MINUTE ',  'SECOND ',   'MSECOND']
  real(kind=coor_k),     parameter :: unit_beam_pperu(nunit_beam) = [      1d0, rad_per_min,rad_per_sec,rad_per_msec]
  integer(kind=code_k),  parameter :: code_unit_beam_user = 3
  integer(kind=code_k),  parameter :: code_unit_beam_prog = 1
  !
  integer(kind=code_k),  parameter :: code_unit_freq = 5
  integer(kind=unit_k),  parameter :: nunit_freq = 4
  character(len=unit_l), parameter :: unit_freq_name(nunit_freq)  = ['THz','GHz','MHz','kHz']
  character(len=unit_l), parameter :: unit_freq_keys(nunit_freq)  = ['THZ','GHZ','MHZ','KHZ']
  real(kind=coor_k),     parameter :: unit_freq_pperu(nunit_freq) = [ 1d6,  1d3,  1d0, 1d-3]
  integer(kind=code_k),  parameter :: code_unit_freq_user = 3
  integer(kind=code_k),  parameter :: code_unit_freq_prog = 3
  !
  integer(kind=code_k),  parameter :: code_unit_velo = 6
  integer(kind=unit_k),  parameter :: nunit_velo = 2
  character(len=unit_l), parameter :: unit_velo_name(nunit_velo)  = ['km/s','m/s ']
  character(len=unit_l), parameter :: unit_velo_keys(nunit_velo)  = ['KM/S','M/S ']
  real(kind=coor_k),     parameter :: unit_velo_pperu(nunit_velo) = [   1d0,  1d-3]
  integer(kind=code_k),  parameter :: code_unit_velo_user = 1
  integer(kind=code_k),  parameter :: code_unit_velo_prog = 1
  !
  integer(kind=code_k),  parameter :: code_unit_wave = 7
  integer(kind=unit_k),  parameter :: nunit_wave = 5
  character(len=unit_l), parameter :: unit_wave_name(nunit_wave)  = ['Ang','nm ','um ','mm ','cm ']
  character(len=unit_l), parameter :: unit_wave_keys(nunit_wave)  = ['ANG','NM ','UM ','MM ','CM ']
  real(kind=coor_k),     parameter :: unit_wave_pperu(nunit_wave) = [ 1d-4, 1d-3, 1d0, 1d3,  1d4]
  integer(kind=code_k),  parameter :: code_unit_wave_user = 4
  integer(kind=code_k),  parameter :: code_unit_wave_prog = 3
  !
  integer(kind=code_k),  parameter :: code_unit_chan = 8
  integer(kind=unit_k),  parameter :: nunit_chan = 1
  character(len=unit_l), parameter :: unit_chan_name(nunit_chan)  = ['channel']
  character(len=unit_l), parameter :: unit_chan_keys(nunit_chan)  = ['CHANNEL']
  real(kind=coor_k),     parameter :: unit_chan_pperu(nunit_chan) = [      1d0]
  integer(kind=code_k),  parameter :: code_unit_chan_user = 1
  integer(kind=code_k),  parameter :: code_unit_chan_prog = 1
  !
  integer(kind=code_k),  parameter :: code_unit_pixe = 9
  integer(kind=unit_k),  parameter :: nunit_pixe = 1
  character(len=unit_l), parameter :: unit_pixe_name(nunit_pixe)  = ['pixel']
  character(len=unit_l), parameter :: unit_pixe_keys(nunit_pixe)  = ['PIXEL']
  real(kind=coor_k),     parameter :: unit_pixe_pperu(nunit_pixe) = [    1d0]
  integer(kind=code_k),  parameter :: code_unit_pixe_user = 1
  integer(kind=code_k),  parameter :: code_unit_pixe_prog = 1
  !
  integer(kind=code_k),  parameter :: code_unit_dist = 10
  integer(kind=unit_k),  parameter :: nunit_dist = 4
  character(len=unit_l), parameter :: unit_dist_name(nunit_dist)  = ['pc ','kpc','Mpc','Gpc']
  character(len=unit_l), parameter :: unit_dist_keys(nunit_dist)  = ['PC ','KPC','MPC','GPC']
  real(kind=coor_k),     parameter :: unit_dist_pperu(nunit_dist) = [ 1d0,  1d3,  1d6,  1d9]
  integer(kind=code_k),  parameter :: code_unit_dist_user = 1
  integer(kind=code_k),  parameter :: code_unit_dist_prog = 1
  !
  integer(kind=code_k),  parameter :: code_unit_unk = 11
  integer(kind=unit_k),  parameter :: nunit_unk = 1
  character(len=unit_l), parameter :: unit_unk_name(nunit_unk)  = [ strg_unk]
  character(len=unit_l), parameter :: unit_unk_keys(nunit_unk)  = ['UNKNOWN']
  real(kind=coor_k),     parameter :: unit_unk_pperu(nunit_unk) = [      1d0]
  integer(kind=code_k),  parameter :: code_unit_unk_user = 1
  integer(kind=code_k),  parameter :: code_unit_unk_prog = 1
  !
  type unit_user_t
     integer(kind=code_k)  :: key                  ! Key in unit array
     character(len=unit_l) :: name = strg_unk      ! Unit name
     real(kind=coor_k)     :: user_per_prog = 1d0  ! Conversion factor 1
     real(kind=coor_k)     :: prog_per_user = 1d0  ! Conversion factor 2
  end type unit_user_t
  !
  type unit_prog_t
     integer(kind=unit_k) :: default(nunitkinds) = [&                ! User default unit
          code_unit_uv_user,code_unit_fov_user,code_unit_pang_user,&
          code_unit_beam_user,code_unit_freq_user,code_unit_velo_user,&
          code_unit_wave_user,code_unit_chan_user,code_unit_pixe_user,&
          code_unit_dist_user,code_unit_unk_user]
     integer(kind=unit_k) :: current(nunitkinds) = [&                ! User current unit
          code_unit_uv_user,code_unit_fov_user,code_unit_pang_user,&
          code_unit_beam_user,code_unit_freq_user,code_unit_velo_user,&
          code_unit_wave_user,code_unit_chan_user,code_unit_pixe_user,&
          code_unit_dist_user,code_unit_unk_user]
     integer(kind=unit_k) :: program(nunitkinds) = [&                ! Internal program unit
          code_unit_uv_prog,code_unit_fov_prog,code_unit_pang_prog,&
          code_unit_beam_prog,code_unit_freq_prog,code_unit_velo_prog,&
          code_unit_wave_prog,code_unit_chan_prog,code_unit_pixe_prog,&
          code_unit_dist_prog,code_unit_unk_prog]
     !
     character(len=unit_l) :: prognames(nunitkinds) = [&    
          unit_uv_name(code_unit_uv_prog),&
          unit_fov_name(code_unit_fov_prog),&
          unit_pang_name(code_unit_pang_prog),&
          unit_beam_name(code_unit_beam_prog),&
          unit_freq_name(code_unit_freq_prog),&
          unit_velo_name(code_unit_velo_prog),&
          unit_wave_name(code_unit_wave_prog),&
          unit_chan_name(code_unit_chan_prog),&
          unit_pixe_name(code_unit_pixe_prog),&
          unit_dist_name(code_unit_dist_prog),&
          unit_unk_name(code_unit_unk_prog)]
     character(len=unit_l) :: usernames(nunitkinds) = [&
          unit_uv_name(code_unit_uv_user),&
          unit_fov_name(code_unit_fov_user),&
          unit_pang_name(code_unit_pang_user),&
          unit_beam_name(code_unit_beam_user),&
          unit_freq_name(code_unit_freq_user),&
          unit_velo_name(code_unit_velo_user),&
          unit_wave_name(code_unit_wave_user),&
          unit_chan_name(code_unit_chan_prog),&
          unit_pixe_name(code_unit_pixe_prog),&
          unit_dist_name(code_unit_dist_user),&
          unit_unk_name(code_unit_unk_user)]
     real(kind=coor_k) :: prog_per_user(nunitkinds) = [&
          unit_uv_pperu(code_unit_uv_user)    ,&
          unit_fov_pperu(code_unit_fov_user)  ,unit_pang_pperu(code_unit_pang_user),&
          unit_beam_pperu(code_unit_beam_user),unit_freq_pperu(code_unit_freq_user),&
          unit_velo_pperu(code_unit_velo_user),unit_wave_pperu(code_unit_wave_user),&
          unit_chan_pperu(code_unit_chan_user),unit_pixe_pperu(code_unit_pixe_user),&
          unit_dist_pperu(code_unit_dist_user),unit_unk_pperu(code_unit_unk_user)]
     real(kind=coor_k) :: user_per_prog(nunitkinds) = [&
          1d0/unit_uv_pperu(code_unit_uv_user)    ,&
          1d0/unit_fov_pperu(code_unit_fov_user)  ,1d0/unit_pang_pperu(code_unit_pang_user),&
          1d0/unit_beam_pperu(code_unit_beam_user),1d0/unit_freq_pperu(code_unit_freq_user),&
          1d0/unit_velo_pperu(code_unit_velo_user),1d0/unit_wave_pperu(code_unit_wave_user),&
          1d0/unit_chan_pperu(code_unit_chan_user),1d0/unit_pixe_pperu(code_unit_pixe_user),&
          1d0/unit_dist_pperu(code_unit_dist_user),1d0/unit_unk_pperu(code_unit_unk_user)]
  end type unit_prog_t
  !
  type(unit_prog_t) :: prog
  !
contains
  !
  subroutine cubetools_unit_defaults(error)
    !---------------------------------------------------------------------
    ! Reset units to defaults by reiinstatiating it
    !---------------------------------------------------------------------
    logical,           intent(inout) :: error
    !
    type(unit_prog_t) :: defaults
    character(len=*), parameter :: rname='UNIT>DEFAULTS'
    !
    call cubetools_message(toolseve%trace,rname,'Welcome')
    !
    prog = defaults
  end subroutine cubetools_unit_defaults
  !
  subroutine cubetools_unit_print(error)
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    logical, intent(inout) :: error
    !
    character(len=message_length) :: mess
    integer(kind=unit_k) :: iunit
    character(len=*), parameter :: rname='UNIT>PRINT'
    !
    call cubetools_message(toolseve%trace,rname,'Welcome')
    !
    write(mess,'(3x,a,10x,a,9x,a,5x,a)') 'KIND','USER','INTERNAL','CONVERSION'
    call cubetools_message(seve%r,rname,mess)
    call cubetools_message(seve%r,rname,'')
    do iunit=1,nunitkinds
       write(mess,'(3x,a,2x,2(a,1x),1pg23.16)') unitkinds(iunit),prog%usernames(iunit),&
            prog%prognames(iunit),prog%prog_per_user(iunit)
       call cubetools_message(seve%r,rname,mess)
    enddo ! iunit
  end subroutine cubetools_unit_print
  !
  subroutine cubetools_unit_set(name,kind,error)
    use gkernel_interfaces
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    character(len=*),     intent(in)    :: name
    integer(kind=code_k), intent(in)    :: kind
    logical,              intent(inout) :: error
    !
    type(unit_user_t) :: user
    character(len=*), parameter :: rname='UNIT>SET'
    !
    call cubetools_message(toolseve%trace,rname,'Welcome')
    !
    call cubetools_unit_get_from_name(name,kind,user,error)
    if (error) return
    !
    prog%current(kind)       = user%key
    prog%usernames(kind)     = user%name
    prog%prog_per_user(kind) = user%prog_per_user
    prog%user_per_prog(kind) = user%user_per_prog
  end subroutine cubetools_unit_set
  !
  subroutine cubetools_unit_get(name,kind,user,error)
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    character(len=*),     intent(in)    :: name
    integer(kind=code_k), intent(in)    :: kind
    type(unit_user_t),    intent(out)   :: user
    logical,              intent(inout) :: error
    !
    character(len=*), parameter :: rname='UNIT>GET'
    !
    call cubetools_message(toolseve%trace,rname,'Welcome')
    !
    if (name.eq.strg_equal.or.name.eq.strg_star) then
       call cubetools_unit_get_from_kind(kind,user,error)
       if (error) return
    else
       call cubetools_unit_get_from_name(name,kind,user,error)
       if (error) return
    endif
  end subroutine cubetools_unit_get
  !
  subroutine cubetools_unit_get_from_kind(code_kind,user,error)
    !---------------------------------------------------------------------
    ! 
    !---------------------------------------------------------------------
    integer(kind=code_k), intent(in)    :: code_kind
    type(unit_user_t),    intent(out)   :: user
    logical,              intent(inout) :: error
    !
    character(len=*), parameter :: rname='UNIT>GET>FROM>KIND'
    character(len=mess_l) :: mess
    !
    call cubetools_message(toolseve%trace,rname,'Welcome')
    !
    if ((code_kind.lt.0).or.(code_kind.gt.nunitkinds)) then
       write(mess,'(a,i0)') 'Unknown unit code ',code_kind
       call cubetools_message(seve%e,rname,mess)
       error = .true.
       return
    else
       user%key  = prog%current(code_kind)
       user%name = prog%usernames(code_kind)
       user%user_per_prog = prog%user_per_prog(code_kind)
       user%prog_per_user = prog%prog_per_user(code_kind)
    endif
  end subroutine cubetools_unit_get_from_kind
  !
  subroutine cubetools_unit_get_from_name(name,kind,user,error)
    use cubetools_disambiguate
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    character(len=*),     intent(in)    :: name
    integer(kind=code_k), intent(in)    :: kind
    type(unit_user_t),    intent(out)   :: user
    logical,              intent(inout) :: error
    !
    character(len=16) :: keyword
    integer(kind=unit_k) :: ikey
    character(len=mess_l) :: mess
    character(len=*), parameter :: rname='UNIT>GET>FROM>NAME'
    !
    call cubetools_message(toolseve%trace,rname,'Welcome')
    !
    select case(kind)
    case(code_unit_uv)
       call cubetools_disambiguate_strict(name,unit_uv_keys,ikey,keyword,error)
       if (error) return
       user%key           = ikey
       user%name          = unit_uv_name(ikey)
       user%prog_per_user = unit_uv_pperu(ikey)
       user%user_per_prog = 1d0/unit_uv_pperu(ikey)
    case(code_unit_fov)
       call cubetools_disambiguate_strict(name,unit_fov_keys,ikey,keyword,error)
       if (error) return
       user%key           = ikey
       user%name          = unit_fov_name(ikey)
       user%prog_per_user = unit_fov_pperu(ikey)
       user%user_per_prog = 1d0/unit_fov_pperu(ikey)
    case(code_unit_pang)
       call cubetools_disambiguate_strict(name,unit_pang_keys,ikey,keyword,error)
       if (error) return
       user%key           = ikey
       user%name          = unit_pang_name(ikey)
       user%prog_per_user = unit_pang_pperu(ikey)
       user%user_per_prog = 1d0/unit_pang_pperu(ikey)
    case(code_unit_beam)
       call cubetools_disambiguate_strict(name,unit_beam_keys,ikey,keyword,error)
       if (error) return
       user%key           = ikey
       user%name          = unit_beam_name(ikey)
       user%prog_per_user = unit_beam_pperu(ikey)
       user%user_per_prog = 1d0/unit_beam_pperu(ikey)
    case(code_unit_freq)
       call cubetools_disambiguate_strict(name,unit_freq_keys,ikey,keyword,error)
       if (error) return
       user%key           = ikey
       user%name          = unit_freq_name(ikey)
       user%prog_per_user = unit_freq_pperu(ikey)
       user%user_per_prog = 1d0/unit_freq_pperu(ikey)
    case(code_unit_velo)
       call cubetools_disambiguate_strict(name,unit_velo_keys,ikey,keyword,error)
       if (error) return
       user%key           = ikey
       user%name          = unit_velo_name(ikey)
       user%prog_per_user = unit_velo_pperu(ikey)
       user%user_per_prog = 1d0/unit_velo_pperu(ikey)
    case(code_unit_wave)
       call cubetools_disambiguate_strict(name,unit_wave_keys,ikey,keyword,error)
       if (error) return
       user%key           = ikey
       user%name          = unit_wave_name(ikey)
       user%prog_per_user = unit_wave_pperu(ikey)
       user%user_per_prog = 1d0/unit_wave_pperu(ikey)
    case(code_unit_chan)
       call cubetools_disambiguate_strict(name,unit_chan_keys,ikey,keyword,error)
       if (error) return
       user%key           = ikey
       user%name          = unit_chan_name(ikey)
       user%prog_per_user = unit_chan_pperu(ikey)
       user%user_per_prog = 1d0/unit_chan_pperu(ikey)
    case(code_unit_pixe)
       call cubetools_disambiguate_strict(name,unit_pixe_keys,ikey,keyword,error)
       if (error) return
       user%key           = ikey
       user%name          = unit_pixe_name(ikey)
       user%prog_per_user = unit_pixe_pperu(ikey)
       user%user_per_prog = 1d0/unit_pixe_pperu(ikey)
    case(code_unit_dist)
       call cubetools_disambiguate_strict(name,unit_dist_keys,ikey,keyword,error)
       if (error) return
       user%key           = ikey
       user%name          = unit_dist_name(ikey)
       user%prog_per_user = unit_dist_pperu(ikey)
       user%user_per_prog = 1d0/unit_dist_pperu(ikey)   
    case(code_unit_unk)
       call cubetools_message(seve%w,rname,'UNKNOWN unit kind')
       ikey               = 1
       user%key           = nunit_unk
       user%name          = unit_unk_name(ikey)
       user%prog_per_user = unit_unk_pperu(ikey)    
       user%user_per_prog = 1d0/unit_unk_pperu(ikey)
    case default
       write(mess,'(a,i0)') 'Unknown unit kind code ',kind
       call cubetools_message(seve%e,rname,mess)
       error = .true.
       return
    end select
  end subroutine cubetools_unit_get_from_name
  !
  !----------------------------------------------------------------------
  !
  subroutine cubetools_unit_get_kind(name,kind,error)
    use cubetools_disambiguate
    use cubetools_brightness
    !------------------------------------------------------------------------
    ! Returns unit kind based on unit name, returns unknown for
    ! unrecognized units
    !------------------------------------------------------------------------
    character(len=*),     intent(in)    :: name
    integer(kind=code_k), intent(out)   :: kind
    logical,              intent(inout) :: error
    !
    integer(kind=4) :: ikey
    character(len=unit_l) :: fullname
    character(len=*), parameter :: rname = 'UNIT>GET>KIND'
    !
    call cubetools_message(toolseve%trace,rname,'Welcome')
    !
    kind = code_unit_unk
    !
    call cubetools_disambiguate_flexible(name,unit_uv_keys,ikey,fullname,error)
    if (error) return
    if (unit_found(code_unit_uv,ikey)) return
    !
    ! Angular units except for msecond are going to be returned as a
    ! FOV unit. This is a choice maybe because all angular other units
    ! are fully ambiguous between POSANG, FOV and BEAM. The choice of
    ! FOV as the main angular unit in this case is dictated by the
    ! main use case. It is left to the calling routine to disambiguate
    ! between FOV,POSANGLE and BEAM based on their specific use case.
    call cubetools_disambiguate_flexible(name,unit_fov_keys,ikey,fullname,error)
    if (error) return
    if (unit_found(code_unit_fov,ikey)) return
    !
    call cubetools_disambiguate_flexible(name,unit_beam_keys,ikey,fullname,error)
    if (error) return
    if (unit_found(code_unit_beam,ikey)) return
    !
    call cubetools_disambiguate_flexible(name,unit_freq_keys,ikey,fullname,error)
    if (error) return
    if (unit_found(code_unit_freq,ikey)) return
    !
    call cubetools_disambiguate_flexible(name,unit_velo_keys,ikey,fullname,error)
    if (error) return
    if (unit_found(code_unit_velo,ikey)) return
    !
    call cubetools_disambiguate_flexible(name,unit_wave_keys,ikey,fullname,error)
    if (error) return
    if (unit_found(code_unit_wave,ikey)) return
    !
    call cubetools_disambiguate_flexible(name,unit_chan_keys,ikey,fullname,error)
    if (error) return
    if (unit_found(code_unit_chan,ikey)) return
    !
    call cubetools_disambiguate_flexible(name,unit_pixe_keys,ikey,fullname,error)
    if (error) return
    if (unit_found(code_unit_pixe,ikey)) return
    !
    call cubetools_disambiguate_flexible(name,unit_dist_keys,ikey,fullname,error)
    if (error) return
    if (unit_found(code_unit_dist,ikey)) return
    !
    ! BRIGHTNESS and FLUX here
    call cubetools_disambiguate_flexible(name,flux_unit,ikey,fullname,error)
    if (error) return
    if (unit_found(code_unit_flux,ikey)) return
    !
    call cubetools_disambiguate_flexible(name,brightness_unit,ikey,fullname,error)
    if (error) return
    if (unit_found(code_unit_brig,ikey)) return
    !
  contains
    function unit_found(thiskind,ikey) result(found)
      integer(kind=code_k), intent(in) :: thiskind
      integer(kind=4),      intent(in) :: ikey
      !
      logical                          :: found
      !
      found = ikey.ne.code_unresolved
      if (found) kind = thiskind
    end function unit_found
  end subroutine cubetools_unit_get_kind
end module cubetools_unit
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
