!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
subroutine mrtcal_chunkset_check(set,error)
  use gbl_message
  use mrtcal_calib_types
  use mrtcal_interfaces, except_this=>mrtcal_chunkset_check
  !---------------------------------------------------------------------
  ! @ private
  ! Check the integrity of a set of chunks
  !---------------------------------------------------------------------
  type(chunkset_t), intent(in)    :: set
  logical,          intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='CHUNKSET>CHECK'
  integer(kind=4) :: ichunk,id
  character(len=12) :: line
  !
  call mrtcal_message(seve%t,rname,'Welcome')
  !
  id = set%chunks(1)%id
  line = set%chunks(1)%spe%line
  do ichunk=2,set%n
     if (set%chunks(ichunk)%id.ne.id) then
        call mrtcal_message(seve%e,rname,'Inconsistant identifiers in set of chunks')
        error = .true.
        return
     endif
     if (set%chunks(ichunk)%spe%line.ne.line) then
        call mrtcal_message(seve%e,rname,'Inconsistant line names in set of chunks')
        error = .true.
        return
     endif
  enddo
  !
end subroutine mrtcal_chunkset_check
!
subroutine mrtcal_chunkset_show(chunkset)
  use gbl_message
  use mrtcal_calib_types
  use mrtcal_interfaces, except_this=>mrtcal_chunkset_show
  !---------------------------------------------------------------------
  ! @ private
  ! Display a set of chunks. For debugging purpose.
  !---------------------------------------------------------------------
  type(chunkset_t), intent(in) :: chunkset
  ! Local
  integer(kind=4) :: ichunk
  character(len=*), parameter :: rname='CHUNKSET>SHOW'
  !
  call mrtcal_message(seve%t,rname,'Welcome')
  !
  do ichunk=1,chunkset%n
     write(*,'(A,I0)') 'Chunk #',ichunk
     call mrtcal_chunk_show(chunkset%chunks(ichunk))
  enddo
  !
end subroutine mrtcal_chunkset_show
!
subroutine chunkset_consistency(caller,c1,c2,error)
  use gbl_message
  use mrtcal_interfaces, except_this=>chunkset_consistency
  use mrtcal_calib_types
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: caller  ! Calling routine name
  type(chunkset_t), intent(in)    :: c1
  type(chunkset_t), intent(in)    :: c2
  logical,          intent(inout) :: error
  ! Local
  integer(kind=4) :: ichunk
  character(len=message_length) :: mess
  !
  if (c1%n.ne.c2%n) then
    write(mess,'(A,I0,1X,I0)')  &
      'Inconsistent number of chunks per set: ',c1%n,c2%n
    call mrtcal_message(seve%e,caller,mess)
    error = .true.
    return
  endif
  !
  do ichunk=1,c1%n
    if (c1%chunks(ichunk)%ndata.ne.c2%chunks(ichunk)%ndata) then
      write(mess,'(A,I0,1X,I0)')  'Inconsistent number of channels: ', &
        c1%chunks(ichunk)%ndata,c2%chunks(ichunk)%ndata
      call mrtcal_message(seve%e,caller,mess)
      error = .true.
      return
    endif
  enddo
  !
end subroutine chunkset_consistency
!
subroutine mrtcal_chunkset_accumulate_setweight(diff,tscale,dowei,error)
  use mrtcal_interfaces, except_this=>mrtcal_chunkset_accumulate_setweight
  use mrtcal_calib_types
  !---------------------------------------------------------------------
  ! @ private
  ! ZZZ
  ! Quick and dirty subroutine to enforce chunks dataw to something
  ! non-zero (needed by simple_waverage). Currently set to 1.0 i.e.
  ! equal weights. Should probably come early and cleverly e.g.
  ! weight equal, tsys, time, maybe in mrtcal_on_minus_off.
  !---------------------------------------------------------------------
  type(chunkset_t), intent(inout) :: diff
  type(chunkset_t), intent(in)    :: tscale
  logical,          intent(in)    :: dowei   ! Compute real weights or dummy?
  logical,          intent(inout) :: error
  ! Local
  integer(kind=size_length) :: ichunk,ichan
  real(kind=4) :: fact
  !
  if (dowei) then
    !
    do ichunk=1,diff%n
      fact = diff%chunks(ichunk)%gen%time * abs(diff%chunks(ichunk)%spe%fres)
      do ichan=1,diff%chunks(ichunk)%ndata
        diff%chunks(ichunk)%dataw(ichan) =  &
          fact / tscale%chunks(ichunk)%data1(ichan)**2
      enddo
    enddo ! ichunk
    !
  else
    !
    do ichunk=1,diff%n
      diff%chunks(ichunk)%dataw(:) = 1.0
    enddo ! ichunk
    !
  endif
  !
end subroutine mrtcal_chunkset_accumulate_setweight
!
subroutine mrtcal_chunkset_accumulate_do(inchunkset,ouchunkset,error)
  use mrtcal_dependencies_interfaces
  use mrtcal_interfaces, except_this=>mrtcal_chunkset_accumulate_do
  use mrtcal_calib_types
  !---------------------------------------------------------------------
  ! @ private
  ! Accumulate the input chunkset into the running output chunkset
  !---------------------------------------------------------------------
  type(chunkset_t), intent(in)    :: inchunkset
  type(chunkset_t), intent(inout) :: ouchunkset
  logical,          intent(inout) :: error
  ! Local
  integer(kind=size_length) :: ichunk
  logical, parameter :: contaminate=.true.  ! Input bad channels contaminate the output sum
  real(kind=8) :: iinteg,ointeg,sinteg
  !
  do ichunk=1,inchunkset%n
    call simple_waverage(                   &
      inchunkset%chunks(ichunk)%data1,      &
      inchunkset%chunks(ichunk)%dataw,bad,  &
      ouchunkset%chunks(ichunk)%data1,      &
      ouchunkset%chunks(ichunk)%dataw,bad,  &
      1,inchunkset%chunks(ichunk)%ndata,    &
      contaminate,.true.)
    ! The following lines assume that the whole spectrum is
    ! not bad
    iinteg = inchunkset%chunks(ichunk)%gen%time
    ointeg = ouchunkset%chunks(ichunk)%gen%time
    sinteg = iinteg+ointeg  ! Total integration time
    ! Compute mean MJD = DOBS + UT
    ouchunkset%chunks(ichunk)%mjd =  &
            (ouchunkset%chunks(ichunk)%mjd*ointeg +  &
            inchunkset%chunks(ichunk)%mjd*iinteg)/sinteg
    call gag_mjd2gagut(ouchunkset%chunks(ichunk)%mjd,       &
                       ouchunkset%chunks(ichunk)%gen%dobs,  &
                       ouchunkset%chunks(ichunk)%gen%ut,    &
                       error)
    ! Compute mean AZ EL, rederive parallactic angle
    ouchunkset%chunks(ichunk)%gen%az =  &
           (ouchunkset%chunks(ichunk)%gen%az*ointeg +  &
            inchunkset%chunks(ichunk)%gen%az*iinteg)/sinteg
    ouchunkset%chunks(ichunk)%gen%el =  &
           (ouchunkset%chunks(ichunk)%gen%el*ointeg +  &
            inchunkset%chunks(ichunk)%gen%el*iinteg)/sinteg
    call mrtcal_chunk_parang_from_gen(ouchunkset%chunks(ichunk)%gen,error)
    ! Set total integration time
    ouchunkset%chunks(ichunk)%gen%time = sinteg
    ! *** JP Normally OTF PSW never explore this subroutine.
    ! *** JP But if it would, the OFF time would be wrongly added...
    ouchunkset%chunks(ichunk)%swi%duree   =  &
      ouchunkset%chunks(ichunk)%swi%duree +  &
      inchunkset%chunks(ichunk)%swi%duree
  enddo ! ichunk
  !
end subroutine mrtcal_chunkset_accumulate_do
!
subroutine mrtcal_chunkset_copy(in,ofirst,ou,error)
  use mrtcal_interfaces, except_this=>mrtcal_chunkset_copy
  use mrtcal_calib_types
  !---------------------------------------------------------------------
  ! @ private
  ! Copy the chunkset to the output structure (from ofirst chunk),
  ! taking care of reallocating chunkds if needed. Copy is done with
  ! allocations, not associations.
  !---------------------------------------------------------------------
  type(chunkset_t), intent(in)    :: in
  integer(kind=4),  intent(in)    :: ofirst
  type(chunkset_t), intent(inout) :: ou
  logical,          intent(inout) :: error
  ! Local
  integer(kind=4) :: ichunk,ochunk
  !
  ochunk = ofirst-1
  do ichunk=1,in%n
    ochunk = ofirst-1+ichunk
    call reallocate_chunk(in%chunks(ichunk)%ndata,ou%chunks(ochunk),error)
    if (error) return
    call mrtcal_chunk_copy_header(in%chunks(ichunk),ou%chunks(ochunk),error)
    if (error) return
    call mrtcal_chunk_copy_data(in%chunks(ichunk),ou%chunks(ochunk),error)
    if (error) return
  enddo
  ou%n = ochunk
end subroutine mrtcal_chunkset_copy
!
subroutine mrtcal_chunkset_append_do(in,ou,error)
  use mrtcal_interfaces, except_this=>mrtcal_chunkset_append_do
  use mrtcal_calib_types
  !---------------------------------------------------------------------
  ! @ private
  ! Append the input chunkset into the running output chunkset
  !---------------------------------------------------------------------
  type(chunkset_t), intent(in)    :: in
  type(chunkset_t), intent(inout) :: ou
  logical,          intent(inout) :: error
  ! Local
  type(chunkset_t) :: tmp
  integer(kind=4) :: newsize
  !
  if (size(ou%chunks).lt.ou%n+in%n) then
    ! ZZZ reallocate_chunkset should have a "keep" mode
    newsize = max(ou%n+in%n,2*ou%n)
    ! Allocate a temporary copy
    call reallocate_chunkset(ou%n,tmp,error)
    if (error)  return
    ! Duplicate the output chunkset
    call mrtcal_chunkset_copy(ou,1,tmp,error)
    if (error)  return
    ! Enlarge the original
    call reallocate_chunkset(newsize,ou,error)
    if (error)  return
    ! Copy back from tmp to original
    call mrtcal_chunkset_copy(tmp,1,ou,error)
    if (error)  return
    ! Free the temporary
    call free_chunkset(tmp,error)
    if (error)  return
  endif
  !
  ! Insert the new ones!
  call mrtcal_chunkset_copy(in,ou%n+1,ou,error)
  if (error)  return
end subroutine mrtcal_chunkset_append_do
