[Git][NTPsec/ntpsec][master] 2 commits: statfiles:py: fix percentiles() for empty and singular data sets.
Gary E. Miller
gitlab at mg.gitlab.com
Fri Jan 6 23:48:57 UTC 2017
Gary E. Miller pushed to branch master at NTPsec / ntpsec
Commits:
0cfc154e by Gary E. Miller at 2017-01-06T15:44:47-08:00
statfiles:py: fix percentiles() for empty and singular data sets.
- - - - -
8b551646 by Gary E. Miller at 2017-01-06T15:45:28-08:00
ntpviz: add stat summaries for gps-log data.
- - - - -
2 changed files:
- ntpclients/ntpviz
- pylib/statfiles.py
Changes:
=====================================
ntpclients/ntpviz
=====================================
--- a/ntpclients/ntpviz
+++ b/ntpclients/ntpviz
@@ -172,7 +172,7 @@ class VizStats(ntp.statfiles.NTPStats):
stats_html = ''
- def __init__(self, values, title, freq=0):
+ def __init__(self, values, title, freq=0, units=''):
values.sort()
self.percs = self.percentiles((100, 99, 95, 50, 5, 1, 0), values)
@@ -188,7 +188,12 @@ class VizStats(ntp.statfiles.NTPStats):
target = max(self.percs["p99"], -self.percs["p1"],
self.percs["p100"]/5, -self.percs["p0"]/5)
- if 1 <= target:
+ if len(units):
+ # fixed scale
+ self.multiplier = 1
+ self.unit = units
+
+ elif 1 <= target:
self.multiplier = 1
if freq:
# go to ppm
@@ -374,6 +379,8 @@ set rmargin 10
starttime=starttime,
endtime=endtime)
+ # FIXME: plot_slice can also gather the values and
+ # save yet another loop over the data
def plot_slice(self, rows, item1, item2=None):
"slice 0,item1, maybe item2, from rows, ready for gnuplot"
# speed up by only sending gnuplot the data it will actually use
@@ -619,21 +626,47 @@ component of frequency drift.</p>
sys.stderr.write("ntpviz: INFO: no GPS data to graph\n")
return ''
- stats = []
+ # build the output dictionary, because Python can not format
+ # complex objects.
gps_data = ()
+ values_nsat = []
+ values_tdop = []
plot_data = ""
for key in gpslist:
# fields: time, TDOP, nSats
- plot_data += self.plot_slice(gpsmap[key], 3, 4)
+ ps = self.plot_slice(gpsmap[key], 3, 4)
+ for line in ps.splitlines():
+ l = line.split()
+ if 3 != len(l):
+ continue
+ try:
+ values_tdop.append(float(l[1]))
+ values_nsat.append(float(l[2]))
+ except:
+ continue
+ plot_data += ps
- out = {}
+ stats = VizStats(values_nsat, "nSats", units='nSat')
+ stats_tdop = VizStats(values_tdop, "TDOP", units=' ')
+
+ out = stats_tdop.percs
out['sitename'] = sitename
out['size'] = args.png_size
+ if out['min_y'] == out['max_y']:
+ # some GPS always output the same TDOP
+ if 0 == out['min_y']:
+ # scale 0:1
+ out['max_y'] = 1
+ else:
+ # scale +/- 20%
+ out['min_y'] = out['max_y'] * 0.8
+ out['max_y'] = out['max_y'] * 1.2
plot_template = NTPViz.Common + """\
set terminal png size %(size)s
set title "%(sitename)s: Local GPS
set ytics format "%%1.1f TDOP" nomirror textcolor rgb '#0060ad'
+set yrange [%(min_y)s:%(max_y)s]
set y2tics format "%%2.0f nSat" nomirror textcolor rgb '#dd181f'
set style line 1 lc rgb '#0060ad' lt 1 lw 1 pt 7 ps 0 # --- blue
set style line 2 lc rgb '#dd181f' lt 1 lw 1 pt 5 ps 0 # --- red
@@ -653,8 +686,14 @@ plot \\
The number of visible satellites (nSat) is plotted in red.</p>
<p>TDOP is field 3, and nSats is field 4, from the gpsd log file. The
gpsd log file is created by the gps-log program.</p>
+<p>TDOP is a dimensionless error factor. TDOP ranges from 1 to greater
+than 20. 1 denotes the highest possible confidence level. 2 to 5 is good.
+Greater than 20 means there will be significant inaccuracy and error.</p>
"""
- ret = {'html': exp, 'stats': stats}
+
+ ret = {}
+ ret['html'] = stats.stats_html + stats_tdop.stats_html + exp
+ ret['stats'] = [stats, stats_tdop]
ret['title'] = "Local GPS"
ret['plot'] = plot_template + plot_data + plot_data
return ret
@@ -1306,7 +1345,7 @@ Python by ESR, concept and gnuplot code by Dan Drown.
type=int)
parser.add_argument('-V', '--version',
action="version",
- version= "ntpviz %s" % ntp.util.stdversion())
+ version="ntpviz %s" % ntp.util.stdversion())
args = parser.parse_args()
=====================================
pylib/statfiles.py
=====================================
--- a/pylib/statfiles.py
+++ b/pylib/statfiles.py
@@ -141,11 +141,22 @@ class NTPStats:
"assuming values are already split and sorted"
ret = {}
length = len(values)
- for perc in percents:
- if perc == 100:
- ret["p100"] = values[length - 1]
+ if 1 >= length:
+ # uh, oh...
+ if 1 == length:
+ # just one data value, set all to that one value
+ v = values[0]
else:
- ret["p" + str(perc)] = values[int(length * (perc/100))]
+ # no data, set all to zero
+ v = 0
+ for perc in percents:
+ ret["p" + str(perc)] = v
+ else:
+ for perc in percents:
+ if perc == 100:
+ ret["p100"] = values[length - 1]
+ else:
+ ret["p" + str(perc)] = values[int(length * (perc/100))]
return ret
def peersplit(self):
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/967ae81a5b138ade0a4bdac2e66bbcf3a4f16f80...8b551646e70827ed8116deba9aa792c7fe41fe48
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ntpsec.org/pipermail/vc/attachments/20170106/19ff2f95/attachment.html>
More information about the vc
mailing list