Inbetween state. GUI crashes on channelConfig.set()

This commit is contained in:
Anne de Jong 2020-10-31 20:51:35 +01:00
parent fa32e9eac3
commit c1f713c8fb
8 changed files with 183 additions and 50 deletions

View File

@ -100,8 +100,11 @@ cdef extern from "lasp_cppdaq.h" nogil:
vector[double] inchannel_sensitivities vector[double] inchannel_sensitivities
vector[string] inchannel_names vector[string] inchannel_names
vector[string] inchannel_metadata
vector[string] outchannel_names vector[string] outchannel_names
vector[double] outchannel_sensitivities
vector[string] outchannel_metadata
us sampleRateIndex us sampleRateIndex

View File

@ -51,12 +51,16 @@ DaqConfiguration::DaqConfiguration(const DeviceInfo &device) {
enoutchannels.resize(device.noutchannels, false); enoutchannels.resize(device.noutchannels, false);
inchannel_sensitivities.resize(device.ninchannels, 1.0); inchannel_sensitivities.resize(device.ninchannels, 1.0);
inchannel_metadata.resize(device.ninchannels, "");
for (us i = 0; i < eninchannels.size(); i++) { for (us i = 0; i < eninchannels.size(); i++) {
std::stringstream chname; std::stringstream chname;
chname << "Unnamed input channel " << i; chname << "Unnamed input channel " << i;
inchannel_names.push_back(chname.str()); inchannel_names.push_back(chname.str());
} }
outchannel_metadata.resize(device.noutchannels, "");
outchannel_sensitivities.resize(device.noutchannels, 1.0);
for (us i = 0; i < enoutchannels.size(); i++) { for (us i = 0; i < enoutchannels.size(); i++) {
std::stringstream chname; std::stringstream chname;
chname << "Unnamed output channel " << i; chname << "Unnamed output channel " << i;

View File

@ -146,11 +146,11 @@ public:
vector<double> inchannel_sensitivities; vector<double> inchannel_sensitivities;
vector<string> inchannel_names; vector<string> inchannel_names;
vector<string> inchannel_qtys; vector<string> inchannel_metadata;
// This is not necessary at the moment vector<double> outchannel_sensitivities;
/* vector<double> outchannel_sensitivities; */
vector<string> outchannel_names; vector<string> outchannel_names;
vector<string> outchannel_metadata;
us sampleRateIndex = 0; // Index in list of sample rates us sampleRateIndex = 0; // Index in list of sample rates

View File

@ -74,6 +74,13 @@ void fillRtAudioDeviceInfo(vector<DeviceInfo> &devinfolist) {
d.prefDataTypeIndex = d.availableDataTypes.size() - 1; d.prefDataTypeIndex = d.availableDataTypes.size() - 1;
d.availableFramesPerBlock.push_back(512);
d.availableFramesPerBlock.push_back(1024);
d.availableFramesPerBlock.push_back(2048);
d.availableFramesPerBlock.push_back(4096);
d.availableFramesPerBlock.push_back(8192);
d.prefFramesPerBlockIndex = 1;
devinfolist.push_back(d); devinfolist.push_back(d);
} }

View File

@ -8,11 +8,65 @@ Description:
Data Acquistiion (DAQ) device descriptors, and the DAQ devices themselves Data Acquistiion (DAQ) device descriptors, and the DAQ devices themselves
""" """
__all__ = ['DaqChannel', 'DaqConfiguration'] __all__ = ['DaqChannel', 'DaqConfiguration', 'DaqConfigurations']
from ..lasp_common import lasp_shelve, SIQtys, Qty from ..lasp_common import lasp_shelve, SIQtys, Qty
from .lasp_device_common import DaqChannel from .lasp_device_common import DaqChannel
import json import json
cdef class DaqConfigurations:
cdef public:
object input_config, output_config, duplex_mode
def __init__(self, duplex_mode, DaqConfiguration input_config,
DaqConfiguration output_config):
self.input_config = input_config
self.output_config = output_config
self.duplex_mode = duplex_mode
def to_json(self):
return json.dumps(
dict(
duplex_mode = self.duplex_mode,
input_config = self.input_config.to_json(),
output_config = self.output_config.to_json(),
)
)
@staticmethod
def from_json(daq_configs_json):
configs_dict = json.loads(daq_configs_json)
input_config = DaqConfiguration.from_json(configs_dict['input_config'])
output_config = DaqConfiguration.from_json(configs_dict['output_config'])
return DaqConfigurations(configs_dict['duplex_mode'],
input_config,
output_config)
@staticmethod
def loadConfigs():
"""
Returns a list of currently available configurations
"""
with lasp_shelve() as sh:
configs_json = sh.load('daqconfigs', {})
configs = {}
for name, val in configs_json.items():
configs[name] = DaqConfigurations.from_json(val)
return configs
def saveConfigs(self, name):
with lasp_shelve() as sh:
configs_json = sh.load('daqconfigs', {})
configs_json[name] = self.to_json()
sh.store('daqconfigs', configs_json)
@staticmethod
def deleteConfig(name):
with lasp_shelve() as sh:
configs_json = sh.load('daqconfigs', {})
del configs_json[name]
sh.store('daqconfigs', configs_json)
cdef class DaqConfiguration: cdef class DaqConfiguration:
""" """
@ -60,6 +114,10 @@ cdef class DaqConfiguration:
config.inputIEPEEnabled = pydict['inputIEPEEnabled'] config.inputIEPEEnabled = pydict['inputIEPEEnabled']
config.inputACCouplingMode = pydict['inputACCouplingMode'] config.inputACCouplingMode = pydict['inputACCouplingMode']
config.inputRangeIndices = pydict['inputRangeIndices'] config.inputRangeIndices = pydict['inputRangeIndices']
config.inchannel_metadata = [inchmeta.encode('utf-8') for inchmeta in
pydict['inchannel_metadata']]
config.outchannel_metadata = [outchmeta.encode('utf-8') for outchmeta in
pydict['outchannel_metadata']]
pydaqcfg = DaqConfiguration() pydaqcfg = DaqConfiguration()
pydaqcfg.config = config pydaqcfg.config = config
@ -76,8 +134,10 @@ cdef class DaqConfiguration:
inchannel_names = [name.decode('utf-8') for name in inchannel_names = [name.decode('utf-8') for name in
self.config.inchannel_names], self.config.inchannel_names],
outchannel_names = [name.decode('utf-8') for name in outchannel_names = [name.decode('utf-8') for name in
self.config.outchannel_names], self.config.outchannel_names],
sampleRateIndex = self.config.sampleRateIndex, sampleRateIndex = self.config.sampleRateIndex,
dataTypeIndex = self.config.dataTypeIndex, dataTypeIndex = self.config.dataTypeIndex,
framesPerBlockIndex = self.config.framesPerBlockIndex, framesPerBlockIndex = self.config.framesPerBlockIndex,
@ -86,6 +146,11 @@ cdef class DaqConfiguration:
inputIEPEEnabled = self.config.inputIEPEEnabled, inputIEPEEnabled = self.config.inputIEPEEnabled,
inputACCouplingMode = self.config.inputACCouplingMode, inputACCouplingMode = self.config.inputACCouplingMode,
inputRangeIndices = self.config.inputRangeIndices, inputRangeIndices = self.config.inputRangeIndices,
inchannel_metadata = [inchmeta.decode('utf-8') for inchmeta in
self.config.inchannel_metadata],
outchannel_metadata = [outchmeta.decode('utf-8') for outchmeta in
self.config.outchannel_metadata]
)) ))
def getInChannel(self, i:int): def getInChannel(self, i:int):
@ -95,24 +160,43 @@ cdef class DaqConfiguration:
sensitivity=self.config.inchannel_sensitivities[i], sensitivity=self.config.inchannel_sensitivities[i],
range_index=self.config.inputRangeIndices[i], range_index=self.config.inputRangeIndices[i],
ACCoupling_enabled=self.config.inputACCouplingMode[i], ACCoupling_enabled=self.config.inputACCouplingMode[i],
IEPE_enabled=self.config.inputIEPEEnabled[i] IEPE_enabled=self.config.inputIEPEEnabled[i],
channel_metadata=self.config.inchannel_metadata[i].decode('utf-8'),
) )
def getOutChannel(self, i:int): def getOutChannel(self, i:int):
return DaqChannel( return DaqChannel(
channel_enabled=self.config.enoutchannels[i], channel_enabled=self.config.enoutchannels[i],
channel_name=self.config.outchannel_names[i].decode('utf-8'), channel_name=self.config.outchannel_names[i].decode('utf-8'),
channel_metadata=self.config.outchannel_metadata[i].decode('utf-8'),
) )
def setInChannel(self, i:int, daqchannel: DaqChannel):
self.config.eninchannels[i] = daqchannel.channel_enabled
self.config.inchannel_names[i] = daqchannel.channel_name.encode('utf-8')
self.config.inchannel_sensitivities[i] = daqchannel.sensitivity
self.config.inputRangeIndices[i] = daqchannel.range_index
self.config.inputACCouplingMode[i] = daqchannel.ACCoupling_enabled
self.config.inputIEPEEnabled[i] = daqchannel.IEPE_enabled
def setOutChannel(self, i:int, daqchannel: DaqChannel): def setInChannel(self, i:int, ch: DaqChannel):
self.config.enoutchannels[i] = daqchannel.channel_enabled self.config.eninchannels[i] = ch.channel_enabled
self.config.outchannel_names[i] = daqchannel.channel_name self.config.inchannel_names[i] = ch.channel_name.encode('utf-8')
self.config.inchannel_sensitivities[i] = ch.sensitivity
self.config.inputRangeIndices[i] = ch.range_index
self.config.inputACCouplingMode[i] = ch.ACCoupling_enabled
self.config.inputIEPEEnabled[i] = ch.IEPE_enabled
self.config.inchannel_metadata[i] = ch.channel_metadata.encode('utf-8')
def setOutChannel(self, i:int, ch: DaqChannel):
self.config.enoutchannels[i] = ch.channel_enabled
self.config.outchannel_names[i] = ch.channel_name.encode('utf-8')
self.config.outchannel_metadata[i] = ch.channel_metadata.encode('utf-8')
@property
def api(self):
return self.config.api.apiname.decode('utf-8')
@api.setter
def api(self, apitxt):
cdef:
vector[DaqApi] apis = DaqApi.getAvailableApis()
for api in apis:
if api.apiname.decode('utf-8') == apitxt:
self.config.api = api
return
raise RuntimeError(f'Api {apitxt} unavailable')
def eninchannels(self): def eninchannels(self):
return self.config.eninchannels return self.config.eninchannels
@ -120,33 +204,43 @@ cdef class DaqConfiguration:
def enoutchannels(self): def enoutchannels(self):
return self.config.enoutchannels return self.config.enoutchannels
@staticmethod @property
def loadConfigsJSON(): def sampleRateIndex(self):
with lasp_shelve() as sh: return self.config.sampleRateIndex
configs_json = sh.load('daqconfigs', {})
return configs_json
@staticmethod @sampleRateIndex.setter
def loadConfigs(): def sampleRateIndex(self, int idx):
""" self.config.sampleRateIndex = idx
Returns a list of currently available configurations
"""
configs_json = DaqConfiguration.loadConfigsJSON()
configs = {}
for name, val in configs_json.items():
configs[name] = DaqConfiguration.from_json(val)
return configs
def saveConfig(self, name): @property
configs_json = DaqConfiguration.loadConfigsJSON() def dataTypeIndex(self):
return self.config.dataTypeIndex
with lasp_shelve() as sh: @dataTypeIndex.setter
configs_json[name] = self.to_json() def dataTypeIndex(self, int idx):
sh.store('daqconfigs', configs_json) self.config.dataTypeIndex = idx
@property
def framesPerBlockIndex(self):
return self.config.framesPerBlockIndex
@framesPerBlockIndex.setter
def framesPerBlockIndex(self, int idx):
self.config.framesPerBlockIndex = idx
@property
def monitorOutput(self):
return self.config.monitorOutput
@monitorOutput.setter
def monitorOutput(self, bool idx):
self.config.monitorOutput = idx
@property
def device_name(self):
return self.config.device_name.decode('utf-8')
@device_name.setter
def device_name(self, idx):
self.config.device_name = idx.encode('utf-8')
@staticmethod
def deleteConfig(name):
with lasp_shelve() as sh:
cur_configs = DaqConfiguration.loadConfigs()
del cur_configs[name]
sh.store('daqconfigs', cur_configs)

View File

@ -1,7 +1,9 @@
__all__ = ['AvType', 'DaqChannel'] __all__ = ['AvType', 'DaqChannel']
from ..lasp_common import Qty, SIQtys
from dataclasses import dataclass, field from dataclasses import dataclass, field
from dataclasses_json import dataclass_json from dataclasses_json import dataclass_json
from typing import List from typing import List
import json
class AvType: class AvType:
"""Specificying the type of data, for adding and removing callbacks from """Specificying the type of data, for adding and removing callbacks from
@ -19,16 +21,26 @@ class DaqChannel:
range_index: int = 0 range_index: int = 0
ACCoupling_enabled: bool = False ACCoupling_enabled: bool = False
IEPE_enabled: bool = False IEPE_enabled: bool = False
channel_metadata: str = ''
class CouplingMode: def __post_init__(self):
ac = 'AC' self.qty = SIQtys.default
dc = 'DC'
undefined = 'Undefined'
class Range: @property
oneV = '+/- 1 V' def qty(self):
tenV = '+/- 10 V' return self._qty
undefined = 'Undefined'
@qty.setter
def qty(self, newqty):
self._qty = newqty
self._store('qty', newqty)
def _store(self, name, val):
if len(self.channel_metadata) > 0:
meta = json.loads(self.channel_metadata)
else:
meta = {}
meta[name] = val.to_json()
self.channel_metadata = json.dumps(meta)

View File

@ -5,6 +5,9 @@ cdef class DeviceInfo:
def __cinit__(self): def __cinit__(self):
pass pass
def __init__(self):
pass
@property @property
def api(self): return self.devinfo.api.apiname.decode('utf-8') def api(self): return self.devinfo.api.apiname.decode('utf-8')
@ -23,6 +26,10 @@ cdef class DeviceInfo:
@property @property
def availableSampleRates(self): return self.devinfo.availableSampleRates def availableSampleRates(self): return self.devinfo.availableSampleRates
@property
def availableFramesPerBlock(self):
return self.devinfo.availableFramesPerBlock
@property @property
def availableDataTypes(self): def availableDataTypes(self):
pydtypes = [] pydtypes = []
@ -73,3 +80,8 @@ cdef class DeviceInfo:
pydevinfos.append(d) pydevinfos.append(d)
return pydevinfos return pydevinfos
@property
def availableInputRanges(self):
return self.devinfo.availableInputRanges

View File

@ -17,7 +17,8 @@ Common definitions used throughout the code.
""" """
__all__ = [ __all__ = [
'P_REF', 'FreqWeighting', 'TimeWeighting', 'getTime', 'getFreq', 'P_REF', 'FreqWeighting', 'TimeWeighting', 'getTime', 'getFreq', 'Qty',
'SIQtys',
'lasp_shelve', 'this_lasp_shelve', 'W_REF', 'U_REF', 'I_REF', 'dBFS_REF', 'lasp_shelve', 'this_lasp_shelve', 'W_REF', 'U_REF', 'I_REF', 'dBFS_REF',
] ]