1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
|
#! /usr/bin/python
def main():
from pytools.log import LogManager
import sys
from optparse import OptionParser
description = """Operate on data gathered during code runs.
FILE is a log saved from a code run. COMMANDS may be one of the
following:
"list" to list the available time-series and constants,
"plot expr_x,expr_y" to plot a graph,
"datafile outfile expr_x,expr_y" to write out a data file.
"table variable" to print the full data table for a time series variable.
"prefix string" to set the legend prefix for all following plot commands.
"next_legend string" to set the legend string for the next plot command.
"warnings" to list the warnings that were issued during the logged run.
"saveplot filename" to save the current plot to a file.
"print" to print the current plot using "lp".
"""
parser = OptionParser(usage="%prog FILE COMMANDS FILE COMMANDS...",
description=description)
parser.add_option("--scale-x", metavar="XMIN,XMAX",
help="Set the scale of the X axis")
parser.add_option("--scale-y", metavar="YMIN,YMAX",
help="Set the scale of the Y axis")
parser.add_option("--skip", metavar="N", type="int",
help="Only use every N'th data point", default=1)
parser.add_option("--units-x",
help="Show only units, not descriptions on the X axis",
action="store_true")
parser.add_option("--units-y",
help="Show only units, not descriptions on the Y axis",
action="store_true")
parser.add_option("--grid",
help="Show a grid",
action="store_true")
parser.add_option("--legend-expr",
help="Generate a legend from the expression",
action="store_true")
parser.add_option("--legend-descr",
help="Generate a legend from the description",
action="store_true")
parser.add_option("--title",
help="Set the title of a plot",
default="Log evaluation")
parser.add_option("--small-legend", action="store_true")
parser.add_option("--label-x", help="Set the label on the X axis")
parser.add_option("--label-y", help="Set the label on the Y axis")
parser.add_option("--start-step", metavar="STEP", type="int",
help="Start the plot at this timestep number")
parser.add_option("--end-step", metavar="STEP", type="int",
help="End the plot at this timestep number")
options, args = parser.parse_args()
if len(args) < 1:
parser.print_help()
sys.exit(1)
logmgr = None
did_plot = False
saveplot_filename = None
print_plot = False
legend_prefix = ""
from pytools import cartesian_product, Record
class PlotStyle(Record):
pass
styles = [
PlotStyle(dashes=dashes, color=color)
for dashes, color in cartesian_product(
[(), (12, 2), (4, 2), (2,2), (2,8) ],
["blue", "green", "red", "magenta", "cyan"],
)]
def check_no_file():
if logmgr is None:
raise RuntimeError, "no file loaded"
next_legend = None
while args:
cmd = args.pop(0)
if cmd == "list":
check_no_file()
print "Time series"
print "-----------"
items = list(logmgr.quantity_data.iteritems())
items.sort(lambda a,b: cmp(a[0], b[0]))
if items:
col0_len = max(len(k) for k, v in items) + 1
else:
col0_len = 0
for key, qdat in items:
print "%s\t%s" % (key.ljust(col0_len), qdat.description)
print
print "Constants"
print "---------"
items = list(logmgr.constants.iteritems())
items.sort(lambda a,b: cmp(a[0], b[0]))
if items:
col0_len = max(len(k) for k, v in items) + 1
else:
col0_len = 0
for key, value in items:
print "%s\t%s" % (key.ljust(col0_len), str(value))
elif cmd == "plot":
check_no_file()
expr_x, expr_y = args.pop(0).split(",")
from pylab import xlabel, ylabel, plot
(data_x, descr_x, unit_x), (data_y, descr_y, unit_y) = \
logmgr.get_plot_data(expr_x, expr_y,
options.start_step, options.end_step)
if options.label_x:
xlabel(options.label_x)
else:
if options.units_x:
xlabel(unit_x)
else:
xlabel("%s [%s]" % (descr_x, unit_x))
if options.label_y:
ylabel(options.label_y)
else:
if options.units_y:
ylabel(unit_y)
else:
ylabel("%s [%s]" % (descr_y, unit_y))
kwargs = {}
if next_legend:
kwargs["label"] = next_legend
else:
if options.legend_expr:
kwargs["label"] = legend_prefix+expr_y
if options.legend_descr:
kwargs["label"] = legend_prefix+descr_y
style = styles.pop(0)
plot(data_x[::options.skip],
data_y[::options.skip],
dashes=style.dashes, color=style.color,
hold=True, **kwargs)
did_plot = True
next_legend = None
elif cmd == "warnings":
check_no_file()
print logmgr.get_warnings()
elif cmd == "datafile":
check_no_file()
expr_x, expr_y = args.pop(0).split(",")
logmgr.write_datafile(args.pop(0), expr_x, expr_y)
elif cmd == "prefix":
legend_prefix = args.pop(0)
elif cmd == "next_legend":
next_legend = args.pop(0)
elif cmd == "table":
check_no_file()
descrs, units, data = logmgr.get_joint_dataset(args.pop(0).split(","))
if options.start_step is not None:
data = [(step, tup) for step, tup in data
if options.start_step <= step]
if options.end_step is not None:
data = [(step, tup) for step, tup in data
if step <= options.end_step]
from pytools import Table
tbl = Table()
tbl.add_row(["step"]+["%s [%s]" % (d, u) for d,u in zip(descrs, units)])
for row in data:
tbl.add_row([row[0]]+row[1])
print tbl
elif cmd == "saveplot":
saveplot_filename = args.pop(0)
elif cmd == "print":
print_plot = True
else:
# not a known command, interpret as file name
from os import access, R_OK
if access(cmd, R_OK):
logmgr = LogManager(cmd, "r")
else:
raise IOError, "file '%s' not found" % cmd
if did_plot:
from pylab import show, title, legend, axis, grid, savefig
if options.legend_expr or options.legend_descr:
if options.small_legend:
from matplotlib.font_manager import FontProperties
legend(borderpad=0.04, prop=FontProperties(size=8), loc="best",
labelspacing=0)
else:
legend(loc="best")
def float_or_none(str):
if str == "*":
return None
else:
return float(str)
xmin, xmax, ymin, ymax = axis()
if options.scale_x:
xmin_new, xmax_new = [float_or_none(x) for x in options.scale_x.split(",")]
if xmin_new is not None:
xmin = xmin_new
if xmax_new is not None:
xmax = xmax_new
if options.scale_y:
ymin_new, ymax_new = [float_or_none(x) for x in options.scale_y.split(",")]
if ymin_new is not None:
ymin = ymin_new
if ymax_new is not None:
ymax = ymax_new
axis((xmin, xmax, ymin, ymax))
if options.grid:
grid()
title(options.title)
if print_plot:
from tempfile import gettempprefix, gettempdir
import os.path
tmpname = os.path.join(gettempdir(), gettempprefix()+"logtoolprint.ps")
savefig(tmpname, orientation="landscape", papertype="letter")
from os import system, unlink
system("lp %s" % tmpname)
unlink(tmpname)
if saveplot_filename:
savefig(saveplot_filename)
if not print_plot and not saveplot_filename:
show()
if __name__ == "__main__":
main()
|