subroutine solve_monitor(line,error)
  use gildas_def
  use gkernel_interfaces
  character(len=*) :: line          !
  logical :: error                  !
  ! Global
  include 'clic_parameter.inc'
  include 'clic_display.inc'
  include 'gbl_memory.inc'
  ! Local
  integer :: m_mon
  integer(kind=address_length) :: ipx,ipy,ipw,ips,ipmon,data_mon
  !------------------------------------------------------------------------
  ! Code:
  ipx = gag_pointer(data_x,memory)
  ipy = gag_pointer(data_y,memory)
  ipw = gag_pointer(data_w,memory)
  ips = gag_pointer(data_s,memory)
  !
  ! just in case m_data has changed
  call get_first(.true.,error)
  !
  m_mon = m_data*8
  error = sic_getvm(m_mon,data_mon).ne.1
  if (error) goto 999
  ipmon = gag_pointer(data_mon,memory)
  call sub_solve_mon(m_data,m_boxes,memory(ipx),   &
    memory(ipy),memory(ipw),   &
    memory(ips), memory(ipmon+6*m_data),   &
    memory(ipmon),   &
    memory(ipmon+2*m_data), memory(ipmon+4*m_data),   &
    line,error)
  call free_vm(m_mon,data_mon)
  return
  !
999 error = .true.
  return
end subroutine solve_monitor
!
subroutine sub_solve_mon(md,mb,x_data,y_data,w_data,   &
    ind,wk1,xxx,yyy,www,line,error)
  use gildas_def
  use gkernel_interfaces
  use classic_api  
  integer :: md                     !
  integer :: mb                     !
  real :: x_data(md,mb)             !
  real :: y_data(md,mb)             !
  real :: w_data(md,mb)             !
  integer :: ind(md)                !
  real*8 :: wk1(3*md)               !
  real*8 :: xxx(md)                 !
  real*8 :: yyy(md)                 !
  real*8 :: www(md)                 !
  character(len=*) :: line          !
  logical :: error                  !
  ! Global
  logical :: gr8_random
  include 'clic_parameter.inc'
  include 'clic_clic.inc'
  include 'clic_display.inc'
  include 'gbl_pi.inc'
  include 'clic_par.inc'
  include 'clic_xy_code.inc'
  ! Local
  integer :: nk, iy, iba, ib, i, l, l1, nn, nd
  integer :: n_br, k_br(10), ikn, nkn, j, ia
  real*8 :: cs(m_spl+4), ks(m_spl+8), rss, ss, sss
  real*8 :: xx(10*m_spl), yy(10*m_spl), xx1
  real*8 :: wk2(4*(m_spl+8)), wk3(2*m_pol)
  real*8 :: w0, xold, xnew
  real*8 :: apol(m_pol,m_pol), spol(m_pol), aa(m_pol)
  real :: x4, x2, y2, x3, y3, t_br(10), tkn(40), step
  logical :: plot, reset, poly, weight
  character(len=132) :: chain
  integer :: ipol, nt, old_pen
  real :: rms_err(mbox)
  real :: ymean, wmean
  save rms_err
  !------------------------------------------------------------------------
  ! Code:
  t_splmon = t_step
  old_pen = -1
  if (i_base(1).gt.mnbas) then
    call message(8,4,'SOLVE_PASS','Triangle mode not supported')
    error = .true.
  endif
  !
  poly = sic_present(9,0)
  ipol = 0
  if (poly) then
    call sic_i4(line,9,1,ipol,.false.,error)
    if (error) goto 999
    ipol = max(min(ipol+1,m_pol),1)    ! degree+1
  endif
  reset = sic_present(4,0)
  if (reset) then
    call reset_time
  endif
  !
  n_br = 0
  if (sic_present(8,0)) then
    i = 0
    do while (i.lt.sic_narg(8))
      n_br = n_br+1
      call sic_i4(line,8,i+1,k_br(n_br),.true.,error)
      if (error) goto 999
      k_br(n_br) = min(max(k_br(n_br),0),3)
      call sic_r4(line,8,i+2,t_br(n_br),.true.,error)
      if (error) goto 999
      i = i + 2
    enddo
  endif
  !
  call show_general('X',.false.,line,error)
  call show_general('Y',.false.,line,error)
  if (change_display) then
    ! plot all scans in index, sorted, plot buffer re-initialized.
    call read_data('ALL',.true.,.true., error)
    plotted = .false.
    if (error) goto 999
    change_display = .false.
  else
    plotted = .true.
  endif
  plot = sic_present(1,0)
  weight = sic_present(2,0)
  if (plot) then
    clear = .true.
    if (.not. plotted) call sub_plot('A',.false.,.false.,0,error)
    if (error) goto 999
    plotted = .true.
    old_pen = gr_spen (1)
    call gr_segm('FIT',error)
  endif
  !
  ! Loop on boxes
  do ib = 1, n_boxes
    iy = i_y(k_y(ib))
    iba = i_base(k_base(ib))
    ia = -iba
    if (n_data(ib).eq.0) then
      call message(4,3,'SOLVE_MONITOR','No data in that box')
      goto 200
    elseif (i_x(k_x(ib)).ne. xy_time) then
      call message(4,2,'SOLVE_MONITOR','X axis should be Time')
      goto 200
    elseif (iy.ne.xy_atm_pow) then
      call message(4,2,'SOLVE_MONITOR',   &
        'Y axis should be Atmospheric Power')
      goto 200
    elseif (iba.gt.0) then
      call message(4,2,'SOLVE_MONITOR',   &
        'Use an antenna plot (SET ANTENNA)')
      goto 200
    endif
    nkn = 0
    if (n_br.gt.0) then
      do i=1, n_br
        do j=1,4-k_br(i)
          nkn = nkn + 1
          tkn(nkn) = t_br(i)
        enddo
      enddo
    endif
    w0 = 0
    !
    ! Load arrays for fitting, ignoring blanked values.
    nd = 0
    ymean = 0
    wmean = 0
    do i=1, n_data(ib)
      if (y_data(i,ib) .ne. blank4 .and.   &
        w_data(i,ib).gt.0) then
        nd = nd+1
        xxx(nd) = x_data(i,ib)
        yyy(nd) = y_data(i,ib)
        ! The MTH_FITPOL routine requires 1/sigma values
        if (w0.eq.0) w0 = sqrt(w_data(i,ib))
        if (weight) then
          www(nd) = sqrt(w_data(i,ib))
        else
          www(nd) = w0
        endif
        ymean = ymean+yyy(nd)+www(nd)
        wmean = wmean+www(nd)
      endif
    enddo
    if (nd.eq.0) goto 200
    if (wmean.gt.0) ymean = ymean / wmean
    !
    if (.not.poly .and. nd.eq.3) then
      y2 = yyy(2)-yyy(1)
      y3 = yyy(3)-yyy(1)
      x2 = xxx(2)-xxx(1)
      x3 = xxx(3)-xxx(1)
      xxx(4) = (xxx(3)+xxx(2))/2
      x4 = xxx(4)-xxx(1)
      yyy(4) = yyy(1) + x4**2*(y2/x2-y3/x3)/(x2-x3)   &
        + x4*(y3*x2/x3-y2*x3/x2)/(x2-x3)
      www(4) = (www(3)+www(2))/2
      nd = 4
    elseif (.not. poly .and. nd.eq.2) then
      y2 = yyy(2)-yyy(1)
      x2 = xxx(2)-xxx(1)
      xxx(3) = xxx(2)-x2/3
      xxx(4) = xxx(1)+x2/3
      yyy(3) = yyy(2)-y2/3
      yyy(4) = yyy(1)+y2/3
      www(3) = www(2)
      www(4) = www(1)
      nd = 4
    elseif (nd.eq.1) then
      xxx(2) = xxx(1)+0.01
      xxx(3) = xxx(1)+0.02
      xxx(4) = xxx(1)-0.01
      yyy(2) = yyy(1)
      yyy(3) = yyy(1)
      yyy(4) = yyy(1)
      www(2) = www(1)
      www(3) = www(1)
      www(4) = www(1)
      nd = 4
    endif
    sss = 0
    do i=1, nd
      sss = sss + www(i)**2
    enddo
    ! Sort if required
    if (gr8_random(xxx,nd)) then
      call gr8_trie(xxx,ind,nd,error)
      if (error) goto 999
      call gr8_sort(yyy,wk1,ind,nd)
      call gr8_sort(www,wk1,ind,nd)
    endif
    ! Set knots
    if (.not. poly) then
      xold = xxx(1)
      ikn = 0
      nk = 0
      do while (xold.lt.xxx(nd))
        if (ikn.eq.nkn) then
          xnew = xxx(nd)
        elseif (nk.lt.m_spl) then
          ikn = ikn + 1
          xnew = tkn(ikn)
          nk = nk+1
          ks(nk+4) = tkn(ikn)
        else
          call message(8,3,'SOLVE_MONITOR',   &
            'Too many knots for this spline')
          error = .true.
          return
        endif
        nt = (xnew-xold)/t_splmon
        nt = min(nt, m_spl-nk, nd-4)
        if (nt.gt.0) then
          step = (xnew-xold)/(nt+1)
          if (nk+nt.gt.m_spl) then
            call message(8,3,'SOLVE_MONITOR',   &
              'Too many knots for this spline')
            error = .true.
            return
          endif
          do i=1, nt
            ks(nk+i+4) = xold + i*step
          enddo
          nk = nk + nt
        endif
        xold = xnew
      enddo
      if (nk.gt.0) call gr8_trie(ks(5:),ind,nk,error)
      if (error) goto 999
      !		write(*,*) 'knots ',nk
      !		if (nk.gt.0) write(*,*) (ks(i),i=5,nk+4)
      call mth_fitspl ('SOLVE_MONITOR', nd, nk+8, xxx,   &
        yyy, www, ks, wk1, wk2, cs, ss, error)
      if (error) goto 999
      rss = sqrt(ss/sss)/ymean
    else
      ipol = min(ipol,nd)
      call mth_fitpol('SOLVE_MONITOR',nd,ipol,m_pol,   &
        xxx,yyy,www,wk1,wk3,apol,spol,error)
      if (error) goto 999
      rss = sqrt(sss/nd)       ! rms obtenu
      rss = spol(ipol)/rss/ymean
    endif
    ! display results
l = min(lenc(y_label(ib)),5)
    l1 = lenc(header_1(ib))
    rms_err(ib) = rss
    write(chain,1000) y_label(ib)(1:3), header_1(ib)(1:l1),rss
1000 format(a,'. ',a,' rms: ',1pg10.3)
    call message(6,1,'SOLVE_MONITOR',chain(1:lenc(chain)))
    if (plot) then
      nn = 10.*m_spl
      step = (gb2_x(ib)-gb1_x(ib)) / (nn-1)
      if (step.eq.0) step = 0.1
      if (poly) then
        do i=1, ipol
          aa(i) = apol(ipol,i)
        enddo
      endif
      do i=1, nn
        xx(i) = gb1_x(ib) + (i-1) * step
        if (.not.poly) then
          xx1 = min(xx(i),ks(nk+5))
          xx1  = max(xx1,ks(4))
          call mth_getspl('SOLVE_MONITOR',   &
            nk+8, ks, cs, xx1, yy(i), error)
          if (error) goto 999
        else
          xx1 = min(max(xx(i),xxx(1)),xxx(nd))
          xx1 = ((xx1-xxx(1))-(xxx(nd)-xx1))   &
            /(xxx(nd)-xxx(1))
          call mth_getpol('SOLVE_MONITOR',   &
            ipol,aa,xx1,yy(i),error)
          if (error) goto 999
        endif
      enddo
      write(chain,'(I4.4)') ib
      call gr_execl('CHANGE DIRECTORY BOX'//chain)
      error = gr_error()
      if (error) goto 999
      call gr8_connect (nn,xx,yy,0.0d0,-1.0d0)
      call gr_execl('CHANGE DIRECTORY')
    endif
    !
    ! Save results
    if (.not.poly) then
      n_splmon(ia) = nk
      do i=1, nk+8
        k_splmon(i,ia) = ks(i) ! in hours
      enddo
      do i=1, nk+4
        c_splmon(i,ia) = cs(i)
      enddo
      rms_splmon(ia) = rss
      f_splmon(ia) = 1
      f_polmon(ia) = 0
    else
      n_polmon(ia) = ipol
      do i=1, ipol
        c_polmon(i,ia) = apol(ipol,i)
      enddo
      t_polmon(1,ia) = xxx(1)
      t_polmon(2,ia) = xxx(nd)
      rms_polmon(ia) = rss
      f_polmon(ia) = 1
      f_splmon(ia) = 0
    endif
    !
200 continue
  enddo
  call sic_delvariable ('RMS_ATM',.false.,error)
  error = .false.
  call sic_def_real ('RMS_ATM',rms_err,1,n_boxes,.false.,error)
  error = .false.
998 continue
  if (old_pen.ne.-1)  then
    call gr_segm_close(error)
    i = gr_spen(old_pen)
  endif
  return
  !
999 error = .true.
  goto 998
end subroutine sub_solve_mon
