aboutsummaryrefslogtreecommitdiffstats
path: root/plot_exps.py
diff options
context:
space:
mode:
Diffstat (limited to 'plot_exps.py')
-rwxr-xr-xplot_exps.py42
1 files changed, 30 insertions, 12 deletions
diff --git a/plot_exps.py b/plot_exps.py
index 2d6f06b..d49e69d 100755
--- a/plot_exps.py
+++ b/plot_exps.py
@@ -1,7 +1,17 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2from __future__ import print_function 2from __future__ import print_function
3 3
4# Without this trickery, matplotlib uses the current X windows session
5# to create graphs. Problem 1 with this: requires user has an X windows,
6# through ssh -X or otherws. Problem 2: it kills the performance on the
7# computer running the X session, even if that computer isn't the one
8# running plot_exps.py!
9import matplotlib
10matplotlib.use('Agg')
4import matplotlib.pyplot as plot 11import matplotlib.pyplot as plot
12
13import common as com
14import multiprocessing
5import os 15import os
6import shutil as sh 16import shutil as sh
7import sys 17import sys
@@ -9,11 +19,11 @@ import traceback
9 19
10from collections import namedtuple 20from collections import namedtuple
11from config.config import DEFAULTS 21from config.config import DEFAULTS
12from multiprocessing import Pool, cpu_count 22
13from optparse import OptionParser 23from optparse import OptionParser
14from parse.col_map import ColMap,ColMapBuilder 24from parse.col_map import ColMap,ColMapBuilder
15from parse.dir_map import DirMap 25from parse.dir_map import DirMap
16from plot.style import StyleMap 26from plot.style import make_styler
17 27
18def parse_args(): 28def parse_args():
19 parser = OptionParser("usage: %prog [options] [csv_dir]...") 29 parser = OptionParser("usage: %prog [options] [csv_dir]...")
@@ -23,7 +33,8 @@ def parse_args():
23 default=DEFAULTS['out-plot']) 33 default=DEFAULTS['out-plot'])
24 parser.add_option('-f', '--force', action='store_true', default=False, 34 parser.add_option('-f', '--force', action='store_true', default=False,
25 dest='force', help='overwrite existing data') 35 dest='force', help='overwrite existing data')
26 parser.add_option('-p', '--processors', default=max(cpu_count() - 1, 1), 36 parser.add_option('-p', '--processors',
37 default=max(multiprocessing.cpu_count() - 1, 1),
27 type='int', dest='processors', 38 type='int', dest='processors',
28 help='number of threads for processing') 39 help='number of threads for processing')
29 40
@@ -53,8 +64,7 @@ def plot_by_variable(details):
53 builder = ColMapBuilder() 64 builder = ColMapBuilder()
54 config_nodes = [] 65 config_nodes = []
55 66
56 # Generate mapping of (column)=>(line property to vary) for consistently 67 # Decode file names into configuration dicts
57 # formatted plots
58 for line_path, line_node in details.node.children.iteritems(): 68 for line_path, line_node in details.node.children.iteritems():
59 encoded = line_path[:line_path.index(".csv")] 69 encoded = line_path[:line_path.index(".csv")]
60 70
@@ -68,14 +78,13 @@ def plot_by_variable(details):
68 config_nodes += [(line_config, line_node)] 78 config_nodes += [(line_config, line_node)]
69 79
70 col_map = builder.build() 80 col_map = builder.build()
71 style_map = StyleMap(col_map.columns(), col_map.get_values()) 81 style_map = make_styler(col_map)
72 82
73 figure = plot.figure() 83 figure = plot.figure()
74 axes = figure.add_subplot(111) 84 axes = figure.add_subplot(111)
75 85
76 # Create a line for each file node and its configuration 86 # Create a line for each file node and its configuration
77 for line_config, line_node in config_nodes: 87 for line_config, line_node in config_nodes:
78 # Create line style to match this configuration
79 style = style_map.get_style(line_config) 88 style = style_map.get_style(line_config)
80 values = sorted(line_node.values, key=lambda tup: tup[0]) 89 values = sorted(line_node.values, key=lambda tup: tup[0])
81 xvalues, yvalues = zip(*values) 90 xvalues, yvalues = zip(*values)
@@ -85,14 +94,19 @@ def plot_by_variable(details):
85 axes.set_title(details.title) 94 axes.set_title(details.title)
86 95
87 lines, labels = zip(*style_map.get_key()) 96 lines, labels = zip(*style_map.get_key())
88 axes.legend(tuple(lines), tuple(labels), prop={'size':10}, loc=2) 97 axes.legend(tuple(lines), tuple(labels), prop={'size':10},
98 # This code places the legend slightly to the right of the plot
99 bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.0)
89 100
90 axes.set_ylabel(details.value) 101 axes.set_ylabel(details.value)
91 axes.set_xlabel(details.variable) 102 axes.set_xlabel(details.variable)
92 axes.set_xlim(0, axes.get_xlim()[1]) 103 axes.set_xlim(0, axes.get_xlim()[1])
93 axes.set_ylim(0, axes.get_ylim()[1]) 104 axes.set_ylim(0, axes.get_ylim()[1])
94 105
95 plot.savefig(details.out, format=OUT_FORMAT) 106 plot.savefig(details.out, format=OUT_FORMAT,
107 # Using 'tight' causes savefig to rescale the image for non-plot
108 # artists, which in our case is just the legend
109 bbox_inches='tight')
96 110
97 return True 111 return True
98 112
@@ -125,8 +139,12 @@ def plot_dir(data_dir, out_dir, max_procs, force):
125 if not plot_details: 139 if not plot_details:
126 return 140 return
127 141
128 procs = min(len(plot_details), max_procs) 142 procs = min(len(plot_details), max_procs)
129 pool = Pool(processes=procs) 143 logged = multiprocessing.Manager().list()
144
145 pool = multiprocessing.Pool(processes=procs,
146 initializer=com.set_logged_list, initargs=(logged,))
147
130 enum = pool.imap_unordered(plot_wrapper, plot_details) 148 enum = pool.imap_unordered(plot_wrapper, plot_details)
131 149
132 try: 150 try: