def make_marker(period, uptime=0.2, offset=0.0, repetitions=1, name='marker'): """ Creates a marker block waveforms of the type qupulse template. Args: period (float): The period of the waveform in seconds. uptime (float): The marker up period in seconds. offset (float): The marker delay in seconds. repetitions (int): The number of oscillations in the sequence. name (str): The name of the returned sequence. Returns: Dict: *NAME*, *TYPE*, *WAVE* keys containing values; sequence name, sequence data type and the actual qupulse sequencePT respectively. """ if abs(offset) > period: raise ValueError('Invalid argument value for offset: |{}| > {}!'.format(offset, period)) if not 0 < uptime < period: raise ValueError("Invalid argument value for uptime '{}'!".format(uptime)) updated_offset = period + offset if offset < 0 else offset input_variables = {'period': period * Sequencer.__sec_to_ns, 'uptime': uptime * Sequencer.__sec_to_ns, 'offset': updated_offset * Sequencer.__sec_to_ns} rollover = updated_offset + uptime > period if rollover: warnings.warn('Marker rolls over to subsequent period.') pulse_template = Templates.rollover_marker(name) if rollover else Templates.marker(name) sequence_data = (pulse_template, input_variables) return {'name': name, 'wave': SequencePT(*((sequence_data,) * repetitions)), 'type': DataTypes.QU_PULSE, 'uptime': uptime, 'offset': offset}
def make_pulse_table(amplitudes, waiting_times, repetitions=1, name='pulse_table'): """ Creates a sequence of pulses from a list of amplitudes and waiting times. Note that the initial voltage level will be given by the last element in amplitudes. Args: amplitudes (list of floats): List with voltage amplitudes of the pulses. waiting_times (list of float): List with durations containing the waiting time of each pulse. repetitions (int): The number of oscillations in the sequence. name (str): The name of the returned sequence. Returns: Dict: *NAME*, *TYPE*, *WAVE* keys containing values; sequence name, sequence data type and the actual qupulse sequencePT respectively. """ if len(amplitudes) != len(waiting_times): raise ValueError( 'Arguments have invalid lengths! (amplitudes={}, waiting_times={}' .format(len(amplitudes), len(waiting_times))) time_in_ns = 0.0 entry_list = list() for waiting_time, amplitude in zip(waiting_times, amplitudes): time_in_ns += waiting_time * Sequencer.__sec_to_ns entry_list.append((time_in_ns, amplitude, 'jump')) sequence_data = Templates.pulse_table(name, entry_list) return { 'name': name, 'wave': SequencePT(*(sequence_data, ) * repetitions), 'type': DataTypes.QU_PULSE }
def make_sawtooth_wave(amplitude, period, width=0.95, repetitions=1, name='sawtooth'): """ Creates a sawtooth waveform of the type qupulse template. Args: amplitude (float): The peak-to-peak voltage of the waveform. width (float): The width of the rising ramp as a proportion of the total cycle. period (float): The period of the waveform in seconds. repetitions (int): The number of oscillations in the sequence. name (str): The name of the returned sequence. Returns: Dict: *NAME*, *TYPE*, *WAVE* keys containing values; sequence name, sequence data type and the actual qupulse sequencePT respectively. """ if width <= 0 or width >= 1: raise ValueError('Invalid argument value (0 < width < 1)!') input_variables = { 'period': period * Sequencer.__sec_to_ns, 'amplitude': amplitude / 2.0, 'width': width } sequence_data = (Templates.sawtooth(name), input_variables) return { 'name': name, 'wave': SequencePT(*((sequence_data, ) * repetitions)), 'type': DataTypes.QU_PULSE }
def make_square_wave(amplitude, period, repetitions=1, name='pulse'): """ Creates a block waveforms of the type qupulse template. Args: amplitude (float): The peak-to-peak voltage of the waveform. period (float): The period of the waveform in seconds. repetitions (int): The number of oscillations in the sequence. name (str): The name of the returned sequence. Returns: Dict: *NAME*, *TYPE*, *WAVE* keys containing values; sequence name, sequence data type and the actual qupulse sequencePT respectively. """ input_variables = {'period': period * Sequencer.__sec_to_ns, 'amplitude': amplitude / 2.0} sequence_data = (Templates.square(name), input_variables) return {'name': name, 'wave': SequencePT(*(sequence_data,) * repetitions), 'type': DataTypes.QU_PULSE}
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 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()
(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) mk = (0, None) vt = (lambda x: x, lambda x: x) hdawg.channel_pair_AB.upload('table_pulse_test1', p, ch, mk, vt) entry_list_zero = [(0, 0), (100, 0, 'hold')] entry_list_step = [(0, 0), (50, .5, 'hold'), (100, 0, 'hold')] marker_start = TablePT({'P1': entry_list_zero, 'marker': entry_list_step}) tpt1 = TablePT({'P1': entry_list_zero, 'marker': entry_list_zero}) spt2 = SequencePT(marker_start, tpt1)