From 98d4e8dad20254f03e43c9048b8e8c1678dfd0f8 Mon Sep 17 00:00:00 2001 From: "J.A. de Jong - Redu-Sone B.V., ASCEE V.O.F" Date: Tue, 19 Dec 2023 12:27:44 +0100 Subject: [PATCH] More checks on refMeas. Renamed method refMeas to getRefMeas. Added removeRefMeas. Stabilized API? --- python_src/lasp/lasp_measurement.py | 94 +++++++++++++++++++---------- 1 file changed, 63 insertions(+), 31 deletions(-) diff --git a/python_src/lasp/lasp_measurement.py b/python_src/lasp/lasp_measurement.py index 61a4ec4..6b70fd3 100644 --- a/python_src/lasp/lasp_measurement.py +++ b/python_src/lasp/lasp_measurement.py @@ -372,7 +372,7 @@ class Measurement: if ext != 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) def genNewUUID(self): @@ -388,7 +388,7 @@ class Measurement: """ 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 measurement is currently not open, it tries to open it by traversing other measurement @@ -402,30 +402,66 @@ class Measurement: except KeyError: raise ValueError(f"No reference measurement configured for '{self.name}'") + m = None # Try to find it in the dictionary of of open measurements if required_uuid in Measurement.uuid_s.keys(): m = Measurement.uuid_s[required_uuid] 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 - try: - m = Measurement(possible_name) - if m.UUID == required_uuid: - logging.info(f'Opened reference measurement {m.name} by name') - return m - except Exception as e: - logging.error(f'Could not find reference measurement using file name: {possible_name}') + # Not found in list of openend measurements. See if we can open it using its last stored file name we know of + if m is None: + try: + m = Measurement(possible_name) + if m.UUID == required_uuid: + logging.info(f'Opened reference measurement {m.name} by name') + except Exception as e: + 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 - m = Measurement.fromFolderWithUUID(required_uuid, self.folder, skip=[self.name]) - logging.info('Found reference measurement in folder with correct UUID. Updating name of reference measurement') - # Update the measurement file name in the list, such that next time it - # can be opened just by its name. - self.setRefMeas(m) - return m - - raise RuntimeError("Could not find reference measurement") + # Last resort, see if we can find the right measurement in the same folder + if m is None: + try: + m = Measurement.fromFolderWithUUID(required_uuid, self.folder, skip=[self.name]) + logging.info('Found reference measurement in folder with correct UUID. Updating name of reference measurement') + # Update the measurement file name in the list, such that next time it + # can be opened just by its name. + self.setRefMeas(m) + 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): """ @@ -438,12 +474,7 @@ class Measurement: raise ValueError('Measurement to be set as reference is not a reference measurement') self._refMeas[mtype] = (m.UUID, m.name) - 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 + self.__storeReafMeas() @staticmethod def fromFolderWithUUID(uuid_str: str, folder: str='', skip=[]): @@ -657,13 +688,13 @@ class Measurement: Nblock = block.shape[0] sum_ += np.sum(block, axis=0) N += Nblock - meansquare += np.sum(block**2, axis=0) / self.N + meansquare += np.sum(block ** 2, axis=0) / self.N avg = sum_ / N # 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 substract_average: - meansquare -= avg**2 + meansquare -= avg ** 2 rms = np.sqrt(meansquare) return rms @@ -768,7 +799,7 @@ class Measurement: signal = self.data(channels) # 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: # 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.") if timestamp is None: timestamp = os.path.getmtime(fn) + if mfn is None: - mfn = os.path.splitext(fn)[0] + ".h5" + mfn = os.path.splitext(fn)[0] + DOTMEXT else: - mfn = os.path.splitext(mfn)[0] + ".h5" + mfn = os.path.splitext(mfn)[0] + DOTMEXT dat = np.loadtxt(fn, skiprows=skiprows, delimiter=delimiter) if firstcoltime: