module astro_types
  use gildas_def
  use ast_params
  use ast_constant
  use astro_pfx_types
  !
  !side band handling
  integer(kind=4), parameter :: m_sideband=2
  integer(kind=4), parameter :: usb_code=1
  integer(kind=4), parameter :: lsb_code=2
  integer(kind=4), parameter :: sb_sign(m_sideband) =  (/ 1, -1/) ! +1 USB/-1 LSB used for tuning
  character(len=16), parameter :: sb_col(m_sideband) =  (/ 'BLUE', 'RED '/) ! USB in blue/ LSB in red
  character(len=3), parameter  :: sideband(m_sideband) = (/ 'USB', 'LSB'/)
  !
  ! Polarisation
  integer(kind=4), parameter :: m_polars=10     !max number of polarizations for a receiver
  integer(kind=4), parameter :: hpol_code=1
  integer(kind=4), parameter :: vpol_code=2
  ! basebands Inner Outer
  integer(kind=4), parameter :: outer_code=1
  integer(kind=4), parameter :: inner_code=2
  !
  ! Maximum numbers
  integer(kind=4), parameter :: m_boxes=20      !max number of frequency boxes in a plot page
  integer(kind=4), parameter :: m_tunings=10    !max number of tunings
  integer(kind=4), parameter :: m_rbands=10     !max number of receiver bands in a receiver
  integer(kind=4), parameter :: m_bbands=10     !max number of basebandsbands in a sideband
  integer(kind=4), parameter :: m_ifcables=16   !max number of if transport cable (PICO/EMIR)
  integer(kind=4), parameter :: m_backends=10   !max number of backends for a receiver
  integer(kind=4), parameter :: m_spw=256       !max number of spectral windows
  integer(kind=4), parameter :: m_res=3         !max number of spectral resolution in a setup
  integer(kind=4), parameter :: m_backunits=32  !max number of backend units
  integer(kind=4), parameter :: m_b2b=16  !max number of parasites affectig a FEBE
  !
  ! Frequency related
  real(kind=8), parameter :: undef_freq=-1d0
  real(kind=8), parameter :: khzpermhz=1d3
  real(kind=8), parameter :: mhzperkhz=1d0/1d3
  real(kind=8), parameter :: mhzperghz=1d3
  real(kind=8), parameter :: ghzpermhz=1d0/1d3
  real(kind=8), parameter :: toldoppler=1d-10
  !
  ! Plot Configuration
  ! Global colors
  integer(kind=4), parameter  :: idefcol=0
  integer(kind=4), parameter  :: iconfliccol=1
  character(len=16), parameter :: adefcol='BLACK' !
  character(len=16), parameter :: azcol='DARK_RED' !
  character(len=16), parameter :: apolcol='GREEN' !
  character(len=16),parameter :: amolcol='BLACK'
  character(len=16),parameter :: asweepfcol='WEB_PURPLE' ! spec sweep frequency coverage
  ! Info for polygon hatching
  real(kind=4), parameter :: hatch_info=45
  real(kind=4), parameter :: hatch_warning=-45
  !
  ! Plot modes (NOEMA)
  integer(kind=4), parameter :: m_pm=6
  integer(kind=4), parameter :: pm_receiver=1 ! RECEIVER mode (1 box = H/V IF)
  integer(kind=4), parameter :: pm_basebands=2 ! BASEBAND mode (1 box = H/V basebands)
  integer(kind=4), parameter :: pm_proposal=3 ! PROPOSAL mode (1 box with all)
  integer(kind=4), parameter :: pm_allbands=4 ! All bands mode 
  integer(kind=4), parameter :: pm_tunedbands=5 ! Tuned bands mode 
  integer(kind=4), parameter :: pm_zoom=6 ! Zoom mode 
  character(len=*), parameter  :: pm_names(m_pm) =  (/ 'RECEIVER  ','BASEBAND  ','PROPOSAL  ', &
                                                       'ALLBANDS  ','TUNEDBANDS','ZOOM      '/)
  !
  !Frequency axis choices
  integer(kind=4), parameter :: m_freqax=10
  integer(kind=4), parameter :: freqax_rest=1 ! REST
  integer(kind=4), parameter :: freqax_rf=2 ! RF
  integer(kind=4), parameter :: freqax_lsr=3 ! LSR
  integer(kind=4), parameter :: freqax_if1=4 ! IF1
  integer(kind=4), parameter :: freqax_if2=5 ! IF2
  integer(kind=4), parameter :: freqax_chunks=6 ! CHUNKS
  integer(kind=4), parameter :: freqax_imrest=7 ! IMREST
  integer(kind=4), parameter :: freqax_imrf=8 ! IMRF
  integer(kind=4), parameter :: freqax_imlsr=9 ! IMLSR
  integer(kind=4), parameter :: freqax_null=10 ! NULL
  character(len=12), parameter  :: freqax_names(m_freqax) = (/ 'REST  ','RF    ','LSR   ','IF1   ','IF2   ' &
                                                              ,'CHUNKS','IMREST','IMRF  ','IMLSR ','NULL  '/)
  !
  !Conflict/warnings
  character(len=16), parameter  :: aconflictcol='ORANGE' ! fill area + text
  character(len=16), parameter  :: aconflictcolh='CHOCOLATE' ! hatched area
  character(len=16), parameter  :: aconflictcolplot='WEB_GREY' ! hatched area
  character(len=16), parameter  :: aconfucol='GREY'
  !Color at receiver level
  character(len=16), parameter :: aoutcol='BLACK' ! out of rec band
  character(len=16), parameter :: aavailcol='DARK_GREY' ! available, not tuned
  character(len=16), parameter :: atunedcol='WHITE' ! tuned
  character(len=16), parameter :: anotselcol='LIGHT_GREY' !
  character(len=16), parameter :: abbifproccol='WEB_PURPLE' !
  character(len=16), parameter :: altunecol='MAGENTA' ! tuned freq
  character(len=16), parameter :: afrepcol='ROYAL_BLUE' ! representative freq
  ! Other global parameters
  real(kind=4), parameter :: ltuneheight=3./4. ! hight of the tuning line indicator
  real(kind=4), parameter :: frepheight=9./16. ! hight of the tuning line indicator
  !
  !Backend
  integer(kind=4), parameter :: icol_fill=1
  integer(kind=4), parameter :: icol_hatch=2
  integer(kind=4), parameter :: icol_border=3
  character(len=16), parameter  :: ahighrescol='PALE_GREEN'
  character(len=16), parameter  :: ahighrescolh='DARK_GREEN'
  character(len=16), parameter  :: ahighrescolr='LIME_GREEN'
  character(len=16), parameter  :: alowrescol='PAPAYA_WHIP'
  character(len=16), parameter  :: alowrescolh='SANDY_BROWN'
  character(len=16), parameter  :: alowrescolr='SANDY_BROWN'
  character(len=16), parameter  :: a250col='LIGHT_STEEL_BLUE'
  character(len=16), parameter  :: a250colh='STEEL_BLUE'
  character(len=16), parameter  :: a250colr='STEEL_BLUE'
  character(len=16), parameter  :: achunkcol='WEB_GREY'
  character(len=16), parameter  :: aoverlapcol='SEA_GREEN'
  !
  ! Types
  type :: receiver_desc_t
    ! describe an heterodyne receiver
    character(len=20) :: name                ! name of the receiver
    logical           :: defined=.false.
    real(kind=8)      :: iflim(2)              ! IF limits
    real(kind=8)      :: ifband                 ! IF bandwidth
    integer(kind=4)   :: n_rbands               ! number of receiver bands
    character(len=20) :: bandname(m_rbands)     ! name of the Bands
    ! Limits of the receiver bands
    real(kind=8)      :: rflim(2,m_rbands)      !  RF (sky) band edge TRUE HARDWARE
    real(kind=8)      :: rfcall(2,m_rbands)     ! RF (sky) band edge CALL for PROP
    real(kind=8)      :: rfcallreq(2,m_rbands)     ! RF (sky) limits for the reqested rf freq, CALL for PROP (mostly used for EMIR)
    real(kind=8)      :: restlim(2,m_rbands)     ! limits of the receiver bands TRUE --> taking into account current source doppler
    real(kind=8)      :: restcall(2,m_rbands)     ! limits of the receiver bands CALL FOR PROP --> taking into account current source doppler
    real(kind=8)      :: lolim(2,m_rbands)     ! limits of the LO for all the bands (used to check freq)
    real(kind=8)      :: lohard(2,m_rbands)     ! limits of the LO for all the bands ("true" hard limits)
    real(kind=8)      :: locall(2,m_rbands)     ! limits of the LO for all the bands (call for proposal limits)
    real(kind=8)      :: lotol                 ! tolerance beyond the call value
    real(kind=8)      :: rejection(m_rbands)    ! image side band rejection (dB)
    integer(kind=4)   :: n_sbands               ! number of sidebands in output of the receiver
    integer(kind=4)   :: n_polar                ! number of polar in output of the receiver
    integer(kind=4)   :: n_bbands                ! number of basebands in output of the receiver
    real(kind=8)      :: flo2                  ! LO frequency used to downconvert the basebands
    real(kind=8)      :: if1conf(2)           ! confusion zone (in IF1 because not the same in upper and lower)
    real(kind=8)      :: bblim(2,m_bbands)      ! limit of the basebands
    character(len=20) :: bbname(m_bbands)       ! name of the basebands
    real(kind=8)      :: bbref(m_bbands)       ! ref in the basebands
    character(len=20) :: polname(m_polars)       ! name of the polars
    integer(kind=4)   :: n_backends                   !number of associated Backends
    logical           :: tuninggrid             ! use a tuning grid
    real(kind=8)      :: gridbin                ! bins of the tuning grid (in LO) MHz
    real(kind=8)      :: gridtol                ! tolerance around the grid nodes MHz
    logical           :: redshift               ! .true. to take into account source redshift, .false. to ignore it
  end type receiver_desc_t
  !
  type :: receiver_source_t
    integer(kind=4)   :: sourcetype ! source kind to define the source handling
    logical           :: defined=.false.
    character(len=3)    :: invtype ! kind of velocity used to define the source
    character(len=sourcename_length) :: name
    real(kind=8)      :: jutc ! Time for which the source doppler was computed
    character(len=2)   :: coord ! coordinate frame
    real(kind=4)       :: eq ! equinox (in case of ra dec)
    character(len=16)  :: lambda
    character(len=16)  :: beta
    real(kind=8)       :: vdop !doppler + source LSR velocity 
    real(kind=8)       :: vdopmin !doppler + source LSR velocity  min over 1 year
    real(kind=8)       :: vdopmax !doppler + source LSR velocity  max over 1 year
    real(kind=8)       :: vlsr ! source LSR velocity
    logical            :: lsrdefined ! true if LSR actually set
    real(kind=8)       :: z      ! redshift
    real(kind=8)       :: zshift ! freq shift due to redshift
    real(kind=8)       :: dopshift ! freq shift dure to doppler + [source LSR velocity or redshift]
    real(kind=8)       :: dopmin ! min doppler shift
    real(kind=8)       :: dopmax ! max doppler shift
    real(kind=8)       :: lsrshift ! freq shift due source [LSR velocity OR redshift] only (no earth motion)
  end type receiver_source_t
  !
  type :: receiver_comm_t
    ! describe user input of receiver command
    character(len=20)  :: rec_name           ! rec name
    character(len=100) :: name           ! line name
    real(kind=8)       :: frest          ! line rest frequency GHz
    character(len=3)   :: sideband        ! USB/LSB
    real(kind=8)       :: fcent          ! IF frequency where RF Frest is tuned
  end type receiver_comm_t
  !
  type receiver_tune_t
    ! tuning dependent parameters of a receiver
    character(len=40) :: name=''           ! line name
    integer(kind=4)   :: iband          ! Used frequency band
    real(kind=8)      :: flo1=0d0           ! LO1 frequency (including doppler tracking)
    real(kind=8)      :: flo1dmin=0d0           ! LO1 frequency (including min doppler)
    real(kind=8)      :: flo1dmax=0d0          ! LO1 frequency (including max doppler)
    real(kind=8)      :: flotune        ! LO1 frequency (used for tuning on a grid)
    real(kind=8)      :: frest          ! reference rest frequency MHz
    real(kind=8)      :: frf           ! RF (sky) frequency MHz
    real(kind=8)      :: flsr           ! frequency corrected for lsr (no doppler) MHz
    real(kind=8)      :: fcent          ! IF center frequency (where frest is tuned)
    character(len=200) :: label         ! Summary of tuning parameters
    logical           :: outlo          ! to warn when between the call and the wide values
    logical           :: ongrid          ! to indicate whether the current tuning respects the optimized tuning grid
    !sideband related
    integer(kind=4)    :: sb_code       !
  end type receiver_tune_t
  !
  type receiver_t
    integer(kind=4)       :: n_tunings
    type(receiver_desc_t) :: desc
    type(receiver_source_t) :: source
    type(receiver_comm_t) :: comm(m_tunings)
    type(receiver_tune_t) :: tune(m_tunings)
  end type receiver_t
  !
  type backend_unit_t
  !describe a correlator unit
    integer(kind=4)     :: n_chunks             ! number of chunks
    real(kind=8)        :: ifmin
    real(kind=8)        :: ifmax
    real(kind=8)        :: ifcenter
    real(kind=8)        :: width
    integer(kind=4)     :: iband    ! receiver processed by unit
    integer(kind=4)     :: sb_code   ! sideband processed by unit
    integer(kind=4)     :: bb_code   ! baseband processed by unit
    integer(kind=4)     :: pol_code  ! polar processed by unit
    character(len=5)    :: label        !
  end type backend_unit_t
  !
  type backend_mode_t
    !describe backend mode
    character(len=50)   :: backname             !backend name
    character(len=50)   :: modename             ! mode name
    integer(kind=4)     :: n_backunits          ! number of units (processes 1 baseband)
    real(kind=8)        :: iflim(2,m_bbands)    ! iflim as a function of baseband - order should be the same as taken in rec%desc
    integer(kind=4)     :: m_chunks
    type(backend_unit_t) :: unit(m_backunits)
  end type backend_mode_t
  !
  type backend_t
    character(len=50) :: name
    integer(kind=4) :: n_backmodes
    integer(kind=4) :: imode
    type(backend_mode_t) :: mode(m_backmodes)
  end type backend_t
  !
  type emir_comm_t
    !emir command parameters
    integer(kind=4)     :: n_tunings
    real(kind=8)        :: frest(m_tunings) ! GHz
    character(len=argument_length)    :: code(m_tunings)
    character(len=50)     :: zoommode 
    real(kind=8)        :: fz1,fz2
    logical             :: fixed_scale
  end type emir_comm_t
  !
  type emir_setup_t
    !emir setup
    character(len=3):: sb_mode ! sideband connected to backend 2SB or SSB
    integer(kind=4):: sb_code(m_tunings) !
    character(len=10) :: polmode          ! polar connected to backend: DUAL/SINGLE/USER
    character(len=3) :: polar(m_tunings)  ! in single polar, the 2 tunings have different polar
    integer(kind=4)    :: pol_code(m_tunings) ! 1=H or 2=V
  end type emir_setup_t
  !
  type if_cable_t
    character(len=5)    :: label
    integer(kind=4)     :: iband
    integer(kind=4)     :: sb_code
    integer(kind=4)     :: bb_code
    integer(kind=4)     :: pol_code
  end type if_cable_t
  !
  type correlator_input_t
    character(len=20)   :: mode              ! switchbox command mode : AUTO/SINGLE/LIST
    logical             :: defined           ! to know whether it has been configured
    integer(kind=4)     :: m_usercables      ! number of cables defined by the user !for emir
    integer(kind=4)     :: n_ifcables        ! number of if cables
    type(if_cable_t)    :: ifc(m_ifcables)   ! individual if cable descritpion
  end type correlator_input_t
  !
  type emir_t
    type(emir_comm_t) :: comm
    type(emir_setup_t) :: setup
    type(receiver_t)    :: rec            ! receiver stuff
    type(correlator_input_t) :: switch
    type(backend_t)       :: be(m_backends) ! backends
  end type emir_t
  !
  type if_selection_t
    ! define a subset of if_cables on which the following SPW commands will work
    integer(kind=4)     :: n_ifsel              ! number of if ranges in the present SPW session
    character(len=4)    :: polmode              ! H,V,B to make the difference between single and dual polar cases
    integer(kind=4)      :: usel(m_backunits)    ! index of the selected pfx units
  end type if_selection_t
  !
  type noema_tuning_comm_t
    !recnoema command parameters
    logical             :: dotune ! no when only info, no tuning
    character(len=12)   :: name
    real(kind=8)        :: frest ! GHz
    real(kind=8)        :: fcent ! MHz
    character(len=3)    :: sideband ! LSB or USB
    character(len=50)   :: zoommode
    real(kind=8)        :: fz1,fz2
    logical             :: fixed_scale
    logical             :: fixedfreq
  end type noema_tuning_comm_t
  !
  type noema_if_t
!    type(noema_comm_t) :: comm
    type(correlator_input_t) :: ifproc
    type(if_selection_t) :: selunit
  end type noema_if_t
  !
  type spw_comm_t
    real(kind=4)    :: resol ! in kHz
    integer(kind=4) :: itype
    integer(kind=8) :: time=-1 ! time when the command was typed (to have chronology)
    logical     :: allowconflict ! if true then it is authorized to go on when a conflict occurs 
    real(kind=8) :: fmin
    real(kind=8) :: fmax
    character(len=32) :: user_label=''
  end type spw_comm_t
  !
  type spw_unit_t
    integer(kind=4)     :: iband     ! receiver processed by unit
    integer(kind=4)     :: sb_code   ! sideband processed by unit
    integer(kind=4)     :: bb_code   ! baseband processed by unit
    integer(kind=4)     :: pol_code  ! polar processed by unit
    character(len=5)    :: label        !
    integer(kind=4)     :: itype        ! Correl mode/type used for the SPW
    real(kind=8)  :: restmin       !rest freq
    real(kind=8)  :: restmax       !rest freq
    integer(kind=4) :: ich1
    integer(kind=4) :: ich2
    real(kind=4) :: resol              !kHz
    character(len=32)    :: user_label=''        !
    logical             :: flexible     ! true = tunable, false = fixed
    logical             :: conflict     ! true if 1 of the chunks is used by several spw
    logical             :: overload     ! true if correl unit uses more resource than possible
    logical             :: chunk1     ! true if highres chunk 1 is used
    integer(kind=8)     :: ctime        ! creation time
  end type spw_unit_t
  !
  type spw_output_t
    integer(kind=4) :: n_spw
    type(spw_unit_t) :: win(m_spw)
  end type spw_output_t
  !
  type spw_t
    type(spw_comm_t)      :: comm
    type(spw_output_t)    :: out
  end type spw_t
  !
  type febe_userinfo_t
    real(kind=8) :: user_frep=astro_nullr8 !MHz
    real(kind=8) :: user_resol=astro_nullr8  !MHz
    character(len=256) :: user_res_unit=astro_nulla
    character(len=256) :: user_exp=astro_nulla
    character(len=256) :: user_expcont=astro_nulla    
  end type febe_userinfo_t
  !
  type febe_b2b_crosstalks_t
    ! Information about parasites affecting a FEBE
    logical :: defined=.false.
    integer(kind=4) :: n_b2b=0
    real(kind=8), allocatable :: freq(:)
  end type febe_b2b_crosstalks_t
  !
  type noema_febe_t
    ! Set of frontend backend parameters
    ! Some descriptors
    integer(kind=4) :: id=0
    character(len=32) :: name
    logical :: defined=.false.
    logical :: loaded=.false.
    ! Actual structures
    type(receiver_comm_t)          :: reccomm            ! receiver tuning input
    type(receiver_tune_t)          :: rectune            ! receiver tuning result
    type(noema_tuning_comm_t) :: tune           ! noema tuning command
    type(noema_if_t)          :: i_f            ! if processor and selection
    type(pfx_t)               :: pfx            ! polyfix backend
    type(spw_t)               :: spw            ! spw collection (defined by polyfix settings)
    type(febe_userinfo_t)      :: uinfo          ! Information to/from PMS
    type(febe_b2b_crosstalks_t) :: b2b ! Information about parasites affecting a FEBE
    !
  end type noema_febe_t
  !
  type noema_febe_selection_t
    ! Describe the selection of FEBE as done in /FEBE option (PROPOSAL or SETUP command)
    integer(kind=4) :: nsel=0
    integer(kind=4) :: nbands
    integer(kind=4), allocatable :: selnum(:) ! number in the saved FEBE
    integer(kind=4), allocatable :: selidx(:) ! index of the selected FEBE in the register
    integer(kind=4), allocatable :: iband(:) ! band of each FEBE
    integer(kind=4), allocatable :: bandsel(:) ! band selection (size nsel) for the selected FEBE
    integer(kind=4), allocatable :: tuning_count(:) ! number of tuning per band (size n_rband)
  end type noema_febe_selection_t
  !
  type info_pms_t
    ! put together all info to be provided to PMS (plot /proposal)
    ! Related to tuning
    integer(kind=4)     :: tuning_band
    real(kind=8)        :: tuning_freq
    real(kind=8)        :: tuning_flo1
    real(kind=8)        :: tuning_maxrf ! highest rf freq
    real(kind=8)        :: tuning_minrf ! lowest rf freq
    logical             :: tuning_ongrid
    logical             :: tuning_outlo ! true means out of Call for prop limits
    logical             :: redshift
    real(kind=8)        :: lsrlim(m_sideband,2)  ! lsb min, lsb max, usb min, usb max limits in LSR (for Tsys comparison)
    ! Related to backend
    ! - LSR/Redshift range
    real(kind=8)        :: lsrrange
    real(kind=8)        :: zrange
    ! Usage
    integer(kind=4)     :: mflex ! total number of flexible chunks available (all units merged)
    integer(kind=4)     :: nflex ! total number of flexible chunks used (all units merged)
    logical             :: chunk1 ! chunk 1 raise a warning
    ! - Representative frequency
    real(kind=8)        :: frep                 !rest frame
    real(kind=8)        :: freplsr               ! representative freq in LSR frame (for Tsys and sensitivity)
    real(kind=8)        :: resrep                ! user input spectral resolution
    integer(kind=4)     :: npolrep                ! nb of polar with user input spectral resolution
    integer(kind=4)     :: nspw
    integer(kind=4)     :: nresol              ! number of different spectral resolution covering the repr. freq
    real(kind=8)        :: resol(m_chtypes)     ! resolutions covering the repr. freq
    integer(kind=4)     :: npol(m_chtypes)      ! numb of polarization covering the repr. freq (in each resolution)
    ! Continuum Part
    real(kind=8)        :: fcont                ! representative frequency for continuum (REST FRAME)
    real(kind=8)        :: fcontlsr             ! representative frequency for continuum (LSR frame)
    real(kind=8)        :: fcontw20             ! representative frequency for continuum (LSR frame) - special semester W20
    real(kind=8)        :: dfcont               ! total bandwidth covered
    real(kind=8)        :: rescont              ! Channel spacing (lowest resolution for information only in PMS)
    integer(kind=4)     :: npolcont             ! number of polarization in continuum mode
    !Tracksharing case
    logical             :: tracksharing 
    real(kind=8)        :: tsdf(2)              ! offset in frequency for Sources with values Vmin and Vmax
    logical             :: ts_freqout           ! true if 1 of the frequency gets out of range
    ! User information
    character(len=256)  :: user_res_unit
    character(len=256)  :: user_fline
    character(len=256)  :: user_fcont
    ! B2B cross talk in dual band
    integer(kind=4)     :: n_b2b
    real(kind=8) :: b2b_freq(m_b2b)
  end type info_pms_t
  !
  type draw_axis_t
    character(len=3)    :: pos          ! UP or LOW
    character(len=4)    :: tick='IN'     ! I O N
    character(len=1)    :: label='P'    !  P O N
    character(len=16)   :: aboxcol='BLACK'
    character(len=16)   :: alabcol='BLACK'
  end type draw_axis_t
  !
  type frequency_box_phys_t
    ! Physical description of a box
    real(kind=8)        :: xmin          ! x left position
    real(kind=8)        :: xmax          ! x right position
    real(kind=8)        :: ymin          ! y lower position
    real(kind=8)        :: ymax          ! y upper position
    real(kind=8)        :: sx           ! x size
    real(kind=8)        :: sy           ! y size
  end type frequency_box_phys_t
  !
  type frequency_box_user_t
    ! user defined parameters of a box
    real(kind=8)        :: xmin          ! x left limit
    real(kind=8)        :: xmax          ! x right limit
    real(kind=8)        :: ymin=0        ! y lower limit
    real(kind=8)        :: ymax=5        ! y upper limit
    character(len=50)   :: name=''       ! name of the Axis
    character(len=3)   :: unit='MHz'     ! unit
    logical :: defined=.false.           ! to check before drawing
  end type frequency_box_user_t
  !
  type frequency_box_t
    !global structure that characterize a box : physical coordinates + all frequency axis
    integer(kind=4)                  :: bb_code
    integer(kind=4)                  :: sb_code
    integer(kind=4)                  :: iband
    type(frequency_box_phys_t)       :: phys
    type(frequency_box_user_t)       :: rest            ! freq in the frame of the source
    type(frequency_box_user_t)       :: lsr             ! freq corrected for LSR or Redshift (no earth)
    type(frequency_box_user_t)       :: rf             ! freq corrected for LSR or Redshift + earth
    type(frequency_box_user_t)       :: imrest
    type(frequency_box_user_t)       :: imrf
    type(frequency_box_user_t)       :: imlsr
    type(frequency_box_user_t)       :: if1
    type(frequency_box_user_t)       :: if2
    type(frequency_box_user_t)       :: chunks
  end type frequency_box_t
  !
  type current_boxes_desc_t
    integer(kind=4)   :: plotmode  ! according to plotmodes defined above
    real(kind=4)      :: hugechar   
    real(kind=4)      :: defchar   
    real(kind=4)      :: smallchar
    real(kind=4)      :: molchar
  end type  current_boxes_desc_t
  !
  type current_boxes_t
    ! current state of the plot pages - nbox boxes described by frequency_box_t(nbox)
    integer(kind=4) :: nbox=0
    type(current_boxes_desc_t) :: desc
    type(frequency_box_t) :: box(m_boxes)
  end type current_boxes_t
  !
  type draw_mark_t
    !parameters needed to draw a line
    real(kind=8)        :: x    ! x positions
    real(kind=8)        :: y    ! y positions
    character(len=16)   :: ref       ! reference for coordinates (USER,PHYSICAl,BOX,CHARACTER)
    integer(kind=4)   :: iref       ! iref (for box and character)
    integer(kind=4)     :: nside=0        ! number of sides of the marker
    integer(kind=4)     :: style=0        ! follows g\set mark
    real(kind=4)     :: s=0.5            ! size in physical units
    character(len=16)   :: col='BLACK'  ! pen color
    logical             :: clip=.false.
  end type draw_mark_t
  !
  type draw_line_t
    !parameters needed to draw a line
    real(kind=8)        :: xmin,xmax    ! x positions
    real(kind=8)        :: ymin,ymax    ! y positions
    character(len=16)   :: col='BLACK'  ! pen color
    integer(kind=4)     :: dash=1       ! pen dash
  end type draw_line_t
  !
  type draw_interbox_line_t
    !parameters needed to draw a line between 2 boxes
    integer(kind=4)     :: ibox(2)      ! boxes
    real(kind=8)        :: xpos(2)      ! x position
    real(kind=8)        :: ypos(2)      ! y positions
    character(len=16)   :: frame(2)     ! frame for values
    character(len=16)   :: col='BLACK'  ! pen color
    integer(kind=4)     :: dash=1       ! pen dash
  end type draw_interbox_line_t
  !
  type draw_rect_t
    !parameters needed to draw a rectangle
    real(kind=8)        :: xmin,xmax    ! x positions
    real(kind=8)        :: ymin,ymax    ! y positions
    real(kind=4)        :: hang=45      ! angle for hatching (if hacthing is chosen)
    character(len=16)     :: col='BLACK'   ! pen color
    integer(kind=4)     :: dash=1          ! pen dash
  end type draw_rect_t
  !
  type draw_gauss_t
    !parameters needed to draw a guassian
    real(kind=8)        :: xcent    ! x position
    real(kind=8)        :: fwhm    ! fwhm
    real(kind=8)        :: ymin,ymax    ! y positions
    character(len=16)   :: col='BLACK'          ! pen color
    integer(kind=4)     :: dash=1          ! pen dash
  end type draw_gauss_t
  !
  type plot_molecules_t
    ! Describes the global behavior for plotting molecular lines
    character(len=filename_length) :: catalog='' ! Name of the catalog. Default is GILDAS one.
    logical            :: doplot=.False.          ! Plot the lines ?
    character(len=12)  :: profile="BOXCAR"        ! Profile of the lines to plot
    real(kind=8)       :: width=0d0               ! Width of the lines to plot [MHz]
  end type plot_molecules_t
  !
  type frequency_axis_t
    ! Describes the global frequency axis used (for NOEMA and EMIR frequency coverages)
    character(len=16)  :: main='REST'        ! lower axis of plots + commands
    character(len=16)  :: second='NULL'        ! upper axis of plots
  end type frequency_axis_t
  !
  type astro_noemareceiver_t
    ! plot pfx configuration from outside ASTRO (CLIC/OBS)
    ! receiver/source part
    real(kind=8) :: flo1 ! frequency of the tuning
    real(kind=8) :: fcent ! MHZ IF1
    integer(kind=4) :: sbcode ! USB or LSB
    character(len=12) :: tuningname ! tuning name
    character(len=12) :: sourcename ! sourcename
    real(kind=8) :: obsdoppler ! current doppler
  end type astro_noemareceiver_t
  !
  type astro_noemaspw_t
    ! plot pfx configuration from outside ASTRO (CLIC/OBS)
    ! spw part
    integer(kind=4) :: n_spw=0 ! number of defined spw
    integer(kind=4) :: chunkmin(m_spw) ! first chunk of spw
    integer(kind=4) :: chunkmax(m_spw) ! last chunk of spw
    real(kind=8) :: resol(m_spw) ! spectral resolution
    character(len=5) :: label(m_spw) ! format: B1HUO,B2HUI,...
    character(len=32) :: user_label(m_spw) ! spw name as stated by user
    integer(kind=4) :: corrmode(m_spw) ! correlator mode
  end type astro_noemaspw_t
  !
  type astro_noemasetup_t
    ! plot pfx configuration from outside ASTRO (CLIC/OBS)
!     character(len=4)  :: mode ! CLIC or OBS ! could set defaults for computations/visualization ?
    type(astro_noemareceiver_t) :: rec
    type(astro_noemaspw_t) :: spw
  end type astro_noemasetup_t
  !
end module astro_types
!
module string_parser_types
  !
  ! Support module for "string parser". See string-parser.f90 for details.
  !
  integer(kind=4), parameter :: substring_parser_mval=4
  integer(kind=4), parameter :: substring_parser_mchar=2
  type :: substring_parser_t
    integer(kind=4) :: nval
    character(len=substring_parser_mchar) :: val(substring_parser_mval)
  end type substring_parser_t
  !
  integer(kind=4), parameter :: string_parser_msub=4
  type :: string_parser_t
    logical :: active(string_parser_msub) = .false.
    type(substring_parser_t) :: substring(string_parser_msub)
  end type string_parser_t
  !
end module string_parser_types
