!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module mrtcal_calib_types
  use gildas_def
  use gkernel_types
  use class_types
  use chopper_definitions
  use imbfits_parameters
  use imbfits_types
  use mrtindex_types
  use mrtindex_parse_types
  !
  type mjd_t
     real(kind=8) :: beg=0d0 ! Time at beginning
     real(kind=8) :: end=0d0 ! Time at end
     real(kind=8) :: med=0d0 ! Median time
  end type mjd_t
  type elev_corr_t
     real(kind=8) :: el      = 0.0 ! Elevation
     real(kind=4) :: airmass = 0.0 ! Airmass
  end type elev_corr_t
  !
  type mrtcal_classuser_t
    integer(kind=4) :: obstype    ! [Code] Observation type
    real(kind=4)    :: noise=-1.  ! [Int. unit] Theoretical noise (rms) from calibration
    real(kind=4)    :: backeff    ! [---------] Backend efficiency
    real(kind=4)    :: airmass    ! [---------] Airmass
    real(kind=4)    :: expatau    ! [---------] exp( airmass * tauzen )
  end type mrtcal_classuser_t
  !
  type chunk_t
    ! Miscelleanous information which is not directly/easily available in the Class sections
    integer(kind=4)  :: id       = 0   ! Identifier (equal to the PART in the IMBFITS)
    real(kind=8)     :: mjd      = 0   ! Date + Time (useful for interpolation around midnight...)
    integer(kind=4)  :: ifront   = 0   ! Line number in IMBFITS frontend table
    character(len=8) :: frontend = ''  ! Frontend abbreviation (as found in the Class telescope name)
    ! Class sections
    type(class_general_t)    :: gen         ! General
    type(class_position_t)   :: pos         ! Position
    type(class_spectro_t)    :: spe         ! Spectroscopic axis description, OR
    type(class_drift_t)      :: con         ! Continuum axis description
    type(class_calib_t)      :: cal         ! Calibration
    type(class_switch_t)     :: swi         ! Switching
    type(class_res_t)        :: res         ! Resolution
    type(mrtcal_classuser_t) :: user        ! Mrtcal User Section
    ! Arrays
    integer(kind=4)          :: ndata = 0   ! Number of channels/points
    real(kind=4)             :: cont1 = 0.0 ! Continuum associated to data1
    real(kind=4), pointer    :: data1(:) => null()  ! [ nchan ] 1D Values
    real(kind=4), pointer    :: dataw(:) => null()  ! [ nchan ] Associated weights
    integer(kind=4)          :: allocated=code_pointer_null ! Allocated or just associated?
  end type chunk_t
  type chunkset_t
    integer(kind=4)        :: n   ! Number of chunks in this set
    type(chunk_t), pointer :: chunks(:) => null() ! [ n ] The chunks
    integer(kind=4)        :: allocated=code_pointer_null ! Allocated or just associated?
  end type chunkset_t
  type chunkset_2d_t
     type(mjd_t)       :: mjd      ! MJD beginning, end, and median
     type(elev_corr_t) :: corr     ! Elevation correction
     integer(kind=4)   :: isub = 0 ! Associated subscan number
     integer(kind=4)   :: npix = 0 ! Number of pixels
     integer(kind=4)   :: nset = 0 ! Number of chunksets
     type(chunkset_t), pointer :: chunkset(:,:) => null()  ! [ nset x npix ] Data array
     integer(kind=4)  :: allocated=code_pointer_null ! Allocated or just associated?
  end type chunkset_2d_t
  integer(kind=4), parameter :: ckind_time=0   ! Time dumps
  integer(kind=4), parameter :: ckind_calib=1  ! Calibration products
  integer(kind=4), parameter :: ckind_onoff=2  ! ON-OFF differences
  type chunkset_3d_t
     integer(kind=4)   :: kind = ckind_time  ! Kind of 3rd dimension
     type(mjd_t)       :: mjd        ! MJD beginning, end, and median
     type(elev_corr_t) :: corr       ! Elevation correction
     integer(kind=4)   :: isub  = 0  ! Associated subscan number
     integer(kind=4)   :: ntime = 0  ! Number of 'time' rows read
     integer(kind=4)   :: npix  = 0  ! Number of pixels
     integer(kind=4)   :: nset  = 0  ! Number of chunksets mapping Nchan in first dimension of DATA block: databuf%imbf%val(:,ipix,itime)
     type(chunkset_t), pointer :: chunkset(:,:,:) => null()  ! [ nset x npix x ntimes] Chunksets mapping the DATA block
  end type chunkset_3d_t
  !
  type calib_backend_t
     ! Input 
     type(mrtindex_header_t) :: head
     integer(kind=4) :: nset = 0
     integer(kind=4) :: npix = 0
     integer(kind=4) :: nspec   ! Number of CLASS spectra produced by this scan
     type(imbfits_back_chunks_t) :: chunksetlist ! List of chunksets
     ! Standard calibration
     type(chunkset_2d_t) :: sky
     type(chunkset_2d_t) :: hot
     type(chunkset_2d_t) :: cold
     type(chunkset_2d_t) :: trec
     type(chunkset_2d_t) :: tcal
     type(chunkset_2d_t) :: atsys ! System temperature attenuated by the atmosphere = Tsys * exp(-airmass*ztau)
     type(chunkset_2d_t) :: tsys
     type(chunkset_2d_t) :: water
     type(chunkset_2d_t) :: ztau  ! Zenith opacity
     type(chunkset_2d_t) :: flag
     type(chopper_t), pointer :: chopperset(:,:) => null()
     ! Polarimetry calibration
     logical :: polar = .false.
     type(chunkset_2d_t) :: grid
     type(chunkset_2d_t) :: amppha
     type(chunkset_2d_t) :: sincos
  end type calib_backend_t
  !
  type calib_scan_t
     ! Provides an array of all possible backends. Use the backend identifier code
     ! as array index.
     integer(kind=4) :: n = 0 ! Sized with the number of backends available in Mrtcal
     type(calib_backend_t), pointer :: val(:) => null() ! Calibration parameters
  end type calib_scan_t
  !
  type calib_t
     type(user_calib_t)      :: user ! User request
     type(mrtindex_optimize_t) :: idx  ! Backend index
     type(calib_scan_t)      :: scan ! Scan calibration parameters
  end type calib_t
  !
  type on_stack_t
     type(chunkset_2d_t) :: curr    ! Current on spectra
  end type on_stack_t
  !
  type off_stack_t
     type(chunkset_2d_t), pointer :: prev=>null() ! Off spectra before current on
     type(chunkset_2d_t), pointer :: curr=>null() ! Off spectra interpolated at current on time
     type(chunkset_2d_t), pointer :: next=>null() ! Off spectra after current on
     type(chunkset_2d_t) :: stack(2) ! off spectra
     type(chunkset_2d_t) :: slope  ! Linear interpolation slope
     type(chunkset_2d_t) :: offset ! Linear interpolation offset
     type(chunkset_2d_t) :: interp ! Linear interpolation result
  end type off_stack_t
  !
  type subscan_list_t
     integer(kind=4) :: nsub = 0 ! Number of subscan in list
     integer(kind=4), pointer :: isub(:)  => null() ! Subscan number
     real(kind=8),    pointer :: mjd(:)   => null() ! Date and time
     real(kind=8),    pointer :: time(:)  => null() ! Declarative integration time
     logical,         pointer :: empty(:) => null() ! Is the subscan empty (0 data dumps)?
     type(eclass_char_t)  :: scanning ! Tracked or OTF
     type(eclass_2dble1char_t) :: onoff
     integer(kind=4) :: tracked = 0
     integer(kind=4) :: otf = 0
     integer(kind=4) :: on  = 0
     integer(kind=4) :: off = 0
  end type subscan_list_t
  !
  type switch_desc_t
     integer(kind=4) :: noffset = 0 ! Number of offsets (1 for FSW, 2 for WSW or PSW)
     integer(kind=4) :: nfront  = 0 ! Number of frontends
     real(kind=4), pointer :: wei(:)   => null() !           nfront phase weights
     real(kind=8), pointer :: off(:,:) => null() ! noffset x nfront phase offsets
  end type switch_desc_t
  !
  type switch_cycle_t
     integer(kind=4) :: mode = switchmode_unk
     integer(kind=4) :: ion  =  0 ! Index of ON  phase
     integer(kind=4) :: ioff =  0 ! Index of OFF phase
     integer(kind=4) :: ndump = 0 ! Number of dumps in dumpcycle
     integer(kind=4) :: npha =  0 ! Number of phases in switch cycle
     integer(kind=4) :: ndata = 0 ! Number of filled elements in the data array
     integer(kind=4) :: ndesc = 0 ! Number of filled elements in the desc array
     type(chunkset_2d_t), pointer :: data(:) => null() ! Data
     type(switch_desc_t), pointer :: desc(:) => null() ! Description
  end type switch_cycle_t
  !
  type switch_book_t
     logical         :: found = .false. ! Is current cycle OK?
     integer(kind=4) :: nphase  = 0     ! Number of mandatory phases in cycle
     integer(kind=4) :: ncycle  = 0     ! Number of dumps in complete cycles
     integer(kind=4) :: ndump   = 0     ! Number of dumps in current subscan
     integer(kind=4) :: norphan = 0     ! Number of dumps that do not belong to a complete cycle
     integer(kind=4) :: idump   = 0     ! Where do we stand in the dump stream?
     integer(kind=4) :: ifirst  = 0     ! First dump of current cycle
     integer(kind=4) :: izero   = 0     ! Index of last dump before on-track signal
  end type switch_book_t
  !
  type switch_t
     type(switch_cycle_t) :: cycle
     type(switch_book_t)  :: book
  end type switch_t
  !
  type science_backend_t
     logical :: cumulinit = .true.    ! Shall we initialize the accumulated spectrum?
     type(mrtindex_header_t) :: head
     type(imbfits_back_chunks_t) :: chunksetlist ! List of chunksets
     type(subscan_list_t)  :: list    ! List of subscan properties
     type(switch_t)        :: switch  ! Switching properties
     type(on_stack_t)      :: on      ! Current on  stack
     type(off_stack_t)     :: off     ! Current off stack
     type(chunkset_3d_t)   :: diff    ! Current on-off
     type(chunkset_3d_t)   :: cumul   ! Current accumulated spectrum
     type(chunkset_2d_t)   :: tscale  ! Current temperature scale
     type(chunkset_2d_t)   :: expatau ! Current exp(airmass*tau)
     integer(kind=4)       :: nspec   ! Number of CLASS spectra produced by this scan
  end type science_backend_t
  !
  type science_scan_t
     integer(kind=4) :: n = 0 ! Number of backends to be calibrated
     type(science_backend_t), pointer :: val(:) => null() ! Calibrated results
  end type science_scan_t
  !
  type science_t
     type(user_calib_t)      :: user ! User request
     type(mrtindex_optimize_t) :: idx  ! Backend index
     type(science_scan_t)    :: scan ! Scan being calibrated
  end type science_t
  !
end module mrtcal_calib_types
!
module mrtcal_sicidx
  !---------------------------------------------------------------------
  ! Support module for
  !  Sic structure  IDX%USER%
  !  Command        VARIABLE USER /INDEX
  !---------------------------------------------------------------------
  !
  type mrtcal_classuser_arr_t
    integer(kind=4), allocatable :: obstype(:)  ! Observation type
    real(kind=4),    allocatable :: noise(:)    ! Theoretical noise (rms) from calibration
    real(kind=4),    allocatable :: backeff(:)  ! Backend efficiency
    real(kind=4),    allocatable :: airmass(:)  ! Airmass
    real(kind=4),    allocatable :: expatau(:)  ! exp( airmass * tauzen )
  end type mrtcal_classuser_arr_t
  !
  ! Support variable for command "SET VARIABLE Section /INDEX"
  type(mrtcal_classuser_arr_t), save :: idxuser
  !
end module mrtcal_sicidx
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
