!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
subroutine mrtindex_open_one(indexfile,directory,ix,error)
  use classic_api
  use mrtindex_interfaces, except_this=>mrtindex_open_one
  use mrtindex_vars
  !---------------------------------------------------------------------
  ! @ private
  !  Open the index file and append IX accordingly
  !---------------------------------------------------------------------
  character(len=*),          intent(in)    :: indexfile  !
  character(len=*),          intent(in)    :: directory  !
  type(mrtindex_optimize_t), intent(inout) :: ix
  logical,                   intent(inout) :: error      !
  ! Local
  integer(kind=4) :: fileid
  !
  ! Now fill the IX optimize buffer
  call mrtindex_file_old(indexfile,directory,.false.,fileid,error)
  if (error)  return
  !
  call mrtindex_index_read(ix_files(fileid),fileid,ix,error)
  if (error)  return
  !
end subroutine mrtindex_open_one
!
subroutine mrtindex_index_read(file,idir,optx,error)
  use gbl_message
  use gkernel_interfaces
  use classic_api
  use imbfits_parameters
  use mrtindex_interfaces, except_this=>mrtindex_index_read
  use mrtindex_types
  !---------------------------------------------------------------------
  ! @ private
  !   Read all entries in one index file, and append them to the given
  ! index.
  !---------------------------------------------------------------------
  type(classic_file_t),    intent(in)    :: file    !
  integer(kind=4),         intent(in)    :: idir    ! Directory identifier
  type(mrtindex_optimize_t), intent(inout) :: optx    !
  logical,                 intent(inout) :: error   ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='INDEX>READ'
  type(mrtindex_indx_t) :: indx
  integer(kind=entry_length) :: nent,ient
  integer(kind=entry_length), parameter :: zero=0
  logical, parameter :: islast=.false.
  !
  call mrtindex_message(seve%t,rname,'Welcome')
  !
  nent = optx%next-1 + file%desc%xnext-1
  !
  call reallocate_mrtoptimize(optx,nent,.true.,error)
  if (error)  return
  !
  do ient=1,file%desc%xnext-1
    call mrtindex_entry_rindx(file,ient,indx,error)
    if (error)  return
    !
    ! "Observation" number is not known at this stage. Use 0 instead. It is
    ! up to the caller to do something! Same for is-last-version flag.
    call mrtindex_index_to_optimize_inplace(indx,idir,ient,optx%next,zero,  &
      optx%next,islast,optx,optx%next,error)
    if (error)  return
    !
    optx%next = optx%next+1
  enddo
  !
end subroutine mrtindex_index_read
!
subroutine mrtindex_entry_read(filein,ient,entry,error)
  use gbl_message
  use classic_api
  use mrtindex_interfaces, except_this=>mrtindex_entry_read
  use mrtindex_types
  use mrtindex_vars
  !---------------------------------------------------------------------
  ! @ private
  ! Read the ient-th entry in the output file
  !---------------------------------------------------------------------
  type(classic_file_t),       intent(in)    :: filein   !
  integer(kind=entry_length), intent(in)    :: ient     !
  type(mrtindex_entry_t),       intent(inout) :: entry    !
  logical,                    intent(inout) :: error    ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='INDEX>READ>ONE'
  !
  call mrtindex_message(seve%t,rname,'Welcome')
  !
  call mrtindex_entry_rindx(filein,ient,entry%indx,error)
  if (error)  return
  !
  call mrtindex_entry_rheader(filein,ient,entry%indx,entry%desc,entry%head,error)
  if (error)  return
  !
end subroutine mrtindex_entry_read
!
subroutine mrtindex_entry_rheader_byoptx(optx,ient,edesc,head,error)
  use gildas_def
  use gbl_message
  use mrtindex_dependencies_interfaces
  use mrtindex_interfaces, except_this=>mrtindex_entry_rheader_byoptx
  use mrtindex_vars
  use mrtindex_types
  !---------------------------------------------------------------------
  ! @ public-generic mrtindex_entry_rheader
  !  Read the header of the ient-th entry in the given index
  !  Also return the entry descriptor as a side product, which is
  ! useful in some cases
  !---------------------------------------------------------------------
  type(mrtindex_optimize_t),    intent(in)    :: optx    !
  integer(kind=entry_length), intent(in)    :: ient    ! Position in index
  type(classic_entrydesc_t),  intent(out)   :: edesc   !
  type(mrtindex_header_t),      intent(inout) :: head    !
  logical,                    intent(inout) :: error   !
  ! Local
  character(len=*), parameter :: rname='RHEADER'
  integer(kind=4) :: fileid
  character(len=message_length) :: mess
  !
  ! Find the associated index file
  fileid = optx%idir(ient)
  call mrtindex_file_old(fileid,.false.,error)
  if (error)  return
  !
  call mrtindex_entry_rheader_sub(ix_files(fileid),optx%fnum(ient),  &
    optx%bloc(ient),optx%word(ient),edesc,head,error)
  if (error) then
    write(mess,'(A,I0,A,A)')  &
      'Error reading entry #',optx%fnum(ient),' from file ',ix_files(fileid)%spec
    call mrtindex_message(seve%e,rname,mess)
    return
  endif
  !
  ! Do not forget the key!
  call mrtindex_optimize_to_key(optx,ient,head%key,error)
  if (error)  return
  !
end subroutine mrtindex_entry_rheader_byoptx
!
subroutine mrtindex_entry_rheader_byindx(filein,ient,indx,edesc,head,error)
  use gildas_def
  use gbl_message
  use mrtindex_dependencies_interfaces
  use mrtindex_interfaces, except_this=>mrtindex_entry_rheader_byindx
  use mrtindex_vars
  use mrtindex_types
  !---------------------------------------------------------------------
  ! @ public-generic mrtindex_entry_rheader
  !  Read the header of the ient-th entry in the file + indx
  !  Also return the entry descriptor as a side product, which is
  ! useful in some cases
  !---------------------------------------------------------------------
  type(classic_file_t),       intent(in)    :: filein  !
  integer(kind=entry_length), intent(in)    :: ient    ! Position in file
  type(mrtindex_indx_t),        intent(in)    :: indx    ! Associated indx
  type(classic_entrydesc_t),  intent(out)   :: edesc   !
  type(mrtindex_header_t),      intent(inout) :: head    !
  logical,                    intent(inout) :: error   !
  ! Local
  character(len=*), parameter :: rname='RHEADER'
  character(len=message_length) :: mess
  !
  call mrtindex_entry_rheader_sub(filein,ient,indx%bloc,indx%word,edesc,head,error)
  if (error) then
    write(mess,'(A,I0,A,A)')  &
      'Error reading entry #',ient,' from file ',filein%spec
    call mrtindex_message(seve%e,rname,mess)
    return
  endif
  !
  ! Do not forget the key!
  call mrtindex_index_to_key(indx,head%key,error)
  if (error)  return
  !
end subroutine mrtindex_entry_rheader_byindx
!
subroutine mrtindex_entry_rheader_sub(filein,ient,bloc,word,edesc,head,error)
  use gildas_def
  use gkernel_interfaces
  use classic_api
  use mrtindex_interfaces, except_this=>mrtindex_entry_rheader_sub
  use mrtindex_vars
  use mrtindex_types
  !---------------------------------------------------------------------
  ! @ private
  !  Read the header of the ient-th entry in file.
  !  Also return the entry descriptor as a side product, which is
  ! useful in some cases
  ! ---
  !   DO NOT CALL DIRECTLY!!! Use generic entry point
  ! 'mrtindex_entry_rheader' instead
  !---------------------------------------------------------------------
  type(classic_file_t),       intent(in)    :: filein  !
  integer(kind=entry_length), intent(in)    :: ient    ! Position in file
  integer(kind=8),            intent(in)    :: bloc    ! In which record?
  integer(kind=4),            intent(in)    :: word    ! Which word in this record?
  type(classic_entrydesc_t),  intent(out)   :: edesc   !
  type(mrtindex_header_t),    intent(inout) :: head    !
  logical,                    intent(inout) :: error   !
  !
  call classic_recordbuf_open(filein,bloc,word,ibufobs,error)
  if (error)  return
  !
  call classic_entrydesc_read(filein,ibufobs,edesc,error)
  if (error)  return
  !
  ! Fill the 'presec' array
  call classic_entrydesc_secfind_all(edesc,head%presec,1,error)
  if (error)  return
  !
  if (head%presec(sec_prim_id)) then
    call mrtindex_entry_rprim(filein,edesc,head%pri,error)
    if (error)  return
  else
    call mrtindex_entry_zprim(head%pri,error)
    if (error)  return
  endif
  !
  if (head%presec(sec_calib_id)) then
    call mrtindex_entry_rcalib(filein,edesc,head%cal,error)
    if (error)  return
  else
    call mrtindex_entry_zcalib(head%cal,error)
    if (error)  return
  endif
  !
  if (head%presec(sec_science_id)) then
    call mrtindex_entry_rscience(filein,edesc,head%sci,error)
    if (error)  return
  else
    call mrtindex_entry_zscience(head%sci,error)
    if (error)  return
  endif
  !
  if (head%presec(sec_pointing_id)) then
    call mrtindex_entry_rpointing(filein,edesc,head%poi,error)
    if (error)  return
  else
    call head%poi%zero(error)
    if (error)  return
  endif
end subroutine mrtindex_entry_rheader_sub
!
subroutine mrtindex_entry_rprim(filein,edesc,prim,error)
  use gkernel_interfaces
  use classic_api
  use mrtindex_interfaces, except_this=>mrtindex_entry_rprim
  use mrtindex_types
  use mrtindex_vars
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  type(classic_file_t),      intent(in)    :: filein  !
  type(classic_entrydesc_t), intent(in)    :: edesc   ! Entry Descriptor
  type(sec_primary_t),       intent(out)   :: prim    !
  logical,                   intent(inout) :: error   !
  ! Local
  character(len=*), parameter :: rname='INDEX>RPRIM'
  integer(kind=data_length) :: lsec
  integer(kind=4) :: iwork(sec_prim_len)
  !
  lsec = sec_prim_len
  call classic_entry_section_read(sec_prim_id,lsec,iwork,edesc,ibufobs,error)
  if (error) return
  !
  call filein%conv%read%r4 (iwork(1),prim%imbfvers,1)
! call filein%conv%read%r8 (iwork(),prim%lam,     1)
! call filein%conv%read%r8 (iwork(),prim%bet,     1)
! call filein%conv%read%r8 (iwork(),prim%timegoal,1)
! call filein%conv%read%i4 (iwork(),prim%nsubgoal,1)
! call filein%conv%read%i4 (iwork(),prim%nsub,    1)
  !
end subroutine mrtindex_entry_rprim
!
subroutine mrtindex_entry_rcalib(filein,edesc,calib,error)
  use gbl_message
  use gkernel_interfaces
  use classic_api
  use mrtindex_interfaces, except_this=>mrtindex_entry_rcalib
  use mrtindex_types
  use mrtindex_vars
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  type(classic_file_t),      intent(in)    :: filein  !
  type(classic_entrydesc_t), intent(in)    :: edesc   ! Entry Descriptor
  type(sec_calib_t),         intent(inout) :: calib   !
  logical,                   intent(inout) :: error   !
  ! Local
  character(len=*), parameter :: rname='INDEX>RCALIB'
  integer(kind=4) :: jsec,ndata,nfreq,nset,npix,iset
  integer(kind=data_length) :: lsec,addr
  integer(kind=4), allocatable :: iwork(:)
  logical :: found
  character(len=message_length) :: mess
  !
  call classic_entrydesc_secfind_one(edesc,sec_calib_id,found,jsec)
  if (.not.found) then
    call mrtindex_message(seve%e,rname,'No calibration section')
    error = .true.
    return
  endif
  lsec = edesc%secleng(jsec)
  !
  allocate(iwork(lsec))  ! zzz failed_allocate
  call classic_entry_section_read(sec_calib_id,lsec,iwork,edesc,ibufobs,error)
  if (error) return
  !
  call filein%conv%read%i4(iwork(1),nfreq,1)
  call filein%conv%read%i4(iwork(2),nset, 1)
  call filein%conv%read%i4(iwork(3),npix, 1)
  !
  ndata = nfreq*nset*npix
  if (lsec.ne.3+2*nset+4*ndata) then
    write(mess,'(5(A,I0))')  &
      'Invalid number of points: expected ',3+2*nset+4*ndata, &
      ' (nfreq=',nfreq, &
      ', nset=',nset,  &
      ', npix=',npix,  &
      '), got ',lsec
    call mrtindex_message(seve%e,rname,mess)
    error = .true.
    return
  endif
  call reallocate_calib_section(nfreq,nset,npix,calib,error)
  if (error)  return
  !
  addr = 4
  do iset=1,nset
    call filein%conv%read%cc(iwork(addr),calib%frontend(iset),2)
    addr = addr+2
  enddo
  call filein%conv%read%r8(iwork(addr),calib%freq,ndata)
  addr = addr+2*ndata
  call filein%conv%read%r4(iwork(addr),calib%atsys,ndata)
  addr = addr+ndata
  call filein%conv%read%r4(iwork(addr),calib%ztau,ndata)
  !
end subroutine mrtindex_entry_rcalib
!
subroutine mrtindex_entry_rscience(filein,edesc,sci,error)
  use gkernel_interfaces
  use classic_api
  use mrtindex_interfaces, except_this=>mrtindex_entry_rscience
  use mrtindex_types
  use mrtindex_vars
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  type(classic_file_t),      intent(in)    :: filein  !
  type(classic_entrydesc_t), intent(in)    :: edesc   ! Entry Descriptor
  type(sec_science_t),       intent(out)   :: sci     !
  logical,                   intent(inout) :: error   !
  ! Local
  character(len=*), parameter :: rname='INDEX>RSCIENCE'
  integer(kind=data_length) :: lsec
  integer(kind=4) :: iwork(sec_science_len)
  !
  lsec = sec_science_len
  call classic_entry_section_read(sec_science_id,lsec,iwork,edesc,ibufobs,error)
  if (error) return
  !
  call filein%conv%read%i4(iwork(1),sci%caldobs,1)
  call filein%conv%read%i4(iwork(2),sci%calscan,1)
  call filein%conv%read%i4(iwork(3),sci%calback,1)
  call filein%conv%read%i4(iwork(4),sci%calvers,1)
  !
end subroutine mrtindex_entry_rscience
!
subroutine mrtindex_entry_rpointing(filein,edesc,poi,error)
  use gbl_message
  use gkernel_interfaces
  use classic_api
  use mrtindex_interfaces, except_this=>mrtindex_entry_rpointing
  use mrtindex_types
  use mrtindex_vars
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  type(classic_file_t),      intent(in)    :: filein  !
  type(classic_entrydesc_t), intent(in)    :: edesc   ! Entry Descriptor
  type(sec_pointing_t),      intent(out)   :: poi     !
  logical,                   intent(inout) :: error   !
  ! Local
  character(len=*), parameter :: rname='INDEX>RPOINTING'
  logical :: found
  integer(kind=4) :: jsec
  integer(kind=data_length) :: lsec
  integer(kind=4), allocatable :: iwork(:)
  !
  call classic_entrydesc_secfind_one(edesc,sec_pointing_id,found,jsec)
  if (.not.found) then
    call mrtindex_message(seve%e,rname,'No pointing section')
    error = .true.
    return
  endif
  lsec = edesc%secleng(jsec)
  !
  allocate(iwork(lsec))  ! zzz failed_allocate
  call classic_entry_section_read(sec_pointing_id,lsec,iwork,edesc,ibufobs,error)
  if (error) return
  call poi%read(filein,iwork,error)
  if (error) return
end subroutine mrtindex_entry_rpointing
!
subroutine mrtindex_entry_rindx(filein,ient,indx,error)
  use gbl_message
  use classic_api
  use mrtindex_interfaces, except_this=>mrtindex_entry_rindx
  use mrtindex_types
  use mrtindex_vars
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  type(classic_file_t),       intent(in)    :: filein  !
  integer(kind=entry_length), intent(in)    :: ient    ! Entry position in file
  type(mrtindex_indx_t),        intent(out)   :: indx    !
  logical,                    intent(inout) :: error   ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='ENTRY>RINDX'
  integer(kind=4) :: idatabi(mrtindex_indx_length)
  !
  call mrtindex_message(seve%t,rname,'Welcome')
  !
  ! Read the block index of entry_num in idatabi(:)
  call classic_entryindex_read(filein,ient,idatabi,ibufbi,error)
  if (error)  return
  !
  ! Fill ind% from idatabi(:), convert bytes if needed
  call mrtindex_index_frombuf(idatabi,indx,filein%desc%vind,filein%conv,error)
  if (error)  return
  !
end subroutine mrtindex_entry_rindx
!
subroutine mrtindex_index_frombuf(data,indx,vind,conv,error)
  use gbl_message
  use gkernel_interfaces
  use classic_api
  use mrtindex_interfaces, except_this=>mrtindex_index_frombuf
  use mrtindex_types
  !---------------------------------------------------------------------
  ! @ private
  !   Copy the Block Index into the given buffer
  !---------------------------------------------------------------------
  integer(kind=4),          intent(in)    :: data(*)  !
  type(mrtindex_indx_t),    intent(out)   :: indx     !
  integer(kind=4),          intent(in)    :: vind     ! Index version
  type(classic_fileconv_t), intent(in)    :: conv     !
  logical,                  intent(inout) :: error    !
  ! Local
  character(len=*), parameter :: rname='INDEX>FROMBUF'
  character(len=message_length) :: mess
  !
  call mrtindex_message(seve%t,rname,'Welcome')
  !
  call conv%read%i8(data(1), indx%bloc,        1)
  call conv%read%i4(data(3), indx%word,        3)
  call conv%read%cc(data(6), indx%source,      3)
  call conv%read%cc(data(9), indx%projid,      2)
  call conv%read%r8(data(11),indx%ut,          2)
  call conv%read%r4(data(15),indx%az,          2)
  call conv%read%r8(data(17),indx%lon,         2)
  call conv%read%i4(data(21),indx%system,      1)
  call conv%read%r8(data(22),indx%equinox,     1)
  call conv%read%cc(data(23),indx%frontend(1), 2)
  call conv%read%cc(data(25),indx%frontend(2), 2)
  call conv%read%cc(data(27),indx%frontend(3), 2)
  call conv%read%cc(data(29),indx%frontend(4), 2)
  select case (vind)
  case (2)
    call conv%read%i4(data(31),indx%dobs,        8)
    indx%solstatus = solstatus_none
    call conv%read%cc(data(39),indx%filename,   10)
    call conv%read%i8(data(49),indx%itime,       1)
  case (3)
    call conv%read%i4(data(31),indx%dobs,        9)
    call conv%read%cc(data(40),indx%filename,   10)
    call conv%read%i8(data(50),indx%itime,       1)
  case default
    write(mess,'(a,i0)') 'Unexpected index version ',vind
    call mrtindex_message(seve%e,rname,mess)
    error = .true.
    return
  end select
  !
end subroutine mrtindex_index_frombuf
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
