def prepare(self, get_t_base=True): ''' This function needs to be overwritten for the ATS based version of this driver Sets parameters in the ATS_CW and turns on the sources. if optimize == True it will optimze the acquisition time for a fixed t_int. ''' # only uploads a seq to AWG if something changed if ((self._awg_seq_filename not in self.AWG.get('setup_filename') or self._awg_seq_parameters_changed) and not self._disable_auto_seq_loading): self.seq_name = st_seqs.generate_and_upload_marker_sequence( 50e-9, 5e-6, RF_mod=True, IF=self.get('f_RO_mod'), mod_amp=0.5) self.AWG.run() if get_t_base is True: trace_length = self.CBox.get('nr_samples') tbase = np.arange(0, 5*trace_length, 5)*1e-9 self.cosI = np.cos(2*np.pi*self.get('f_RO_mod')*tbase) self.sinI = np.sin(2*np.pi*self.get('f_RO_mod')*tbase) self.LO.on() # Changes are now incorporated in the awg seq self._awg_seq_parameters_changed = False self.CBox.set('nr_samples', 1) # because using integrated avg
def prepare_CBox(self, get_t_base=True): """ uses the AWG to generate the modulating signal and CBox for readout """ # only uploads a seq to AWG if something changed if (self._awg_seq_filename not in self.AWG.setup_filename() or self._awg_seq_parameters_changed) and self.auto_seq_loading(): self._awg_seq_filename = \ st_seqs.generate_and_upload_marker_sequence( self.RO_length(), self.trigger_separation(), RF_mod=True, IF=self.f_RO_mod(), mod_amp=0.5, acq_marker_channels=self.acq_marker_channels(), I_channel=self.I_channel(), Q_channel=self.Q_channel()) self.AWG.ch3_amp(self.mod_amp()) self.AWG.ch4_amp(self.mod_amp()) self._awg_seq_parameters_changed = False self.AWG.ch3_amp(self.mod_amp()) self.AWG.ch4_amp(self.mod_amp()) if get_t_base is True: trace_length = self.CBox.nr_samples() tbase = np.arange(0, 5 * trace_length, 5) * 1e-9 self.cosI = np.cos(2 * np.pi * self.f_RO_mod() * tbase) self.sinI = np.sin(2 * np.pi * self.f_RO_mod() * tbase) self.CBox.nr_samples(1) # because using integrated avg
def prepare_ATS(self, get_t_base=True): if self.AWG != None: if (self._awg_seq_filename not in self.AWG.setup_filename() or self._awg_seq_parameters_changed) and \ self.auto_seq_loading(): self._awg_seq_filename = \ st_seqs.generate_and_upload_marker_sequence( self.RO_length(), self.trigger_separation(), RF_mod=False, acq_marker_channels=self.acq_marker_channels()) self._awg_seq_parameters_changed = False if get_t_base: self._acquisition_instr_controller.demodulation_frequency = \ self.f_RO_mod() buffers_per_acquisition = 8 self._acquisition_instr_controller.update_acquisitionkwargs( # mode='NPT', samples_per_record=64 * 1000, # 4992, records_per_buffer=int(self.nr_averages() / buffers_per_acquisition), # 70 segments buffers_per_acquisition=buffers_per_acquisition, channel_selection='AB', transfer_offset=0, external_startcapture='ENABLED', enable_record_headers='DISABLED', alloc_buffers='DISABLED', fifo_only_streaming='DISABLED', interleave_samples='DISABLED', get_processed_data='DISABLED', allocated_buffers=buffers_per_acquisition, buffer_timeout=1000)
def prepare(self, get_t_base=True): # Uploading the AWG sequence if self.AWG != None: if (self._awg_seq_filename not in self.AWG.setup_filename() or self._awg_seq_parameters_changed ) and self.auto_seq_loading(): self._awg_seq_filename = \ st_seqs.generate_and_upload_marker_sequence( 5e-9, self.trigger_separation(), RF_mod=False, acq_marker_channels=self.acq_marker_channels(), trigger_wait=self.external_trigger()) self._awg_seq_parameters_changed = False # Preparing the acquisition instruments if 'CBox' in self.acquisition_instr(): self.prepare_CBox(get_t_base) elif 'UHFQC' in self.acquisition_instr(): self.prepare_UHFQC() elif 'ATS' in self.acquisition_instr(): self.prepare_ATS(get_t_base) elif 'DDM' in self.acquisition_instr(): self.prepare_DDM() else: raise ValueError("Invalid acquisition instrument {} in {}".format( self.acquisition_instr(), self.__class__.__name__)) # turn on the AWG and the MWGs if self.AWG != None: self.AWG.run() self.on()
def prepare(self, get_t_base=True, RO_length=2274e-9, trigger_separation=10e-6): ''' This function needs to be overwritten for the ATS based version of this driver ''' if ((self._awg_seq_filename not in self.AWG.get('setup_filename')) and not self._disable_auto_seq_loading): self.seq_name = st_seqs.generate_and_upload_marker_sequence( RO_length, trigger_separation, RF_mod=False, IF=self.get('f_RO_mod'), mod_amp=0.5) self.AWG.run() print('RO_length heterodyne', RO_length) if get_t_base is True: if 'CBox' in self.acquisition_instr(): trace_length = 512 tbase = np.arange(0, 5*trace_length, 5)*1e-9 self.cosI = np.floor( 127.*np.cos(2*np.pi*self.get('f_RO_mod')*tbase)) self.sinI = np.floor( 127.*np.sin(2*np.pi*self.get('f_RO_mod')*tbase)) self._acquisition_instr.sig0_integration_weights(self.cosI) self._acquisition_instr.sig1_integration_weights(self.sinI) # because using integrated avg self._acquisition_instr.set('nr_samples', 1) self._acquisition_instr.nr_averages(int(self.nr_averages())) elif 'UHFQC' in self.acquisition_instr(): print("f_RO_mod", self.get('f_RO_mod')) # self._acquisition_instr.prepare_SSB_weight_and_rotation(IF=self.get('f_RO_mod'), # weight_function_I=0, weight_function_Q=1) self._acquisition_instr.prepare_DSB_weight_and_rotation( IF=self.get('f_RO_mod'), weight_function_I=0, weight_function_Q=1) # this sets the result to integration and rotation outcome self._acquisition_instr.quex_rl_source(2) # only one sample to average over self._acquisition_instr.quex_rl_length(1) self._acquisition_instr.quex_rl_avgcnt( int(np.log2(self.nr_averages()))) print("preparing UHFQ with avg", self._acquisition_instr.quex_rl_avgcnt()) self._acquisition_instr.quex_wint_length( int(RO_length*(1.8e9))) # Configure the result logger to not do any averaging # The AWG program uses userregs/0 to define the number o # iterations in the loop self._acquisition_instr.awgs_0_userregs_0( int(self.nr_averages())) # 0 for rl, 1 for iavg self._acquisition_instr.awgs_0_userregs_1(0) self._acquisition_instr.awgs_0_single(1) self.LO.on() # Changes are now incorporated in the awg seq self._awg_seq_parameters_changed = False
def prepare_UHFQC(self): """ uses the UHFQC to generate the modulating signal and readout """ # only uploads a seq to AWG if something changed if (self._awg_seq_filename not in self.AWG.setup_filename() or self._awg_seq_parameters_changed) and self.auto_seq_loading(): self._awg_seq_filename = \ st_seqs.generate_and_upload_marker_sequence( 5e-9, self.trigger_separation(), RF_mod=False, acq_marker_channels=self.acq_marker_channels()) self._awg_seq_parameters_changed = False # reupload the UHFQC pulse generation only if something changed if self._UHFQC_awg_parameters_changed and self.auto_seq_loading(): self._acquisition_instr.awg_sequence_acquisition_and_pulse_SSB( self.f_RO_mod.get(), self.mod_amp(), RO_pulse_length=800e-9, acquisition_delay=self.acquisition_delay()) self._UHFQC_awg_parameters_changed = False # prepare weights and rotation if self.single_sideband_demod(): self._acquisition_instr.prepare_SSB_weight_and_rotation( IF=self.f_RO_mod(), weight_function_I=0, weight_function_Q=1) else: self._acquisition_instr.prepare_DSB_weight_and_rotation( IF=self.f_RO_mod(), weight_function_I=0, weight_function_Q=1) # this sets the result to integration and rotation outcome self._acquisition_instr.quex_rl_source(2) self._acquisition_instr.quex_rl_length(1) self._acquisition_instr.quex_rl_avgcnt(int(np.log2( self.nr_averages()))) self._acquisition_instr.quex_wint_length(int(self.RO_length() * 1.8e9)) # The AWG program uses userregs/0 to define the number of # iterations in the loop self._acquisition_instr.awgs_0_userregs_0(int(self.nr_averages())) self._acquisition_instr.awgs_0_userregs_1(0) # 0 for rl, 1 for iavg self._acquisition_instr.awgs_0_userregs_2( int(self.acquisition_delay() * 1.8e9 / 8)) self._acquisition_instr.awgs_0_single(1)
def prepare_UHFQC(self): """ uses the UHFQC to generate the modulating signal and readout """ # only uploads a seq to AWG if something changed if (self._awg_seq_filename not in self.AWG.setup_filename() or self._awg_seq_parameters_changed) and self.auto_seq_loading(): self._awg_seq_filename = \ st_seqs.generate_and_upload_marker_sequence( 5e-9, self.trigger_separation(), RF_mod=False, acq_marker_channels=self.acq_marker_channels()) self._awg_seq_parameters_changed = False # reupload the UHFQC pulse generation only if something changed if self._UHFQC_awg_parameters_changed and self.auto_seq_loading(): self._acquisition_instr.awg_sequence_acquisition_and_pulse_SSB( self.f_RO_mod.get(), self.mod_amp(), RO_pulse_length=800e-9, acquisition_delay=self.acquisition_delay()) self._UHFQC_awg_parameters_changed = False # prepare weights and rotation if self.single_sideband_demod(): self._acquisition_instr.prepare_SSB_weight_and_rotation( IF=self.f_RO_mod(), weight_function_I=0, weight_function_Q=1) else: self._acquisition_instr.prepare_DSB_weight_and_rotation( IF=self.f_RO_mod(), weight_function_I=0, weight_function_Q=1) # this sets the result to integration and rotation outcome self._acquisition_instr.qas_0_result_source(2) self._acquisition_instr.qas_0_result_length(1) self._acquisition_instr.qas_0_result_averages(self.nr_averages()) self._acquisition_instr.qas_0_integration_length( int(self.RO_length() * 1.8e9)) self._acquisition_instr.awgs_0_single(1) self._acquisition_instr.wait_dly( int(self.acquisition_delay() * 1.8e9 / 8)) self._acquisition_instr.acquisition_initialize( samples=1, averages=self.nr_averages(), channels=[0, 1], mode='rl')
def mixer_skewness_cal_UHFQC_adaptive(UHFQC, SH, source, AWG, acquisition_marker_channel, LutMan, MC, SH_ref_level: float=-40, verbose: bool=True): ''' Input args UHFQC: UHFQC acquisition instrument SH: Signal Hound source: MW-source connected to the mixer LutMan: Used for changing the pars and loading the pulses AWG: Used for supplying triggers to the CBox MC: awg_nrs: The awgs used in the CBox to which the pulses are uploaded. (list to allow setting a copy on e.g. awg_nr = 1) Calibrates the mixer skewnness The UHFQC, in this case a fixed sequence is played in the tektronix to ensure the UHFQC is continously triggered and the parameters are reloaded between each measured point. If calibrate_both_sidebands is True the optimization runs two calibrations, first it tries to minimize the power in the spurious sideband by varying the phase and amplitude skewness. After that it flips the phase 180 degrees and repeates the same experiment for the desired sideband. Both should give the same result. For a description on how to translate these coefficients to a rotation matrix see the notes in docs/notes/MixerSkewnessCalibration_LDC_150629.pdf If calibrate_both_sidebands is False it will only minimize the signal in the spurious sideband. and return those values. ''' # Loads a train of pulses to the AWG to trigger the UHFQC continuously AWG.stop() st_seqs.generate_and_upload_marker_sequence( 5e-9, 1.0e-6, RF_mod=False, acq_marker_channels=acquisition_marker_channel) AWG.run() # Ensure that the block is 4 periods of the modulation freq # Ensure that the block is 4 periods of the modulation freq LutMan.M_block_length.set(960e-9) # in ns LutMan.M_ampCW.set(0.4) LutMan.render_wave('M_ModBlock', time_unit='ns') # divide instead of multiply by 1e-9 because of rounding errors S1 = swf.UHFQC_Lutman_par_with_reload( LutMan, LutMan.mixer_alpha, ['M_ModBlock'], run=True, single=False) S2 = swf.UHFQC_Lutman_par_with_reload( LutMan, LutMan.mixer_phi, ['M_ModBlock'], run=True, single=False) SH.ref_lvl(SH_ref_level) detector = det.Signal_Hound_fixed_frequency( SH, frequency=(source.frequency.get() - LutMan.M_modulation()), Navg=5, delay=0.0, prepare_each_point=False) ad_func_pars = {'adaptive_function': nelder_mead, 'x0': [1.0, 0.0], 'initial_step': [.15, 10], 'no_improv_break': 15, 'minimize': True, 'maxiter': 500} MC.set_sweep_functions([S1, S2]) MC.set_detector_function(detector) # sets test_detector MC.set_adaptive_function_parameters(ad_func_pars) MC.run(name='Spurious_sideband', mode='adaptive') a = ma.OptimizationAnalysis(auto=True, label='Spurious_sideband') alpha = a.optimization_result[0][0] phi = a.optimization_result[0][1] return phi, alpha