def ramsey_seq_multiple_detunings(times, pulse_pars, RO_pars, artificial_detunings=None, cal_points=True, upload=True, return_seq=False): ''' Ramsey sequence for a single qubit using the tektronix. SSB_Drag pulse is used for driving, simple modualtion used for RO !!! Each value in the times array must be repeated len(artificial_detunings) times!!! Input pars: times: array of times between (start of) pulses (s) pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters artificial_detunings: list of artificial_detunings (Hz) implemented using phase cal_points: whether to use calibration points or not ''' seq_name = 'Ramsey_sequence_multiple_detunings' seq = sequence.Sequence(seq_name) ps.Pulsar.get_instance().update_channel_settings() seg_list = [] # First extract values from input, later overwrite when generating # waveforms pulses = get_pulse_dict_from_pars(pulse_pars) pulse_pars_x2 = deepcopy(pulses['X90']) pulse_pars_x2['ref_point'] = 'start' for i, tau in enumerate(times): pulse_pars_x2['pulse_delay'] = tau art_det = artificial_detunings[i % len(artificial_detunings)] if art_det is not None: Dphase = ((tau - times[0]) * art_det * 360) % 360 pulse_pars_x2['phase'] = Dphase if cal_points and (i == (len(times) - 4) or i == (len(times) - 3)): seg = segment.Segment('segment_{}'.format(i), [pulses['I'], RO_pars]) elif cal_points and (i == (len(times) - 2) or i == (len(times) - 1)): seg = segment.Segment('segment_{}'.format(i), [pulses['X180'], RO_pars]) else: seg = segment.Segment('segment_{}'.format(i), [pulses['X90'], pulse_pars_x2, RO_pars]) seg_list.append(seg) seq.add(seg) if upload: ps.Pulsar.get_instance().program_awgs(seq) if return_seq: return seq, seg_list else: return seq_name
def ramsey_seq_VZ(times, pulse_pars, RO_pars, artificial_detuning=None, cal_points=True, upload=True, return_seq=False): ''' Ramsey sequence for a single qubit using the tektronix. SSB_Drag pulse is used for driving, simple modualtion used for RO Input pars: times: array of times between (start of) pulses (s) pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters artificial_detuning: artificial_detuning (Hz) implemented using phase cal_points: whether to use calibration points or not ''' if np.any(times > 1e-3): logging.warning('The values in the times array might be too large.' 'The units should be seconds.') seq_name = 'Ramsey_sequence' seq = sequence.Sequence(seq_name) seg_list = [] # First extract values from input, later overwrite when generating # waveforms pulses = get_pulse_dict_from_pars(pulse_pars) pulse_pars_x2 = deepcopy(pulses['X90']) pulse_pars_x2['ref_point'] = 'start' for i, tau in enumerate(times): pulse_pars_x2['pulse_delay'] = tau if artificial_detuning is not None: Dphase = ((tau - times[0]) * artificial_detuning * 360) % 360 else: Dphase = ((tau - times[0]) * 1e6 * 360) % 360 Z_gate = Z(Dphase, pulse_pars) if cal_points and (i == (len(times) - 4) or i == (len(times) - 3)): seg = segment.Segment('segment_{}'.format(i), [pulses['I'], RO_pars]) elif cal_points and (i == (len(times) - 2) or i == (len(times) - 1)): seg = segment.Segment('segment_{}'.format(i), [pulses['X180'], RO_pars]) else: pulse_list = [pulses['X90'], Z_gate, pulse_pars_x2, RO_pars] seg = segment.Segment('segment_{}'.format(i), pulse_list) seg_list.append(seg) seq.add(seg) if upload: ps.Pulsar.get_instance().program_awgs(seq) if return_seq: return seq, seg_list else: return seq_name
def echo_seq(times, pulse_pars, RO_pars, artificial_detuning=None, cal_points=True, upload=True, return_seq=False): ''' Echo sequence for a single qubit using the tektronix. Input pars: times: array of times between (start of) pulses (s) artificial_detuning: artificial_detuning (Hz) implemented using phase pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters cal_points: whether to use calibration points or not ''' seq_name = 'Echo_sequence' seq = sequence.Sequence(seq_name) seg_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) center_X180 = deepcopy(pulses['X180']) final_X90 = deepcopy(pulses['X90']) center_X180['ref_point'] = 'start' final_X90['ref_point'] = 'start' for i, tau in enumerate(times): center_X180['pulse_delay'] = tau / 2 final_X90['pulse_delay'] = tau / 2 if artificial_detuning is not None: final_X90['phase'] = (tau - times[0]) * artificial_detuning * 360 if cal_points and (i == (len(times) - 4) or i == (len(times) - 3)): seg = segment.Segment('segment_{}'.format(i), [pulses['I'], RO_pars]) elif cal_points and (i == (len(times) - 2) or i == (len(times) - 1)): seg = segment.Segment('segment_{}'.format(i), [pulses['X180'], RO_pars]) else: seg = segment.Segment( 'segment_{}'.format(i), [pulses['X90'], center_X180, final_X90, RO_pars]) seg_list.append(seg) seq.add(seg) if upload: ps.Pulsar.get_instance().program_awgs(seq) if return_seq: return seq, seg_list else: return seq_name
def interleaved_pulse_list_equatorial_seg(qubit_names, operation_dict, interleaved_pulse_list, phase, pihalf_spacing=None, prep_params=None, segment_name='equatorial_segment'): prep_params = {} if prep_params is None else prep_params pulse_list = [] for notfirst, qbn in enumerate(qubit_names): pulse_list.append(deepcopy(operation_dict['X90 ' + qbn])) pulse_list[-1]['ref_point'] = 'start' if not notfirst: pulse_list[-1]['name'] = 'refpulse' pulse_list += interleaved_pulse_list for notfirst, qbn in enumerate(qubit_names): pulse_list.append(deepcopy(operation_dict['X90 ' + qbn])) pulse_list[-1]['phase'] = phase if notfirst: pulse_list[-1]['ref_point'] = 'start' elif pihalf_spacing is not None: pulse_list[-1]['ref_pulse'] = 'refpulse' pulse_list[-1]['ref_point'] = 'start' pulse_list[-1]['pulse_delay'] = pihalf_spacing pulse_list += generate_mux_ro_pulse_list(qubit_names, operation_dict) pulse_list = add_preparation_pulses(pulse_list, operation_dict, qubit_names, **prep_params) return segment.Segment(segment_name, pulse_list)
def n_qubit_ref_seq(qubit_names, operation_dict, ref_desc, upload=True, return_seq=False, preselection=False, ro_spacing=1e-6): """ Calibration points for arbitrary combinations Arguments: qubits: List of calibrated qubits for obtaining the pulse dictionaries. ref_desc: Description of the calibration sequence. Dictionary name of the state as key, and list of pulses names as values. """ # create the elements seq_name = 'Calibration' seq = sequence.Sequence(seq_name) seg_list = [] # calibration elements # calibration_sequences = [] # for pulses in ref_desc: # calibration_sequences.append( # [pulse+' '+qb for qb, pulse in zip(qubit_names, pulses)]) calibration_sequences = [] for pulses in ref_desc: calibration_sequence_new = [] for i, pulse in enumerate(pulses): if i == 0: qb = ' ' + qubit_names[i] else: qb = 's ' + qubit_names[i] calibration_sequence_new.append(pulse + qb) calibration_sequences.append(calibration_sequence_new) for i, calibration_sequence in enumerate(calibration_sequences): pulse_list = [] pulse_list.extend( [operation_dict[pulse] for pulse in calibration_sequence]) ro_pulses = generate_mux_ro_pulse_list(qubit_names, operation_dict) pulse_list.extend(ro_pulses) if preselection: ro_pulses_presel = generate_mux_ro_pulse_list( qubit_names, operation_dict, 'RO_presel', 'start', -ro_spacing) pulse_list.extend(ro_pulses_presel) seg = segment.Segment('calibration_{}'.format(i), pulse_list) seg_list.append(seg) seq.add(seg) if upload: ps.Pulsar.get_instance().program_awgs(seq) if return_seq: return seq, seg_list else: return seq_name
def pulse_list_list_seq(pulse_list_list, name='pulse_list_list_sequence', upload=True, fast_mode=False): seq = sequence.Sequence(name) for i, pulse_list in enumerate(pulse_list_list): seq.add( segment.Segment('segment_{}'.format(i), pulse_list, fast_mode=fast_mode)) if upload: ps.Pulsar.get_instance().program_awgs(seq) return seq
def n_qubit_tomo_seq(qubit_names, operation_dict, prep_sequence=None, prep_name=None, rots_basis=tomo.DEFAULT_BASIS_ROTS, upload=True, return_seq=False, preselection=False, ro_spacing=1e-6): """ """ # create the sequence if prep_name is None: seq_name = 'N-qubit tomography' else: seq_name = prep_name + ' tomography' seq = sequence.Sequence(seq_name) seg_list = [] if prep_sequence is None: prep_sequence = ['Y90 ' + qubit_names[0]] # tomography elements tomography_sequences = get_tomography_pulses(*qubit_names, basis_pulses=rots_basis) for i, tomography_sequence in enumerate(tomography_sequences): pulse_list = [operation_dict[pulse] for pulse in prep_sequence] # tomography_sequence.append('RO mux') # if preselection: # tomography_sequence.append('RO mux_presel') # tomography_sequence.append('RO presel_dummy') pulse_list.extend( [operation_dict[pulse] for pulse in tomography_sequence]) ro_pulses = generate_mux_ro_pulse_list(qubit_names, operation_dict) pulse_list.extend(ro_pulses) if preselection: ro_pulses_presel = generate_mux_ro_pulse_list( qubit_names, operation_dict, 'RO_presel', 'start', -ro_spacing) pulse_list.extend(ro_pulses_presel) seg = segment.Segment('tomography_{}'.format(i), pulse_list) seg_list.append(seg) seq.add(seg) if upload: ps.Pulsar.get_instance().program_awgs(seq) if return_seq: return seq, seg_list else: return seq_name
def over_under_rotation_seq(qb_name, nr_pi_pulses_array, operation_dict, pi_pulse_amp=None, cal_points=True, upload=True): seq_name = 'Over-under rotation sequence' seq = sequence.Sequence(seq_name) seg_list = [] X90 = deepcopy(operation_dict['X90 ' + qb_name]) X180 = deepcopy(operation_dict['X180 ' + qb_name]) if pi_pulse_amp is not None: X90['amplitude'] = pi_pulse_amp / 2 X180['amplitude'] = pi_pulse_amp for i, N in enumerate(nr_pi_pulses_array): if cal_points and (i == (len(nr_pi_pulses_array) - 4) or i == (len(nr_pi_pulses_array) - 3)): seg = segment.Segment('segment_{}'.format(i), [ operation_dict['I ' + qb_name], operation_dict['RO ' + qb_name] ]) elif cal_points and (i == (len(nr_pi_pulses_array) - 2) or i == (len(nr_pi_pulses_array) - 1)): seg = segment.Segment('segment_{}'.format(i), [ operation_dict['X180 ' + qb_name], operation_dict['RO ' + qb_name] ]) else: pulse_list = [X90] pulse_list += N * [X180] pulse_list += [operation_dict['RO ' + qb_name]] seg = segment.Segment('segment_{}'.format(i), pulse_list) seg_list.append(seg) seq.add(seg) if upload: ps.Pulsar.get_instance().program_awgs(seq) return
def single_state_active_reset(operation_dict, qb_name, state='e', upload=True, prep_params={}): ''' OffOn sequence for a single qubit using the tektronix. SSB_Drag pulse is used for driving, simple modualtion used for RO Input pars: pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters pulse_pars_2nd: dict containing the pulse parameters of ef transition. Required if state is 'f'. Initialize: adds an exta measurement before state preparation to allow initialization by post-selection Post-measurement delay: should be sufficiently long to avoid photon-induced gate errors when post-selecting. state: specifies for which state a pulse should be generated (g,e,f) preselection: adds an extra readout pulse before other pulses. ''' seq_name = 'single_state_sequence' seq = sequence.Sequence(seq_name) # Create dicts with the parameters for all the pulses state_ops = dict(g=["I", "RO"], e=["X180", "RO"], f=["X180", "X180_ef", "RO"]) pulses = [ deepcopy(operation_dict[op]) for op in add_suffix(state_ops[state], " " + qb_name) ] #add preparation pulses pulses_with_prep = \ add_preparation_pulses(pulses, operation_dict, [qb_name], **prep_params) seg = segment.Segment('segment_{}_level'.format(state), pulses_with_prep) seq.add(seg) # reuse sequencer memory by repeating readout pattern seq.repeat_ro(f"RO {qb_name}", operation_dict) if upload: ps.Pulsar.get_instance().program_awgs(seq) return seq, np.arange(seq.n_acq_elements())
def readout_pulse_scope_seq(delays, pulse_pars, RO_pars, RO_separation, cal_points=((-4, -3), (-2, -1)), comm_freq=225e6, upload=True, return_seq=False, prep_pulses=None, verbose=False): """ Prepares the AWGs for a readout pulse shape and timing measurement. The sequence consists of two readout pulses where the drive pulse start time is swept through the first readout pulse. Because the photons in the readout resonator induce an ac-Stark shift of the qubit frequency, we can determine the readout pulse shape by sweeping the drive frequency in an outer loop to determine the qubit frequency. Important: This sequence includes two readouts per segment. For this reason the calibration points are also duplicated. Args: delays: A list of delays between the start of the first readout pulse and the end of the drive pulse. pulse_pars: Pulse dictionary for the drive pulse. RO_pars: Pulse dictionary for the readout pulse. RO_separation: Separation between the starts of the two readout pulses. If the comm_freq parameter is not None, the used value is increased to satisfy the commensurability constraint. cal_points: True for default calibration points, False for no calibration points or a list of two lists, containing the indices of the calibration segments for the ground and excited state. comm_freq: The readout pulse separation will be a multiple of 1/comm_freq Returns: The sequence object and the element list if return_seq is True. Else return the sequence name. """ if cal_points: cal_points = ((-4, -3), (-2, -1)) elif not cal_points or cal_points is None: cal_points = ((), ()) if prep_pulses is None: prep_pulses = [] if comm_freq: RO_separation -= RO_separation % (-1 / comm_freq) seq_name = 'readout_pulse_scope_sequence' seq = sequence.Sequence(seq_name) seg_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) min_delay = min(delays) readout_x1 = deepcopy(RO_pars) readout_x1['ref_point'] = 'end' readout_x2 = deepcopy(RO_pars) readout_x2['pulse_delay'] = RO_separation readout_x2['ref_point'] = 'start' probe_pulse = deepcopy(pulses['X180']) prep_pulses = [deepcopy(pulses[pulse_name]) for pulse_name in prep_pulses] for pulse in prep_pulses: pulse['pulse_delay'] = -2 * np.abs(min_delay) for i, tau in enumerate(delays): if i in cal_points[0] or i - len(delays) in cal_points[0]: seg = segment.Segment('segment_{}'.format(2 * i), [pulses['I'], RO_pars]) seg_list.append(seg) seq.add(seg) seg = segment.Segment('segment_{}'.format(2 * i + 1), [pulses['I'], RO_pars]) seg_list.append(seg) seq.add(seg) elif i in cal_points[1] or i - len(delays) in cal_points[1]: seg = segment.Segment('segment_{}'.format(2 * i), [pulses['X180'], RO_pars]) seg_list.append(seg) seq.add(seg) seg = segment.Segment('segment_{}'.format(2 * i + 1), [pulses['X180'], RO_pars]) seg_list.append(seg) seq.add(seg) else: probe_pulse['pulse_delay'] = tau - min_delay readout_x1['pulse_delay'] = -tau seg = segment.Segment( 'segment_{}'.format(2 * i), prep_pulses + [probe_pulse, readout_x1, readout_x2]) seg_list.append(seg) seq.add(seg) if upload: ps.Pulsar.get_instance().program_awgs(seq) if return_seq: return seq, seg_list else: return seq_name
def create_segments(self, operation_dict, pulse_modifs=None, segment_prefix='calibration_', **prep_params): segments = [] if pulse_modifs is None: pulse_modifs = dict() if self.pulse_modifs is not None: pm = deepcopy(self.pulse_modifs) pm.update(pulse_modifs) pulse_modifs = pm for i, seg_states in enumerate(self.states): pulse_list = [] for j, qbn in enumerate(self.qb_names): unique, counts = np.unique(self.get_states(qbn)[qbn], return_counts=True) cal_pt_idx = i % np.squeeze( counts[np.argwhere(unique == seg_states[j])]) for k, pulse_name in enumerate( self.pulse_label_map[seg_states[j]]): pulse = deepcopy(operation_dict[pulse_name + qbn]) pulse['name'] = f"{seg_states[j]}_{pulse_name + qbn}_" \ f"{cal_pt_idx}" if k == 0: pulse['ref_pulse'] = 'segment_start' if len(pulse_modifs) > 0: # The pulse(s) to which the pulse_modifs refer might # not be present in all calibration segments. We # thus disable the pulse_not_found_warning. pulse = sweep_pulse_params( [pulse], pulse_modifs, pulse_not_found_warning=False)[0][0] # reset the name as sweep_pulse_params deletes it pulse['name'] = f"{seg_states[j]}_{pulse_name + qbn}_" \ f"{cal_pt_idx}" pulse_list.append(pulse) state_prep_pulse_names = [p['name'] for p in pulse_list] pulse_list = add_preparation_pulses(pulse_list, operation_dict, [qbn for qbn in self.qb_names], **prep_params) ro_pulses = generate_mux_ro_pulse_list(self.qb_names, operation_dict) # reference all readout pulses to all pulses of the pulse list, to ensure # readout happens after the last pulse (e.g. if doing "f" on some qubits # and "e" on others). In the future we could use the circuitBuilder # and Block here [ rp.update({ 'ref_pulse': state_prep_pulse_names, "ref_point": 'end' }) for rp in ro_pulses ] pulse_list += ro_pulses seg = segment.Segment(segment_prefix + f'{i}', pulse_list) segments.append(seg) return segments
def ramsey_seq_cont_drive(times, pulse_pars, RO_pars, artificial_detuning=None, cal_points=True, upload=True, return_seq=False, **kw): ''' Ramsey sequence for a single qubit using the tektronix. SSB_Drag pulse is used for driving, simple modualtion used for RO Input pars: times: array of times between (start of) pulses (s) pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters artificial_detuning: artificial_detuning (Hz) implemented using phase cal_points: whether to use calibration points or not ''' if np.any(times > 1e-3): logging.warning('The values in the times array might be too large.' 'The units should be seconds.') seq_name = 'Ramsey_sequence' seq = sequence.Sequence(seq_name) seg_list = [] # First extract values from input, later overwrite when generating # waveforms pulses = get_pulse_dict_from_pars(pulse_pars) pulse_pars_x2 = deepcopy(pulses['X90']) DRAG_length = pulse_pars['nr_sigma'] * pulse_pars['sigma'] cont_drive_ampl = 0.1 * pulse_pars['amplitude'] X180_pulse = deepcopy(pulses['X180']) cos_pulse = { 'pulse_type': 'CosPulse_gauss_rise', 'channel': X180_pulse['I_channel'], 'frequency': X180_pulse['mod_frequency'], 'length': 0, 'phase': X180_pulse['phi_skew'], 'amplitude': cont_drive_ampl * X180_pulse['alpha'], 'pulse_delay': 0, 'ref_point': 'end' } sin_pulse = { 'pulse_type': 'CosPulse_gauss_rise', 'channel': X180_pulse['Q_channel'], 'frequency': X180_pulse['mod_frequency'], 'length': 0, 'phase': 90, 'amplitude': cont_drive_ampl * X180_pulse['alpha'], 'pulse_delay': 0, 'ref_point': 'simultaneous' } for i, tau in enumerate(times): if artificial_detuning is not None: Dphase = ((tau - times[0]) * artificial_detuning * 360) % 360 pulse_pars_x2['phase'] = Dphase if cal_points and (i == (len(times) - 4) or i == (len(times) - 3)): seg = segment.Segment('segment_{}'.format(i), [pulses['I'], RO_pars]) elif cal_points and (i == (len(times) - 2) or i == (len(times) - 1)): seg = segment.Segment('segment_{}'.format(i), [pulses['X180'], RO_pars]) else: X90_separation = tau - DRAG_length if X90_separation > 0: pulse_pars_x2['ref_point'] = 'end' cos_pls1 = deepcopy(cos_pulse) sin_pls1 = deepcopy(sin_pulse) cos_pls1['length'] = X90_separation / 2 sin_pls1['length'] = X90_separation / 2 cos_pls2 = deepcopy(cos_pls1) sin_pls2 = deepcopy(sin_pls1) cos_pls2['amplitude'] = -cos_pls1['amplitude'] cos_pls2['pulse_type'] = 'CosPulse_gauss_fall' sin_pls2['amplitude'] = -sin_pls1['amplitude'] sin_pls2['pulse_type'] = 'CosPulse_gauss_fall' pulse_dict_list = [ pulses['X90'], cos_pls1, sin_pls1, cos_pls2, sin_pls2, pulse_pars_x2, RO_pars ] else: pulse_pars_x2['ref_point'] = 'start' pulse_pars_x2['pulse_delay'] = tau pulse_dict_list = [pulses['X90'], pulse_pars_x2, RO_pars] seg = segment.Segment('segment_{}'.format(i), pulse_dict_list) seg_list.append(seg) seq.add(seg) if upload: ps.Pulsar.get_instance().program_awgs(seq) if return_seq: return seq, seg_list else: return seq_name
def ramsey_seq_Echo(times, pulse_pars, RO_pars, nr_echo_pulses=4, artificial_detuning=None, cal_points=True, cpmg_scheme=True, upload=True, return_seq=False): ''' Ramsey sequence for a single qubit using the tektronix. SSB_Drag pulse is used for driving, simple modualtion used for RO Input pars: times: array of times between (start of) pulses (s) pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters artificial_detuning: artificial_detuning (Hz) implemented using phase cal_points: whether to use calibration points or not ''' if np.any(times > 1e-3): logging.warning('The values in the times array might be too large.' 'The units should be seconds.') seq_name = 'Ramsey_sequence' seq = sequence.Sequence(seq_name) seg_list = [] # First extract values from input, later overwrite when generating # waveforms pulses = get_pulse_dict_from_pars(pulse_pars) pulse_pars_x2 = deepcopy(pulses['X90']) pulse_pars_x2['ref_point'] = 'start' X180_pulse = deepcopy(pulses['X180']) Echo_pulses = nr_echo_pulses * [X180_pulse] DRAG_length = pulse_pars['nr_sigma'] * pulse_pars['sigma'] for i, tau in enumerate(times): if artificial_detuning is not None: Dphase = ((tau - times[0]) * artificial_detuning * 360) % 360 pulse_pars_x2['phase'] = Dphase if cal_points and (i == (len(times) - 4) or i == (len(times) - 3)): seg = segment.Segment('segment_{}'.format(i), [pulses['I'], RO_pars]) elif cal_points and (i == (len(times) - 2) or i == (len(times) - 1)): seg = segment.Segment('segment_{}'.format(i), [pulses['X180'], RO_pars]) else: X90_separation = tau - DRAG_length if cpmg_scheme: if i == 0: print('cpmg') echo_pulse_delay = (X90_separation - nr_echo_pulses*DRAG_length) / \ nr_echo_pulses if echo_pulse_delay < 0: pulse_pars_x2['pulse_delay'] = tau pulse_dict_list = [pulses['X90'], pulse_pars_x2, RO_pars] else: pulse_dict_list = [pulses['X90']] start_end_delay = echo_pulse_delay / 2 for p_nr, pulse_dict in enumerate(Echo_pulses): pd = deepcopy(pulse_dict) pd['ref_point'] = 'end' pd['pulse_delay'] = \ (start_end_delay if p_nr == 0 else echo_pulse_delay) pulse_dict_list.append(pd) pulse_pars_x2['ref_point'] = 'end' pulse_pars_x2['pulse_delay'] = start_end_delay pulse_dict_list += [pulse_pars_x2, RO_pars] else: if i == 0: print('UDD') pulse_positions_func = \ lambda idx, N: np.sin(np.pi*idx/(2*N+2))**2 pulse_delays_func = (lambda idx, N: X90_separation * (pulse_positions_func(idx, N) - pulse_positions_func(idx - 1, N)) - ( (0.5 if idx == 1 else 1) * DRAG_length)) if nr_echo_pulses * DRAG_length > X90_separation: pulse_pars_x2['pulse_delay'] = tau pulse_dict_list = [pulses['X90'], pulse_pars_x2, RO_pars] else: pulse_dict_list = [pulses['X90']] for p_nr, pulse_dict in enumerate(Echo_pulses): pd = deepcopy(pulse_dict) pd['ref_point'] = 'end' pd['pulse_delay'] = pulse_delays_func( p_nr + 1, nr_echo_pulses) pulse_dict_list.append(pd) pulse_pars_x2['ref_point'] = 'end' pulse_pars_x2['pulse_delay'] = pulse_delays_func( 1, nr_echo_pulses) pulse_dict_list += [pulse_pars_x2, RO_pars] seg = segment.Segment('segment_{}'.format(i), pulse_dict_list) seg_list.append(seg) seq.add(seg) if upload: ps.Pulsar.get_instance().program_awgs(seq) if return_seq: return seq, seg_list else: return seq_name
def n_qubit_off_on(pulse_pars_list, RO_pars_list, return_seq=False, parallel_pulses=False, preselection=False, upload=True, RO_spacing=2000e-9): n = len(pulse_pars_list) seq_name = '{}_qubit_OffOn_sequence'.format(n) seq = sequence.Sequence(seq_name) seg_list = [] RO_pars_list_presel = deepcopy(RO_pars_list) for i, RO_pars in enumerate(RO_pars_list): RO_pars['name'] = 'RO_{}'.format(i) RO_pars['element_name'] = 'RO' if i != 0: RO_pars['ref_point'] = 'start' for i, RO_pars_presel in enumerate(RO_pars_list_presel): RO_pars_presel['ref_pulse'] = RO_pars_list[-1]['name'] RO_pars_presel['ref_point'] = 'start' RO_pars_presel['element_name'] = 'RO_presel' RO_pars_presel['pulse_delay'] = -RO_spacing # Create a dict with the parameters for all the pulses pulse_dict = dict() for i, pulse_pars in enumerate(pulse_pars_list): pars = pulse_pars.copy() if i == 0 and parallel_pulses: pars['ref_pulse'] = 'segment_start' if i != 0 and parallel_pulses: pars['ref_point'] = 'start' pulses = add_suffix_to_dict_keys(get_pulse_dict_from_pars(pars), ' {}'.format(i)) pulse_dict.update(pulses) # Create a list of required pulses pulse_combinations = [] for pulse_list in itertools.product(*(n * [['I', 'X180']])): pulse_comb = (n) * [''] for i, pulse in enumerate(pulse_list): pulse_comb[i] = pulse + ' {}'.format(i) pulse_combinations.append(pulse_comb) for i, pulse_comb in enumerate(pulse_combinations): pulses = [] for j, p in enumerate(pulse_comb): pulses += [pulse_dict[p]] pulses += RO_pars_list if preselection: pulses = pulses + RO_pars_list_presel seg = segment.Segment('segment_{}'.format(i), pulses) seg_list.append(seg) seq.add(seg) repeat_dict = {} repeat_pattern = ((1.0 + int(preselection)) * len(pulse_combinations), 1) for i, RO_pars in enumerate(RO_pars_list): repeat_dict = seq.repeat(RO_pars, None, repeat_pattern) if upload: ps.Pulsar.get_instance().program_awgs(seq) if return_seq: return seq, seg_list else: return seq_name