Merge remote-tracking branch 'origin/develop' into develop
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Anne de Jong 2023-04-19 15:56:35 +02:00
commit 3844827505
1 changed files with 42 additions and 34 deletions

View File

@ -274,7 +274,6 @@ class Measurement:
self._qtys = [SIQtys.default() for i in range(self.nchannels)]
logging.debug(f'Physical quantity data not available in measurement file. Assuming {SIQtys.default}')
def setAttribute(self, atrname, value):
"""
Set an attribute in the measurement file, and keep a local copy in
@ -632,8 +631,8 @@ class Measurement:
return False
def exportAsWave(self, fn=None, force=False, newsampwidth=None,
normalize=True, **kwargs):
def exportAsWave(self, fn=None, force=False, dtype=None,
normalize=False, **kwargs):
"""Export measurement file as wave. In case the measurement data is
stored as floats, the values are scaled to the proper integer (PCM)
data format.
@ -645,9 +644,8 @@ class Measurement:
force: If True, overwrites any existing files with the given name
, otherwise a RuntimeError is raised.
newsampwidth: sample width in bytes with which to export the data.
This should only be given in case the measurement data is stored as
floating point values, otherwise an error is thrown
dtype: if not None, convert data to this data type.
Options are 'int16', 'int32', 'float32'.
normalize: If set: normalize the level to something sensible.
"""
@ -661,39 +659,49 @@ class Measurement:
if os.path.exists(fn) and not force:
raise RuntimeError(f'File already exists: {fn}')
if not np.isclose(self.samplerate%1,0):
raise RuntimeError(f'Sample rates should be approximately integer for exporting to Wave to work')
# TODO: With VERY large measurment files, this is not possible! Is this
# a theoretical case?
# TODO: add sensitivity? Then use self.data() instead of self.rawData()
data = self.rawData(**kwargs)
if np.issubdtype(data.dtype, np.floating) and newsampwidth is None:
raise ValueError('Newsampwidth parameter should be given for floating point raw data')
if normalize:
# Scale back to maximum of absolute value
maxabs = np.max(np.abs(data))
data = data / maxabs # "data /= maxabs" fails if dtpyes differ
if newsampwidth is not None:
# Convert to floats, then to new sample width
sensone = np.ones_like(self.sensitivity)
data = scaleBlockSens(data, sensone)
if dtype==None:
dtype = data.dtype # keep existing
logging.debug(f"dtype not passed as arg; using dtype = {dtype}")
if newsampwidth == 2:
newtype = np.int16
elif newsampwidth == 4:
newtype = np.int32
else:
raise ValueError('Invalid sample width, should be 2 or 4')
# dtype conversion
if dtype=='int16':
newtype = np.int16
newsampwidth = 2
elif dtype=='int32':
newtype = np.int32
newsampwidth = 4
elif dtype=='float32':
newtype = np.float32
elif dtype=='float64':
newtype = np.float64
else:
logging.debug(f"cannot handle this dtype {dtype}")
pass
# Convert range to [-1, 1]
# TODO: this is wrong for float data where full scale > 1
sensone = np.ones_like(self.sensitivity)
data = scaleBlockSens(data, sensone)
if dtype=='int16' or dtype=='int32':
# Scale data to integer range and convert to integers
scalefac = 2**(8*newsampwidth-1)-1
# Scale data to integer range, and then convert to integers
data = (data*scalefac).astype(newtype)
wavfile.write(fn, int(self.samplerate), data)
wavfile.write(fn, int(self.samplerate), data.astype(newtype))
@staticmethod
def fromtxt(fn,