From 7d110edb28b85c279a28a417a7bcdd9a4ac20fd1 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Fri, 15 Mar 2024 16:11:22 +0100 Subject: [PATCH 1/3] Move DummyAWG and DummyDAC into main package --- qupulse/hardware/awgs/dummy.py | 74 ++++++++++++++++++ qupulse/hardware/dacs/dummy.py | 44 +++++++++++ tests/hardware/dummy_devices.py | 128 +------------------------------- 3 files changed, 120 insertions(+), 126 deletions(-) create mode 100644 qupulse/hardware/awgs/dummy.py create mode 100644 qupulse/hardware/dacs/dummy.py diff --git a/qupulse/hardware/awgs/dummy.py b/qupulse/hardware/awgs/dummy.py new file mode 100644 index 000000000..a132f958f --- /dev/null +++ b/qupulse/hardware/awgs/dummy.py @@ -0,0 +1,74 @@ +from .base import AWG + +class DummyAWG(AWG): + """Dummy AWG for debugging purposes.""" + + def __init__(self, + sample_rate: float=10, + output_range: Tuple[float, float]=(-5, 5), + num_channels: int=1, + num_markers: int=1) -> None: + """Create a new DummyAWG instance. + + Args: + memory (int): Available memory slots for waveforms. (default = 100) + sample_rate (float): The sample rate of the dummy. (default = 10) + output_range (float, float): A (min,max)-tuple of possible output values. + (default = (-5,5)). + """ + super().__init__(identifier="DummyAWG{0}".format(id(self))) + + self._programs = {} # contains program names and programs + self._sample_rate = sample_rate + self._output_range = output_range + self._num_channels = num_channels + self._num_markers = num_markers + self._channels = ('default',) + self._armed = None + + def set_volatile_parameters(self, program_name: str, parameters): + raise NotImplementedError() + + def upload(self, name, program, channels, markers, voltage_transformation, force=False) -> None: + if name in self.programs: + if not force: + raise ProgramOverwriteException(name) + else: + self.remove(name) + self.upload(name, program) + else: + self._programs[name] = (program, channels, markers, voltage_transformation) + + def remove(self, name) -> None: + if name in self.programs: + self._programs.pop(name) + + def clear(self) -> None: + self._programs = {} + + def arm(self, name: str) -> None: + self._armed = name + + @property + def programs(self) -> Set[str]: + return set(self._programs.keys()) + + @property + def output_range(self) -> Tuple[float, float]: + return self._output_range + + @property + def identifier(self) -> str: + return "DummyAWG{0}".format(id(self)) + + @property + def sample_rate(self) -> float: + return self._sample_rate + + @property + def num_channels(self): + return self._num_channels + + @property + def num_markers(self): + return self._num_markers diff --git a/qupulse/hardware/dacs/dummy.py b/qupulse/hardware/dacs/dummy.py new file mode 100644 index 000000000..7fba3342d --- /dev/null +++ b/qupulse/hardware/dacs/dummy.py @@ -0,0 +1,44 @@ +from typing import Tuple, Set, Dict +from collections import deque + +from qupulse.hardware.dacs.dac_base import DAC + +class DummyDAC(DAC): + def __init__(self): + self._measurement_windows = dict() + self._operations = dict() + self.measured_data = deque([]) + self._meas_masks = {} + self._armed_program = None + + @property + def armed_program(self): + return self._armed_program + + def register_measurement_windows(self, program_name: str, windows: Dict[str, Tuple['numpy.ndarray', + 'numpy.ndarray']]): + self._measurement_windows[program_name] = windows + + def register_operations(self, program_name: str, operations): + self._operations[program_name] = operations + + def arm_program(self, program_name: str): + self._armed_program = program_name + + def delete_program(self, program_name): + if program_name in self._operations: + self._operations.pop(program_name) + if program_name in self._measurement_windows: + self._measurement_windows.pop(program_name) + + def clear(self) -> None: + self._measurement_windows = dict() + self._operations = dict() + self._armed_program = None + + def measure_program(self, channels): + return self.measured_data.pop() + + def set_measurement_mask(self, program_name, mask_name, begins, lengths) -> Tuple['numpy.ndarray', 'numpy.ndarray']: + self._meas_masks.setdefault(program_name, {})[mask_name] = (begins, lengths) + return begins, lengths diff --git a/tests/hardware/dummy_devices.py b/tests/hardware/dummy_devices.py index a92ce1282..60dee6f9e 100644 --- a/tests/hardware/dummy_devices.py +++ b/tests/hardware/dummy_devices.py @@ -1,126 +1,2 @@ -from typing import Tuple, Set, Dict -from collections import deque - - -from qupulse.hardware.awgs.base import AWG, ProgramOverwriteException -from qupulse.hardware.dacs import DAC - -class DummyDAC(DAC): - def __init__(self): - self._measurement_windows = dict() - self._operations = dict() - self.measured_data = deque([]) - self._meas_masks = {} - self._armed_program = None - - @property - def armed_program(self): - return self._armed_program - - def register_measurement_windows(self, program_name: str, windows: Dict[str, Tuple['numpy.ndarray', - 'numpy.ndarray']]): - self._measurement_windows[program_name] = windows - - def register_operations(self, program_name: str, operations): - self._operations[program_name] = operations - - def arm_program(self, program_name: str): - self._armed_program = program_name - - def delete_program(self, program_name): - if program_name in self._operations: - self._operations.pop(program_name) - if program_name in self._measurement_windows: - self._measurement_windows.pop(program_name) - - def clear(self) -> None: - self._measurement_windows = dict() - self._operations = dict() - self._armed_program = None - - def measure_program(self, channels): - return self.measured_data.pop() - - def set_measurement_mask(self, program_name, mask_name, begins, lengths) -> Tuple['numpy.ndarray', 'numpy.ndarray']: - self._meas_masks.setdefault(program_name, {})[mask_name] = (begins, lengths) - return begins, lengths - - -class DummyAWG(AWG): - """Dummy AWG for debugging purposes.""" - - def __init__(self, - memory: int=100, - sample_rate: float=10, - output_range: Tuple[float, float]=(-5, 5), - num_channels: int=1, - num_markers: int=1) -> None: - """Create a new DummyAWG instance. - - Args: - memory (int): Available memory slots for waveforms. (default = 100) - sample_rate (float): The sample rate of the dummy. (default = 10) - output_range (float, float): A (min,max)-tuple of possible output values. - (default = (-5,5)). - """ - super().__init__(identifier="DummyAWG{0}".format(id(self))) - - self._programs = {} # contains program names and programs - self._sample_rate = sample_rate - self._output_range = output_range - self._num_channels = num_channels - self._num_markers = num_markers - self._channels = ('default',) - self._armed = None - - # todo [2018-06-14]: The following attributes (and thus the memory argument) are never used. Remove? - self._waveform_memory = [None for i in range(memory)] - self._waveform_indices = {} # dict that maps from waveform hash to memory index - self._program_wfs = {} # contains program names and necessary waveforms indices - - def set_volatile_parameters(self, program_name: str, parameters): - raise NotImplementedError() - - def upload(self, name, program, channels, markers, voltage_transformation, force=False) -> None: - if name in self.programs: - if not force: - raise ProgramOverwriteException(name) - else: - self.remove(name) - self.upload(name, program) - else: - self._programs[name] = (program, channels, markers, voltage_transformation) - - def remove(self, name) -> None: - if name in self.programs: - self._programs.pop(name) - - def clear(self) -> None: - self._programs = {} - - def arm(self, name: str) -> None: - self._armed = name - - @property - def programs(self) -> Set[str]: - return set(self._programs.keys()) - - @property - def output_range(self) -> Tuple[float, float]: - return self._output_range - - @property - def identifier(self) -> str: - return "DummyAWG{0}".format(id(self)) - - @property - def sample_rate(self) -> float: - return self._sample_rate - - @property - def num_channels(self): - return self._num_channels - - @property - def num_markers(self): - return self._num_markers \ No newline at end of file +from qupulse.hardware.dacs.dummy import DummyDAC +from qupulse.hardware.awgs.dummy import DummyAWG From ed1f3d34103863515f89c6855339c175450ab10f Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Fri, 15 Mar 2024 16:13:35 +0100 Subject: [PATCH 2/3] Document intent --- qupulse/hardware/awgs/dummy.py | 5 +---- qupulse/hardware/dacs/dummy.py | 2 ++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/qupulse/hardware/awgs/dummy.py b/qupulse/hardware/awgs/dummy.py index a132f958f..f3199d4de 100644 --- a/qupulse/hardware/awgs/dummy.py +++ b/qupulse/hardware/awgs/dummy.py @@ -1,17 +1,14 @@ from .base import AWG class DummyAWG(AWG): - """Dummy AWG for debugging purposes.""" - def __init__(self, sample_rate: float=10, output_range: Tuple[float, float]=(-5, 5), num_channels: int=1, num_markers: int=1) -> None: - """Create a new DummyAWG instance. + """Dummy AWG for automated testing, debugging and usage in examples. Args: - memory (int): Available memory slots for waveforms. (default = 100) sample_rate (float): The sample rate of the dummy. (default = 10) output_range (float, float): A (min,max)-tuple of possible output values. (default = (-5,5)). diff --git a/qupulse/hardware/dacs/dummy.py b/qupulse/hardware/dacs/dummy.py index 7fba3342d..ba0cf6f51 100644 --- a/qupulse/hardware/dacs/dummy.py +++ b/qupulse/hardware/dacs/dummy.py @@ -4,6 +4,8 @@ from qupulse.hardware.dacs.dac_base import DAC class DummyDAC(DAC): + """Dummy DAC for automated testing, debugging and usage in examples. """ + def __init__(self): self._measurement_windows = dict() self._operations = dict() From 9258399091cca1e67c318ab8efbab68892737090 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Fri, 15 Mar 2024 16:16:14 +0100 Subject: [PATCH 3/3] Missing imports --- qupulse/hardware/awgs/dummy.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qupulse/hardware/awgs/dummy.py b/qupulse/hardware/awgs/dummy.py index f3199d4de..93ef38343 100644 --- a/qupulse/hardware/awgs/dummy.py +++ b/qupulse/hardware/awgs/dummy.py @@ -1,3 +1,5 @@ +from typing import Tuple, Set + from .base import AWG class DummyAWG(AWG):