From 081ec4a73a9df227cc774f4b19ac93e03b19d998 Mon Sep 17 00:00:00 2001
From: sldesnoo-Delft <s.l.desnoo@tudelft.nl>
Date: Wed, 20 Dec 2023 09:14:51 +0100
Subject: [PATCH] Added RF parameters frequency, source_amplitude and phase

---
 pulse_lib/base_pulse.py                       |  3 +
 pulse_lib/configuration/rf_parameters.py      | 71 +++++++++++++++++++
 .../tests/rf_source/test_read_sweep_rf.py     | 45 ++++++++++++
 .../test_rf_qblox_fast_sweep_frequency.py     | 54 ++------------
 4 files changed, 125 insertions(+), 48 deletions(-)
 create mode 100644 pulse_lib/configuration/rf_parameters.py
 create mode 100644 pulse_lib/tests/rf_source/test_read_sweep_rf.py

diff --git a/pulse_lib/base_pulse.py b/pulse_lib/base_pulse.py
index 0c063b94..be2d5f0c 100644
--- a/pulse_lib/base_pulse.py
+++ b/pulse_lib/base_pulse.py
@@ -11,6 +11,7 @@ from pulse_lib.configuration.physical_channels import (
         awg_channel, marker_channel, digitizer_channel, resonator_rf_source)
 from pulse_lib.configuration.iq_channels import IQ_channel, QubitChannel
 from pulse_lib.configuration.devices import awg_slave
+from pulse_lib.configuration.rf_parameters import RfParameters
 from pulse_lib.virtual_matrix.virtual_gate_matrices import VirtualGateMatrices
 
 logger = logging.getLogger(__name__)
@@ -29,6 +30,7 @@ class pulselib:
         self.awg_channels = dict()
         self.marker_channels = dict()
         self.digitizer_channels = dict()
+        self.rf_params = dict()
         self._virtual_matrices = VirtualGateMatrices()
         self.qubit_channels = dict()
         self.IQ_channels = dict()
@@ -171,6 +173,7 @@ class pulselib:
         self.digitizer_channels[name] = digitizer_channel(name, digitizer_name, [channel_number], iq_out=iq_out)
         if hw_input_channel is not None:
             self.set_digitizer_hw_input_channel(name, hw_input_channel)
+        self.rf_params[name] = RfParameters(self.digitizer_channels[name])
 
     def define_digitizer_channel_iq(self, name, digitizer_name, channel_numbers, phase=0.0, iq_out=False):
         ''' Defines a digitizer I/Q input pair.
diff --git a/pulse_lib/configuration/rf_parameters.py b/pulse_lib/configuration/rf_parameters.py
new file mode 100644
index 00000000..b9a4f4ce
--- /dev/null
+++ b/pulse_lib/configuration/rf_parameters.py
@@ -0,0 +1,71 @@
+from qcodes import Parameter
+
+from .physical_channels import digitizer_channel as DigitizerChannel
+
+
+class RfParameters:
+    def __init__(self, digitizer_channel: DigitizerChannel):
+        self._frequency = RfFrequencyParameter(digitizer_channel)
+        self._source_amplitude = RfAmplitudeParameter(digitizer_channel)
+        self._phase = RfPhaseParameter(digitizer_channel)
+
+    @property
+    def frequency(self):
+        return self._frequency
+
+    @property
+    def source_amplitude(self):
+        return self._source_amplitude
+
+    @property
+    def phase(self):
+        return self._phase
+
+
+class RfFrequencyParameter(Parameter):
+    def __init__(self, digitizer_channel: DigitizerChannel):
+        super().__init__(
+            name=f'{digitizer_channel.name}_frequency',
+            label=f'{digitizer_channel.name} resonator frequency',
+            unit='Hz')
+        self.channel = digitizer_channel
+
+    def get_raw(self):
+        return self.channel.frequency
+
+    def set_raw(self, value):
+        self.channel.frequency = value
+
+
+class RfAmplitudeParameter(Parameter):
+    def __init__(self, digitizer_channel: DigitizerChannel):
+        super().__init__(
+            name=f'{digitizer_channel.name}_amplitude',
+            label=f'{digitizer_channel.name} rf source amplitude',
+            unit='mV')
+        self.channel = digitizer_channel
+
+    def get_raw(self):
+        if self.channel.rf_source is None:
+            return None
+        return self.channel.rf_source.amplitude
+
+    def set_raw(self, value):
+        if self.channel.rf_source is None:
+            raise Exception(f'No RF source configured for {self.channel.name}')
+        self.channel.rf_source.amplitude = value
+
+
+class RfPhaseParameter(Parameter):
+    def __init__(self, digitizer_channel: DigitizerChannel):
+        super().__init__(
+            name=f'{digitizer_channel.name}_phase',
+            label=f'{digitizer_channel.name} phase',
+            unit='rad')
+        self.channel = digitizer_channel
+
+    def get_raw(self):
+        return self.channel.phase
+
+    def set_raw(self, value):
+        self.channel.phase = value
diff --git a/pulse_lib/tests/rf_source/test_read_sweep_rf.py b/pulse_lib/tests/rf_source/test_read_sweep_rf.py
new file mode 100644
index 00000000..4dd377dc
--- /dev/null
+++ b/pulse_lib/tests/rf_source/test_read_sweep_rf.py
@@ -0,0 +1,45 @@
+from pulse_lib.tests.configurations.test_configuration import context
+
+# %%
+import numpy as np
+from pulse_lib.scan.read_input import read_channels
+from core_tools.sweeps.sweeps import do1D
+
+
+def test_freq():
+    pulse = context.init_pulselib(n_gates=2, n_sensors=2, rf_sources=True)
+
+    rf_frequency = pulse.rf_params['SD1'].frequency
+    meas_param = read_channels(pulse, 2_000, channels=['SD1'], iq_mode='I+Q')
+    ds = do1D(rf_frequency, 80e6, 120e6, 21, 0.0, meas_param,
+              name='frequency_search', reset_param=True).run()
+
+    return ds
+
+
+def test_ampl():
+    pulse = context.init_pulselib(n_gates=2, n_sensors=2, rf_sources=True)
+
+    rf_amplitude = pulse.rf_params['SD2'].source_amplitude
+    meas_param = read_channels(pulse, 2_000, channels=['SD1'], iq_mode='I+Q')
+    ds = do1D(rf_amplitude, 20.0, 200.0, 10, 0.0, meas_param, name='amplitude_sweep', reset_param=True).run()
+
+    return ds
+
+
+def test_phase():
+    pulse = context.init_pulselib(n_gates=2, n_sensors=2, rf_sources=True)
+
+    rf_phase = pulse.rf_params['SD1'].phase
+    meas_param = read_channels(pulse, 2_000, channels=['SD1'], iq_mode='I+Q')
+    ds = do1D(rf_phase, 0.0, 2*np.pi, 20, 0.0, meas_param, name='phase_sweep', reset_param=True).run()
+
+    return ds
+
+
+# %%
+if __name__ == '__main__':
+    context.init_coretools()
+    ds1 = test_freq()
+    ds2 = test_ampl()
+    ds3 = test_phase()
diff --git a/pulse_lib/tests/rf_source/test_rf_qblox_fast_sweep_frequency.py b/pulse_lib/tests/rf_source/test_rf_qblox_fast_sweep_frequency.py
index 5de9f139..f2c36e42 100644
--- a/pulse_lib/tests/rf_source/test_rf_qblox_fast_sweep_frequency.py
+++ b/pulse_lib/tests/rf_source/test_rf_qblox_fast_sweep_frequency.py
@@ -1,73 +1,31 @@
 from pulse_lib.tests.configurations.test_configuration import context
 
 #%%
-from qcodes import Parameter
-from pulse_lib.fast_scan.qblox_fast_scans import fast_scan1D_param, fast_scan2D_param
+from pulse_lib.fast_scan.qblox_fast_scans import fast_scan1D_param
 from core_tools.sweeps.sweeps import do1D
 
-class RfParameter(Parameter):
-    def __init__(self, pulselib, digitizer_channel_name):
-        super().__init__(
-                name=f'{digitizer_channel_name}_RF',
-                label=f'{digitizer_channel_name} resonator frequency',
-                unit='Hz')
-        self.channel = pulselib.digitizer_channels[digitizer_channel_name]
-
-    def get_raw(self):
-        return self.channel.frequency
-
-    def set_raw(self, value):
-        self.channel.frequency = value
-
-# TODO: Fix amplitude sweep. THIS DOES NOT WORK!!
-class RfAmplitudeParameter(Parameter):
-    def __init__(self, pulselib, digitizer_channel_name):
-        super().__init__(
-                name=f'{digitizer_channel_name}_amplitude',
-                label=f'{digitizer_channel_name} resonator drive amplitude',
-                unit='mV')
-        self.channel = pulselib.digitizer_channels[digitizer_channel_name]
-
-    def get_raw(self):
-        return self.channel.rf_source.amplitude
-
-    def set_raw(self, value):
-        self.channel.rf_source.amplitude = value
-
-
-class PhaseParameter(Parameter):
-    def __init__(self, pulselib, digitizer_channel_name):
-        super().__init__(
-                name=f'{digitizer_channel_name} phase',
-                label=f'{digitizer_channel_name} phase',
-                unit='degrees')
-        self.channel = pulselib.digitizer_channels[digitizer_channel_name]
-
-    def get_raw(self):
-        return self.channel.phase
-
-    def set_raw(self, value):
-        self.channel.phase = value
-
 
 def test_freq():
     pulse = context.init_pulselib(n_gates=2, n_sensors=2, rf_sources=True)
 
-    rf_frequency = RfParameter(pulse, 'SD2')
+    rf_frequency = pulse.rf_params['SD2'].frequency
     fast_scan_param = fast_scan1D_param(pulse, 'P1', 50.0, 21, 2_000, iq_mode='I+Q')
     ds = do1D(rf_frequency, 80e6, 120e6, 21, 0.0, fast_scan_param, name='frequency_search', reset_param=True).run()
 
     return ds
 
+
 def test_ampl():
     pulse = context.init_pulselib(n_gates=2, n_sensors=2, rf_sources=True)
 
-    rf_amplitude = RfAmplitudeParameter(pulse, 'SD2')
+    rf_amplitude = pulse.rf_params['SD2'].source_amplitude
+    # NOTE:  reload_seq=True !!!
     fast_scan_param = fast_scan1D_param(pulse, 'P1', 50.0, 21, 2_000, iq_mode='I+Q', reload_seq=True)
     ds = do1D(rf_amplitude, 20.0, 200.0, 10, 0.0, fast_scan_param, name='amplitude_sweep', reset_param=True).run()
 
     return ds
 
+
 #%%
 if __name__ == '__main__':
     context.init_coretools()
-- 
GitLab