subroutine astro_observatory_command(line,error)
  use gbl_message
  use gkernel_interfaces
  use imager_interfaces, except_this=>astro_observatory_command
  use ast_params
  use ast_astro
  use ast_telescope
  !---------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER: Support routine for command  
  ! 
  ! ARRAY name [subname size] | Long Lat Altitude [Sun-Avoidance]
  ! 
  ! Derived from ASTRO code, but with a reduced list of Observatories,
  ! restricted to Interferometers.
  !!
  !---------------------------------------------------------------------
  character(len=*), intent(in)  :: line   !
  !! Command line
  logical,          intent(out) :: error  
  !! Logical error flag
  !
  ! Constants
  character(len=*), parameter :: rname='ARRAY' 
  integer(kind=4), parameter :: mobs=11   ! 38
  character(len=12) :: knownobs(mobs)
!  data knownobs /  &
!    'BURE','PDBI','NOEMA','PICOVELETA','VELETA','30M',  &  ! IRAM ones first
!    'ACA','ALMA','APEX','ATF','CARMA','CSO','EFFELSBERG','FAST','FCRAO','GBT',  &
!    'GI2T','HAYSTACK','HHT','IOTA','JCMT','KITTPEAK','KOSMA','LASILLA',         &
!    'MAUNAKEA','MEDICINA','NRO','NOBEYAMA','PARANAL','PTI','SEST','SMA','SMT',  &
!    'TRAO','VLA','VLT','WESTFORD','YEBES' /
  !
  ! USER must be first to allow a User defined array
  data knownobs /'USER','ACA','ALMA','NOEMA','PARANAL','VLT','VLTI','IOTA','PTI','VLA','SMA'/ 
  !
  ! Local ---
  character(len=12) :: argum, previous
  integer(kind=4) :: nc,ier,nk
  character(len=24) :: clon,clat,fich,more
  real(kind=8) :: alti,slim
  integer(kind=4) :: date(7)
  !
  ! Code ----
  previous=obsname
  error = .false.
  if (sic_narg(0).eq.0) then
    !
    ! No argument == decode GAG_ASTRO_OBS
    !
    ier = sic_getlog('GAG_ASTRO_OBS',argum)
    if (ier.ne.0) then
      call astro_message(seve%e,rname,  &
        'Failure in translation of GAG_ASTRO_OBS logical')
      error = .true.
      return
    endif
  endif
  call sic_ke (line,0,1,argum,nc,.false.,error)
  if (error) return
  if (argum.eq.'?') then
    ! sic_ambigs_list required to keep "observatory ?" working with the use of sic_ambigs_sub
    call sic_ambigs_list(rname,seve%i,'Choices are:',knownobs)
    return
  endif
  call sic_ambigs_sub(rname,argum,obsname,nk,knownobs,mobs,error)
  if (error) return
  if (nk.eq.1) then
    fich = 'user'
    if (sic_present(0,2)) then
      call sic_ch(line,0,2,more,nc,.false.,error)
      fich = 'user-'//more(1:nc)
    endif
    call astro_observatory_user(trim(fich),diam,error)
    if (error) return
    config_prefix = trim(fich)//'-'
    ier = sic_setlog('astro_stations',config_prefix)
    call astro_message(seve%i,rname,'Selected '//trim(obsname)//' observatory')
  else if (nk.gt.1) then
    !name of the observatory is recognized
    call astro_observatory_byname (obsname,error)
    if (error)  return
    call astro_message(seve%i,rname,'Selected '//trim(obsname)//' observatory')
  else
    !
    ! Do not recognize the observatory name == decode coordinates
    call sic_ch(line,0,1,clon,nc,.true.,error)
    if (error)  return
    call sic_ch(line,0,2,clat,nc,.true.,error)
    if (error)  return
    call sic_r8(line,0,3,alti,.true.,error)
    if (error) return
    slim = 30.d0
    call sic_r8(line,0,4,slim,.false.,error)
    if (error) return
    call astro_observatory_bychcoords(clon,clat,alti,slim,error)
    if (error)  return
  endif
  ! Make sure the Ephemeris are available
  call astro_init
  !
  call utc (date)            ! read UTC from system clock
  call do_astro_time(jnow_utc,d_ut1,d_tdt,error)
  !
  config_count = 0
end subroutine astro_observatory_command
!
subroutine astro_observatory_byname(arg,error)
  use gbl_message
  use gkernel_interfaces
  use ast_astro
  use ast_telescope
  !---------------------------------------------------------------------
  ! @ private
  !
  !!  Set the Astro observatory given its name
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: arg      !! Telescope name
  logical,          intent(inout) :: error    !! Logical error flag
  !
  ! Local ---
  character(len=*), parameter :: rname='OBSERVATORY'
  real(4) :: beamsize, factor
  integer :: ier
  logical :: sim_exist
  real(8) :: xyz(3)
  character(len=80) :: mess
  !
  ! Code ----
  teles = arg  ! arg can be smaller or larger than 4 characters, truncate here
  freq = 100.d0
  sim_exist = sic_varexist('SIM%FNU')
  if (sim_exist) call sic_get_dble('SIM%FNU',freq,error)
  !
  config_prefix = 'astro_stations'
  call gwcs_observatory(arg,lonlat,altitude,slimit,diam,error)
  factor = 1.155   ! Default beamsize in Lambda/Diam
  select case (teles)
  case ('ALMA')
    config_prefix = 'alma-current-'
    call astro_message(seve%i,rname,'Available configurations 1 to 10')
    factor = 1.13
  case ('ACA')
    config_prefix = 'aca-current-'
    call astro_message(seve%i,rname,'Available configurations I and NS')
    factor = 1.13
  case ('NOEM')
    config_prefix = 'noema-12'
    call astro_message(seve%i,rname,'Available configurations A, B, C, D')
    factor = 1.22
  case ('VLA','JVLA','EVLA') 
    freq = 10.d0
    config_prefix = 'vla-'
    call astro_message(seve%i,rname,'Available configurations A, BnA, B, CnB, C, DnC, D')
  case ('NGVL') 
    freq = 40.d0
    config_prefix = 'ngvla-'
    call astro_message(seve%i,rname,'Available configurations Core, Long, Main, Mid, Sba, Spiral')
  case ('PARA','VLT ','VLTI')
    call astro_message(seve%i,rname,  &
      &  'Frequency set to 299.792458 THz = 1 micron')
    freq = 299792.458d0
  case ('IOTA')
    call astro_message(seve%i,rname,  &
      &  'Frequency set to 187.370286 THz = 1.6 micron')
    freq = 187370.286d0
  case ('PTI ')
    call astro_message(seve%i,rname,'Frequency set to 136.269299 THz = '//  &
       & '2.2 micron')
    freq = 136269.299d0
  case ('GI2T')
    call astro_message(seve%i,rname,'Frequency set to 500 THz = '//  &
       & '0.6 micron')
    freq = 499653.8397d0
  end select
  ier = sic_setlog('astro_stations',config_prefix)
  !
  beamsize = factor*(299792458D0/freq/1d9)/diam*180*3600/acos(-1d0)
  !
  if (sim_exist) then
    call sic_let_dble('SIM%FNU',freq,error)
    call sic_let_real('SIM%PRIMARY',beamsize,error)
  endif
  !
  call gwcs_lonlat2geo(lonlat(1),lonlat(2),altitude,xyz)
  !
  write(mess,'(A,3(1X,F0.8))') 'XYZ',xyz
  call astro_message(seve%i,'OBSERVATORY',mess)
end subroutine astro_observatory_byname
!
subroutine astro_observatory_bychcoords(clon,clat,alt,slim,error)
  use gbl_message
  use gkernel_interfaces
  use imager_interfaces, only : astro_observatory_byr8coords
  !---------------------------------------------------------------------
  ! @ private
  !
  !!  Set Astro observatory given its longitude/latitude (sexagesimal
  !! strings), altitude and avoidance
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: clon     !! Telescope longitude (sexagesimal string)
  character(len=*), intent(in)    :: clat     !! Telescope latitude (sexagesimal string)
  real(kind=8),     intent(in)    :: alt      !! Altitude [km]
  real(kind=8),     intent(in)    :: slim     !! Sun avoidance
  logical,          intent(inout) :: error    !! Logical error flag
  !
  ! Local ---
  integer(kind=4) :: llon,llat
  real(kind=8) :: lon,lat
  !
  ! Code ----
  llon = len_trim(clon)
  call sic_sexa(clon(1:llon),llon,lon,error)
  if (error) return
  !
  llat = len_trim(clat)
  call sic_sexa(clat(1:llat),llat,lat,error)
  if (error) return
  !
  call astro_observatory_byr8coords(lon,lat,alt,slim,error)
  if (error)  return
  !
end subroutine astro_observatory_bychcoords
!
subroutine astro_observatory_byr8coords(lon,lat,alt,slim,error)
  use gbl_message
  use gkernel_interfaces
  use ast_astro
  !---------------------------------------------------------------------
  ! @ private
  !!  Set Astro observatory given its longitude/latitude (float values),
  !! altitude and avoidance
  !---------------------------------------------------------------------
  real(kind=8), intent(in)    :: lon      !! Telescope longitude [deg]
  real(kind=8), intent(in)    :: lat      !! Telescope latitude [deg]
  real(kind=8), intent(in)    :: alt      !! Altitude [km]
  real(kind=8), intent(in)    :: slim     !! Sun avoidance
  logical,      intent(inout) :: error    !! Logical error flag
  !
  ! Local ---
  real(8) :: xyz(3)
  character(len=message_length) :: mess
  !
  ! Code ----
  if (abs(lat).gt.90.d0) then
    call astro_message(seve%e,'OBSERVATORY','Latitude must be < 90 degrees')
    error = .true.
    return
  endif
  !
  lonlat(1) = lon
  lonlat(2) = lat
  altitude = alt
  slimit = slim
  obsname = "USER"
  !
  call gwcs_lonlat2geo(lon,lat,alt,xyz)
  !
  write(mess,'(A,3(1X,F0.8))') 'XYZ',xyz
  call astro_message(seve%i,'OBSERVATORY',mess)
end subroutine astro_observatory_byr8coords
!
subroutine astro_message(seve,comm,mess)
  use imager_interfaces, only : map_message
  !! Remap to MAP_MESSAGE
  integer, intent(in) :: seve
  character(len=*), intent(in) :: comm
  character(len=*), intent(in) :: mess
  !
  call map_message(seve,comm,mess)
end subroutine astro_message
!
subroutine astro_teles(freqs)
  use ast_astro
  use ast_telescope
  use gkernel_interfaces
  !
  real(4), intent(in) :: freqs ! Frequency in GHz
  !
  real(4), parameter  :: pi=acos(-1.D0)
  real(4) :: Ruze=0.8 ! Ruze reduction factor
  real(4) :: surface_rms  ! Surface error
  real(4) :: lambda   ! Wavelength
  real(4) :: beamsize ! Beamsize (FWHM)
  real(4) :: factor   ! Beamsize in Lambda/Diameter
  real(4) :: omega    ! Beam solid angle (radian)
  real(4) :: taper    ! Edge taper (dB)
  real(4) :: aeff     ! Effective area
  real(4) :: loss     ! Surface error loss
  logical :: sim_exist, error
  !
  freq = freqs ! Setup Frequency
  aeff = 0.7   ! Typical value
  lambda = 299792458D0/freq*1D-9
  factor = 1.13d0
  !
  !! Print *,'FREQS ',freqs,' GHZ ; Lambda ',lambda,' m ; Diam ',diam,' m'
  select case (teles)
  case ('NOEM') 
    factor = 1.22
    surface_rms = 35E-6 ! 25 microns
    taper = 15.
  case ('30M')
    surface_rms = 50E-6
    taper = 12.
  case ('ALMA','ACA')
    surface_rms = 20
    taper = 8.
  case ('VLA','JVLA','EVLA') 
    surface_rms = 1E-3 !  1 mm 
    taper = 12.
  case default
    surface_rms = lambda/16.
    taper = 10.
  end select
  factor = 1.02+0.0135*taper             ! Resolution factor from edge taper
  !
  beamsize = factor*lambda/diam          ! In radians
  omega    = pi*beamsize**2/4/log(2.)    ! Omega X Aeff = Lambda^2
  loss = exp(-(4.0d0*pi*Ruze*surface_rms/lambda)**2)
  aeff = loss*lambda**2/omega
  !! Print *,'Surface_rms ',surface_rms,' R ',loss,'Aeff ',aeff,' Diam ',diam
  jypk = 2.*1.38E3/aeff
  !! Print *,'JYPK ',jypk,' Aeff ',aeff,' Beamsize ',beamsize,' " '
  beamsize = beamsize*180*3600/pi        ! In arcseconds
  sim_exist = sic_varexist('SIM%FNU')
  if (sim_exist) then
    error = .false.
    call sic_let_dble('SIM%FNU',freq,error)
    call sic_let_real('SIM%PRIMARY',beamsize,error)
  endif
end subroutine astro_teles
!
subroutine astro_observatory_user(file,diam,error)
  use gbl_message
  use gkernel_interfaces, only : sic_getlun
  use imager_interfaces, only : obs_read_key, astro_observatory_byr8coords
  !---------------------------------------------------------------------
  ! @ private
  !
  !! USER defined Observatory - Search for a "user-"'name'".cfg" file 
  !! with Observatory Coordinates
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: file  !! Array configuration file
  real, intent(inout) :: diam           !! Antenna diameter
  logical, intent(inout) :: error       !! Error flhg
  !
  ! Local --
  character(len=*), parameter :: rname='ARRAY'
  character(len=32) :: chain
  integer :: lun,ier,jer,ic
  logical :: exist
  real(8) :: alt,lon,lat,slim,radius,diameter
  !
  ! Code ---
  inquire(file=file//'.cfg',exist=exist)
  if (.not.exist) then
    call astro_message(seve%e,rname,'No "user.cfg" file')
    error = .true.
    return
  endif
  ier = sic_getlun(lun)
  open(unit=lun,file=file//'.cfg',status='old')
  jer = 0
  ! Skip first line
  read(lun,'(A)') chain
  !
  error = .false.
  ! m
  call obs_read_key(lun,'RADIUS',radius,error)
  call obs_read_key(lun,'ALTITUDE',alt,error)
  ! Longitude & Latitude are in Degrees
  call obs_read_key(lun,'LONGITUDE',lon,error)
  call obs_read_key(lun,'LATITUDE',lat,error)
  call obs_read_key(lun,'DIAMETER',diameter,error)
  !
  close(unit=lun)
  call sic_frelun(lun)
  if (error) then
    call astro_message(seve%e,rname,'Invalid format for "user.cfg" file')
    error = .true.
    return
  endif
  !
  slim = 0.
  alt = alt*1d-3 ! Altitude is read in m, but converted to km
  call astro_observatory_byr8coords(lon,lat,alt,slim,error)
  diam = diameter
end subroutine astro_observatory_user
!
subroutine obs_read_key(lun,key,value,error)
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  !! Read value corresponding to KEY in next line of file on LUN
  !---------------------------------------------------------------------
  integer,  intent(in) :: lun             !! Logical unit number
  character(len=*), intent(in) :: key     !! Expected key
  real(kind=8), intent(out) :: value      !! Returned value
  logical, intent(inout) :: error         !! Error flag
  !
  ! Local
  character(len=80) :: chain
  integer :: ic,ier
  !
  if (error) return ! Previous error, skip
  read(lun,'(A)',iostat=ier) chain
  error = .true.
  if (ier.ne.0) return
  !
  ic = index(chain,key) 
  if (ic.eq.3) then
    ic = index(chain,'=') 
    if (ic.ne.0) then
      ic = ic+1
      read(chain(ic:),*,iostat=ier) value
      if (ier.eq.0) error = .false. 
    endif
  endif
  if (error) call astro_message(seve%e,'ARRAY','Invalid format, expected "'//key//' = Value"')
end subroutine obs_read_key
