#!/usr/bin/env python import argparse import labcomm2014 import sys import time class Reader(object): def __init__(self, file_): self._file = file_ def read(self, count): data = self._file.read(count) if len(data) == 0: raise EOFError() return data def mark(self, value, decl): pass class FollowingReader(Reader): def __init__(self, file_, interval, timeout): super(FollowingReader, self).__init__(file_) self._interval = interval self._timeout = timeout def read(self, count): data = '' t_start = time.time() while len(data) < count: tmp = self._file.read(count - len(data)) if tmp: data += tmp else: time.sleep(self._interval) if self._timeout and time.time() - t_start > self._timeout: raise EOFError() return data def flatten(sample, _type): if isinstance(_type, labcomm2014.sample): flatten(sample, _type.decl) elif isinstance(_type, labcomm2014.array): for e in sample: flatten(e, _type.decl) elif isinstance(_type, labcomm2014.struct): for name, decl in _type.field: flatten(sample[name], decl) elif isinstance(_type, labcomm2014.BOOLEAN): print "%d," % sample, elif isinstance(_type, labcomm2014.STRING): print "\"%s\"," % sample, elif isinstance(_type, labcomm2014.primitive): print "%s," % sample, else: raise Exception("Unhandled type. " + str(type(type_)) + " " + str(type_)) def flatten_labels(_type, prefix=""): if isinstance(_type, labcomm2014.sample): flatten_labels(_type.decl, _type.name) elif isinstance(_type, labcomm2014.array): if len(_type.indices) != 1: raise Exception("Fix multidimensional arrays") if len(_type.indices) == 0: raise Exception("We dont't handle dynamical sizes yet %s" % _type) for i in range(0, _type.indices[0]): flatten_labels(_type.decl, prefix + "[%d]" % i) elif isinstance(_type, labcomm2014.struct): for name, decl in _type.field: flatten_labels(decl, prefix + "." + name) elif isinstance(_type, labcomm2014.primitive): print '"%s",' % prefix, else: raise Exception("Unhandled type. " + str(type(type_)) + " " + str(type_)) def default(type_): if isinstance(type_, labcomm2014.sample): return default(type_.decl) elif isinstance(type_, labcomm2014.array): if len(type_.indices) != 1: raise Exception("Fix multidimensional arrays") if len(type_.indices) == 0: raise Exception("We dont't handle dynamical sizes yet %s" % type_) for i in range(0, type_.indices[0]): return [default(type_.decl) for _ in range(type_.indices[0])] elif isinstance(type_, labcomm2014.struct): return {name: default(decl) for name, decl in type_.field} elif isinstance(type_, labcomm2014.STRING): return '' elif isinstance(type_, labcomm2014.BOOLEAN): return False elif (isinstance(type_, labcomm2014.FLOAT) or isinstance(type_, labcomm2014.DOUBLE)): return float('NaN') elif (isinstance(type_, labcomm2014.BYTE) or isinstance(type_, labcomm2014.SHORT) or isinstance(type_, labcomm2014.INTEGER) or isinstance(type_, labcomm2014.LONG)): return 0 else: raise Exception("Unhandled type. " + str(type(type_)) + " " + str(type_)) def dump(sample, _type): for k in sorted(_type.keys()): flatten(sample[k], _type[k]) print def dump_labels(type_): for k in sorted(type_.keys()): flatten_labels(type_[k]) print def defaults(current, type_): for k in sorted(type_.keys()): if k not in current: current[k] = default(type_[k]) def main(main_args): parser = argparse.ArgumentParser() parser.add_argument('elc', type=str, help="The log file.") parser.add_argument('-f', '--follow', action='store_true', help="find all registrations that already " "exist, then watch the file for changes. All " "future registrations are ignored (because " "the header has already been written).") parser.add_argument('-s', '--interval', action="store", type=float, default=0.040, help="time to sleep between failed reads. Requires -f.") parser.add_argument('-t', '--timeout', action="store", type=float, help="timeout to terminate when no changes are detected. " "Requires -f.") parser.add_argument('-w', '--no-default-columns', action="store_true", help="Do not fill columns for which there is no " "data with default values. Wait instead until at least " "one sample has arrived for each registration.") parser.add_argument('-a', '--trigger-all', action="store_true", help="Output one line for each sample instead of for " "each sample of the registration that has arrived with " "the highest frequency.") args = parser.parse_args(main_args) n_samples = {} # The number of received samples for each sample reg. current = {} # The most recent sample for each sample reg. type_ = {} # The type (declaration) of each sample reg. file_ = open(args.elc) if args.follow: reader = FollowingReader(file_, args.interval, args.timeout) else: reader = Reader(file_) d = labcomm2014.Decoder(reader) while True: try: o, t = d.decode() if o is None: n_samples[t.name] = 0 type_[t.name] = t else: n_samples[t.name] += 1 current[t.name] = o break except EOFError: break dump_labels(type_) if not args.no_default_columns: defaults(current, type_) n_rows = 0 while True: try: o, t = d.decode() if o is None: continue current[t.name] = o n_samples[t.name] += 1 if len(current) < len(type_): continue if args.trigger_all: dump(current, type_) else: if n_samples[t.name] > n_rows: n_rows = n_samples[t.name] dump(current, type_) except EOFError: break if __name__ == "__main__": main(sys.argv[1:])