From 2167f01938775fbed16e349329cfdd2a0bde4389 Mon Sep 17 00:00:00 2001 From: THuckemann Date: Mon, 16 Sep 2024 14:54:24 +0200 Subject: [PATCH 1/6] Parameters that are not settable will not be ramped anymore. Devices set_state, set_defaults and set_stored_values now ramp parameters by default. --- src/qumada/measurement/device_object.py | 37 +++++++++++++++++-------- src/qumada/utils/ramp_parameter.py | 7 ++++- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/qumada/measurement/device_object.py b/src/qumada/measurement/device_object.py index 8c747b5c..f5dcaed1 100644 --- a/src/qumada/measurement/device_object.py +++ b/src/qumada/measurement/device_object.py @@ -49,6 +49,7 @@ def __init__( self.station = station self.buffer_script_setup = {} self.states = {} + self.ramp: bool = True def add_terminal(self, terminal_name: str, type: str | None = None, terminal_data: dict | None = {}): if terminal_name not in self.terminals.keys(): @@ -82,7 +83,7 @@ def update_terminal_parameters(self): for param in mapping.keys(): self.terminals[terminal].update_terminal_parameter(param) - def save_defaults(self): + def save_defaults(self, ramp = None, **kwargs): """ Saves current values as default for all Terminals and their parameters """ @@ -96,22 +97,28 @@ def save_state(self, name: str): """ self.states[name] = self.save_to_dict(priorize_stored_value=False) - def set_state(self, name: str): + def set_state(self, name: str, ramp = None, **kwargs): + if ramp is None: + ramp = self.ramp self.load_from_dict(self.states[name]) - self.set_stored_values() + self.set_stored_values(ramp = ramp, **kwargs) - def set_stored_values(self): + def set_stored_values(self, ramp = None, **kwargs): + if ramp is None: + ramp = self.ramp for terminal in self.terminals.values(): for param in terminal.terminal_parameters.values(): param.set_stored_value() - def set_defaults(self): + def set_defaults(self, ramp = None, **kwargs): """ Sets all Terminals and their parameters to their default values """ + if ramp is None: + ramp = self.ramp for terminal in self.terminals.values(): for param in terminal.terminal_parameters.values(): - param.set_default() + param.set_default(ramp = ramp, **kwargs) def voltages(self): """ @@ -515,7 +522,7 @@ def value(self): @value.setter def value(self, value): - if self.locked: + if self.locked is True: raise Exception(f"Parameter {self.name} of Terminal {self._parent.name} is locked and cannot be set!") return @@ -679,31 +686,37 @@ def save_default(self): logger.warning(f"{e} was raised when trying to save default value of {self.name}") pass - def set_default(self): + def set_default(self, ramp = True, **kwargs): """ Sets value to default value """ if self.default_value is not None: try: - self.value = self.default_value + if ramp is True: + self.ramp(self.default_value, **kwargs) + else: + self.value = self.default_value except NotImplementedError as e: logger.debug(f"{e} was raised and ignored") else: logger.warning(f"No default value set for parameter {self.name}") - def set_stored_value(self): + def set_stored_value(self, ramp = True, **kwargs): """ Sets value to stored value from dict """ if self._stored_value is not None: try: - self.value = self._stored_value + if ramp is True: + self.ramp(self._stored_value, **kwargs) + else: + self.value = self._stored_value except NotImplementedError as e: logger.debug(f"{e} was raised and ignored") else: logger.warning(f"No stored value set for parameter {self.name}") - def __call__(self, value=None): + def __call__(self, value=None, ramp = None): if value is None: return self.value else: diff --git a/src/qumada/utils/ramp_parameter.py b/src/qumada/utils/ramp_parameter.py index eb89dc57..444425a8 100644 --- a/src/qumada/utils/ramp_parameter.py +++ b/src/qumada/utils/ramp_parameter.py @@ -83,9 +83,14 @@ def ramp_parameter( """ # time.sleep(0.1) + if parameter._settable is False: + LOG.warning(f"{parameter} is not _settable and cannot be ramped!") + return False LOG.debug(f"parameter: {parameter}") current_value = parameter.get() LOG.debug(f"current value: {current_value}") + LOG.debug(f"ramp rate: {ramp_rate}") + LOG.debug(f"ramp time: {ramp_time}") if isinstance(current_value, float): LOG.debug(f"target: {target}") @@ -99,7 +104,7 @@ def ramp_parameter( num_points = int(abs(current_value - float(target)) / (ramp_rate * setpoint_intervall)) + 2 if ramp_time is not None and ramp_time < abs(current_value - float(target)) / ramp_rate: print( - "Ramp rate is to low to reach target value in specified" + "Ramp rate of is to low to reach target value in specified" "max ramp time. Adapting ramp rate to match ramp time" ) return ramp_parameter( From 93971a883fb0290ede2d6f906488ceb30bcfc158 Mon Sep 17 00:00:00 2001 From: THuckemann Date: Mon, 16 Sep 2024 14:55:29 +0200 Subject: [PATCH 2/6] Some MFLI Parameters were not marked as not settable. Fixed this... --- src/qumada/instrument/custom_drivers/ZI/MFLI.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/qumada/instrument/custom_drivers/ZI/MFLI.py b/src/qumada/instrument/custom_drivers/ZI/MFLI.py index 5374bf5a..afb371f4 100644 --- a/src/qumada/instrument/custom_drivers/ZI/MFLI.py +++ b/src/qumada/instrument/custom_drivers/ZI/MFLI.py @@ -84,7 +84,7 @@ def __init__( unit="V", get_cmd=lambda: demod0.sample()["y"], get_parser=float, - set_cmd=None, + set_cmd=False, docstring="X component of sample measured by demod1", ) self.voltage_y_component.signal_name = ("demod0", "y") @@ -95,7 +95,7 @@ def __init__( unit="V", get_cmd=lambda: demod0.sample()["y"], get_parser=float, - set_cmd=None, + set_cmd=False, docstring="X component of sample measured by demod1", ) self.voltage_x_component.signal_name = ("demod0", "x") @@ -106,7 +106,7 @@ def __init__( unit="A", get_cmd=lambda: np.sqrt(demod0.sample()["x"] ** 2 + demod0.sample()["y"] ** 2), get_parser=float, - set_cmd=None, + set_cmd=False, docstring="Absolute current as measured by demod0", ) self.current.signal_name = ("demod0", "r") @@ -116,7 +116,7 @@ def __init__( unit="A", get_cmd=lambda: demod0.sample()["x"], get_parser=float, - set_cmd=None, + set_cmd=False, docstring="X component of sample measured by demod1", ) self.current_x_component.signal_name = ("demod0", "x") @@ -127,7 +127,7 @@ def __init__( unit="rad", get_cmd=lambda: demod0.sample()["phase"], get_parser=float, - set_cmd=None, + set_cmd=False, docstring="Phase of the measured current in radians", ) self.phase.signal_name = ("demod0", "phase") @@ -137,7 +137,7 @@ def __init__( unit="A", get_cmd=lambda: demod0.sample()["y"], get_parser=float, - set_cmd=None, + set_cmd=False, docstring="X component of sample measured by demod1", ) self.current_y_component.signal_name = ("demod0", "y") @@ -205,7 +205,7 @@ def __init__( name="demod0_aux_in_1", label="Demod0 AuxIn 1", get_cmd=lambda: demod0.sample()["auxin0"], - set_cmd=None, + set_cmd=False, get_parser=float, docstring="Aux In 1 of demod0", ) @@ -215,7 +215,7 @@ def __init__( name="demod0_aux_in_2", label="Demod0 AuxIn 2", get_cmd=lambda: demod0.sample()["auxin1"], - set_cmd=None, + set_cmd=False, get_parser=float, docstring="Aux In 2 of demod0", ) From eef587d6f37e24bbf319593bce351fe14f838eb3 Mon Sep 17 00:00:00 2001 From: THuckemann Date: Mon, 16 Sep 2024 15:02:44 +0200 Subject: [PATCH 3/6] Updated Documentation --- docs/device_object.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/device_object.rst b/docs/device_object.rst index 65fda83b..22692220 100644 --- a/docs/device_object.rst +++ b/docs/device_object.rst @@ -143,8 +143,11 @@ in the function call of measurement scripts, you can set the argument priorize_s Another important feature is the possibility to save and load device working points. To store a certain configuration as your default working point, use device.save_defaults. This stores all parameter values (of parameters that can be set). With device.set_defaults() you can reset it to the stored configuration. Alternatively you can use "device.save_state(name)" and "device.set_state(name)" to store and set multiple working points with -custom names. They can also be accessed via "device.states" in case you forgot the name. Be aware that the set commands currently set the -parameters instead of ramping to them, which can endanger your device if it is sensitive to voltage jumps. +custom names. They can also be accessed via "device.states" in case you forgot the name. +For all of those methods the parameters are ramped to the final state by default (with the default QuMada ramp rate). You can use the argument "ramp = False" to avoid this, or use keyword +arguments (ramp_rate, duration) to adjust the ramp speed when calling the methods. Alternatively, you can set the parameter "device.ramp" to True or False in order to control the behaviour +for the complete device. + ############### From 7ae35ab212fe81e412ffc54f89bf78f1c166ad7e Mon Sep 17 00:00:00 2001 From: THuckemann Date: Mon, 16 Sep 2024 15:26:46 +0200 Subject: [PATCH 4/6] If target value is already very close to current values, ramps will not be performed to save time. --- src/qumada/utils/ramp_parameter.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/qumada/utils/ramp_parameter.py b/src/qumada/utils/ramp_parameter.py index 444425a8..0a0f5f7a 100644 --- a/src/qumada/utils/ramp_parameter.py +++ b/src/qumada/utils/ramp_parameter.py @@ -25,6 +25,8 @@ import logging import time +from math import isclose + from qumada.utils.generate_sweeps import generate_sweep LOG = logging.getLogger(__name__) @@ -41,6 +43,7 @@ def ramp_parameter( ramp_time: float | None = None, setpoint_intervall: float = 0.1, valid_units: str = "all", + tolerance: float = 1e-5, **kwargs, ): """ @@ -68,6 +71,9 @@ def ramp_parameter( The default is 0.1. valid_units : str, optional Not used yet. The default is "all". + tolerance: float, optional + If abs(current_value- target_value) < tolerance*max(current_value, target_value) + no ramp is done. Default 1e-5. **kwargs : TYPE DESCRIPTION. @@ -82,18 +88,21 @@ def ramp_parameter( True if sweep was completed, False if it failed. """ - # time.sleep(0.1) if parameter._settable is False: LOG.warning(f"{parameter} is not _settable and cannot be ramped!") return False - LOG.debug(f"parameter: {parameter}") current_value = parameter.get() + LOG.debug(f"parameter: {parameter}") LOG.debug(f"current value: {current_value}") LOG.debug(f"ramp rate: {ramp_rate}") LOG.debug(f"ramp time: {ramp_time}") if isinstance(current_value, float): LOG.debug(f"target: {target}") + if isclose(current_value, target, rel_tol = tolerance): + LOG.debug("Target value is sufficiently close to current_value, no need to ramp") + return True + if not ramp_rate: if not ramp_time: print("Please specify either ramp_time or ramp_speed") From 7abe68cd0ee971230969ad37f1311a5db6684517 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 12:50:48 +0000 Subject: [PATCH 5/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/device_object.rst | 2 +- src/qumada/measurement/device_object.py | 18 +++++++++--------- src/qumada/utils/ramp_parameter.py | 5 ++--- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/docs/device_object.rst b/docs/device_object.rst index 22692220..d5d5cc0c 100644 --- a/docs/device_object.rst +++ b/docs/device_object.rst @@ -143,7 +143,7 @@ in the function call of measurement scripts, you can set the argument priorize_s Another important feature is the possibility to save and load device working points. To store a certain configuration as your default working point, use device.save_defaults. This stores all parameter values (of parameters that can be set). With device.set_defaults() you can reset it to the stored configuration. Alternatively you can use "device.save_state(name)" and "device.set_state(name)" to store and set multiple working points with -custom names. They can also be accessed via "device.states" in case you forgot the name. +custom names. They can also be accessed via "device.states" in case you forgot the name. For all of those methods the parameters are ramped to the final state by default (with the default QuMada ramp rate). You can use the argument "ramp = False" to avoid this, or use keyword arguments (ramp_rate, duration) to adjust the ramp speed when calling the methods. Alternatively, you can set the parameter "device.ramp" to True or False in order to control the behaviour for the complete device. diff --git a/src/qumada/measurement/device_object.py b/src/qumada/measurement/device_object.py index f5dcaed1..e62f77b5 100644 --- a/src/qumada/measurement/device_object.py +++ b/src/qumada/measurement/device_object.py @@ -83,7 +83,7 @@ def update_terminal_parameters(self): for param in mapping.keys(): self.terminals[terminal].update_terminal_parameter(param) - def save_defaults(self, ramp = None, **kwargs): + def save_defaults(self, ramp=None, **kwargs): """ Saves current values as default for all Terminals and their parameters """ @@ -97,20 +97,20 @@ def save_state(self, name: str): """ self.states[name] = self.save_to_dict(priorize_stored_value=False) - def set_state(self, name: str, ramp = None, **kwargs): + def set_state(self, name: str, ramp=None, **kwargs): if ramp is None: ramp = self.ramp self.load_from_dict(self.states[name]) - self.set_stored_values(ramp = ramp, **kwargs) + self.set_stored_values(ramp=ramp, **kwargs) - def set_stored_values(self, ramp = None, **kwargs): + def set_stored_values(self, ramp=None, **kwargs): if ramp is None: ramp = self.ramp for terminal in self.terminals.values(): for param in terminal.terminal_parameters.values(): param.set_stored_value() - def set_defaults(self, ramp = None, **kwargs): + def set_defaults(self, ramp=None, **kwargs): """ Sets all Terminals and their parameters to their default values """ @@ -118,7 +118,7 @@ def set_defaults(self, ramp = None, **kwargs): ramp = self.ramp for terminal in self.terminals.values(): for param in terminal.terminal_parameters.values(): - param.set_default(ramp = ramp, **kwargs) + param.set_default(ramp=ramp, **kwargs) def voltages(self): """ @@ -686,7 +686,7 @@ def save_default(self): logger.warning(f"{e} was raised when trying to save default value of {self.name}") pass - def set_default(self, ramp = True, **kwargs): + def set_default(self, ramp=True, **kwargs): """ Sets value to default value """ @@ -701,7 +701,7 @@ def set_default(self, ramp = True, **kwargs): else: logger.warning(f"No default value set for parameter {self.name}") - def set_stored_value(self, ramp = True, **kwargs): + def set_stored_value(self, ramp=True, **kwargs): """ Sets value to stored value from dict """ @@ -716,7 +716,7 @@ def set_stored_value(self, ramp = True, **kwargs): else: logger.warning(f"No stored value set for parameter {self.name}") - def __call__(self, value=None, ramp = None): + def __call__(self, value=None, ramp=None): if value is None: return self.value else: diff --git a/src/qumada/utils/ramp_parameter.py b/src/qumada/utils/ramp_parameter.py index 0a0f5f7a..ff939ee5 100644 --- a/src/qumada/utils/ramp_parameter.py +++ b/src/qumada/utils/ramp_parameter.py @@ -24,7 +24,6 @@ import logging import time - from math import isclose from qumada.utils.generate_sweeps import generate_sweep @@ -73,7 +72,7 @@ def ramp_parameter( Not used yet. The default is "all". tolerance: float, optional If abs(current_value- target_value) < tolerance*max(current_value, target_value) - no ramp is done. Default 1e-5. + no ramp is done. Default 1e-5. **kwargs : TYPE DESCRIPTION. @@ -99,7 +98,7 @@ def ramp_parameter( if isinstance(current_value, float): LOG.debug(f"target: {target}") - if isclose(current_value, target, rel_tol = tolerance): + if isclose(current_value, target, rel_tol=tolerance): LOG.debug("Target value is sufficiently close to current_value, no need to ramp") return True From dba060dd9657388a8f651b5c1828c62b73264fe5 Mon Sep 17 00:00:00 2001 From: THuckemann Date: Mon, 7 Oct 2024 15:03:20 +0200 Subject: [PATCH 6/6] Ramp rate warning now show parameter name. --- src/qumada/utils/ramp_parameter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qumada/utils/ramp_parameter.py b/src/qumada/utils/ramp_parameter.py index ff939ee5..834b4f68 100644 --- a/src/qumada/utils/ramp_parameter.py +++ b/src/qumada/utils/ramp_parameter.py @@ -112,7 +112,7 @@ def ramp_parameter( num_points = int(abs(current_value - float(target)) / (ramp_rate * setpoint_intervall)) + 2 if ramp_time is not None and ramp_time < abs(current_value - float(target)) / ramp_rate: print( - "Ramp rate of is to low to reach target value in specified" + f"Ramp rate of {param} is to low to reach target value in specified" "max ramp time. Adapting ramp rate to match ramp time" ) return ramp_parameter(