From f11dcbd15f13cadad66af0d4227394399d26e6ea Mon Sep 17 00:00:00 2001 From: jupfi Date: Fri, 7 Jun 2024 17:30:11 +0200 Subject: [PATCH] Added table option for phase cycling readout scheme. --- src/quackseq/options.py | 36 +++++++++++++++++++ src/quackseq/phase_table.py | 21 ----------- src/quackseq/pulseparameters.py | 16 +++++---- src/quackseq/pulsesequence.py | 26 +++++++++----- .../spectrometer/spectrometer_controller.py | 4 +-- 5 files changed, 66 insertions(+), 37 deletions(-) diff --git a/src/quackseq/options.py b/src/quackseq/options.py index 2a06209..bc52ae4 100644 --- a/src/quackseq/options.py +++ b/src/quackseq/options.py @@ -232,3 +232,39 @@ class FunctionOption(Option): obj = cls(data["name"], functions) obj.value = Function.from_json(data["value"]) return obj + +class TableOption(Option): + """A table option has rows and columns and can be used to store a table of values. The value is a list of lists.""" + + def __init__(self, name: str, value) -> None: + """Initializes the table option.""" + super().__init__(name, value) + + def set_value(self, value): + """Sets the value of the option.""" + self.value = value + + def to_json(self): + """Returns a json representation of the option. + + Returns: + dict: The json representation of the option. + """ + return { + "name": self.name, + "value": self.value, + "class": self.__class__.__name__, + } + + @classmethod + def from_json(cls, data): + """Creates a TableOption from a json representation. + + Args: + data (dict): The json representation of the TableOption. + + Returns: + TableOption: The TableOption. + """ + obj = cls(data["name"], data["value"]) + return obj diff --git a/src/quackseq/phase_table.py b/src/quackseq/phase_table.py index e244b75..1131566 100644 --- a/src/quackseq/phase_table.py +++ b/src/quackseq/phase_table.py @@ -184,27 +184,6 @@ class PhaseTable: def phase_array(self, phase_array : np.array): self._phase_array = phase_array - @property - def rx_phase_sign(self) -> list: - return self._rx_phase_sign - - @rx_phase_sign.setter - def rx_phase_sign(self, rx_phase_sign: list): - """The phase sign of the RX pulse. - - Args: - rx_phase_sign (list): A list of phase signs for the RX pulse. The different entries are tuples with the first element being the sign and the second element being the phase. - """ - - # Check that the rx_phase_sign has the same length as the number of rows in the phase table - - if len(rx_phase_sign) != self.phase_array.shape[0]: - raise ValueError( - f"The number of rows in the phase table is {self.phase_table.shape[0]} but the length of the rx_phase_sign is {len(rx_phase_sign)}" - ) - - self._rx_phase_sign = rx_phase_sign - @property def n_phase_cycles(self) -> int: return self.phase_array.shape[0] diff --git a/src/quackseq/pulseparameters.py b/src/quackseq/pulseparameters.py index fef018d..4043529 100644 --- a/src/quackseq/pulseparameters.py +++ b/src/quackseq/pulseparameters.py @@ -10,7 +10,13 @@ import logging import numpy as np from numpy.core.multiarray import array as array -from quackseq.options import BooleanOption, FunctionOption, NumericOption, Option +from quackseq.options import ( + BooleanOption, + FunctionOption, + NumericOption, + Option, + TableOption, +) from quackseq.functions import ( RectFunction, SincFunction, @@ -163,7 +169,7 @@ class RXReadout(PulseParameter): """ RX = "Enable RX Readout" - PHASE = "RX Phase (°)" + READOUT_SCHEME = "Readout Scheme" def __init__(self, name) -> None: """Initializes the RX Readout PulseParameter. @@ -173,10 +179,8 @@ class RXReadout(PulseParameter): super().__init__(name) self.add_option(BooleanOption(self.RX, False)) - # Receiver Phase - self.add_option( - NumericOption(self.PHASE, 0, min_value=0, max_value=360, is_float=True) - ) + # Readout Scheme for phase cycling - default is a positive sign with a 0 phase + self.add_option(TableOption(self.READOUT_SCHEME, [[1, 0]])) class Gate(PulseParameter): diff --git a/src/quackseq/pulsesequence.py b/src/quackseq/pulsesequence.py index 8305b8e..b54f4ed 100644 --- a/src/quackseq/pulsesequence.py +++ b/src/quackseq/pulsesequence.py @@ -260,7 +260,7 @@ class QuackSequence(PulseSequence): self.set_tx_phase(event, phase) self.set_tx_shape(event, shape) - def add_readout_event(self, event_name: str, duration: float, phase: float = 0): + def add_readout_event(self, event_name: str, duration: float): """Adds a readout event to the pulse sequence. Args: @@ -269,7 +269,6 @@ class QuackSequence(PulseSequence): """ event = self.create_event(event_name, duration) self.set_rx(event, True) - self.set_rx_phase(event, phase) # TX Specific functions @@ -344,13 +343,24 @@ class QuackSequence(PulseSequence): """ event.parameters[self.RX_READOUT].get_option_by_name(RXReadout.RX).value = rx - def set_rx_phase(self, event, phase: float) -> None: - """Sets the phase of the receiver. + def set_rx_readout_scheme(self, event, readout_scheme: list) -> None: + """Sets the readout scheme of the receiver. Args: - event (Event): The event to set the phase for - phase (float): The phase of the receiver + event (Event): The event to set the readout scheme for + readout_scheme (list): The readout scheme of the receiver """ + # Check that the readout scheme is valid + self.phase_table.update_phase_array() + n_cycles = self.phase_table.n_phase_cycles + + rows = len(readout_scheme) + + if rows != n_cycles: + raise ValueError( + f"Readout scheme needs to have {n_cycles} cycles, but has {rows}" + ) + event.parameters[self.RX_READOUT].get_option_by_name( - RXReadout.PHASE - ).value = phase + RXReadout.READOUT_SCHEME + ).value = readout_scheme diff --git a/src/quackseq/spectrometer/spectrometer_controller.py b/src/quackseq/spectrometer/spectrometer_controller.py index 007e158..fc0f319 100644 --- a/src/quackseq/spectrometer/spectrometer_controller.py +++ b/src/quackseq/spectrometer/spectrometer_controller.py @@ -55,12 +55,12 @@ class SpectrometerController: [event.duration for event in previous_events] ) rx_duration = event.duration - phase = parameter.get_option_by_name(RXReadout.PHASE).value + readout_scheme = parameter.get_option_by_name(RXReadout.READOUT_SCHEME).value rx_begin = float(previous_events_duration) if rx_duration: rx_stop = rx_begin + float(rx_duration) - return rx_begin * 1e6, rx_stop * 1e6, phase + return rx_begin * 1e6, rx_stop * 1e6, readout_scheme else: return None, None, None