Compare commits

...

3 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
6b0442fe90 Version bump 1.6.8
All checks were successful
Building, testing and releasing LASP if it has a tag / Build-Test-Ubuntu (push) Successful in -1m5s
Building, testing and releasing LASP if it has a tag / Release-Ubuntu (push) Successful in -5m36s
2024-07-02 10:57:16 +02:00
e542f805e9 Removed old unused Fir filterbank code. 2024-07-02 10:56:42 +02:00
6 changed files with 16 additions and 182 deletions

View File

@ -4,6 +4,7 @@ project(LASP LANGUAGES C CXX VERSION 1.6.3)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED) set(CMAKE_CXX_STANDARD_REQUIRED)
# Experimental: support for Raspberry Pi (64-bit architectures)
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64") if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
set(RPI TRUE) set(RPI TRUE)
else() else()
@ -55,7 +56,6 @@ cmake_policy(SET CMP0079 NEW)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
include_directories(/usr/include/python3.8)
include("BuildType") include("BuildType")
include("QueryPythonForPybind11") include("QueryPythonForPybind11")

View File

@ -60,4 +60,4 @@ if(DEFINED PY_BUILD_CMAKE_MODULE_NAME)
COMPONENT python_modules COMPONENT python_modules
DESTINATION ${PY_BUILD_CMAKE_MODULE_NAME}) DESTINATION ${PY_BUILD_CMAKE_MODULE_NAME})
endif() endif()

View File

@ -5,7 +5,7 @@ requires-python = ">=3.10"
description = "Library for Acoustic Signal Processing" description = "Library for Acoustic Signal Processing"
license = { "file" = "LICENSE" } license = { "file" = "LICENSE" }
authors = [{ "name" = "J.A. de Jong", "email" = "j.a.dejong@ascee.nl" }] authors = [{ "name" = "J.A. de Jong", "email" = "j.a.dejong@ascee.nl" }]
version = "1.6.7" version = "1.6.8"
keywords = ["DSP", "DAQ", "Signal processing"] keywords = ["DSP", "DAQ", "Signal processing"]

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

@ -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

@ -6,12 +6,10 @@ Author: J.A. de Jong - ASCEE
Provides the implementations of (fractional) octave filter banks Provides the implementations of (fractional) octave filter banks
""" """
__all__ = ['FirOctaveFilterBank', 'FirThirdOctaveFilterBank',
'OverallFilterBank', 'SosOctaveFilterBank',
'SosThirdOctaveFilterBank']
from .filter.filterbank_design import (OctaveBankDesigner, __all__ = ["OverallFilterBank", "SosOctaveFilterBank", "SosThirdOctaveFilterBank"]
ThirdOctaveBankDesigner)
from .filter.filterbank_design import OctaveBankDesigner, ThirdOctaveBankDesigner
from .lasp_cpp import BiquadBank from .lasp_cpp import BiquadBank
import numpy as np import numpy as np
@ -19,7 +17,7 @@ import numpy as np
class OverallFilterBank: class OverallFilterBank:
""" """
Dummy type filter bank. Does nothing special, only returns output in a Dummy type filter bank. Does nothing special, only returns output in a
sensible way way compatible with SosFilterBank.
""" """
def __init__(self, fs): def __init__(self, fs):
@ -51,174 +49,13 @@ class OverallFilterBank:
t = np.linspace(tstart, tend, Ncur, endpoint=False) 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}
return output return output
def decimation(self, x): def decimation(self, x):
return [1] return [1]
class FirFilterBank:
"""
Single channel (fractional) octave filter bank implementation, based on FIR
filters and sample rate decimation.
"""
def __init__(self, fs, xmin, xmax):
"""
Initialize a OctaveFilterBank object.
Args:
fs: Sampling frequency of base signal
"""
assert np.isclose(fs, 48000), "Only sampling frequency" \
" available is 48 kHz"
self.fs = fs
self.xs = list(range(xmin, xmax + 1))
raise RuntimeError('Not working code anymore')
maxdecimation = self.designer.firDecimation(self.xs[0])
self.decimators = []
for dec in maxdecimation:
self.decimators.append(Decimator(1, dec))
xs_d1 = []
xs_d4 = []
xs_d16 = []
xs_d64 = []
xs_d256 = []
self.filterbanks = []
# Sort the x values in categories according to the required decimation
for x in self.xs:
dec = self.designer.firDecimation(x)
if len(dec) == 1 and dec[0] == 1:
xs_d1.append(x)
elif len(dec) == 1 and dec[0] == 4:
xs_d4.append(x)
elif len(dec) == 2:
xs_d16.append(x)
elif len(dec) == 3:
xs_d64.append(x)
elif len(dec) == 4:
xs_d256.append(x)
else:
raise ValueError(f'No decimation found for x={x}')
xs_all = [xs_d1, xs_d4, xs_d16, xs_d64, xs_d256]
for xs in xs_all:
nominals_txt = []
if len(xs) > 0:
firs = np.empty((self.designer.firFilterLength, len(xs)), order='F')
for i, x in enumerate(xs):
# These are the filters that do not require lasp_decimation
# prior to filtering
nominals_txt.append(self.designer.nominal_txt(x))
firs[:, i] = self.designer.createFirFilter(x)
filterbank = {'fb': pyxFilterBank(firs, 1024),
'xs': xs,
'nominals': nominals_txt}
self.filterbanks.append(filterbank)
# Sample input counter.
self.N = 0
self.dec = [1, 4, 16, 64, 256]
# Filter output counters
# These intial delays are found 'experimentally' using a toneburst
# response.
self.Nf = [915, 806, 780, 582, 338]
def filterd(self, dec_stage, data):
"""
Filter data for a given decimation stage
Args:
dec_stage: decimation stage
data: Pre-filtered data
"""
output = {}
if data.shape[0] == 0:
return output
filtered = self.filterbanks[dec_stage]['fb'].filter_(data)
Nf = filtered.shape[0]
if Nf > 0:
dec = self.dec[dec_stage]
fd = self.fs/dec
oldNf = self.Nf[dec_stage]
tstart = oldNf/fd
tend = tstart + Nf/fd
t = np.linspace(tstart, tend, Nf, endpoint=False)
self.Nf[dec_stage] += Nf
for i, nom_txt in enumerate(self.filterbanks[dec_stage]['nominals']):
x = self.designer.nominal_txt_tox(nom_txt)
output[nom_txt] = {'t': t, 'data': filtered[:, [i]], 'x': x}
return output
def filter_(self, data):
"""
Filter input data
"""
assert data.ndim == 2
assert data.shape[1] == 1, "invalid number of channels, should be 1"
if data.shape[0] == 0:
return {}
# Output given as a dictionary with x as the key
output = {}
output_unsorted = {}
self.N += data.shape[0]
output_unsorted = {**output_unsorted, **self.filterd(0, data)}
for i in range(len(self.decimators)):
dec_stage = i+1
if data.shape[0] > 0:
# Apply a decimation stage
data = self.decimators[i].decimate(data)
output_unsorted = {**output_unsorted,
**self.filterd(dec_stage, data)}
# Create sorted output
for x in self.xs:
nom_txt = self.designer.nominal_txt(x)
output[nom_txt] = output_unsorted[nom_txt]
return output
def decimation(self, x):
return self.designer.firDecimation(x)
class FirOctaveFilterBank(FirFilterBank):
"""
Filter bank which uses FIR filtering for each octave frequency band
"""
def __init__(self, fs, xmin, xmax):
self.designer = OctaveBankDesigner(fs)
FirFilterBank.__init__(self, fs, xmin, xmax)
class FirThirdOctaveFilterBank(FirFilterBank):
"""
Filter bank which uses FIR filtering for each one-third octave frequency
band.
"""
def __init__(self, fs, xmin, xmax):
self.designer = ThirdOctaveBankDesigner(fs)
FirFilterBank.__init__(self, fs, xmin, xmax)
class SosFilterBank: class SosFilterBank:
def __init__(self, fs, xmin, xmax): def __init__(self, fs, xmin, xmax):
""" """
@ -247,7 +84,7 @@ class SosFilterBank:
channel = self.designer.createSOSFilter(x) channel = self.designer.createSOSFilter(x)
if sos is None: if sos is None:
sos = empty((channel.size, len(self.xs))) sos = empty((channel.size, len(self.xs)))
sos[:, i] = channel.flatten() sos[:, i] = channel.flatten()
self._fb = BiquadBank(sos) self._fb = BiquadBank(sos)