def test_make_compatible(self): program = Loop() pub_kwargs = dict(minimal_waveform_length=5, waveform_quantum=10, sample_rate=time_from_float(1.)) priv_kwargs = dict(min_len=5, quantum=10, sample_rate=time_from_float(1.)) with mock.patch( 'qupulse._program._loop._is_compatible', return_value=_CompatibilityLevel.incompatible) as mocked: with self.assertRaisesRegex(ValueError, 'cannot be made compatible'): make_compatible(program, **pub_kwargs) mocked.assert_called_once_with(program, **priv_kwargs) with mock.patch( 'qupulse._program._loop._is_compatible', return_value=_CompatibilityLevel.action_required) as is_compat: with mock.patch( 'qupulse._program._loop._make_compatible') as make_compat: make_compatible(program, **pub_kwargs) is_compat.assert_called_once_with(program, **priv_kwargs) make_compat.assert_called_once_with(program, **priv_kwargs)
def test_default_time_from_float(self): # assert mocking did no permanent damage self.assertIs(gmpy2.mpq, qutypes.TimeType) self.assertEqual(qutypes.time_from_float(123 / 931), gmpy2.mpq(123, 931)) self.assertEqual(qutypes.time_from_float(1000000 / 1000001, 1e-5), gmpy2.mpq(1))
def test_unsafe_get_subset_for_channels(self): dwf_1 = DummyWaveform(duration=2.2, defined_channels={'A', 'B', 'C'}) dwf_2 = DummyWaveform(duration=3.3, defined_channels={'A', 'B', 'C'}) wf = SequenceWaveform([dwf_1, dwf_2]) subset = {'A', 'C'} sub_wf = wf.unsafe_get_subset_for_channels(subset) self.assertIsInstance(sub_wf, SequenceWaveform) self.assertEqual(len(sub_wf.compare_key), 2) self.assertEqual(sub_wf.compare_key[0].defined_channels, subset) self.assertEqual(sub_wf.compare_key[1].defined_channels, subset) self.assertEqual(sub_wf.compare_key[0].duration, time_from_float(2.2)) self.assertEqual(sub_wf.compare_key[1].duration, time_from_float(3.3))
def test_make_compatible_complete_unroll(self): wf1 = DummyWaveform(duration=1.5) wf2 = DummyWaveform(duration=2.0) program = Loop(children=[ Loop(waveform=wf1, repetition_count=2), Loop(waveform=wf2, repetition_count=1) ], repetition_count=2) _make_compatible(program, min_len=5, quantum=10, sample_rate=time_from_float(1.)) self.assertIsInstance(program.waveform, RepetitionWaveform) self.assertEqual(program.children, []) self.assertEqual(program.repetition_count, 1) self.assertIsInstance(program.waveform, RepetitionWaveform) self.assertIsInstance(program.waveform._body, SequenceWaveform) body_wf = program.waveform._body self.assertEqual(len(body_wf._sequenced_waveforms), 2) self.assertIsInstance(body_wf._sequenced_waveforms[0], RepetitionWaveform) self.assertIs(body_wf._sequenced_waveforms[0]._body, wf1) self.assertEqual(body_wf._sequenced_waveforms[0]._repetition_count, 2) self.assertIs(body_wf._sequenced_waveforms[1], wf2)
def test_is_compatible_leaf(self): self.assertEqual( _is_compatible(Loop(waveform=DummyWaveform(duration=1.1), repetition_count=10), min_len=11, quantum=1, sample_rate=time_from_float(1.)), _CompatibilityLevel.action_required) self.assertEqual( _is_compatible(Loop(waveform=DummyWaveform(duration=1.1), repetition_count=10), min_len=11, quantum=1, sample_rate=time_from_float(10.)), _CompatibilityLevel.compatible)
def __init__(self, duration: float = 0, sample_output: Union[numpy.ndarray, dict] = None, defined_channels={'A'}) -> None: super().__init__() self.duration_ = time_from_float(duration) self.sample_output = sample_output self.defined_channels_ = defined_channels self.sample_calls = []
def test_is_compatible_node(self): program = Loop(children=[ Loop(waveform=DummyWaveform(duration=1.5), repetition_count=2), Loop(waveform=DummyWaveform(duration=2.0)) ]) self.assertEqual( _is_compatible(program, min_len=1, quantum=1, sample_rate=time_from_float(2.)), _CompatibilityLevel.compatible) self.assertEqual( _is_compatible(program, min_len=1, quantum=1, sample_rate=time_from_float(1.)), _CompatibilityLevel.action_required)
def sample_rate(self) -> TimeType: """The default sample rate of the AWG channel group.""" node_path = '/{}/awgs/{}/time'.format(self.device.serial, self.awg_group_index) sample_rate_num = self.device.api_session.getInt(node_path) node_path = '/{}/system/clocks/sampleclock/freq'.format(self.device.serial) sample_clock = self.device.api_session.getDouble(node_path) """Calculate exact rational number based on (sample_clock Sa/s) / 2^sample_rate_num. Otherwise numerical imprecision will give rise to errors for very long pulses. fractions.Fraction does not accept floating point numerator, which sample_clock could potentially be.""" return time_from_float(sample_clock) / 2 ** sample_rate_num
def test_make_compatible_repetition_count(self): wf1 = DummyWaveform(duration=1.5) wf2 = DummyWaveform(duration=2.0) program = Loop(children=[ Loop(waveform=wf1, repetition_count=2), Loop(waveform=wf2) ]) duration = program.duration _make_compatible(program, min_len=1, quantum=1, sample_rate=time_from_float(1.)) self.assertEqual(program.duration, duration) wf2 = DummyWaveform(duration=2.5) program = Loop(children=[ Loop(waveform=wf1, repetition_count=3), Loop(waveform=wf2) ]) duration = program.duration with self.assertWarns(MakeCompatibleWarning): make_compatible(program, minimal_waveform_length=1, waveform_quantum=1, sample_rate=time_from_float(1.)) self.assertEqual(program.duration, duration) program = Loop(children=[ Loop(waveform=wf1, repetition_count=3), Loop(waveform=wf2) ], repetition_count=3) duration = program.duration _make_compatible(program, min_len=1, quantum=3, sample_rate=time_from_float(1.)) self.assertEqual(program.duration, duration)
def test_is_compatible_incompatible(self): wf = DummyWaveform(duration=1.1) self.assertEqual( _is_compatible(Loop(waveform=wf), min_len=1, quantum=1, sample_rate=time_from_float(1.)), _CompatibilityLevel.incompatible) self.assertEqual( _is_compatible(Loop(waveform=wf, repetition_count=10), min_len=20, quantum=1, sample_rate=time_from_float(1.)), _CompatibilityLevel.incompatible) self.assertEqual( _is_compatible(Loop(waveform=wf, repetition_count=10), min_len=10, quantum=3, sample_rate=time_from_float(1.)), _CompatibilityLevel.incompatible)
def test_is_compatible_warnings(self): wf = DummyWaveform(duration=1) volatile_repetition_count = VolatileRepetitionCount( ExpressionScalar('x'), DictScope.from_kwargs(x=3, volatile={'x'})) volatile_leaf = Loop(waveform=wf, repetition_count=volatile_repetition_count) with self.assertWarns(VolatileModificationWarning): self.assertEqual( _CompatibilityLevel.action_required, _is_compatible(volatile_leaf, min_len=3, quantum=1, sample_rate=time_from_float(1.))) volatile_node = Loop(children=[Loop(waveform=wf)], repetition_count=volatile_repetition_count) with self.assertWarns(VolatileModificationWarning): self.assertEqual( _CompatibilityLevel.action_required, _is_compatible(volatile_node, min_len=3, quantum=1, sample_rate=time_from_float(1.)))
def __init__(self, expression: ExpressionScalar, duration: float, channel: ChannelID) -> None: """Creates a new FunctionWaveform instance. Args: expression: The function represented by this FunctionWaveform as a mathematical expression where 't' denotes the time variable. It must not have other variables duration: The duration of the waveform measurement_windows: A list of measurement windows channel: The channel this waveform is played on """ super().__init__() if set(expression.variables) - set('t'): raise ValueError( 'FunctionWaveforms may not depend on anything but "t"') self._expression = expression self._duration = time_from_float(duration) self._channel_id = channel
def test_init_several_channels(self) -> None: dwf_a = DummyWaveform(duration=2.2, defined_channels={'A'}) dwf_b = DummyWaveform(duration=2.2, defined_channels={'B'}) dwf_c = DummyWaveform(duration=2.3, defined_channels={'C'}) waveform = MultiChannelWaveform([dwf_a, dwf_b]) self.assertEqual({'A', 'B'}, waveform.defined_channels) self.assertEqual(time_from_float(2.2), waveform.duration) with self.assertRaises(ValueError): MultiChannelWaveform([dwf_a, dwf_c]) with self.assertRaises(ValueError): MultiChannelWaveform([waveform, dwf_c]) with self.assertRaises(ValueError): MultiChannelWaveform((dwf_a, dwf_a)) dwf_c_valid = DummyWaveform(duration=2.2, defined_channels={'C'}) waveform_flat = MultiChannelWaveform((waveform, dwf_c_valid)) self.assertEqual(len(waveform_flat.compare_key), 3)
def _to_time_type(duration: Real) -> TimeType: if isinstance(duration, TimeType): return duration else: return time_from_float(float(duration), absolute_error=PULSE_TO_WAVEFORM_ERROR)
def test_from_float_exceptions(self): with self.assertRaisesRegex(ValueError, 'at least 0'): qutypes.time_from_float(.8, -1) with self.assertRaisesRegex(ValueError, 'smaller 1'): qutypes.time_from_float(.8, 2)
def duration(self) -> TimeType: return time_from_float(float(self._duration), absolute_error=PULSE_TO_WAVEFORM_ERROR)
def duration(self) -> TimeType: return time_from_float(self._table[-1].t)
def test_duration(self): wf = RepetitionWaveform(DummyWaveform(duration=2.2), 3) self.assertEqual(wf.duration, time_from_float(2.2) * 3)
def test_init_single_channel(self) -> None: dwf = DummyWaveform(duration=1.3, defined_channels={'A'}) waveform = MultiChannelWaveform([dwf]) self.assertEqual({'A'}, waveform.defined_channels) self.assertEqual(time_from_float(1.3), waveform.duration)
def get_from_float(fs): return [qutypes.time_from_float(f) for f in fs]
def test_from_float_exceptions(self): with self.assertRaisesRegex(ValueError, '> 0'): qutypes.time_from_float(.8, -1) with self.assertRaisesRegex(ValueError, '<= 1'): qutypes.time_from_float(.8, 2)
def test_duration(self) -> None: wf = FunctionWaveform(expression=Expression('2*t'), duration=4/5, channel='A') self.assertEqual(time_from_float(4/5), wf.duration)