mirror of
https://github.com/ARM-software/devlib.git
synced 2025-01-31 02:00:45 +00:00
instrument: add get_raw() API
Derived metrics may be calculated form data in raw output that is not present in the resulting MeasurementCSV. This adds a method to provide uniform access to raw artifacts generated by an instrument.
This commit is contained in:
parent
2afa8f86a4
commit
823ce718bf
@ -297,3 +297,6 @@ class Instrument(object):
|
|||||||
|
|
||||||
def get_data(self, outfile):
|
def get_data(self, outfile):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def get_raw(self):
|
||||||
|
return []
|
||||||
|
@ -121,3 +121,6 @@ class AcmeCapeInstrument(Instrument):
|
|||||||
output_row.append(float(row[i])/1000)
|
output_row.append(float(row[i])/1000)
|
||||||
writer.writerow(output_row)
|
writer.writerow(output_row)
|
||||||
return MeasurementsCsv(outfile, self.active_channels, self.sample_rate_hz)
|
return MeasurementsCsv(outfile, self.active_channels, self.sample_rate_hz)
|
||||||
|
|
||||||
|
def get_raw(self):
|
||||||
|
return [self.raw_data_file]
|
||||||
|
@ -33,6 +33,7 @@ class DaqInstrument(Instrument):
|
|||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
super(DaqInstrument, self).__init__(target)
|
super(DaqInstrument, self).__init__(target)
|
||||||
self._need_reset = True
|
self._need_reset = True
|
||||||
|
self._raw_files = []
|
||||||
if execute_command is None:
|
if execute_command is None:
|
||||||
raise HostError('Could not import "daqpower": {}'.format(import_error_mesg))
|
raise HostError('Could not import "daqpower": {}'.format(import_error_mesg))
|
||||||
if labels is None:
|
if labels is None:
|
||||||
@ -68,6 +69,7 @@ class DaqInstrument(Instrument):
|
|||||||
if not result.status == Status.OK: # pylint: disable=no-member
|
if not result.status == Status.OK: # pylint: disable=no-member
|
||||||
raise HostError(result.message)
|
raise HostError(result.message)
|
||||||
self._need_reset = False
|
self._need_reset = False
|
||||||
|
self._raw_files = []
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
if self._need_reset:
|
if self._need_reset:
|
||||||
@ -86,6 +88,7 @@ class DaqInstrument(Instrument):
|
|||||||
site = os.path.splitext(entry)[0]
|
site = os.path.splitext(entry)[0]
|
||||||
path = os.path.join(tempdir, entry)
|
path = os.path.join(tempdir, entry)
|
||||||
raw_file_map[site] = path
|
raw_file_map[site] = path
|
||||||
|
self._raw_files.append(path)
|
||||||
|
|
||||||
active_sites = unique([c.site for c in self.active_channels])
|
active_sites = unique([c.site for c in self.active_channels])
|
||||||
file_handles = []
|
file_handles = []
|
||||||
@ -131,6 +134,9 @@ class DaqInstrument(Instrument):
|
|||||||
for fh in file_handles:
|
for fh in file_handles:
|
||||||
fh.close()
|
fh.close()
|
||||||
|
|
||||||
|
def get_raw(self):
|
||||||
|
return self._raw_files
|
||||||
|
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
self.execute('close')
|
self.execute('close')
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ class EnergyProbeInstrument(Instrument):
|
|||||||
self.raw_output_directory = None
|
self.raw_output_directory = None
|
||||||
self.process = None
|
self.process = None
|
||||||
self.sample_rate_hz = 10000 # Determined empirically
|
self.sample_rate_hz = 10000 # Determined empirically
|
||||||
|
self.raw_data_file = None
|
||||||
|
|
||||||
for label in self.labels:
|
for label in self.labels:
|
||||||
for kind in self.attributes:
|
for kind in self.attributes:
|
||||||
@ -64,6 +65,7 @@ class EnergyProbeInstrument(Instrument):
|
|||||||
for i, rval in enumerate(self.resistor_values)]
|
for i, rval in enumerate(self.resistor_values)]
|
||||||
rstring = ''.join(parts)
|
rstring = ''.join(parts)
|
||||||
self.command = '{} -d {} -l {} {}'.format(self.caiman, self.device_entry, rstring, self.raw_output_directory)
|
self.command = '{} -d {} -l {} {}'.format(self.caiman, self.device_entry, rstring, self.raw_output_directory)
|
||||||
|
self.raw_data_file = None
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.logger.debug(self.command)
|
self.logger.debug(self.command)
|
||||||
@ -92,10 +94,10 @@ class EnergyProbeInstrument(Instrument):
|
|||||||
num_of_ports = len(self.resistor_values)
|
num_of_ports = len(self.resistor_values)
|
||||||
struct_format = '{}I'.format(num_of_ports * self.attributes_per_sample)
|
struct_format = '{}I'.format(num_of_ports * self.attributes_per_sample)
|
||||||
not_a_full_row_seen = False
|
not_a_full_row_seen = False
|
||||||
raw_data_file = os.path.join(self.raw_output_directory, '0000000000')
|
self.raw_data_file = os.path.join(self.raw_output_directory, '0000000000')
|
||||||
|
|
||||||
self.logger.debug('Parsing raw data file: {}'.format(raw_data_file))
|
self.logger.debug('Parsing raw data file: {}'.format(self.raw_data_file))
|
||||||
with open(raw_data_file, 'rb') as bfile:
|
with open(self.raw_data_file, 'rb') as bfile:
|
||||||
with open(outfile, 'wb') as wfh:
|
with open(outfile, 'wb') as wfh:
|
||||||
writer = csv.writer(wfh)
|
writer = csv.writer(wfh)
|
||||||
writer.writerow(active_channels)
|
writer.writerow(active_channels)
|
||||||
@ -114,3 +116,6 @@ class EnergyProbeInstrument(Instrument):
|
|||||||
else:
|
else:
|
||||||
not_a_full_row_seen = True
|
not_a_full_row_seen = True
|
||||||
return MeasurementsCsv(outfile, self.active_channels, self.sample_rate_hz)
|
return MeasurementsCsv(outfile, self.active_channels, self.sample_rate_hz)
|
||||||
|
|
||||||
|
def get_raw(self):
|
||||||
|
return [self.raw_data_file]
|
||||||
|
@ -20,6 +20,7 @@ class FramesInstrument(Instrument):
|
|||||||
self.collector = None
|
self.collector = None
|
||||||
self.header = None
|
self.header = None
|
||||||
self._need_reset = True
|
self._need_reset = True
|
||||||
|
self._raw_file = None
|
||||||
self._init_channels()
|
self._init_channels()
|
||||||
|
|
||||||
def reset(self, sites=None, kinds=None, channels=None):
|
def reset(self, sites=None, kinds=None, channels=None):
|
||||||
@ -27,6 +28,7 @@ class FramesInstrument(Instrument):
|
|||||||
self.collector = self.collector_cls(self.target, self.period,
|
self.collector = self.collector_cls(self.target, self.period,
|
||||||
self.collector_target, self.header)
|
self.collector_target, self.header)
|
||||||
self._need_reset = False
|
self._need_reset = False
|
||||||
|
self._raw_file = None
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
if self._need_reset:
|
if self._need_reset:
|
||||||
@ -38,14 +40,16 @@ class FramesInstrument(Instrument):
|
|||||||
self._need_reset = True
|
self._need_reset = True
|
||||||
|
|
||||||
def get_data(self, outfile):
|
def get_data(self, outfile):
|
||||||
raw_outfile = None
|
|
||||||
if self.keep_raw:
|
if self.keep_raw:
|
||||||
raw_outfile = outfile + '.raw'
|
self._raw_file = outfile + '.raw'
|
||||||
self.collector.process_frames(raw_outfile)
|
self.collector.process_frames(self._raw_file)
|
||||||
active_sites = [chan.label for chan in self.active_channels]
|
active_sites = [chan.label for chan in self.active_channels]
|
||||||
self.collector.write_frames(outfile, columns=active_sites)
|
self.collector.write_frames(outfile, columns=active_sites)
|
||||||
return MeasurementsCsv(outfile, self.active_channels, self.sample_rate_hz)
|
return MeasurementsCsv(outfile, self.active_channels, self.sample_rate_hz)
|
||||||
|
|
||||||
|
def get_raw(self):
|
||||||
|
return [self._raw_file] if self._raw_file else []
|
||||||
|
|
||||||
def _init_channels(self):
|
def _init_channels(self):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@ -65,8 +65,8 @@ Instrument
|
|||||||
:INSTANTANEOUS: The instrument supports taking a single sample via
|
:INSTANTANEOUS: The instrument supports taking a single sample via
|
||||||
``take_measurement()``.
|
``take_measurement()``.
|
||||||
:CONTINUOUS: The instrument supports collecting measurements over a
|
:CONTINUOUS: The instrument supports collecting measurements over a
|
||||||
period of time via ``start()``, ``stop()``, and
|
period of time via ``start()``, ``stop()``, ``get_data()``,
|
||||||
``get_data()`` methods.
|
and (optionally) ``get_raw`` methods.
|
||||||
|
|
||||||
.. note:: It's possible for one instrument to support more than a single
|
.. note:: It's possible for one instrument to support more than a single
|
||||||
mode.
|
mode.
|
||||||
@ -161,6 +161,13 @@ Instrument
|
|||||||
.. note:: This method is only implemented by :class:`Instrument`\ s that
|
.. note:: This method is only implemented by :class:`Instrument`\ s that
|
||||||
support ``CONTINUOUS`` measurement.
|
support ``CONTINUOUS`` measurement.
|
||||||
|
|
||||||
|
.. method:: Instrument.get_raw()
|
||||||
|
|
||||||
|
Returns a list of paths to files containing raw output from the underlying
|
||||||
|
source(s) that is used to produce the data CSV. If now raw output is
|
||||||
|
generated or saved, an empty list will be returned. The format of the
|
||||||
|
contents of the raw files is entirely source-dependent.
|
||||||
|
|
||||||
.. attribute:: Instrument.sample_rate_hz
|
.. attribute:: Instrument.sample_rate_hz
|
||||||
|
|
||||||
Sample rate of the instrument in Hz. Assumed to be the same for all channels.
|
Sample rate of the instrument in Hz. Assumed to be the same for all channels.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user