More checks on refMeas. Renamed method refMeas to getRefMeas. Added removeRefMeas. Stabilized API?

This commit is contained in:
Anne de Jong 2023-12-19 12:27:44 +01:00
parent 87283e4aba
commit 98d4e8dad2

View File

@ -372,7 +372,7 @@ class Measurement:
if ext != DOTMEXT: if ext != DOTMEXT:
newname = newname + DOTMEXT newname = newname + DOTMEXT
newname_full = str(pathlib.Path(self.folder) / newname ) newname_full = str(pathlib.Path(self.folder) / newname)
os.rename(self.fn, newname_full) os.rename(self.fn, newname_full)
def genNewUUID(self): def genNewUUID(self):
@ -388,7 +388,7 @@ class Measurement:
""" """
return self._UUID return self._UUID
def refMeas(self, mtype: MeasurementType): def getRefMeas(self, mtype: MeasurementType):
""" """
Return corresponding reference measurement, if configured and can be found. If the reference Return corresponding reference measurement, if configured and can be found. If the reference
measurement is currently not open, it tries to open it by traversing other measurement measurement is currently not open, it tries to open it by traversing other measurement
@ -402,30 +402,66 @@ class Measurement:
except KeyError: except KeyError:
raise ValueError(f"No reference measurement configured for '{self.name}'") raise ValueError(f"No reference measurement configured for '{self.name}'")
m = None
# Try to find it in the dictionary of of open measurements # Try to find it in the dictionary of of open measurements
if required_uuid in Measurement.uuid_s.keys(): if required_uuid in Measurement.uuid_s.keys():
m = Measurement.uuid_s[required_uuid] m = Measurement.uuid_s[required_uuid]
logging.info(f'Returned reference measurement {m.name} from list of open measurements') logging.info(f'Returned reference measurement {m.name} from list of open measurements')
return m
# See if we can open it using its last stored file name # Not found in list of openend measurements. See if we can open it using its last stored file name we know of
try: if m is None:
m = Measurement(possible_name) try:
if m.UUID == required_uuid: m = Measurement(possible_name)
logging.info(f'Opened reference measurement {m.name} by name') if m.UUID == required_uuid:
return m logging.info(f'Opened reference measurement {m.name} by name')
except Exception as e: except Exception as e:
logging.error(f'Could not find reference measurement using file name: {possible_name}') logging.error(f'Could not find reference measurement using file name: {possible_name}')
# Last resort, see if we can find the measurement in the same folder # Last resort, see if we can find the right measurement in the same folder
m = Measurement.fromFolderWithUUID(required_uuid, self.folder, skip=[self.name]) if m is None:
logging.info('Found reference measurement in folder with correct UUID. Updating name of reference measurement') try:
# Update the measurement file name in the list, such that next time it m = Measurement.fromFolderWithUUID(required_uuid, self.folder, skip=[self.name])
# can be opened just by its name. logging.info('Found reference measurement in folder with correct UUID. Updating name of reference measurement')
self.setRefMeas(m) # Update the measurement file name in the list, such that next time it
return m # can be opened just by its name.
self.setRefMeas(m)
raise RuntimeError("Could not find reference measurement") except:
logging.error("Could not find the reference measurement. Is it deleted?")
# Well, we found it. Now make sure the reference measurement actually has the right type (User could have marked it as a NotSpecific for example in the mean time).
if m is not None:
if m.measurementType() != mtype:
m.removeRefMeas(mtype)
raise RuntimeError(f"Reference measurement for {self.name} is not a proper reference (anymore).")
# Whow, we passed all security checks, here we go!
return m
else:
# Nope, not there.
raise RuntimeError(f"Could not find the reference measurement for '{self.name}'. Is it deleted?")
def removeRefMeas(self, mtype: MeasurementType):
"""
Remove an existing reference measurement of specified type from this measurement. Silently ignores this
action if no reference measurement of this type is configured.
"""
try:
del self._refMeas[mtype]
self.__storeReafMeas()
except KeyError:
pass
def __storeReafMeas(self):
"""
Internal method that syncs the dictionary of reference methods with the backing HDF5 file
"""
with self.file("r+") as f:
# Update attribute in file. Stored as a flat list of string tuples:
# [(ref_value1, uuid_1, name_1), (ref_value2, uuid_2, name_2), ...]
reflist = list((str(key.value), val1, val2) for key, (val1, val2) in self._refMeas.items())
# print(reflist)
f.attrs['refMeas'] = reflist
def setRefMeas(self, m: Measurement): def setRefMeas(self, m: Measurement):
""" """
@ -438,12 +474,7 @@ class Measurement:
raise ValueError('Measurement to be set as reference is not a reference measurement') raise ValueError('Measurement to be set as reference is not a reference measurement')
self._refMeas[mtype] = (m.UUID, m.name) self._refMeas[mtype] = (m.UUID, m.name)
with self.file("r+") as f: self.__storeReafMeas()
# Update attribute in file. Stored as a flat list of string tuples:
# [(ref_value1, uuid_1, name_1), (ref_value2, uuid_2, name_2), ...]
reflist = list((str(key.value), val1, val2) for key, (val1, val2) in self._refMeas.items())
# print(reflist)
f.attrs['refMeas'] = reflist
@staticmethod @staticmethod
def fromFolderWithUUID(uuid_str: str, folder: str='', skip=[]): def fromFolderWithUUID(uuid_str: str, folder: str='', skip=[]):
@ -657,13 +688,13 @@ class Measurement:
Nblock = block.shape[0] Nblock = block.shape[0]
sum_ += np.sum(block, axis=0) sum_ += np.sum(block, axis=0)
N += Nblock N += Nblock
meansquare += np.sum(block**2, axis=0) / self.N meansquare += np.sum(block ** 2, axis=0) / self.N
avg = sum_ / N avg = sum_ / N
# In fact, this is not the complete RMS, as in includes the DC # In fact, this is not the complete RMS, as in includes the DC
# If p = p_dc + p_osc, then rms(p_osc) = sqrt(ms(p)-ms(p_dc)) # If p = p_dc + p_osc, then rms(p_osc) = sqrt(ms(p)-ms(p_dc))
if substract_average: if substract_average:
meansquare -= avg**2 meansquare -= avg ** 2
rms = np.sqrt(meansquare) rms = np.sqrt(meansquare)
return rms return rms
@ -768,7 +799,7 @@ class Measurement:
signal = self.data(channels) signal = self.data(channels)
# Estimate noise power in block # Estimate noise power in block
blocks = [signal[i * N : (i + 1) * N] for i in range(Nblocks)] blocks = [signal[i * N: (i + 1) * N] for i in range(Nblocks)]
if noiseCorrection: if noiseCorrection:
# The difference between the measured signal in the previous block and # The difference between the measured signal in the previous block and
@ -972,10 +1003,11 @@ class Measurement:
raise ValueError(f"File {fn} does not exist.") raise ValueError(f"File {fn} does not exist.")
if timestamp is None: if timestamp is None:
timestamp = os.path.getmtime(fn) timestamp = os.path.getmtime(fn)
if mfn is None: if mfn is None:
mfn = os.path.splitext(fn)[0] + ".h5" mfn = os.path.splitext(fn)[0] + DOTMEXT
else: else:
mfn = os.path.splitext(mfn)[0] + ".h5" mfn = os.path.splitext(mfn)[0] + DOTMEXT
dat = np.loadtxt(fn, skiprows=skiprows, delimiter=delimiter) dat = np.loadtxt(fn, skiprows=skiprows, delimiter=delimiter)
if firstcoltime: if firstcoltime: