Example #1
0
    def generate_sequence(self, upload=True, debug=False):
        """
        generate the sequence for the purification experiment.
        Tries to be as general as possible in order to suffice for multiple calibration measurements
        """

        ### initialize empty sequence and elements
        combined_list_of_elements = []
        combined_seq = pulsar.Sequence('Purification')

        ### create a list of gates according to the current sweep.
        for pt in range(self.params['pts']):

            #sweep parameter
            if self.params['do_general_sweep'] == 1:
                self.params[self.params['general_sweep_name']] = self.params[
                    'general_sweep_pts'][pt]

            gate_seq = []

            ### LDE elements: WE have two LDE elements with potentially different functions
            LDE1 = DD.Gate('LDE1' + str(pt), 'LDE')
            LDE1.el_state_after_gate = 'sup'

            if self.params['LDE1_attempts'] > 1:
                LDE1.reps = self.params['LDE1_attempts'] - 1
                LDE1.is_final = False
                LDE1_final = DD.Gate('LDE1_final_' + str(pt), 'LDE')
                LDE1_final.el_state_after_gate = 'sup'
                LDE1_final.reps = 1
                LDE1_final.is_final = True
            else:
                LDE1.is_final = True

            if self.params['LDE1_attempts'] != 1:
                LDE1.reps = self.params['LDE1_attempts'] - 1

            ### LDE elements need rephasing or repumping elements
            LDE_rephase1 = DD.Gate(
                'LDE_rephasing_1' + str(pt),
                'single_element',
                wait_time=self.params['average_repump_time'])
            LDE_rephase1.scheme = 'single_element'

            LDE_repump1 = DD.Gate('LDE_repump_1_' + str(pt), 'Trigger')
            LDE_repump1.duration = 2e-6
            LDE_repump1.elements_duration = LDE_repump1.duration
            LDE_repump1.channel = 'AOM_Newfocus'
            LDE_repump1.el_state_before_gate = '0'

            e_RO = [
                DD.Gate('Tomo_Trigger_' + str(pt), 'Trigger', wait_time=10e-6)
            ]

            #######################################################################
            ### append all necessary gates according to the current measurement ###
            #######################################################################

            if self.params['do_N_MBI'] > 0:
                ### Nitrogen MBI
                mbi = DD.Gate('MBI_' + str(pt), 'MBI')
                gate_seq.append(mbi)

            # this could be used for the synchronization of the two setups
            # gate_seq.append(DD.Gate('dummy_wait'+str(pt),'passive_elt',wait_time = 3e-6))

            if self.params['do_carbon_init'] > 0:
                ### initialize carbon in +Z or +X
                carbon_init_seq = self.initialize_carbon_sequence(
                    go_to_element='start',
                    prefix='C_Init',
                    pt=pt,
                    addressed_carbon=self.params['carbon'],
                    initialization_method=self.params['carbon_init_method'])

                if gate_seq != []:
                    carbon_init_seq[0].wait_for_trigger = False

                gate_seq.extend(carbon_init_seq)

            #### insert a MW pi pulse when repumping
            if self.params['MW_before_LDE1'] > 0:
                mw_pi = DD.Gate('elec_pi_' + str(pt),
                                'electron_Gate',
                                Gate_operation='pi')

                if gate_seq == []:
                    mw_pi.wait_for_trigger = True
                gate_seq.append(mw_pi)

            if self.params['do_LDE_1'] > 0:
                ### needs corresponding adwin parameter
                if gate_seq == []:
                    LDE1.wait_for_trigger = True
                gate_seq.append(LDE1)

                # print 'LDE1 reps',LDE1.reps
                ### append last adwin synchro element
                if not LDE1.is_final:
                    gate_seq.append(LDE1_final)

                if self.params['do_swap_onto_carbon'] > 0:
                    gate_seq.append(LDE_rephase1)

                elif self.params['LDE_1_is_init'] == 0 and self.params[
                        'opt_pi_pulses'] < 2 and self.params[
                            'no_repump_after_LDE1'] == 0:
                    gate_seq.append(LDE_repump1)
                    # gate_seq.append(DD.Gate('LDE_1_wait'+str(pt),'passive_elt',wait_time = 3e-6))

            if self.params['do_swap_onto_carbon'] > 0:
                ### Elementes for swapping
                swap_with_init = self.carbon_swap_gate(
                    go_to_element='start',
                    pt=pt,
                    addressed_carbon=self.params['carbon'],
                    swap_type='swap_w_init',
                    RO_after_swap=True)

                if self.params['do_carbon_init'] > 0:
                    ### important to realize that the tau_cut of a potential decoupling sequence can alter the
                    ### electron rephasing element. --> Therefore the element has to be rebuilt
                    self.generate_LDE_rephasing_elt(LDE_rephase1)

                    gate_seq.extend(swap_with_init)
                else:
                    self.generate_LDE_rephasing_elt(LDE_rephase1)

                    gate_seq.extend(swap_with_init)
                    print '*' * 20
                    print 'Warning ' * 4
                    print 'Swap without initialization not implemented'
                    print '*' * 20

            if self.params['do_LDE_2'] > 0:
                if gate_seq == []:
                    LDE2.wait_for_trigger = True

                gate_seq.append(LDE2)

                # need a final element for adwin communication
                if self.params['LDE2_attempts'] > 1:
                    gate_seq.append(LDE2_final)

                if (self.params['do_purifying_gate'] > 0
                        or self.params['do_phase_correction'] > 0
                    ) and self.params['do_repump_after_LDE2'] == 0:
                    # electron has to stay coherent after LDE attempts
                    self.generate_LDE_rephasing_elt(LDE_rephase2)
                    gate_seq.append(LDE_rephase2)

                else:  # this is used if we sweep the number of repetitions for Qmemory testing.
                    gate_seq.append(LDE_repump2)

            if self.params['do_phase_correction'] > 0 and self.params[
                    'phase_correct_max_reps'] > 0:
                gate_seq.extend(dynamic_phase_correct_list)

            if self.params['do_purifying_gate'] > 0:
                gate_seq.extend(carbon_purify_seq)

            if self.params['do_carbon_readout'] > 0:
                if self.params['do_purifying_gate'] > 0:
                    ### prepare branching of the sequence
                    gate_seq0 = copy.deepcopy(gate_seq)
                    gate_seq1 = copy.deepcopy(gate_seq)

                    carbon_tomo_seq0 = self.readout_carbon_sequence(
                        prefix='Tomo0',
                        pt=pt,
                        go_to_element=None,
                        event_jump_element=None,
                        RO_trigger_duration=10e-6,
                        el_state_in=0,
                        carbon_list=[self.params['carbon']],
                        RO_basis_list=self.params['Tomography_bases'],
                        readout_orientation=self.
                        params['carbon_readout_orientation'])
                    gate_seq0.extend(carbon_tomo_seq0)

                    carbon_tomo_seq1 = self.readout_carbon_sequence(
                        prefix='Tomo1',
                        pt=pt,
                        go_to_element=None,
                        event_jump_element=None,
                        RO_trigger_duration=10e-6,
                        el_state_in=1,
                        carbon_list=[self.params['carbon']],
                        RO_basis_list=self.params['Tomography_bases'],
                        readout_orientation=self.
                        params['carbon_readout_orientation'])
                    gate_seq1.extend(carbon_tomo_seq1)

                    # Make jump statements for branching to two different ROs
                    gate_seq[-1].go_to = carbon_tomo_seq1[0].name
                    gate_seq[-1].event_jump = carbon_tomo_seq0[0].name

                    # In the end all roads lead to Rome
                    Rome = DD.Gate('Rome_' + str(pt),
                                   'passive_elt',
                                   wait_time=3e-6)
                    gate_seq1.append(Rome)
                    gate_seq0[-1].go_to = gate_seq1[-1].name

                    # take care of electron states after the purification msmt. I.e. the electron state is set during the trigger.

                    gate_seq0[len(gate_seq) -
                              1].el_state_before_gate = '0'  #Element -1
                    gate_seq1[len(gate_seq) -
                              1].el_state_before_gate = '1'  #Element -1

                    ### generate and merge branches
                    gate_seq = self.generate_AWG_elements(gate_seq, pt)
                    gate_seq0 = self.generate_AWG_elements(gate_seq0, pt)
                    gate_seq1 = self.generate_AWG_elements(gate_seq1, pt)

                    merged_sequence = []
                    merged_sequence.extend(gate_seq)
                    merged_sequence.extend(gate_seq0[len(gate_seq):])
                    merged_sequence.extend(gate_seq1[len(gate_seq):])
                    gate_seq = copy.deepcopy(
                        merged_sequence)  # for further processing

                else:  ### no purifying gate --> we don't need branching!
                    carbon_tomo_seq = self.readout_carbon_sequence(
                        prefix='Tomo',
                        pt=pt,
                        go_to_element=None,
                        event_jump_element=None,
                        RO_trigger_duration=10e-6,
                        el_state_in=0,
                        carbon_list=[self.params['carbon']],
                        RO_basis_list=self.params['Tomography_bases'],
                        readout_orientation=self.
                        params['carbon_readout_orientation'])
                    gate_seq.extend(carbon_tomo_seq)
                    # e_RO =  [DD.Gate('Tomo_Trigger_'+str(pt),'Trigger',
                    #     wait_time = 20e-6)]
                    # gate_seq.extend(e_RO)
                # print 'This is the tomography base', self.params['Tomography_bases']

            else:  #No carbon spin RO? Do espin RO!
                if self.params['do_purifying_gate'] == 0:
                    gate_seq.extend(e_RO)

            ###############################################
            # prepare and program the actual AWG sequence #
            ###############################################

            #### insert elements here

            if not (self.params['do_purifying_gate'] > 0
                    and self.params['do_carbon_readout'] > 0):
                gate_seq = self.generate_AWG_elements(gate_seq, pt)

            #### for carbon phase debbuging purposes.
            # for g in gate_seq:
            #     if not 'correct' in g.name:
            #         print g.name
            #         self.print_carbon_phases(g,[self.params['carbon']],verbose=True)

            ### Convert elements to AWG sequence and add to combined list
            list_of_elements, seq = self.combine_to_AWG_sequence(gate_seq,
                                                                 explicit=True)
            combined_list_of_elements.extend(list_of_elements)

            for seq_el in seq.elements:
                combined_seq.append_element(seq_el)

        if upload:
            print ' uploading sequence'
            qt.pulsar.program_awg(combined_seq,
                                  *combined_list_of_elements,
                                  debug=debug)
Example #2
0
    def generate_sequence(self, upload=True, debug=False):
        """
        generate the sequence for the single click experiment.
        Tries to be as general as possible in order to suffice for multiple calibration measurements
        """

        if self.params['only_meas_phase']:
            return  # NO AWG NEEDED

        ### initialize empty sequence and elements
        combined_list_of_elements = []
        combined_seq = pulsar.Sequence('SingleClickEnt')
        if self.params['do_general_sweep'] == 1:
            if type(self.params['general_sweep_name']) == list:
                x0 = self.params['general_sweep_pts'][0]
                x1 = self.params['general_sweep_pts'][1]
                self.params['general_sweep_pts1'] = x0
                self.params['general_sweep_pts2'] = x1
                self.params['general_sweep_pts'] = []
                sweep_pts = list(product(x0, x1))

        ### create a list of gates according to the current sweep.
        for pt in range(self.params['pts']):
            self.pt = pt
            #sweep parameter
            if self.params['do_general_sweep'] == 1:
                if type(self.params['general_sweep_name']) == list:

                    self.params[self.params['general_sweep_name']
                                [0]] = sweep_pts[pt][0]
                    self.params[self.params['general_sweep_name']
                                [1]] = sweep_pts[pt][1]
                    self.params['sweep_pts'] = range(len(sweep_pts))
                else:
                    self.params[
                        self.params['general_sweep_name']] = self.params[
                            'general_sweep_pts'][pt]
            else:
                self.params['general_sweep_name'] = 'no_sweep'

            gate_seq = []

            LDE = DD.Gate('LDE' + str(pt), 'LDE')

            if self.params['LDE_attempts'] > 1:
                LDE.reps = self.params['LDE_attempts'] - 1
                LDE.is_final = False
                LDE_final = DD.Gate('LDE_final_' + str(pt), 'LDE')
                LDE_final.reps = 1
                LDE_final.is_final = True
            else:
                LDE.is_final = True

            ### if statement to decide what LDE does: entangling or just make a specific e state.
            if self.params['LDE_is_init'] > 0:
                if self.params[
                        'force_LDE_attempts_before_init'] == 0 or self.params[
                            'LDE_attempts'] == 1:
                    LDE.reps = 1
                    LDE.is_final = True

                    manipulated_LDE_elt = copy.deepcopy(LDE)
                else:
                    manipulated_LDE_elt = copy.deepcopy(LDE_final)
                    LDE.reps = self.params['LDE_attempts'] - 1

                if self.params['input_el_state'] in ['X', 'mX', 'Y', 'mY']:
                    manipulated_LDE_elt.first_pulse_is_pi2 = True

                    #### define some phases:
                    x_phase = self.params['X_phase']
                    y_phase = self.params['Y_phase']
                    first_mw_phase_dict = {
                        'X': y_phase,
                        'mX': y_phase + 180,
                        'Y': x_phase + 180,
                        'mY': x_phase
                    }

                    manipulated_LDE_elt.first_mw_pulse_phase = first_mw_phase_dict[
                        self.params['input_el_state']]

                elif self.params['input_el_state'] in ['Z']:
                    manipulated_LDE_elt.no_first_pulse = True

                elif self.params['input_el_state'] in ['mZ']:
                    manipulated_LDE_elt.no_mw_pulse = True

                ### clean up by casting the manipulation back onto the original object:
                if self.params[
                        'force_LDE_attempts_before_init'] == 0 or self.params[
                            'LDE_attempts'] == 1:
                    LDE = manipulated_LDE_elt
                else:
                    LDE_final = manipulated_LDE_elt

            ### if more than 1 reps then we need to take the final element into account
            elif self.params['LDE_attempts'] != 1:

                ############ do the yellow check here!
                LDE.reps = self.params['LDE_attempts'] - 1

                if self.params['do_yellow_with_AWG'] > 0:
                    LDE_list = []
                    LDE_reionize = DD.Gate('LDE_reionize_' + str(pt),
                                           'Trigger')
                    LDE_reionize.duration = self.params['Yellow_AWG_duration']
                    LDE_reionize.elements_duration = LDE_reionize.duration
                    LDE_reionize.channel = 'AOM_Yellow'

                    # LDE_rounds, remaining_LDE_reps = divmod(LDE.reps,self.joint_params['LDE_attempts_before_yellow'])
                    LDE_rounds, remaining_LDE_reps = divmod(
                        LDE.reps, self.params['LDE_attempts_before_yellow'])

                    for i in range(int(LDE_rounds)):
                        #### when putting more stuff in the AWG have to make sure that names are unique
                        ## LDE elts
                        L = copy.deepcopy(LDE)
                        L.name = L.name + '_' + str(i)
                        L.reps = int(self.params['LDE_attempts_before_yellow'])
                        LDE_list.append(L)

                        ### yellow elts
                        Y = copy.deepcopy(LDE_reionize)
                        Y.name = Y.name + '_' + str(i)
                        Y.prefix = Y.prefix + '_' + str(i)
                        LDE_list.append(Y)

                    if remaining_LDE_reps != 0:
                        LDE.reps = remaining_LDE_reps
                        LDE.name = LDE.name + '_' + str(int(LDE_rounds))
                        LDE_list.append(LDE)

                else:
                    LDE_list = [LDE]
            else:
                LDE_list = [LDE]

            ### LDE elements need rephasing or repumping elements
            LDE_repump = DD.Gate('LDE_repump_' + str(pt), 'Trigger')
            LDE_repump.duration = 2e-6
            LDE_repump.elements_duration = LDE_repump.duration
            LDE_repump.channel = 'AOM_Newfocus'
            LDE_repump.el_state_before_gate = '0'

            LDE_rephasing = DD.Gate('LDE_rephasing_' + str(pt),
                                    'single_element')
            LDE_rephasing.scheme = 'single_element'
            self.generate_LDE_rephasing_elt(LDE_rephasing)

            ## decoupling sequence
            tomography_pulse = DD.Gate('tomography_pulse_' + str(pt),
                                       'single_element')
            tomography_pulse.scheme = 'single_element'
            self.generate_tomography_pulse(
                tomography_pulse)  ### this is still wrong!!!

            cond_decoupling = DD.Gate(
                'dd_' + str(pt),
                'Carbon_Gate',
                Carbon_ind=1,  # does not matter.
                event_jump='dd_end' + str(pt),
                tau=self.params['dynamic_decoupling_tau'],
                N=self.params['dynamic_decoupling_N'],
                no_connection_elt=True)
            cond_decoupling.scheme = 'carbon_phase_feedback'
            cond_decoupling.reps = int(self.params['max_decoupling_reps'])

            cond_decoupling_end = DD.Gate(
                'dd_end' + str(pt),
                'Carbon_Gate',
                Carbon_ind=1,  # does not matter.
                tau=self.params['dynamic_decoupling_tau'],
                N=self.params['dynamic_decoupling_N'],
                no_connection_elt=True)
            cond_decoupling_end.scheme = 'carbon_phase_feedback_end_elt'

            e_RO = [
                DD.Gate('Tomo_Trigger_' + str(pt), 'Trigger', wait_time=10e-6)
            ]
            Fail_done = DD.Gate('Fail_done' + str(pt),
                                'Trigger',
                                wait_time=10e-6)

            if self.params['do_dynamical_decoupling'] + self.params[
                    'do_dynamical_decoupling_AWG_only'] > 0:
                Fail_done.go_to = 'dd_' + str(pt)
            else:
                Fail_done.go_to = 'wait_for_adwin_' + str(pt)

            if self.params['do_dynamical_decoupling'] + self.params[
                    'do_dynamical_decoupling_AWG_only'] > 0:
                Fail_done.go_to = 'dd_' + str(pt)
            else:
                Fail_done.go_to = 'wait_for_adwin_' + str(pt)
            #######################################################################
            ### append all necessary gates according to the current measurement ###
            #######################################################################
            waiting_for_adwin = DD.Gate('wait_for_adwin_' + str(pt),
                                        'passive_elt',
                                        wait_time=10e-6)
            waiting_for_adwin.wait_for_trigger = True
            gate_seq.append(waiting_for_adwin)
            if self.params['do_N_MBI'] > 0:
                ### Nitrogen MBI
                mbi = DD.Gate('MBI_' + str(pt), 'MBI')
                gate_seq.append(mbi)

            #### insert a MW pi pulse when repumping
            if self.params['MW_before_LDE'] > 0:
                mw_pi = DD.Gate('elec_pi_' + str(pt),
                                'electron_Gate',
                                Gate_operation='pi')

                if gate_seq == []:
                    mw_pi.wait_for_trigger = True
                gate_seq.append(mw_pi)

            if self.params['do_LDE'] > 0:
                ### needs corresponding adwin parameter
                if gate_seq == []:
                    LDE_list[0].wait_for_trigger = True
                gate_seq.extend(LDE_list)
                ### append last adwin synchro element
                if not LDE_list[0].is_final:
                    gate_seq.append(LDE_final)
                    if self.params['force_repump_after_LDE'] > 0:
                        gate_seq.append(LDE_repump)

                    if self.params['do_dynamical_decoupling'] + self.params[
                            'do_dynamical_decoupling_AWG_only'] > 0:
                        LDE_rephasing.go_to = 'dd_' + str(pt)
                    else:
                        LDE_rephasing.go_to = 'Tomo_Trigger_' + str(pt)

                    gate_seq.append(LDE_rephasing)

                    if self.params['PLU_during_LDE'] > 0:
                        gate_seq.append(Fail_done)

                else:
                    ### there is only a single LDE repetition in the LDE element and we do not repump.
                    ### --> add the rephasing element
                    gate_seq.append(LDE_rephasing)

            if self.params['do_dynamical_decoupling'] + self.params[
                    'do_dynamical_decoupling_AWG_only'] > 0:
                gate_seq.append(cond_decoupling)
                gate_seq.append(cond_decoupling_end)
                gate_seq.append(tomography_pulse)

            gate_seq.extend(e_RO)

            ###############################################
            # prepare and program the actual AWG sequence #
            ###############################################

            #### insert elements here
            gate_seq = self.generate_AWG_elements(gate_seq, pt)

            ### Convert elements to AWG sequence and add to combined list
            list_of_elements, seq = self.combine_to_AWG_sequence(gate_seq,
                                                                 explicit=True)
            combined_list_of_elements.extend(list_of_elements)

            for seq_el in seq.elements:
                combined_seq.append_element(seq_el)
        if upload:
            print ' uploading sequence'
            qt.pulsar.program_awg(combined_seq,
                                  *combined_list_of_elements,
                                  debug=debug,
                                  verbose=False)
        else:

            print 'upload = false, no sequence uploaded to AWG'
    def generate_sequence(self, upload=True, debug=False):
        pts = self.params['pts']

        ### initialize empty sequence and elements
        combined_list_of_elements = []
        combined_seq = pulsar.Sequence('Uncond Pi Sweep')

        for pt in range(pts):  ### Sweep over RO basis

            gate_seq = []

            ### Nitrogen MBI
            mbi = DD.Gate('MBI_' + str(pt), 'MBI')
            mbi_seq = [mbi]
            gate_seq.extend(mbi_seq)

            ### Carbon initialization
            init_wait_for_trigger = True

            for kk in range(self.params['Nr_C13_init']):

                if self.params['el_after_init'] == '1':
                    self.params['do_wait_after_pi'] = True
                else:
                    self.params['do_wait_after_pi'] = False

                carbon_init_seq = self.initialize_carbon_sequence(
                    go_to_element=mbi,
                    prefix='C_' + self.params['init_method_list'][kk] +
                    str(kk + 1) + '_C',
                    wait_for_trigger=init_wait_for_trigger,
                    pt=pt,
                    initialization_method=self.params['init_method_list'][kk],
                    C_init_state=self.params['init_state_list'][kk],
                    addressed_carbon=self.params['carbon_init_list'][kk],
                    el_after_init=self.params['el_after_init'],
                    do_wait_after_pi=self.params['do_wait_after_pi'])
                gate_seq.extend(carbon_init_seq)
                init_wait_for_trigger = False

            C_Echo = DD.Gate(
                'C_echo' + str(pt),
                'Carbon_Gate',
                Carbon_ind=self.params['carbon_list'][0],
                phase=self.params['C13_X_phase'])  #Wellicht reset?

            C_Echo_2 = DD.Gate('C_echo2_' + str(pt),
                               'Carbon_Gate',
                               Carbon_ind=self.params['carbon_list'][0],
                               phase=self.params['C13_X_phase'])
            # self.params['Carbon_pi_duration'] += 2 * C_Echo_2.N * C_Echo_2.tau

            gate_seq.extend([C_Echo, C_Echo_2])

            carbon_tomo_seq = self.readout_carbon_sequence(
                prefix='Tomo',
                pt=pt,
                go_to_element=None,
                event_jump_element=None,
                RO_trigger_duration=10e-6,
                carbon_list=self.params['carbon_list'],
                RO_basis_list=self.params['Tomography Bases'][pt],
                readout_orientation=self.params['electron_readout_orientation']
            )
            gate_seq.extend(carbon_tomo_seq)

            gate_seq = self.generate_AWG_elements(gate_seq, pt)

            ### Convert elements to AWG sequence and add to combined list`
            list_of_elements, seq = self.combine_to_AWG_sequence(gate_seq,
                                                                 explicit=True)
            combined_list_of_elements.extend(list_of_elements)

            for seq_el in seq.elements:
                combined_seq.append_element(seq_el)

            if debug:
                for g in gate_seq:
                    print g.name
                    self.print_carbon_phases(g, self.params['carbon_list'])
        if upload:
            print ' uploading sequence'
            qt.pulsar.program_awg(combined_seq,
                                  *combined_list_of_elements,
                                  debug=debug)

        else:
            print 'upload = false, no sequence uploaded to AWG'