subroutine clic_monitor(line,error)
  use gkernel_interfaces
  use gildas_def
  use classic_api
  use clic_index
  !---------------------------------------------------------------------
  ! Command MONITOR
  ! It processes CAL scans as encountered, to deduce the atmospheric
  ! parameters from the monitor at 230 GHz (receiver 2, in fact).
  ! Monitor time 0|1
  ! time defaults to 1 h ; 0 means each interval is one scan
  ! 0 for constant, 1 for linear fit to the atm power data.
  !---------------------------------------------------------------------
  character(len=*) :: line          !
  logical :: error                  !
  ! Global
  include 'clic_parameter.inc'
  include 'clic_clic.inc'
  include 'clic_par.inc'
  include 'gbl_pi.inc'
  include 'clic_dheader.inc'
  include 'clic_proc_par.inc'
  include 'gbl_memory.inc'
  ! Local
  logical :: end, do_write
  integer(kind=address_length) :: data_in, kin
  integer(kind=data_length)    :: ldata_in 
  integer(kind=entry_length)   :: k,kx,kxsave,kx1,kx2
  integer :: ia,izero, it
  integer :: save_mon(matmon), s_scan
  character(len=12) :: source1,ch
  real*8 :: interval, mininterval, t_old, t_now, dt
  !      PARAMETER (MININTERVAL=55.0D0)
  parameter (mininterval=10.0d0)
  integer :: chop, cold, sky, mes, i
  parameter (chop=1, cold=2, sky=3)
  real*8 :: st(3), st2(3), sw(3), t0(3,mnant), t1(3,mnant), dn
  real*8 :: sy(3,mnant), syt(3,mnant)
  real*8 :: times(m_cx)
  real :: test
  !
  ! probably not useful here 18-oct-1999
  save save_mon, s_scan
  !------------------------------------------------------------------------
  ! Code:
  call check_input_file(error)
  if (error) return
  call check_index(error)
  if (error) return
  do_write = .not.sic_present(3,0)
  if (do_write) then
    call check_output_file(error)
    if (error) return
    call check_equal_file(error)
    if (error) return
  endif
  !
  ! default 1 hour
  ! Monitor 0 : use average of scan as reference
  !
  interval = 3600.0d0
  call sic_r8(line,0,1,interval,.false.,error)
  interval = max(mininterval,interval)
  !
  ideg = 0
  call sic_i4(line,0,2,ideg,.false.,error)
  ideg = max(0,ideg)
  ideg = min(1,ideg)
  !
  ! Loop on current index
  call get_first(.true.,error)
  if (error) return
  do i=1, mnant
    r_ccold_mon(i) = 0
    r_cchop_mon(i) = 0
    r_csky_mon(i) = 0
  enddo
  call r4tor4(r_nrec_mon,save_mon,matmon)
  !
  ! Get storage and data
  call get_data (ldata_in,data_in,error)
  if (error) return
  ! Decode average data record header:
  kin = gag_pointer(data_in,memory) + r_ndump*r_ldump
  call decode_header (memory(kin))
  source1 = r_sourc
  do i=1, 3
    sw(i) = 0
    st(i) = 0
    st2(i) = 0
  enddo
  do ia = 1, r_nant
    do i=1, 3
      sy(i,ia) = 0
      syt(i,ia) = 0
    enddo
  enddo
  izero = dh_obs
  t_now = mod(dh_utc+86400d0-dh_integ/2.d0,86400d0)
  t_old = t_now
  times(knext) = 0
  kx1 = knext
  kx2 = knext
  end = .false.
  do while (.not.end)
    !
    ! Process
    mes = 0
    if (r_proc.eq.p_cal .and. r_scaty.eq.4) then
      mes = chop
    elseif (r_proc.eq.p_cal .and. r_scaty.eq.7) then
      mes = cold
    elseif (r_proc.ne.p_pass) then
      mes = sky
    endif
    if (mes.ne.0) then
      dt = t_now-t_old
      do ia=1, r_nant
        sy(mes,ia) = sy(mes,ia)+dh_test1(2,ia)*dh_integ
        syt(mes,ia) = syt(mes,ia)+dh_test1(2,ia)*dt*dh_integ
      enddo
      st(mes) = st(mes)+dt*dh_integ
      st2(mes) = st2(mes)+dt**2*dh_integ
      sw(mes) = sw(mes)+dh_integ
    endif
    !
    ! Next observation
    if (sic_ctrlc()) then
      error = .true.
      return
    endif
    kx2 = knext
    error = .false.
    s_scan = r_scan
    call get_next(end, error)
    if (error) return
    !
    ! Get storage and data
    call get_data (ldata_in,data_in,error)
    if (error) return
    kin = gag_pointer(data_in,memory) + r_ndump*r_ldump
    call decode_header (memory(kin))
    it = dh_obs-izero
    t_now = dble(it)*86400d0   &
      +mod(dh_utc-dh_integ/2.+86400d0,86400d0)
    times(knext) = t_now-t_old
    !
    ! Write the data if period has elapsed:
    if (end .or. (r_scan.ne.s_scan .and. ((r_sourc.ne.source1)   &
      .or. (dabs(t_old-t_now).ge.interval)))) then
      !
      ! Compute the regression coefficients
      do i=1, 3
        dn = st2(i)*sw(i)-st(i)**2
        if (dn.ne.0 .and. ideg.eq.1) then
          do ia = 1,r_nant
            t1(i,ia)=(syt(i,ia)*sw(i)-sy(i,ia)*st(i))/dn
            t0(i,ia)=-(syt(i,ia)*st(i)-sy(i,ia)*st2(i))/dn
          enddo
        elseif (sw(i).ne.0) then
          do ia = 1,r_nant
            t1(i,ia)=0
            t0(i,ia)=sy(i,ia)/sw(i)
          enddo
        else
          do ia = 1,r_nant
            t1(i,ia)=0
            t0(i,ia)=0
          enddo
        endif
      enddo
      !
      if (sw(chop).eq.0 .and. interval.gt.mininterval) then
        write(ch,'(i4,a4,i4)')   &
          ix_scan(cx_ind(kx1)),' to ',ix_scan(cx_ind(kx2))
        call message(8,2,'MONITOR   ',   &
          'Uncalibrated monitor data scans '//ch(1:12))
      endif
      !
      ! reset the counters
      do i=1, 3
        sw(i) = 0
        st(i) = 0
        st2(i) = 0
      enddo
      do ia = 1, r_nant
        do i=1, 3
          sy(i,ia) = 0
          syt(i,ia) = 0
        enddo
      enddo
      kxsave = r_xnum
      do k = kx1, kx2
        kx = cx_ind(k)
        call get_it(kx, error)
        if (r_proc.eq.p_cal .and. r_scaty.eq.5) then
          do ia=1,r_nant
            test  = t1(chop,ia)*times(k)+t0(chop,ia)
            if (test.gt.0) r_cchop_mon(ia)=test
            r_ccold_mon(ia) = t1(cold,ia)*times(k)+t0(cold,ia)
          enddo
          error = .false.
          call do_monitor (.false.,error)
          do i=1, mnant
            r_ccold_mon(i) = 0
          enddo
          if (.not.error)   &
            call r4tor4(r_nrec_mon,save_mon,matmon)
        else
          call r4tor4(save_mon,r_nrec_mon,matmon)
        endif
        do ia=1,r_nant
          r_csky_mon(ia)=t1(sky,ia)*times(k)+t0(sky,ia)
        enddo
        if (do_write) then
          call write_scan (.false.,error)
          if (error) return
        endif
      enddo
      ! after writing, reload the next scan
      if (.not.end) then
        call get_it(kxsave, error)
        kx1 = knext
        kx2 = knext
        t_old = t_now
        times(knext) = 0
        source1 = r_sourc
      endif
    endif
  enddo
  !
  return
end subroutine clic_monitor
!
subroutine do_monitor (again,error)
  use gkernel_interfaces
  use gildas_def
  use classic_api  
  !---------------------------------------------------------------------
  ! The chopper standard program is called for each antenna,
  ! in the mode selected in OBS.
  !---------------------------------------------------------------------
  logical :: again                  !
  logical :: error                  !
  ! Global
  include 'clic_parameter.inc'
  include 'clic_par.inc'
  include 'clic_clic.inc'
  include 'clic_display.inc'
  include 'clic_proc_par.inc'
  ! Local
  integer :: ia, ntrec
  real :: frs, fri, fro, awater, prec_water
  character(len=160) :: ch
  integer :: mode_au, mode_tr, ilevel
  character(len=4) :: cmode(mnant)
  character(len=2) :: chcode
  !------------------------------------------------------------------------
  ! Code:
  call chtoby('AU  ',mode_au,4)
  call chtoby('TR  ',mode_tr,4)
  ! Force input values if desired
  ilevel = 1
  if (r_proc.eq.p_cal) ilevel=6
  do ia = 1, r_nant
    !
    ! Water
    if (atm_mode(ia).eq.'AUTO') then
      if (atm_water.eq.0) then
        r_h2o_mon(ia) =  prec_water(r_tamb,r_humid)
      elseif (atm_water.gt.0) then
        r_h2o_mon(ia) = atm_water
      endif
      r_cmode_mon(ia) = mode_au
    elseif (atm_mode(ia).eq.'TREC') then
      if (atm_trec(ia).gt.0) then
        r_trec_mon(ia) = atm_trec(ia)
      endif
      r_cmode_mon(ia) = mode_tr
    endif
    !
    ! Gain Image
    if (atm_gim(ia).gt.0) then
      r_gim_mon(ia) = atm_gim(ia)
    endif
    write(cmode(ia),'(a2)')  chcode(r_cmode_mon(ia))
  enddo
  ! Get continuum measurement
  frs = r_frs_mon/1000.
  fri = r_fri_mon/1000.
  fro = r_flo1/1000.
  !
  ! TREC antennas
  ntrec = 0
  awater = 0
  do ia=1, r_nant
    !         print *, 'ia, cmode(ia), R_CMODE_MON(IA)',
    !     $        ia, cmode(ia), R_CMODE_MON(IA)
    if (cmode(ia).eq.'TR') then
      error = .false.
      call chopper_mon (cmode(ia), r_el, frs, fri, r_tamb,   &
        r_pamb, r_alti, r_feff_mon(ia),   &
        r_tchop_mon(ia), r_tcold_mon(ia), r_trec_mon(ia),   &
        r_gim_mon(ia), r_csky_mon(ia), r_cchop_mon(ia),   &
        r_ccold_mon(ia), r_tsys_mon(ia), r_tem_mon(ia),   &
        r_h2o_mon(ia), r_tatms_mon(ia), r_tatmi_mon(ia),   &
        r_taus_mon(ia), r_taui_mon(ia),   &
        again,fro, r_path_mon(ia), r_dpath_mon(ia), error)
      if (.not.again) then
        write(ch,1000) r_kant(ia),   &
          chcode(r_cmode_mon(ia)), r_h2o_mon(ia),   &
          r_trec_mon(ia), r_tsys_mon(ia), r_tem_mon(ia),   &
          r_dpath_mon(ia)
        call message(ilevel,1,'MONITOR   ',ch(1:lenc(ch)))
      endif
      if (.not.error) then
        awater = awater+r_h2o_mon(ia)
        ntrec = ntrec+1
      endif
    endif
  enddo
  if (ntrec.gt.0) awater = awater / ntrec
  !
  ! Then other modes
  do ia = 1, r_nant
    if (r_cmode_mon(ia).eq.mode_au) then
      if (ntrec.gt.0) r_h2o_mon(ia) = awater
    endif
    if (cmode(ia).ne.'TR' .and. cmode(ia).ne.'NO') then
      error = .false.
      call chopper_mon (cmode(ia), r_el, frs, fri, r_tamb,   &
        r_pamb, r_alti, r_feff_mon(ia),   &
        r_tchop_mon(ia), r_tcold_mon(ia), r_trec_mon(ia),   &
        r_gim_mon(ia), r_csky_mon(ia), r_cchop_mon(ia),   &
        r_ccold_mon(ia), r_tsys_mon(ia), r_tem_mon(ia),   &
        r_h2o_mon(ia), r_tatms_mon(ia), r_tatmi_mon(ia),   &
        r_taus_mon(ia), r_taui_mon(ia),   &
        again,fro, r_path_mon(ia), r_dpath_mon(ia), error)
      if (.not.again) then
        write(ch,1000) r_kant(ia),   &
          chcode(r_cmode_mon(ia)), r_h2o_mon(ia),   &
          r_trec_mon(ia), r_tsys_mon(ia), r_tem_mon(ia),   &
          r_dpath_mon(ia)
        call message(ilevel,1,'MONITOR   ',ch(1:lenc(ch)))
      endif
    endif
  enddo
  !
  return
1000 format('A',i1,1x,a2,' H2O=',f6.2,' Tr=',f5.1,   &
    ' Tsys=',f5.1,' Tem=',f5.1,' Dpath=',f6.3)
end subroutine do_monitor
!
subroutine chopper_mon (cmode, el, frs, fri, tamb, pamb, alti,   &
    feff, tchop, tcold, trec, gim, csky, cchop, ccold,   &
    tsysd, tem, h2o, tatms, tatmi, taus, taui,   &
    again, fro, path, dpath, error)
  use gkernel_interfaces
  use atm_interfaces_public
  !---------------------------------------------------------------------
  ! CLIC
  !	compute TCAL, TSYS, TREC, from the chop and atm values observed
  !	according to the usual chopper method (Ulich and Haas)
  !
  !	Double side band operation
  !
  !	_ If cmode is 'AU' and a cold load is available, or if cmode
  !	is 'TR', derive the sky emission TEMI from the receiver
  !	temperature TREC, and then H2O from the best model fitting.
  !	_ Else, if cmode is 'AU', the sky emission is computed from
  !	the given H2O,
  !       _ if cmode is 'MA', the sky emission is computed from the
  !       given opacities and atmospheric temperatures.
  !
  !  	Uses a curved atmosphere, equivalent height 5.5 KM
  !
  !	FRS, FRI   I	R Frequencies signal image in GHz (!!!)
  !       tamb       I    R Ambient temperature (K)
  !       pamb       I    R Ambient pressure (mbar)
  !       alti       I    R altitude in km
  !       FEFF       I    R Forward Eff
  !       BEFF       I    R Beam Eff
  !       TCHOP      I    R Ambient Load Temperature (K)
  !       TCOLD      I    R Cold  Load Temperature (K)
  !       GIM        I    R Image/Signal Gain ratio
  !       CCHOP      I    R Ambient Load Counts
  !       CSKY       I    R Sky Counts
  !       CCOLD      I    R Cold  Load Counts
  !	TREC       I/O  R Receiver dsb temperature (K)
  !	TSYSD 	   O    R DSB system temperature (K)
  !       H2O        O    R Water vapor content (mm)
  !---------------------------------------------------------------------
  include 'clic_parameter.inc'
  include 'clic_clic.inc'
  !
  character(len=2) :: cmode         !
  real :: el                        !
  real :: frs                       !
  real :: fri                       !
  real :: tamb                      !
  real :: pamb                      !
  real :: alti                      !
  real :: feff                      !
  real :: tchop                     !
  real :: tcold                     !
  real :: trec                      !
  real :: gim                       !
  real :: csky                      !
  real :: cchop                     !
  real :: ccold                     !
  real :: tsysd                     !
  real :: tem                       !
  real :: h2o                       !
  real :: tatms                     !
  real :: tatmi                     !
  real :: taus                      !
  real :: taui                      !
  logical :: again                  !
  real :: fro                       !
  real :: path                      !
  real :: dpath                     !
  logical :: error                  !
  ! Global
  real*8 :: air_mass
  ! Local
  real :: dtem, airmas, tatm, taut, dwater, err, deltaw
  real :: temis, temii, tsky, temi, t1, t2, h2o1, path1
  real :: h2o2, path2, tem1, tem2, t3, t4
  integer :: k, ier, lc
  character(len=80) :: chain
  !------------------------------------------------------------------------
  error = .false.
  ier = 0
  airmas = air_mass(el)
  !
  if (again) goto 500
  !
  ! Check for Really bad atmosphere
  if (csky.ge.cchop) then
    write(chain,1000) csky, cchop
1000 format('Bad Atmosphere: SKY=',1pg11.4,'; CHOP=',1pg11.4)
    lc = lenc(chain)
    call message (8,3,'CHOPPER_MON',chain(1:lc))
    error = .true.
    return
  endif
  if (ccold.ge.cchop) then
    call message (8,3,'CHOPPER_MON',   &
      'Signal stronger on COLD than on CHOPPER')
    error = .true.
    return
  endif
  !
  ! AUTO mode with cold load or fixed TREC : minimize for water vapor
  ! content
  if ((cmode.eq.'AU' .and. ccold.gt.0)   &
    .or. cmode.eq.'TR') then
    if (atm_interpolate) then
      call atm_atmosp_i (tamb, pamb, alti)   ! press at 2550m
    else
      call atm_atmosp (tamb, pamb, alti)   ! press at 2550m
    endif
    ! use a reasonable starting value
    h2o = min(10.,max(0.5,h2o))
    !
    ! cold load available: compute TREC
    if (ccold.ne.0) then
      trec = (tcold*cchop - tchop*ccold ) / (ccold-cchop)
    endif
    !
    ! Compute TSKY: antenna temperature on sky
    tsky = (tchop+trec) *csky/cchop-trec
    !
    ! And TEMI: brightness temperature of sky
    temi = (tsky - (1.-feff)*tamb) / feff
    err = 1e10
    dwater = .02
    k = 0
10  continue
    k = k + 1
    if (atm_interpolate) then
      call atm_transm_i (h2o,airmas,frs,temis,tatms,t1,t2,taut,ier)
      taus = t1 + t2
      call atm_transm_i (h2o,airmas,fri,temii,tatmi,t1,t2,taut,ier)
      taui = t1 + t2
      tem = (temis + temii*gim) / (1.+gim)
      call atm_transm_i (h2o+dwater,airmas,frs,temis,   &
        tatm, t1, t2, taut,ier)
      call atm_transm_i (h2o+dwater, airmas, fri,temii,   &
        tatm, t1, t2, taut,ier)
    else
      call atm_transm (h2o,airmas,frs,temis,tatms,t1,t2,taut,ier)
      taus = t1 + t2
      call atm_transm (h2o,airmas,fri,temii,tatmi,t1,t2,taut,ier)
      taui = t1 + t2
      tem = (temis + temii*gim) / (1.+gim)
      call atm_transm (h2o+dwater,airmas,frs,temis,   &
        tatm, t1, t2, taut,ier)
      call atm_transm (h2o+dwater, airmas, fri,temii,   &
        tatm, t1, t2, taut,ier)
    endif
    dtem = (temis + temii*gim) / (1.+gim) - tem
    err = tem - temi
    if (abs(err) .ge. 0.1 .and. dtem.ne.0 .and. k.le.10) then
      deltaw = dwater * err / dtem
      if(abs(dwater).ge.abs(deltaw/10.)) dwater = deltaw/10.
      ! limit optical depth to [0.01,~20]
      h2o = max(0.01,min(h2o-deltaw,   &
        20.*h2o/max(taus,taui)/airmas))
      goto 10
    endif
    if (atm_interpolate) then
      call atm_transm_i  (h2o,airmas,frs,temis,tatms,t1,t2,taut,ier)
      call atm_transm_i  (h2o,airmas,fri,temii,tatmi,t1,t2,taut,ier)
    else
      call atm_transm  (h2o,airmas,frs,temis,tatms,t1,t2,taut,ier)
      call atm_transm  (h2o,airmas,fri,temii,tatmi,t1,t2,taut,ier)
    endif
    taus = t1 + t2
    taui = t1 + t2
    tem = (temis + temii*gim) / (1.+gim)
  elseif (cmode .eq. 'AU') then
    !
    ! Auto Mode without cold load, or when the water vapor content is known
    if (atm_interpolate) then
      call atm_atmosp_i (tamb, pamb, alti)   ! press at 2550m
      call atm_transm_i (h2o,airmas,frs,temis,tatms,t1,t2,taut,ier)
      call atm_transm_i (h2o,airmas,fri,temii,tatmi,t1,t2,taut,ier)
    else
      call atm_atmosp (tamb, pamb, alti)   ! press at 2550m
      call atm_transm (h2o,airmas,frs,temis,tatms,t1,t2,taut,ier)
      call atm_transm (h2o,airmas,fri,temii,tatmi,t1,t2,taut,ier)
    endif
    taus = t1 + t2
    taui = t1 + t2
    tem = (temis + temii*gim) / (1.+gim)
    tsky = (1.-feff)*tamb + feff*tem
  !
  ! Manual Mode
  elseif (cmode.eq.'MA') then
    temis = tatms * (1.-exp(-taus*airmas))
    temii = tatmi * (1.-exp(-taui*airmas))
    tem = (temis + temii*gim) / (1.+gim)
    tsky = (1.-feff)*tamb + feff*tem
  else
    call message(8,4,'CHOPPER_MON','Invalid mode '//cmode)
    error = .true.
    return
  endif
  !
  ! Compute TREC
  if (cmode.ne.'TR') then
    trec = (csky*tchop - tsky*cchop) / (cchop-csky)
  endif
  !
  ! Compute TSYSD
  tsysd = (trec+tsky)/feff
  tsysd = max(min(1e10,tsysd),0.)
  !
  ! Get pathlength (in mm.)  and difference at observing frequency
  !
500 call atm_atmosp_i (tamb, pamb, alti)
  call atm_path_i(h2o,airmas,fro,path,ier)
  path = path*10.
  !
  h2o1 = h2o-0.1
  call atm_path_i(h2o1,airmas,fro,path1,ier)
  path1 = path1*10.
  call atm_transm_i (h2o1,airmas,frs,temis,t3,t1,t2,t4,ier)
  call atm_transm_i (h2o1,airmas,fri,temii,t3,t1,t2,t4,ier)
  tem1 = (temis + temii*gim)/(1.+gim)
  !
  h2o2 = h2o+0.1
  call atm_path_i(h2o2,airmas,fro,path2,ier)
  path2 = path2*10.
  call atm_transm_i (h2o2,airmas,frs,temis,t3,t1,t2,t4,ier)
  call atm_transm_i (h2o2,airmas,fri,temii,t3,t1,t2,t4,ier)
  tem2 = (temis + temii*gim)/(1.+gim)
  !
  dtem = tem2 - tem1
  if (dtem.ne.0) then
    dpath = (path2-path1) / dtem
  else
    dpath = path
  endif
  return
end subroutine chopper_mon
