diff options
author | Ollivier Robert <roberto@FreeBSD.org> | 2008-08-17 17:37:33 +0000 |
---|---|---|
committer | Ollivier Robert <roberto@FreeBSD.org> | 2008-08-17 17:37:33 +0000 |
commit | cce65f439697627afbccf5a67035a957bb4d784a (patch) | |
tree | 16d100fbc9dae63888d48b464e471ba0e5065193 /scripts/stats | |
parent | 8c24a1e0ffd629427f94da1b681600008030c41a (diff) |
Notes
Diffstat (limited to 'scripts/stats')
-rw-r--r-- | scripts/stats/README | 39 | ||||
-rw-r--r-- | scripts/stats/README.stats | 246 | ||||
-rw-r--r-- | scripts/stats/README.timecodes | 149 | ||||
-rwxr-xr-x | scripts/stats/clock.awk | 431 | ||||
-rwxr-xr-x | scripts/stats/dupe.awk | 8 | ||||
-rwxr-xr-x | scripts/stats/ensemble.S | 5 | ||||
-rwxr-xr-x | scripts/stats/ensemble.awk | 17 | ||||
-rwxr-xr-x | scripts/stats/etf.S | 15 | ||||
-rwxr-xr-x | scripts/stats/etf.awk | 19 | ||||
-rwxr-xr-x | scripts/stats/itf.S | 5 | ||||
-rwxr-xr-x | scripts/stats/itf.awk | 19 | ||||
-rwxr-xr-x | scripts/stats/loop.S | 7 | ||||
-rwxr-xr-x | scripts/stats/loop.awk | 45 | ||||
-rwxr-xr-x | scripts/stats/loop_summary | 2 | ||||
-rwxr-xr-x | scripts/stats/peer.awk | 68 | ||||
-rwxr-xr-x | scripts/stats/psummary.awk | 82 | ||||
-rwxr-xr-x | scripts/stats/summary.sh | 88 | ||||
-rwxr-xr-x | scripts/stats/tdata.S | 5 | ||||
-rwxr-xr-x | scripts/stats/tdata.awk | 45 |
19 files changed, 1295 insertions, 0 deletions
diff --git a/scripts/stats/README b/scripts/stats/README new file mode 100644 index 0000000000000..680896342acbb --- /dev/null +++ b/scripts/stats/README @@ -0,0 +1,39 @@ +Statistics processing scripts (README) + +This directory contains a number of scripts for use with the filegen +facility. Those files ending in .awk are for the Unix awk utility, while +those ending in .sh are for the csh utility. Normally, the summary.sh +script is called from a cron job once per day. This script processes the +daily loopstats, peerstats and clockstats files produced by the daemon, +updates the loop_summary, peer_summary and clock_summary archive files, +and deletes the daily files. + +In the case of the Austron 2201A GPS receiver, the clockstats file +contains a wealth of additional monitoring data. These data are summarized +and writted to the clock_summary file, then a series of special files are +constructed for later processing by the S utility. + +The summary.sh script invokes a number of awk scripts to actually produce +the data. This may result in multiple scans of the same input file. +The input file is deleted after processing. In fact, the shell scripts will +process all input files found of the correct type in chronological order, +deleting each one as it is scanned, except the current day file. + +The summary.sh script can produce input files for the S utility, if it +is found on the search path. This utility makes PostScript graphs of the +loopstats data for each day, as well as various statistics produced by +the Austorn 220aA GPS receiver. The S utility is automatically run +as a background job. Its control files have the .S extension. + +The psummary.awk script can be used to scan the peer_summary file and +construct an historical reprise of the daily summaries. + +The file formats are documented in the README.stats file and in the +scripts themselves. Further detail on the radio clock ASCII timecode +formats and related data are in the README.timecode file. + +David L. Mills +University of Delaware +mills@udel.edu +1 November 1993 +Revised 12 April 1994 diff --git a/scripts/stats/README.stats b/scripts/stats/README.stats new file mode 100644 index 0000000000000..aa8e77fb1bbe5 --- /dev/null +++ b/scripts/stats/README.stats @@ -0,0 +1,246 @@ +Statistics file formats (README.stats) + +The xntp3 daemon can produce a variety of statistics files which are +useful for maintenance, evaluation and retrospective calibration +purposes. See the xntpd.8 man page for instructions on how to configure +this feature. Since these files can become rather large and cumbersome, +they are ordinarily reduced to summary form by running the summary.sh +shell script once per day, week or month, as appropriate. There are +three file collections presently defined: peerstats, loopstats and +clockstats, each of which is described in this note. + +peerstats + +The following data are collected in the peerstats files. The files are +reduced to summary data using the peer.sh shell script. See the peer.awk +script for further information. A line in the file is produced upon +reception of each valid update from a configured peer. + + 49236 30.756 140.173.96.1 9474 0.000603 0.37532 + + 49236 modified Julian day number + 30.756 time of day (s) past midnight UTC + 140.173.96.1 peer identifier (IP address or receiver identifier) + 9474 peer status word (hex) (see NTP specification) + 0.000603 offset (s) + 0.08929 delay (s) + 0.37532 dispersion (s) + +loopstats + +The following data are collected in the loopstats files. The files are +reduced to summary data using the loop.sh shell script. See the loop.awk +script for further information. A line in the file is produced at each +valid update of the local clock. + + 49236 11.897 -0.000004 -35.9384 0 + + 49236 modified Julian day number + 11.897 time of day (s) past midnight UTC + -0.000004 time offset (s) + -35.9384 frequency offset (ppm) + 0 phase-lock loop time constant + +clockstats + +The following data are collected in the clockstats files. The files are +reduced to summary data using the clock.sh shell script, which also +updates the ensemble, etf, itf and tdata data files as well. See the +clock.awk, ensemble.awk, etf.awk, itf.awk and tdta.awk scripts for +further information. A line in the file is produced at each valid update +received from a configured radio clock. Data are at present recorded for +several radios. The first part of each data line is similar for all +radios, e.g.: + + 49234 60517.826 127.127.4.1 93 247 16:48:21.814 + + 49234 modified Julian day number + 60517.826 time of day (s) past midnight UTC + 127.127.4.1 receiver identifier (Spectracom 8170/Netclock-2) + 93 247 16:48:21.814 timecode (format varies) + +In the case of the Austron GPS receiver, a good deal of additional +information is extracted from the radio, as described below. The formats +shown consist of one line with all the fields shown in order. The +timecode formats specific to each radio follow. See the file +README.timecodes for detailed information on the timecode formats used +by these radios. + +Spectracom 8170/Netclock-2 WWVB receiver + + 49234 60517.826 127.127.4.1 ?A93 247 16:48:21.814 + + The '?' and 'A' characters are present only when the receiver is + unsynchronized; otherwise, they are replaced by space ' ' characters. + +IRIG audio decoder + + 49234 60517.826 127.127.6.0 247 16:48:21? + + The '?' character is present only when the receiver is unsynchronized. + +Austron 2200A/2201A GPS receiver + + 49234 60580.843 127.127.10.1 93:247:16:49:24.814? + + The '?' character is present only when the receiver is unsynchronized. + +Depending on the installed options, the Austron 2200A/2201A recognizes a +number of special commands that report various data items. See the +refclock_as2201.c source module for a list of the commands used. These +data are collected only if the following line is included in the +configuration file ntp.conf: + + fudge 127.127.10.1 flag4 1 # enable extended statistics collection + +The format of each data line returned is summarized in the following +list. + +External time/frequency data (requires input buffer option IN) + +These data determine the deviations of external time/frequency inputs +relative to receiver oscillator time. The following data are typical +using an external cesium oscillator PPS and 5-MHz outputs. + + 49234 60580.843 127.127.10.1 93:247:16:49:24.814 ETF + + -85.9 time interval (ns) + -89.0 average time interval (ns) + 4.0 time interval sigma (ns) + +1.510E-11 time interval rate + -4.500E-11 deltaf/f + +1.592E-11 average deltaf/f + 5.297E-13 sigma deltaf/f + 500 number of samples + +Model and option identifiers + +These data show the receiver model number and option configuration. + + 49234 60708.848 127.127.10.1 93:247:16:51:32.817 ID;OPT;VER + + GPS 2201A model ident (must be "GPS 2200A" or "GPS 2201A") + TTY1 rs232 option present (required) + TC1 IRIG option present (optional) + LORAN LORAN assist option present (optional) + IN input buffer option present (optional) + OUT1 output buffer option present (required) + B.00 data processor software version ("B.00" or later) + B.00 signal processor software version ("B.00" or later) + 28-Apr-93 software version date ("28-Apr-93" or later) + +Internal time/frequency data + +These data determine the deviations of the receiver oscillator with +respect to satellite time. + + 49234 60564.846 127.127.10.1 93:247:16:49:08.816 ITF + + COCO current mode (must be "COCO") + 0 code coast mode (must be zero) + +6.6152E-08 code sigma (s) + -3.5053E-08 code delta t (s) + -4.0361E-11 deltat/t + -6.4746E-11 oscillator ageing rate + 500.00 loop time constant + 4.984072 electrical tuning (V) + +GPS/LORAN ensemble data (requires LORAN assist option LORAN) + +These data determine the deviations and weights to calculate ensemble +time from GPS and LORAN data. + + 49234 60596.852 127.127.10.1 93:247:16:49:40.812 LORAN ENSEMBLE + + +9.06E-08 GPS t (s) + +3.53E-08 GPS sigma (s) + .532 GPS weight + +3.71E-08 LORAN t (s) + +3.76E-08 LORAN sigma (s) + .468 LORAN weight + +6.56E-08 ensemble t + +6.94E-08 ensemble sigma (s) + +LORAN stationkeeping data (requires LORAN assist option LORAN) + +These data determine which stations of the LORAN chain are being +tracked, together with individual signal/noise ratios, deviations and +weights. + + 49234 60532.850 127.127.10.1 93:247:16:48:36.820 LORAN TDATA + + M station identifier; data follows + OK status (must be "OK" for tracking) + 0 cw flag + 0 sw flag + 1162.17 time of arrival + -4.6 snr (-30.0 if not "OK" status) + 1.67E-07 2-sample phase-time deviation + .507 weight (included only if "OK" status) + W AQ 0 0 3387.80 -31.0 station identifier and data + X OK 0 0 1740.27 -11.2 2.20E-07 .294 station identifier and data + Y OK 0 0 2180.71 -4.6 2.68E-07 .198 station identifier and data + Z CV 0 0 3392.94 -30.0 station identifier and data + +Oscillator status and environment + +These data determine the receiver oscillator type, mode, status and +environment. Nominal operating conditions are shown below. + + 49234 60628.847 127.127.10.1 93:247:16:50:12.817 OSC;ET;TEMP + + 1121 Software Control oscillator model and mode (must be + "Software Control") + Locked status (must be "Locked") + 4.979905 electrical tuning (V) + 44.81 oscillator cavity temperature + +Receiver position, status and offsets + +These data determine the receiver position and elevation, together with +programmable delay corrections for the antenna cable and receiver. + + 49234 60788.847 127.127.10.1 93:247:16:52:52.817 POS;PPS;PPSOFF + + +39:40:48.425 receiver latitude (N) + -075:45:02.392 receiver longitude (E) + +74.09 receiver elevation (m) + Stored position status (must be "Stored") + UTC PPS/PPM alignment (must be "UTC") + 0 receiver delay (ns) (should be zero for calibrated + receiver) + 200 cable delay (ns) + 0 user time bias (ns) (must be zero) + +Satellite tracking status + +These data determine how many satellites are being tracked. At the +present state of constellation development, there should be at least +three visible satellites in view. Much of the time the maximum of +seven are being tracked; rarely this number drops to two. + + 49234 60612.850 127.127.10.1 93:247:16:49:56.820 TRSTAT + + 24 T satellite prn and status (T = track, A = acquire) + 16 A 13 T 20 T 18 T 07 T 12 T list continued + +UTC leap-second information + +These data determine when the next leap second is to occur. The exact +method to use is obscure. + + 49234 60548.847 127.127.10.1 93:247:16:48:52.818 UTC + + -1.2107E-08 A0 term (s) + -1.2790E-13 A1 term (s) + +9.0000E+00 current leap seconds (s) + +2.0480E+05 time for leap seconds (s) + +2.0100E+02 week number for delta leap (weeks) + +1.9100E+02 week number for future leap (weeks) + +4.0000E+00 day number for future leap (days) + +9.0000E+00 future leap seconds (s) + +David L. Mills +University of Delaware +mills@udel.edu +23 October 1993 diff --git a/scripts/stats/README.timecodes b/scripts/stats/README.timecodes new file mode 100644 index 0000000000000..00b5ba54584fd --- /dev/null +++ b/scripts/stats/README.timecodes @@ -0,0 +1,149 @@ +Radio Timecode Formats (README.timecodes) + +Following are examples of the serial timecode formats used by various +timecode receivers as given in the instruction manuals. These examples +are intended only for illustration and not as the basis of system +design. The following symbols are used to identify the timecode +character that begins a subfield. The values given after this symbol +represent the character offset from the beginning of the timecode string +as edited to remove control characters. + +C on-time character (start bit) +Y year of century +T time of day +D day of year or month/day +A alarm indicator (format specific) +Q quality indicator (format specific) +<LF> ASCII line feed (hex 0a) +<CR> ASCII carriage return (hex 0d) +<SP> ASCII space (hex 20) + +In order to promote uniform behavior in the various implementations, it +is useful to have a common interpretation of alarm conditions and signal +quality. When the alarm indicator it on, the receiver is not operating +correctly or has never synchronized to the broadcast signal. When the +alarm indicator is off and the quality indicator is on, the receiver has +synchronized to the broadcast signal, then lost the signal and is +coasting on its internal oscillator. + +In the following uppercase letters, punctuation marks and spaces <SP> +stand for themselves; lowercase letters stand for fields as described. +Special characters other than <LF>, <CR> and <SP> are preceded by ^. + +Spectracom 8170 and Netclock/2 WWV Synchonized Clock (format 0) + +"<CR><LF>i ddd hh:mm:ss TZ=zz<CR><LF>" + C A D T + + poll: ?; offsets: Y = none, D = 3, T = 7, A = 0, Q = none + i = synchronization flag (<SP> = in synch, ? = out synch) + ddd = day of year + hh:mm:ss = hours, minutes, seconds + zz = timezone offset (hours from UTC) + + Note: alarm condition is indicated by other than <SP> at A, which + occurs during initial synchronization and when received signal has + been lost for about ten hours + + example: " 216 15:36:43 TZ=0" + A D T + +Netclock/2 WWV Synchonized Clock (format 2) + +"<CR><LF>iqyy ddd hh:mm:ss.fff ld" + C AQY D T + + poll: ?; offsets: Y = 2, D = 5, T = 9, A = 0, Q = 1 + i = synchronization flag (<SP> = in synch, ? = out synch) + q = quality indicator (<SP> < 1ms, A < 10 ms, B < 100 ms, C < 500 + ms, D > 500 ms) + yy = year (as broadcast) + ddd = day of year + hh:mm:ss.fff = hours, minutes, seconds, milliseconds of day + l = leap-second warning (L indicates leap at end of month) + d = standard/daylight time indicator (<SP> standard, D daylight) + + Note: alarm condition is indicated by other than <SP> at A, which + occurs during initial synchronization and when received signal has + been lost for about ten hours; unlock condition is indicated by + other than <SP> at Q, with time since last lock indicated by the + letter code A < 13 min, B < 1.5 hr, C < 7 hr, D > 7 hr. + + example: " 92 216 15:36:43.640 D" + AQ D T + +TrueTime 468-DC Satellite Synchronized Clock (and other TrueTime +receivers) + +"<CR><LF><^A>ddd:hh:mm:ssq<CR>" + D T QC + + poll: none; offsets: Y = none, D = 0, T = 4, A = 12, Q = 12 + hh:mm:ss = hours, minutes, seconds + q = quality/alarm indicator (<SP> = locked, ? = alarm) + + Note: alarm condition is indicated by ? at A, which occurs during + initial synchronization and when received signal is lost for an + extended period; unlock condition is indicated by other than <SP> + at Q + + example: "216:15:36:43 " + D T Q + +Heath GC-1000 Most Accurate Clock (WWV/H) + +"<CR>hh:mm:ss.f dd/mm/yy<CR>" + C T A D + + poll: none; offsets: Y = none, D = 15, T = 0, A = 9, Q = none + hh:mm:ss = hours, minutes, seconds + f = deciseconds (? when out of spec) + dd/mm = day, month + yy = year of century (from DIPswitches) + + Note: 0?:??:??.? is displayed before synch is first established and + hh:mm:ss.? once synch is established and then lost again for about + a day. + + example: "15:36:43.6 04/08/91" + T A D Y + +PST/Traconex 1020 Time Source (WWV/H) (firmware revision V4.01) + +"frdzycchhSSFTttttuuxx<CR>" "ahh:mm:ss.fffs<CR>" "yy/dd/mm/ddd<CR>" + A Q T Y D + + poll: "QMQDQT"; offsets: Y = 0, D = 3 T = 1,, A = 11, Q = 13 + f = frequency enable (O = all frequencies enabled) + r = baud rate (3 = 1200, 6 = 9600) + d = features indicator (@ = month/day display enabled) + z = time zone (0 = UTC) + y = year (5 = 1991) + cc = WWV propagation delay (52 = 22 ms) + hh = WWVH propagation delay (81 = 33 ms) + SS = status (80 or 82 = operating correctly) + F = current receive frequency (1-5 = 2.5, 5, 10, 15, 20 MHz) + T = transmitter (C = WWV, H = WWVH) + tttt = time since last update (minutes) + uu = flush character (03 = ^C) + xx = 94 (unknown) (firmware revision X4.01.999 only) + + a = AM/PM indicator (A = AM, P = PM, <SP> - 24-hour format) + hh:mm:ss.fff = hours, minutes, seconds, milliseconds of day + s = daylight-saving indicator (<SP> standard, D daylight) + + yy = year of century (from DIPswitches) + dd/mm/ddd = day of month, month of year, day of year + + Note: The alarm condition is indicated by other than ? at A, which + occurs during initial synchronization and when received signal is + lost for an extended period. A receiver unlock condition is + indicated by other than "0000" in the tttt subfield at Q. + + example: "O3@055281824C00000394 91/08/04/216 15:36:43.640" + T Y D T + +David L. Mills +University of Delaware +mills@udel.edu +23 October 1993 diff --git a/scripts/stats/clock.awk b/scripts/stats/clock.awk new file mode 100755 index 0000000000000..ef62da9ebdc07 --- /dev/null +++ b/scripts/stats/clock.awk @@ -0,0 +1,431 @@ +# awk program to scan clockstat files and report errors/statistics +# +# usage: awk -f check.awk clockstats +# +# This program works for the following radios: +# PST/Traconex 1020 WWV reciever +# Arbiter 1088 GPS receiver +# Spectracom 8170/Netclock-2 WWVB receiver +# IRIG audio decoder +# Austron 2200A/2201A GPS receiver (see README.austron file) +# +BEGIN { + etf_min = osc_vmin = osc_tmin = 1e9 + etf_max = osc_vmax = osc_tmax = -1e9 +} +# +# scan all records in file +# +{ + # + # select PST/Traconex WWV records + # 00:00:37.234 96/07/08/190 O6@0:5281825C07510394 + # + if (NF >= 4 && $3 == "127.127.3.1") { + if (substr($6, 14, 4) > "0010") + wwv_sync++ + if (substr($6, 13, 1) == "C") + wwv_wwv++ + if (substr($6, 13, 1) == "H") + wwv_wwvh++ + x = substr($6, 12, 1) + if (x == "1") + wwv_2.5++ + else if (x == "2") + wwv_5++ + else if (x == "3") + wwv_10++ + else if (x == "4") + wwv_15++ + else if (x == "5") + wwv_20++ + continue + } + # + # select Arbiter GPS records + # 96 190 00:00:37.000 0 V=08 S=44 T=3 P=10.6 E=00 + # N39:42:00.951 W075:46:54.880 210.55 2.50 0.00 + # + if (NF >= 4 && $3 == "127.127.11.1") { + if (NF > 8) { + arb_count++ + if ($7 != 0) + arb_sync++ + x = substr($10, 3, 1) + if (x == "0") + arb_0++ + else if (x == "1") + arb_1++ + else if (x == "2") + arb_2++ + else if (x == "3") + arb_3++ + else if (x == "4") + arb_4++ + else if (x == "5") + arb_5++ + else if (x == "6") + arb_6++ + } else if (NF == 8) { + arbn++ + arb_mean += $7 + arb_rms += $7 * $7 + if (arbn > 0) { + x = $7 - arb_val + arb_var += x * x + } + arb_val = $7 + } + continue + } + # + # select Spectracom WWVB records + # see summary for decode + # 96 189 23:59:32.248 D + # + if (NF >= 4 && $3 == "127.127.4.1") { + if ($4 == "SIGNAL" || NF > 7) + printf "%s\n", $0 + else { + wwvb_count++ + if ($4 ~ /\?/) + wwvb_x++ + else if ($4 ~ /A/) + wwvb_a++ + else if ($4 ~ /B/) + wwvb_b++ + else if ($4 ~ /C/) + wwvb_c++ + else if ($4 ~ /D/) + wwvb_d++ + } + continue + } + # + # select IRIG audio decoder records + # see summary for decode + # + if (NF >= 4 && $3 == "127.127.6.0") { + irig_count++ + if ($5 ~ /\?/) + irig_error++ + continue + } + # + # select Austron GPS LORAN ENSEMBLE records + # see summary for decode + # + else if (NF >= 13 && $6 == "ENSEMBLE") { + ensemble_count++ + if ($9 <= 0) + ensemble_badgps++ + else if ($12 <= 0) + ensemble_badloran++ + else { + if ($13 > 200e-9 || $13 < -200e-9) + ensemble_200++ + else if ($13 > 100e-9 || $13 < -100e-9) + ensemble_100++ + ensemble_mean += $13 + ensemble_rms += $13 * $13 + } + continue + } + # + # select Austron LORAN TDATA records + # see summary for decode; note that signal quality log is simply + # copied to output + # + else if (NF >= 7 && $6 == "TDATA") { + tdata_count++ + for (i = 7; i < NF; i++) { + if ($i == "M" && $(i+1) == "OK") { + i += 5 + m += $i + tdata_m++ + } + else if ($i == "W" && $(i+1) == "OK") { + i += 5 + w += $i + tdata_w++ + } + else if ($i == "X" && $(i+1) == "OK") { + i += 5 + x += $i + tdata_x++ + } + else if ($i == "Y" && $(i+1) == "OK") { + i += 5 + y += $i + tdata_y++ + } + else if ($i == "Z" && $(i+1) == "OK") { + i += 5 + z += $i + tdata_z++ + } + } + continue + } + # + # select Austron ITF records + # see summary for decode + # + else if (NF >= 13 && $5 == "ITF" && $12 >= 100) { + itf_count++ + if ($9 > 200e-9 || $9 < -200e-9) + itf_200++ + else if ($9 > 100e-9 || $9 < -100e-9) + itf_100++ + itf_mean += $9 + itf_rms += $9 * $9 + itf_var += $10 * $10 + continue + } + # + # select Austron ETF records + # see summary for decode + # + else if (NF >= 13 && $5 == "ETF" && $13 >= 100) { + etf_count++ + if ($6 > etf_max) + etf_max = $6 + else if ($6 < etf_min) + etf_min = $6 + etf_mean += $6 + etf_rms += $6 * $6 + etf_var += $9 * $9 + continue + } + # + # select Austron TRSTAT records + # see summary for decode + # + else if (NF >= 5 && $5 == "TRSTAT") { + trstat_count++ + j = 0 + for (i = 6; i <= NF; i++) + if ($i == "T") + j++ + trstat_sat[j]++ + continue + } + # + # select Austron ID;OPT;VER records + # + # config GPS 2201A TTY1 TC1 LORAN IN OUT1 B.00 B.00 28-Apr-93 + # + # GPS 2201A receiver model + # TTY1 rs232 moduel + # TC1 IRIG module + # LORAN LORAN assist module + # IN input module + # OUT1 output module + # B.00 B.00 firmware revision + # 28-Apr-9 firmware date3 + # + else if (NF >= 5 && $5 == "ID;OPT;VER") { + id_count++ + id_temp = "" + for (i = 6; i <= NF; i++) + id_temp = id_temp " " $i + if (id_string != id_temp) + printf "config%s\n", id_temp + id_string = id_temp + continue + } + # + # select Austron POS;PPS;PPSOFF records + # + # position +39:40:48.425 -075:45:02.392 +74.09 Stored UTC 0 200 0 + # + # +39:40:48.425 position north latitude + # -075:45:02.392 position east longitude + # +74.09 elevation (meters) + # Stored position is stored + # UTC time is relative to UTC + # 0 200 0 PPS offsets + # + else if (NF >= 5 && $5 == "POS;PPS;PPSOFF") { + pos_count++ + pos_temp = "" + for (i = 6; i <= NF; i++) + pos_temp = pos_temp " " $i + if (pos_string != pos_temp) + printf "position%s\n", pos_temp + pos_string = pos_temp + continue + } + # + # select Austron OSC;ET;TEMP records + # + # loop 1121 Software Control Locked + # + # 1121 oscillator type + # Software Control loop is under software control + # Locked loop is locked + # + else if (NF >= 5 && $5 == "OSC;ET;TEMP") { + osc_count++ + osc_temp = $6 " " $7 " " $8 " " $9 + if (osc_status != osc_temp) + printf "loop %s\n", osc_temp + osc_status = osc_temp + if ($10 > osc_vmax) + osc_vmax = $10 + if ($10 < osc_vmin) + osc_vmin = $10 + if ($11 > osc_tmax) + osc_tmax = $11 + if ($11 < osc_tmin) + osc_tmin = $11 + continue + } + # + # select Austron UTC records + # these ain't ready yet + # + else if (NF >= 5 && $5 == "UTC") { + utc_count++ + utc_temp = "" + for (i = 6; i <= NF; i++) + utc_temp = utc_temp " " $i + if (utc_string != utc_temp) +# printf "utc%s\n", utc_temp + utc_string = utc_temp + continue + } +} END { +# +# PST/Traconex WWV summary data +# + if (wwv_wwv + wwv_wwvh > 0) + printf "wwv %d, wwvh %d, err %d, MHz (2.5) %d, (5) %d, (10) %d, (15) %d, (20) %d\n", wwv_wwv, wwv_wwvh, wwv_sync, wwv_2.5, wwv_5, wwv_10, wwv_15, wwv_20 +# +# Arbiter 1088 summary data +# +# gps record count +# err error count +# sats(0-6) satellites tracked +# mean 1 PPS mean (us) +# rms 1 PPS rms error (us) +# var 1 PPS Allan variance +# + if (arb_count > 0) { + printf "gps %d, err %d, sats(0-6) %d %d %d %d %d %d %d", arb_count, arb_sync, arb_0, arb_1, arb_2, arb_3, arb_4, arb_5, arb_6 + if (arbn > 1) { + arb_mean /= arbn + arb_rms = sqrt(arb_rms / arbn - arb_mean * arb_mean) + arb_var = sqrt(arb_var / (2 * (arbn - 1))) + printf ", mean %.2f, rms %.2f, var %.2e\n", arb_mean, arb_rms, arb_var * 1e-6 + } else { + printf "\n" + } + } +# +# ensemble summary data +# +# ensemble record count +# badgps gps data unavailable +# badloran loran data unavailable +# rms ensemble rms error (ns) +# >200 ensemble error >200 ns +# >100 100 ns < ensemble error < 200 ns +# + if (ensemble_count > 0) { + ensemble_mean /= ensemble_count + ensemble_rms = sqrt(ensemble_rms / ensemble_count - ensemble_mean * ensemble_mean) * 1e9 + printf "ensemble %d, badgps %d, badloran %d, rms %.1f, >200 %d, >100 %d\n", ensemble_count, ensemble_badgps, ensemble_badloran, ensemble_rms, ensemble_200, ensemble_100 + } +# +# wwvb summary data +# +# wwvb record count +# ? unsynchronized +# >1 error > 1 ms +# >10 error > 10 ms +# >100 error > 100 ms +# >500 error > 500 ms +# + if (wwvb_count > 0) + printf "wwvb %d, ? %d, >1 %d, >10 %d, >100 %d, >500 %d\n", wwvb_count, wwvb_x, wwvb_a, wwvb_b, wwvb_c, wwvb_d +# +# irig summary data +# +# irig record count +# err error count +# + if (irig_count > 0) + printf "irig %d, err %d\n", irig_count, irig_error +# +# tdata summary data +# +# tdata record count +# m M master OK-count, mean level (dB) +# w W slave OK-count, mean level (dB) +# x X slave OK-count, mean level (dB) +# y Y slave OK-count, mean level (dB) +# z Z slave OK-count, mean level (dB) +# + if (tdata_count > 0 ) { + if (tdata_m > 0) + m /= tdata_count + if (tdata_x > 0) + w /= tdata_count + if (tdata_x > 0) + x /= tdata_count + if (tdata_y > 0) + y /= tdata_count + if (tdata_z > 0) + z /= tdata_count + printf "tdata %d, m %d %.1f, w %d %.1f, x %d %.1f, y %d %.1f, z %d %.1f\n", tdata_count, tdata_m, m, tdata_w, w, tdata_x, x, tdata_y, y, tdata_z, z + } +# +# itf summary data +# +# itf record count +# rms itf rms error (ns) +# >200 itf error > 200 ns +# >100 itf error > 100 ns +# var Allan variance +# + if (itf_count > 1) { + itf_mean /= itf_count + itf_rms = sqrt(itf_rms / itf_count - itf_mean * itf_mean) * 1e9 + itf_var = sqrt(itf_var / (2 * (itf_count - 1))) + printf "itf %d, rms %.1f, >200 %d, >100 %d, var %.2e\n", itf_count, itf_rms, itf_200, itf_100, itf_var + } +# +# etf summary data +# +# etf record count +# mean etf mean (ns) +# rms etf rms error (ns) +# max etf maximum (ns) +# min etf minimum (ns) +# var Allan variance +# + if (etf_count > 0) { + etf_mean /= etf_count + etf_rms = sqrt(etf_rms / etf_count - etf_mean * etf_mean) + etf_var = sqrt(etf_var / (2 * (etf_count - 1))) + printf "etf %d, mean %.1f, rms %.1f, max %d, min %d, var %.2e\n", etf_count, etf_mean, etf_rms, etf_max, etf_min, etf_var + } +# +# trstat summary data +# +# trstat record count +# sat histogram of tracked satellites (0 - 7) +# + if (trstat_count > 0) + printf "trstat %d, sat %d %d %d %d %d %d %d %d\n", trstat_count, trstat_sat[0], trstat_sat[1], trstat_sat[2], trstat_sat[2], trstat_sat[3], trstat_sat[4], trstat_sat[5], trstat_sat[6], trstat_sat[7] +# +# osc summary data +# +# osc record count +# control control midrange (V) +/- deviation (mV) +# temp oven temperature midrange +/- deviation (deg C) +# + if (osc_count > 0) + printf "osc %d, control %.3f+/-%.3f, temp %.1f+/-%.2f\n", osc_count, (osc_vmax + osc_vmin) / 2, (osc_vmax - osc_vmin) / 2 * 1e3, (osc_tmax + osc_tmin) / 2, (osc_tmax - osc_tmin) / 2 +} diff --git a/scripts/stats/dupe.awk b/scripts/stats/dupe.awk new file mode 100755 index 0000000000000..317c2a4faf842 --- /dev/null +++ b/scripts/stats/dupe.awk @@ -0,0 +1,8 @@ +# +# delete duplicate lines +# +{ + if (old != $0) + printf "%s\n", $0 + old = $0 +} diff --git a/scripts/stats/ensemble.S b/scripts/stats/ensemble.S new file mode 100755 index 0000000000000..32a4dbabb8207 --- /dev/null +++ b/scripts/stats/ensemble.S @@ -0,0 +1,5 @@ +ensemble <- scan(file1, list(day=0, sec=0, gps=0, gpsw=0, loran=0, loranw=0, ensemble=0, std=0)) +str <- paste("eps/", file1, ".eps", sep="") +postscript(str, , , , 5, pointsize=18) +par(mgp=c(1, 0, 0), tck = 0.03, mar = c(2, 2, 1, 1)) +plot(ensemble$sec, ensemble$ensemble, type="l", xlab=paste("MJD", ensemble$day, "Time (s)"), ylab="Ensemble Offset (ns)", ylim=c(-400, 400)) diff --git a/scripts/stats/ensemble.awk b/scripts/stats/ensemble.awk new file mode 100755 index 0000000000000..136b33da37cbf --- /dev/null +++ b/scripts/stats/ensemble.awk @@ -0,0 +1,17 @@ +# program to produce loran ensemble statistics from clockstats files +# +# usage: awk -f ensemble.awk clockstats +# +# format of input record (time values in seconds) +# 49165 8.628 127.127.10.1 93:178:00:00:07.241 LORAN ENSEMBLE +# -6.43E-08 +5.02E-08 .091 +5.98E-08 +1.59E-08 .909 +4.85E-08 +3.52E-08 +# +# format of output record (time values in nanoseconds) +# MJD sec GPS wgt LORAN wgt avg sigma +# 49165 8.628 -64.3 0.091 59.8 0.909 48.5 35.2 +# +# select LORAN ENSEMBLE records with valid format and weights +{ + if (NF >= 14 && $6 == "ENSEMBLE" && $9 > 0 && $12 > 0) + printf "%5s %9.3f %7.1f %6.3f %7.1f %6.3f %7.1f %7.1f\n", $1, $2, $7*1e9, $9, $10*1e9, $12, $13*1e9, $14*1e9 +} diff --git a/scripts/stats/etf.S b/scripts/stats/etf.S new file mode 100755 index 0000000000000..9b9c68b937b5a --- /dev/null +++ b/scripts/stats/etf.S @@ -0,0 +1,15 @@ +options(digits=4) +file2 <- "etf_summary" +etf <- scan(file1, list(day=0, sec=0, offset=0, stab=0)) +r <- lsfit(etf$sec, etf$offset) +count<-length(etf$sec) +mean<-r$coef[[1]] +std<-sqrt(var(r$residuals)) +slope<-r$coef[[2]] * 1000 +cat("\n", file=file2 , append=TRUE, fill=FALSE, sep="") +cat(file1, "\n", file=file2, append=TRUE, fill=FALSE, sep="") +cat("etf1 ", count, ", T ", mean, " ns, R ", slope, " ps/s, std ", std, " us\n", file=file2, append=TRUE, fill=FALSE, sep="") +str <- paste("eps/", file1, ".eps", sep="") +postscript(str, , , , 5, pointsize=18) +par(mgp=c(1, 0, 0), tck=0.03, mar=c(2, 2, 1, 1)) +plot(etf$sec, etf$offset, type="l", xlab=paste("MJD", etf$day, "Time (s)"), ylab="External Offset (ns)", ylim=c(-400, 400)) diff --git a/scripts/stats/etf.awk b/scripts/stats/etf.awk new file mode 100755 index 0000000000000..8e6e334c1e013 --- /dev/null +++ b/scripts/stats/etf.awk @@ -0,0 +1,19 @@ +# program to produce external time/frequence statistics from clockstats files +# +# usage: awk -f etf.awk clockstats +# +# format of input record +# 49165 40.473 127.127.10.1 93:178:00:00:39.238 ETF +# +175.0 +176.8 2.0 +3.729E-11 +1.000E-10 +3.511E-11 4.005E-13 500 +# +# format of output record (time values in nanoseconds) +# MJD sec time freq +# 49165 40.473 175.0 3.729e-11 +# +# select ETF records with valid format +{ + if (NF >= 9 && $5 == "ETF") { + printf "%5s %9.3f %7.1f %10.3e\n", $1, $2, $6, $9 + } +} + diff --git a/scripts/stats/itf.S b/scripts/stats/itf.S new file mode 100755 index 0000000000000..56c8c8d0cc7a3 --- /dev/null +++ b/scripts/stats/itf.S @@ -0,0 +1,5 @@ +itf <- scan(file1, list(day=0, sec=0, offset=0, stab=0)) +str <- paste("eps/", file1, ".eps", sep="") +postscript(str, , , , 5, pointsize=18) +par(mgp=c(1, 0, 0), tck=0.03, mar=c(2, 2, 1, 1)) +plot(itf$sec, itf$offset, type="l", xlab=paste("MJD", itf$day, "Time (s)"), ylab="Internal Offset (ns)", ylim=c(-400, 400)) diff --git a/scripts/stats/itf.awk b/scripts/stats/itf.awk new file mode 100755 index 0000000000000..2b21c5b9b97cd --- /dev/null +++ b/scripts/stats/itf.awk @@ -0,0 +1,19 @@ +# program to produce intewrnal time/frequence statistics from clockstats files +# +# usage: awk -f itf.awk clockstats +# +# format of input record +# 49227 67.846 127.127.10.1 93:240:00:00:51.816 ITF +# COCO 0 +2.0579E-07 -3.1037E-08 -7.7723E-11 +6.5455E-10 500.00 4.962819 +# +# format of output record (time values in nanoseconds) +# MJD sec time freq +# 49227 67.846 +2.0579E-07 -7.7723E-11 +# +# select ITF records with valid format +{ + if (NF >= 10 && $5 == "ITF") { + printf "%5s %9.3f %7.1f %10.3e\n", $1, $2, $8 * 1e9, $10 + } +} + diff --git a/scripts/stats/loop.S b/scripts/stats/loop.S new file mode 100755 index 0000000000000..8e564b67eb676 --- /dev/null +++ b/scripts/stats/loop.S @@ -0,0 +1,7 @@ +options(digits=4) +loop <- scan(file1, list(day=0, sec=0, offset=0, freq=0, tc=0)) +loop$offset <- loop$offset * 1e6 +str <- paste("eps/", file1, ".eps", sep="") +postscript(str, , , , 5, pointsize=18) +par(mgp=c(1, 0, 0), tck=0.03, mar=c(2, 2, 1, 1)) +plot(loop$sec, loop$offset, type="l", xlab=paste("MJD", loop$day, "Time (s)"), ylab="PLL Offset (us)", ylim=c(-400, 400)) diff --git a/scripts/stats/loop.awk b/scripts/stats/loop.awk new file mode 100755 index 0000000000000..bac90db8b9541 --- /dev/null +++ b/scripts/stats/loop.awk @@ -0,0 +1,45 @@ +# awk program to scan loopstats files and report errors/statistics +# +# usage: awk -f loop.awk loopstats +# +# format of loopstats record +# MJD sec time (s) freq (ppm) poll +# 49235 3.943 0.000016 22.4716 6 +# +# format of output dataset (time values in milliseconds, freq in ppm) +# loopstats.19960706 +# loop 1180, 0+/-11.0, rms 2.3, freq -24.45+/-0.045, var 0.019 +# +BEGIN { + loop_tmax = loop_fmax = -1e9 + loop_tmin = loop_fmin = 1e9 +} +# +# scan all records in file +# +{ + if (NF >= 5) { + loop_count++ + if ($3 > loop_tmax) + loop_tmax = $3 + if ($3 < loop_tmin) + loop_tmin = $3 + if ($4 > loop_fmax) + loop_fmax = $4 + if ($4 < loop_fmin) + loop_fmin = $4 + loop_time += $3 + loop_time_rms += $3 * $3 + loop_freq += $4 + loop_freq_rms += $4 * $4 + } +} END { + if (loop_count > 0) { + loop_time /= loop_count + loop_time_rms = sqrt(loop_time_rms / loop_count - loop_time * loop_time) + loop_freq /= loop_count + loop_freq_rms = sqrt(loop_freq_rms / loop_count - loop_freq * loop_freq) + printf "loop %d, %.0f+/-%.1f, rms %.1f, freq %.2f+/-%0.3f, var %.3f\n", loop_count, (loop_tmax + loop_tmin) / 2 * 1e6, (loop_tmax - loop_tmin) / 2 * 1e6, loop_time_rms * 1e6, (loop_fmax + loop_fmin) / 2, (loop_fmax - loop_fmin) / 2, loop_freq_rms + } +} + diff --git a/scripts/stats/loop_summary b/scripts/stats/loop_summary new file mode 100755 index 0000000000000..35479ecec0da0 --- /dev/null +++ b/scripts/stats/loop_summary @@ -0,0 +1,2 @@ + +loopstats.[1-9] diff --git a/scripts/stats/peer.awk b/scripts/stats/peer.awk new file mode 100755 index 0000000000000..5fe260e495400 --- /dev/null +++ b/scripts/stats/peer.awk @@ -0,0 +1,68 @@ +# awk program to scan peerstats files and report errors/statistics +# +# usage: awk -f peer.awk peerstats +# +# format of peerstats record +# MJD sec ident stat offset (s) delay (s) disp (s) +# 49235 11.632 128.4.2.7 f414 -0.000041 0.21910 0.00084 +# +# format of output dataset (time values in milliseconds) +# peerstats.19960706 +# ident cnt mean rms max delay dist disp +# ========================================================================== +# 140.173.112.2 85 -0.509 1.345 4.606 80.417 49.260 1.092 +# 128.4.1.20 1364 0.058 0.364 4.465 3.712 10.540 1.101 +# 140.173.16.1 1415 -0.172 0.185 1.736 3.145 5.020 0.312 +#... +# +BEGIN { + n = 0 + MAXDISTANCE = 1.0 +} +# +# scan all records in file +# +# we toss out all distances greater than one second on the assumption the +# peer is in initial acquisition +# +{ + if (NF >= 7 && ($7 + $6 / 2) < MAXDISTANCE) { + i = n + for (j = 0; j < n; j++) { + if ($3 == peer_ident[j]) + i = j + } + if (i == n) { + peer_ident[i] = $3 + peer_tmax[i] = peer_dist[i] = -1e9 + peer_tmin[i] = 1e9 + n++ + } + peer_count[i]++ + if ($5 > peer_tmax[i]) + peer_tmax[i] = $5 + if ($5 < peer_tmin[i]) + peer_tmin[i] = $5 + dist = $7 + $6 / 2 + if (dist > peer_dist[i]) + peer_dist[i] = dist + peer_time[i] += $5 + peer_time_rms[i] += $5 * $5 + peer_delay[i] += $6 + peer_disp[i] += $7 + } +} END { + printf " ident cnt mean rms max delay dist disp\n" + printf "==========================================================================\n" + for (i = 0; i < n; i++) { + peer_time[i] /= peer_count[i] + peer_time_rms[i] = sqrt(peer_time_rms[i] / peer_count[i] - peer_time[i] * peer_time[i]) + peer_delay[i] /= peer_count[i] + peer_disp[i] /= peer_count[i] + peer_tmax[i] = peer_tmax[i] - peer_time[i] + peer_tmin[i] = peer_time[i] - peer_tmin[i] + if (peer_tmin[i] > peer_tmax[i]) + peer_tmax[i] = peer_tmin[i] + printf "%-15s%5d%9.3f%9.3f%9.3f%9.3f%9.3f%9.3f\n", peer_ident[i], peer_count[i], peer_time[i] * 1e3, peer_time_rms[i] * 1e3, peer_tmax[i] * 1e3, peer_delay[i] * 1e3, peer_dist[i] * 1e3, peer_disp[i] * 1e3 + } +} diff --git a/scripts/stats/psummary.awk b/scripts/stats/psummary.awk new file mode 100755 index 0000000000000..ec06b0c2cbe35 --- /dev/null +++ b/scripts/stats/psummary.awk @@ -0,0 +1,82 @@ +# program to scan peer_summary file and produce summary of daily summaries +# +# usage: awk -f psummary.awk peer_summary +# +# format of input records +# peerstats.19960706 +# ident cnt mean rms max delay dist disp +# ========================================================================== +# 140.173.112.2 85 -0.509 1.345 4.606 80.417 49.260 1.092 +# 128.4.1.20 1364 0.058 0.364 4.465 3.712 10.540 1.101 +# ... +# +# format of output records (actual data from rackety.udel.edu) +# host days mean rms max >1 >5 >10 >50 +# ================================================================== +# 127.127.22.1 1090 0.001 0.401 99.800 19 14 13 10 +# 127.0.0.1 1188 0.060 1.622 105.004 78 65 51 32 +# 127.127.4.1 586 0.000 0.000 0.000 0 0 0 0 +# 140.173.64.1 975 -0.010 2.552 257.595 399 192 114 8 +# 128.175.1.3 1121 0.447 8.637 204.123 479 460 397 147 +# 140.173.16.1 1106 0.027 1.014 267.857 242 38 31 23 +# 128.4.1.4 1119 0.023 1.037 267.748 223 41 34 23 +# 128.4.1.2 850 1.202 1.654 267.704 196 53 45 34 +# 128.4.1.20 1101 0.088 1.139 268.322 430 111 83 16 +# 140.173.32.1 979 -0.949 2.344 257.671 396 217 136 7 +# 140.173.112.2 1066 0.040 2.111 152.969 442 315 152 16 +# 140.173.80.1 1059 0.019 1.858 87.690 438 348 150 9 +# 140.173.96.1 1015 0.110 2.007 266.744 399 314 170 17 +# 140.173.128.1 1103 -0.002 2.600 257.672 465 262 132 13 +# 140.222.135.1 347 -4.626 8.804 196.394 135 135 134 95 +# 140.173.128.2 1081 -0.046 2.967 261.448 463 342 172 17 +# 140.222.141.1 354 0.820 8.809 195.333 142 141 139 100 +# 140.173.144.2 1058 -0.107 2.805 270.498 448 341 163 17 +# 140.222.134.1 354 -0.056 8.479 172.458 142 141 141 100 +# 140.222.144.1 415 -1.456 9.964 191.684 161 161 161 123 +# 140.222.136.1 234 0.902 7.707 182.431 62 62 62 48 +# 128.175.1.1 774 0.890 4.838 266.799 358 291 200 83 +# 127.127.10.1 1086 -0.002 1.462 231.128 240 239 60 57 +# 140.173.48.2 576 0.016 4.092 350.512 213 126 88 16 +# 128.4.1.11 3 0.000 0.000 0.000 0 0 0 0 +# 128.4.1.26 386 -1.363 20.251 341.284 164 164 161 132 +# +# select table beginning with "ident" +{ + if (NF < 8 || $1 == "ident") + continue + i = n + for (j = 0; j < n; j++) { + if ($1 == peer_ident[j]) + i = j + } + if (i == n) { + peer_ident[i] = $1 + n++ + } + peer_count[i]++ + if (($7 - $6 / 2) < 400) { + peer_count[i]++ + peer_mean[i] += $3 + peer_var[i] += $4 * $4 + if ($5 > peer_max[i]) + peer_max[i] = $5 + if ($5 > 1) + peer_1[i]++ + if ($5 > 5) + peer_2[i]++ + if ($5 > 10) + peer_3[i]++ + if ($5 > 50) + peer_4[i]++ + } +} END { + printf " host days mean rms max >1 >5 >10 >50\n" + printf "==================================================================\n" + for (i = 0; i < n; i++) { + if (peer_count[i] <= 0) + continue + peer_mean[i] /= peer_count[i] + peer_var[i] = sqrt(peer_var[i] / peer_count[i]) + printf "%-15s%4d%10.3f%10.3f%10.3f%4d%4d%4d%4d\n", peer_ident[i], peer_count[i], peer_mean[i], peer_var[i], peer_max[i], peer_1[i], peer_2[i], peer_3[i], peer_4[i] + } +} diff --git a/scripts/stats/summary.sh b/scripts/stats/summary.sh new file mode 100755 index 0000000000000..dffdb0b1569f8 --- /dev/null +++ b/scripts/stats/summary.sh @@ -0,0 +1,88 @@ +#!/bin/sh +# +# Script to summarize ipeerstats, loopstats and clockstats files +# +# This script can be run from a cron job once per day, week or month. It +# runs the file-specific summary script and appends the summary data to +# designated files. +# +DATE=`date +20%y%m%d` +S=/usr/local/bin/S +SIN=S.in +SOUT=S.out +LOOP=loop_summary +PEER=peer_summary +CLOCK=clock_summary + +rm -f $SIN $SOUT + +# +# Summarize loopstats files +# +for f in loopstats.[12][0-9][0-9][0-9][0-1][0-9][0-3][0-9]; do + d=`echo $f | cut -f2 -d.` + if [ -f $f ] && [ $DATE != $d ]; then + echo " " >>$LOOP + echo $f >>$LOOP + awk -f loop.awk $f >>$LOOP + if [ -f $S ]; then + echo "file1<-"\"${f}\" >>$SIN + echo "source("\""loop.S"\"")" >>$SIN + echo "unix("\""rm ${f}"\"")" >>$SIN + else + rm -f $f + fi + fi +done + +# +# Summarize peerstats files +# +for f in peerstats.199[4-9][0-1][0-9][0-3][0-9]; do + d=`echo $f | cut -f2 -d.` + if [ -f $f ] && [ $DATE != $d ]; then + echo " " >>$PEER + echo $f >>$PEER + awk -f peer.awk $f >>$PEER + rm -f $f + fi +done + +# +# Summarize clockstats files +# +for f in clockstats.199[4-9][0-1][0-9][0-3][0-9]; do + d=`echo $f | cut -f2 -d.` + if [ -f $f ] && [ $DATE != $d ]; then + echo " " >>$CLOCK + echo $f >>$CLOCK + awk -f clock.awk $f >>$CLOCK + if [ -f /dev/gps[0-9] ]; then + awk -f itf.awk $f >itf.$d + awk -f etf.awk $f >etf.$d + awk -f ensemble.awk $f >ensemble.$d + awk -f tdata.awk $f >tdata.$d + fi + rm -f $f + fi +done + +# +# Process clockstat files with S and generate PostScript plots +# +for f in itf etf ensemble tdata; do + for d in ${f}.199[4-9][0-1][0-9][0-3][0-9]; do + if [ -f $d ]; then + if [ -f $S ]; then + echo "file1<-"\"${d}\" >>$SIN + echo "source("\"${f}.S\"")" >>$SIN + echo "unix("\""rm ${d}"\"")" >>$SIN + else + rm -f $d + fi + fi + done +done +if [ -f $SIN ]; then + $S BATCH $SIN $SOUT +fi diff --git a/scripts/stats/tdata.S b/scripts/stats/tdata.S new file mode 100755 index 0000000000000..f360a248c06a3 --- /dev/null +++ b/scripts/stats/tdata.S @@ -0,0 +1,5 @@ +tdata <- scan(file1, list(day=0, sec=0, m=0, w=0, x=0, y=0, z=0)) +str <- paste("eps/", file1, ".eps", sep="") +postscript(str, , , , 5, pointsize=18) +par(mgp=c(1, 0, 0), tck=0.03, mar=c(2, 2, 1, 1)) +plot(tdata$sec, tdata$m, type="l", xlab=paste("MJD", tdata$day, "Time (s)"), ylab="LORAN-M SNR (dB)") diff --git a/scripts/stats/tdata.awk b/scripts/stats/tdata.awk new file mode 100755 index 0000000000000..5be9c0490e3f7 --- /dev/null +++ b/scripts/stats/tdata.awk @@ -0,0 +1,45 @@ +# program to produce loran tdata statistics from clockstats files +# +# usage: awk -f tdata.awk clockstats +# +# format of input record (missing replaced by -40.0) +# 49228 36.852 127.127.10.1 93:241:00:00:20.812 LORAN TDATA +# M OK 0 0 1169.14 -7.4 3.16E-07 .424 +# W CV 0 0 3329.30 -16.4 1.81E-06 +# X OK 0 0 1737.19 -10.5 3.44E-07 .358 +# Y OK 0 0 2182.07 -9.0 4.41E-07 .218 +# +# format of output record (time in nanoseconds, signal values in dB) +# MJD sec time M W X Y Z +# 49228 36.852 175.0 -7.4 -16.4 -10.5 -9.0 +# +# select LORAN TDATA records with valid format +{ + if (NF >= 7 && $6 == "TDATA") { + m = w = x = y = z = -40.0 + for (i = 7; i < NF - 5; i++) { + if ($i == "M" && $(i+1) == "OK") { + i += 5 + m = $i + } + else if ($i == "W" && $(i+1) == "OK") { + i += 5 + w = $i + } + else if ($i == "X" && $(i+1) == "OK") { + i += 5 + x = $i + } + else if ($i == "Y" && $(i+1) == "OK") { + i += 5 + y = $i + } + else if ($i == "Z" && $(i+1) == "OK") { + i += 5 + z = $i + } + } + printf "%5s %9.3f %6.1f %6.1f %6.1f %6.1f %6.1f\n", $1, $2, m, w, x, y, z + } +} + |