1
0
mirror of https://github.com/ARM-software/devlib.git synced 2025-04-05 01:10:03 +01:00
Sergei Trofimov 390a544a92 instrument: allow specifying channels in reset()
Prior to this commit, measurements to be collected were specified via
"sites" and "kinds" parameters. This has the limitation that if you
wanted measurments of kind X from site A and kind Y from site B, you'd
have to specify them as

	reset(sites=['A', 'B'], kinds=['X', 'Y'])

Which would have the effect of also collecting measurments Y for site A
and measurments X for site B. This commit adds the option of specifying
individual channels, via thier labels, e.g.

	reset(channels=['A_X', 'B_Y'])

so that only the channels you're interested in will be collected.
2016-09-02 14:03:33 +01:00

139 lines
5.3 KiB
Python

import os
import csv
import tempfile
from itertools import chain
from devlib.instrument import Instrument, MeasurementsCsv, CONTINUOUS
from devlib.exception import HostError
from devlib.utils.misc import unique
try:
from daqpower.client import execute_command, Status
from daqpower.config import DeviceConfiguration, ServerConfiguration
except ImportError, e:
execute_command, Status = None, None
DeviceConfiguration, ServerConfiguration, ConfigurationError = None, None, None
import_error_mesg = e.message
class DaqInstrument(Instrument):
mode = CONTINUOUS
def __init__(self, target, resistor_values, # pylint: disable=R0914
labels=None,
host='localhost',
port=45677,
device_id='Dev1',
v_range=2.5,
dv_range=0.2,
sampling_rate=10000,
channel_map=(0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23),
):
# pylint: disable=no-member
super(DaqInstrument, self).__init__(target)
self._need_reset = True
if execute_command is None:
raise HostError('Could not import "daqpower": {}'.format(import_error_mesg))
if labels is None:
labels = ['PORT_{}'.format(i) for i in xrange(len(resistor_values))]
if len(labels) != len(resistor_values):
raise ValueError('"labels" and "resistor_values" must be of the same length')
self.server_config = ServerConfiguration(host=host,
port=port)
result = self.execute('list_devices')
if result.status == Status.OK:
if device_id not in result.data:
raise ValueError('Device "{}" is not found on the DAQ server.'.format(device_id))
elif result.status != Status.OKISH:
raise HostError('Problem querying DAQ server: {}'.format(result.message))
self.device_config = DeviceConfiguration(device_id=device_id,
v_range=v_range,
dv_range=dv_range,
sampling_rate=sampling_rate,
resistor_values=resistor_values,
channel_map=channel_map,
labels=labels)
for label in labels:
for kind in ['power', 'voltage']:
self.add_channel(label, kind)
def reset(self, sites=None, kinds=None, channels=None):
super(DaqInstrument, self).reset(sites, kinds, channels)
self.execute('close')
result = self.execute('configure', config=self.device_config)
if not result.status == Status.OK: # pylint: disable=no-member
raise HostError(result.message)
self._need_reset = False
def start(self):
if self._need_reset:
self.reset()
self.execute('start')
def stop(self):
self.execute('stop')
self._need_reset = True
def get_data(self, outfile): # pylint: disable=R0914
tempdir = tempfile.mkdtemp(prefix='daq-raw-')
self.execute('get_data', output_directory=tempdir)
raw_file_map = {}
for entry in os.listdir(tempdir):
site = os.path.splitext(entry)[0]
path = os.path.join(tempdir, entry)
raw_file_map[site] = path
active_sites = unique([c.site for c in self.active_channels])
file_handles = []
try:
site_readers = {}
for site in active_sites:
try:
site_file = raw_file_map[site]
fh = open(site_file, 'rb')
site_readers[site] = csv.reader(fh)
file_handles.append(fh)
except KeyError:
message = 'Could not get DAQ trace for {}; Obtained traces are in {}'
raise HostError(message.format(site, tempdir))
# The first row is the headers
channel_order = []
for site, reader in site_readers.iteritems():
channel_order.extend(['{}_{}'.format(site, kind)
for kind in reader.next()])
def _read_next_rows():
parts = []
for reader in site_readers.itervalues():
try:
parts.extend(reader.next())
except StopIteration:
parts.extend([None, None])
return list(chain(parts))
with open(outfile, 'wb') as wfh:
field_names = [c.label for c in self.active_channels]
writer = csv.writer(wfh)
writer.writerow(field_names)
raw_row = _read_next_rows()
while any(raw_row):
row = [raw_row[channel_order.index(f)] for f in field_names]
writer.writerow(row)
raw_row = _read_next_rows()
return MeasurementsCsv(outfile, self.active_channels)
finally:
for fh in file_handles:
fh.close()
def teardown(self):
self.execute('close')
def execute(self, command, **kwargs):
return execute_command(self.server_config, command, **kwargs)