def test_render_loop_compare(self) -> None: wf1 = DummyWaveform(duration=19) wf2 = DummyWaveform(duration=21) block = InstructionBlock() block.add_instruction_exec(wf1) block.add_instruction_meas([('asd', 0, 1), ('asd', 1, 1)]) block.add_instruction_exec(wf2) mcp = MultiChannelProgram(block) loop = next(iter(mcp.programs.values())) block_times, block_voltages, _ = render(block, sample_rate=0.5) loop_times, loop_voltages, _ = render(loop, sample_rate=0.5) numpy.testing.assert_equal(block_times, loop_times) numpy.testing.assert_equal(block_voltages, loop_voltages) block_times, block_voltages, block_measurements = render( block, sample_rate=0.5, render_measurements=True) loop_times, loop_voltages, loop_measurements = render( loop, sample_rate=0.5, render_measurements=True) numpy.testing.assert_equal(block_times, loop_times) numpy.testing.assert_equal(block_voltages, loop_voltages) self.assertEqual(block_measurements, loop_measurements)
def test_scaling(self): from qupulse.pulses import plotting parameters = {**self.parameters, 'foo': 5.3} t_ref, reference, _ = plotting.render(self.complex_pt.create_program(parameters=parameters)) for factor in (5, 5.3, 'foo'): scaled = factor * self.complex_pt real_scale = ExpressionScalar(factor).evaluate_numeric(**parameters) program = scaled.create_program(parameters=parameters) t, rendered, _ = plotting.render(program, 10.) np.testing.assert_equal(t_ref, t) for ch, volts in rendered.items(): np.testing.assert_allclose(reference[ch] * real_scale, volts) divided = self.complex_pt / factor t, rendered, _ = plotting.render(divided.create_program(parameters=parameters), 10.) np.testing.assert_equal(t_ref, t) for ch, volts in rendered.items(): np.testing.assert_allclose(reference[ch] / real_scale, volts) sel_scaled = {'X': factor} * self.complex_pt t, rendered, _ = plotting.render(sel_scaled.create_program(parameters=parameters), 10.) np.testing.assert_equal(t_ref, t) for ch, volts in rendered.items(): if ch == 'X': np.testing.assert_allclose(reference[ch] * real_scale, volts) else: np.testing.assert_equal(reference[ch], volts)
def test_render(self) -> None: with self.assertWarnsRegex(DeprecationWarning, ".*InstructionBlock.*"): wf1 = DummyWaveform(duration=19) wf2 = DummyWaveform(duration=21) block = InstructionBlock() block.add_instruction_exec(wf1) block.add_instruction_meas([('asd', 0, 1)]) block.add_instruction_exec(wf2) wf1_expected = ('A', [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]) wf2_expected = ('A', [ x - 19 for x in [20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40] ]) wf1_output_array_len_expected = len(wf1_expected[1]) wf2_output_array_len_expected = len(wf2_expected[1]) wf1.sample_output = numpy.linspace(start=4, stop=5, num=len(wf1_expected[1])) wf2.sample_output = numpy.linspace(6, 7, num=len(wf2_expected[1])) expected_times = numpy.arange(start=0, stop=42, step=2) expected_result = numpy.concatenate( (wf1.sample_output, wf2.sample_output)) times, voltages, _ = render(block, sample_rate=0.5) self.assertEqual(len(wf1.sample_calls), 1) self.assertEqual(len(wf2.sample_calls), 1) self.assertEqual(wf1_expected[0], wf1.sample_calls[0][0]) self.assertEqual(wf2_expected[0], wf2.sample_calls[0][0]) numpy.testing.assert_almost_equal(wf1_expected[1], wf1.sample_calls[0][1]) numpy.testing.assert_almost_equal(wf2_expected[1], wf2.sample_calls[0][1]) self.assertEqual(wf1_output_array_len_expected, len(wf1.sample_calls[0][2])) self.assertEqual(wf2_output_array_len_expected, len(wf2.sample_calls[0][2])) self.assertEqual(voltages.keys(), dict(A=0).keys()) numpy.testing.assert_almost_equal(expected_times, times) numpy.testing.assert_almost_equal(expected_result, voltages['A']) self.assertEqual(expected_result.shape, voltages['A'].shape) times, voltages, measurements = render(block, sample_rate=0.5, render_measurements=True) self.assertEqual(voltages.keys(), dict(A=0).keys()) numpy.testing.assert_almost_equal(expected_times, times) numpy.testing.assert_almost_equal(expected_result, voltages['A']) self.assertEqual(expected_result.shape, voltages['A'].shape) self.assertEqual(measurements, [('asd', 19, 1)])
def test_render_warning(self) -> None: wf1 = DummyWaveform(duration=19) wf2 = DummyWaveform(duration=21) program = Loop(children=[Loop(waveform=wf1), Loop(waveform=wf2)]) with self.assertWarns(UserWarning): render(program, sample_rate=0.51314323423)
def test_render_warning(self) -> None: wf1 = DummyWaveform(duration=19) wf2 = DummyWaveform(duration=21) block = InstructionBlock() block.add_instruction_exec(wf1) block.add_instruction_meas([('asd', 0, 1)]) block.add_instruction_exec(wf2) with self.assertWarns(UserWarning): render(block, sample_rate=0.51314323423)
def test_qupulse_template_to_array_new_style_vs_values_old_style(self): with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=UserWarning, message="qupulse") warnings.filterwarnings( "ignore", category=DeprecationWarning, message="InstructionBlock API is deprecated") period = 1e-3 amplitude = 1.5 sampling_rate = 1e9 sequence = Sequencer.make_sawtooth_wave(amplitude, period) template = sequence['wave'] channels = template.defined_channels loop = template.create_program( parameters=dict(), measurement_mapping={w: w for w in template.measurement_names}, channel_mapping={ch: ch for ch in channels}, global_transformation=None, to_single_waveform=set()) (_, voltages_new, _) = render(loop, sampling_rate / 1e9) # the value to compare to are calculated using qupulse 0.4 Sequencer class self.assertTrue(1000001 == len(voltages_new['sawtooth'])) self.assertAlmostEqual(-amplitude / 2, np.min(voltages_new['sawtooth']), 12) self.assertAlmostEqual(amplitude / 2, np.max(voltages_new['sawtooth']), 12)
def test_bug_422_mock(self): pt = TablePulseTemplate({'X': [(0, 1), (100, 1)]}) program = pt.create_program() mock_program = mock.Mock(spec=dir(program)) for attr in dir(Loop): if not attr.endswith('_'): setattr(mock_program, attr, getattr(program, attr)) mock_program.__len__ = lambda x: 1 mock_program.__iter__ = lambda x: iter(program) mock_program.__getitem__ = lambda x, idx: program[idx] self.assertNotIsInstance(mock_program, Loop) render(mock_program, sample_rate=1)
def __qupulse_template_to_array(sequence, sampling_rate): """ Renders a qupulse sequence as array with voltages. Args: sequence (dict): a waveform is a dictionary with "type" value given the used pulse library. The "wave" value should contain the actual wave-object. sampling_rate (float): The number of samples per second. Returns: voltages (np.array): The array with voltages generated from the template. """ sequencer = Sequencing() template = sequence['wave'] channels = template.defined_channels sequencer.push( template, dict(), channel_mapping={ch: ch for ch in channels}, window_mapping={w: w for w in template.measurement_names}) instructions = sequencer.build() if not sequencer.has_finished(): raise PlottingNotPossibleException(template) (_, voltages, _) = render(instructions, sampling_rate / Sequencer.__sec_to_ns) return np.array(voltages[next(iter(voltages))])
def test_bug_447(self): """Code from https://github.com/qutech/qupulse/issues/447""" TablePT = TablePulseTemplate SequencePT = SequencePulseTemplate Sequencing = Sequencer period = 8.192004194306148e-05 repetitions = 80 sampling_rate = 1e7 sec_to_ns = 1e9 table_pt = TablePT( {'test': [(0, 0), (period * sec_to_ns, 0, 'linear')]}) sequencer = Sequencing() template = SequencePT(*((table_pt, ) * repetitions)) channels = template.defined_channels sequencer.push( template, dict(), channel_mapping={ch: ch for ch in channels}, window_mapping={w: w for w in template.measurement_names}) instructions = sequencer.build() with self.assertWarns(UserWarning): (_, voltages, _) = render(instructions, sampling_rate / sec_to_ns)
def test_qupulse_template_to_array_new_style_vs_old_style(self): with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=UserWarning, message="qupulse") warnings.filterwarnings( "ignore", category=DeprecationWarning, message="InstructionBlock API is deprecated") period = 1e-3 amplitude = 1.5 sampling_rate = 1e9 sequence = Sequencer.make_sawtooth_wave(amplitude, period) template = sequence['wave'] channels = template.defined_channels sequencer = Sequencing() sequencer.push( template, dict(), channel_mapping={ch: ch for ch in channels}, window_mapping={w: w for w in template.measurement_names}) instructions = sequencer.build() if not sequencer.has_finished(): raise PlottingNotPossibleException(template) (_, voltages_old, _) = render(instructions, sampling_rate / 1e9) loop = template.create_program( parameters=dict(), measurement_mapping={w: w for w in template.measurement_names}, channel_mapping={ch: ch for ch in channels}, global_transformation=None, to_single_waveform=set()) (_, voltages_new, _) = render(loop, sampling_rate / 1e9) self.assertTrue(len(voltages_old) == len(voltages_new)) self.assertTrue(np.min(voltages_old) == np.min(voltages_old)) self.assertTrue(np.max(voltages_old) == np.max(voltages_old))
def test_render_block_time_slice(self) -> None: with self.assertWarnsRegex(DeprecationWarning, ".*InstructionBlock.*"): with self.assertRaises(ValueError): wf1 = DummyWaveform(duration=19) wf2 = DummyWaveform(duration=21) block = InstructionBlock() block.add_instruction_exec(wf1) block.add_instruction_exec(wf2) times, voltages, _ = render(block, sample_rate=0.5, time_slice=(1, 16))
def test_bug_447(self): """Adapted code from https://github.com/qutech/qupulse/issues/447""" TablePT = TablePulseTemplate SequencePT = SequencePulseTemplate period = 8.192004194306148e-05 repetitions = 80 sampling_rate = 1e7 sec_to_ns = 1e9 table_pt = TablePT( {'test': [(0, 0), (period * sec_to_ns, 0, 'linear')]}) template = SequencePT(*((table_pt, ) * repetitions)) program = template.create_program() with self.assertWarns(UserWarning): (_, voltages, _) = render(program, sampling_rate / sec_to_ns)
def integrated_test_with_sequencer_and_pulse_templates(self) -> None: # Setup test data square = TablePulseTemplate() square.add_entry('up', 'v', 'hold') square.add_entry('down', 0, 'hold') square.add_entry('length', 0) mapping1 = { 'up': 'uptime', 'down': 'uptime + length', 'v': 'voltage', 'length': '0.5 * pulse_length' } outer_parameters = ['uptime', 'length', 'pulse_length', 'voltage'] parameters = {} parameters['uptime'] = 5 parameters['length'] = 10 parameters['pulse_length'] = 100 parameters['voltage'] = 10 sequence = SequencePulseTemplate([(square, mapping1), (square, mapping1)], outer_parameters) # run the sequencer and render the plot sample_rate = 20 sequencer = Sequencer() sequencer.push(sequence, parameters) block = sequencer.build() times, voltages = render(block, sample_rate=sample_rate) # compute expected values expected_times = numpy.linspace(0, 100, sample_rate) expected_voltages = numpy.zeros_like(expected_times) expected_voltages[100:300] = numpy.ones(200) * parameters['voltage'] # compare self.assertEqual(expected_times, times) self.assertEqual(expected_voltages, voltages)
def test_render_loop_sliced(self) -> None: wf = DummyWaveform(duration=19) full_times = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] wf.sample_output = numpy.linspace(start=4, stop=5, num=len(full_times))[3:7] full_measurements = [('foo', 1, 3), ('bar', 5, 2), ('foo', 7, 3), ('bar', 11, 2), ('foo', 15, 3)] loop = Loop(waveform=wf, measurements=full_measurements) expected_times = full_times[3:7] expected_measurements = full_measurements[1:4] times, voltages, measurements = render(loop, sample_rate=0.5, render_measurements=True, time_slice=(6, 12)) numpy.testing.assert_almost_equal(expected_times, times) numpy.testing.assert_almost_equal(wf.sample_output, voltages['A']) self.assertEqual(expected_measurements, measurements)
def __qupulse_template_to_array(sequence, sampling_rate): """ Renders a qupulse sequence as array with voltages. Args: sequence (dict): a waveform is a dictionary with "type" value given the used pulse library. The "wave" value should contain the actual wave-object. sampling_rate (float): The number of samples per second. Returns: voltages (np.array): The array with voltages generated from the template. """ template = sequence['wave'] channels = template.defined_channels loop = template.create_program(parameters=dict(), measurement_mapping={w: w for w in template.measurement_names}, channel_mapping={ch: ch for ch in channels}, global_transformation=None, to_single_waveform=set()) (_, voltages, _) = render(loop, sampling_rate / Sequencer.__sec_to_ns) return np.array(voltages[next(iter(voltages))])
def test_render_loop_invalid_slice(self) -> None: with self.assertRaises(ValueError): render(Loop(waveform=DummyWaveform()), time_slice=(5, 1)) render(Loop(waveform=DummyWaveform()), time_slice=(-1, 4)) render(Loop(waveform=DummyWaveform()), time_slice=(-7, -3))
def test_render_no_waveforms(self) -> None: time, channel_data, measurements = render(InstructionBlock()) self.assertEqual(channel_data, dict()) self.assertEqual(measurements, []) numpy.testing.assert_equal(time, numpy.empty(0))
def test_render_unsupported_instructions(self) -> None: block = InstructionBlock() block.add_instruction(DummyInstruction()) with self.assertRaises(NotImplementedError): render(block)