Skip to content

Commit

Permalink
Merge pull request #98 from qutech/feature/improve_ramping
Browse files Browse the repository at this point in the history
Feature/improve ramping
  • Loading branch information
THuckemann authored Oct 7, 2024
2 parents cfa5d46 + dba060d commit f4e413a
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 25 deletions.
7 changes: 5 additions & 2 deletions docs/device_object.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.



###############
Expand Down
16 changes: 8 additions & 8 deletions src/qumada/instrument/custom_drivers/ZI/MFLI.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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")
Expand All @@ -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")
Expand All @@ -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")
Expand All @@ -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")
Expand All @@ -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")
Expand Down Expand Up @@ -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",
)
Expand All @@ -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",
)
Expand Down
37 changes: 25 additions & 12 deletions src/qumada/measurement/device_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down Expand Up @@ -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
"""
Expand All @@ -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):
"""
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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:
Expand Down
19 changes: 16 additions & 3 deletions src/qumada/utils/ramp_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import logging
import time
from math import isclose

from qumada.utils.generate_sweeps import generate_sweep

Expand All @@ -41,6 +42,7 @@ def ramp_parameter(
ramp_time: float | None = None,
setpoint_intervall: float = 0.1,
valid_units: str = "all",
tolerance: float = 1e-5,
**kwargs,
):
"""
Expand Down Expand Up @@ -68,6 +70,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.
Expand All @@ -82,13 +87,21 @@ def ramp_parameter(
True if sweep was completed, False if it failed.
"""
# time.sleep(0.1)
LOG.debug(f"parameter: {parameter}")
if parameter._settable is False:
LOG.warning(f"{parameter} is not _settable and cannot be ramped!")
return False
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")
Expand All @@ -99,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 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(
Expand Down

0 comments on commit f4e413a

Please sign in to comment.