From 83f66a705a8376e6aa79307d6ccb2ac6354be402 Mon Sep 17 00:00:00 2001 From: hylta Date: Thu, 20 Feb 2020 12:03:36 +0100 Subject: [PATCH 1/5] Add update_volatile_parameters tests for tabor program class --- tests/_program/tabor_tests.py | 67 ++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/tests/_program/tabor_tests.py b/tests/_program/tabor_tests.py index 081fda6d3..a55f33119 100644 --- a/tests/_program/tabor_tests.py +++ b/tests/_program/tabor_tests.py @@ -11,11 +11,13 @@ from teawg import model_properties_dict from qupulse._program.tabor import TaborException, TaborProgram, \ - TaborSegment, TaborSequencing, PlottableProgram, TableDescription, make_combined_wave + TaborSegment, TaborSequencing, PlottableProgram, TableDescription, TableEntry, make_combined_wave from qupulse._program._loop import MultiChannelProgram, Loop from qupulse._program.instructions import InstructionBlock from qupulse.hardware.util import voltage_to_uint16 from qupulse.utils.types import TimeType +from qupulse.expressions import ExpressionScalar +from qupulse.pulses.parameters import MappedParameter, ConstantParameter from tests.pulses.sequencing_dummies import DummyWaveform from tests._program.loop_tests import LoopTests, WaveformGenerator, MultiChannelTests @@ -369,6 +371,69 @@ def my_gen(gen): np.testing.assert_equal(sampled_seg.ch_a, data[0]) np.testing.assert_equal(sampled_seg.ch_b, data[1]) + def test_update_volatile_parameters_with_depth1(self): + parameters = {'seq': ConstantParameter(10), 'not': ConstantParameter(13)} + seq = MappedParameter(ExpressionScalar('seq'), {'seq': ConstantParameter(3)}) + + wf_1 = DummyWaveform(defined_channels={'A'}, duration=1) + wf_2 = DummyWaveform(defined_channels={'A'}, duration=1) + + program = Loop(children=[Loop(waveform=wf_1, repetition_count=seq.get_value(), repetition_parameter=seq), + Loop(waveform=wf_2, repetition_count=4), + Loop(waveform=wf_1, repetition_count=1)], + repetition_count=1) + + t_program = TaborProgram(program, channels=(None, 'A'), markers=(None, None), + device_properties=self.instr_props, **self.program_entry_kwargs) + + self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(3, 0, 0), seq), + (TableDescription(4, 1, 0), None), + (TableDescription(1, 0, 0), None)]]) + self.assertEqual(t_program.get_advanced_sequencer_table(), [TableDescription(1, 1, 0)]) + + modifications = t_program.update_volatile_parameters(parameters) + + expected_seq = MappedParameter(ExpressionScalar('seq'), {'seq': ConstantParameter(10)}) + expected_modifications = {(0, 0): TableDescription(10, 0, 0)} + + self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(10, 0, 0), expected_seq), + (TableDescription(4, 1, 0), None), + (TableDescription(1, 0, 0), None)]]) + self.assertEqual(t_program.get_advanced_sequencer_table(), [TableDescription(1, 1, 0)]) + self.assertEqual(modifications, expected_modifications) + + def test_update_volatile_parameters_with_depth2(self): + parameters = {'seq': ConstantParameter(10), 'aseq': ConstantParameter(2), 'not': ConstantParameter(13)} + seq = MappedParameter(ExpressionScalar('seq'), {'seq': ConstantParameter(3)}) + aseq = MappedParameter(ExpressionScalar('aseq'), {'aseq': ConstantParameter(5)}) + + wf_1 = DummyWaveform(defined_channels={'A'}, duration=1) + wf_2 = DummyWaveform(defined_channels={'A'}, duration=1) + + program = Loop(children=[Loop(waveform=wf_1, repetition_count=seq.get_value(), repetition_parameter=seq), + Loop(waveform=wf_2, repetition_count=4), + Loop(waveform=wf_1, repetition_count=1)], + repetition_count=aseq.get_value(), repetition_parameter=aseq) + + t_program = TaborProgram(program, channels=(None, 'A'), markers=(None, None), + device_properties=self.instr_props, **self.program_entry_kwargs) + + self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(3, 0, 0), seq), + (TableDescription(4, 1, 0), None), + (TableDescription(1, 0, 0), None)]]) + self.assertEqual(t_program.get_advanced_sequencer_table(), [TableDescription(5, 1, 0)]) + + modifications = t_program.update_volatile_parameters(parameters) + + expected_seq = MappedParameter(ExpressionScalar('seq'), {'seq': ConstantParameter(10)}) + expected_modifications = {(0, 0): TableDescription(10, 0, 0), 0: TableEntry(2, 1, 0)} + + self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(10, 0, 0), expected_seq), + (TableDescription(4, 1, 0), None), + (TableDescription(1, 0, 0), None)]]) + self.assertEqual(t_program.get_advanced_sequencer_table(), [TableDescription(2, 1, 0)]) + self.assertEqual(modifications, expected_modifications) + class TaborSegmentTests(unittest.TestCase): @staticmethod From 658836b1961b39dbfa2de000b53ef964bb5cd5ff Mon Sep 17 00:00:00 2001 From: hylta Date: Thu, 20 Feb 2020 14:36:31 +0100 Subject: [PATCH 2/5] Improve test_update_volatile_parameters_with_depth2 --- tests/_program/tabor_tests.py | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/tests/_program/tabor_tests.py b/tests/_program/tabor_tests.py index a55f33119..62e1f5b92 100644 --- a/tests/_program/tabor_tests.py +++ b/tests/_program/tabor_tests.py @@ -410,28 +410,44 @@ def test_update_volatile_parameters_with_depth2(self): wf_1 = DummyWaveform(defined_channels={'A'}, duration=1) wf_2 = DummyWaveform(defined_channels={'A'}, duration=1) - program = Loop(children=[Loop(waveform=wf_1, repetition_count=seq.get_value(), repetition_parameter=seq), - Loop(waveform=wf_2, repetition_count=4), - Loop(waveform=wf_1, repetition_count=1)], - repetition_count=aseq.get_value(), repetition_parameter=aseq) + program = Loop(children=[Loop(children=[Loop(waveform=wf_1, repetition_count=seq.get_value(), + repetition_parameter=seq), + Loop(waveform=wf_2, repetition_count=4), + Loop(waveform=wf_1, repetition_count=2)], + repetition_count=4), + Loop(children=[Loop(waveform=wf_2, repetition_count=5), + Loop(waveform=wf_1, repetition_count=seq.get_value(), + repetition_parameter=seq), + Loop(waveform=wf_2, repetition_count=5)], + repetition_count=aseq.get_value(), repetition_parameter=aseq)], + repetition_count=1) t_program = TaborProgram(program, channels=(None, 'A'), markers=(None, None), device_properties=self.instr_props, **self.program_entry_kwargs) self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(3, 0, 0), seq), (TableDescription(4, 1, 0), None), - (TableDescription(1, 0, 0), None)]]) - self.assertEqual(t_program.get_advanced_sequencer_table(), [TableDescription(5, 1, 0)]) + (TableDescription(2, 0, 0), None)], + [(TableDescription(5, 1, 0), None), + (TableDescription(3, 0, 0), seq), + (TableDescription(5, 1, 0), None)] + ]) + self.assertEqual(t_program.get_advanced_sequencer_table(), [TableEntry(4, 1, 0), TableEntry(5, 2, 0)]) modifications = t_program.update_volatile_parameters(parameters) expected_seq = MappedParameter(ExpressionScalar('seq'), {'seq': ConstantParameter(10)}) - expected_modifications = {(0, 0): TableDescription(10, 0, 0), 0: TableEntry(2, 1, 0)} + expected_modifications = {(0, 0): TableDescription(10, 0, 0), (1, 1): TableDescription(10, 0, 0), + 1: TableEntry(2, 2, 0)} self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(10, 0, 0), expected_seq), (TableDescription(4, 1, 0), None), - (TableDescription(1, 0, 0), None)]]) - self.assertEqual(t_program.get_advanced_sequencer_table(), [TableDescription(2, 1, 0)]) + (TableDescription(2, 0, 0), None)], + [(TableDescription(5, 1, 0), None), + (TableDescription(10, 0, 0), expected_seq), + (TableDescription(5, 1, 0), None)] + ]) + self.assertEqual(t_program.get_advanced_sequencer_table(), [TableEntry(4, 1, 0), TableEntry(2, 2, 0)]) self.assertEqual(modifications, expected_modifications) From 1866b6901262997c34bc61cea32da3c05584da79 Mon Sep 17 00:00:00 2001 From: hylta Date: Fri, 21 Feb 2020 15:57:29 +0100 Subject: [PATCH 3/5] Fix bug affecting adv seq table in parse_aseq_program --- qupulse/_program/tabor.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qupulse/_program/tabor.py b/qupulse/_program/tabor.py index 50b5839a5..96359b34c 100644 --- a/qupulse/_program/tabor.py +++ b/qupulse/_program/tabor.py @@ -644,11 +644,11 @@ def prepare_program_for_advanced_sequence_mode(program: Loop, min_seq_len: int, ParsedProgram = NamedTuple('ParsedProgram', [('advanced_sequencer_table', Sequence[TableEntry]), - ('sequencer_tables', Sequence[Sequence[ + ('sequencer_tables', Sequence[Sequence[ Tuple[TableDescription, Optional[VolatileProperty]]]]), - ('waveforms', Tuple[Waveform, ...]), - ('volatile_parameter_positions', Dict[Union[int, Tuple[int, int]], - VolatileRepetitionCount])]) + ('waveforms', Tuple[Waveform, ...]), + ('volatile_parameter_positions', Dict[Union[int, Tuple[int, int]], + VolatileRepetitionCount])]) def parse_aseq_program(program: Loop, used_channels: FrozenSet[ChannelID]) -> ParsedProgram: @@ -683,7 +683,7 @@ def parse_aseq_program(program: Loop, used_channels: FrozenSet[ChannelID]) -> Pa advanced_sequencer_table.append(TableEntry(repetition_count=sequencer_table_loop.repetition_count, element_number=sequence_no, jump_flag=0)) if sequencer_table_loop.volatile_repetition: - volatile_parameter_positions[adv_position] = sequencer_table_loop.volatile_repetition + volatile_parameter_positions[adv_position] = sequencer_table_loop.repetition_definition # transform sequencer_tables in lists to make it indexable and mutable sequencer_tables = list(map(list, sequencer_tables)) From d349c33a05cfe132e2b37dd6c4dc1c81f16d6ef8 Mon Sep 17 00:00:00 2001 From: hylta Date: Tue, 25 Feb 2020 10:57:12 +0100 Subject: [PATCH 4/5] Fix _program based update_volatile_parameters test --- tests/_program/tabor_tests.py | 44 +++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/tests/_program/tabor_tests.py b/tests/_program/tabor_tests.py index 6530d06c1..8856f3366 100644 --- a/tests/_program/tabor_tests.py +++ b/tests/_program/tabor_tests.py @@ -1,6 +1,7 @@ import unittest import itertools import numpy as np +from qupulse.utils.types import FrozenDict from unittest import mock try: @@ -13,10 +14,11 @@ from qupulse._program.tabor import TaborException, TaborProgram, \ TaborSegment, TaborSequencing, PlottableProgram, TableDescription, make_combined_wave, TableEntry from qupulse._program._loop import Loop +from qupulse._program.volatile import VolatileRepetitionCount from qupulse.hardware.util import voltage_to_uint16 from qupulse.utils.types import TimeType from qupulse.expressions import ExpressionScalar -from qupulse.pulses.parameters import MappedParameter, ConstantParameter +from qupulse.parameter_scope import DictScope from tests.pulses.sequencing_dummies import DummyWaveform from tests._program.loop_tests import LoopTests, WaveformGenerator @@ -372,13 +374,14 @@ def my_gen(gen): np.testing.assert_equal(sampled_seg.ch_b, data[1]) def test_update_volatile_parameters_with_depth1(self): - parameters = {'seq': ConstantParameter(10), 'not': ConstantParameter(13)} - seq = MappedParameter(ExpressionScalar('seq'), {'seq': ConstantParameter(3)}) + parameters = {'s': 10, 'not': 13} + s = VolatileRepetitionCount(expression=ExpressionScalar('s'), scope=DictScope(values=FrozenDict(s=3), + volatile=set('s'))) wf_1 = DummyWaveform(defined_channels={'A'}, duration=1) wf_2 = DummyWaveform(defined_channels={'A'}, duration=1) - program = Loop(children=[Loop(waveform=wf_1, repetition_count=seq.get_value(), repetition_parameter=seq), + program = Loop(children=[Loop(waveform=wf_1, repetition_count=s), Loop(waveform=wf_2, repetition_count=4), Loop(waveform=wf_1, repetition_count=1)], repetition_count=1) @@ -386,65 +389,66 @@ def test_update_volatile_parameters_with_depth1(self): t_program = TaborProgram(program, channels=(None, 'A'), markers=(None, None), device_properties=self.instr_props, **self.program_entry_kwargs) - self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(3, 0, 0), seq), + self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(3, 0, 0), s.volatile_property), (TableDescription(4, 1, 0), None), (TableDescription(1, 0, 0), None)]]) self.assertEqual(t_program.get_advanced_sequencer_table(), [TableDescription(1, 1, 0)]) modifications = t_program.update_volatile_parameters(parameters) - expected_seq = MappedParameter(ExpressionScalar('seq'), {'seq': ConstantParameter(10)}) + expected_seq = VolatileRepetitionCount(expression=ExpressionScalar('s'), scope=DictScope(values=FrozenDict(s=10), volatile=set('s'))) expected_modifications = {(0, 0): TableDescription(10, 0, 0)} - self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(10, 0, 0), expected_seq), + self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(10, 0, 0), expected_seq.volatile_property), (TableDescription(4, 1, 0), None), (TableDescription(1, 0, 0), None)]]) self.assertEqual(t_program.get_advanced_sequencer_table(), [TableDescription(1, 1, 0)]) self.assertEqual(modifications, expected_modifications) def test_update_volatile_parameters_with_depth2(self): - parameters = {'seq': ConstantParameter(10), 'aseq': ConstantParameter(2), 'not': ConstantParameter(13)} - seq = MappedParameter(ExpressionScalar('seq'), {'seq': ConstantParameter(3)}) - aseq = MappedParameter(ExpressionScalar('aseq'), {'aseq': ConstantParameter(5)}) + parameters = {'s': 10, 'a': 2, 'not': 13} + s = VolatileRepetitionCount(expression=ExpressionScalar('s'), + scope=DictScope(values=FrozenDict(s=3), volatile=set('s'))) + a = VolatileRepetitionCount(expression=ExpressionScalar('a'), + scope=DictScope(values=FrozenDict(a=5), volatile=set('a'))) wf_1 = DummyWaveform(defined_channels={'A'}, duration=1) wf_2 = DummyWaveform(defined_channels={'A'}, duration=1) - program = Loop(children=[Loop(children=[Loop(waveform=wf_1, repetition_count=seq.get_value(), - repetition_parameter=seq), + program = Loop(children=[Loop(children=[Loop(waveform=wf_1, repetition_count=s), Loop(waveform=wf_2, repetition_count=4), Loop(waveform=wf_1, repetition_count=2)], repetition_count=4), Loop(children=[Loop(waveform=wf_2, repetition_count=5), - Loop(waveform=wf_1, repetition_count=seq.get_value(), - repetition_parameter=seq), + Loop(waveform=wf_1, repetition_count=s), Loop(waveform=wf_2, repetition_count=5)], - repetition_count=aseq.get_value(), repetition_parameter=aseq)], + repetition_count=a)], repetition_count=1) t_program = TaborProgram(program, channels=(None, 'A'), markers=(None, None), device_properties=self.instr_props, **self.program_entry_kwargs) - self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(3, 0, 0), seq), + self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(3, 0, 0), s.volatile_property), (TableDescription(4, 1, 0), None), (TableDescription(2, 0, 0), None)], [(TableDescription(5, 1, 0), None), - (TableDescription(3, 0, 0), seq), + (TableDescription(3, 0, 0), s.volatile_property), (TableDescription(5, 1, 0), None)] ]) self.assertEqual(t_program.get_advanced_sequencer_table(), [TableEntry(4, 1, 0), TableEntry(5, 2, 0)]) modifications = t_program.update_volatile_parameters(parameters) - expected_seq = MappedParameter(ExpressionScalar('seq'), {'seq': ConstantParameter(10)}) + expected_seq = VolatileRepetitionCount(expression=ExpressionScalar('s'), + scope=DictScope(values=FrozenDict(s=10), volatile=set('s'))) expected_modifications = {(0, 0): TableDescription(10, 0, 0), (1, 1): TableDescription(10, 0, 0), 1: TableEntry(2, 2, 0)} - self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(10, 0, 0), expected_seq), + self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(10, 0, 0), expected_seq.volatile_property), (TableDescription(4, 1, 0), None), (TableDescription(2, 0, 0), None)], [(TableDescription(5, 1, 0), None), - (TableDescription(10, 0, 0), expected_seq), + (TableDescription(10, 0, 0), expected_seq.volatile_property), (TableDescription(5, 1, 0), None)] ]) self.assertEqual(t_program.get_advanced_sequencer_table(), [TableEntry(4, 1, 0), TableEntry(2, 2, 0)]) From e9e95a7d96482e0f443b118fcd78aca0c3269da2 Mon Sep 17 00:00:00 2001 From: hylta Date: Tue, 25 Feb 2020 11:47:32 +0100 Subject: [PATCH 5/5] Fix tests --- qupulse/hardware/awgs/tabor.py | 4 ++-- tests/_program/tabor_tests.py | 7 +------ tests/hardware/tabor_dummy_based_tests.py | 2 +- tests/hardware/tabor_simulator_based_tests.py | 2 +- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/qupulse/hardware/awgs/tabor.py b/qupulse/hardware/awgs/tabor.py index efb4db1af..90e7b1831 100644 --- a/qupulse/hardware/awgs/tabor.py +++ b/qupulse/hardware/awgs/tabor.py @@ -2,6 +2,7 @@ import functools import weakref import logging +import numbers from typing import List, Tuple, Set, Callable, Optional, Any, Sequence, cast, Union, Dict, Mapping, NamedTuple from collections import OrderedDict @@ -15,7 +16,6 @@ from qupulse._program._loop import Loop, make_compatible from qupulse.hardware.util import voltage_to_uint16, find_positions from qupulse.hardware.awgs.base import AWG, AWGAmplitudeOffsetHandling -from qupulse.pulses.parameters import Parameter from qupulse._program.tabor import TaborSegment, TaborException, TaborProgram, PlottableProgram, TaborSequencing,\ make_combined_wave @@ -723,7 +723,7 @@ def _execute_multiple_commands_with_config_guard(self, commands: List[str]) -> N cmd_str = ";".join(commands) self.device.send_cmd(cmd_str, paranoia_level=self.internal_paranoia_level) - def set_volatile_parameters(self, program_name: str, parameters: Mapping[str, Parameter]) -> None: + def set_volatile_parameters(self, program_name: str, parameters: Mapping[str, numbers.Number]) -> None: """ Set the values of parameters which were marked as volatile on program creation. Sets volatile parameters in program memory and device's (adv.) sequence tables if program is current program. diff --git a/tests/_program/tabor_tests.py b/tests/_program/tabor_tests.py index 8856f3366..f874f718c 100644 --- a/tests/_program/tabor_tests.py +++ b/tests/_program/tabor_tests.py @@ -335,11 +335,9 @@ def my_gen(gen): with self.assertRaisesRegex(ValueError, "non integer length"): root_loop = LoopTests.get_test_loop(WaveformGenerator( waveform_data_generator=my_gen(self.waveform_data_generator), - duration_generator=itertools.repeat(1/200), + duration_generator=itertools.repeat(1 / 200), num_channels=4)) - mcp = MultiChannelProgram(InstructionBlock(), tuple()) - mcp.programs[frozenset(('A', 'B', 'C', 'D'))] = root_loop TaborProgram(root_loop, self.instr_props, ('A', 'B'), (None, None), **self.program_entry_kwargs) root_loop = LoopTests.get_test_loop(WaveformGenerator( @@ -347,9 +345,6 @@ def my_gen(gen): duration_generator=itertools.repeat(1), num_channels=4)) - mcp = MultiChannelProgram(InstructionBlock(), tuple()) - mcp.programs[frozenset(('A', 'B', 'C', 'D'))] = root_loop - prog = TaborProgram(root_loop, self.instr_props, ('A', 'B'), (None, None), **self.program_entry_kwargs) sampled, sampled_length = prog.get_sampled_segments() diff --git a/tests/hardware/tabor_dummy_based_tests.py b/tests/hardware/tabor_dummy_based_tests.py index fa1b1f1ed..ba5226f3c 100644 --- a/tests/hardware/tabor_dummy_based_tests.py +++ b/tests/hardware/tabor_dummy_based_tests.py @@ -212,7 +212,7 @@ def test__execute_multiple_commands_with_config_guard(self): def test_set_volatile_parameters(self): channel_pair = self.TaborChannelPair(self.instrument, identifier='asd', channels=(1, 2)) - parameters = {'var': ConstantParameter(2)} + parameters = {'var': 2} modifications = {1: TableEntry(repetition_count=5, element_number=1, jump_flag=0), (0, 1): TableDescription(repetition_count=10, element_id=0, jump_flag=0)} invalid_modification = {1: TableEntry(repetition_count=0, element_number=1, jump_flag=0)} diff --git a/tests/hardware/tabor_simulator_based_tests.py b/tests/hardware/tabor_simulator_based_tests.py index f837809e0..fd4bfdfdc 100644 --- a/tests/hardware/tabor_simulator_based_tests.py +++ b/tests/hardware/tabor_simulator_based_tests.py @@ -262,7 +262,7 @@ def test_set_volatile_parameter(self): self.channel_pair._amend_segments(self.segments) self.arm_program(self.sequence_tables, self.advanced_sequence_table, None, np.asarray([1, 2])) - para = {'a': ConstantParameter(5)} + para = {'a': 5} actual_sequence_tables = [self.channel_pair._idle_sequence_table] + [[(rep, index + 2, jump) for rep, index, jump in table] for table in self.sequence_tables_raw]