!-----------------------------------------------------------------------
! Support file for loading and plotting the Tsys and opacity tables
! created by command NOEMAOFFLINE\TSYS.
!
! Public procedures are:
!   @ noema-tsys-table-load
!     Load the Tsys binary table (name found in logical name
!     GAG_NOEMA_TSYS) in memory in structure noema%tsys%tab%
!   @ noema-tsys-table-dump  ASCIITableName
!     Dump the structure noema%tsys%tab% to ASCII file (for debugging only)
!   @ noema-tsys-table-plot
!     Plot the content of the noema%tsys%tab% structure. The plot adapts
!     itself to the current plot page (portrait|landscape|other)
!   @ noema-tsys-table-interpolate W|S Freq Water Elevation
!     Interpolate Tsys from table and save result in noema%tsys%done%
!-----------------------------------------------------------------------
!
begin procedure define-struct
  !
  if .not.exist(noema) then
    define structure noema                  /global
  endif
  if exist(noema%tsys) then
    delete /var noema%tsys
  endif
  !
  define structure noema%tsys               /global
  define structure noema%tsys%tab           /global
  define char*32   noema%tsys%tab%file      /global
  define integer   noema%tsys%tab%version   /global
  define real      noema%tsys%tab%pressure  /global
  define real      noema%tsys%tab%gaini     /global
  define real      noema%tsys%tab%if        /global
  define integer   noema%tsys%tab%nfreq     /global
  define integer   noema%tsys%tab%nairmass  /global
  define integer   noema%tsys%tab%nwater    /global
  define integer   noema%tsys%tab%ntemp     /global
  !
  define structure noema%tsys%done          /global
  define integer   noema%tsys%done%iwater   /global
  define real      noema%tsys%done%airmass  /global
  define real      noema%tsys%done%tsys     /global
  !
end procedure define-struct
!
begin procedure exa0-to-file
  !---------------------------------------------------------------------
  !   Same as EXAMINE command, except that it can be redirected to a
  ! file if SIC OUTPUT was used before.
  !   Generic engine which takes a 1D flattened array as argument.
  !---------------------------------------------------------------------
  define integer n1
  let n1 'pro%arg[2]'
  define alias array 'pro%arg[1]'
  define integer i j k l m
  for i1 1 to n1 by 5
    let i i1
    let j i1+1
    let k i1+2
    let l i1+3
    let m i1+4
    if m.le.n1 then
      say 'array[i]' 'array[j]' 'array[k]' 'array[l]' 'array[m]' -
        /format 1pg14.7 1pg14.7 1pg14.7 1pg14.7 1pg14.7
    else if l.eq.n1 then
      say 'array[i]' 'array[j]' 'array[k]' 'array[l]' -
        /format 1pg14.7 1pg14.7 1pg14.7 1pg14.7
    else if k.eq.n1 then
      say 'array[i]' 'array[j]' 'array[k]' -
        /format 1pg14.7 1pg14.7 1pg14.7
    else if j.eq.n1 then
      say 'array[i]' 'array[j]' -
        /format 1pg14.7 1pg14.7
    else if i.eq.n1 then
      say 'array[i]' -
        /format 1pg14.7
    endif
  next i1
  delete /var array
end procedure exa0-to-file
!
begin procedure exa1-to-file
  !---------------------------------------------------------------------
  !   Same as EXAMINE command, except that it can be redirected to a
  ! file if SIC OUTPUT was used before.
  !   1D version
  !---------------------------------------------------------------------
  define integer n1
  let n1 'pro%arg[2]'
  say ""
  say 'pro%arg[1]'" is a real array of dimension "'n1'
  @ exa0-to-file 'pro%arg[1]' 'pro%arg[2]'
end procedure exa1-to-file
!
begin procedure exa4-to-file
  !---------------------------------------------------------------------
  !   Same as EXAMINE command, except that it can be redirected to a
  ! file if SIC OUTPUT was used before.
  !   4D version
  !---------------------------------------------------------------------
  define integer n1 n2 n3 n4
  let n1 'pro%arg[2]'
  let n2 'pro%arg[3]'
  let n3 'pro%arg[4]'
  let n4 'pro%arg[5]'
  say ""
  say 'pro%arg[1]'" is a real array of dimension "'n1'" "'n2'" "'n3'" "'n4'
  !
  ! Can not define a 1D-reshaped alias. Use a copy instead...
  define integer nt
  let nt n1*n2*n3*n4
  define real array4[nt] /global
  let array4 'pro%arg[1]'
  @ exa0-to-file array4 'nt'
  delete /var array4
end procedure exa4-to-file
!
begin procedure noema-tsys-table-load
  !---------------------------------------------------------------------
  ! Load the whole Tsys table in memory in the structure
  ! "noema%tsys%tab%"
  ! Arguments:
  !  Table file name (optional, default is logical `gag_noema_tsys`)
  !---------------------------------------------------------------------
  !
  @ define-struct
  if pro%narg.ge.1 then
    let noema%tsys%tab%file 'pro%arg[1]'
  else
    let noema%tsys%tab%file `gag_noema_tsys`
  endif
  define integer nskip
  let nskip 1
  !
  ! Read version
  accept noema%tsys%tab%version /bin 'noema%tsys%tab%file' 'nskip*4'
  let nskip nskip+1
  !
  ! Read context
  define real params[3]
  accept params /bin 'noema%tsys%tab%file' 'nskip*4'
  let noema%tsys%tab%pressure params[1]
  let noema%tsys%tab%gaini params[2]
  let noema%tsys%tab%if params[3]
  let nskip nskip+3
  !
  ! Read dimensions
  define integer n[4]
  accept n /bin 'noema%tsys%tab%file' 'nskip*4'
  let noema%tsys%tab%nfreq n[1]
  let noema%tsys%tab%nairmass n[2]
  let noema%tsys%tab%nwater n[3]
  let noema%tsys%tab%ntemp n[4]
  let nskip nskip+4
  !
  define real noema%tsys%tab%freq[noema%tsys%tab%nfreq] -
              noema%tsys%tab%airmass[noema%tsys%tab%nairmass] -
              noema%tsys%tab%water[noema%tsys%tab%nwater] -
              noema%tsys%tab%temp[noema%tsys%tab%ntemp] -
              noema%tsys%tab%trec[noema%tsys%tab%nfreq] -
              noema%tsys%tab%feff[noema%tsys%tab%nfreq] /global
  ! Read frequencies
  accept noema%tsys%tab%freq /bin 'noema%tsys%tab%file' 'nskip*4'
  let nskip nskip+noema%tsys%tab%nfreq
  ! Read airmasses
  accept noema%tsys%tab%airmass /bin 'noema%tsys%tab%file' 'nskip*4'
  let nskip nskip+noema%tsys%tab%nairmass
  ! Read waters
  accept noema%tsys%tab%water /bin 'noema%tsys%tab%file' 'nskip*4'
  let nskip nskip+noema%tsys%tab%nwater
  ! Read temperatures
  accept noema%tsys%tab%temp /bin 'noema%tsys%tab%file' 'nskip*4'
  let nskip nskip+noema%tsys%tab%ntemp
  ! Read Trec
  accept noema%tsys%tab%trec /bin 'noema%tsys%tab%file' 'nskip*4'
  let nskip nskip+noema%tsys%tab%nfreq
  ! Read Feff
  accept noema%tsys%tab%feff /bin 'noema%tsys%tab%file' 'nskip*4'
  let nskip nskip+noema%tsys%tab%nfreq
  !
  ! Read Tsys
  define real noema%tsys%tab%tsys[noema%tsys%tab%nfreq,noema%tsys%tab%nairmass,noema%tsys%tab%nwater,noema%tsys%tab%ntemp] /global
  accept noema%tsys%tab%tsys /bin 'noema%tsys%tab%file' 'nskip*4'
  !
end procedure noema-tsys-table-load
!
begin procedure noema-tsys-table-water
  !---------------------------------------------------------------------
  ! Find the water index according to input pwv (mm). Result is stored
  ! in noema%tsys%done%iwater
  !  Arguments:
  !   pro%arg[1]: Water vapour [mm] (must be on grid)
  !---------------------------------------------------------------------
  !
  define real water
  let water 'pro%arg[1]'
  !
  define integer wloca[2]
  compute wloca location noema%tsys%tab%water water
  !
  ! Water: no interpolation, the exact value must be found
  define integer iwater1 iwater2
  let iwater1 wloca[1]
  let iwater2 wloca[2]
  if abs(noema%tsys%tab%water[iwater1]-water).lt.1e-5 then
    let noema%tsys%done%iwater iwater1
  else if abs(noema%tsys%tab%water[iwater2]-water).lt.1e-5 then
    let noema%tsys%done%iwater iwater2
  else
    message e noema-tsys-table-interpolate "Water value "''" not found in table"
    return base
  endif
  !
end procedure noema-tsys-table-water
!
begin procedure noema-tsys-table-dump
  !---------------------------------------------------------------------
  ! Dump the contents of the structure "noema%tsys%tab%" to the named ASCII
  ! file.
  ! Arguments:
  !   pro%arg[1]: output file name
  !---------------------------------------------------------------------
  !
  if pro%narg.ne.1 then
    message e noema-tsys-table "Missing output ASCII table name as argument"
    return base
  endif
  !
  sic output 'pro%arg[1]' new
  !
  ! Dump version
  say "Version = "'noema%tsys%tab%version'
  say ""
  !
  ! Dump context
  say "Pressure = "'noema%tsys%tab%pressure'
  say "Image gain = "'noema%tsys%tab%gaini'
  say "IF = "'noema%tsys%tab%if'
  say ""
  !
  ! Dump dimensions
  say "Nfreq = "'noema%tsys%tab%nfreq'
  say "Nairmass = "'noema%tsys%tab%nairmass'
  say "Nwater = "'noema%tsys%tab%nwater'
  say "Ntemp = "'noema%tsys%tab%ntemp'
  !
  ! Dump vectors
  @ exa1-to-file noema%tsys%tab%freq    noema%tsys%tab%nfreq
  @ exa1-to-file noema%tsys%tab%airmass noema%tsys%tab%nairmass
  @ exa1-to-file noema%tsys%tab%water   noema%tsys%tab%nwater
  @ exa1-to-file noema%tsys%tab%temp    noema%tsys%tab%ntemp
  @ exa1-to-file noema%tsys%tab%trec    noema%tsys%tab%nfreq
  @ exa1-to-file noema%tsys%tab%feff    noema%tsys%tab%nfreq
  !
  ! Dump data
  @ exa4-to-file noema%tsys%tab%tsys noema%tsys%tab%nfreq -
    noema%tsys%tab%nairmass noema%tsys%tab%nwater noema%tsys%tab%ntemp
  !
  sic output
  !
end procedure noema-tsys-table-dump
!
begin procedure noema-tsys-table-plot
  !---------------------------------------------------------------------
  ! Plot the contents of the noema%tsys%tab% structure
  !---------------------------------------------------------------------
  !
  g\clear
  g\set mark 4 1 0.06 45
  g\set char 0.45
  g\tickspace 0. 0. 0. 0.
  !
  ! Grey out the regions out-of-bands
  g\set box_loc box_xmin box_xmax 'page_y*0.07' 'page_y*0.93'
  g\limits noema%tsys%tab%freq[1]  noema%tsys%tab%freq[noema%tsys%tab%nfreq] -
           0                      1                                          -
           /margin 5 10 0 0
  define real b1min b1max b2min b2max b3min b3max  ! Band limits
  let b1min 82
  let b1max 110
  let b2min 136
  let b2max 172
  let b3min 208
  let b3max 268
  g\pen /col grey
  define real poly[4,2]
  let poly[,1] user_xmin b1min b1min user_xmin
  let poly[,2] user_ymin user_ymin user_ymax user_ymax
  g\poly poly /var /hatch /plot
  let poly[,1] b1max b2min b2min b1max
  let poly[,2] user_ymin user_ymin user_ymax user_ymax
  g\poly poly /var /hatch /plot
  let poly[,1] b2max b3min b3min b2max
  let poly[,2] user_ymin user_ymin user_ymax user_ymax
  g\poly poly /var /hatch /plot
  let poly[,1] b3max user_xmax user_xmax b3max
  let poly[,2] user_ymin user_ymin user_ymax user_ymax
  g\poly poly /var /hatch /plot
  g\pen /col foreground
  !
  ! Trec box
  define real tmin tmax
  compute tmin min noema%tsys%tab%trec /blank 1e4
  compute tmax max noema%tsys%tab%trec /blank 1e4
  g\set box_loc box_xmin box_xmax 'page_y*0.07' 'page_y*0.20'
  g\limits noema%tsys%tab%freq[1] noema%tsys%tab%freq[noema%tsys%tab%nfreq] -
           tmin                   tmax                                      -
           /margin 5 10 30 30
  g\box
  g\label "Freq [GHz]" /X
  g\label "Trec [K]"   /Y
  g\pen /col web_green
  g\point noema%tsys%tab%freq noema%tsys%tab%trec
  g\pen /col foreground
  !
  ! Feff box
  g\set box_loc box_xmin box_xmax 'page_y*0.20' 'page_y*0.33'
  g\limits noema%tsys%tab%freq[1] noema%tsys%tab%freq[noema%tsys%tab%nfreq] -
           noema%tsys%tab%feff[1] noema%tsys%tab%feff[noema%tsys%tab%nfreq] -
           /rev y /margin 5 10 30 30
  g\box n o
  g\label "Feff"   /Y
  g\pen /col magenta
  g\point noema%tsys%tab%freq noema%tsys%tab%feff
  g\pen /col foreground
  !
  ! Tsys box
  g\set box_loc box_xmin box_xmax 'page_y*0.33' 'page_y*0.93'
  g\limits noema%tsys%tab%freq[1] noema%tsys%tab%freq[noema%tsys%tab%nfreq] -
           50 450 -
           /margin 5 10 0 0
  g\box n o
  g\label "Line Tsys [K]" /Y
  define integer iairmass
  let iairmass 1
  for iwater 1 to noema%tsys%tab%nwater by 2
    g\pen /col blue
    g\point noema%tsys%tab%freq noema%tsys%tab%tsys[iairmass,iwater,1]
    g\pen /col red
    g\point noema%tsys%tab%freq noema%tsys%tab%tsys[iairmass,iwater,2]
    g\pen /col foreground
    g\draw text noema%tsys%tab%freq[noema%tsys%tab%nfreq] -
                noema%tsys%tab%tsys[noema%tsys%tab%nfreq,iairmass,iwater,1] -
                " "'noema%tsys%tab%water[iwater]'" mm" 6 /user
  next iwater
  !
  ! Legend
  define character*16 val
  !
  let val noema%tsys%tab%temp[1] /format f0.1
  g\pen /col blue
  g\draw text 0.5 -0.7 "Temperature "'val'" K (winter)" 6 /box 7
  !
  let val noema%tsys%tab%temp[2] /format f0.1
  g\pen /col red
  g\draw text 0.5 -1.4 "Temperature "'val'" K (summer)" 6 /box 7
  !
  let val noema%tsys%tab%pressure /format f0.1
  g\pen /col foreground
  g\draw text 0.5 -2.1 "Local pressure "'val'" HPa"     6 /box 7
  !
  let val noema%tsys%tab%gaini /format f5.3
  g\draw text 0.5 -2.8 "Image gain "'val'               6 /box 7
  !
  let val '(noema%tsys%tab%freq[2]-noema%tsys%tab%freq[1])*1e3' /format f0.0
  g\draw text 0.5 -3.5 "Freq step "'val'" MHz"          6 /box 7
  !
  let val noema%tsys%tab%airmass[1] /format f3.1
  g\draw text 0.5 -4.2 "Airmass "'val'" (available "'noema%tsys%tab%airmass[1]'" to "'noema%tsys%tab%airmass[noema%tsys%tab%nairmass]'")" 6 /box 7
  !
  let val 'noema%tsys%tab%water[2]-noema%tsys%tab%water[1]' /format f3.1
  g\draw text 0.5 -4.9 "Pwv step "'val'" mm"            6 /box 7
  !
  ! Title
  g\draw text 0 1 'noema%tsys%tab%file'                 5 /box 8
  !
end procedure noema-tsys-table-plot
!
begin procedure noema-tsys-estimator-plot
  !---------------------------------------------------------------------
  ! Plot Tsys curve used by the NOEMA sensitivity estimator.
  ! This plot is used for the call for proposals.
  !---------------------------------------------------------------------
  !
  define integer nband nseason
  let nband 3
  let nseason 2
  !
  define char*8 seasons[nseason]
  let seasons "WINTER" "SUMMER"
  !
  ! --- Parameters ---
  define real water[nseason,nband]
  let water[1] 5.0 6.0
  let water[2] 4.0 5.0
  let water[3] 3.0 4.0
  !
  define char*12 scolour[nseason]
  let scolour "BLUE" "RED"
  !
  define real frange[2,nband]
  let frange[1] 70.284 121.716
  let frange[2] 124.284 183.716
  let frange[3] 196.284 279.716
  !
  define real elev
  let elev 65  ! [deg] Max elev of a typical source at 20 deg declination
  ! --- End of parameters ---
  !
  g\clear
  g\tickspace 0. 0. 0. 0.
  g\limits noema%tsys%tab%freq[1] noema%tsys%tab%freq[noema%tsys%tab%nfreq] 50 300 -
           /margin 5 0
  g\box
  g\label "Freq [GHz]" /X
  g\label "Tsys [K]"   /Y
  !
  define real tsys /like noema%tsys%tab%freq
  let tsys -1000.
  define real freq
  !
  for iseason 1 to nseason
    !
    for iband 1 to nband
      !
      for ifreq 1 to noema%tsys%tab%nfreq
        let freq noema%tsys%tab%freq[ifreq]
        if freq.gt.frange[1,iband].and.freq.lt.frange[2,iband] then
          @ noema-tsys-table-interpolate -
            'seasons[iseason]' 'freq' 'water[iseason,iband]' 'elev'
          let tsys[ifreq] noema%tsys%done%tsys
        endif
      next ifreq
      !
    next iband
    !
    g\pen /col 'scolour[iseason]'
    g\connect noema%tsys%tab%freq tsys /blank -1000. 1.
    g\pen /col foreground
    !
  next iseason
  !
  g\pen /col blue
  g\draw text 100  75 'water[1,1]'" mm" 6 /user
  g\draw text 160 115 'water[1,2]'" mm" 6 /user
  g\draw text 250 190 'water[1,3]'" mm" 6 /user
  g\pen /col red
  g\draw text  75 100 'water[2,1]'" mm" 6 /user
  g\draw text 128 128 'water[2,2]'" mm" 6 /user
  g\draw text 200 235 'water[2,3]'" mm" 6 /user
  g\pen /col foreground
  !
end procedure noema-tsys-estimator-plot
!
begin procedure noema-tsys-table-interpolate
  !---------------------------------------------------------------------
  ! Compute a Tsys value from input frequency and pwv. This is done
  ! by interpolating the Tsys and opacity found in the Tsys table
  ! currently loaded.
  !  Arguments:
  !   pro%arg[1]: WINTER or SUMMER [keyword]
  !   pro%arg[2]: Frequency        [GHz] (free value)
  !   pro%arg[3]: Water vapour     [mm]  (must be on grid)
  !   pro%arg[4]: Elevation        [deg] (free value)
  !---------------------------------------------------------------------
  !
  define char*1 season
  define real freq water elevation
  let season 'pro%arg[1]' /upper
  let freq 'pro%arg[2]'
  let water 'pro%arg[3]'
  let elevation 'pro%arg[4]'
  !
  ! Season: if Winter, use the lowest temperature. If Summer, use the highest. No
  ! assumption on which order they come in the binary table.
  define integer ilow ihigh
  if noema%tsys%tab%temp[1].lt.noema%tsys%tab%temp[noema%tsys%tab%ntemp] then
    let ilow 1
    let ihigh noema%tsys%tab%ntemp
  else
    let ilow noema%tsys%tab%ntemp
    let ihigh 1
  endif
  define integer iseason
  if season.eq."W" then
    let iseason ilow
  else if season.eq."S" then
    let iseason ihigh
  else
    message E noema-tsys-table-interpolate "Invalid season """'pro%arg[1]'""""
    return base
  endif
  !
  ! Water: find the corresponding water index
  @ noema-tsys-table-water 'water'
  !
  ! Bilinear interpolation in the space [freq,airmass]. See formula in
  !  https://fr.wikipedia.org/wiki/Interpolation_bilin%C3%A9aire
  !
  ! Frequency
  define integer floca[2] ifreq1 ifreq2
  compute floca location noema%tsys%tab%freq freq
  let ifreq1 floca[1]
  let ifreq2 floca[2]
  define real freq1 freq2 ffact
  let freq1 noema%tsys%tab%freq[ifreq1]
  let freq2 noema%tsys%tab%freq[ifreq2]
  let ffact (freq-freq1)/(freq2-freq1)
  !
  ! Airmass
  let noema%tsys%done%airmass 1./sin(elevation*pi/180)
  define integer aloca[2] iairmass1 iairmass2
  compute aloca location noema%tsys%tab%airmass noema%tsys%done%airmass
  let iairmass1 aloca[1]
  let iairmass2 aloca[2]
  define real airmass1 airmass2 afact
  let airmass1 noema%tsys%tab%airmass[iairmass1]
  let airmass2 noema%tsys%tab%airmass[iairmass2]
  let afact (noema%tsys%done%airmass-airmass1)/(airmass2-airmass1)
  !
  ! Get Tsys at the 4 nearest points
  define real tsys_f1a1 tsys_f1a2 tsys_f2a1 tsys_f2a2
  let tsys_f1a1 noema%tsys%tab%tsys[ifreq1,iairmass1,noema%tsys%done%iwater,iseason]
  let tsys_f1a2 noema%tsys%tab%tsys[ifreq1,iairmass2,noema%tsys%done%iwater,iseason]
  let tsys_f2a1 noema%tsys%tab%tsys[ifreq2,iairmass1,noema%tsys%done%iwater,iseason]
  let tsys_f2a2 noema%tsys%tab%tsys[ifreq2,iairmass2,noema%tsys%done%iwater,iseason]
  !
  ! Interpolate
  define real delta_tsys_a delta_tsys_f delta_tsys_af
  let delta_tsys_f  tsys_f2a1-tsys_f1a1
  let delta_tsys_a  tsys_f1a2-tsys_f1a1
  let delta_tsys_af tsys_f1a1+tsys_f2a2-tsys_f2a1-tsys_f1a2
  !
  let noema%tsys%done%tsys -
    tsys_f1a1+delta_tsys_f*ffact+delta_tsys_a*afact+delta_tsys_af*ffact*afact
  !
end procedure noema-tsys-table-interpolate
!
begin procedure noema-tsys-table-compare
  !---------------------------------------------------------------------
  ! Compare results provided by the table + noema-tsys-table-interpolate
  ! versus real call to ATM
  !---------------------------------------------------------------------
  !
  define real elevation
  let elevation 20  ! [deg] A value which gives a non-friendly airmass
  !
  ! ATM call. Must match parameters used to generate the table in
  ! NOEMA\TSYS (in particular for the Band 2 used below)
  let temperature 283  ! Must match season used in noema-tsys-table-interpolate
  let zero_pressure 1013
  let airmass '1/sin(elevation*pi/180)'
  let water 5.0
  let forward_eff 0.95
  let gain_image 0.050
  let trec 40.0
  !
  define integer nfreq
  let nfreq 150
  define real freq[nfreq] tsys_atm[nfreq] tsys_table[nfreq] diff[nfreq]
  ! Band 2
  for ifreq 1 to nfreq
    ! Frequency by non integer step checks correct interpolation of 
    ! the table
    let freq[ifreq] 124+ifreq/pi
    let freq_sig freq[ifreq]
    let freq_ima freq_sig  ! No IF => same as in the table
    !
    atm
    let tsys_atm[ifreq] tsys
    !
    @ noema-tsys-table-interpolate SUMMER 'freq_sig' 5.0 'elevation'
    let tsys_table[ifreq] noema%tsys%done%tsys
    !
    let diff[ifreq] 'tsys_table[ifreq]-tsys_atm[ifreq]'
  next ifreq
  !
  g\clear
  g\tickspace 0. 0. 0. 0.
  g\set plot portrait
  !
  g\set box_loc 2.5 19.5 16 28
  g\limits /var freq tsys_atm /margin 5 10
  g\box
  g\connect freq tsys_atm
  g\pen /col red
  g\connect freq tsys_table
  g\pen /col foreground
  g\label "Tsys [K]" /Y
  g\draw text 1 -1 "Elevation "'elevation'" deg." 6 /box 7
  define char*5 release
  let release `gag_version`
  g\draw text 0 1 'release' 5 /box 8
  !
  g\set box_loc 2.5 19.5 4 16
  g\limits = = -10 10
  g\box
  g\connect freq diff
  g\label "Frequency [GHz]" /X
  g\label "Diff [K]" /Y
  !
end procedure noema-tsys-table-compare
