1e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#! /usr/bin/env python
2e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#
3e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat# btt_plot.py: Generate matplotlib plots for BTT generate data files
4e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#
5e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#  (C) Copyright 2009 Hewlett-Packard Development Company, L.P.
6e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#
7e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#  This program is free software; you can redistribute it and/or modify
8e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#  it under the terms of the GNU General Public License as published by
9e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#  the Free Software Foundation; either version 2 of the License, or
10e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#  (at your option) any later version.
11e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#
12e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#  This program is distributed in the hope that it will be useful,
13e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#  but WITHOUT ANY WARRANTY; without even the implied warranty of
14e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#  GNU General Public License for more details.
16e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#
17e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#  You should have received a copy of the GNU General Public License
18e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#  along with this program; if not, write to the Free Software
19e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#
21e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
22e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat"""
23e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatbtt_plot.py: Generate matplotlib plots for BTT generated data files
24e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
25e20e1347b9914aa05e30548c15d7cd5e412cc0e2San MehatFiles handled:
26e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  AQD	- Average Queue Depth		Running average of queue depths
27e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
28e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  BNOS	- Block numbers accessed	Markers for each block
29e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
30e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  Q2D	- Queue to Issue latencies	Running averages
31e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  D2C	- Issue to Complete latencies	Running averages
32e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  Q2C	- Queue to Complete latencies	Running averages
33e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
34e20e1347b9914aa05e30548c15d7cd5e412cc0e2San MehatUsage:
35e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  btt_plot_aqd.py	equivalent to: btt_plot.py -t aqd	<type>=aqd
36e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  btt_plot_bnos.py	equivalent to: btt_plot.py -t bnos	<type>=bnos
37e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  btt_plot_q2d.py	equivalent to: btt_plot.py -t q2d	<type>=q2d
38e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  btt_plot_d2c.py	equivalent to: btt_plot.py -t d2c	<type>=d2c
39e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  btt_plot_q2c.py	equivalent to: btt_plot.py -t q2c	<type>=q2c
40e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
41e20e1347b9914aa05e30548c15d7cd5e412cc0e2San MehatArguments:
42e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  [ -A          | --generate-all   ] Default: False
43e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  [ -L          | --no-legend      ] Default: Legend table produced
44e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  [ -o <file>   | --output=<file>  ] Default: <type>.png
45e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  [ -T <string> | --title=<string> ] Default: Based upon <type>
46e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  [ -v          | --verbose        ] Default: False
47e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  <data-files...>
48e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
49e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  The -A (--generate-all) argument is different: when this is specified,
50e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  an attempt is made to generate default plots for all 5 types (aqd, bnos,
51e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  q2d, d2c and q2c). It will find files with the appropriate suffix for
52e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  each type ('aqd.dat' for example). If such files are found, a plot for
53e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  that type will be made. The output file name will be the default for
54e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  each type. The -L (--no-legend) option will be obeyed for all plots,
55e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat  but the -o (--output) and -T (--title) options will be ignored.
56e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat"""
57e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
58e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat__author__ = 'Alan D. Brunelle <alan.brunelle@hp.com>'
59e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
60e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#------------------------------------------------------------------------------
61e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
62e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatimport matplotlib
63e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatmatplotlib.use('Agg')
64e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatimport getopt, glob, os, sys
65e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatimport matplotlib.pyplot as plt
66e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
67e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatplot_size	= [10.9, 8.4]	# inches...
68e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
69e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatadd_legend	= True
70e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatgenerate_all	= False
71e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatoutput_file	= None
72e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehattitle_str	= None
73e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehattype		= None
74e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatverbose		= False
75e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
76e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehattypes		= [ 'aqd', 'q2d', 'd2c', 'q2c', 'bnos' ]
77e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatprogs		= [ 'btt_plot_%s.py' % t for t in types ]
78e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
79e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatget_base 	= lambda file: file[file.find('_')+1:file.rfind('_')]
80e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
81e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#------------------------------------------------------------------------------
82e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatdef fatal(msg):
83e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	"""Generate fatal error message and exit"""
84e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
85e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	print >>sys.stderr, 'FATAL: %s' % msg
86e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	sys.exit(1)
87e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
88e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#----------------------------------------------------------------------
89e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatdef get_data(files):
90e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	"""Retrieve data from files provided.
91e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
92e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	Returns a database containing:
93e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		'min_x', 'max_x' 	- Minimum and maximum X values found
94e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		'min_y', 'max_y' 	- Minimum and maximum Y values found
95e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		'x', 'y'		- X & Y value arrays
96e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		'ax', 'ay'		- Running average over X & Y --
97e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat					  if > 10 values provided...
98e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	"""
99e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	#--------------------------------------------------------------
100e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	def check(mn, mx, v):
101e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		"""Returns new min, max, and float value for those passed in"""
102e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
103e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		v = float(v)
104e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if mn == None or v < mn: mn = v
105e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if mx == None or v > mx: mx = v
106e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		return mn, mx, v
107e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
108e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	#--------------------------------------------------------------
109e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	def avg(xs, ys):
110e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		"""Computes running average for Xs and Ys"""
111e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
112e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		#------------------------------------------------------
113e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		def _avg(vals):
114e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			"""Computes average for array of values passed"""
115e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
116e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			total = 0.0
117e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			for val in vals:
118e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				total += val
119e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			return total / len(vals)
120e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
121e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		#------------------------------------------------------
122e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if len(xs) < 1000:
123e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			return xs, ys
124e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
125e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		axs = [xs[0]]
126e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		ays = [ys[0]]
127e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		_xs = [xs[0]]
128e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		_ys = [ys[0]]
129e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
130e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		x_range = (xs[-1] - xs[0]) / 100
131e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		for idx in range(1, len(ys)):
132e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			if (xs[idx] - _xs[0]) > x_range:
133e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				axs.append(_avg(_xs))
134e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				ays.append(_avg(_ys))
135e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				del _xs, _ys
136e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
137e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				_xs = [xs[idx]]
138e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				_ys = [ys[idx]]
139e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			else:
140e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				_xs.append(xs[idx])
141e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				_ys.append(ys[idx])
142e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
143e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if len(_xs) > 1:
144e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			axs.append(_avg(_xs))
145e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			ays.append(_avg(_ys))
146e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
147e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		return axs, ays
148e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
149e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	#--------------------------------------------------------------
150e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	global verbose
151e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
152e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	db = {}
153e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	min_x = max_x = min_y = max_y = None
154e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	for file in files:
155e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if not os.path.exists(file):
156e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			fatal('%s not found' % file)
157e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		elif verbose:
158e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			print 'Processing %s' % file
159e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
160e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		xs = []
161e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		ys = []
162e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		for line in open(file, 'r'):
163e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			f = line.rstrip().split(None)
164e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			if line.find('#') == 0 or len(f) < 2:
165e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				continue
166e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			(min_x, max_x, x) = check(min_x, max_x, f[0])
167e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			(min_y, max_y, y) = check(min_y, max_y, f[1])
168e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			xs.append(x)
169e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			ys.append(y)
170e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
171e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		db[file] = {'x':xs, 'y':ys}
172e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if len(xs) > 10:
173e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			db[file]['ax'], db[file]['ay'] = avg(xs, ys)
174e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		else:
175e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			db[file]['ax'] = db[file]['ay'] = None
176e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
177e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	db['min_x'] = min_x
178e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	db['max_x'] = max_x
179e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	db['min_y'] = min_y
180e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	db['max_y'] = max_y
181e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return db
182e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
183e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#----------------------------------------------------------------------
184e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatdef parse_args(args):
185e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	"""Parse command line arguments.
186e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
187e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	Returns list of (data) files that need to be processed -- /unless/
188e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	the -A (--generate-all) option is passed, in which case superfluous
189e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	data files are ignored...
190e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	"""
191e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
192e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	global add_legend, output_file, title_str, type, verbose
193e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	global generate_all
194e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
195e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	prog = args[0][args[0].rfind('/')+1:]
196e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if prog == 'btt_plot.py':
197e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		pass
198e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	elif not prog in progs:
199e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal('%s not a valid command name' % prog)
200e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	else:
201e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		type = prog[prog.rfind('_')+1:prog.rfind('.py')]
202e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
203e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	s_opts = 'ALo:t:T:v'
204e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	l_opts = [ 'generate-all', 'type', 'no-legend', 'output', 'title',
205e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		   'verbose' ]
206e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
207e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	try:
208e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		(opts, args) = getopt.getopt(args[1:], s_opts, l_opts)
209e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	except getopt.error, msg:
210e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		print >>sys.stderr, msg
211e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal(__doc__)
212e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
213e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	for (o, a) in opts:
214e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if o in ('-A', '--generate-all'):
215e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			generate_all = True
216e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		elif o in ('-L', '--no-legend'):
217e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			add_legend = False
218e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		elif o in ('-o', '--output'):
219e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			output_file = a
220e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		elif o in ('-t', '--type'):
221e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			if not a in types:
222e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				fatal('Type %s not supported' % a)
223e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			type = a
224e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		elif o in ('-T', '--title'):
225e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			title_str = a
226e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		elif o in ('-v', '--verbose'):
227e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			verbose = True
228e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
229e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if type == None and not generate_all:
230e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal('Need type of data files to process - (-t <type>)')
231e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
232e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return args
233e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
234e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#------------------------------------------------------------------------------
235e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatdef gen_title(fig, type, title_str):
236e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	"""Sets the title for the figure based upon the type /or/ user title"""
237e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
238e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if title_str != None:
239e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		pass
240e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	elif type == 'aqd':
241e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		title_str = 'Average Queue Depth'
242e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	elif type == 'bnos':
243e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		title_str = 'Block Numbers Accessed'
244e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	elif type == 'q2d':
245e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		title_str = 'Queue (Q) To Issue (D) Average Latencies'
246e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	elif type == 'd2c':
247e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		title_str = 'Issue (D) To Complete (C) Average Latencies'
248e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	elif type == 'q2c':
249e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		title_str = 'Queue (Q) To Complete (C) Average Latencies'
250e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
251e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	title = fig.text(.5, .95, title_str, horizontalalignment='center')
252e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	title.set_fontsize('large')
253e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
254e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#------------------------------------------------------------------------------
255e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatdef gen_labels(db, ax, type):
256e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	"""Generate X & Y 'axis'"""
257e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
258e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	#----------------------------------------------------------------------
259e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	def gen_ylabel(ax, type):
260e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		"""Set the Y axis label based upon the type"""
261e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
262e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if type == 'aqd':
263e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			str = 'Number of Requests Queued'
264e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		elif type == 'bnos':
265e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			str = 'Block Number'
266e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		else:
267e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			str = 'Seconds'
268e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		ax.set_ylabel(str)
269e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
270e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	#----------------------------------------------------------------------
271e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	xdelta = 0.1 * (db['max_x'] - db['min_x'])
272e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	ydelta = 0.1 * (db['max_y'] - db['min_y'])
273e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
274e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	ax.set_xlim(db['min_x'] - xdelta, db['max_x'] + xdelta)
275e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	ax.set_ylim(db['min_y'] - ydelta, db['max_y'] + ydelta)
276e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	ax.set_xlabel('Runtime (seconds)')
277e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	ax.grid(True)
278e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	gen_ylabel(ax, type)
279e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
280e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#------------------------------------------------------------------------------
281e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatdef generate_output(type, db):
282e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	"""Generate the output plot based upon the type and database"""
283e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
284e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	#----------------------------------------------------------------------
285e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	def color(idx, style):
286e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		"""Returns a color/symbol type based upon the index passed."""
287e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
288e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat                colors = [ 'b', 'g', 'r', 'c', 'm', 'y', 'k' ]
289e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		l_styles = [ '-', ':', '--', '-.' ]
290e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		m_styles = [ 'o', '+', '.', ',', 's', 'v', 'x', '<', '>' ]
291e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
292e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		color = colors[idx % len(colors)]
293e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if style == 'line':
294e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			style = l_styles[(idx / len(l_styles)) % len(l_styles)]
295e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		elif style == 'marker':
296e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			style = m_styles[(idx / len(m_styles)) % len(m_styles)]
297e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
298e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		return '%s%s' % (color, style)
299e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
300e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	#----------------------------------------------------------------------
301e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	def gen_legends(a, legends):
302e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		leg = ax.legend(legends, 'best', shadow=True)
303e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		frame = leg.get_frame()
304e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		frame.set_facecolor('0.80')
305e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		for t in leg.get_texts():
306e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			t.set_fontsize('xx-small')
307e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
308e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	#----------------------------------------------------------------------
309e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	global add_legend, output_file, title_str, verbose
310e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
311e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if output_file != None:
312e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		ofile = output_file
313e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	else:
314e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		ofile = '%s.png' % type
315e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
316e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if verbose:
317e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		print 'Generating plot into %s' % ofile
318e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
319e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	fig = plt.figure(figsize=plot_size)
320e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	ax = fig.add_subplot(111)
321e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
322e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	gen_title(fig, type, title_str)
323e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	gen_labels(db, ax, type)
324e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
325e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	idx = 0
326e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if add_legend:
327e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		legends = []
328e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	else:
329e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		legends = None
330e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
331e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	keys = []
332e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	for file in db.iterkeys():
333e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if not file in ['min_x', 'max_x', 'min_y', 'max_y']:
334e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			keys.append(file)
335e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
336e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	keys.sort()
337e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	for file in keys:
338e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		dat = db[file]
339e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if type == 'bnos':
340e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			ax.plot(dat['x'], dat['y'], color(idx, 'marker'),
341e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				markersize=1)
342e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		elif dat['ax'] == None:
343e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			continue	# Don't add legend
344e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		else:
345e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			ax.plot(dat['ax'], dat['ay'], color(idx, 'line'),
346e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				linewidth=1.0)
347e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if add_legend:
348e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			legends.append(get_base(file))
349e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		idx += 1
350e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
351e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if add_legend and len(legends) > 0:
352e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		gen_legends(ax, legends)
353e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	plt.savefig(ofile)
354e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
355e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#------------------------------------------------------------------------------
356e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatdef get_files(type):
357e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	"""Returns the list of files for the -A option based upon type"""
358e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
359e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if type == 'bnos':
360e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		files = []
361e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		for fn in glob.glob('*c.dat'):
362e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			for t in [ 'q2q', 'd2d', 'q2c', 'd2c' ]:
363e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				if fn.find(t) >= 0:
364e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat					break
365e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			else:
366e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				files.append(fn)
367e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	else:
368e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		files = glob.glob('*%s.dat' % type)
369e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return files
370e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
371e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#------------------------------------------------------------------------------
372e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatif __name__ == '__main__':
373e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	files = parse_args(sys.argv)
374e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
375e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if generate_all:
376e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		output_file = title_str = type = None
377e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		for t in types:
378e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			files = get_files(t)
379e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			if len(files) == 0:
380e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				continue
381e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			elif t != 'bnos':
382e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				generate_output(t, get_data(files))
383e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				continue
384e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
385e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			for file in files:
386e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				base = get_base(file)
387e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				title_str = 'Block Numbers Accessed: %s' % base
388e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				output_file = 'bnos_%s.png' % base
389e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				generate_output(t, get_data([file]))
390e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	elif len(files) < 1:
391e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal('Need data files to process')
392e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	else:
393e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		generate_output(type, get_data(files))
394e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	sys.exit(0)
395