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)
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'