diff options
Diffstat (limited to 'plot_exps.py')
-rwxr-xr-x | plot_exps.py | 42 |
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 |
2 | from __future__ import print_function | 2 | from __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! | ||
9 | import matplotlib | ||
10 | matplotlib.use('Agg') | ||
4 | import matplotlib.pyplot as plot | 11 | import matplotlib.pyplot as plot |
12 | |||
13 | import common as com | ||
14 | import multiprocessing | ||
5 | import os | 15 | import os |
6 | import shutil as sh | 16 | import shutil as sh |
7 | import sys | 17 | import sys |
@@ -9,11 +19,11 @@ import traceback | |||
9 | 19 | ||
10 | from collections import namedtuple | 20 | from collections import namedtuple |
11 | from config.config import DEFAULTS | 21 | from config.config import DEFAULTS |
12 | from multiprocessing import Pool, cpu_count | 22 | |
13 | from optparse import OptionParser | 23 | from optparse import OptionParser |
14 | from parse.col_map import ColMap,ColMapBuilder | 24 | from parse.col_map import ColMap,ColMapBuilder |
15 | from parse.dir_map import DirMap | 25 | from parse.dir_map import DirMap |
16 | from plot.style import StyleMap | 26 | from plot.style import make_styler |
17 | 27 | ||
18 | def parse_args(): | 28 | def 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: |