1"""Shared routines for the plotters.""" 2 3import fileinput 4import collections 5 6Record = collections.namedtuple('Record', 'variant function bytes loops src_alignment dst_alignment run_id elapsed rest') 7 8 9def make_colours(): 10 return iter('m b g r c y k pink orange brown grey'.split()) 11 12def parse_value(v): 13 """Turn text into a primitive""" 14 try: 15 if '.' in v: 16 return float(v) 17 else: 18 return int(v) 19 except ValueError: 20 return v 21 22def create_column_tuple(record, names): 23 cols = [getattr(record, name) for name in names] 24 return tuple(cols) 25 26def unique(records, name, prefer=''): 27 """Return the unique values of a column in the records""" 28 if type(name) == tuple: 29 values = list(set(create_column_tuple(x, name) for x in records)) 30 else: 31 values = list(set(getattr(x, name) for x in records)) 32 33 if not values: 34 return values 35 elif type(values[0]) == str: 36 return sorted(values, key=lambda x: '%-06d|%s' % (-prefer.find(x), x)) 37 else: 38 return sorted(values) 39 40def alignments_equal(alignments): 41 for alignment in alignments: 42 if alignment[0] != alignment[1]: 43 return False 44 return True 45 46def parse_row(line): 47 return Record(*[parse_value(y) for y in line.split(':')]) 48 49def parse(): 50 """Parse a record file into named tuples, correcting for loop 51 overhead along the way. 52 """ 53 records = [parse_row(x) for x in fileinput.input()] 54 55 # Pull out any bounce values 56 costs = {} 57 58 for record in [x for x in records if x.function=='bounce']: 59 costs[(record.bytes, record.loops)] = record.elapsed 60 61 # Fix up all of the records for cost 62 out = [] 63 64 for record in records: 65 if record.function == 'bounce': 66 continue 67 68 cost = costs.get((record.bytes, record.loops), None) 69 70 if not cost: 71 out.append(record) 72 else: 73 # Unfortunately you can't update a namedtuple... 74 values = list(record) 75 values[-2] -= cost 76 out.append(Record(*values)) 77 78 return out 79