aboutsummaryrefslogtreecommitdiffstats
path: root/netsec.py
diff options
context:
space:
mode:
Diffstat (limited to 'netsec.py')
-rwxr-xr-xnetsec.py223
1 files changed, 223 insertions, 0 deletions
diff --git a/netsec.py b/netsec.py
new file mode 100755
index 0000000..b1f4f30
--- /dev/null
+++ b/netsec.py
@@ -0,0 +1,223 @@
1#!/usr/bin/env python
2import defapp
3
4from plot import decode
5from util import load_csv_file, write_csv_file
6
7from math import ceil
8
9from numpy import amin, amax, mean, median, std, histogram, zeros, arange
10
11from os.path import splitext, basename
12from optparse import make_option as o
13
14from gnuplot import gnuplot, FORMATS, Plot, label, curve
15
16options = [
17 # output options
18 o('-f', '--format', action='store', dest='format', type='choice',
19 choices=FORMATS, help='output format'),
20 o(None, '--save-script', action='store_true', dest='save_script'),
21 o('-p', '--prefix', action='store', dest='prefix'),
22
23 # formatting options
24 # These may or may not be supported by a particular experiment plotter.
25 o(None, '--smooth', action='store_true', dest='smooth'),
26 o(None, '--hist', action='store_true', dest='histogram'),
27 ]
28
29defaults = {
30 # output options
31 'format' : 'pdf',
32 'save_script' : False,
33 'prefix' : '',
34
35 # formatting options
36 'histogram' : False,
37 'smooth' : False,
38 }
39
40def get_stats_label(samples):
41 avg = mean(samples)
42 med = median(samples)
43 dev = std(samples)
44 max = amax(samples)
45 min = amin(samples)
46 return "min=%.2f max=%.2f avg=%.2f median=%.2f std=%.2f" \
47 % (min, max, avg, med, dev)
48
49class NetsecPlotter(defapp.App):
50 def __init__(self):
51 defapp.App.__init__(self, options, defaults, no_std_opts=True)
52 self.tmpfiles = []
53
54 def make_plot(self, fname=None):
55 p = Plot()
56 p.output = "%s%s.%s" % (self.options.prefix, fname, self.options.format)
57 p.format = self.options.format
58 return p
59
60 def setup_png(self, plot):
61 # standard png options; usually correct; never tweaked for paper
62 if self.options.format == 'png':
63 plot.font_size = 'large'
64 plot.size = (1024, 768)
65 plot.xticks = (0, 1)
66 plot.yticks = (0, 0.1)
67 plot.default_style = "linespoints"
68 return True
69 else:
70 return False
71
72 def write(self, data, name, ext='data'):
73 if self.options.save_script:
74 fname = "%s.%s" % (name, ext)
75 write_csv_file(fname, data)
76 return fname
77 else:
78 tmp = write_csv_file(None, data)
79 # keep a reference so that it isn't deleted
80 self.tmpfiles.append(tmp)
81 return tmp.name
82
83 def load(self, datafile):
84 data = load_csv_file(datafile)
85 print "loaded %d lines" % len(data)
86 return data
87
88 def write_histogram(self, samples, name):
89 max = amax(samples)
90 (hist, edges) = histogram(samples, bins=max,
91 range=(0.5,max+.5))
92 data = zeros((len(edges)-1, 3))
93 cumulative = 0
94 for i in xrange(len(hist)):
95 data[i, 0] = (edges[i] + edges[i + 1]) / 2.0
96 data[i, 1] = hist[i]
97 cumulative += hist[i]
98 data[i, 2] = cumulative
99
100 if len(hist) > 20:
101 label_freq = 10
102 else:
103 label_freq = 1
104
105 for_file = []
106 for i, row in enumerate(data):
107 label = '%d' % row[0] if row[0] % label_freq == 0 else ''
108 for_file.append([row[0], row[1], row[2], label])
109
110 return (data, self.write(for_file, name, ext='hist'))
111
112 def render(self, p):
113 if self.options.save_script:
114 p.gnuplot_save(p.output + '.plot')
115 else:
116 p.gnuplot_exec()
117
118 def plot_hchisto(self, datafile, name, conf):
119 data = self.load(datafile)
120
121 #max_val = amax(data[:,1])
122
123 if self.options.histogram:
124 name += '_hist'
125
126 p = self.make_plot(name)
127
128 # place a label on the graph
129 p.labels = [label(0.5, 0.9, get_stats_label(data[:,1]),
130 coord=['graph', 'screen'], align='center')]
131
132 (data, fname) = self.write_histogram(data[:,1], name)
133 p.xlabel = "hop count"
134
135 p.ylabel = "number of sources"
136 p.setup_histogram(gap=1, boxwidth=1.0)
137 p.title = "hop counts;"
138
139 if 'per-host' in conf:
140 p.title += " HC per-host: %s" % conf['per-host']
141
142 if 'as-num' in conf:
143 p.title += " AS=%s, IP/mask=%s/%s MB=%s Unique Hosts=%s" % \
144 (conf['as-num'], conf['as-str'], conf['as-mask'], \
145 conf['megabytes'], conf['num-hosts'])
146
147# p.xrange = (0, ceil(max_cost))
148 p.xticks = (0, 10)
149# p.yticks = (0, 1)
150 #p.yrange = (0, (ceil(amax(data[:,1]) / 100) * 100))
151
152
153 ymax = amax(data[:,1])
154 p.curves = [curve(histogram=fname, col=2, labels_col=4)]
155 p.yrange = (1, amax(data[:,1]) + 2)
156
157 if ymax > 10000:
158 p.ylog = True
159
160 #print "not implemented yet..."
161 #return
162 ## plot raw samples
163 #p.title = "raw decoding cost; input=%s; host=%s" \
164 # % (conf['file'], conf['host'])
165
166 #p.ylabel = "decoding cost (ms)"
167 #p.xlabel = "frame number"
168 #p.xrange = (0, len(data))
169 ##p.xticks = (0, 100)
170 #p.yticks = (0, 1)
171 #p.yrange = (1, ceil(max_cost) + 2)
172
173 #p.curves = [curve(fname=fname, xcol=2, ycol=1, title="decoding cost")]
174
175
176 #### Styling.
177
178 if not self.setup_png(p):
179 p.rounded_caps = True
180 p.font = 'Helvetica'
181
182 p.font_size = '10'
183 p.size = ('20cm', '10cm')
184 p.monochrome = False
185 p.dashed_lines = False
186 p.key = 'off'
187 p.default_style = 'points lw 1'
188
189 if self.options.smooth:
190 p.default_style += " smooth bezier"
191
192 self.render(p)
193
194
195 def plot_file(self, datafile):
196 bname = basename(datafile)
197 name, ext = splitext(bname)
198 conf = decode(name)
199
200 if 'per-host' in conf or 'as-num' in conf:
201 self.plot_hchisto(datafile, name, conf)
202
203 #for plot_type in plotters:
204 # if plot_type in conf:
205 # try:
206 # plotters[plot_type](datafile, name, conf)
207 # except IOError as err:
208 # self.err("Skipped '%s' (%s)." % err)
209 # break
210 #else:
211 # self.err("Skipped '%s'; unkown experiment type."
212 # % bname)
213
214 # release all tmp files
215 self.tmpfiles = []
216
217 def default(self, _):
218 for i, datafile in enumerate(self.args):
219 self.out("[%d/%d] Processing %s ..." % (i + 1, len(self.args), datafile))
220 self.plot_file(datafile)
221
222if __name__ == "__main__":
223 NetsecPlotter().launch()