Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/improve ramping #98

Merged
merged 6 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
self.station = station
self.buffer_script_setup = {}
self.states = {}
self.ramp: bool = True

Check warning on line 52 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L52

Added line #L52 was not covered by tests

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 @@
for param in mapping.keys():
self.terminals[terminal].update_terminal_parameter(param)

def save_defaults(self):
def save_defaults(self, ramp=None, **kwargs):

Check warning on line 86 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L86

Added line #L86 was not covered by tests
"""
Saves current values as default for all Terminals and their parameters
"""
Expand All @@ -96,22 +97,28 @@
"""
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

Check warning on line 102 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L100-L102

Added lines #L100 - L102 were not covered by tests
self.load_from_dict(self.states[name])
self.set_stored_values()
self.set_stored_values(ramp=ramp, **kwargs)

Check warning on line 104 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L104

Added line #L104 was not covered by tests

def set_stored_values(self):
def set_stored_values(self, ramp=None, **kwargs):
if ramp is None:
ramp = self.ramp

Check warning on line 108 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L106-L108

Added lines #L106 - L108 were not covered by tests
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):

Check warning on line 113 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L113

Added line #L113 was not covered by tests
"""
Sets all Terminals and their parameters to their default values
"""
if ramp is None:
ramp = self.ramp

Check warning on line 118 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L117-L118

Added lines #L117 - L118 were not covered by tests
for terminal in self.terminals.values():
for param in terminal.terminal_parameters.values():
param.set_default()
param.set_default(ramp=ramp, **kwargs)

Check warning on line 121 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L121

Added line #L121 was not covered by tests

def voltages(self):
"""
Expand Down Expand Up @@ -515,7 +522,7 @@

@value.setter
def value(self, value):
if self.locked:
if self.locked is True:

Check warning on line 525 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L525

Added line #L525 was not covered by tests
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 @@
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):

Check warning on line 689 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L689

Added line #L689 was not covered by tests
"""
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)

Check warning on line 696 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L695-L696

Added lines #L695 - L696 were not covered by tests
else:
self.value = self.default_value

Check warning on line 698 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L698

Added line #L698 was not covered by tests
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):

Check warning on line 704 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L704

Added line #L704 was not covered by tests
"""
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)

Check warning on line 711 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L710-L711

Added lines #L710 - L711 were not covered by tests
else:
self.value = self._stored_value

Check warning on line 713 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L713

Added line #L713 was not covered by tests
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):

Check warning on line 719 in src/qumada/measurement/device_object.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/measurement/device_object.py#L719

Added line #L719 was not covered by tests
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 @@
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 @@
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 @@
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

Check warning on line 92 in src/qumada/utils/ramp_parameter.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/utils/ramp_parameter.py#L90-L92

Added lines #L90 - L92 were not covered by tests
current_value = parameter.get()
LOG.debug(f"parameter: {parameter}")

Check warning on line 94 in src/qumada/utils/ramp_parameter.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/utils/ramp_parameter.py#L94

Added line #L94 was not covered by tests
LOG.debug(f"current value: {current_value}")
LOG.debug(f"ramp rate: {ramp_rate}")
LOG.debug(f"ramp time: {ramp_time}")

Check warning on line 97 in src/qumada/utils/ramp_parameter.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/utils/ramp_parameter.py#L96-L97

Added lines #L96 - L97 were not covered by tests

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

Check warning on line 103 in src/qumada/utils/ramp_parameter.py

View check run for this annotation

Codecov / codecov/patch

src/qumada/utils/ramp_parameter.py#L101-L103

Added lines #L101 - L103 were not covered by tests

if not ramp_rate:
if not ramp_time:
print("Please specify either ramp_time or ramp_speed")
Expand All @@ -99,7 +112,7 @@
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
Loading