3 # Create a figure with the NeuroDebian repo subscription stats from the apache logs
5 # zgrep "GET /lists/[a-z\.]\+ HTTP" neuro.debian.net-*access*gz | sed -e 's,.*gz:\([0-9\.]\+\).*\[\(.*\):.*:.*:.*/lists/\(.*\) HTTP.*,\2;\3;\1,' -e 's,/, ,g'
6 # either from a file or on stdin. Needs output filename as the only argument
10 from datetime import datetime
15 from matplotlib.dates import date2num
16 from matplotlib.dates import YearLocator, MonthLocator, DateFormatter
17 from matplotlib.font_manager import FontProperties
18 from ConfigParser import SafeConfigParser
27 def make_figure(data, ymax):
28 fig = pl.figure(figsize=(14,3))
29 ax = fig.add_subplot(121)
30 plot_datehist(ax, data, 10, [code for code in cfg.options('release codenames') if cfg.get('release codenames', code).count('Debian')], title="Debian", ymax=ymax)
31 ax = fig.add_subplot(122)
32 plot_datehist(ax, data, 10, [code for code in cfg.options('release codenames') if cfg.get('release codenames', code).count('Ubuntu')], title="Ubuntu", ymax=ymax)
37 def plot_datehist(ax, data, bins, suites, title=None, ymax=None):
38 colors=['#ff0088', '#20435C', '#45902C', '#E08720']
43 for i, suite in enumerate(suites):
44 dates = data['date'][data['suite'] == suite]
46 history_length = dates.max() - dates.min()
47 # make approx monthly bins, smaller bins yield spiky curves
48 # needs new=True to work with oldish numpy
49 (hist, bin_edges) = np.histogram(dates, np.ceil(history_length/30.), new=True)
50 if len(bin_edges) < 2:
51 # protect against single data point entries by ignoring them
52 # wouldn't be able to draw a line anyway ;-)
54 width = bin_edges[1] - bin_edges[0]
56 ax.plot(bin_edges[:-1]+(width/2), hist / width,
57 label=suite, color=colors[i%4], linestyle=linestyle[i//4], lw=2)
58 # transparent curve shading
59 ax.fill_between(bin_edges[:-1]+(width/2), 0, hist / width, alpha=0.2,
60 label=suite, color=colors[i%4])
61 # figure out axis limits to avoid whitespace in plots
62 x_max = bin_edges[-2] + width/2
63 x_min = bin_edges[0] + width/2
64 if global_x_max is None or x_max > global_x_max:
66 if global_x_min is None or x_min < global_x_min:
69 ax.set_xlim(global_x_min, global_x_max)
70 ax.set_ylabel('New subscriptions [1/day]')
77 # see: http://matplotlib.sourceforge.net/examples/api/date_demo.html
78 ax.xaxis.set_major_locator(YearLocator())
79 ax.xaxis.set_major_formatter(DateFormatter('\n\n%Y'))
80 ax.xaxis.set_minor_locator(MonthLocator())
81 ax.xaxis.set_minor_formatter(DateFormatter('%b'))
82 # format the coords message box
83 ax.format_xdata = DateFormatter('%Y-%m-%d')
85 # pukes with old matplotlib
86 #font = FontProperties()
88 pl.legend(loc='upper left', #prop=font,
89 labelspacing=.2, borderaxespad=.2,
90 handletextpad=.2, borderpad=.2)
93 if __name__ == '__main__':
94 if not len(sys.argv) > 1:
95 print 'Need output filename.'
97 cfg_path="/home/neurodebian/neurodebian.git/neurodebian.cfg"
98 cfg = SafeConfigParser()
101 for line in fileinput.FileInput(sys.argv[2:], openhook=fileinput.hook_compressed):
102 date, list_, ip = line.split(';')
104 suite, loc = list_.split('.')
108 date = datetime.strptime(date, "%d %b %Y")
109 data.append((ip.strip(), loc, suite, date2num(date)))
110 data = np.array(data, dtype=dt)
111 make_figure(data, ymax=18).savefig(sys.argv[1], bbox_inches='tight', dpi=60)