aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2012-10-29 21:48:23 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2012-10-29 21:48:23 -0400
commit2e804f8fa7d26755088e47357f8de6feb6dbe292 (patch)
tree5e96c664fcd2b072d80ad06808371dd0ceb61505
parent5b50c58ea4881dd185897dfa93860c60f551d815 (diff)
Added option to output parsed data as a python-parseable map.
-rw-r--r--parse/point.py9
-rw-r--r--parse/sched.py5
-rw-r--r--parse/tuple_table.py41
-rwxr-xr-xparse_exps.py25
4 files changed, 62 insertions, 18 deletions
diff --git a/parse/point.py b/parse/point.py
index 8fdd115..d5f4a5e 100644
--- a/parse/point.py
+++ b/parse/point.py
@@ -37,12 +37,13 @@ class Measurement(object):
37 self[Type.Max] = array.max() 37 self[Type.Max] = array.max()
38 self[Type.Avg] = array.mean() 38 self[Type.Avg] = array.mean()
39 self[Type.Var] = array.var() 39 self[Type.Var] = array.var()
40 self[Type.Min] = array.min()
40 return self 41 return self
41 42
42 def __check_type(self, type): 43 def __check_type(self, type):
43 if not type in Type: 44 if not type in Type:
44 raise AttributeError("Not a valid type '%s'" % type) 45 raise AttributeError("Not a valid type '%s'" % type)
45 46
46 def __getitem__(self, type): 47 def __getitem__(self, type):
47 self.__check_type(type) 48 self.__check_type(type)
48 return self.stats[type] 49 return self.stats[type]
@@ -60,11 +61,11 @@ class Measurement(object):
60 61
61 def __str__(self): 62 def __str__(self):
62 return "%s" % dict_str(self.stats, " ") 63 return "%s" % dict_str(self.stats, " ")
63 64
64 65
65class Summary(Measurement): 66class Summary(Measurement):
66 def __init__(self, id, measures, typemap = default_typemap): 67 def __init__(self, id, measures, typemap = default_typemap):
67 super(Summary, self).__init__("Summary-%s" % id) 68 super(Summary, self).__init__(id)
68 69
69 self.__check_types(measures, typemap) 70 self.__check_types(measures, typemap)
70 self.__summarize(measures, typemap) 71 self.__summarize(measures, typemap)
@@ -108,7 +109,7 @@ class ExpPoint(object):
108 def __check_val(self, obj): 109 def __check_val(self, obj):
109 if not isinstance(obj, Measurement): 110 if not isinstance(obj, Measurement):
110 raise AttributeError("Not a valid measurement '%s'" % obj) 111 raise AttributeError("Not a valid measurement '%s'" % obj)
111 112
112 def __getitem__(self, type): 113 def __getitem__(self, type):
113 return self.stats[type] 114 return self.stats[type]
114 115
diff --git a/parse/sched.py b/parse/sched.py
index cbb051e..80764b6 100644
--- a/parse/sched.py
+++ b/parse/sched.py
@@ -1,6 +1,9 @@
1""" 1"""
2TODO: No longer very pythonic, lot of duplicate code 2TODO: No longer very pythonic, lot of duplicate code
3print out task execution times 3print out task execution times or something
4get miss ratio and tardiness directly from schedule OR
5email list about turning on optional summary statistics OR
6set up run exps to only get release and completions to get these stats
4""" 7"""
5 8
6import config.config as conf 9import config.config as conf
diff --git a/parse/tuple_table.py b/parse/tuple_table.py
index 434eb22..465abb3 100644
--- a/parse/tuple_table.py
+++ b/parse/tuple_table.py
@@ -1,7 +1,9 @@
1from collections import defaultdict 1from collections import defaultdict
2from point import SummaryPoint 2from point import SummaryPoint,Type
3from dir_map import DirMap 3from dir_map import DirMap
4 4
5from pprint import pprint
6
5class ColMap(object): 7class ColMap(object):
6 def __init__(self): 8 def __init__(self):
7 self.rev_map = {} 9 self.rev_map = {}
@@ -31,13 +33,16 @@ class ColMap(object):
31 map[self.col_list[i]] = tuple[i] 33 map[self.col_list[i]] = tuple[i]
32 return map 34 return map
33 35
36 def force_add(self, column):
37 self.rev_map[column] = len(self.col_list)
38 self.col_list += [column]
39
34 def try_add(self, column, value): 40 def try_add(self, column, value):
35 if column not in self.rev_map: 41 if column not in self.rev_map:
36 if column not in self.value_map: 42 if column not in self.value_map:
37 self.value_map[column] = value 43 self.value_map[column] = value
38 elif value != self.value_map[column]: 44 elif value != self.value_map[column]:
39 self.rev_map[column] = len(self.col_list) 45 self.force_add(column)
40 self.col_list += [column]
41 46
42 def __str__(self): 47 def __str__(self):
43 return "<ColMap>%s" % (self.rev_map) 48 return "<ColMap>%s" % (self.rev_map)
@@ -53,6 +58,9 @@ class TupleTable(object):
53 key = self.col_map.get_key(kv) 58 key = self.col_map.get_key(kv)
54 self.table[key] += [point] 59 self.table[key] += [point]
55 60
61 def col_map(self):
62 return self.col_map
63
56 def get_exps(self, kv): 64 def get_exps(self, kv):
57 key = self.col_map.get_key(kv) 65 key = self.col_map.get_key(kv)
58 return self.table[key] 66 return self.table[key]
@@ -66,9 +74,32 @@ class TupleTable(object):
66 raise Exception("cannot reduce twice!") 74 raise Exception("cannot reduce twice!")
67 self.reduced = True 75 self.reduced = True
68 for key, values in self.table.iteritems(): 76 for key, values in self.table.iteritems():
69 self.table[key] = SummaryPoint(str(key), values) 77 self.table[key] = SummaryPoint(values[0].id, values)
70 78
71 def write_result(self, out_dir): 79 def write_map(self, out_map):
80 if not self.reduced:
81 raise Exception("must reduce table to write map!")
82
83 rows = {}
84
85 for key, point in self.table.iteritems():
86 row = {}
87 for name,measurement in point:
88 name = name.lower().replace('_','-')
89 row[name]={}
90 for base_type in Type:
91 type_key = str(base_type).lower()
92 if base_type in measurement[Type.Avg]:
93 value = measurement[Type.Avg][base_type]
94 row[name][type_key] = value
95 rows[key] = row
96
97 result = {'columns': self.col_map.columns(), 'rows':rows}
98
99 with open(out_map, 'wc') as map_file:
100 pprint(result,stream=map_file, width=20)
101
102 def write_csvs(self, out_dir):
72 dir_map = DirMap(out_dir) 103 dir_map = DirMap(out_dir)
73 104
74 for key, point in self.table.iteritems(): 105 for key, point in self.table.iteritems():
diff --git a/parse_exps.py b/parse_exps.py
index aa203d3..2d1c370 100755
--- a/parse_exps.py
+++ b/parse_exps.py
@@ -16,10 +16,12 @@ from parse.point import ExpPoint
16from parse.tuple_table import ColMap,TupleTable 16from parse.tuple_table import ColMap,TupleTable
17 17
18def parse_args(): 18def parse_args():
19 # TODO: convert data-dir to proper option
19 parser = OptionParser("usage: %prog [options] [data_dir]...") 20 parser = OptionParser("usage: %prog [options] [data_dir]...")
20 21
21 parser.add_option('-o', '--out-dir', dest='out_dir', 22 parser.add_option('-o', '--out', dest='out',
22 help='directory for data output', default='parse-data') 23 help='file or directory for data output', default='parse-data')
24
23 # TODO: this means nothing 25 # TODO: this means nothing
24 parser.add_option('-c', '--clean', action='store_true', default=False, 26 parser.add_option('-c', '--clean', action='store_true', default=False,
25 dest='clean', help='do not output single-point csvs') 27 dest='clean', help='do not output single-point csvs')
@@ -30,6 +32,9 @@ def parse_args():
30 dest='force', help='overwrite existing data') 32 dest='force', help='overwrite existing data')
31 parser.add_option('-v', '--verbose', action='store_true', default=False, 33 parser.add_option('-v', '--verbose', action='store_true', default=False,
32 dest='verbose', help='print out data points') 34 dest='verbose', help='print out data points')
35 parser.add_option('-m', '--write-map', action='store_true', default=False,
36 dest='write_map',
37 help='Output map of values instead of csv tree')
33 38
34 return parser.parse_args() 39 return parser.parse_args()
35 40
@@ -102,8 +107,8 @@ def main():
102 raise IOError("Base column '%s' not present in any parameters!" % 107 raise IOError("Base column '%s' not present in any parameters!" %
103 base_conf.keys()[0]) 108 base_conf.keys()[0])
104 109
105 base_table = TupleTable(col_map) 110 base_table = TupleTable(col_map) # For tracking 'base' experiments
106 result_table = TupleTable(col_map) 111 result_table = TupleTable(col_map) # For generating csv directories
107 112
108 # Used to find matching scaling_base for each experiment 113 # Used to find matching scaling_base for each experiment
109 for base in scaling_bases: 114 for base in scaling_bases:
@@ -133,13 +138,17 @@ def main():
133 if opts.verbose: 138 if opts.verbose:
134 print(result) 139 print(result)
135 140
136 if opts.force and os.path.exists(opts.out_dir): 141 if opts.force and os.path.exists(opts.out):
137 sh.rmtree(opts.out_dir) 142 sh.rmtree(opts.out)
138 143
139 # Remove un-plottable values
140 result_table.reduce() 144 result_table.reduce()
141 145
142 result_table.write_result(opts.out_dir) 146 if opts.write_map:
147 # Write summarized results into map
148 result_table.write_map(opts.out)
149 else:
150 # Write out csv directories for all variable params
151 result_table.write_csvs(opts.out)
143 152
144if __name__ == '__main__': 153if __name__ == '__main__':
145 main() 154 main()