def test_issue_451(self): from qupulse.pulses import TablePT, SequencePT, AtomicMultiChannelPT gates_template = TablePT({'gate': [(0, 1), (60 * 1e3, 2, 'hold')]}) input_variables = {'period': float(gates_template.duration), 'uptime': 0} marker_sequence = (TablePT({'m': [(0, 1), ('uptime', 0), ('period', 0)]}), input_variables) combined_template = AtomicMultiChannelPT(gates_template, marker_sequence) combined_template.create_program() marker_sequence2 = TablePT({'m': [(0, 1), (0, 0), (gates_template.duration, 0)]}) combined_template2 = AtomicMultiChannelPT(gates_template, marker_sequence2) combined_template2.create_program()
def test_regression_sequencept_with_mappingpt(self): t1 = TablePT({'C1': [(0, 0), (100, 0)], 'C2': [(0, 1), (100, 1)]}) t2 = ConstantPulseTemplate(200, {'C1': 2, 'C2': 3}) qupulse_template = SequencePulseTemplate(t1, t2) channel_mapping = {'C1': None, 'C2': 'C2'} p = MappingPT(qupulse_template, channel_mapping=channel_mapping) plot(p) self.assertEqual(p.defined_channels, {'C2'})
def setUp(self) -> None: # define some building blocks self.sin_pt = FunctionPT('sin(omega*t)', 't_duration', channel='X') self.cos_pt = FunctionPT('sin(omega*t)', 't_duration', channel='Y') self.exp_pt = AtomicMultiChannelPT(self.sin_pt, self.cos_pt) self.tpt = TablePT({'X': [(0, 0), (3., 4.), ('t_duration', 2., 'linear')], 'Y': [(0, 1.), ('t_y', 5.), ('t_duration', 0., 'linear')]}) self.complex_pt = RepetitionPT(self.tpt, 5) @ self.exp_pt self.parameters = dict(t_duration=10, omega=3.14*2/10, t_y=3.4)
def hold(name): """Creates a DC offset qupulse template for sequencing. Args: name (str): The user defined name of the sequence. Returns: TablePT: The sequence with the wait pulse. """ return TablePT({name: [(0, 'offset'), ('period', 'offset')]})
def marker(name): """Creates a TTL pulse qupulse template for sequencing. Args: name (str): The user defined name of the sequence. Returns: TablePT: The sequence with the wait pulse. """ return TablePT({name: [(0, 0), ('offset', 1), ('offset+uptime', 0), ('period', 0)]})
def square(name): """ Creates a block wave qupulse template for sequencing. Args: name (str): The user defined name of the sequence. Returns: TablePT: The template with the square wave. """ return TablePT({name: [(0, 0), ('period/4', 'amplitude'), ('period*3/4', 0), ('period', 0)]})
def test_regression_template_combination(self): old_value = qupulse.utils.sympy.SYMPY_DURATION_ERROR_MARGIN try: qupulse.utils.sympy.SYMPY_DURATION_ERROR_MARGIN = 1e-9 duration_in_seconds = 2e-6 full_template = ConstantPulseTemplate(duration=duration_in_seconds * 1e9, amplitude_dict={'C1': 1.1}) duration_in_seconds_derived = 1e-9 * full_template.duration marker_pulse = TablePT({'marker': [(0, 0), (duration_in_seconds_derived * 1e9, 0)]}) full_template = AtomicMultiChannelPT(full_template, marker_pulse) finally: qupulse.utils.sympy.SYMPY_DURATION_ERROR_MARGIN = old_value
def sawtooth(name): """ Creates a sawtooth qupulse template for sequencing. Args: name (str): The user defined name of the sequence. Returns: TablePT: The sequence with the sawtooth wave. """ return TablePT({name: [(0, 0), ('period*(1-width)/2', '-amplitude', 'linear'), ('period*(1-(1-width)/2)', 'amplitude', 'linear'), ('period', 0, 'linear')]})
def sawtooth(name, padding=0): """ Creates a sawtooth qupulse template for sequencing. Args: name (str): The user defined name of the sequence. padding (float): Padding to add at the end of the sawtooth Returns: TablePT: The sequence with the sawtooth wave. """ tbl = [(0, 0), ('period*(1-width)/2', '-amplitude', 'linear'), ('period*(1-(1-width)/2)', 'amplitude', 'linear'), ('period', 0, 'linear')] if padding > 0: tbl += [(f'period+{padding}', 0, 'hold')] return TablePT({name: tbl})
def rollover_marker(name): """Creates a TTL pulse qupulse template for sequencing that rolls over to the subsequent period. --------- ---------- | | | | ---------- <---------period------------> <-----offset-----> <--------> uptime <---------> Args: name (str): The user defined name of the sequence. Returns: TablePT: The sequence with the marker pulse and rollover part of the pulse. """ return TablePT({ name: [(0, 1), ('offset + uptime - period', 0), ('offset', 1), ('period', 1)] })
def get_pulse_template(self) -> PulseTemplate: fpt = FunctionPT('sin(omega*t)', 't_duration', 'X', measurements=[('M', 0, 't_duration')]) tpt = TablePT( { 'Y': [(0, 'a'), ('t_duration', 2)], 'Z': [('t_duration', 1)] }, measurements=[('N', 0, 't_duration/2')]) mpt = MappingPT(fpt, parameter_mapping={'omega': '2*pi/t_duration'}, allow_partial_parameter_mapping=True) ampt = AtomicMultiChannelPT(mpt, tpt) body = ampt @ ampt rpt = RepetitionPT(body, 'N_rep', measurements=[('O', 0, 1)]) forpt = ForLoopPT(rpt, 'a', '6') final = SequencePT(rpt, forpt) return final
def skewed_sawtooth(name): r""" Creates a skewed sawtooth qupulse template for sequencing. This pulse is symmetric, has total integral zero and right at period/2 it has amplitude 0 and a sharp corner. A visual representation of the waveform is: A /\ /\ / \ / \ 0 / \ /\ / \ \ / \ / -A \/ \/ T/6 <-> T/3 <------> T/2 <---------> T <--------------------> T is period and A is the amplitude. Negative amplitude will produce an inverted pulse. Args: name (str): The user defined name of the sequence. Returns: TablePT: The sequence with the skewed sawtooth wave. Parameters of the pulse template are the `amplitude` and `period`. """ return TablePT({ name: [(0, 0), ('period/6', 'amplitude', 'linear'), ('period/3', '-amplitude', 'linear'), ('period/2', 0, 'linear'), ('period*2/3', '-amplitude', 'linear'), ('period*5/6', 'amplitude', 'linear'), ('period', 0, 'linear')] })
if __name__ == "__main__": from qupulse.pulses import TablePT, SequencePT, RepetitionPT hdawg = HDAWGRepresentation(device_serial='dev8075', device_interface='USB') entry_list1 = [(0, 0), (20, .2, 'hold'), (40, .3, 'linear'), (80, 0, 'jump')] entry_list2 = [(0, 0), (20, -.2, 'hold'), (40, -.3, 'linear'), (50, 0, 'jump')] entry_list3 = [(0, 0), (20, -.2, 'linear'), (50, -.3, 'linear'), (70, 0, 'jump')] tpt1 = TablePT({ 0: entry_list1, 1: entry_list2 }, measurements=[('m', 20, 30)]) tpt2 = TablePT({0: entry_list2, 1: entry_list1}) tpt3 = TablePT({ 0: entry_list3, 1: entry_list2 }, measurements=[('m', 10, 50)]) rpt = RepetitionPT(tpt1, 4) spt = SequencePT(tpt2, rpt) rpt2 = RepetitionPT(spt, 2) spt2 = SequencePT(rpt2, tpt3) p = spt2.create_program() ch = (0, 1)
def example_upload(hdawg_kwargs: dict, channels: Set[int], markers: Set[Tuple[int, int]]): # pragma: no cover from qupulse.pulses import TablePT, SequencePT, RepetitionPT if isinstance(hdawg_kwargs, dict): hdawg = HDAWGRepresentation(**hdawg_kwargs) else: hdawg = hdawg_kwargs assert not set(channels) - set(range(8)), "Channels must be in 0..=7" channels = sorted(channels) required_channels = {*channels, *(ch for ch, _ in markers)} channel_group = get_group_for_channels(hdawg, required_channels) channel_group_channels = range(channel_group.awg_group_index * channel_group.num_channels, (channel_group.awg_group_index + 1) * channel_group.num_channels) # choose length based on minimal sample rate sample_rate = channel_group.sample_rate / 10**9 min_t = channel_group.MIN_WAVEFORM_LEN / sample_rate quant_t = channel_group.WAVEFORM_LEN_QUANTUM / sample_rate assert min_t > 4 * quant_t, "Example not updated" entry_list1 = [(0, 0), (quant_t * 2, .2, 'hold'), (min_t, .3, 'linear'), (min_t + 3*quant_t, 0, 'jump')] entry_list2 = [(0, 0), (quant_t * 3, -.2, 'hold'), (min_t, -.3, 'linear'), (min_t + 4*quant_t, 0, 'jump')] entry_list3 = [(0, 0), (quant_t * 1, -.2, 'linear'), (min_t, -.3, 'linear'), (2*min_t, 0, 'jump')] entry_lists = [entry_list1, entry_list2, entry_list3] entry_dict1 = {ch: entry_lists[:2][i % 2] for i, ch in enumerate(channels)} entry_dict2 = {ch: entry_lists[1::-1][i % 2] for i, ch in enumerate(channels)} entry_dict3 = {ch: entry_lists[2:0:-1][i % 2] for i, ch in enumerate(channels)} tpt1 = TablePT(entry_dict1, measurements=[('m', 20, 30)]) tpt2 = TablePT(entry_dict2) tpt3 = TablePT(entry_dict3, measurements=[('m', 10, 50)]) rpt = RepetitionPT(tpt1, 4) spt = SequencePT(tpt2, rpt) rpt2 = RepetitionPT(spt, 2) spt2 = SequencePT(rpt2, tpt3) p = spt2.create_program() upload_ch = tuple(ch if ch in channels else None for ch in channel_group_channels) upload_mk = (None,) * channel_group.num_markers upload_vt = (lambda x: x,) * channel_group.num_channels channel_group.upload('pulse_test1', p, upload_ch, upload_mk, upload_vt) if markers: markers = sorted(markers) assert len(markers) == len(set(markers)) channel_group_markers = tuple((ch, mk) for ch in channel_group_channels for mk in (0, 1)) full_on = [(0, 1), (min_t, 1)] two_3rd = [(0, 1), (min_t*2/3, 0), (min_t, 0)] one_3rd = [(0, 0), (min_t*2/3, 1), (min_t, 1)] marker_start = TablePT({'m0': full_on, 'm1': full_on}) marker_body = TablePT({'m0': two_3rd, 'm1': one_3rd}) marker_test_pulse = marker_start @ RepetitionPT(marker_body, 10000) marker_program = marker_test_pulse.create_program() upload_ch = (None, ) * channel_group.num_channels upload_mk = tuple(f"m{mk}" if (ch, mk) in markers else None for (ch, mk) in channel_group_markers) channel_group.upload('marker_test', marker_program, upload_ch, upload_mk, upload_vt) try: while True: for program in channel_group.programs: print(f'playing {program}') channel_group.arm(program) channel_group.run_current_program() while not channel_group.was_current_program_finished(): print(f'waiting for {program} to finish') time.sleep(1e-2) finally: channel_group.enable(False)
def example_upload(hdawg_kwargs: dict, channels: Set[int], markers: Set[Tuple[int, int]]): from qupulse.pulses import TablePT, SequencePT, RepetitionPT if isinstance(hdawg_kwargs, dict): hdawg = HDAWGRepresentation(**hdawg_kwargs) else: hdawg = hdawg_kwargs assert not set(channels) - set(range(8)), "Channels must be in 0..=7" channels = sorted(channels) channel_tuples = [ ct for i, ct in enumerate(hdawg.channel_tuples) if i * 2 in channels or i * 2 + 1 in channels ] assert channel_tuples # choose length based on minimal sample rate min_sr = min(ct.sample_rate for ct in channel_tuples) / 10**9 min_t = channel_tuples[0].MIN_WAVEFORM_LEN / min_sr quant_t = channel_tuples[0].WAVEFORM_LEN_QUANTUM / min_sr assert min_t > 4 * quant_t, "Example not updated" entry_list1 = [(0, 0), (quant_t * 2, .2, 'hold'), (min_t, .3, 'linear'), (min_t + 3 * quant_t, 0, 'jump')] entry_list2 = [(0, 0), (quant_t * 3, -.2, 'hold'), (min_t, -.3, 'linear'), (min_t + 4 * quant_t, 0, 'jump')] entry_list3 = [(0, 0), (quant_t * 1, -.2, 'linear'), (min_t, -.3, 'linear'), (2 * min_t, 0, 'jump')] entry_lists = [entry_list1, entry_list2, entry_list3] entry_dict1 = {ch: entry_lists[:2][i % 2] for i, ch in enumerate(channels)} entry_dict2 = { ch: entry_lists[1::-1][i % 2] for i, ch in enumerate(channels) } entry_dict3 = { ch: entry_lists[2:0:-1][i % 2] for i, ch in enumerate(channels) } tpt1 = TablePT(entry_dict1, measurements=[('m', 20, 30)]) tpt2 = TablePT(entry_dict2) tpt3 = TablePT(entry_dict3, measurements=[('m', 10, 50)]) rpt = RepetitionPT(tpt1, 4) spt = SequencePT(tpt2, rpt) rpt2 = RepetitionPT(spt, 2) spt2 = SequencePT(rpt2, tpt3) p = spt2.create_program() # use HardwareSetup for this for ct in channel_tuples: i = hdawg.channel_tuples.index(ct) ch = tuple(ch if ch in channels else None for ch in (2 * i, 2 * i + 1)) mk = (None, None, None, None) vt = (lambda x: x, lambda x: x) ct.upload('pulse_test1', p, ch, mk, vt) for ct in channel_tuples: ct.arm('pulse_test1') # channel_tuples[0].run_current_program() if markers: markers = sorted(markers) assert len(markers) == len(set(markers)) channel_tuples = [] for ch, m in markers: assert ch in range(8) assert m in (0, 1) ct = hdawg.channel_tuples[ch // 2] if ct not in channel_tuples: channel_tuples.append(ct) full_on = [(0, 1), (min_t, 1)] two_3rd = [(0, 1), (min_t * 2 / 3, 0), (min_t, 0)] one_3rd = [(0, 0), (min_t * 2 / 3, 1), (min_t, 1)] marker_start = TablePT({'m1': full_on, 'm2': full_on}) marker_body = TablePT({'m1': two_3rd, 'm2': one_3rd}) marker_test_pulse = marker_start @ RepetitionPT(marker_body, 10000) marker_program = marker_test_pulse.create_program() for ct in channel_tuples: i = hdawg.channel_tuples.index(ct) ch = (None, None) mk = ('m1' if (i * 2, 0) in markers else None, 'm2' if (i * 2, 1) in markers else None, 'm1' if (i * 2 + 1, 0) in markers else None, 'm2' if (i * 2 + 1, 1) in markers else None) vt = (lambda x: x, lambda x: x) ct.upload('marker_test', marker_program, ch, mk, vt) ct.arm('marker_test') channel_tuples[0].run_current_program()
def pulse_table(name, entries): return TablePT({name: entries})
playback_name = '{name}_{ch_name}'.format(name=awg_name, ch_name=ch_name) hardware_setup.set_channel(playback_name, PlaybackChannel(channel_pair, ch_i)) hardware_setup.set_channel(playback_name + '_MARKER', MarkerChannel(channel_pair, ch_i)) awg_channel = channel_pairs[0] else: ValueError('Unknown AWG') #%% """ Create three simple pulses and put them together to a PulseTemplate called dnp """ plus = [(0, 0), ('ta', 'va', 'hold'), ('tb', 'vb', 'linear'), ('tend', 0, 'jump')] minus = [(0, 0), ('ta', '-va', 'hold'), ('tb', '-vb', 'linear'), ('tend', 0, 'jump')] zero_pulse = PointPT([(0, 0), ('tend', 0)], ('X', 'Y')) plus_pulse = TablePT(entries={'X': plus, 'Y': plus}) minus_pulse = TablePT(entries={'X': minus, 'Y': minus}) dnp = RepetitionPT(minus_pulse, 'n_minus') @ RepetitionPT(zero_pulse, 'n_zero') @ RepetitionPT(plus_pulse, 'n_plus') #%% """ Create a program dnp with the number of pulse repetitions as volatile parameters """ sample_rate = awg_channel.sample_rate / 10**9 n_quant = 192 t_quant = n_quant / sample_rate dnp_prog = dnp.create_program(parameters=dict(tend=float(t_quant), ta=float(t_quant/3), tb=float(2*t_quant/3), va=0.12, vb=0.25, n_minus=3, n_zero=3, n_plus=3), channel_mapping={'X': '{}_A'.format(awg_name), 'Y': '{}_B'.format(awg_name)}, volatile={'n_minus', 'n_zero', 'n_plus'})