Commit 95aef48f authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Merge branch 'master' into 'master'

Master

The CSV tool can follow an active log file now.

See merge request !6
parents c6627bc8 1c68e143
#!/usr/bin/env python #!/usr/bin/env python
import sys import argparse
import labcomm import labcomm
import sys
import time
class Reader(object): class Reader(object):
def __init__(self, _file): def __init__(self, file_):
self._file = open(_file) self._file = file_
def read(self, count): def read(self, count):
data = self._file.read(count) data = self._file.read(count)
...@@ -18,6 +20,26 @@ class Reader(object): ...@@ -18,6 +20,26 @@ class Reader(object):
pass 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): def flatten(sample, _type):
if isinstance(_type, labcomm.sample): if isinstance(_type, labcomm.sample):
flatten(sample, _type.decl) flatten(sample, _type.decl)
...@@ -34,27 +56,55 @@ def flatten(sample, _type): ...@@ -34,27 +56,55 @@ def flatten(sample, _type):
elif isinstance(_type, labcomm.primitive): elif isinstance(_type, labcomm.primitive):
print "%s," % sample, print "%s," % sample,
else: else:
print sample, _type raise Exception("Unhandled type. " + str(type(type_)) + " " + str(type_))
def flatten_labels(sample, _type, prefix=""): def flatten_labels(_type, prefix=""):
if isinstance(_type, labcomm.sample): if isinstance(_type, labcomm.sample):
flatten_labels(sample, _type.decl, _type.name) flatten_labels(_type.decl, _type.name)
elif isinstance(_type, labcomm.array): elif isinstance(_type, labcomm.array):
if len(_type.indices) != 1: if len(_type.indices) != 1:
raise Exception("Fix multidimensional arrays") raise Exception("Fix multidimensional arrays")
if len(sample) == 0: if len(_type.indices) == 0:
raise Exception("We dont't handle dynamical sizes yet %s" % _type) raise Exception("We dont't handle dynamical sizes yet %s" % _type)
for i in range(0, len(sample)): for i in range(0, _type.indices[0]):
flatten_labels(sample[i], _type.decl, prefix + "[%d]" % i) flatten_labels(_type.decl, prefix + "[%d]" % i)
elif isinstance(_type, labcomm.struct): elif isinstance(_type, labcomm.struct):
for name, decl in _type.field: for name, decl in _type.field:
flatten_labels(sample[name], decl, flatten_labels(decl,
prefix + "." + name) prefix + "." + name)
elif isinstance(_type, labcomm.primitive): elif isinstance(_type, labcomm.primitive):
print '"%s",' % prefix, print '"%s",' % prefix,
else: else:
print sample, _type raise Exception("Unhandled type. " + str(type(type_)) + " " + str(type_))
def default(type_):
if isinstance(type_, labcomm.sample):
return default(type_.decl)
elif isinstance(type_, labcomm.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_, labcomm.struct):
return {name: default(decl) for name, decl in type_.field}
elif isinstance(type_, labcomm.STRING):
return ''
elif isinstance(type_, labcomm.BOOLEAN):
return False
elif (isinstance(type_, labcomm.FLOAT) or
isinstance(type_, labcomm.DOUBLE)):
return float('NaN')
elif (isinstance(type_, labcomm.BYTE) or
isinstance(type_, labcomm.SHORT) or
isinstance(type_, labcomm.INTEGER) or
isinstance(type_, labcomm.LONG)):
return 0
else:
raise Exception("Unhandled type. " + str(type(type_)) + " " + str(type_))
def dump(sample, _type): def dump(sample, _type):
...@@ -63,49 +113,84 @@ def dump(sample, _type): ...@@ -63,49 +113,84 @@ def dump(sample, _type):
print print
def dump_labels(current, _type): def dump_labels(type_):
for k in sorted(_type.keys()): for k in sorted(type_.keys()):
flatten_labels(current[k], _type[k]) flatten_labels(type_[k])
print print
def main(): def defaults(current, type_):
if len(sys.argv) != 2: for k in sorted(type_.keys()):
sys.exit("Give input file as argument\n") if k not in current:
d = labcomm.Decoder(Reader(sys.argv[1])) current[k] = default(type_[k])
seen = {}
current = {}
_type = {} def main(main_args):
parser = argparse.ArgumentParser()
# Do one pass through the file to find all registrations. 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 = labcomm.Decoder(reader)
while True: while True:
try: try:
o, t = d.decode() o, t = d.decode()
if o is None: if o is None:
seen[t.name] = 0 n_samples[t.name] = 0
_type[t.name] = t type_[t.name] = t
else: else:
n_samples[t.name] += 1
current[t.name] = o current[t.name] = o
break
except EOFError: except EOFError:
break break
dump_labels(current, _type) dump_labels(type_)
if not args.no_default_columns:
# Do another pass to extract the data. defaults(current, type_)
current = {} n_rows = 0
d = labcomm.Decoder(Reader(sys.argv[1]))
while True: while True:
try: try:
o, t = d.decode() o, t = d.decode()
if o is not None: if o is None:
current[t.name] = o continue
if len(current) == len(_type): current[t.name] = o
# Assume that samples arrive at different rates. n_samples[t.name] += 1
# Trigger on everything once we have a value for if len(current) < len(type_):
# each column. continue
dump(current, _type) 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: except EOFError:
break break
if __name__ == "__main__": if __name__ == "__main__":
main() main(sys.argv[1:])
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment