From 8fafac20506a75a32e5ef2ac282c0ee97fb505e5 Mon Sep 17 00:00:00 2001 From: "J.A. de Jong - Redu-Sone B.V., ASCEE V.O.F" Date: Thu, 28 May 2020 21:26:30 +0200 Subject: [PATCH] First work on getting units in metadata --- lasp/lasp_common.py | 89 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 12 deletions(-) diff --git a/lasp/lasp_common.py b/lasp/lasp_common.py index 60e856b..1933a55 100644 --- a/lasp/lasp_common.py +++ b/lasp/lasp_common.py @@ -8,6 +8,7 @@ import appdirs import numpy as np from .wrappers import Window as wWindow +from collections import namedtuple """ Common definitions used throughout the code. @@ -15,9 +16,77 @@ Common definitions used throughout the code. __all__ = [ 'P_REF', 'FreqWeighting', 'TimeWeighting', 'getTime', 'getFreq', - 'lasp_shelve', 'this_lasp_shelve', 'W_REF', 'U_REF', 'I_REF' + 'lasp_shelve', 'this_lasp_shelve', 'W_REF', 'U_REF', 'I_REF', 'dBFS_REF', + 'SIUnits' ] +# Reference sound pressure level +P_REF = 2e-5 # 20 micropascal + +W_REF = 1e-12 # 1 picoWatt +I_REF = 1e-12 # 1 picoWatt/ m^2 + +# Reference velocity for sound velocity level +U_REF = 5e-8 # 50 nano meter / s + +# Wiki: The unit dB FS or dBFS is defined in AES Standard AES17-1998,[13] +# IEC 61606,[14] and ITU-T P.38x,[15][16] such that the RMS value of a +# full-scale sine wave is designated 0 dB FS + +# The LASP code converts integer samples to floats, where the mapping is such +# that the maximum value (POSITIVE) that can be represented by the integer data +# is mapped to the value of 1.0. Following this convention, a sine wave with +# amplitude of 1.0 is 0 dB FS, and subsequently, its rms value is 0.5*sqrt(2), +# hence this is the reference level as specified below. +dBFS_REF = 0.5*2**0.5 # Which level would be -3.01 dBFS + +Qty = namedtuple('Qty', 'name unit_name unit_symb level_unit level_ref_name level_ref_value') + +class SIQtys: + AP = Qty(name='Acoustic Pressure', + unit_name='Pascal', + unit_symb=('Pa', 'muPa'), + level_unit=('dB SPL','dBPa'), + level_ref_name=('2 micropascal', '1 pascal',), + level_ref_value=(P_REF, 1) + ) + + V = Qty(name='Voltage', + unit_name='volt', + unit_symb='V', + level_unit=('dBV',), # dBV + level_ref_name=('1V',), + level_ref_value=(1.0,), + ) + N = Qty(name='No unit', + unit_name='', + unit_symb='[-]', + level_unit=('dBFS',), + level_ref_name=('Full scale sine wave',), + level_ref_value=(dBFS_REF,) + ) + types = (AP, V, N) + default = AP + default_index = 0 + + @staticmethod + def fillComboBox(cb): + """ + Fill FreqWeightings to a combobox + + Args: + cb: QComboBox to fill + """ + cb.clear() + for ty in SIQtys.types: + cb.addItem(f'{ty.name} [{ty.unit_symb[0]}') + cb.setCurrentIndex(SIQtys.default_index) + + @staticmethod + def getCurrent(cb): + return SIQtys.types[cb.currentIndex()] + + lasp_appdir = appdirs.user_data_dir('Lasp', 'ASCEE') if not os.path.exists(lasp_appdir): @@ -27,6 +96,7 @@ if not os.path.exists(lasp_appdir): print('Fatal error: could not create application directory') sys.exit(1) + class Shelve: def load(self, key, default_value): """ @@ -69,11 +139,11 @@ class Shelve: def __exit__(self, type, value, traceback): self.decref() + class lasp_shelve(Shelve): _refcount = 0 _shelve = None - @property def refcount(self): return lasp_shelve._refcount @@ -93,6 +163,7 @@ class lasp_shelve(Shelve): def shelve_fn(self): return os.path.join(lasp_appdir, 'config.shelve') + class this_lasp_shelve(Shelve): _refcount = 0 _shelve = None @@ -118,16 +189,6 @@ class this_lasp_shelve(Shelve): return os.path.join(lasp_appdir, f'{node}_config.shelve') -# Reference sound pressure level -P_REF = 2e-5 - -W_REF = 1e-12 # 1 picoWatt -I_REF = 1e-12 # 1 picoWatt/ m^2 - -# Reference velocity for sound velocity level -U_REF = 5e-8 - - class Window: hann = (wWindow.hann, 'Hann') hamming = (wWindow.hamming, 'Hamming') @@ -154,6 +215,7 @@ class Window: def getCurrent(cb): return Window.types[cb.currentIndex()] + class TimeWeighting: none = (-1, 'Raw (no time weighting)') uufast = (1e-4, '0.1 ms') @@ -188,6 +250,7 @@ class TimeWeighting: def getCurrent(cb): return TimeWeighting.types_all[cb.currentIndex()] + class FreqWeighting: """ Frequency weighting types @@ -216,6 +279,7 @@ class FreqWeighting: def getCurrent(cb): return FreqWeighting.types[cb.currentIndex()] + def getTime(fs, N, start=0): """ Return a time array for given number of points and sampling frequency. @@ -228,6 +292,7 @@ def getTime(fs, N, start=0): assert N > 0 and fs > 0 return np.linspace(start, start + N/fs, N, endpoint=False) + def getFreq(fs, nfft): """ return an array of frequencies for single-sided spectra