From 59f36fc7683fcba1b63d092160a3b21378df9904 Mon Sep 17 00:00:00 2001 From: Sergei Trofimov Date: Wed, 7 Jun 2017 10:07:22 +0100 Subject: [PATCH] instrument: Add channel discovery to MeasurementCsv - Add "unknown" measurement type to be used when the type of measurement for a CSV column cannot be established. - Make channels argument optional for MeasurementCsv. - If channels for a MeasurementCsv have not been specified, attempt to discover them from the CSV header. This will check if each entry in the header ends with the name of a known MeasurementType prefixed with a "_"; if so, it will assume the reset of the entry is the site. Otherwise, the entire entry will be assumed to be the site and "unknown" MeasurementType will be used. --- devlib/instrument/__init__.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/devlib/instrument/__init__.py b/devlib/instrument/__init__.py index 3828fff..044c7d4 100644 --- a/devlib/instrument/__init__.py +++ b/devlib/instrument/__init__.py @@ -72,6 +72,7 @@ class MeasurementType(object): # Standard measures _measurement_types = [ + MeasurementType('unknown', None), MeasurementType('time', 'seconds', conversions={ 'time_us': lambda x: x * 1000, @@ -132,10 +133,12 @@ class Measurement(object): class MeasurementsCsv(object): - def __init__(self, path, channels): + def __init__(self, path, channels=None): self.path = path self.channels = channels self._fh = open(path, 'rb') + if self.channels is None: + self._load_channels() def measurements(self): return list(self.itermeasurements()) @@ -148,6 +151,29 @@ class MeasurementsCsv(object): values = map(numeric, row) yield [Measurement(v, c) for (v, c) in zip(values, self.channels)] + def _load_channels(self): + self._fh.seek(0) + reader = csv.reader(self._fh) + header = reader.next() + self._fh.seek(0) + + self.channels = [] + for entry in header: + for mt in MEASUREMENT_TYPES: + suffix = '_{}'.format(mt) + if entry.endswith(suffix): + site = entry[:-len(suffix)] + measure = mt + name = '{}_{}'.format(site, measure) + break + else: + site = entry + measure = 'unknown' + name = entry + + chan = InstrumentChannel(name, site, measure) + self.channels.append(chan) + class InstrumentChannel(object):