Converted daqconfig to Python3.7 dataclass. Changed revtime name to revtimewidget. Added real time APS dialog. But contains bug on close! Split up SLMWidget and SLM into different files for accessing the SLM class from scripts. Changed lower y-limits of figure plot in GUI to something more sensible. Added umik to list of devices, but does not work yet due to 24-bits audio bug. First steps to change legend position in bar plot.
This commit is contained in:
parent
889a1898f5
commit
a10326d617
@ -20,7 +20,8 @@ include_directories(
|
|||||||
# DEPENDS MakeTable
|
# DEPENDS MakeTable
|
||||||
# )
|
# )
|
||||||
|
|
||||||
set(ui_files ui_apsrtsettings ui_mainwindow ui_figure ui_about ui_apswidget ui_revtime ui_slmwidget ui_daq ui_apssettings)
|
set(ui_files ui_apsrtsettings ui_mainwindow ui_figure ui_about
|
||||||
|
ui_apswidget ui_revtimewidget ui_slmwidget ui_daqwidget ui_apssettings)
|
||||||
foreach(fn ${ui_files})
|
foreach(fn ${ui_files})
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT "${fn}.py"
|
OUTPUT "${fn}.py"
|
||||||
|
@ -8,76 +8,53 @@ Description:
|
|||||||
Data Acquistiion (DAQ) device descriptors, and the DAQ devices themselves
|
Data Acquistiion (DAQ) device descriptors, and the DAQ devices themselves
|
||||||
|
|
||||||
"""
|
"""
|
||||||
__all__ = ['DAQConfiguration', 'roga_plugndaq', 'default_soundcard']
|
from dataclasses import dataclass, field
|
||||||
|
from .lasp_daqdevice import query_devices, DeviceInfo
|
||||||
|
__all__ = ['DAQConfiguration', 'roga_plugndaq', 'umik',
|
||||||
|
'default_soundcard', 'configs',
|
||||||
|
'findDAQDevice']
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
class DAQConfiguration:
|
class DAQConfiguration:
|
||||||
def __init__(self, name,
|
"""
|
||||||
cardname,
|
Initialize a device descriptor
|
||||||
cardlongnamematch,
|
|
||||||
device_name,
|
|
||||||
en_format,
|
|
||||||
en_input_rate,
|
|
||||||
en_input_channels,
|
|
||||||
|
|
||||||
input_sensitivity,
|
Args:
|
||||||
input_gain_settings,
|
name: Name of the device to appear to the user
|
||||||
en_input_gain_setting,
|
cardname: ALSA name identifier
|
||||||
|
cardlongnamematch: Long name according to ALSA
|
||||||
en_output_rate,
|
device_name: ASCII name with which to open the device when connected
|
||||||
en_output_channels):
|
en_format: index in the list of sample formats
|
||||||
"""
|
en_input_rate: index of enabled input sampling frequency [Hz]
|
||||||
Initialize a device descriptor
|
in the list of frequencies.
|
||||||
|
en_input_channels: list of channel indices which are used to
|
||||||
Args:
|
acquire data from.
|
||||||
name: Name of the device to appear to the user
|
input_sensitivity: List of sensitivity values, in units of [Pa^-1]
|
||||||
cardname: ALSA name identifier
|
input_gain_settings: If a DAQ supports it, list of indices which
|
||||||
cardlongnamematch: Long name according to ALSA
|
corresponds to a position in the possible input
|
||||||
device_name: ASCII name with which to open the device when connected
|
gains for each channel. Should only be not equal
|
||||||
en_format: index in the list of sample formats
|
to None when the hardware supports changing the
|
||||||
en_input_rate: index of enabled input sampling frequency [Hz]
|
input gain.
|
||||||
in the list of frequencies.
|
en_output_rate: index in the list of possible output sampling
|
||||||
en_input_channels: list of channel indices which are used to
|
frequencies.
|
||||||
acquire data from.
|
en_output_channels: list of enabled output channels
|
||||||
input_sensitivity: List of sensitivity values, in units of [Pa^-1]
|
|
||||||
input_gain_setting: If a DAQ supports it, list of indices which
|
|
||||||
corresponds to a position in the possible input
|
|
||||||
gains for each channel. Should only be not equal
|
|
||||||
to None when the hardware supports changing the
|
|
||||||
input gain.
|
|
||||||
en_output_rate: index in the list of possible output sampling
|
|
||||||
frequencies.
|
|
||||||
en_output_channels: list of enabled output channels
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.name = name
|
|
||||||
self.cardlongnamematch = cardlongnamematch
|
|
||||||
self.cardname = cardname
|
|
||||||
self.device_name = device_name
|
|
||||||
self.en_format = en_format
|
|
||||||
|
|
||||||
self.en_input_rate = en_input_rate
|
|
||||||
self.en_input_channels = en_input_channels
|
|
||||||
|
|
||||||
self.input_sensitivity = input_sensitivity
|
|
||||||
self.input_gain_settings = input_gain_settings
|
|
||||||
|
|
||||||
self.en_output_rate = en_output_rate
|
|
||||||
self.en_output_channels = en_output_channels
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
"""
|
|
||||||
String representation of configuration
|
|
||||||
"""
|
|
||||||
rep = f"""Name: {self.name}
|
|
||||||
Enabled input channels: {self.en_input_channels}
|
|
||||||
Enabled input sampling frequency: {self.en_input_rate}
|
|
||||||
Input gain settings: {self.input_gain_settings}
|
|
||||||
Sensitivity: {self.input_sensitivity}
|
|
||||||
"""
|
|
||||||
return rep
|
|
||||||
|
|
||||||
|
name: str
|
||||||
|
cardname: str
|
||||||
|
cardlongnamematch: str
|
||||||
|
device_name: str
|
||||||
|
en_format: int
|
||||||
|
en_input_rate: int
|
||||||
|
en_input_channels: list
|
||||||
|
input_sensitivity: list
|
||||||
|
input_gain_settings: list
|
||||||
|
en_input_gain_settings: list = field(default_factory=list)
|
||||||
|
en_output_rate: int = -1
|
||||||
|
en_output_channels: list = field(default_factory=list)
|
||||||
|
|
||||||
def match(self, device):
|
def match(self, device):
|
||||||
"""
|
"""
|
||||||
@ -117,10 +94,23 @@ roga_plugndaq = DAQConfiguration(name='Roga-instruments Plug.n.DAQ USB',
|
|||||||
en_input_channels=[0],
|
en_input_channels=[0],
|
||||||
input_sensitivity=[46.92e-3, 46.92e-3],
|
input_sensitivity=[46.92e-3, 46.92e-3],
|
||||||
input_gain_settings=[-20, 0, 20],
|
input_gain_settings=[-20, 0, 20],
|
||||||
en_input_gain_setting=[1, 1],
|
en_input_gain_settings=[1, 1],
|
||||||
en_output_rate=1,
|
en_output_rate=1,
|
||||||
en_output_channels=[False, False]
|
en_output_channels=[False, False]
|
||||||
)
|
)
|
||||||
|
umik = DAQConfiguration(name='UMIK-1',
|
||||||
|
cardname='Umik-1 Gain: 18dB',
|
||||||
|
cardlongnamematch='miniDSP Umik-1 Gain: 18dB',
|
||||||
|
device_name='iec958:CARD=U18dB,DEV=0',
|
||||||
|
en_format=0,
|
||||||
|
en_input_rate=0,
|
||||||
|
en_input_channels=[0],
|
||||||
|
input_sensitivity=[1., 1.],
|
||||||
|
input_gain_settings=[0., 0.],
|
||||||
|
en_input_gain_settings=[0, 0],
|
||||||
|
en_output_rate=0,
|
||||||
|
en_output_channels=[True, True]
|
||||||
|
)
|
||||||
|
|
||||||
default_soundcard = DAQConfiguration(name="Default device",
|
default_soundcard = DAQConfiguration(name="Default device",
|
||||||
cardname=None,
|
cardname=None,
|
||||||
@ -131,8 +121,23 @@ default_soundcard = DAQConfiguration(name="Default device",
|
|||||||
en_input_channels=[0],
|
en_input_channels=[0],
|
||||||
input_sensitivity=[1.0, 1.0],
|
input_sensitivity=[1.0, 1.0],
|
||||||
input_gain_settings=[0],
|
input_gain_settings=[0],
|
||||||
en_input_gain_setting=[0, 0],
|
en_input_gain_settings=[0, 0],
|
||||||
en_output_rate=1,
|
en_output_rate=1,
|
||||||
en_output_channels=[]
|
en_output_channels=[]
|
||||||
)
|
)
|
||||||
configs = (roga_plugndaq, default_soundcard)
|
configs = (roga_plugndaq, default_soundcard)
|
||||||
|
|
||||||
|
|
||||||
|
def findDAQDevice(config: DAQConfiguration) -> DeviceInfo:
|
||||||
|
"""
|
||||||
|
Search for a DaQ device for the given configuration.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config: configuration to search a device for
|
||||||
|
"""
|
||||||
|
devices = query_devices()
|
||||||
|
|
||||||
|
for device in devices:
|
||||||
|
if config.match(device):
|
||||||
|
return device
|
||||||
|
return None
|
||||||
|
@ -129,8 +129,13 @@ class DeviceInfo:
|
|||||||
Will later be replaced by a dataclass. Storage container for a lot of
|
Will later be replaced by a dataclass. Storage container for a lot of
|
||||||
device parameters.
|
device parameters.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
rep = f"""Device name: {self.device_name}
|
rep = f"""Device name: {self.device_name}
|
||||||
|
Card name: {self.cardname}
|
||||||
|
Available sample formats: {self.available_formats}
|
||||||
|
Max input channels: {self.max_input_channels}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return rep
|
return rep
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ class AvStream:
|
|||||||
self._vframectr <<= 0
|
self._vframectr <<= 0
|
||||||
self._video_started <<= False
|
self._video_started <<= False
|
||||||
|
|
||||||
def isStarted(self):
|
def isRunning(self):
|
||||||
return self._running()
|
return self._running()
|
||||||
|
|
||||||
def hasVideo(self):
|
def hasVideo(self):
|
||||||
|
@ -7,11 +7,11 @@ Common definitions used throughout the code.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
__all__ = ['P_REF', 'FreqWeighting', 'TimeWeighting', 'getTime', 'calfile',
|
__all__ = ['P_REF', 'FreqWeighting', 'TimeWeighting', 'getTime', 'calfile',
|
||||||
]
|
'W_REF']
|
||||||
|
|
||||||
# Reference sound pressure level
|
# Reference sound pressure level
|
||||||
P_REF = 2e-5
|
P_REF = 2e-5
|
||||||
|
W_REF = 1e-12 # 1 picoWatt
|
||||||
# Todo: fix This
|
# Todo: fix This
|
||||||
# calfile = '/home/anne/wip/UMIK-1/cal/7027430_90deg.txt'
|
# calfile = '/home/anne/wip/UMIK-1/cal/7027430_90deg.txt'
|
||||||
calfile = None
|
calfile = None
|
||||||
|
@ -67,7 +67,7 @@ class Recording:
|
|||||||
self._running <<= True
|
self._running <<= True
|
||||||
# Videothread is going to start
|
# Videothread is going to start
|
||||||
|
|
||||||
if not stream.isStarted():
|
if not stream.isRunning():
|
||||||
stream.start()
|
stream.start()
|
||||||
|
|
||||||
stream.addCallback(self._callback)
|
stream.addCallback(self._callback)
|
||||||
@ -93,7 +93,7 @@ class Recording:
|
|||||||
self._running_cond.notify()
|
self._running_cond.notify()
|
||||||
|
|
||||||
def _callback(self, _type, data, aframe, vframe):
|
def _callback(self, _type, data, aframe, vframe):
|
||||||
if not self._stream.isStarted():
|
if not self._stream.isRunning():
|
||||||
self._running <<= False
|
self._running <<= False
|
||||||
with self._running_cond:
|
with self._running_cond:
|
||||||
self._running_cond.notify()
|
self._running_cond.notify()
|
||||||
|
300
lasp/lasp_slm.py
300
lasp/lasp_slm.py
@ -5,18 +5,10 @@ Sound level meter implementation
|
|||||||
@author: J.A. de Jong - ASCEE
|
@author: J.A. de Jong - ASCEE
|
||||||
"""
|
"""
|
||||||
from .wrappers import SPLowpass
|
from .wrappers import SPLowpass
|
||||||
from .lasp_computewidget import ComputeWidget
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from .lasp_config import zeros
|
from .lasp_common import (TimeWeighting, P_REF)
|
||||||
from .lasp_common import (FreqWeighting, calfile,
|
|
||||||
TimeWeighting, getTime, P_REF)
|
__all__ = ['SLM', 'Dummy']
|
||||||
from .lasp_weighcal import WeighCal
|
|
||||||
from .lasp_gui_tools import wait_cursor
|
|
||||||
from .lasp_figure import PlotOptions, Plotable
|
|
||||||
from .ui_slmwidget import Ui_SlmWidget
|
|
||||||
from .filter.bandpass_fir import OctaveBankDesigner, ThirdOctaveBankDesigner
|
|
||||||
from .lasp_octavefilter import OctaveFilterBank, ThirdOctaveFilterBank
|
|
||||||
__all__ = ['SLM', 'SlmWidget']
|
|
||||||
|
|
||||||
|
|
||||||
class Dummy:
|
class Dummy:
|
||||||
@ -103,289 +95,3 @@ class SLM:
|
|||||||
self._Lmax = curmax
|
self._Lmax = curmax
|
||||||
|
|
||||||
return Level
|
return Level
|
||||||
|
|
||||||
|
|
||||||
class SlmWidget(ComputeWidget, Ui_SlmWidget):
|
|
||||||
def __init__(self, parent=None):
|
|
||||||
"""
|
|
||||||
Initialize the SlmWidget.
|
|
||||||
"""
|
|
||||||
super().__init__(parent)
|
|
||||||
self.setupUi(self)
|
|
||||||
|
|
||||||
self.eqFreqBandChanged(0)
|
|
||||||
self.tFreqBandChanged(0)
|
|
||||||
self.setMeas(None)
|
|
||||||
|
|
||||||
def init(self, fm):
|
|
||||||
"""
|
|
||||||
Register combobox of the figure dialog to plot to in the FigureManager
|
|
||||||
"""
|
|
||||||
super().init(fm)
|
|
||||||
fm.registerCombo(self.tfigure)
|
|
||||||
fm.registerCombo(self.eqfigure)
|
|
||||||
|
|
||||||
self.tbandstart.setEnabled(False)
|
|
||||||
self.tbandstop.setEnabled(False)
|
|
||||||
|
|
||||||
def setMeas(self, meas):
|
|
||||||
"""
|
|
||||||
Set the current measurement for this widget.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
meas: if None, the Widget is disabled
|
|
||||||
"""
|
|
||||||
self.meas = meas
|
|
||||||
if meas is None:
|
|
||||||
self.setEnabled(False)
|
|
||||||
else:
|
|
||||||
self.setEnabled(True)
|
|
||||||
rt = meas.recTime
|
|
||||||
self.tstarttime.setRange(0, rt, 0)
|
|
||||||
self.tstoptime.setRange(0, rt, rt)
|
|
||||||
|
|
||||||
self.eqstarttime.setRange(0, rt, 0)
|
|
||||||
self.eqstoptime.setRange(0, rt, rt)
|
|
||||||
|
|
||||||
self.tchannel.clear()
|
|
||||||
self.eqchannel.clear()
|
|
||||||
for i in range(meas.nchannels):
|
|
||||||
self.tchannel.addItem(str(i))
|
|
||||||
self.eqchannel.addItem(str(i))
|
|
||||||
self.tchannel.setCurrentIndex(0)
|
|
||||||
self.eqchannel.setCurrentIndex(0)
|
|
||||||
|
|
||||||
def computeEq(self):
|
|
||||||
"""
|
|
||||||
Compute equivalent levels for a piece of time
|
|
||||||
"""
|
|
||||||
meas = self.meas
|
|
||||||
fs = meas.samplerate
|
|
||||||
channel = self.eqchannel.currentIndex()
|
|
||||||
fw = FreqWeighting.getCurrent(self.eqfreqweighting)
|
|
||||||
|
|
||||||
istart, istop = self.getStartStopIndices(meas, self.eqstarttime,
|
|
||||||
self.eqstoptime)
|
|
||||||
|
|
||||||
bands = self.eqfreqband.currentIndex()
|
|
||||||
if bands == 0:
|
|
||||||
# 1/3 Octave bands
|
|
||||||
filt = ThirdOctaveFilterBank(fs)
|
|
||||||
xs = filt.xs
|
|
||||||
xmin = xs[0] + self.eqbandstart.currentIndex()
|
|
||||||
xmax = xs[0] + self.eqbandstop.currentIndex()
|
|
||||||
if bands == 1:
|
|
||||||
# Octave bands
|
|
||||||
filt = OctaveFilterBank(fs)
|
|
||||||
xs = filt.xs
|
|
||||||
xmin = xs[0] + self.eqbandstart.currentIndex()
|
|
||||||
xmax = xs[0] + self.eqbandstop.currentIndex()
|
|
||||||
|
|
||||||
leveltype = self.eqleveltype.currentIndex()
|
|
||||||
if leveltype == 0:
|
|
||||||
# equivalent levels
|
|
||||||
tw = TimeWeighting.fast
|
|
||||||
elif leveltype == 1:
|
|
||||||
# fast time weighting
|
|
||||||
tw = TimeWeighting.fast
|
|
||||||
elif leveltype == 2:
|
|
||||||
# slow time weighting
|
|
||||||
tw = TimeWeighting.slow
|
|
||||||
|
|
||||||
with wait_cursor():
|
|
||||||
# This one exctracts the calfile and sensitivity from global
|
|
||||||
# variables defined at the top. # TODO: Change this to a more
|
|
||||||
# robust variant.
|
|
||||||
weighcal = WeighCal(fw, nchannels=1,
|
|
||||||
fs=fs, calfile=calfile)
|
|
||||||
praw = meas.praw()[istart:istop, [channel]]
|
|
||||||
|
|
||||||
weighted = weighcal.filter_(praw)
|
|
||||||
filtered_out = filt.filter_(weighted)
|
|
||||||
|
|
||||||
levels = np.empty((xmax - xmin + 1))
|
|
||||||
xlabels = []
|
|
||||||
for i, x in enumerate(range(xmin, xmax+1)):
|
|
||||||
nom = filt.nominal(x)
|
|
||||||
xlabels.append(nom)
|
|
||||||
filt_x = filtered_out[nom]['data']
|
|
||||||
slm = SLM(filt.fs, tw)
|
|
||||||
slm.addData(filt_x)
|
|
||||||
if leveltype > 0:
|
|
||||||
level = slm.Lmax
|
|
||||||
else:
|
|
||||||
level = slm.Leq
|
|
||||||
levels[i] = level
|
|
||||||
|
|
||||||
pto = PlotOptions.forLevelBars()
|
|
||||||
pta = Plotable(xlabels, levels)
|
|
||||||
fig, new = self.getFigure(self.eqfigure, pto, 'bar')
|
|
||||||
fig.fig.add(pta)
|
|
||||||
fig.show()
|
|
||||||
|
|
||||||
def computeT(self):
|
|
||||||
"""
|
|
||||||
Compute sound levels as a function of time.
|
|
||||||
"""
|
|
||||||
meas = self.meas
|
|
||||||
fs = meas.samplerate
|
|
||||||
channel = self.tchannel.currentIndex()
|
|
||||||
tw = TimeWeighting.getCurrent(self.ttimeweighting)
|
|
||||||
fw = FreqWeighting.getCurrent(self.tfreqweighting)
|
|
||||||
|
|
||||||
istart, istop = self.getStartStopIndices(meas, self.tstarttime,
|
|
||||||
self.tstoptime)
|
|
||||||
|
|
||||||
bands = self.tfreqband.currentIndex()
|
|
||||||
if bands == 0:
|
|
||||||
# Overall
|
|
||||||
filt = Dummy()
|
|
||||||
else:
|
|
||||||
# Octave bands
|
|
||||||
filt = OctaveFilterBank(
|
|
||||||
fs) if bands == 1 else ThirdOctaveFilterBank(fs)
|
|
||||||
xs = filt.xs
|
|
||||||
xmin = xs[0] + self.tbandstart.currentIndex()
|
|
||||||
xmax = xs[0] + self.tbandstop.currentIndex()
|
|
||||||
|
|
||||||
# Downsampling factor of result
|
|
||||||
dsf = self.tdownsampling.value()
|
|
||||||
|
|
||||||
with wait_cursor():
|
|
||||||
# This one exctracts the calfile and sensitivity from global
|
|
||||||
# variables defined at the top. # TODO: Change this to a more
|
|
||||||
# robust variant.
|
|
||||||
|
|
||||||
praw = meas.praw()[istart:istop, [channel]]
|
|
||||||
|
|
||||||
weighcal = WeighCal(fw, nchannels=1,
|
|
||||||
fs=fs, calfile=calfile)
|
|
||||||
|
|
||||||
weighted = weighcal.filter_(praw)
|
|
||||||
|
|
||||||
if bands == 0:
|
|
||||||
slm = SLM(fs, tw)
|
|
||||||
level = slm.addData(weighted)[::dsf]
|
|
||||||
|
|
||||||
# Filter, downsample data
|
|
||||||
N = level.shape[0]
|
|
||||||
time = getTime(float(fs)/dsf, N)
|
|
||||||
Lmax = slm.Lmax
|
|
||||||
|
|
||||||
pta = Plotable(time, level,
|
|
||||||
name=f'Overall level [dB([fw[0]])]')
|
|
||||||
pto = PlotOptions()
|
|
||||||
pto.ylabel = f'L{fw[0]} [dB({fw[0]})]'
|
|
||||||
pto.xlim = (time[0], time[-1])
|
|
||||||
fig, new = self.getFigure(self.tfigure, pto, 'line')
|
|
||||||
fig.fig.add(pta)
|
|
||||||
|
|
||||||
else:
|
|
||||||
pto = PlotOptions()
|
|
||||||
fig, new = self.getFigure(self.tfigure, pto, 'line')
|
|
||||||
pto.ylabel = f'L{fw[0]} [dB({fw[0]})]'
|
|
||||||
|
|
||||||
out = filt.filter_(weighted)
|
|
||||||
tmin = 0
|
|
||||||
tmax = 0
|
|
||||||
|
|
||||||
for x in range(xmin, xmax+1):
|
|
||||||
dec = np.prod(filt.decimation(x))
|
|
||||||
fd = filt.fs/dec
|
|
||||||
# Nominal frequency text
|
|
||||||
nom = filt.nominal(x)
|
|
||||||
|
|
||||||
leg = f'{nom} Hz - [dB({fw[0]})]'
|
|
||||||
|
|
||||||
# Find global tmin and tmax, used for xlim
|
|
||||||
time = out[nom]['t']
|
|
||||||
tmin = min(tmin, time[0])
|
|
||||||
tmax = max(tmax, time[-1])
|
|
||||||
slm = SLM(fd, tw)
|
|
||||||
level = slm.addData(out[nom]['data'])
|
|
||||||
plotable = Plotable(time[::dsf//dec],
|
|
||||||
level[::dsf//dec],
|
|
||||||
name=leg)
|
|
||||||
|
|
||||||
fig.fig.add(plotable)
|
|
||||||
pto.xlim = (tmin, tmax)
|
|
||||||
fig.fig.setPlotOptions(pto)
|
|
||||||
fig.show()
|
|
||||||
|
|
||||||
# stats = f"""Statistical results:
|
|
||||||
# =============================
|
|
||||||
# Applied frequency weighting: {fw[1]}
|
|
||||||
# Applied time weighting: {tw[1]}
|
|
||||||
# Applied Downsampling factor: {dsf}
|
|
||||||
# Maximum level (L{fw[0]} max): {Lmax:4.4} [dB({fw[0]})]
|
|
||||||
#
|
|
||||||
# """
|
|
||||||
# self.results.setPlainText(stats)
|
|
||||||
|
|
||||||
def compute(self):
|
|
||||||
"""
|
|
||||||
Compute Sound Level using settings. This method is
|
|
||||||
called whenever the Compute button is pushed in the SLM tab
|
|
||||||
"""
|
|
||||||
if self.ttab.isVisible():
|
|
||||||
self.computeT()
|
|
||||||
elif self.eqtab.isVisible():
|
|
||||||
self.computeEq()
|
|
||||||
|
|
||||||
def eqFreqBandChanged(self, idx):
|
|
||||||
"""
|
|
||||||
User changes frequency bands to plot time-dependent values for
|
|
||||||
"""
|
|
||||||
self.eqbandstart.clear()
|
|
||||||
self.eqbandstop.clear()
|
|
||||||
|
|
||||||
if idx == 1:
|
|
||||||
# 1/3 Octave bands
|
|
||||||
o = OctaveBankDesigner()
|
|
||||||
for x in o.xs:
|
|
||||||
nom = o.nominal(x)
|
|
||||||
self.eqbandstart.addItem(nom)
|
|
||||||
self.eqbandstop.addItem(nom)
|
|
||||||
self.eqbandstart.setCurrentIndex(0)
|
|
||||||
self.eqbandstop.setCurrentIndex(len(o.xs)-1)
|
|
||||||
elif idx == 0:
|
|
||||||
# Octave bands
|
|
||||||
o = ThirdOctaveBankDesigner()
|
|
||||||
for x in o.xs:
|
|
||||||
nom = o.nominal(x)
|
|
||||||
self.eqbandstart.addItem(nom)
|
|
||||||
self.eqbandstop.addItem(nom)
|
|
||||||
self.eqbandstart.setCurrentIndex(2)
|
|
||||||
self.eqbandstop.setCurrentIndex(len(o.xs) - 3)
|
|
||||||
|
|
||||||
def tFreqBandChanged(self, idx):
|
|
||||||
"""
|
|
||||||
User changes frequency bands to plot time-dependent values for
|
|
||||||
"""
|
|
||||||
self.tbandstart.clear()
|
|
||||||
self.tbandstop.clear()
|
|
||||||
enabled = False
|
|
||||||
|
|
||||||
if idx == 1:
|
|
||||||
# Octave bands
|
|
||||||
enabled = True
|
|
||||||
o = OctaveBankDesigner()
|
|
||||||
for x in o.xs:
|
|
||||||
nom = o.nominal(x)
|
|
||||||
self.tbandstart.addItem(nom)
|
|
||||||
self.tbandstop.addItem(nom)
|
|
||||||
self.tbandstart.setCurrentIndex(2)
|
|
||||||
self.tbandstop.setCurrentIndex(len(o.xs)-1)
|
|
||||||
elif idx == 2:
|
|
||||||
# Octave bands
|
|
||||||
enabled = True
|
|
||||||
o = ThirdOctaveBankDesigner()
|
|
||||||
for x in o.xs:
|
|
||||||
nom = o.nominal(x)
|
|
||||||
self.tbandstart.addItem(nom)
|
|
||||||
self.tbandstop.addItem(nom)
|
|
||||||
self.tbandstart.setCurrentIndex(2)
|
|
||||||
self.tbandstop.setCurrentIndex(len(o.xs) - 3)
|
|
||||||
|
|
||||||
self.tbandstart.setEnabled(enabled)
|
|
||||||
self.tbandstop.setEnabled(enabled)
|
|
||||||
|
@ -47,7 +47,8 @@ class BarScene(QGraphicsScene):
|
|||||||
ylabel=None,
|
ylabel=None,
|
||||||
title=None,
|
title=None,
|
||||||
colors=DEFAULT_COLORS, size=(1200, 600),
|
colors=DEFAULT_COLORS, size=(1200, 600),
|
||||||
legend=None):
|
legend=None,
|
||||||
|
legendpos=None):
|
||||||
"""
|
"""
|
||||||
Initialize a bar scene
|
Initialize a bar scene
|
||||||
|
|
||||||
@ -61,6 +62,7 @@ class BarScene(QGraphicsScene):
|
|||||||
colors: color cycler
|
colors: color cycler
|
||||||
size: size of the plot in pixels
|
size: size of the plot in pixels
|
||||||
legend: list of legend strings to show.
|
legend: list of legend strings to show.
|
||||||
|
legendpos: position of legend w.r.t. default position, in pixels
|
||||||
"""
|
"""
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
self.setSceneRect(QRect(0,0,*size))
|
self.setSceneRect(QRect(0,0,*size))
|
||||||
@ -171,8 +173,11 @@ class BarScene(QGraphicsScene):
|
|||||||
|
|
||||||
if legend is not None:
|
if legend is not None:
|
||||||
maxlegtxtwidth = 0
|
maxlegtxtwidth = 0
|
||||||
legpos = (xsize-rightoffset-300,
|
legposx = 0 if legendpos is None else legendpos[0]
|
||||||
ysize-topoffset-30)
|
legposy = 0 if legendpos is None else legendpos[1]
|
||||||
|
|
||||||
|
legpos = (xsize-rightoffset-300+legposx,
|
||||||
|
ysize-topoffset-30+legposy)
|
||||||
|
|
||||||
dyleg = 15
|
dyleg = 15
|
||||||
dylegtxt = dyleg
|
dylegtxt = dyleg
|
||||||
|
@ -1,22 +1,37 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
import sys
|
import sys
|
||||||
|
import argparse
|
||||||
from lasp.lasp_rtapsdialog import RealTimeAPSDialog
|
from lasp.lasp_rtapsdialog import RealTimeAPSDialog
|
||||||
from lasp.lasp_avstream import AvStream
|
from lasp.lasp_avstream import AvStream
|
||||||
from lasp.device.lasp_daqconfig import default_soundcard, roga_plugndaq
|
from lasp.device.lasp_daqconfig import default_soundcard, roga_plugndaq, umik
|
||||||
from lasp.lasp_gui_tools import Branding, ASCEEColors, warningdialog
|
from lasp.lasp_gui_tools import Branding, warningdialog
|
||||||
from PySide import QtGui
|
from PySide import QtGui
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description='Run real time power spectra monitor')
|
||||||
|
device_help = 'Device to record from'
|
||||||
|
parser.add_argument('-d', '--device', help=device_help, type=str,
|
||||||
|
choices=['roga', 'umik', 'default'], default='roga')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
device_str = args.device
|
||||||
|
if 'roga' == device_str:
|
||||||
|
device = roga_plugndaq
|
||||||
|
elif 'default' == device_str:
|
||||||
|
device = default_soundcard
|
||||||
|
elif 'umik' == device_str:
|
||||||
|
device = umik
|
||||||
|
|
||||||
app = QtGui.QApplication(sys.argv) # A new instance of QApplication
|
app = QtGui.QApplication(sys.argv) # A new instance of QApplication
|
||||||
app.setFont(Branding.font())
|
app.setFont(Branding.font())
|
||||||
|
|
||||||
stream = AvStream(default_soundcard)
|
# stream = AvStream(default_soundcard)
|
||||||
# stream = AvStream(roga_plugndaq)
|
stream = AvStream(device)
|
||||||
mw = RealTimeAPSDialog(None, stream)
|
mw = RealTimeAPSDialog(None, stream)
|
||||||
|
|
||||||
mw.show() # Show the form
|
|
||||||
|
|
||||||
# Install exception hook to catch exceptions
|
# Install exception hook to catch exceptions
|
||||||
def excepthook(cls, exception, traceback):
|
def excepthook(cls, exception, traceback):
|
||||||
"""
|
"""
|
||||||
@ -33,7 +48,8 @@ def main():
|
|||||||
# Set custom exception hook that catches all exceptions
|
# Set custom exception hook that catches all exceptions
|
||||||
sys.excepthook = excepthook
|
sys.excepthook = excepthook
|
||||||
stream.start()
|
stream.start()
|
||||||
app.exec_() # and execute the app
|
mw.show() # Show the window
|
||||||
|
app.exec_() # and start the event loop
|
||||||
stream.stop()
|
stream.stop()
|
||||||
|
|
||||||
|
|
||||||
|
58
scripts/lasp_calibrate.py
Executable file
58
scripts/lasp_calibrate.py
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Created on Tue Aug 14 12:49:27 2018
|
||||||
|
|
||||||
|
@author: J.A. de Jong - ASCEE
|
||||||
|
|
||||||
|
Description: calibrate device using measurement
|
||||||
|
|
||||||
|
"""
|
||||||
|
import numpy as np
|
||||||
|
import argparse
|
||||||
|
from lasp.lasp_measurement import Measurement
|
||||||
|
from lasp.lasp_common import P_REF
|
||||||
|
import os
|
||||||
|
|
||||||
|
spl_default = 94.
|
||||||
|
gain_default = 0.
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser('Calibrate device using'
|
||||||
|
' calibration measurement')
|
||||||
|
|
||||||
|
parser.add_argument('--gain-setting','-g',
|
||||||
|
help='DAQ Input gain setting during calibration in [dB]' +
|
||||||
|
f' default = {gain_default} dB.',
|
||||||
|
type=float, default=gain_default)
|
||||||
|
|
||||||
|
parser.add_argument('fn',help='File name of calibration measurement', type=str)
|
||||||
|
|
||||||
|
parser.add_argument('--channel',help='Channel of the device to calibrate, default = 0',
|
||||||
|
type=int, default=0)
|
||||||
|
|
||||||
|
parser.add_argument('--spl','-s',help='Applied sound pressure level to the'
|
||||||
|
f' microphone in dB, default = {spl_default}',
|
||||||
|
default=spl_default)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
m = Measurement(args.fn)
|
||||||
|
nchannels = m.nchannels
|
||||||
|
|
||||||
|
# Reset measurement sensitivity, in case it was set wrongly
|
||||||
|
m.sensitivity = np.ones(nchannels)
|
||||||
|
|
||||||
|
# Compute Vrms
|
||||||
|
Vrms = m.prms * 10**(args.gain_setting/20.)
|
||||||
|
|
||||||
|
prms = P_REF*10**(args.spl/20)
|
||||||
|
|
||||||
|
sens = Vrms / prms
|
||||||
|
|
||||||
|
print(f'Computed sensitivity: {sens[args.channel]:.5} V/Pa')
|
||||||
|
print('Searching for files in directory to apply sensitivity value to...')
|
||||||
|
dir_ = os.path.dirname(args.fn)
|
||||||
|
for f in os.listdir(dir_):
|
||||||
|
yn = input(f'Apply sensitivity to {f}? [Y/n]')
|
||||||
|
if yn in ['','Y','y']:
|
||||||
|
meas = Measurement(os.path.join(dir_,f))
|
||||||
|
meas.sensitivity = sens
|
@ -2,7 +2,7 @@
|
|||||||
import argparse
|
import argparse
|
||||||
from lasp.lasp_record import Recording
|
from lasp.lasp_record import Recording
|
||||||
from lasp.lasp_avstream import AvStream
|
from lasp.lasp_avstream import AvStream
|
||||||
|
from lasp.device.lasp_daqconfig import default_soundcard, roga_plugndaq, umik
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description='Acquire data and store a measurement file'
|
description='Acquire data and store a measurement file'
|
||||||
)
|
)
|
||||||
@ -13,9 +13,22 @@ parser.add_argument('--duration', '-d', type=float,
|
|||||||
help='The recording duration in [s]')
|
help='The recording duration in [s]')
|
||||||
parser.add_argument('--comment', '-c', type=str,
|
parser.add_argument('--comment', '-c', type=str,
|
||||||
help='Add a measurement comment, optionally')
|
help='Add a measurement comment, optionally')
|
||||||
|
|
||||||
|
device_help = 'DAQ Device to record from'
|
||||||
|
parser.add_argument('--input-daq','-i', help=device_help, type=str,
|
||||||
|
choices=['roga', 'umik', 'default'], default='roga')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
stream = AvStream()
|
device_str = args.input_daq
|
||||||
|
if 'roga' == device_str:
|
||||||
|
device = roga_plugndaq
|
||||||
|
elif 'default' == device_str:
|
||||||
|
device = default_soundcard
|
||||||
|
elif 'umik' == device_str:
|
||||||
|
device = umik
|
||||||
|
|
||||||
|
stream = AvStream(device)
|
||||||
rec = Recording(args.filename, stream, args.duration)
|
rec = Recording(args.filename, stream, args.duration)
|
||||||
rec.start()
|
rec.start()
|
||||||
stream.stop()
|
stream.stop()
|
||||||
|
Loading…
Reference in New Issue
Block a user