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