module sofia_types
  !
  type sofia_kalibrate_t
    ! Atmospheric model information
    character(len=12)   :: atmodel
    character(len=36)   :: atmid
    integer(kind=4)     :: atmarg
    ! Environment information
    real(kind=4)        :: tamb_sofi
    real(kind=4)        :: tempri1
    real(kind=4)        :: tempsec1
    ! Flight information
    real(kind=4)        :: gndspeed
    real(kind=4)        :: heading
    ! Instrument information
    character(len=16)   :: instrume
    character(len=32)   :: instcfg
    character(len=16)   :: frontend
    character(len=16)   :: backend
    ! Chopper information
    real(kind=4)        :: schpfrq
    real(kind=4)        :: chpamp1
    real(kind=8)        :: chpangle
    ! Mission management
    character(len=32)   :: datasrc
    character(len=32)   :: observer
    character(len=32)   :: operater ! operator is a keyword even in Fortran
    character(len=32)   :: planid
    character(len=32)   :: mission_id
    character(len=32)   :: obs_id
    ! Atmospheric calibration parameters
    real(kind=4)        :: pwv_mm
    real(kind=4)        :: err_pwv_mm
    integer(kind=4)     :: fit_pwv_mm
    real(kind=8)        :: ratio_f_th
    real(kind=4)        :: dry_atm
    real(kind=4)        :: err_dry_atm
    integer(kind=4)     :: fit_dry_atm
    real(kind=4)        :: dry_ratio
    real(kind=4)        :: err_dry_ratio
    integer(kind=4)     :: fit_dry_ratio
    real(kind=4)        :: tcold_scale
    real(kind=4)        :: err_tcold_scale
    integer(kind=4)     :: fit_tcold_scale
    real(kind=4)        :: tcold_ratio
    real(kind=4)        :: err_tcold_ratio
    integer(kind=4)     :: fit_tcold_ratio
    real(kind=4)        :: chisq
    real(kind=4)        :: pwv_ratio
    real(kind=4)        :: err_pwv_ratio
    integer(kind=4)     :: fit_pwv_ratio
    real(kind=4)        :: dry_off
    real(kind=4)        :: err_dry_off
    integer(kind=4)     :: fit_dry_off
    real(kind=4)        :: dry_off_ratio
    real(kind=4)        :: err_dry_off_ratio
    integer(kind=4)     :: fit_dry_off_ratio
    integer(kind=4)     :: last_load
    real(kind=8)        :: freq_off
    ! Beam rotator related angles
    real(kind=8)        :: posangle
    real(kind=8)        :: beamangle
    real(kind=8)        :: anglediff
    real(kind=8)        :: rxdx
    real(kind=8)        :: rxdy
    real(kind=8)        :: refrxdx
    real(kind=8)        :: refrxdy
    integer(kind=4)     :: signrxdx
    integer(kind=4)     :: signrxdy
    real(kind=8)        :: focallength
    ! Atmospheric model
    integer(kind=4)     :: atm_model_dim(2)
    real(kind=4), allocatable :: atm_model_data(:,:)
    character(len=12), allocatable :: atm_model_param(:)
    ! Runtime setup of kalibrate
    character(len=256)  :: kalibraterc
    character(len=256)  :: kalibrate_args
    character(len=256)  :: processing_steps
    character(len=256)  :: backend_grouping
    ! Observation setup
    character(len=32)   :: aor_id
    integer(kind=4)     :: aot_id_len
    character(len=4), allocatable :: aot_id(:)
    real(kind=4)        :: main_beam_eff
    integer(kind=4)     :: pi_name_len
    character(len=4), allocatable :: pi_name(:)
  end type sofia_kalibrate_t
  !
end module sofia_types
!
subroutine sofia_fromclass1(skdata,version)
  use sofia_types
  use class_api
  !---------------------------------------------------------------------
  !
  !---------------------------------------------------------------------
  type(sofia_kalibrate_t), intent(out) :: skdata   ! The data to be filled with the Class buffer
  integer(kind=4),         intent(in)  :: version  ! The version of the data
  !
  ! print *,'>>> Entering sofia_fromclass1'
  !
  call class_user_classtodata(skdata%atmodel)
  call class_user_classtodata(skdata%atmid)
  call class_user_classtodata(skdata%atmarg)

  if (version .lt. 2) then
    return
  end if

  call class_user_classtodata(skdata%tamb_sofi)
  call class_user_classtodata(skdata%tempri1)
  call class_user_classtodata(skdata%tempsec1)

  call class_user_classtodata(skdata%gndspeed)
  call class_user_classtodata(skdata%heading)

  call class_user_classtodata(skdata%instrume)
  call class_user_classtodata(skdata%instcfg)
  call class_user_classtodata(skdata%frontend)
  call class_user_classtodata(skdata%backend)

  call class_user_classtodata(skdata%schpfrq)
  call class_user_classtodata(skdata%chpamp1)
  call class_user_classtodata(skdata%chpangle)

  if (version .lt. 3) then
    return
  end if

  call class_user_classtodata(skdata%datasrc)
  call class_user_classtodata(skdata%observer)
  call class_user_classtodata(skdata%operater)
  call class_user_classtodata(skdata%planid)
  call class_user_classtodata(skdata%mission_id)
  call class_user_classtodata(skdata%obs_id)

  if (version .lt. 4) then
    return
  end if

  call class_user_classtodata(skdata%pwv_mm)
  call class_user_classtodata(skdata%err_pwv_mm)
  call class_user_classtodata(skdata%fit_pwv_mm)

  call class_user_classtodata(skdata%ratio_f_th)

  call class_user_classtodata(skdata%dry_atm)
  call class_user_classtodata(skdata%err_dry_atm)
  call class_user_classtodata(skdata%fit_dry_atm)

  call class_user_classtodata(skdata%dry_ratio)
  call class_user_classtodata(skdata%err_dry_ratio)
  call class_user_classtodata(skdata%fit_dry_ratio)

  call class_user_classtodata(skdata%tcold_scale)
  call class_user_classtodata(skdata%err_tcold_scale)
  call class_user_classtodata(skdata%fit_tcold_scale)

  call class_user_classtodata(skdata%tcold_ratio)
  call class_user_classtodata(skdata%err_tcold_ratio)
  call class_user_classtodata(skdata%fit_tcold_ratio)

  if (version .lt. 5) then
    return
  end if

  call class_user_classtodata(skdata%chisq)

  if (version .lt. 6) then
    return
  end if

  call class_user_classtodata(skdata%pwv_ratio)
  call class_user_classtodata(skdata%err_pwv_ratio)
  call class_user_classtodata(skdata%fit_pwv_ratio)

  if (version .lt. 7) then
    return
  end if

  call class_user_classtodata(skdata%dry_off)
  call class_user_classtodata(skdata%err_dry_off)
  call class_user_classtodata(skdata%fit_dry_off)

  call class_user_classtodata(skdata%dry_off_ratio)
  call class_user_classtodata(skdata%err_dry_off_ratio)
  call class_user_classtodata(skdata%fit_dry_off_ratio)

  if (version .lt. 8) then
    return
  end if

  call class_user_classtodata(skdata%last_load)

  if (version .lt. 9) then
    return
  end if

  call class_user_classtodata(skdata%freq_off)

  if (version .lt. 10) then
    return
  end if

  call class_user_classtodata(skdata%posangle)
  call class_user_classtodata(skdata%beamangle)
  call class_user_classtodata(skdata%anglediff)

  if (version .lt. 11) then
    return
  end if

  call class_user_classtodata(skdata%rxdx)
  call class_user_classtodata(skdata%rxdy)
  call class_user_classtodata(skdata%refrxdx)
  call class_user_classtodata(skdata%refrxdy)
  call class_user_classtodata(skdata%signrxdx)
  call class_user_classtodata(skdata%signrxdy)
  call class_user_classtodata(skdata%focallength)

  if (version .lt. 12) then
    return
  end if

  call class_user_classtodata(skdata%atm_model_dim)
  if (allocated(skdata%atm_model_data)) then
    deallocate(skdata%atm_model_data)
  end if
  allocate(skdata%atm_model_data(skdata%atm_model_dim(1),skdata%atm_model_dim(2)))
  call class_user_classtodata(skdata%atm_model_data)

  if (version .lt. 13) then
    return
  end if

  if (allocated(skdata%atm_model_param)) then
    deallocate(skdata%atm_model_param)
  end if
  allocate(skdata%atm_model_param(skdata%atm_model_dim(1)))
  call class_user_classtodata(skdata%atm_model_param)

  if (version .lt. 14) then
    return
  end if
  call class_user_classtodata(skdata%kalibraterc)
  call class_user_classtodata(skdata%kalibrate_args)
  call class_user_classtodata(skdata%processing_steps)
  call class_user_classtodata(skdata%backend_grouping)

  if (version .lt. 15) then
     return
  end if
  call class_user_classtodata(skdata%aor_id)
  call class_user_classtodata(skdata%aot_id_len)
  if (allocated(skdata%aot_id)) then
     deallocate(skdata%aot_id)
  end if
  allocate(skdata%aot_id(skdata%aot_id_len/4))
  call class_user_classtodata(skdata%aot_id)
  if (version .lt. 16) then
     return
  end if
  call class_user_classtodata(skdata%main_beam_eff)

  call class_user_classtodata(skdata%pi_name_len)
  if (allocated(skdata%pi_name)) then
     deallocate(skdata%pi_name)
  end if
  allocate(skdata%pi_name(skdata%pi_name_len/4))
  call class_user_classtodata(skdata%pi_name)
  return
  !
end subroutine sofia_fromclass1
!
subroutine sofia_dump1(version,error)
  use sofia_types
  !---------------------------------------------------------------------
  ! Hook for command LAS\DUMP
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: version  ! The version of the data
  logical,         intent(inout) :: error    ! Logical error flag
  ! Local
  type(sofia_kalibrate_t) :: skdata   ! The data to be listed
  !
  ! print *,'>>> Entering sofia_dump1 for version ',version
  !
  call sofia_fromclass1(skdata,version)
  !
  print *,' atmodel            = ',skdata%atmodel
  print *,' atmid              = ',skdata%atmid
  print *,' atmarg             = ',skdata%atmarg

  if (version .lt. 2) then
    return
  end if

  print *,' tamb_sofi          = ',skdata%tamb_sofi
  print *,' tempri1            = ',skdata%tempri1
  print *,' tempsec1           = ',skdata%tempsec1

  print *,' gndspeed           = ',skdata%gndspeed
  print *,' heading            = ',skdata%heading

  print *,' instrume           = ',skdata%instrume
  print *,' instcfg            = ',skdata%instcfg
  print *,' frontend           = ',skdata%frontend
  print *,' backend            = ',skdata%backend

  print *,' schpfrq            = ',skdata%schpfrq
  print *,' chpamp1            = ',skdata%chpamp1
  print *,' chpangle           = ',skdata%chpangle

  if (version .lt. 3) then
    return
  end if

  print *,' datasrc            = ',skdata%datasrc
  print *,' observer           = ',skdata%observer
  print *,' operator           = ',skdata%operater
  print *,' planid             = ',skdata%planid
  print *,' mission_id         = ',skdata%mission_id
  print *,' obs_id             = ',skdata%obs_id

  if (version .lt. 4) then
    return
  end if

  print *,' pwv_mm             = ',skdata%pwv_mm
  print *,' err_pwv_mm         = ',skdata%err_pwv_mm
  print *,' fit_pwv_mm         = ',skdata%fit_pwv_mm

  print *,' ratio_f_th         = ',skdata%ratio_f_th

  print *,' dry_atm            = ',skdata%dry_atm
  print *,' err_dry_atm        = ',skdata%err_dry_atm
  print *,' fit_dry_atm        = ',skdata%fit_dry_atm

  print *,' dry_ratio          = ',skdata%dry_ratio
  print *,' err_dry_ratio      = ',skdata%err_dry_ratio
  print *,' fit_dry_ratio      = ',skdata%fit_dry_ratio

!  print *,' tcold_scale        = ',skdata%tcold_scale
!  print *,' err_tcold_scale    = ',skdata%err_tcold_scale
!  print *,' fit_tcold_scale    = ',skdata%fit_tcold_scale

!  print *,' tcold_ratio        = ',skdata%tcold_ratio
!  print *,' err_tcold_ratio    = ',skdata%err_tcold_ratio
!  print *,' fit_tcold_ratio    = ',skdata%fit_tcold_ratio

  if (version .lt. 5) then
    return
  end if

  print *,' chisq              = ',skdata%chisq

  if (version .lt. 6) then
    return
  end if

  print *,' pwv_ratio          = ',skdata%pwv_ratio
  print *,' err_pwv_ratio      = ',skdata%err_pwv_ratio
  print *,' fit_pwv_ratio      = ',skdata%fit_pwv_ratio

  if (version .lt. 7) then
    return
  end if

  print *,' dry_off            = ',skdata%dry_off
  print *,' err_dry_off        = ',skdata%err_dry_off
  print *,' fit_dry_off        = ',skdata%fit_dry_off

  print *,' dry_off_ratio      = ',skdata%dry_off_ratio
  print *,' err_dry_off_ratio  = ',skdata%err_dry_off_ratio
  print *,' fit_dry_off_ratio  = ',skdata%fit_dry_off_ratio

  if (version .lt. 8) then
    return
  end if

  print *,' last_load          = ',skdata%last_load

  if (version .lt. 9) then
    return
  end if

  print *,' freq_off           = ',skdata%freq_off

  if (version .lt. 10) then
    return
  end if

  print *,' posangle           = ',skdata%posangle
  print *,' beamangle          = ',skdata%beamangle
  print *,' anglediff          = ',skdata%anglediff

  if (version .lt. 11) then
    return
  end if

  print *,' rxdx               = ',skdata%rxdx
  print *,' rxdy               = ',skdata%rxdy
  print *,' refrxdx            = ',skdata%refrxdx
  print *,' refrxdy            = ',skdata%refrxdy
  print *,' signrxdx           = ',skdata%signrxdx
  print *,' signrxdy           = ',skdata%signrxdy
  print *,' focallength        = ',skdata%focallength

  if (version .lt. 12) then
    return
  end if

  print *,' atm_model_dim      = ',skdata%atm_model_dim
  print *,' atm_model_data     = (2-D array)'

  if (version .lt. 13) then
    return
  end if

  print *,' atm_model_param    = (string array)'

  if (version .lt. 14) then
    return
  end if

  print *,' kalibraterc        = ',trim(skdata%kalibraterc)
  print *,' kalibrate_args     = ',trim(skdata%kalibrate_args)
  print *,' processing_steps   = ',trim(skdata%processing_steps)
  print *,' backend_grouping   = ',trim(skdata%backend_grouping)

  if (version .lt. 15) then
     return
  end if

  print *,' aor_id             = ',skdata%aor_id
  print *,' aot_id_len         = ',skdata%aot_id_len
  print *,' aot_id             =  (character array)'

  if (version .lt. 16) then
     return
  end if

  print *,' main_beam_eff      = ',skdata%main_beam_eff
  print *,' pi_name_len        = ',skdata%pi_name_len
  print *,' pi_name            =  (character array)'

  return
  !
end subroutine sofia_dump1
!
subroutine sofia_setvar1(version,error)
  use gbl_message
  use class_api
  use sofia_types
  !---------------------------------------------------------------------
  ! Hook for command LAS\SET VARIABLE USER
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: version  ! The version of the data
  logical,         intent(inout) :: error    ! Logical error flag
  ! Local
  integer(kind=4) :: ndim,dims(4)
  character(len=*), parameter :: rname='SOFIA_SETVAR1'
  !
  ! print *,'>>> Entering sofia_setvar1 for version ',version
  !
  error = .false.
  ndim = 0
  call class_user_def_char('ATMODEL',12,error)
  call class_user_def_char('ATMID',36,error)
  call class_user_def_inte('ATMARG',ndim,dims,error)

  if (version .lt. 2) then
    return
  end if

  call class_user_def_real('TAMB_SOFI',ndim,dims,error)
  call class_user_def_real('TEMPRI1',ndim,dims,error)
  call class_user_def_real('TEMPSEC1',ndim,dims,error)

  call class_user_def_real('GNDSPEED',ndim,dims,error)
  call class_user_def_real('HEADING',ndim,dims,error)

  call class_user_def_char('INSTRUME',16,error)
  call class_user_def_char('INSTCFG',32,error)
  call class_user_def_char('FRONTEND',16,error)
  call class_user_def_char('BACKEND',16,error)

  call class_user_def_real('SCHPFRQ',ndim,dims,error)
  call class_user_def_real('CHPAMP1',ndim,dims,error)
  call class_user_def_dble('CHPANGLE',ndim,dims,error)

  if (version .lt. 3) then
    return
  end if

  call class_user_def_char('DATASRC',32,error)
  call class_user_def_char('OBSERVER',32,error)
  call class_user_def_char('OPERATOR',32,error)
  call class_user_def_char('PLANID',32,error)
  call class_user_def_char('MISSION_ID',32,error)
  call class_user_def_char('OBS_ID',32,error)

  if (version .lt. 4) then
    return
  end if

  call class_user_def_real('PWV_MM',ndim,dims,error)
  call class_user_def_real('ERR_PWV_MM',ndim,dims,error)
  call class_user_def_inte('FIT_PWV_MM',ndim,dims,error)

  call class_user_def_dble('RATIO_F_TH',ndim,dims,error)

  call class_user_def_real('DRY_ATM',ndim,dims,error)
  call class_user_def_real('ERR_DRY_ATM',ndim,dims,error)
  call class_user_def_inte('FIT_DRY_ATM',ndim,dims,error)

  call class_user_def_real('DRY_RATIO',ndim,dims,error)
  call class_user_def_real('ERR_DRY_RATIO',ndim,dims,error)
  call class_user_def_inte('FIT_DRY_RATIO',ndim,dims,error)

  call class_user_def_real('TCOLD_SCALE',ndim,dims,error)
  call class_user_def_real('ERR_TCOLD_SCALE',ndim,dims,error)
  call class_user_def_inte('FIT_TCOLD_SCALE',ndim,dims,error)

  call class_user_def_real('TCOLD_RATIO',ndim,dims,error)
  call class_user_def_real('ERR_TCOLD_RATIO',ndim,dims,error)
  call class_user_def_inte('FIT_TCOLD_RATIO',ndim,dims,error)

  if (version .lt. 5) then
    return
  end if

  call class_user_def_real('CHISQ',ndim,dims,error)

  if (version .lt. 6) then
    return
  end if

  call class_user_def_real('PWV_RATIO',ndim,dims,error)
  call class_user_def_real('ERR_PWV_RATIO',ndim,dims,error)
  call class_user_def_inte('FIT_PWV_RATIO',ndim,dims,error)

  if (version .lt. 7) then
    return
  end if

  call class_user_def_real('DRY_OFF',ndim,dims,error)
  call class_user_def_real('ERR_DRY_OFF',ndim,dims,error)
  call class_user_def_inte('FIT_DRY_OFF',ndim,dims,error)

  call class_user_def_real('DRY_OFF_RATIO',ndim,dims,error)
  call class_user_def_real('ERR_DRY_OFF_RATIO',ndim,dims,error)
  call class_user_def_inte('FIT_DRY_OFF_RATIO',ndim,dims,error)

  if (version .lt. 8) then
    return
  end if

  call class_user_def_inte('LAST_LOAD',ndim,dims,error)

  if (version .lt. 9) then
    return
  end if

  call class_user_def_dble('FREQ_OFF',ndim,dims,error)

  if (version .lt. 10) then
    return
  end if

  call class_user_def_dble('POSANGLE',ndim,dims,error)
  call class_user_def_dble('BEAMANGLE',ndim,dims,error)
  call class_user_def_dble('ANGLEDIFF',ndim,dims,error)

  if (version .lt. 11) then
    return
  end if

  call class_user_def_dble('RXDX',ndim,dims,error)
  call class_user_def_dble('RXDY',ndim,dims,error)
  call class_user_def_dble('REFRXDX',ndim,dims,error)
  call class_user_def_dble('REFRXDY',ndim,dims,error)
  call class_user_def_inte('SIGNRXDX',ndim,dims,error)
  call class_user_def_inte('SIGNRXDY',ndim,dims,error)
  call class_user_def_dble('FOCALLENGTH',ndim,dims,error)

  if (version .lt. 12) then
    return
  end if

  ndim = 1
  dims(1) = 2
  call class_user_def_inte('ATM_MODEL_DIM',ndim,dims,error)
  call sic_get_inte('R%USER%SOFIA%ATM_MODEL_DIM[1]',dims(1),error)
  if (error) then
    call class_message(seve%e, rname, 'Cannot get R%USER%SOFIA%ATM_MODEL_DIM[1]')
    return
  end if
  call sic_get_inte('R%USER%SOFIA%ATM_MODEL_DIM[2]',dims(2),error)
  if (error) then
    call class_message(seve%e, rname, 'Cannot get R%USER%SOFIA%ATM_MODEL_DIM[2]')
    return
  end if
  if (dims(1)*dims(2) .gt. 0) then
    ndim = 2
    call class_user_def_real('ATM_MODEL_DATA',ndim,dims,error)
  end if
  ndim = 0

  if (version .lt. 13) then
    return
  end if

  if (dims(1) .gt. 0) then
    call class_user_def_char('ATM_MODEL_PARAM',12*dims(1),error)
  end if

  if (version .lt. 14) then
    return
  end if

  call class_user_def_char('KALIBRATERC',256,error)
  call class_user_def_char('KALIBRATE_ARGS',256,error)
  call class_user_def_char('PROCESSING_STEPS',256,error)
  call class_user_def_char('BACKEND_GROUPING',256,error)

  if (version .lt. 15) then
     return
  end if

  call class_user_def_char('AOR_ID',32,error)
  call class_user_def_inte('AOT_ID_LEN',ndim,dims,error)
  call sic_get_inte('R%USER%SOFIA%AOT_ID_LEN',dims(1),error)
  if (error) then
     call class_message(seve%e, rname, 'Cannot get AOT_ID_LEN')
     return
  end if
  call class_user_def_char('AOT_ID',dims(1),error)

  if (version .lt. 16) then
     return
  end if
  call class_user_def_real('MAIN_BEAM_EFF',ndim,dims,error)
  call class_user_def_inte('PI_NAME_LEN',ndim,dims,error)
  call sic_get_inte('R%USER%SOFIA%PI_NAME_LEN',dims(1),error)
  if (error) then
     call class_message(seve%e, rname, 'Cannot get PI_NAME_LEN')
     return
  end if
  call class_user_def_char('PI_NAME',dims(1),error)

  return
  !
end subroutine sofia_setvar1
