From 0056b4001037eef0e3d143ed3a2d9fab47de62ec Mon Sep 17 00:00:00 2001 From: Serwan Asaad Date: Wed, 10 Apr 2024 16:10:01 +0200 Subject: [PATCH 1/2] Add set_dc_offset --- quam/components/channels.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/quam/components/channels.py b/quam/components/channels.py index f139ee72..6482116e 100644 --- a/quam/components/channels.py +++ b/quam/components/channels.py @@ -1,5 +1,5 @@ from dataclasses import field -from typing import ClassVar, Dict, List, Optional, Tuple, Union +from typing import ClassVar, Dict, List, Literal, Optional, Tuple, Union import warnings from quam.components.hardware import BaseFrequencyConverter, Mixer, LocalOscillator @@ -17,6 +17,7 @@ measure, dual_demod, declare, + set_dc_offset, fixed, frame_rotation, ) @@ -409,6 +410,18 @@ class SingleChannel(Channel): opx_output_offset: float = None intermediate_frequency: float = None + def set_dc_offset(self, voltage: QuaNumberType): + """Set the DC offset of an element's input to the given value. + This value will remain the DC offset until changed or until the Quantum Machine + is closed. + + Args: + voltage (QuaNumberType): The DC offset to set the input to. + This is limited by the OPX output voltage range. + The number can be a QUA variable + """ + set_dc_offset(element=self.name, element_input="single", offset=voltage) + def apply_to_config(self, config: dict): """Adds this SingleChannel to the QUA configuration. @@ -558,6 +571,19 @@ def mixer(self) -> Optional[Mixer]: def rf_frequency(self): return self.frequency_converter_up.LO_frequency + self.intermediate_frequency + def set_dc_offset(self, voltage: QuaNumberType, element_input: Literal["I", "Q"]): + """Set the DC offset of an element's input to the given value. + This value will remain the DC offset until changed or until the Quantum Machine + is closed. + + Args: + voltage (QuaNumberType): The DC offset to set the input to. + This is limited by the OPX output voltage range. + The number can be a QUA variable + element_input (Literal["I", "Q"]): The element input to set the offset for. + """ + set_dc_offset(element=self.name, element_input=element_input, offset=voltage) + def apply_to_config(self, config: dict): """Adds this IQChannel to the QUA configuration. From 2d66d26a59de54c20fbc76f1dd1c59cd1338ec9b Mon Sep 17 00:00:00 2001 From: Serwan Asaad Date: Wed, 10 Apr 2024 16:30:33 +0200 Subject: [PATCH 2/2] add tests for set_dc_offset --- quam/components/channels.py | 19 ++++++++----- tests/components/channels/test_IQ_channel.py | 27 +++++++++++++++++++ .../channels/test_single_channel.py | 13 +++++++++ 3 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 tests/components/channels/test_IQ_channel.py diff --git a/quam/components/channels.py b/quam/components/channels.py index 6482116e..b9d8f505 100644 --- a/quam/components/channels.py +++ b/quam/components/channels.py @@ -410,17 +410,17 @@ class SingleChannel(Channel): opx_output_offset: float = None intermediate_frequency: float = None - def set_dc_offset(self, voltage: QuaNumberType): + def set_dc_offset(self, offset: QuaNumberType): """Set the DC offset of an element's input to the given value. This value will remain the DC offset until changed or until the Quantum Machine is closed. Args: - voltage (QuaNumberType): The DC offset to set the input to. + offset (QuaNumberType): The DC offset to set the input to. This is limited by the OPX output voltage range. The number can be a QUA variable """ - set_dc_offset(element=self.name, element_input="single", offset=voltage) + set_dc_offset(element=self.name, element_input="single", offset=offset) def apply_to_config(self, config: dict): """Adds this SingleChannel to the QUA configuration. @@ -571,18 +571,25 @@ def mixer(self) -> Optional[Mixer]: def rf_frequency(self): return self.frequency_converter_up.LO_frequency + self.intermediate_frequency - def set_dc_offset(self, voltage: QuaNumberType, element_input: Literal["I", "Q"]): + def set_dc_offset(self, offset: QuaNumberType, element_input: Literal["I", "Q"]): """Set the DC offset of an element's input to the given value. This value will remain the DC offset until changed or until the Quantum Machine is closed. Args: - voltage (QuaNumberType): The DC offset to set the input to. + offset (QuaNumberType): The DC offset to set the input to. This is limited by the OPX output voltage range. The number can be a QUA variable element_input (Literal["I", "Q"]): The element input to set the offset for. + + Raises: + ValueError: If element_input is not "I" or "Q" """ - set_dc_offset(element=self.name, element_input=element_input, offset=voltage) + if element_input not in ["I", "Q"]: + raise ValueError( + f"element_input should be either 'I' or 'Q', got {element_input}" + ) + set_dc_offset(element=self.name, element_input=element_input, offset=offset) def apply_to_config(self, config: dict): """Adds this IQChannel to the QUA configuration. diff --git a/tests/components/channels/test_IQ_channel.py b/tests/components/channels/test_IQ_channel.py new file mode 100644 index 00000000..65596bba --- /dev/null +++ b/tests/components/channels/test_IQ_channel.py @@ -0,0 +1,27 @@ +import pytest +from quam.components import IQChannel + + +def test_IQ_channel_set_dc_offset(mocker): + mocker.patch("quam.components.channels.set_dc_offset") + + channel = IQChannel( + id="channel", + opx_output_I=("con1", 1), + opx_output_Q=("con1", 2), + frequency_converter_up=None, + ) + + with pytest.raises(TypeError): + channel.set_dc_offset(0.5) + + with pytest.raises(ValueError): + channel.set_dc_offset(0.5, "X") + + channel.set_dc_offset(0.5, "I") + + from quam.components.channels import set_dc_offset + + set_dc_offset.assert_called_once_with( + element="channel", element_input="I", offset=0.5 + ) diff --git a/tests/components/channels/test_single_channel.py b/tests/components/channels/test_single_channel.py index a6aeefbc..a19b6022 100644 --- a/tests/components/channels/test_single_channel.py +++ b/tests/components/channels/test_single_channel.py @@ -123,3 +123,16 @@ class QuamTest(QuamRoot): cfg = machine.generate_config() expected_cfg["controllers"]["con1"]["analog_outputs"][1]["offset"] = 0.1 assert cfg == expected_cfg + + +def test_single_channel_set_dc_offset(mocker): + mocker.patch("quam.components.channels.set_dc_offset") + + channel = SingleChannel(id="channel", opx_output=("con1", 1)) + channel.set_dc_offset(0.5) + + from quam.components.channels import set_dc_offset + + set_dc_offset.assert_called_once_with( + element="channel", element_input="single", offset=0.5 + )