def test_const_propagation(self): lhs = MultiChannelWaveform([ DummyWaveform(duration=1.5, defined_channels={'a', 'c', 'd', 'i'}), ConstantWaveform.from_mapping(1.5, {'e': 1.2, 'f': 1.3, 'h': 4.6}) ]) rhs = MultiChannelWaveform([ DummyWaveform(duration=1.5, defined_channels={'a', 'b', 'e'}), ConstantWaveform.from_mapping(1.5, {'f': 2.5, 'g': 3.5, 'i': 6.4}) ]) wf = ArithmeticWaveform(lhs, '-', rhs) assert_constant_consistent(self, wf) expected = {'a': None, 'b': None, 'c': None, 'd': None, 'e': None, 'f': 1.3-2.5, 'g': -3.5, 'h': 4.6, 'i': None} actual = {ch: wf.constant_value(ch) for ch in wf.defined_channels} self.assertEqual(expected, actual)
def test_waveform_sample(self): waveform = ConstantWaveform(10, .1, 'P1') sample_times = [-1, 0, 1, 2] result = waveform.unsafe_sample('P1', sample_times) self.assertTrue(np.all(result == .1)) self.assertIs(waveform, waveform.unsafe_get_subset_for_channels({'A'}))
def test_from_sequence(self): dwf = DummyWaveform(duration=1.1, defined_channels={'A'}) self.assertIs(dwf, SequenceWaveform.from_sequence((dwf,))) swf1 = SequenceWaveform.from_sequence((dwf, dwf)) swf2 = SequenceWaveform.from_sequence((swf1, dwf)) assert_constant_consistent(self, swf1) assert_constant_consistent(self, swf2) self.assertEqual(3*(dwf,), swf2.sequenced_waveforms) cwf_2_a = ConstantWaveform(duration=1.1, amplitude=2.2, channel='A') cwf_3 = ConstantWaveform(duration=1.1, amplitude=3.3, channel='A') cwf_2_b = ConstantWaveform(duration=1.1, amplitude=2.2, channel='A') with mock.patch.object(ConstantWaveform, 'from_mapping', return_value=mock.sentinel) as from_mapping: new_constant = SequenceWaveform.from_sequence((cwf_2_a, cwf_2_b)) self.assertIs(from_mapping.return_value, new_constant) from_mapping.assert_called_once_with(2*TimeType.from_float(1.1), {'A': 2.2}) swf3 = SequenceWaveform.from_sequence((cwf_2_a, dwf)) self.assertEqual((cwf_2_a, dwf), swf3.sequenced_waveforms) self.assertIsNone(swf3.constant_value('A')) assert_constant_consistent(self, swf3) swf3 = SequenceWaveform.from_sequence((cwf_2_a, cwf_3)) self.assertEqual((cwf_2_a, cwf_3), swf3.sequenced_waveforms) self.assertIsNone(swf3.constant_value('A')) assert_constant_consistent(self, swf3)
def test_from_mapping(self): from_single = ConstantWaveform.from_mapping(1., {'A': 2.}) expected_single = ConstantWaveform(duration=1., amplitude=2., channel='A') self.assertEqual(expected_single, from_single) from_multi = ConstantWaveform.from_mapping(1., {'A': 2., 'B': 3.}) expected_from_multi = MultiChannelWaveform([ConstantWaveform(duration=1., amplitude=2., channel='A'), ConstantWaveform(duration=1., amplitude=3., channel='B')]) self.assertEqual(expected_from_multi, from_multi)
def test_from_functor(self): dummy_wf = DummyWaveform(1.5, defined_channels={'A', 'B'}) const_wf = ConstantWaveform.from_mapping(1.5, {'A': 1.1, 'B': 2.2}) wf = FunctorWaveform.from_functor(dummy_wf, {'A': np.negative, 'B': np.positive}) self.assertEqual(FunctorWaveform(dummy_wf, {'A': np.negative, 'B': np.positive}), wf) self.assertFalse(wf.is_constant()) assert_constant_consistent(self, wf) wf = FunctorWaveform.from_functor(const_wf, {'A': np.negative, 'B': np.positive}) self.assertEqual(ConstantWaveform.from_mapping(1.5, {'A': -1.1, 'B': 2.2}), wf) assert_constant_consistent(self, wf)
def test_from_operator(self): lhs = DummyWaveform(duration=1.5, defined_channels={'a', 'b', 'c'}) rhs = DummyWaveform(duration=1.5, defined_channels={'a', 'b', 'd'}) lhs_const = ConstantWaveform.from_mapping(1.5, {'a': 1.1, 'b': 2.2, 'c': 3.3}) rhs_const = ConstantWaveform.from_mapping(1.5, {'a': 1.2, 'b': 2.4, 'd': 3.4}) self.assertEqual(ArithmeticWaveform(lhs, '+', rhs), ArithmeticWaveform.from_operator(lhs, '+', rhs)) self.assertEqual(ArithmeticWaveform(lhs_const, '+', rhs), ArithmeticWaveform.from_operator(lhs_const, '+', rhs)) self.assertEqual(ArithmeticWaveform(lhs, '+', rhs_const), ArithmeticWaveform.from_operator(lhs, '+', rhs_const)) expected = ConstantWaveform.from_mapping(1.5, {'a': 1.1-1.2, 'b': 2.2-2.4, 'c': 3.3, 'd': -3.4}) consted = ArithmeticWaveform.from_operator(lhs_const, '-', rhs_const) self.assertEqual(expected, consted)
def test_upload_exceptions(self): wv = ConstantWaveform(channel=1, duration=192, amplitude=0.1) channel_pair = TaborChannelPair(self.instrument, identifier='asd', channels=(1, 2)) program = Loop(waveform=wv) with self.assertRaises(ValueError): channel_pair.upload('test', program, (1, 2, 3), (5, 6), (lambda x: x, lambda x: x)) with self.assertRaises(ValueError): channel_pair.upload('test', program, (1, 2), (5, 6, 'a'), (lambda x: x, lambda x: x)) with self.assertRaises(ValueError): channel_pair.upload('test', program, (1, 2), (3, 4), (lambda x: x, )) old = channel_pair._amplitude_offset_handling with self.assertRaises(ValueError): channel_pair._amplitude_offset_handling = 'invalid' channel_pair.upload('test', program, (1, None), (None, None), (lambda x: x, lambda x: x)) channel_pair._amplitude_offset_handling = old channel_pair._known_programs['test'] = TaborProgramMemory( np.array([0]), None) with self.assertRaises(ValueError): channel_pair.upload('test', program, (1, 2), (3, 4), (lambda x: x, lambda x: x))
def test_from_table(self): expected = ConstantWaveform(0.1, 0.2, 'A') for interp in (HoldInterpolationStrategy(), JumpInterpolationStrategy(), LinearInterpolationStrategy()): wf = TableWaveform.from_table('A', [TableWaveformEntry(0.0, 0.2, interp), TableWaveformEntry(0.1, 0.2, interp)]) self.assertEqual(expected, wf)
def test_from_repetition_count(self): dwf = DummyWaveform() self.assertEqual(RepetitionWaveform(dwf, 3), RepetitionWaveform.from_repetition_count(dwf, 3)) cwf = ConstantWaveform(duration=3, amplitude=2.2, channel='A') with mock.patch.object(ConstantWaveform, 'from_mapping', return_value=mock.sentinel) as from_mapping: self.assertIs(from_mapping.return_value, RepetitionWaveform.from_repetition_count(cwf, 5)) from_mapping.assert_called_once_with(15, {'A': 2.2})
def test_constant_default_impl(self): wf_non_const_a = DummyWaveform(defined_channels={'A'}, duration=3) wf_non_const_b = DummyWaveform(defined_channels={'B'}, duration=3) wf_const_c = ConstantWaveform(channel='C', amplitude=2.2, duration=3) wf_const_d = ConstantWaveform(channel='D', amplitude=3.3, duration=3) wf_const = MultiChannelWaveform.from_parallel((wf_const_c, wf_const_d)) wf_non_const = MultiChannelWaveform.from_parallel((wf_non_const_b, wf_non_const_a)) wf_mixed = MultiChannelWaveform.from_parallel((wf_non_const_a, wf_const_c)) assert_constant_consistent(self, wf_const) assert_constant_consistent(self, wf_non_const) assert_constant_consistent(self, wf_mixed) self.assertEqual(wf_const.constant_value_dict(), {'C': 2.2, 'D': 3.3}) self.assertIsNone(wf_non_const.constant_value_dict()) self.assertIsNone(wf_mixed.constant_value_dict()) self.assertEqual(wf_mixed.constant_value('C'), 2.2)
def test_construction(self): with self.assertRaises(ValueError): FunctionWaveform(ExpressionScalar('sin(omega*t)'), duration=5, channel='A') const = FunctionWaveform.from_expression(ExpressionScalar('4.'), duration=5, channel='A') expected_const = ConstantWaveform(duration=5, amplitude=4., channel='A') self.assertEqual(expected_const, const) linear = FunctionWaveform.from_expression(ExpressionScalar('4.*t'), 5, 'A') expected_linear = FunctionWaveform(ExpressionScalar('4.*t'), 5, 'A') self.assertEqual(expected_linear, linear)
def test_build_waveform(self): tpt = ConstantPulseTemplate(200, {'C1': 2, 'C2': 3}) wf_id = tpt.build_waveform({}, {'C1': 'C1', 'C2': 'C2'}) self.assertEqual( ConstantWaveform.from_mapping(200, { 'C1': 2, 'C2': 3 }), wf_id) wf_1 = tpt.build_waveform({}, {'C1': 'C1', 'C2': None}) self.assertEqual(ConstantWaveform.from_mapping(200, {'C1': 2}), wf_1) wf_2 = tpt.build_waveform({}, {'C1': None, 'C2': 'A'}) self.assertEqual(ConstantWaveform.from_mapping(200, {'A': 3}), wf_2) wf_all = tpt.build_waveform({}, {'C1': 'B', 'C2': 'A'}) self.assertEqual(ConstantWaveform.from_mapping(200, { 'A': 3, 'B': 2 }), wf_all) self.assertIsNone(tpt.build_waveform({}, {'C1': None, 'C2': None}))
def roll_constant_waveforms(program: Loop, minimal_waveform_quanta: int, waveform_quantum: int, sample_rate: TimeType): """This function finds waveforms in program that can be replaced with repetitions of shorter waveforms and replaces them. Complexity O(N_waveforms) This is possible if: - The waveform is constant on all channels - waveform.duration * sample_rate / waveform_quantum has a factor that is bigger than minimal_waveform_quanta Args: program: minimal_waveform_quanta: waveform_quantum: sample_rate: """ waveform = program.waveform if waveform is None: for child in program: roll_constant_waveforms(child, minimal_waveform_quanta, waveform_quantum, sample_rate) else: waveform_quanta = (waveform.duration * sample_rate) // waveform_quantum # example # waveform_quanta = 15 # minimal_waveform_quanta = 2 # => repetition_count = 5, new_waveform_quanta = 3 if waveform_quanta < minimal_waveform_quanta * 2: # there is no way to roll this waveform because it is too short return const_values = waveform.constant_value_dict() if const_values is None: # The waveform is not constant return new_waveform_quanta = smallest_factor_ge(waveform_quanta, min_factor=minimal_waveform_quanta) if new_waveform_quanta == waveform_quanta: # the waveform duration in samples has no suitable factor # TODO: Option to insert multiple Loop objects return additional_repetition_count = waveform_quanta // new_waveform_quanta new_waveform = ConstantWaveform.from_mapping( duration=waveform_quantum * new_waveform_quanta / sample_rate, constant_values=const_values) # use the private properties to avoid invalidating the duration cache of the parent loop program._repetition_definition = program.repetition_definition * additional_repetition_count program._waveform = new_waveform
def build_waveform( self, parameters: Dict[str, numbers.Real], channel_mapping: Dict[ChannelID, Optional[ChannelID]] ) -> Optional[Union[ConstantWaveform, MultiChannelWaveform]]: logging.debug( f'build_waveform of ConstantPulse: channel_mapping {channel_mapping}, ' f'defined_channels {self.defined_channels}') constant_values = {} for channel, value in self._amplitude_dict.items(): mapped_channel = channel_mapping[channel] if mapped_channel is not None: constant_values[mapped_channel] = value if constant_values: return ConstantWaveform.from_mapping(self.duration, constant_values) else: return None
def test_from_transformation(self): const_output = {'c': 4.4, 'd': 5.5, 'e': 6.6} trafo = TransformationDummy(output_channels=const_output.keys(), constant_invariant=False) const_trafo = TransformationDummy(output_channels=const_output.keys(), constant_invariant=True, transformed=const_output) dummy_wf = DummyWaveform(duration=1.5, defined_channels={'a', 'b'}) const_wf = ConstantWaveform.from_mapping(3, {'a': 2.2, 'b': 3.3}) self.assertEqual(TransformingWaveform(inner_waveform=dummy_wf, transformation=trafo), TransformingWaveform.from_transformation(inner_waveform=dummy_wf, transformation=trafo)) self.assertEqual(TransformingWaveform(inner_waveform=dummy_wf, transformation=const_trafo), TransformingWaveform.from_transformation(inner_waveform=dummy_wf, transformation=const_trafo)) self.assertEqual(TransformingWaveform(inner_waveform=const_wf, transformation=trafo), TransformingWaveform.from_transformation(inner_waveform=const_wf, transformation=trafo)) with mock.patch.object(ConstantWaveform, 'from_mapping', return_value=mock.sentinel) as from_mapping: self.assertIs(from_mapping.return_value, TransformingWaveform.from_transformation(inner_waveform=const_wf, transformation=const_trafo)) from_mapping.assert_called_once_with(const_wf.duration, const_output)
def build_waveform( self, parameters: Dict[str, numbers.Real], channel_mapping: Dict[ChannelID, Optional[ChannelID]] ) -> Optional[Union[ConstantWaveform, MultiChannelWaveform]]: logging.debug( f'build_waveform of ConstantPulse: channel_mapping {channel_mapping}, defined_channels {self.defined_channels} ' ) if all( channel_mapping.get(channel, None) is None for channel in self.defined_channels): return None waveforms = [ ConstantWaveform(self.duration, amplitude, channel) for channel, amplitude in self._amplitude_dict.items() if channel_mapping[channel] is not None ] if len(waveforms) == 1: return waveforms.pop() else: return MultiChannelWaveform(waveforms)
def get_constant_unique_wfs(n=10000, duration=192, defined_channels=frozenset(['A'])): if not hasattr(get_unique_wfs, 'cache'): get_unique_wfs.cache = {} key = (n, duration, defined_channels) if key not in get_unique_wfs.cache: bit_gen = np.random.PCG64(_key_to_int(n, duration, defined_channels)) rng = np.random.Generator(bit_gen) random_values = rng.random(size=(n, len(defined_channels))) sorted_channels = sorted(defined_channels) get_unique_wfs.cache[key] = [ ConstantWaveform.from_mapping(duration, { ch: ch_value for ch, ch_value in zip(sorted_channels, wf_values) }) for wf_values in random_values ] return get_unique_wfs.cache[key]
def test_const_value(self): mixed_wf = MultiChannelWaveform([DummyWaveform(1.5, defined_channels={'A'}), ConstantWaveform(1.5, 1.1, 'B')]) wf = FunctorWaveform(mixed_wf, {'A': np.negative, 'B': np.negative}) self.assertIsNone(wf.constant_value('A')) self.assertEqual(-1.1, wf.constant_value('B'))
def test_repr(self): body_wf = ConstantWaveform(amplitude=1.1, duration=1.3, channel='3') wf = RepetitionWaveform(body_wf, 3) r = repr(wf) self.assertEqual(wf, eval(r))
def test_repr(self): cwf_2_a = ConstantWaveform(duration=1.1, amplitude=2.2, channel='A') cwf_3 = ConstantWaveform(duration=1.1, amplitude=3.3, channel='A') swf = SequenceWaveform([cwf_2_a, cwf_3]) r = repr(swf) self.assertEqual(swf, eval(r))
def test_upload_offset_handling(self): program = Loop( waveform=ConstantWaveform(channel=1, duration=192, amplitude=0.1)) channel_pair = TaborChannelPair(self.instrument, identifier='asd', channels=(1, 2)) channels = (1, None) markers = (None, None) tabor_program_kwargs = dict( channels=channels, markers=markers, device_properties=channel_pair.device.dev_properties) amplitudes = (0.5, 0.3) test_sample_rate = TimeType.from_fraction(1, 1) test_amplitudes = (0.5 / 2, 0.3 / 2) test_offset = 0.1 test_transform = (lambda x: x, lambda x: x) with patch('qupulse.hardware.awgs.tabor.TaborProgram', wraps=TaborProgram) as tabor_program_mock: with patch.object(self.instrument, 'offset', return_value=test_offset) as offset_mock: tabor_program_mock.get_sampled_segments = mock.Mock( wraps=tabor_program_mock.get_sampled_segments) self.instrument.amplitude = mock.Mock(side_effect=amplitudes) self.instrument.sample_rate = mock.Mock(return_value=10**9) channel_pair.amplitude_offset_handling = AWGAmplitudeOffsetHandling.CONSIDER_OFFSET channel_pair.upload('test1', program, channels, markers, test_transform) tabor_program_mock.assert_called_once_with( program, **tabor_program_kwargs, sample_rate=test_sample_rate, amplitudes=test_amplitudes, offsets=(test_offset, test_offset), voltage_transformations=test_transform) self.assertEqual([mock.call(1), mock.call(2)], offset_mock.call_args_list) offset_mock.reset_mock() tabor_program_mock.reset_mock() self.instrument.amplitude = mock.Mock(side_effect=amplitudes) self.instrument.sample_rate = mock.Mock(return_value=10**9) channel_pair.amplitude_offset_handling = AWGAmplitudeOffsetHandling.IGNORE_OFFSET channel_pair.upload('test2', program, (1, None), (None, None), test_transform) tabor_program_mock.assert_called_once_with( program, **tabor_program_kwargs, sample_rate=test_sample_rate, amplitudes=test_amplitudes, offsets=(0., 0.), voltage_transformations=test_transform) self.assertEqual([], offset_mock.call_args_list)
def test_constness(self): waveform = ConstantWaveform(10, .1, 'P1') self.assertTrue(waveform.is_constant()) assert_constant_consistent(self, waveform)
def test_slot(self): wf = ConstantWaveform.from_mapping(1, {'f': 3}) with self.assertRaises(AttributeError): wf.asd = 5
def test_waveform_sample(self): waveform = ConstantWaveform(10, .1, 'P1') sample_times = [-1, 0, 1, 2] result = waveform.unsafe_sample('P1', sample_times) self.assertTrue(np.all(result == .1))
def test_waveform_duration(self): waveform = ConstantWaveform(10, 1., 'P1') self.assertEqual(waveform.duration, 10)