!-----------------------------------------------------------------------
! API to plot/list NOEMA/POLYFIX frequency coverage from outside ASTRO
! 3 subroutines must be called 
! The first 2 fill in the astro_noemasetup_t structure (define in astro/lib/types.f90)
!       astro_noemasetup_receiver() to transfer tuning and some source information (1 call)
!                                   (fills astro_noemareceiver_t)
!       astro_noemasetup_spw() to transfer polyfix configuration (1 call / SPW) 
!                              (fills astro_noemaspw_t)
! The last procedure can be:
! astro_noemasetup_plot() to do the plot (arguments can be used to customize the layout, see below)
! OR
! astro_noemasetup_list() to do the list ast LIST command in ASTRO
!-----------------------------------------------------------------------
!
subroutine astro_noemasetup_plot(rname,isetup,iplotmode,iupperaxis,showlines,error)
  use gbl_message
  use gkernel_interfaces
  use astro_interfaces, except_this=>astro_noemasetup_plot
  use astro_noema_type
  !-----------------------------------------------------------------------
  ! @ public
  ! Plot a NOEMA receiver\backend setup as done in ASTRO
  !
  ! input:
  ! isetup: import structure filled in by 2 public subroutines:
  !       astro_noemasetup_receiver to transfer tuning/source information (1 call)
  !       astro_noemasetup_spw to transfer polyfix configuration (1 call / SPW)
  !
  ! Plot can be configured with:
  ! plotmode (integer*4):  pm+* defined in astro_types module
  !    pm_basebands=1= BASEBANDS = 4 boxes (H/V)LO, (H/V)LI, (H/V)UI, (H/V)UO
  !                               chunk limits are drawn
  !    pm_receiver=2= RECEIVER = 3 boxes (H/V)-USB, (H/V)-LSB, Global receiver band
  !                               chunk limits are not drawn
  ! iupperaxis (integer*4): choice for upper axis (lower axis is always REST)
  !     freqax_* defined in astro_types
  !     freqax_rest,freqax_rf, _lsr, _if1, _if2,_chunks,_imrest, _imrf, _imrf,_imlsr, _null
  !
  ! showline (logical): if .true. the catalog lines are indicated on the plot
  !-----------------------------------------------------------------------
  character(len=*), intent(in) :: rname
  type(astro_noemasetup_t), intent(in) :: isetup    ! import structure
  integer(kind=4), intent(in) :: iplotmode     ! BASEBANDS or RECEIVER
  integer(kind=4), intent(in) :: iupperaxis
  logical, intent(in) :: showlines
  logical, intent(inout) :: error
  ! local
  character(len=*), parameter :: noemamode='ONLINE'
  type(noema_t) :: lnoema
  type(plot_molecules_t) :: molecules
  type(current_boxes_t) :: cplot
  type(frequency_axis_t) :: freq_axis
  integer(kind=4) :: userns,useris,i
  real(kind=4) :: usersize
  !
  !Define receiver parameters
  call rec_define_noema(lnoema%recdesc,noemamode,error)
  if (error) return
  !Reset tuning parameters
  lnoema%cfebe%defined=.false.
  lnoema%cfebe%rectune%name = ''
  lnoema%cfebe%rectune%iband = 0
  lnoema%cfebe%rectune%flo1 = 0
  lnoema%cfebe%rectune%flotune = 0
  lnoema%cfebe%rectune%frest = 0
  lnoema%cfebe%rectune%frf = 0
  lnoema%cfebe%rectune%flsr = 0
  lnoema%cfebe%rectune%fcent = 0
  lnoema%cfebe%rectune%label = ''
  lnoema%cfebe%rectune%ongrid = .false.
  lnoema%recdesc%redshift = .false. ! does NOT takes into accound source redshift (call from the OBS)
  ! As a result the LO check must take into account the 100MHz tolerance (for doppler)
  do i=1,lnoema%recdesc%n_rbands
    lnoema%recdesc%lolim(1,i)=lnoema%recdesc%lolim(1,i)-lnoema%recdesc%lotol
    lnoema%recdesc%lolim(2,i)=lnoema%recdesc%lolim(2,i)+lnoema%recdesc%lotol
  enddo
  !
  call rec_define_noema_ifproc(lnoema%cfebe%i_f%ifproc,error)
  if (error) return
  !
  ! Tuning and source information
  call noema_external_tuning(rname,isetup%rec,lnoema,error)
  if (error) return
  !
  !SPW configuration
  call noema_external_spw(rname,isetup%spw,lnoema,error)
  if (error) return
  !
  freq_axis%main=trim(freqax_names(freqax_rest))
  if (iupperaxis.le.0.or.iupperaxis.gt.m_freqax) then
    call astro_message(seve%e,rname,'Problem with decoding frequency axis')
    error=.true.
    return
  endif
  freq_axis%second=trim(freqax_names(iupperaxis))
  molecules%doplot=showlines
  molecules%catalog='gag_data:molecules.dat'
  !
  ! Get current marker characteristiacs
  call gr_get_marker(userns,useris,usersize)
  ! Do the PLOT
  if (iplotmode.eq.pm_basebands) then
    call noema_plot_selpfx(rname,lnoema,cplot,molecules,freq_axis,error)
    if (error) return
  else if (iplotmode.eq.pm_receiver) then
    call rec_plot_sidebands(lnoema%recdesc,lnoema%source,lnoema%cfebe%rectune & 
                            ,cplot,molecules,freq_axis,error)
    if (error) return
    call noema_draw_summary(lnoema,cplot,molecules,freq_axis,error)
    if (error) return
  else
    call astro_message(seve%e,rname,'Plot mode not understood')
    error = .true.
    return
  endif
  !
  ! Set marker characteristics as they were:
  call gr_set_marker(userns,useris,usersize)
  !
end subroutine astro_noemasetup_plot
!
subroutine astro_noemasetup_list(rname,isetup,doindex,error)
  use gbl_message
  use gkernel_interfaces
  use astro_interfaces, except_this=>astro_noemasetup_list
  use astro_noema_type
  !-----------------------------------------------------------------------
  ! @ public
  ! Plot/List a NOEMA receiver\backend setup as done in ASTRO
  !
  ! input:
  ! isetup: import structure filled in by 2 public subroutines:
  !       astro_noemasetup_receiver to transfer tuning/source information (1 call)
  !       astro_noemasetup_spw to transfer polyfix configuration (1 call / SPW)
  ! doindex .true. to list SPW according to their number in the data instead of frequency
  !-----------------------------------------------------------------------
  character(len=*), intent(in) :: rname
  type(astro_noemasetup_t), intent(in) :: isetup    ! import structure
  logical, intent(in) :: doindex
  logical, intent(inout) :: error
  ! local
  character(len=*), parameter :: noemamode='ONLINE'
  type(noema_t) :: lnoema
  type(frequency_axis_t) :: freq_axis
  logical :: doconflict
  integer(kind=4) :: is1, is2
  !
  !Define receiver parameters
  call rec_define_noema(lnoema%recdesc,noemamode,error)
  if (error) return
  !Reset tuning parameters
  lnoema%cfebe%defined=.false.
  lnoema%cfebe%rectune%name = ''
  lnoema%cfebe%rectune%iband = 0
  lnoema%cfebe%rectune%flo1 = 0
  lnoema%cfebe%rectune%flotune = 0
  lnoema%cfebe%rectune%frest = 0
  lnoema%cfebe%rectune%frf = 0
  lnoema%cfebe%rectune%flsr = 0
  lnoema%cfebe%rectune%fcent = 0
  lnoema%cfebe%rectune%label = ''
  lnoema%cfebe%rectune%ongrid = .false.
  lnoema%recdesc%redshift = .false. ! does NOT takes into accound source redshift (call from the OBS)
  !
  call rec_define_noema_ifproc(lnoema%cfebe%i_f%ifproc,error)
  if (error) return
  !
  ! Tuning and source information
  call noema_external_tuning(rname,isetup%rec,lnoema,error)
  if (error) return
  !
  !SPW configuration
  call noema_external_spw(rname,isetup%spw,lnoema,error)
  if (error) return
  !
  freq_axis%main=trim(freqax_names(freqax_rest))
  !
  ! Do the list
  doconflict=.false.
  is1=1
  is2=lnoema%cfebe%spw%out%n_spw
  call noema_list_spw(rname,lnoema%cfebe%spw%out,freq_axis%main,lnoema%source,doindex,doconflict,is1,is2,error)
  !
end subroutine astro_noemasetup_list
!
subroutine astro_noemasetup_receiver(rname,irec,flo1,fcent,sb,tuningname,sourcename,doppler,error)
  use gbl_message
  use astro_interfaces, except_this=>astro_noemasetup_receiver
  use astro_types
  !-----------------------------------------------------------------------
  ! @ public
  ! API to fill in receiver section of the ASTRO import structure
  ! irec = isetup%rec ! irec = astro_noemareceiver_t
  !        isetup = astro_noemasetup
  ! flo1 (real*8) = LO1 tuning frequency (REST frame) in MHz
  ! fcent (real*8) = IF1 center frequency in MHz
  ! sb (integer*4) = sideband code where the tuning frequency is placed (1=USB,2=LSB)
  ! tuning name (character*12) = name of the LINE command at the observatory
  ! source name (character*128) = name of the source
  ! doppler (real*8) = doppler of the observation
  !-----------------------------------------------------------------------
  character(len=*), intent(in) :: rname
  type(astro_noemareceiver_t), intent(inout) :: irec
  real(kind=8), intent(in)  :: flo1   ! MHz, rest
  real(kind=8), intent(in)  :: fcent    !MHz, if1
  integer(kind=4), intent(in) :: sb ! sideband
  character(len=*), intent(in) :: tuningname ! tuning name
  character(len=*), intent(in) :: sourcename ! source name
  real(kind=8), intent(in)  :: doppler    ! as defined in obs/clic
  logical, intent(inout) :: error
  ! Local
  character(len=*), parameter :: noemamode='ONLINE'
  type(receiver_desc_t) :: rdesc
  !
  call rec_define_noema(rdesc,noemamode,error)
  if (error) return
  !
  irec%flo1=flo1
  !
  if (fcent.lt.rdesc%iflim(1).or.fcent.gt.rdesc%iflim(2)) then
    call astro_message(seve%e,rname,'Wrong IF frequency')
    error=.true.
    return
  endif
  irec%fcent=fcent
  if (sb.le.0.or.sb.gt.m_sideband) then
    call astro_message(seve%e,rname,'Problem with sideband')
    error=.true.
    return
  endif
  irec%sbcode=sb
  if (tuningname.eq.'') then
    call astro_message(seve%e,rname,'Missing tuning name')
    error=.true.
    return
  endif
  irec%tuningname=tuningname
  !
  if (sourcename.eq.'') then
    call astro_message(seve%e,rname,'Missing source name')
    error=.true.
    return
  endif
  irec%sourcename=sourcename

  !
  irec%obsdoppler=doppler
  !
end subroutine astro_noemasetup_receiver
!
subroutine astro_noemasetup_spw_bychunk(rname,ispw,ch1,ch2,resol,label,user_label,corrmode,error)
  use gbl_message
  use astro_interfaces, except_this=>astro_noemasetup_spw_bychunk
  use astro_types
  !-----------------------------------------------------------------------
  ! @ public-generic astro_noemasetup_spw
  ! API to fill in SPW section of the ASTRO import structure 
  ! 1 call per SPW: the list of SPW is incremented internally
  !
  ! Definition by chunk:
  ! For each spectral window input is:
  ! ch1 (integer*4) = 1st chunk of the SPW
  ! ch2 (integer*4) = last chunk of the SPW
  ! real (real*8) = resolution of the SPW (in MHz)
  ! label (character*3) = label to identify the baseband where the SPW is placed. Format: HLO
  ! user_label (character*32) = in case the used attached a name to the SPW
  ! corrmode (integer*4) = correlator mode used for the baseband
  !
  ! NB: When a HighResolution SPW is defined, the Low SPW of the current baseband is
  ! also defined if it does not exist yet
  !-----------------------------------------------------------------------
  character(len=*), intent(in) :: rname
  type(astro_noemaspw_t), intent(inout) :: ispw
  integer(kind=4), intent(in) :: ch1
  integer(kind=4), intent(in) :: ch2
  real(kind=8), intent(in)  :: resol
  character(len=*), intent(in) :: label
  character(len=*), intent(in) :: user_label
  integer(kind=4), intent(in) :: corrmode
  logical, intent(inout) :: error
  !
  integer(kind=4) :: iw,chmax,it,ic2
  type(pfx_t) :: pfx
  logical :: gotres
  integer(kind=4), parameter :: lenlabel=3
  character(len=128) :: mess
  !
  ispw%n_spw=ispw%n_spw+1
  iw=ispw%n_spw
  !
  call noema_define_pfx(pfx,error)
  if (error) return
  !
  if (corrmode.le.0) then
    call astro_message(seve%e,rname,'Correlator mode undefined')
    error=.true.
    return
  endif
  ispw%corrmode(iw)=corrmode
  !
  chmax=0
  gotres=.false.
  do it=1,pfx%unit(1)%mode(corrmode)%n_types
    if (pfx%unit(1)%mode(corrmode)%chtype(it)%df_chunks.eq.resol) gotres=.true.
    if (pfx%unit(1)%mode(corrmode)%chtype(it)%n_chunks.le.chmax) cycle
    chmax=pfx%unit(1)%mode(corrmode)%chtype(it)%n_chunks
  enddo
  if (.not.gotres) then
    call astro_message(seve%e,rname,'Problem with SPW resolution')
    error=.true.
    return
  endif
  ispw%resol(iw)=resol
  !
  if (ch1.le.0) then
    call astro_message(seve%e,rname,'Chunk 1 undefined')
    error=.true.
    return
  endif
  ispw%chunkmin(iw)=ch1
  if (ch2.le.0) then
    call astro_message(seve%e,rname,'Chunk 2 undefined')
    error=.true.
    return
  endif
  if (ch2.gt.chmax) then
    if (ch2.gt.64) then
      ! patch to be used as long as there is a discrepancy between observed data and astro definitions
      ! (problem of the last 3 chunks)
      call astro_message(seve%e,rname,'Chunk 2 does not exist')
      error=.true.
      return
    endif
    ic2=chmax
    write (mess,'(a,i0,a,1x,i0)') 'Chunk 2 (',ch2,') sent back to',chmax
    call astro_message(seve%w,rname,mess)
  else
    ic2=ch2
  endif
  ispw%chunkmax(iw)=ic2
  if (len_trim(label).ne.lenlabel) then
    call astro_message(seve%e,rname,'Problem with label format (expect 5 characters)')
    error=.true.
    return
  endif
  ispw%label(iw)=label
  !
  ispw%user_label(iw)=user_label
  !
end subroutine astro_noemasetup_spw_bychunk
!
subroutine astro_noemasetup_spw_byfreq(rname,ispw,f1,f2,resol,label,user_label,corrmode,error)
  use gbl_message
  use astro_interfaces, except_this=>astro_noemasetup_spw_byfreq
  use astro_types
  !-----------------------------------------------------------------------
  ! @ public-generic astro_noemasetup_spw
  ! API to fill in SPW section of the ASTRO import structure 
  ! 1 call per SPW: the list of SPW is incremented internally
  !
  ! Definition by frequency:
  ! For each spectral window input is:
  ! f1 (real*8) = IF2 min of the SPW
  ! f2 (real*8) = IF2 max of the SPW
  ! real (real*8) = resolution of the SPW (in MHz)
  ! label (character*3) = label to identify the baseband where the SPW is placed. Format: HLO
  ! user_label (character*32) = in case the used attached a name to the SPW
  ! corrmode (integer*4) = correlator mode used for the baseband
  !
  ! NB: When a HighResolution SPW is defined, the Low SPW of the current baseband is
  ! also defined if it does not exist yet
  !-----------------------------------------------------------------------
  character(len=*), intent(in) :: rname
  type(astro_noemaspw_t), intent(inout) :: ispw
  real(kind=8), intent(in) :: f1
  real(kind=8), intent(in) :: f2
  real(kind=8), intent(in)  :: resol
  character(len=*), intent(in) :: label
  character(len=*), intent(in) :: user_label
  integer(kind=4), intent(in) :: corrmode
  logical, intent(inout) :: error
  !
  integer(kind=4) :: it,itype,ic1,ic2
  type(pfx_t) :: pfx
  logical :: gotres
  integer(kind=4), parameter :: lenlabel=3
  !
  !
  call noema_define_pfx(pfx,error)
  if (error) return
  !
  if (corrmode.le.0) then
    call astro_message(seve%e,rname,'Correlator mode undefined')
    error=.true.
    return
  endif
  gotres=.false.
  do it=1,pfx%unit(1)%mode(corrmode)%n_types
    if (pfx%unit(1)%mode(corrmode)%chtype(it)%df_chunks.eq.resol) gotres=.true.
    itype=it
  enddo
  if (.not.gotres) then
    call astro_message(seve%e,rname,'Problem with SPW resolution')
    error=.true.
    return
  endif
  !
  if (f1.lt.pfx%if2lim(1)) then
    call astro_message(seve%e,rname,'Problem with IF2 min')
    error=.true.
    return
  endif
  !
  if (f2.le.pfx%if2lim(1)) then
    call astro_message(seve%e,rname,'Problem with IF2 max')
    error=.true.
    return
  endif
  !
  ! Convert if2 into chunk number
  call if2tochunk(rname,pfx%unit(1)%mode(corrmode)%chtype(itype),f1,.true.,ic1,error)
  if (error) return
  call if2tochunk(rname,pfx%unit(1)%mode(corrmode)%chtype(itype),f2,.false.,ic2,error)
  if (error) return
  !
  call astro_noemasetup_spw_bychunk(rname,ispw,ic1,ic2,resol,label,user_label,corrmode,error)
  if (error) return
  !
end subroutine astro_noemasetup_spw_byfreq
