Esempio n. 1
0
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
Esempio n. 2
0
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
Esempio n. 3
0
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
Esempio n. 6
0
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
Esempio n. 8
0
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
Esempio n. 9
0
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())
Esempio n. 10
0
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
Esempio n. 11
0
    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
Esempio n. 12
0
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
Esempio n. 13
0
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