From 54937eb4a3bd303b0e641a26c220c63bc6544028 Mon Sep 17 00:00:00 2001 From: Matheus Date: Tue, 25 Mar 2025 13:19:07 -0300 Subject: [PATCH 01/10] COMMISS.WIP: initial draft of inj nudge class --- apsuite/commisslib/inj_nudges.py | 215 +++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 apsuite/commisslib/inj_nudges.py diff --git a/apsuite/commisslib/inj_nudges.py b/apsuite/commisslib/inj_nudges.py new file mode 100644 index 00000000..d393906c --- /dev/null +++ b/apsuite/commisslib/inj_nudges.py @@ -0,0 +1,215 @@ +import threading as _threading +import time as _time + +import numpy as _np +from siriuspy.devices import EVG +from siriuspy.epics import PV + +from ..utils import ParamsBaseClass as _ParamsBaseClass, \ + ThreadedMeasBaseClass as _BaseClass + + +class InjNudgesParams(_ParamsBaseClass): + """.""" + + def __init__(self): + """.""" + super().__init__() + self.num_inj_samples = 3 + self.topup_current = 200 # [mA] + self.pv_connection_timeout = 3 + self.knobs_lims = { + # knob [lim_low, lim_high] unit + "BO-01D:PU-InjKckr:Voltage-SP" : [-1, 1], # [V] + "TB-04:PS-CH-1:Current-SP" : [-0.25, 0.25], # [A] + "TB-04:PU-InjSept:Voltage-SP" : [-1, 1], # [V] + "TB-04:PS-CV-1:Current-SP" : [-0.25, 0.25], # [A] + "TB-04:PS-CV-2:Current-SP" : [-0.25, 0.25], # [A] + "LA-RF:LLRF:BUN1:SET_AMP" : [-0.5, 0.5], # [%] + "LA-RF:LLRF:KLY1:SET_AMP" : [-1, 1], # [%] + "LA-RF:LLRF:KLY2:SET_AMP" : [-1, 1], # [%] + "RA-RaBO01:RF-LLRF:RmpPhsBot-SP" : [-5, 5], # [deg] + "BO-Fam:PS-QD:WfmOffset-SP" : [-0.02, 0.02], # [A] + "BO-Fam:PS-QF:WfmOffset-SP" : [-0.02, 0.02], # [A] + "BO-Fam:PS-SD:WfmOffset-SP" : [-0.05, 0.05], # [A] + "BO-Fam:PS-SF:WfmOffset-SP" : [-0.05, 0.05], # [A] + "BO-Fam:PS-B-1:WfmOffset-SP" : [-0.05, 0.05], # [A] + "BO-Fam:PS-B-2:WfmOffset-SP" : [-0.05, 0.05], # [A] + } + self.knobs_pvs_names = sorted(self.knobs.keys()) + self.injeff_pv_name = None + self.si_curr_pv_name = "SI-Glob:AP-CurrInfo:Current-Mon" + self.low_lims = [ + self.knobs_lims[kn][0] for kn in self.knobs_pvs_names + ] + self.upper_lims = [ + self.knobs_lims[kn][1] for kn in self.knobs_pvs_names + ] + + +class InjNudges(_BaseClass): + """.""" + def __init__(self, isonline=True): + """.""" + self.params = InjNudgesParams + super().__init__( + self, params=self.params, + target=self.do_measure, isonline=isonline + ) + self.ref_injeff_mean = None + self.ref_injeff_std = None + + if self.isonline: + self.connect_pvs() + + def connect_pvs(self): + """.""" + print("Is online. Connecting to PVs.") + pvs_names = [self.params.injeff_pv_name] + pvs_names += [self.params.si_curr_pv_name] + pvs_names += self.params.knobs_pvs_names + + pvs = {} + for pv_name in pvs_names: + pv = PV(pv_name) + pv.wait_for_connection(timeout=self.params.pv_connection_timeout) + print(f"PV {pv_name:<35s} connected: {pv.connected}") + pvs[pv_name] = pv + + self.pvs = pvs + self.devices = {"evg": EVG()} + + def get_pos(self): + """.""" + pos = list() + for pv_name in self.params.knobs_pvs_names: + pos.append(self.pvs[pv_name].value) + return pos + + def set_pos(self, pos): + """.""" + for i, pv_name in enumerate(self.params.knobs_pvs_names): + self.pvs[pv_name].value = pos[i] + + def get_knob_nudge(self): + """.""" + nudges = _np.random.uniform( + low=self.params.low_lims, high=self.params.upper_lims + ) + return nudges + + def acquire_efficiencies(self, ref_mean, ref_sigma): + """.""" + print("\tacquiring injeffs...") + injeff_pv = self.pvs[self.params.injeff_pv_name] + tim, vals = [], [] + event = _threading.Event() + injeff_pv.add_callback( + self, self.on_change, tim=tim, + vals=vals, event=event, + ref_mean=ref_mean, ref_sigma=ref_sigma) + event.wait() + injeff_pv.clear_callbacks() + mean, sigma = _np.mean(vals), _np.std(vals) + + print(f"\t\tmean injeff {mean:3.2f} +- {sigma:.2f} %") + print("\tacquisitions finished.") + return tim, vals, mean, sigma + + def on_change( + self, timestamp, value, tim, vals, event, + ref_mean, ref_sigma, num_samples, **kwargs + ): + """Callback function to be added to the injeff PV.""" + print(f"\t\tinjeff now at {value:3.2f} %") + tim.append(timestamp) + vals.append(value) + if len(vals) >= num_samples: + event.set() + if None in (ref_mean, ref_sigma): + return + if len(vals) > 1 and (_np.mean(vals) < ref_mean - ref_sigma): + event.set() + + def recover_topup(self, pos_good, sleep_time=30): + """.""" + print("") + print( + f"SI current below {self.params.topup_curent}. Recovering top-up." + ) + self.set_pos(pos_good) + si_curr = self.pvs[self.params.si_curr_pv_name] + curr = si_curr.value + while curr < 180: + _time.sleep(sleep_time) + curr = si_curr.value + else: + print(f"\tcurrent at {curr:3.2f} mA.") + print("\tcurrent restored. Continuing nudges.") + + def do_measure(self): + """.""" + self.data["timestamps"] = list() + self.data["values"] = list() + self.data["positions"] = list() + + print("Starting injection nudging loop.\n") + print("Efficiency acquisitions for initial reference") + + tim, vals, ref_mean, ref_sigma = self.acquire_efficiencies() + + pos = self.get_pos() + + while True: + + delta_pos = self.get_knob_nudge() + + i = _np.random.randint(len(delta_pos)) + dposi = delta_pos[i] + knobi_name = self.params.knobs_pvs_names[i] + print("") + print(f"Nudging {knobi_name} in {dposi:2.2f}") + posi0 = pos[i] + pos[i] += dposi + + evg = self.devices["evg"] + if evg.injection_state: + print("\tinjection is on. Waiting for it to finish...") + evg.wait_injection_finish() + + if self._stopevt.is_set(): + print("Stop event was set.") + self.finish_meas() + + print("\tsetting new position") + self.set_pos(pos) + + tim, vals, mean_injeff, sigma_injeff = self.acquire_efficiencies( + ref_mean=ref_mean, ref_sigma=ref_sigma + ) + + self.data["timestamps"].append(tim) + self.data["values"].append(vals) + self.data["positions"].append(pos) + + if mean_injeff >= ref_mean: + print(f"\tchanges in {knobi_name} improved injeff!") + ref_mean, ref_sigma = mean_injeff, sigma_injeff + print(f"\tnew reference injeff: {ref_mean:3.3f} %") + else: + print(f"\treverting changes in {knobi_name}...") + pos[i] = posi0 + self.set_pos(pos) + + si_curr = self.pvs[self.params.si_curr_pv_name].value + if si_curr < self.params.topup_current: + self.recover_topup(pos, sleep_time=10) + + self.save_data(fname="inj_nudges", overwrite=True) + + def finish_meas(self): + """.""" + print("Finishing measurement.") + self.save_data(fname="inj_nudges", overwrite=True) + self.pvs[self.params.injeff_pv_name].clear_callbacks() + return From 56f11c8c9159de66bb555c4e61e981ebeb7d1752 Mon Sep 17 00:00:00 2001 From: Matheus Date: Tue, 1 Apr 2025 16:28:37 -0300 Subject: [PATCH 02/10] COMMISS.WIP: bring news from last tests --- apsuite/commisslib/inj_nudges.py | 147 ++++++++++++++++++++----------- 1 file changed, 94 insertions(+), 53 deletions(-) diff --git a/apsuite/commisslib/inj_nudges.py b/apsuite/commisslib/inj_nudges.py index d393906c..651cd181 100644 --- a/apsuite/commisslib/inj_nudges.py +++ b/apsuite/commisslib/inj_nudges.py @@ -4,6 +4,7 @@ import numpy as _np from siriuspy.devices import EVG from siriuspy.epics import PV +from siriuspy.clientarch import Time from ..utils import ParamsBaseClass as _ParamsBaseClass, \ ThreadedMeasBaseClass as _BaseClass @@ -16,7 +17,8 @@ def __init__(self): """.""" super().__init__() self.num_inj_samples = 3 - self.topup_current = 200 # [mA] + self.num_attempts_per_ref = 5 + self.min_topup_current = 198.5 # [mA] self.pv_connection_timeout = 3 self.knobs_lims = { # knob [lim_low, lim_high] unit @@ -36,14 +38,14 @@ def __init__(self): "BO-Fam:PS-B-1:WfmOffset-SP" : [-0.05, 0.05], # [A] "BO-Fam:PS-B-2:WfmOffset-SP" : [-0.05, 0.05], # [A] } - self.knobs_pvs_names = sorted(self.knobs.keys()) - self.injeff_pv_name = None - self.si_curr_pv_name = "SI-Glob:AP-CurrInfo:Current-Mon" + self.knobs_pvsnames = sorted(self.knobs_lims.keys()) + self.injeff_pvname = None + self.si_curr_pvname = "SI-Glob:AP-CurrInfo:Current-Mon" self.low_lims = [ - self.knobs_lims[kn][0] for kn in self.knobs_pvs_names + self.knobs_lims[kn][0] for kn in self.knobs_pvsnames ] self.upper_lims = [ - self.knobs_lims[kn][1] for kn in self.knobs_pvs_names + self.knobs_lims[kn][1] for kn in self.knobs_pvsnames ] @@ -51,23 +53,22 @@ class InjNudges(_BaseClass): """.""" def __init__(self, isonline=True): """.""" - self.params = InjNudgesParams super().__init__( - self, params=self.params, - target=self.do_measure, isonline=isonline + self, target=self.do_measure, isonline=isonline ) + self.params = InjNudgesParams() self.ref_injeff_mean = None self.ref_injeff_std = None if self.isonline: - self.connect_pvs() + self.connect_pvs_and_evg() - def connect_pvs(self): + def connect_pvs_and_evg(self): """.""" print("Is online. Connecting to PVs.") - pvs_names = [self.params.injeff_pv_name] - pvs_names += [self.params.si_curr_pv_name] - pvs_names += self.params.knobs_pvs_names + pvs_names = [self.params.injeff_pvname] + pvs_names += [self.params.si_curr_pvname] + pvs_names += self.params.knobs_pvsnames pvs = {} for pv_name in pvs_names: @@ -80,55 +81,74 @@ def connect_pvs(self): self.devices = {"evg": EVG()} def get_pos(self): - """.""" - pos = list() - for pv_name in self.params.knobs_pvs_names: - pos.append(self.pvs[pv_name].value) + """Returns knobs positions as a dict of (timestamp, value).""" + vals = self.get_pvs_tmtsp_and_vals() + pos = { + pvname: vals[pvname] for pvname in self.params.knobs_pvsnames + } return pos + def get_pvs_tmtsp_and_vals(self): + """.""" + vals = dict() + for pvname, pv in self.pvs.items(): + vals[pvname] = [pv.timestamp, pv.value] + return vals + def set_pos(self, pos): """.""" - for i, pv_name in enumerate(self.params.knobs_pvs_names): - self.pvs[pv_name].value = pos[i] + for pv_name in self.params.knobs_pvsnames: + _, value = pos[pv_name] + pv = self.pvs[pv_name] + if value != pv.value: + pv.value = value - def get_knob_nudge(self): + def get_knob_nudges(self): """.""" nudges = _np.random.uniform( low=self.params.low_lims, high=self.params.upper_lims ) return nudges - def acquire_efficiencies(self, ref_mean, ref_sigma): + def acquire_efficiencies(self, ref_mean=None, ref_sigma=None): """.""" - print("\tacquiring injeffs...") - injeff_pv = self.pvs[self.params.injeff_pv_name] - tim, vals = [], [] - event = _threading.Event() + print("\tacquiring inj. effs. ...") + + injeff_pv = self.pvs[self.params.injeff_pvname] + tim, effs, pvvals = [], [], [] + event = _threading.Event() # signals acqs. are finished + injeff_pv.add_callback( - self, self.on_change, tim=tim, - vals=vals, event=event, - ref_mean=ref_mean, ref_sigma=ref_sigma) - event.wait() + self, self.on_change, tim=tim, effs=effs, pvvals=pvvals, + event=event, ref_mean=ref_mean, ref_sigma=ref_sigma + ) + event.wait(timeout=(60 + 2) * self.params.num_inj_samples) injeff_pv.clear_callbacks() - mean, sigma = _np.mean(vals), _np.std(vals) + + mean, sigma = _np.mean(effs), _np.std(effs) print(f"\t\tmean injeff {mean:3.2f} +- {sigma:.2f} %") print("\tacquisitions finished.") - return tim, vals, mean, sigma + return tim, effs, mean, sigma, pvvals def on_change( - self, timestamp, value, tim, vals, event, - ref_mean, ref_sigma, num_samples, **kwargs + self, timestamp, value, tim, effs, pvvals, event, + ref_mean, ref_sigma, **kwargs ): """Callback function to be added to the injeff PV.""" - print(f"\t\tinjeff now at {value:3.2f} %") + tmstp = Time.fromtimestamp(_time.time()) + datetime = tmstp.strftime("%Y-%m-%d %H:%M:%S") + print(f"\t\t{datetime} inj. eff.: {value:3.2f}%, SI curr.:") + + pvvals.append(self.get_pvs_tmtsp_and_vals()) tim.append(timestamp) - vals.append(value) - if len(vals) >= num_samples: + effs.append(value) + + if len(effs) >= self.params.num_inj_samples: event.set() if None in (ref_mean, ref_sigma): - return - if len(vals) > 1 and (_np.mean(vals) < ref_mean - ref_sigma): + return # What to do? + if len(effs) > 1 and (_np.mean(effs) < ref_mean - ref_sigma): event.set() def recover_topup(self, pos_good, sleep_time=30): @@ -138,7 +158,7 @@ def recover_topup(self, pos_good, sleep_time=30): f"SI current below {self.params.topup_curent}. Recovering top-up." ) self.set_pos(pos_good) - si_curr = self.pvs[self.params.si_curr_pv_name] + si_curr = self.pvs[self.params.si_curr_pvname] curr = si_curr.value while curr < 180: _time.sleep(sleep_time) @@ -150,27 +170,31 @@ def recover_topup(self, pos_good, sleep_time=30): def do_measure(self): """.""" self.data["timestamps"] = list() - self.data["values"] = list() + self.data["effs"] = list() + self.data["pvvals"] = list() self.data["positions"] = list() print("Starting injection nudging loop.\n") print("Efficiency acquisitions for initial reference") - tim, vals, ref_mean, ref_sigma = self.acquire_efficiencies() - + ret = self.acquire_efficiencies() + if ret is None: + raise ValueError + tim, effs, ref_mean, ref_sigma, pvvals = ret + si_curr = self.pvs[self.params.si_curr_pvname].value pos = self.get_pos() - + fails_w_same_ref = 0 while True: - delta_pos = self.get_knob_nudge() + delta_pos = self.get_knob_snudge() i = _np.random.randint(len(delta_pos)) dposi = delta_pos[i] - knobi_name = self.params.knobs_pvs_names[i] + knobi_name = self.params.knobs_pvsnames[i] print("") print(f"Nudging {knobi_name} in {dposi:2.2f}") - posi0 = pos[i] - pos[i] += dposi + posi0 = pos[i].copy() + pos[knobi_name][i] += dposi evg = self.devices["evg"] if evg.injection_state: @@ -184,24 +208,41 @@ def do_measure(self): print("\tsetting new position") self.set_pos(pos) - tim, vals, mean_injeff, sigma_injeff = self.acquire_efficiencies( + ret = self.acquire_efficiencies( ref_mean=ref_mean, ref_sigma=ref_sigma ) + if ret is None: + print("None returned. Starting over again.") + self.set_pos(pos) + continue + tim, effs, mean_injeff, sigma_injeff, pvvals = ret self.data["timestamps"].append(tim) - self.data["values"].append(vals) + self.data["effs"].append(effs) self.data["positions"].append(pos) + self.data["pvvals"] = pvvals - if mean_injeff >= ref_mean: + if mean_injeff - sigma_injeff >= ref_mean - ref_sigma: print(f"\tchanges in {knobi_name} improved injeff!") ref_mean, ref_sigma = mean_injeff, sigma_injeff + fails_w_same_ref = 0 print(f"\tnew reference injeff: {ref_mean:3.3f} %") else: print(f"\treverting changes in {knobi_name}...") + fails_w_same_ref += 1 pos[i] = posi0 self.set_pos(pos) - si_curr = self.pvs[self.params.si_curr_pv_name].value + if fails_w_same_ref > self.params.num_attempts_per_ref: + t = "\nSame reference used for too long." + t += "Updating reference" + print(t) + + ret = self.acquire_efficiencies() + if ret is not None: + _, _, ref_mean, ref_sigma, _ = ret + fails_w_same_ref = 0 + if si_curr < self.params.topup_current: self.recover_topup(pos, sleep_time=10) @@ -211,5 +252,5 @@ def finish_meas(self): """.""" print("Finishing measurement.") self.save_data(fname="inj_nudges", overwrite=True) - self.pvs[self.params.injeff_pv_name].clear_callbacks() + self.pvs[self.params.injeff_pvname].clear_callbacks() return From 0bbb9f01efb28545cf93d4936b93d331139b4bb1 Mon Sep 17 00:00:00 2001 From: Matheus Date: Wed, 2 Apr 2025 09:12:07 -0300 Subject: [PATCH 03/10] COMMISS.INJNUDG.BUG - fix some bugs - add TODOs --- apsuite/commisslib/inj_nudges.py | 34 +++++++++++++++++++------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/apsuite/commisslib/inj_nudges.py b/apsuite/commisslib/inj_nudges.py index 651cd181..7e4bc48c 100644 --- a/apsuite/commisslib/inj_nudges.py +++ b/apsuite/commisslib/inj_nudges.py @@ -12,10 +12,10 @@ class InjNudgesParams(_ParamsBaseClass): """.""" - def __init__(self): """.""" super().__init__() + self.filename2use = "inj_nudges" self.num_inj_samples = 3 self.num_attempts_per_ref = 5 self.min_topup_current = 198.5 # [mA] @@ -39,7 +39,7 @@ def __init__(self): "BO-Fam:PS-B-2:WfmOffset-SP" : [-0.05, 0.05], # [A] } self.knobs_pvsnames = sorted(self.knobs_lims.keys()) - self.injeff_pvname = None + self.injeff_pvname = "BO-Glob:AP-CurrInfo:RampEff-Mon" self.si_curr_pvname = "SI-Glob:AP-CurrInfo:Current-Mon" self.low_lims = [ self.knobs_lims[kn][0] for kn in self.knobs_pvsnames @@ -47,6 +47,7 @@ def __init__(self): self.upper_lims = [ self.knobs_lims[kn][1] for kn in self.knobs_pvsnames ] + self.observables_pvs_names = "" # Other observable params class InjNudges(_BaseClass): @@ -103,7 +104,7 @@ def set_pos(self, pos): if value != pv.value: pv.value = value - def get_knob_nudges(self): + def get_knobs_nudges(self): """.""" nudges = _np.random.uniform( low=self.params.low_lims, high=self.params.upper_lims @@ -179,30 +180,34 @@ def do_measure(self): ret = self.acquire_efficiencies() if ret is None: + print("No samples for initial inj. eff. reference.") raise ValueError tim, effs, ref_mean, ref_sigma, pvvals = ret - si_curr = self.pvs[self.params.si_curr_pvname].value + pos = self.get_pos() fails_w_same_ref = 0 + evg = self.devices["evg"] + while True: - delta_pos = self.get_knob_snudge() + delta_pos = self.get_knobs_nudges() i = _np.random.randint(len(delta_pos)) - dposi = delta_pos[i] + dposi = float(delta_pos[i]) knobi_name = self.params.knobs_pvsnames[i] print("") print(f"Nudging {knobi_name} in {dposi:2.2f}") - posi0 = pos[i].copy() - pos[knobi_name][i] += dposi + posi0 = pos[knobi_name].copy() + pos[knobi_name][1] += dposi - evg = self.devices["evg"] if evg.injection_state: print("\tinjection is on. Waiting for it to finish...") evg.wait_injection_finish() if self._stopevt.is_set(): print("Stop event was set.") + # TODO: handle stops during self.acquire_efficiencies + # & self.on_change self.finish_meas() print("\tsetting new position") @@ -234,23 +239,24 @@ def do_measure(self): self.set_pos(pos) if fails_w_same_ref > self.params.num_attempts_per_ref: - t = "\nSame reference used for too long." - t += "Updating reference" + t = "\nSame references used for too long." + t += "Updating references" print(t) ret = self.acquire_efficiencies() if ret is not None: _, _, ref_mean, ref_sigma, _ = ret fails_w_same_ref = 0 - + si_curr = self.pvs[self.params.si_curr_pvname].value if si_curr < self.params.topup_current: self.recover_topup(pos, sleep_time=10) - self.save_data(fname="inj_nudges", overwrite=True) + self.save_data(fname=self.params.filename2use, overwrite=True) def finish_meas(self): """.""" print("Finishing measurement.") - self.save_data(fname="inj_nudges", overwrite=True) + self.save_data(fname=self.params.filename2use, overwrite=True) + # TODO: automatic naming convention if filename2use is None self.pvs[self.params.injeff_pvname].clear_callbacks() return From 5093e24fbfb6520ca1761a83f15b3d82ab16b848 Mon Sep 17 00:00:00 2001 From: Matheus Date: Wed, 2 Apr 2025 09:43:01 -0300 Subject: [PATCH 04/10] COMMISS.INJNDG.DEV: add params str method --- apsuite/commisslib/inj_nudges.py | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/apsuite/commisslib/inj_nudges.py b/apsuite/commisslib/inj_nudges.py index 7e4bc48c..a8302bff 100644 --- a/apsuite/commisslib/inj_nudges.py +++ b/apsuite/commisslib/inj_nudges.py @@ -15,11 +15,11 @@ class InjNudgesParams(_ParamsBaseClass): def __init__(self): """.""" super().__init__() - self.filename2use = "inj_nudges" + self.pv_connection_timeout = 3 self.num_inj_samples = 3 self.num_attempts_per_ref = 5 self.min_topup_current = 198.5 # [mA] - self.pv_connection_timeout = 3 + self.filename2use = "inj_nudges" self.knobs_lims = { # knob [lim_low, lim_high] unit "BO-01D:PU-InjKckr:Voltage-SP" : [-1, 1], # [V] @@ -49,6 +49,31 @@ def __init__(self): ] self.observables_pvs_names = "" # Other observable params + def __str__(self): + """.""" + ftmp = "{0:24s} = {1:9.3f} {2:s}\n".format + dtmp = "{0:24s} = {1:9d} {2:s}\n".format + stmp = "{0:24s} = {1:9s} {2:s}\n".format + + stg = "" + stg += ftmp( + "pv_connection_timeout", self.pv_connection_timeout, "[s]" + ) + stg += dtmp("num_inj_samples", self.num_inj_samples, "") + stg += dtmp("num_attempts_per_ref", self.num_attempts_per_ref, "") + stg += ftmp("min_topup_current", self.min_topup_current, "mA") + stg += stmp("filename2use", self.filename2use, "") + stg += stmp("injeff_pvname", self.injeff_pvname, "") + stg += "\n" + stg += " knob [lim_low, lim_high]\n" + for kn in self.knobs_pvsnames: + stg += f"{kn:<30s} : {self.knobs_lims[kn]}\n" + + stg += "\n" + stg += "other observables\n" + for pvname in self.observables_pvs_names: + stg += f"{pvname:<30s}" + return stg class InjNudges(_BaseClass): """.""" From 1fa04c6d0e2f8a7af66b5649bf55209a8d646a42 Mon Sep 17 00:00:00 2001 From: Matheus Date: Wed, 2 Apr 2025 10:59:40 -0300 Subject: [PATCH 05/10] COMMISS.INJNDG.DEV: allow choosing btw inj BO or inj SI --- apsuite/commisslib/inj_nudges.py | 116 +++++++++++++++++++++++-------- 1 file changed, 88 insertions(+), 28 deletions(-) diff --git a/apsuite/commisslib/inj_nudges.py b/apsuite/commisslib/inj_nudges.py index a8302bff..29afb0d4 100644 --- a/apsuite/commisslib/inj_nudges.py +++ b/apsuite/commisslib/inj_nudges.py @@ -9,8 +9,45 @@ from ..utils import ParamsBaseClass as _ParamsBaseClass, \ ThreadedMeasBaseClass as _BaseClass - -class InjNudgesParams(_ParamsBaseClass): +BOINJEFF_PVNAME = "BO-Glob:AP-CurrInfo:RampEff-Mon" +BOINJ_KNOBS = { + # knob [lim_low, lim_high] unit + "BO-01D:PU-InjKckr:Voltage-SP" : [-1, 1], # [V] + "TB-04:PS-CH-1:Current-SP" : [-0.25, 0.25], # [A] + "TB-04:PU-InjSept:Voltage-SP" : [-1, 1], # [V] + "TB-04:PS-CV-1:Current-SP" : [-0.25, 0.25], # [A] + "TB-04:PS-CV-2:Current-SP" : [-0.25, 0.25], # [A] + "LA-RF:LLRF:BUN1:SET_AMP" : [-0.5, 0.5], # [%] + "LA-RF:LLRF:KLY1:SET_AMP" : [-1, 1], # [%] + "LA-RF:LLRF:KLY2:SET_AMP" : [-1, 1], # [%] + "RA-RaBO01:RF-LLRF:RmpPhsBot-SP" : [-5, 5], # [deg] + "BO-Fam:PS-QD:WfmOffset-SP" : [-0.02, 0.02], # [A] + "BO-Fam:PS-QF:WfmOffset-SP" : [-0.02, 0.02], # [A] + "BO-Fam:PS-SD:WfmOffset-SP" : [-0.05, 0.05], # [A] + "BO-Fam:PS-SF:WfmOffset-SP" : [-0.05, 0.05], # [A] + "BO-Fam:PS-B-1:WfmOffset-SP" : [-0.05, 0.05], # [A] + "BO-Fam:PS-B-2:WfmOffset-SP" : [-0.05, 0.05], # [A] +} + +SIINJEFF_PVNAME = "SI-Glob:AP-CurrInfo:InjEff-Mon" +SIINJ_KNOBS = { + # knob [lim_low, lim_high] unit + "BO-48D:PU-EjeKckr:Voltage-SP" : [-1, 1], # [V] + "TS-01:PU-EjeSeptF:Voltage-SP" : [-1, 1], # [V] + "TS-01:PU-EjeSeptG:Voltage-SP" : [-1, 1], # [V] + "TS-04:PU-InjSeptF:Voltage-SP" : [-1, 1], # [V] + "TS-04:PU-InjSeptG-1:Voltage-SP" : [-1, 1], # [V] + "TS-04:PU-InjSeptG-2:Voltage-SP" : [-1, 1], # [V] + "SI-01SA:PU-InjNLKckr:Voltage-SP" : [-1, 1], # [V] + "TS-04:PS-CV-0:Current-SP" : [-0.25, 0.25], # [A] (check) + "TS-04:PS-CV-1:Current-SP" : [-0.25, 0.25], # [A] + "TS-04:PS-CV-1E2:Current-SP" : [-0.25, 0.25], # [A] + "TS-04:PS-CV-2:Current-SP" : [-0.25, 0.25], # [A] + "RA-RaBO01:RF-LLRF:RmpPhsTop-SP" : [-5, 5], # [deg] +} + + +class InjNudgesBaseParams(_ParamsBaseClass): """.""" def __init__(self): """.""" @@ -20,34 +57,32 @@ def __init__(self): self.num_attempts_per_ref = 5 self.min_topup_current = 198.5 # [mA] self.filename2use = "inj_nudges" - self.knobs_lims = { - # knob [lim_low, lim_high] unit - "BO-01D:PU-InjKckr:Voltage-SP" : [-1, 1], # [V] - "TB-04:PS-CH-1:Current-SP" : [-0.25, 0.25], # [A] - "TB-04:PU-InjSept:Voltage-SP" : [-1, 1], # [V] - "TB-04:PS-CV-1:Current-SP" : [-0.25, 0.25], # [A] - "TB-04:PS-CV-2:Current-SP" : [-0.25, 0.25], # [A] - "LA-RF:LLRF:BUN1:SET_AMP" : [-0.5, 0.5], # [%] - "LA-RF:LLRF:KLY1:SET_AMP" : [-1, 1], # [%] - "LA-RF:LLRF:KLY2:SET_AMP" : [-1, 1], # [%] - "RA-RaBO01:RF-LLRF:RmpPhsBot-SP" : [-5, 5], # [deg] - "BO-Fam:PS-QD:WfmOffset-SP" : [-0.02, 0.02], # [A] - "BO-Fam:PS-QF:WfmOffset-SP" : [-0.02, 0.02], # [A] - "BO-Fam:PS-SD:WfmOffset-SP" : [-0.05, 0.05], # [A] - "BO-Fam:PS-SF:WfmOffset-SP" : [-0.05, 0.05], # [A] - "BO-Fam:PS-B-1:WfmOffset-SP" : [-0.05, 0.05], # [A] - "BO-Fam:PS-B-2:WfmOffset-SP" : [-0.05, 0.05], # [A] - } - self.knobs_pvsnames = sorted(self.knobs_lims.keys()) - self.injeff_pvname = "BO-Glob:AP-CurrInfo:RampEff-Mon" + + self._knobs_lims = None + self.knobs_pvsnames = None + self.low_lims = None + self.upper_lims = None self.si_curr_pvname = "SI-Glob:AP-CurrInfo:Current-Mon" + self.observables_pvs_names = "" + + @property + def knobs_lims(self): + """.""" + return self._knobs_lims + + @knobs_lims.setter + def knobs_lims(self, lims): + """.""" + if not isinstance(lims, dict): + raise ValueError("knobs_lims must be a dictionary") + self._knobs_lims = lims + self.knobs_pvsnames = sorted(self._knobs_lims.keys()) self.low_lims = [ - self.knobs_lims[kn][0] for kn in self.knobs_pvsnames + self._knobs_lims[kn][0] for kn in self.knobs_pvsnames ] self.upper_lims = [ - self.knobs_lims[kn][1] for kn in self.knobs_pvsnames + self._knobs_lims[kn][1] for kn in self.knobs_pvsnames ] - self.observables_pvs_names = "" # Other observable params def __str__(self): """.""" @@ -67,7 +102,7 @@ def __str__(self): stg += "\n" stg += " knob [lim_low, lim_high]\n" for kn in self.knobs_pvsnames: - stg += f"{kn:<30s} : {self.knobs_lims[kn]}\n" + stg += f"{kn:<35s} : {self.knobs_lims[kn]}\n" stg += "\n" stg += "other observables\n" @@ -75,14 +110,39 @@ def __str__(self): stg += f"{pvname:<30s}" return stg + +class BOInjNudgesParams(InjNudgesBaseParams): + """.""" + def __init__(self): + """.""" + super().__init__() + self.injeff_pvname = BOINJEFF_PVNAME + self.knobs_lims = BOINJ_KNOBS + + +class SIInjNudgesParams(InjNudgesBaseParams): + """.""" + def __init__(self): + """.""" + super().__init__() + self.injeff_pvname = SIINJEFF_PVNAME + self.knobs_lims = SIINJ_KNOBS + + class InjNudges(_BaseClass): """.""" - def __init__(self, isonline=True): + def __init__(self, isonline=True, inj_system="BO"): """.""" super().__init__( self, target=self.do_measure, isonline=isonline ) - self.params = InjNudgesParams() + if inj_system.lower() == "bo": + self.params = BOInjNudgesParams() + elif inj_system.lower() == "si": + self.params = SIInjNudgesParams() + else: + raise ValueError("Injection system must be SI or BO.") + self.ref_injeff_mean = None self.ref_injeff_std = None From 16d4c88e66027f40021de2dffbc5e78f4a807dc0 Mon Sep 17 00:00:00 2001 From: Matheus Date: Mon, 7 Apr 2025 16:46:46 -0300 Subject: [PATCH 06/10] COMMISS.INJNDGE.ENH: sort imports & make public imports private --- apsuite/commisslib/inj_nudges.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/apsuite/commisslib/inj_nudges.py b/apsuite/commisslib/inj_nudges.py index 29afb0d4..523c1062 100644 --- a/apsuite/commisslib/inj_nudges.py +++ b/apsuite/commisslib/inj_nudges.py @@ -1,10 +1,11 @@ +"""Module for online nudging of injection efficiency knobs.""" import threading as _threading import time as _time import numpy as _np -from siriuspy.devices import EVG -from siriuspy.epics import PV -from siriuspy.clientarch import Time +from siriuspy.clientarch import Time as _Time +from siriuspy.devices import EVG as _EVG +from siriuspy.epics import PV as _PV from ..utils import ParamsBaseClass as _ParamsBaseClass, \ ThreadedMeasBaseClass as _BaseClass @@ -158,13 +159,13 @@ def connect_pvs_and_evg(self): pvs = {} for pv_name in pvs_names: - pv = PV(pv_name) + pv = _PV(pv_name) pv.wait_for_connection(timeout=self.params.pv_connection_timeout) print(f"PV {pv_name:<35s} connected: {pv.connected}") pvs[pv_name] = pv self.pvs = pvs - self.devices = {"evg": EVG()} + self.devices = {"evg": _EVG()} def get_pos(self): """Returns knobs positions as a dict of (timestamp, value).""" @@ -222,7 +223,7 @@ def on_change( ref_mean, ref_sigma, **kwargs ): """Callback function to be added to the injeff PV.""" - tmstp = Time.fromtimestamp(_time.time()) + tmstp = _Time.fromtimestamp(_time.time()) datetime = tmstp.strftime("%Y-%m-%d %H:%M:%S") print(f"\t\t{datetime} inj. eff.: {value:3.2f}%, SI curr.:") From 11f8fdf577259e7f33416ffd8e085e321b037f62 Mon Sep 17 00:00:00 2001 From: Matheus Date: Thu, 17 Apr 2025 10:05:56 -0300 Subject: [PATCH 07/10] COMMISS.INJNDG.ENH: add BO inj observables (temperatures) --- apsuite/commisslib/inj_nudges.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/apsuite/commisslib/inj_nudges.py b/apsuite/commisslib/inj_nudges.py index 523c1062..58cfe3f1 100644 --- a/apsuite/commisslib/inj_nudges.py +++ b/apsuite/commisslib/inj_nudges.py @@ -30,6 +30,17 @@ "BO-Fam:PS-B-2:WfmOffset-SP" : [-0.05, 0.05], # [A] } +BOINJ_OBSERVABLES = [ + "LINAC:Temperatura-Mon", # LINAC env temp + "LA-CN:H1MPS-1:A1Temp1", # Accelerating strurctures + "LA-CN:H1MPS-1:K1Temp1", # (K1 body) + "LA-CN:H1MPS-1:K1Temp2", # (K1 Waveguide) + "LA-CN:H1MPS-1:K2Temp1", # (K2 body) + "LA-CN:H1MPS-1:K2Temp2", # (K2 Waveguide) + "TB-04:PU-InjSept-BG:Temp-Mon", # septa + "TB-04:PU-InjSept-ED:Temp-Mon", # septa +] + SIINJEFF_PVNAME = "SI-Glob:AP-CurrInfo:InjEff-Mon" SIINJ_KNOBS = { # knob [lim_low, lim_high] unit @@ -47,6 +58,10 @@ "RA-RaBO01:RF-LLRF:RmpPhsTop-SP" : [-5, 5], # [deg] } +SIINJ_OBSERVABLES = [ + # to be implemented +] + class InjNudgesBaseParams(_ParamsBaseClass): """.""" @@ -119,6 +134,7 @@ def __init__(self): super().__init__() self.injeff_pvname = BOINJEFF_PVNAME self.knobs_lims = BOINJ_KNOBS + self.observables_pvs_names = BOINJ_OBSERVABLES class SIInjNudgesParams(InjNudgesBaseParams): @@ -128,6 +144,7 @@ def __init__(self): super().__init__() self.injeff_pvname = SIINJEFF_PVNAME self.knobs_lims = SIINJ_KNOBS + self.observables_pvs_names = SIINJ_OBSERVABLES class InjNudges(_BaseClass): @@ -156,6 +173,7 @@ def connect_pvs_and_evg(self): pvs_names = [self.params.injeff_pvname] pvs_names += [self.params.si_curr_pvname] pvs_names += self.params.knobs_pvsnames + pvs_names += self.params.observables_pvs_names pvs = {} for pv_name in pvs_names: From 5e60f4a3b751f32693fa15a45133419be6715c7f Mon Sep 17 00:00:00 2001 From: Matheus Date: Thu, 17 Apr 2025 16:27:34 -0300 Subject: [PATCH 08/10] COMMISS.INJNDGE.STY: improve params print method --- apsuite/commisslib/inj_nudges.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apsuite/commisslib/inj_nudges.py b/apsuite/commisslib/inj_nudges.py index 58cfe3f1..9fcf46a2 100644 --- a/apsuite/commisslib/inj_nudges.py +++ b/apsuite/commisslib/inj_nudges.py @@ -116,6 +116,7 @@ def __str__(self): stg += stmp("filename2use", self.filename2use, "") stg += stmp("injeff_pvname", self.injeff_pvname, "") stg += "\n" + stg += "Knobs & limits\n" stg += " knob [lim_low, lim_high]\n" for kn in self.knobs_pvsnames: stg += f"{kn:<35s} : {self.knobs_lims[kn]}\n" @@ -123,7 +124,7 @@ def __str__(self): stg += "\n" stg += "other observables\n" for pvname in self.observables_pvs_names: - stg += f"{pvname:<30s}" + stg += f"{pvname:<30s}\n" return stg From 54027256b2e323408db483cf6972cc14654b168c Mon Sep 17 00:00:00 2001 From: Matheus Date: Wed, 30 Apr 2025 13:28:49 -0300 Subject: [PATCH 09/10] COMMISS.INJNDGE.ENH: add BO ramp DCCT wfm - introduces `use_dcct_wfm` arg for BOInjNudgesParams, setting ramp wfm as inj. eff. PV or observable PV only. --- apsuite/commisslib/inj_nudges.py | 50 +++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/apsuite/commisslib/inj_nudges.py b/apsuite/commisslib/inj_nudges.py index 9fcf46a2..de2bf345 100644 --- a/apsuite/commisslib/inj_nudges.py +++ b/apsuite/commisslib/inj_nudges.py @@ -10,7 +10,10 @@ from ..utils import ParamsBaseClass as _ParamsBaseClass, \ ThreadedMeasBaseClass as _BaseClass +import warnings + BOINJEFF_PVNAME = "BO-Glob:AP-CurrInfo:RampEff-Mon" +BOINJ_DCCT_WFM = "BO-35D:DI-DCCT:RawReadings-Mon" BOINJ_KNOBS = { # knob [lim_low, lim_high] unit "BO-01D:PU-InjKckr:Voltage-SP" : [-1, 1], # [V] @@ -130,12 +133,37 @@ def __str__(self): class BOInjNudgesParams(InjNudgesBaseParams): """.""" - def __init__(self): + def __init__(self, use_dcct_wfm=False): """.""" super().__init__() - self.injeff_pvname = BOINJEFF_PVNAME self.knobs_lims = BOINJ_KNOBS - self.observables_pvs_names = BOINJ_OBSERVABLES + self._default_injeff_pvname = BOINJEFF_PVNAME + self._dcct_wfm_pvname = BOINJ_DCCT_WFM + self._base_observables = BOINJ_OBSERVABLES + + self._use_dcct_wfm = None + self.use_dcct_wfm = use_dcct_wfm + + @property + def use_dcct_wfm(self): + """.""" + return self._use_dcct_wfm + + @use_dcct_wfm.setter + def use_dcct_wfm(self, val): + # TODO: currently, setting this to True/False changes the + # observables_pvs_names in such a manner that any changes made by the + # user are lost and the default observables are restored. + self._use_dcct_wfm = val + if val: + self.injeff_pvname = self._dcct_wfm_pvname + self.observables_pvs_names = self._base_observables + else: + self.injeff_pvname = self._default_injeff_pvname + obs = list(self._base_observables) + if self._dcct_wfm_pvname not in obs: + obs.append(self._dcct_wfm_pvname) + self.observables_pvs_names = obs class SIInjNudgesParams(InjNudgesBaseParams): @@ -150,15 +178,18 @@ def __init__(self): class InjNudges(_BaseClass): """.""" - def __init__(self, isonline=True, inj_system="BO"): + def __init__(self, isonline=True, inj_system="BO", use_dcct_wfm=False): """.""" super().__init__( self, target=self.do_measure, isonline=isonline ) if inj_system.lower() == "bo": - self.params = BOInjNudgesParams() + self.params = BOInjNudgesParams(use_dcct_wfm=use_dcct_wfm) elif inj_system.lower() == "si": self.params = SIInjNudgesParams() + warnings.warn( + "use_dcct_wfm not supported for SI, ignoring it", stacklevel=2 + ) else: raise ValueError("Injection system must be SI or BO.") @@ -230,7 +261,8 @@ def acquire_efficiencies(self, ref_mean=None, ref_sigma=None): ) event.wait(timeout=(60 + 2) * self.params.num_inj_samples) injeff_pv.clear_callbacks() - + if len(effs) == 0: + return None mean, sigma = _np.mean(effs), _np.std(effs) print(f"\t\tmean injeff {mean:3.2f} +- {sigma:.2f} %") @@ -244,7 +276,11 @@ def on_change( """Callback function to be added to the injeff PV.""" tmstp = _Time.fromtimestamp(_time.time()) datetime = tmstp.strftime("%Y-%m-%d %H:%M:%S") - print(f"\t\t{datetime} inj. eff.: {value:3.2f}%, SI curr.:") + measurement = "inj. eff." + if getattr(self.params, "use_dcct_wfm", False): + value = _np.linalg.norm(value) + measurement = "avg. rms dcct wfm" + print(f"\t\t{datetime} {measurement}.: {value:3.2f}%, SI curr.:") pvvals.append(self.get_pvs_tmtsp_and_vals()) tim.append(timestamp) From 758c0a6aca2e0265db8cdf1baf0f1c434734a4b6 Mon Sep 17 00:00:00 2001 From: Matheus Date: Wed, 30 Apr 2025 18:17:56 -0300 Subject: [PATCH 10/10] COMMISS.INJNDGE.BUG: fix setting up callback functions for injeffs - fixes the `_on_change` function - minor fixes and style conventions --- apsuite/commisslib/inj_nudges.py | 76 ++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/apsuite/commisslib/inj_nudges.py b/apsuite/commisslib/inj_nudges.py index de2bf345..b4ae7cd3 100644 --- a/apsuite/commisslib/inj_nudges.py +++ b/apsuite/commisslib/inj_nudges.py @@ -74,7 +74,7 @@ def __init__(self): self.pv_connection_timeout = 3 self.num_inj_samples = 3 self.num_attempts_per_ref = 5 - self.min_topup_current = 198.5 # [mA] + self.topup_current = 198.5 # [mA] self.filename2use = "inj_nudges" self._knobs_lims = None @@ -115,7 +115,7 @@ def __str__(self): ) stg += dtmp("num_inj_samples", self.num_inj_samples, "") stg += dtmp("num_attempts_per_ref", self.num_attempts_per_ref, "") - stg += ftmp("min_topup_current", self.min_topup_current, "mA") + stg += ftmp("topup_current", self.topup_current, "mA") stg += stmp("filename2use", self.filename2use, "") stg += stmp("injeff_pvname", self.injeff_pvname, "") stg += "\n" @@ -158,12 +158,15 @@ def use_dcct_wfm(self, val): if val: self.injeff_pvname = self._dcct_wfm_pvname self.observables_pvs_names = self._base_observables + self.measurement, self.units = "rms dcct wfm", "mA" else: self.injeff_pvname = self._default_injeff_pvname obs = list(self._base_observables) if self._dcct_wfm_pvname not in obs: obs.append(self._dcct_wfm_pvname) self.observables_pvs_names = obs + self.measurement, self.units = "inj. eff.", "%" + class SIInjNudgesParams(InjNudgesBaseParams): @@ -249,50 +252,55 @@ def get_knobs_nudges(self): def acquire_efficiencies(self, ref_mean=None, ref_sigma=None): """.""" + def _on_change( + timestamp, value, tim, effs, pvvals, event, + ref_mean, ref_sigma, si_curr_pv, **kwargs + ): + """Callback function to be added to the injeff PV.""" + tmstp = _Time.fromtimestamp(_time.time()) + dttime = tmstp.strftime("%Y-%m-%d %H:%M:%S") + + if getattr(self.params, "use_dcct_wfm", False): + value = value[:500] # discard abrupt ending of the ramp + value = _np.linalg.norm(value) / _np.sqrt(len(value)) + meas, units = self.params.measurement, self.params.units + stg = f"\t\t{dttime} {meas}: {value:3.2f} {units}" + stg += f", SI curr.: {si_curr_pv.value:3.1f} mA" + print(stg) + + pvvals.append(self.get_pvs_tmtsp_and_vals()) + tim.append(timestamp) + effs.append(value) + + if len(effs) >= self.params.num_inj_samples: + event.set() + if None in (ref_mean, ref_sigma): + return # What to do? + if len(effs) > 1 and (_np.mean(effs) < ref_mean - ref_sigma): + event.set() + print("\tacquiring inj. effs. ...") injeff_pv = self.pvs[self.params.injeff_pvname] + si_curr_pv = self.pvs[self.params.si_curr_pvname] tim, effs, pvvals = [], [], [] event = _threading.Event() # signals acqs. are finished injeff_pv.add_callback( - self, self.on_change, tim=tim, effs=effs, pvvals=pvvals, - event=event, ref_mean=ref_mean, ref_sigma=ref_sigma + _on_change, tim=tim, effs=effs, pvvals=pvvals, + event=event, ref_mean=ref_mean, ref_sigma=ref_sigma, + si_curr_pv=si_curr_pv ) event.wait(timeout=(60 + 2) * self.params.num_inj_samples) injeff_pv.clear_callbacks() if len(effs) == 0: return None mean, sigma = _np.mean(effs), _np.std(effs) - - print(f"\t\tmean injeff {mean:3.2f} +- {sigma:.2f} %") + meas, unit = self.params.measurement, self.params.units + print(f"\t\tmean {meas} {mean:3.2f} +- {sigma:.2f} {unit}") print("\tacquisitions finished.") return tim, effs, mean, sigma, pvvals - def on_change( - self, timestamp, value, tim, effs, pvvals, event, - ref_mean, ref_sigma, **kwargs - ): - """Callback function to be added to the injeff PV.""" - tmstp = _Time.fromtimestamp(_time.time()) - datetime = tmstp.strftime("%Y-%m-%d %H:%M:%S") - measurement = "inj. eff." - if getattr(self.params, "use_dcct_wfm", False): - value = _np.linalg.norm(value) - measurement = "avg. rms dcct wfm" - print(f"\t\t{datetime} {measurement}.: {value:3.2f}%, SI curr.:") - - pvvals.append(self.get_pvs_tmtsp_and_vals()) - tim.append(timestamp) - effs.append(value) - - if len(effs) >= self.params.num_inj_samples: - event.set() - if None in (ref_mean, ref_sigma): - return # What to do? - if len(effs) > 1 and (_np.mean(effs) < ref_mean - ref_sigma): - event.set() - def recover_topup(self, pos_good, sleep_time=30): """.""" print("") @@ -330,12 +338,11 @@ def do_measure(self): evg = self.devices["evg"] while True: - delta_pos = self.get_knobs_nudges() - i = _np.random.randint(len(delta_pos)) dposi = float(delta_pos[i]) knobi_name = self.params.knobs_pvsnames[i] + print("") print(f"Nudging {knobi_name} in {dposi:2.2f}") posi0 = pos[knobi_name].copy() @@ -369,10 +376,11 @@ def do_measure(self): self.data["pvvals"] = pvvals if mean_injeff - sigma_injeff >= ref_mean - ref_sigma: - print(f"\tchanges in {knobi_name} improved injeff!") + meas = self.params.measurement + print(f"\tchanges in {knobi_name} improved {meas}!") ref_mean, ref_sigma = mean_injeff, sigma_injeff fails_w_same_ref = 0 - print(f"\tnew reference injeff: {ref_mean:3.3f} %") + print(f"\tnew reference {meas}: {ref_mean:3.3f} %") else: print(f"\treverting changes in {knobi_name}...") fails_w_same_ref += 1