From 82ec7faa45ff23c8e46b3da978c73f0300775a2f Mon Sep 17 00:00:00 2001 From: "J.A. de Jong - Redu-Sone B.V., ASCEE V.O.F" Date: Wed, 29 Apr 2020 15:00:00 +0200 Subject: [PATCH] Bugfix for float32 data type. Neoformat comment markup --- lasp/lasp_measurement.py | 120 ++++++++++++++------------------------- 1 file changed, 42 insertions(+), 78 deletions(-) diff --git a/lasp/lasp_measurement.py b/lasp/lasp_measurement.py index 60baefd..02418c6 100644 --- a/lasp/lasp_measurement.py +++ b/lasp/lasp_measurement.py @@ -45,12 +45,10 @@ import time class BlockIter: - """ - Iterate over the blocks in the audio data of a h5 file - """ + """Iterate over the blocks in the audio data of a h5 file.""" + def __init__(self, f): - """ - Initialize a BlockIter object + """Initialize a BlockIter object. Args: faudio: Audio dataset in the h5 file, accessed as f['audio'] @@ -63,9 +61,7 @@ class BlockIter: return self def __next__(self): - """ - Return the next block - """ + """Return the next block.""" if self.i == self.nblocks: raise StopIteration self.i += 1 @@ -73,8 +69,7 @@ class BlockIter: def getSampWidth(dtype): - """ - Returns the width of a single sample in bytes. + """Returns the width of a single sample in bytes. Args: dtype: numpy dtype @@ -82,7 +77,7 @@ def getSampWidth(dtype): Returns: Size of a sample in bytes (int) """ - if dtype == np.int32: + if dtype in (np.int32, np.float32): return 4 elif dtype == np.int16: return 2 @@ -93,15 +88,12 @@ def getSampWidth(dtype): def scaleBlockSens(block, sens): - """ - Scale a block of raw data to return raw acoustic - pressure data. + """Scale a block of raw data to return raw acoustic pressure data. Args: block: block of raw data with integer data type sensitivity: array of sensitivity coeficients for each channel - """ assert sens.ndim == 1 assert sens.size == block.shape[1] @@ -129,14 +121,11 @@ def exportAsWave(fn, fs, data, force=False): class Measurement: - """ - Provides access to measurement data stored in the h5 measurement file - format. - """ + """Provides access to measurement data stored in the h5 measurement file + format.""" + def __init__(self, fn): - """ - Initialize a Measurement object based on the filename - """ + """Initialize a Measurement object based on the filename.""" if '.h5' not in fn: fn += '.h5' @@ -190,9 +179,7 @@ class Measurement: @property def name(self): - """ - Returns filename base without extension - """ + """Returns filename base without extension.""" return os.path.splitext(self.fn_base)[0] @property @@ -201,8 +188,7 @@ class Measurement: @contextmanager def file(self, mode='r'): - """ - Contextmanager which opens the storage file and yields the file. + """Contextmanager which opens the storage file and yields the file. Args: mode: Opening mode for the file. Should either be 'r', or 'r+' @@ -214,8 +200,7 @@ class Measurement: @property def comment(self): - """ - Return the measurement comment + """Return the measurement comment. Returns: The measurement comment (text string) @@ -224,8 +209,7 @@ class Measurement: @comment.setter def comment(self, cmt): - """ - Set the measurement comment + """Set the measurement comment. Args: cmt: Comment text string to set @@ -237,24 +221,19 @@ class Measurement: @property def recTime(self): - """ - Returns - the total recording time of the measurement, in float seconds. - """ + """Returns the total recording time of the measurement, in float + seconds.""" return self.blocksize * self.nblocks / self.samplerate @property def time(self): - """ - Returns the measurement time in seconds since the epoch. - """ + """Returns the measurement time in seconds since the epoch.""" return self._time def scaleBlock(self, block): - """ - When the data is stored as integers, we assume dB full-scale scaling. - Hence, when we convert the data to floats, we divide by the maximum - possible value. + """When the data is stored as integers, we assume dB full-scale + scaling. Hence, when we convert the data to floats, we divide by the + maximum possible value. Returns: Block of measurement data, scaled using sensitivity values and @@ -264,8 +243,7 @@ class Measurement: @property def prms(self): - """ - Returns the root mean square of the uncalibrated rms sound pressure + """Returns the root mean square of the uncalibrated rms sound pressure level (equivalend SPL). Returns: @@ -287,10 +265,8 @@ class Measurement: return self._prms def praw(self, block=None): - """ - Returns the uncalibrated acoustic pressure signal, converted to - floating point acoustic pressure values [Pa]. - """ + """Returns the uncalibrated acoustic pressure signal, converted to + floating point acoustic pressure values [Pa].""" if block is not None: with self.file() as f: blocks = f['audio'][block] @@ -308,8 +284,7 @@ class Measurement: return blocks def iterBlocks(self, opened_file): - """ - Iterate over all the audio blocks in the opened file + """Iterate over all the audio blocks in the opened file. Args: opened_file: The h5File with the data @@ -318,20 +293,19 @@ 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. If the sensitivity is not stored in - the measurement file, this function returns 1.0 + """Sensitivity of the data in Pa^-1, from floating point data scaled + between -1.0 and 1.0 to Pascal. + + If the sensitivity is not stored in the measurement file, this + function returns 1.0 """ return self._sens def checkOverflow(self): - """ - Coarse check for overflow in measurement + """Coarse check for overflow in measurement. Return: True if overflow is possible, else False - """ with self.file() as f: @@ -347,17 +321,16 @@ class Measurement: return False return False - @sensitivity.setter def sensitivity(self, sens): - """ - Set the sensitivity of the measurement in the file + """Set the sensitivity of the measurement in the file. Args: sens: sensitivity data, should be a float, or an array of floats equal to the number of channels. """ if isinstance(sens, float): + # Put all sensitivities equal sens = sens * np.ones(self.nchannels) valid = sens.ndim == 1 @@ -370,9 +343,8 @@ class Measurement: self._sens = sens def exportAsWave(self, fn=None, force=False, newsampwidth=2, normalize=True): - """ - Export measurement file as wave. In case the measurement data is stored - as floats, the values are scaled between 0 and 1 + """Export measurement file as wave. In case the measurement data is + stored as floats, the values are scaled between 0 and 1. Args: fn: If given, this will be the filename to write to. If the @@ -386,8 +358,6 @@ class Measurement: floating point values, otherwise an error is thrown normalize: If set: normalize the level to something sensible. - - """ if fn is None: fn = self.fn @@ -442,10 +412,9 @@ class Measurement: timestamp=None, delimiter='\t', firstcoltime=True): - """ - Converts a txt file to a LASP Measurement file, opens the associated - Measurement object and returns it. The measurement file will have - the same file name as the txt file, except with h5 extension. + """Converts a txt file to a LASP Measurement file, opens the associated + Measurement object and returns it. The measurement file will have the + same file name as the txt file, except with h5 extension. Args: fn: Filename of text file @@ -460,7 +429,6 @@ class Measurement: delimiter: Column delimiter firstcoltime: If true, the first column is the treated as the sample time. - """ if not os.path.exists(fn): raise ValueError(f'File {fn} does not exist.') @@ -497,7 +465,6 @@ class Measurement: compression='gzip') ad[0] = dat return Measurement(mfn) - @staticmethod def fromnpy(data, @@ -505,14 +472,12 @@ class Measurement: sensitivity, mfn, timestamp=None): - """ - Converts a numpy array to a LASP Measurement file, opens the associated - Measurement object and returns it. The measurement file will have - the same file name as the txt file, except with h5 extension. - + """Converts a numpy array to a LASP Measurement file, opens the + associated Measurement object and returns it. The measurement file will + have the same file name as the txt file, except with h5 extension. Args: - data: Numpy array, first column is sample, second is channel. Can + data: Numpy array, first column is sample, second is channel. Can also be specified with a single column for single-channel data samplerate: Sampling frequency in [Hz] sensitivity: 1D array of channel sensitivities [Pa^-1] @@ -523,7 +488,6 @@ class Measurement: delimiter: Column delimiter firstcoltime: If true, the first column is the treated as the sample time. - """ if os.path.exists(mfn): raise ValueError(f'File {mfn} already exist.')