Compare commits

..

1 Commits

Author SHA1 Message Date
5a051d21a1 Measurement.fromnpy(): accept sensitivity as scalar or 0-dim numpy.ndarray
All checks were successful
Building, testing and releasing LASP if it has a tag / Build-Test-Ubuntu (push) Successful in -3m20s
Building, testing and releasing LASP if it has a tag / Release-Ubuntu (push) Has been skipped
2024-09-10 13:40:47 +02:00
13 changed files with 44 additions and 60 deletions

View File

@ -2,7 +2,7 @@
include_directories(uldaq) include_directories(uldaq)
include_directories(portaudio) include_directories(portaudio)
add_library(lasp_device_lib OBJECT add_library(lasp_device_lib OBJECT
lasp_daq.cpp lasp_daq.cpp
lasp_daqconfig.cpp lasp_daqconfig.cpp
lasp_daqdata.cpp lasp_daqdata.cpp
@ -10,8 +10,12 @@ add_library(lasp_device_lib OBJECT
lasp_rtaudiodaq.cpp lasp_rtaudiodaq.cpp
lasp_streammgr.cpp lasp_streammgr.cpp
lasp_indatahandler.cpp lasp_indatahandler.cpp
lasp_uldaq.cpp
uldaq/lasp_uldaq_impl.cpp
uldaq/lasp_uldaq_bufhandler.cpp
uldaq/lasp_uldaq_common.cpp
portaudio/lasp_portaudiodaq.cpp portaudio/lasp_portaudiodaq.cpp
) )
# Callback requires certain arguments that are not used by code. This disables # Callback requires certain arguments that are not used by code. This disables
# a compiler warning about it. # a compiler warning about it.
@ -24,9 +28,7 @@ target_include_directories(lasp_device_lib INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}) ${CMAKE_CURRENT_SOURCE_DIR})
if(LASP_HAS_ULDAQ) if(LASP_HAS_ULDAQ)
add_subdirectory(uldaq) target_link_libraries(lasp_device_lib uldaq)
target_include_directories(lasp_device_lib INTERFACE uldaq)
target_link_libraries(lasp_device_lib uldaq_backend uldaq)
endif() endif()
if(LASP_HAS_RTAUDIO) if(LASP_HAS_RTAUDIO)
target_link_libraries(lasp_device_lib rtaudio) target_link_libraries(lasp_device_lib rtaudio)

View File

@ -1,6 +0,0 @@
add_library(uldaq_backend lasp_uldaq.cpp lasp_uldaq_bufhandler.cpp lasp_uldaq_common.cpp lasp_uldaq_impl.cpp)
target_include_directories(uldaq_backend PUBLIC ../)
target_include_directories(uldaq_backend PUBLIC ../../)
target_include_directories(uldaq_backend PUBLIC ../../dsp)
target_include_directories(uldaq_backend INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

View File

@ -3,8 +3,8 @@
#include "lasp_config.h" #include "lasp_config.h"
#if LASP_HAS_ULDAQ == 1 #if LASP_HAS_ULDAQ == 1
#include "lasp_daq.h"
#include "lasp_uldaq_common.h" #include "lasp_uldaq_common.h"
#include "lasp_daq.h"
string getErrMsg(UlError err) { string getErrMsg(UlError err) {
string errstr; string errstr;
@ -21,9 +21,11 @@ void showErr(string errstr) {
std::cerr << "***********************************************\n\n"; std::cerr << "***********************************************\n\n";
} }
void showErr(UlError err) { void showErr(UlError err) {
if (err != ERR_NO_ERROR) showErr(getErrMsg(err)); if (err != ERR_NO_ERROR)
showErr(getErrMsg(err));
} }
void throwOnPossibleUlException(UlError err) { void throwOnPossibleUlException(UlError err) {
if (err == ERR_NO_ERROR) { if (err == ERR_NO_ERROR) {
return; return;

View File

@ -10,11 +10,11 @@ from .lasp_cpp import *
# from .lasp_imptube import * # TwoMicImpedanceTube # from .lasp_imptube import * # TwoMicImpedanceTube
from .lasp_measurement import * # Measurement, scaleBlockSens from .lasp_measurement import * # Measurement, scaleBlockSens
from .lasp_octavefilter import * from .lasp_octavefilter import * # OverallFilterBank, SosOctaveFilterBank, SosThirdOctaveFilterBank
from .lasp_slm import * # SLM, Dummy from .lasp_slm import * # SLM, Dummy
from .lasp_record import * # RecordStatus, Recording from .lasp_record import * # RecordStatus, Recording
from .lasp_daqconfigs import * from .lasp_daqconfigs import * # DaqConfigurations
from .lasp_measurementset import * from .lasp_measurementset import * # MeasurementSet
# from .lasp_siggen import * # SignalType, NoiseType, SiggenMessage, SiggenData, Siggen # from .lasp_siggen import * # SignalType, NoiseType, SiggenMessage, SiggenData, Siggen
# from .lasp_weighcal import * # WeighCal # from .lasp_weighcal import * # WeighCal

View File

@ -15,7 +15,6 @@ import warnings
import numpy as np import numpy as np
# For designing second-order sections # For designing second-order sections
from scipy.signal import butter from scipy.signal import butter
from ..lasp_config import LASP_NUMPY_FLOAT_TYPE
from .fir_design import bandpass_fir_design from .fir_design import bandpass_fir_design
from .fir_design import freqResponse as firFreqResponse from .fir_design import freqResponse as firFreqResponse
@ -255,9 +254,9 @@ class FilterBankDesigner:
fuu = self.fu(xu) fuu = self.fu(xu)
if scale == 'lin': if scale == 'lin':
freq = np.linspace(fll, fuu, npoints, dtype=LASP_NUMPY_FLOAT_TYPE) freq = np.linspace(fll, fuu, npoints)
elif scale == 'log': elif scale == 'log':
freq = np.logspace(np.log10(fll), np.log10(fuu), npoints, dtype=LASP_NUMPY_FLOAT_TYPE) freq = np.logspace(np.log10(fll), np.log10(fuu), npoints)
else: else:
raise ValueError(f'Invalid scale parameter: {scale}') raise ValueError(f'Invalid scale parameter: {scale}')

View File

@ -7,7 +7,6 @@ from dataclasses import dataclass
from dataclasses_json import dataclass_json from dataclasses_json import dataclass_json
from enum import Enum, unique, auto from enum import Enum, unique, auto
from .lasp_cpp import DaqChannel from .lasp_cpp import DaqChannel
from .lasp_config import LASP_NUMPY_FLOAT_TYPE
""" """
Common definitions used throughout the code. Common definitions used throughout the code.
@ -396,9 +395,7 @@ def getTime(fs, N, start=0):
start: Optional start ofset in number of samples start: Optional start ofset in number of samples
""" """
assert N > 0 and fs > 0 assert N > 0 and fs > 0
return np.linspace( return np.linspace(start, start + N/fs, N, endpoint=False)
start, start + N / fs, N, endpoint=False, dtype=LASP_NUMPY_FLOAT_TYPE
)
def getFreq(fs, nfft): def getFreq(fs, nfft):
@ -409,6 +406,6 @@ def getFreq(fs, nfft):
fs: Sampling frequency [Hz] fs: Sampling frequency [Hz]
nfft: Fft length (int) nfft: Fft length (int)
""" """
df = fs / nfft # frequency resolution df = fs/nfft # frequency resolution
K = nfft // 2 + 1 # number of frequency bins K = nfft//2+1 # number of frequency bins
return np.linspace(0, (K - 1) * df, K, dtype=LASP_NUMPY_FLOAT_TYPE) return np.linspace(0, (K-1)*df, K)

View File

@ -5,12 +5,9 @@ Author: J.A. de Jong - ASCEE
Description: LASP configuration Description: LASP configuration
""" """
import numpy as np import numpy as np
from .lasp_cpp import LASP_DOUBLE_PRECISION from .lasp_cpp import LASP_DOUBLE_PRECISION
__all__ = ["zeros", "ones", "empty", "LASP_NUMPY_FLOAT_TYPE", "LASP_NUMPY_COMPLEX_TYPE"]
if LASP_DOUBLE_PRECISION: if LASP_DOUBLE_PRECISION:
LASP_NUMPY_FLOAT_TYPE = np.float64 LASP_NUMPY_FLOAT_TYPE = np.float64
LASP_NUMPY_COMPLEX_TYPE = np.complex128 LASP_NUMPY_COMPLEX_TYPE = np.complex128
@ -19,28 +16,28 @@ else:
LASP_NUMPY_COMPLEX_TYPE = np.float64 LASP_NUMPY_COMPLEX_TYPE = np.float64
def zeros(shape, dtype=float, order="F"): def zeros(shape, dtype=float, order='F'):
if dtype is float: if dtype == float:
return np.zeros(shape, dtype=LASP_NUMPY_FLOAT_TYPE, order=order) return np.zeros(shape, dtype=LASP_NUMPY_FLOAT_TYPE, order=order)
elif dtype is complex: elif dtype == complex:
return np.zeros(shape, dtype=LASP_NUMPY_COMPLEX_TYPE, order=order) return np.zeros(shape, dtype=LASP_NUMPY_COMPLEX_TYPE, order=order)
else: else:
raise RuntimeError(f"Unknown dtype: {dtype}") raise RuntimeError(f"Unknown dtype: {dtype}")
def ones(shape, dtype=float, order="F"): def ones(shape, dtype=float, order='F'):
if dtype is float: if dtype == float:
return np.ones(shape, dtype=LASP_NUMPY_FLOAT_TYPE, order=order) return np.ones(shape, dtype=LASP_NUMPY_FLOAT_TYPE, order=order)
elif dtype is complex: elif dtype == complex:
return np.ones(shape, dtype=LASP_NUMPY_COMPLEX_TYPE, order=order) return np.ones(shape, dtype=LASP_NUMPY_COMPLEX_TYPE, order=order)
else: else:
raise RuntimeError(f"Unknown dtype: {dtype}") raise RuntimeError(f"Unknown dtype: {dtype}")
def empty(shape, dtype=float, order='F'):
def empty(shape, dtype=float, order="F"): if dtype == float:
if dtype is float:
return np.empty(shape, dtype=LASP_NUMPY_FLOAT_TYPE, order=order) return np.empty(shape, dtype=LASP_NUMPY_FLOAT_TYPE, order=order)
elif dtype is complex: elif dtype == complex:
return np.empty(shape, dtype=LASP_NUMPY_COMPLEX_TYPE, order=order) return np.empty(shape, dtype=LASP_NUMPY_COMPLEX_TYPE, order=order)
else: else:
raise RuntimeError(f"Unknown dtype: {dtype}") raise RuntimeError(f"Unknown dtype: {dtype}")

View File

@ -77,9 +77,9 @@ class MeasurementType(Enum):
Measurement flags related to the measurement. Stored as bit flags in the measurement file. This is for possible changes in the API later. Measurement flags related to the measurement. Stored as bit flags in the measurement file. This is for possible changes in the API later.
""" """
# Not specific measurement type # Not specific measurement type
NotSpecific = 0 NotSpecific = 0
# Measurement serves as an insertion loss reference measurement # Measurement serves as an insertion loss reference measurement
ILReference = 1 << 0 ILReference = 1 << 0
@ -1156,11 +1156,8 @@ class Measurement:
if data.ndim != 2: if data.ndim != 2:
data = data[:, np.newaxis] data = data[:, np.newaxis]
try: if not (isinstance(sensitivity, np.ndarray) and sensitivity.ndim >= 1):
len(sensitivity) sensitivity = np.asarray(sensitivity)[np.newaxis]
except:
raise ValueError("Sensitivity should be given as array-like data type")
sensitivity = np.asarray(sensitivity)
nchannels = data.shape[1] nchannels = data.shape[1]
if nchannels != sensitivity.shape[0]: if nchannels != sensitivity.shape[0]:

View File

@ -11,7 +11,6 @@ __all__ = ["OverallFilterBank", "SosOctaveFilterBank", "SosThirdOctaveFilterBank
from .filter.filterbank_design import OctaveBankDesigner, ThirdOctaveBankDesigner from .filter.filterbank_design import OctaveBankDesigner, ThirdOctaveBankDesigner
from .lasp_cpp import BiquadBank from .lasp_cpp import BiquadBank
from .lasp_config import empty, LASP_NUMPY_FLOAT_TYPE
import numpy as np import numpy as np
@ -47,7 +46,7 @@ class OverallFilterBank:
Ncur = data.shape[0] Ncur = data.shape[0]
tend = tstart + Ncur / self.fs tend = tstart + Ncur / self.fs
t = np.linspace(tstart, tend, Ncur, endpoint=False, dtype=LASP_NUMPY_FLOAT_TYPE) t = np.linspace(tstart, tend, Ncur, endpoint=False)
self.N += Ncur self.N += Ncur
output["Overall"] = {"t": t, "data": data, "x": 0} output["Overall"] = {"t": t, "data": data, "x": 0}
@ -115,7 +114,7 @@ class SosFilterBank:
Ncur = data.shape[0] Ncur = data.shape[0]
tend = tstart + Ncur / self.fs tend = tstart + Ncur / self.fs
t = np.linspace(tstart, tend, Ncur, endpoint=False, dtype=LASP_NUMPY_FLOAT_TYPE) t = np.linspace(tstart, tend, Ncur, endpoint=False)
self.N += Ncur self.N += Ncur
for i, x in enumerate(self.xs): for i, x in enumerate(self.xs):

View File

@ -4,15 +4,14 @@
Sound level meter implementation Sound level meter implementation
@author: J.A. de Jong - ASCEE @author: J.A. de Jong - ASCEE
""" """
from .lasp_cpp import cppSLM from .lasp_cpp import cppSLM
from .lasp_config import empty, LASP_NUMPY_FLOAT_TYPE from .lasp_config import empty
import numpy as np import numpy as np
from .lasp_common import TimeWeighting, FreqWeighting, P_REF from .lasp_common import (TimeWeighting, FreqWeighting, P_REF)
from .filter import SPLFilterDesigner from .filter import SPLFilterDesigner
import logging import logging
__all__ = ["SLM", "Dummy"] __all__ = ['SLM', 'Dummy']
class Dummy: class Dummy:
@ -90,24 +89,24 @@ class SLM:
elif fw == FreqWeighting.Z: elif fw == FreqWeighting.Z:
prefilter = None prefilter = None
else: else:
raise ValueError(f"Not implemented prefilter {fw}") raise ValueError(f'Not implemented prefilter {fw}')
# 'Probe' size of filter coefficients # 'Probe' size of filter coefficients
self.nom_txt = [] self.nom_txt = []
# This is a bit of a hack, as the 5 is hard-encoded here, but should in # This is a bit of a hack, as the 5 is hard-encoded here, but should in
# fact be coming from somewhere else.. # fact be coming from somewhere else..
sos_overall = np.array([1, 0, 0, 1, 0, 0] * 5, dtype=float) sos_overall = np.array([1, 0, 0, 1, 0, 0]*5, dtype=float)
if fbdesigner is not None: if fbdesigner is not None:
assert fbdesigner.fs == fs assert fbdesigner.fs == fs
sos_firstx = fbdesigner.createSOSFilter(self.xs[0]).flatten() sos_firstx = fbdesigner.createSOSFilter(self.xs[0]).flatten()
self.nom_txt.append(fbdesigner.nominal_txt(self.xs[0])) self.nom_txt.append(fbdesigner.nominal_txt(self.xs[0]))
sos = empty((sos_firstx.size, nfilters), dtype=float, order="C") sos = empty((sos_firstx.size, nfilters), dtype=float, order='C')
sos[:, 0] = sos_firstx sos[:, 0] = sos_firstx
for i, x in enumerate(self.xs[1:]): for i, x in enumerate(self.xs[1:]):
sos[:, i + 1] = fbdesigner.createSOSFilter(x).flatten() sos[:, i+1] = fbdesigner.createSOSFilter(x).flatten()
self.nom_txt.append(fbdesigner.nominal_txt(x)) self.nom_txt.append(fbdesigner.nominal_txt(x))
if include_overall: if include_overall:

View File

@ -7,7 +7,6 @@ Weighting and calibration filter in one
from .lasp_common import FreqWeighting from .lasp_common import FreqWeighting
from .filter import SPLFilterDesigner from .filter import SPLFilterDesigner
from lasp.lasp_config import ones, empty from lasp.lasp_config import ones, empty
from ..lasp_config import LASP_NUMPY_FLOAT_TYPE
from .wrappers import FilterBank from .wrappers import FilterBank
import numpy as np import numpy as np
@ -40,7 +39,7 @@ class WeighCal:
self.calfile = calfile self.calfile = calfile
# Frequencies used for the filter design # Frequencies used for the filter design
freq_design = np.linspace(0, 17e3, 3000, dtype=LASP_NUMPY_FLOAT_TYPE) freq_design = np.linspace(0, 17e3, 3000)
freq_design[-1] = fs/2 freq_design[-1] = fs/2
# Objective function for the frequency response # Objective function for the frequency response
@ -141,7 +140,6 @@ class WeighCal:
""" """
Returns the frequency response of the designed FIR filter Returns the frequency response of the designed FIR filter
""" """
raise RuntimeError('This code bugs. TODO: Re-implement?')
if freq is None: if freq is None:
freq = np.logspace(1, np.log10(self.fs/2), 500) freq = np.logspace(1, np.log10(self.fs/2), 500)
return (freq, frp(self.fs, freq, self._firs[chan]), return (freq, frp(self.fs, freq, self._firs[chan]),