Level ref value can be changed in SLM, Qty stuff stored in measurement
This commit is contained in:
parent
0a8949e0cf
commit
4dd95cb80c
@ -10,8 +10,8 @@ Data Acquistiion (DAQ) device descriptors, and the DAQ devices themselves
|
||||
"""
|
||||
from dataclasses import dataclass, field
|
||||
from dataclasses_json import dataclass_json
|
||||
import numpy as np
|
||||
from ..lasp_common import lasp_shelve, Qty
|
||||
from ..lasp_common import lasp_shelve, Qty, SIQtys
|
||||
from typing import List
|
||||
|
||||
|
||||
@dataclass
|
||||
@ -35,7 +35,7 @@ class DAQChannel:
|
||||
channel_enabled: bool
|
||||
channel_name: str
|
||||
sensitivity: float
|
||||
unit: Qty
|
||||
qty: Qty
|
||||
|
||||
|
||||
@dataclass_json
|
||||
@ -83,12 +83,12 @@ class DAQConfiguration:
|
||||
en_input_rate: int
|
||||
en_output_rate: int
|
||||
|
||||
input_channel_configs: list
|
||||
output_channel_configs: list
|
||||
monitor_gen: bool
|
||||
input_channel_configs: List[DAQChannel] = field(default_factory=list)
|
||||
output_channel_configs: List[DAQChannel] = field(default_factory=list)
|
||||
monitor_gen: bool = False
|
||||
|
||||
outputDelayBlocks: int
|
||||
nFramesPerBlock: int
|
||||
outputDelayBlocks: int = 0
|
||||
nFramesPerBlock: int = 512
|
||||
|
||||
def firstEnabledInputChannelNumber(self):
|
||||
"""
|
||||
@ -135,6 +135,9 @@ class DAQConfiguration:
|
||||
def getEnabledInputChannelNames(self):
|
||||
return [ch.channel_name for ch in self.getEnabledInputChannels()]
|
||||
|
||||
def getEnabledInputChannelQtys(self):
|
||||
return [ch.qty for ch in self.getEnabledInputChannels()]
|
||||
|
||||
def getEnabledInputChannelSensitivities(self):
|
||||
return [float(channel.sensitivity) for channel in
|
||||
self.getEnabledInputChannels()]
|
||||
@ -146,23 +149,36 @@ class DAQConfiguration:
|
||||
en_channels.append(chan)
|
||||
return en_channels
|
||||
|
||||
def getEnabledOutputChannelQtys(self):
|
||||
return [ch.qty for ch in self.getEnabledOutputChannels()]
|
||||
|
||||
def getEnabledOutputChannelSensitivities(self):
|
||||
return [float(channel.sensitivity) for channel in
|
||||
self.getEnabledOutputChannels()]
|
||||
|
||||
@staticmethod
|
||||
def loadConfigsJSON():
|
||||
with lasp_shelve() as sh:
|
||||
configs_json = sh.load('daqconfigs', {})
|
||||
return configs_json
|
||||
|
||||
@staticmethod
|
||||
def loadConfigs():
|
||||
"""
|
||||
Returns a list of currently available configurations
|
||||
"""
|
||||
with lasp_shelve() as sh:
|
||||
return sh.load('daqconfigs', {})
|
||||
configs_json = DAQConfiguration.loadConfigsJSON()
|
||||
configs = {}
|
||||
for name, val in configs_json.items():
|
||||
configs[name] = DAQConfiguration.from_json(val)
|
||||
return configs
|
||||
|
||||
def saveConfig(self, name):
|
||||
configs_json = DAQConfiguration.loadConfigsJSON()
|
||||
|
||||
with lasp_shelve() as sh:
|
||||
cur_configs = self.loadConfigs()
|
||||
cur_configs[name] = self
|
||||
sh.store('daqconfigs', cur_configs)
|
||||
configs_json[name] = self.to_json()
|
||||
sh.store('daqconfigs', configs_json)
|
||||
|
||||
@staticmethod
|
||||
def deleteConfig(name):
|
||||
|
@ -51,12 +51,15 @@ class AvStream:
|
||||
if daqconfig.monitor_gen:
|
||||
self.input_channel_names = self.output_channel_names
|
||||
self.input_sensitivity = daqconfig.getEnabledOutputChannelSensitivities()
|
||||
self.input_qtys = daqconfig.getEnabledOutputChannelQtys()
|
||||
else:
|
||||
self.input_channel_names = []
|
||||
self.input_sensitivity = []
|
||||
self.input_qtys = []
|
||||
|
||||
self.input_sensitivity += daqconfig.getEnabledInputChannelSensitivities()
|
||||
self.input_sensitivity = np.asarray(self.input_sensitivity)
|
||||
self.input_qtys += daqconfig.getEnabledInputChannelQtys()
|
||||
|
||||
# Fill in numpy data type, and sample width
|
||||
self.input_numpy_dtype = get_numpy_dtype_from_format_string(
|
||||
|
@ -16,6 +16,8 @@ is assumed to be acoustic data.
|
||||
'sensitivity': (Optionally) the stored sensitivity of the record channels.
|
||||
This can be a single value, or a list of sensitivities for
|
||||
each channel. Both representations are allowed.
|
||||
'qtys' : (Optionally): list of quantities that is recorded for each channel', if
|
||||
this array is not found. Quantities are defaulted to 'Number / Full scale'
|
||||
|
||||
- Datasets:
|
||||
|
||||
@ -182,6 +184,19 @@ class Measurement:
|
||||
|
||||
self._time = f.attrs['time']
|
||||
|
||||
|
||||
try:
|
||||
qtys_json = f.attrs['qtys']
|
||||
self._qtys = [Qty.from_json(qty_json) for qty_json in qtys_json]
|
||||
except KeyError:
|
||||
self._qtys = [SIQtys.default for i in range(self.nchannels)]
|
||||
|
||||
def setAttribute(self, atrname, value):
|
||||
with self.file('r+') as f:
|
||||
# Update comment attribute in the file
|
||||
f.attrs[atrname] = value
|
||||
setattr(self, '_' + atrname, value)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Returns filename base without extension."""
|
||||
@ -191,6 +206,52 @@ class Measurement:
|
||||
def channelNames(self):
|
||||
return self._channel_names
|
||||
|
||||
@channelNames.setter
|
||||
def channelNames(self, newchnames):
|
||||
if len(newchnames) != self.nchannels:
|
||||
raise RuntimeError('Invalid length of new channel names')
|
||||
self.setAttribute('channelNames', newchnames)
|
||||
|
||||
@property
|
||||
def channelConfig(self):
|
||||
return [DAQChannel(channel_enabled=True,
|
||||
channel_name=chname,
|
||||
sensitivity=sens,
|
||||
qty=qty)
|
||||
for chname, sens, qty in zip(
|
||||
self.channelNames,
|
||||
self.sensitivity,
|
||||
self.qtys)]
|
||||
|
||||
@channelConfig.setter
|
||||
def channelConfig(self, chcfg):
|
||||
chname = []
|
||||
sens = []
|
||||
qtys = []
|
||||
for ch in chcfg:
|
||||
chname.append(ch.channel_name)
|
||||
sens.append(ch.sensitivity)
|
||||
qtys.append(ch.qty)
|
||||
|
||||
self.channelNames = chname
|
||||
self.sensitivity = sens
|
||||
self.qtys = qtys
|
||||
|
||||
@property
|
||||
def qtys(self):
|
||||
return self._qtys
|
||||
|
||||
@qtys.setter
|
||||
def qtys(self, newqtys):
|
||||
if not len(newqtys) == len(self._qtys):
|
||||
raise ValueError('Invalid number of quantities')
|
||||
qtys_json = [qty.to_json() for qty in newqtys]
|
||||
# Use setAttribute here, but thos store the jsonified version as well,
|
||||
# which we have to overwrite again with the deserialized ones. This is
|
||||
# actually not a very nice way of coding.
|
||||
self.setAttribute('qtys', qtys_json)
|
||||
self._qtys = newqtys
|
||||
|
||||
@contextmanager
|
||||
def file(self, mode='r'):
|
||||
"""Contextmanager which opens the storage file and yields the file.
|
||||
@ -322,11 +383,11 @@ class Measurement:
|
||||
|
||||
@property
|
||||
def sensitivity(self):
|
||||
"""Sensitivity of the data in Pa^-1, from floating point data scaled
|
||||
between -1.0 and 1.0 to Pascal.
|
||||
"""Sensitivity of the data in U^-1, from floating point data scaled
|
||||
between -1.0 and 1.0 to Units [U].
|
||||
|
||||
If the sensitivity is not stored in the measurement file, this
|
||||
function returns 1.0
|
||||
function returns 1.0 for each channel
|
||||
"""
|
||||
return self._sens
|
||||
|
||||
@ -361,6 +422,8 @@ class Measurement:
|
||||
if isinstance(sens, float):
|
||||
# Put all sensitivities equal
|
||||
sens = sens * np.ones(self.nchannels)
|
||||
elif isinstance(sens, list):
|
||||
sens = np.asarray(sens)
|
||||
|
||||
valid = sens.ndim == 1
|
||||
valid &= sens.shape[0] == self.nchannels
|
||||
|
@ -102,6 +102,7 @@ class Recording:
|
||||
f.attrs['sensitivity'] = stream.input_sensitivity
|
||||
f.attrs['channel_names'] = stream.input_channel_names
|
||||
f.attrs['time'] = time.time()
|
||||
f.attrs['qtys'] = [qty.to_json() for qty in stream.input_qtys]
|
||||
self._running <<= True
|
||||
|
||||
if not stream.isRunning():
|
||||
|
@ -6,7 +6,7 @@ Sound level meter implementation
|
||||
"""
|
||||
from .wrappers import Slm as pyxSlm
|
||||
import numpy as np
|
||||
from .lasp_common import (TimeWeighting, P_REF, FreqWeighting)
|
||||
from .lasp_common import (TimeWeighting, FreqWeighting, P_REF)
|
||||
from .filter import SPLFilterDesigner
|
||||
|
||||
__all__ = ['SLM', 'Dummy']
|
||||
@ -36,7 +36,8 @@ class SLM:
|
||||
fw=FreqWeighting.A,
|
||||
xmin = None,
|
||||
xmax = None,
|
||||
include_overall=True):
|
||||
include_overall=True,
|
||||
level_ref_value=P_REF):
|
||||
"""
|
||||
Initialize a sound level meter object.
|
||||
|
||||
@ -52,6 +53,7 @@ class SLM:
|
||||
xmax: Filter designator of highest band
|
||||
include_overall: If true, a non-functioning filter is added which
|
||||
is used to compute the overall level.
|
||||
level_ref_value: Reference value for computing the levels in dB
|
||||
|
||||
"""
|
||||
|
||||
@ -105,7 +107,7 @@ class SLM:
|
||||
self.nom_txt.append('overall')
|
||||
|
||||
self.slm = pyxSlm(prefilter, sos,
|
||||
fs, tw[0], P_REF)
|
||||
fs, tw[0], level_ref_value)
|
||||
|
||||
dsfac = self.slm.downsampling_fac
|
||||
if dsfac > 0:
|
||||
|
Loading…
Reference in New Issue
Block a user