def sweep_awg_chans(meas_param, awg_ch_1, awg_ch_2, start, stop, step, delay=0.01, do_plots=True): """ Sweeps two awg channels at once and is otherwise the same as sweep1d Args: meas_param: parameter which we want the value of at each point awg_ch_1: one of the awg channels to vary awg_ch_2: one of the awg channels to vary start: starting value for awg channels stop: final value for awg channels step: value to step awg channels delay (default 0.01): mimimum time to spend on each point do_plots: Default True: If False no plots are produced. Data is still saved and can be displayed with show_num. Returns: data (qcodes dataset) plot: QT plot """ loop = qc.Loop(awg_ch_1.sweep(start, stop, step)).each( qc.Task(awg_ch_2.set, awg_ch_1.get), meas_param) set_params = ((awg_ch_1, start, stop, step), ) meas_params = _select_plottables(meas_param) plot, data = _do_measurement(loop, set_params, meas_params, do_plots=do_plots) return data, plot
def do1dDiagonal(inst_set, inst2_set, start, stop, num_points, delay, start2, slope, *inst_meas, do_plots=True): """ Perform diagonal sweep in 1 dimension, given two instruments Args: inst_set: Instrument to sweep over inst2_set: Second instrument to sweep over start: Start of sweep stop: End of sweep num_points: Number of steps to perform delay: Delay at every step start2: Second start point slope: slope of the diagonal cut *inst_meas: any number of instrument to measure do_plots: Default True: If False no plots are produced. Data is still saved and can be displayed with show_num. Returns: plot, data : returns the plot and the dataset """ # (WilliamHPNielsen) If I understand do1dDiagonal correctly, the inst2_set # is supposed to be varied secretly in the background set_params = ((inst_set, start, stop),) meas_params = _select_plottables(inst_meas) slope_task = qc.Task(inst2_set, (inst_set)*slope+(slope*start-start2)) loop = qc.Loop(inst_set.sweep(start, stop, num=num_points), delay).each(slope_task, *inst_meas, inst2_set) plot, data = _do_measurement(loop, set_params, meas_params, do_plots=do_plots) return plot, data
def pb(diff): pulse_builder.averages(int(pulse_builder.averages() + diff)) print(pulse_builder.averages()) def QubitPower(pulse_builder,qubit,pwr): qubit.power(pwr) def compensate_cutter(cutter_gate, plunger_gate, slope, offset): current_plunger_voltage = plunger_gate() compensated_cutter_voltage = -slope * current_plunger_voltage + offset cutter_gate(compensated_cutter_voltage) # def set_localos(localos, cavity, USE_DEMOD_FREQ): # localos.frequency(cavity.frequency()+USE_DEMOD_FREQ) Alazar_Cavset_Task = qc.Task(partial(Alazar_Cavset,cal_traces,pulse_builder,switch,qubit,cavity,detuning=0.3e6)) Alazar_SingleCavset_Task = qc.Task(partial(Alazar_SingleCavset,vna.S21_1.trace,pulse_builder.readout_freq_1,switch,qubit,cavity,detuning=0.3e6)) CavPrep_Task = qc.Task(partial(CavPrep,switch,qubit,cavity)) # LocalosPrep_taks = qc.Task(partial(set_localos,localos, cavity, USE_DEMOD_FREQ)) #%% #Example measurement: Non overlapping spectroscopy with Alazar and AWG; we assume that we did spectroscopy with the VNA beforehand and know the resonator frequency and a range for the qubit frequency #In this measurement a qubit pulse is sent out first and directly afterwards a readout tone. If the qubit lifetime is sufficiently high we should see a peak in I and Q and knowing that the qubit didn't decay immediately back to the groundstate after the qubit drive #prepare switches and instruments
def twod_param_sweep(SetParam1, SetArray1, SetParam2, SetArray2, *MeasParams, SetDelay1=0, SetDelay2=0, Param2_SetBetween=None, DataName='', ZParam=None, plot_results=True, save_plots=True): """ Single parameter sweep, single measure (for more measurements, add parameters to the .each() part). Includes live plot. Note: if the SetParam1 array is nonuniform, the y axis of the plot will be messed up. Try MatPlot instead of QtPlot in that situation. Returns: data (a qcodes DataSet object), plot Arguments: SetParam1: The outer parameter to sweep (such as a temperature) SetArray1: should be a list or numpy array of values you want to set SetParam1 to. This array will be run through once SetParam2: The inner parameter to sweep (such as a voltage) Param2_SetBetween: Sets parameter 2 to this value at the end of each sweep of the parameter (completion of one row) and before changing parameter 1. SetArray1: should be a list or numpy array of values you want to set SetParam2 to. This array will be run through for each value of SetArray1 MeasParams: The parameter(s) you want to measure at each setpoint Keyword Arguments: SetDelay1: The delay time between when SetParam1 is set till the SetParam2 is set to its first value (0 by default) SetDelay2: Delay time between when SetParam2 is set and the MeasParam is measured (0 by default) DataName: A name to tag the data (defaults to nothing) ZParam: Allows you to pick only a few parameters to plot out of those measured. (if not mentioned, will plot all *MeasParams) plot_results: True by default, if false, suppresses plotting save_plots: True by default. If false, doesn't save plots at the end of the sweep """ if Param2_SetBetween is None: def between_func(): pass else: def between_func(): SetParam2(Param2_SetBetween) return innerloop = qc.Loop(SetParam2[SetArray2], delay=SetDelay2).each(*MeasParams) twodloop = qc.Loop(SetParam1[SetArray1], delay=SetDelay1).each(innerloop, qc.Task(between_func)) data = twodloop.get_data_set(name=DataName) plot = [] def _plot_update(): if type(plot) is list: for p in plot: p.update() else: plot.update() def _plot_save(): if type(plot) is list: for i in range(len(plot)): fname = '{}_{}.png'.format(plot[i].get_default_title(), str(ZParam[i])) plot[i].save(filename=fname) else: fname = '{}_{}.png'.format(plot.get_default_title(), str(*MeasParams)) plot.save(filename=fname) if plot_results: if len(MeasParams) == 1: plot = qc.QtPlot(getattr(data, str(*MeasParams)), window_title=str(*MeasParams)) twodloop.with_bg_task(plot.update) else: if ZParam is None: ZParam = MeasParams if type(ZParam) is not list and type(ZParam) is not tuple: ZParam = [ZParam] for zp in ZParam: plot.append( qc.QtPlot(getattr(data, str(zp)), window_title=str(zp))) twodloop.with_bg_task(_plot_update) try: twodloop.run() if save_plots and plot_results: _plot_save() return data, plot except KeyboardInterrupt: if plot_results: _plot_update() if save_plots: _plot_save() print('Keyboard Interrupt') return data, plot
vna.channels[i].format('Linear Magnitude') cal_traces.append(vna.channels[i].trace) #vna.display_grid(2,2) vna.rf_power(1) switch.all(2) time.sleep(2) vna.channels.autoscale() vna.channels.status(0) from scripts.Task_functions import Alazar_Cavset, CavPrep from functools import partial Alazar_Cavset_Task = qc.Task( partial(Alazar_Cavset, cal_traces, pulse_builder, switch, qubit, detuning=-1e6)) CavPrep_Task = qc.Task(partial(CavPrep, switch, qubit)) #%% Stuff added by OE # Short-hand measurement handles twotone = [ CavPrep_Task, vna.S21_1.trace, Alazar_Cavset_Task, alazar_ctrl.channels[12:14].data ] vnat = [vna.S21_1.trace]
def scan_surface(self, scan_params: Dict[str, Any]) -> None: """ Scan the current surface while acquiring data in the channels defined in measurement configuration file (e.g. MAG, SUSCX, SUSCY, CAP). Args: scan_params: Dict of scan parameters as defined in measuremnt configuration file. Returns: None """ if not self.atto.surface_is_current: raise RuntimeError('Surface is not current. Aborting scan.') surface_type = scan_params['surface_type'].lower() if surface_type not in ['plane', 'surface']: raise ValueError('surface_type must be "plane" or "surface".') old_pos = self.scanner.position() daq_config = self.config['instruments']['daq'] ao_channels = daq_config['channels']['analog_outputs'] ai_channels = daq_config['channels']['analog_inputs'] meas_channels = scan_params['channels'] channels = {} for ch in meas_channels: channels.update({ch: ai_channels[ch]}) nchannels = len(channels.keys()) daq_name = daq_config['name'] #: DAQ AI sampling rate is divided amongst all active AI channels daq_rate = self.Q_(daq_config['rate']).to('Hz').magnitude / nchannels fast_ax = scan_params['fast_ax'].lower() slow_ax = 'x' if fast_ax == 'y' else 'y' pix_per_line = scan_params['scan_size'][fast_ax] line_duration = pix_per_line * self.ureg('pixels') / self.Q_( scan_params['scan_rate']) pts_per_line = int(daq_rate * line_duration.to('s').magnitude) height = self.Q_(scan_params['height']).to('V').magnitude if 1 / self.Q_(scan_params['scan_rate']).to( 'pixels/s').magnitude < self.SUSC_lockin.time_constant(): warning = 'Averaging time per pixel is less than the SUSC_lockin time constant. ' warning += 'For reliable susceptibility data, averaging time per pixel should be ' warning += 'significantly greater than the SUSC_lockin time constant.' log.warning(warning) scan_vectors = utils.make_scan_vectors(scan_params, self.ureg) #scan_grids = utils.make_scan_grids(scan_vectors, slow_ax, fast_ax, # pts_per_line, plane, height) plane = self.scanner.metadata['plane'] if surface_type == 'plane': scan_grids = utils.make_scan_surface(surface_type, scan_vectors, slow_ax, fast_ax, pts_per_line, plane, height) else: scan_grids = utils.make_scan_surface( surface_type, scan_vectors, slow_ax, fast_ax, pts_per_line, plane, height, interpolator=self.scanner.surface_interp) utils.validate_scan_params(self.scanner.metadata, scan_params, scan_grids, pix_per_line, pts_per_line, self.temp, self.ureg, log) self.scanner.goto([scan_grids[axis][0][0] for axis in ['x', 'y', 'z']]) self.set_lockins(scan_params) #: get channel prefactors in pint Quantity form prefactors = self.get_prefactors(scan_params) #: get channel prefactors in string form so they can be saved in metadata prefactor_strs = {} for ch, prefac in prefactors.items(): unit = scan_params['channels'][ch]['unit'] pre = prefac.to('{}/V'.format(unit)) prefactor_strs.update( {ch: '{} {}'.format(pre.magnitude, pre.units)}) ai_task = nidaqmx.Task('scan_plane_ai_task') self.remove_component('daq_ai') if hasattr(self, 'daq_ai'): #self.daq_ai.clear_instances() self.daq_ai.close() self.daq_ai = DAQAnalogInputs( 'daq_ai', daq_name, daq_rate, channels, ai_task, samples_to_read=pts_per_line, target_points=pix_per_line, #: Very important to synchronize AOs and AIs clock_src='ao/SampleClock') self.add_component(self.daq_ai) slow_ax_position = getattr(self.scanner, 'position_{}'.format(slow_ax)) slow_ax_start = scan_vectors[slow_ax][0] slow_ax_end = scan_vectors[slow_ax][-1] slow_ax_step = scan_vectors[slow_ax][1] - scan_vectors[slow_ax][0] #: There is probably a counter built in to qc.Loop, but I couldn't find it loop_counter = utils.Counter() scan_plot = ScanPlot(scan_params, self.ureg) loop = qc.Loop( slow_ax_position.sweep(start=slow_ax_start, stop=slow_ax_end, step=slow_ax_step), delay=0.1 ).each( #: Create AO task and queue data to be written to AOs qc.Task(self.scanner.scan_line, scan_grids, ao_channels, daq_rate, loop_counter), #: Start AI task; acquisition won't start until AO task is started qc.Task(ai_task.start), #: Start AO task qc.Task(self.scanner.control_ao_task, 'start'), #: Acquire voltage from all active AI channels self.daq_ai.voltage, qc.Task(ai_task.wait_until_done), qc.Task(self.scanner.control_ao_task, 'wait_until_done'), qc.Task(ai_task.stop), #: Stop and close AO task so that AOs can be used for goto qc.Task(self.scanner.control_ao_task, 'stop'), qc.Task(self.scanner.control_ao_task, 'close'), qc.Task(self.scanner.goto_start_of_next_line, scan_grids, loop_counter), #: Update and save plot qc.Task(scan_plot.update, qc.loops.active_data_set, loop_counter), qc.Task(scan_plot.save), qc.Task(loop_counter.advance) ).then( qc.Task(ai_task.stop), qc.Task(ai_task.close), qc.Task(self.daq_ai.close), #qc.Task(self.daq_ai.clear_instances), qc.Task(self.scanner.goto, old_pos), #qc.Task(self.CAP_lockin.amplitude, 0.004), #qc.Task(self.SUSC_lockin.amplitude, 0.004) ) #: loop.metadata will be saved in DataSet loop.metadata.update(scan_params) loop.metadata.update({'prefactors': prefactor_strs}) for idx, ch in enumerate(meas_channels): loop.metadata['channels'][ch].update({'idx': idx}) data = loop.get_data_set(name=scan_params['fname']) #: Run the loop try: loop.run() log.info('Scan completed. DataSet saved to {}.'.format( data.location)) #: If loop is aborted by user: except KeyboardInterrupt: log.warning( 'Scan aborted by user. Going to [0,0,0] V. DataSet saved to {}.' .format(data.location)) finally: try: #: Stop 'scan_plane_ai_task' so that we can read our current position ai_task.stop() ai_task.close() #: If there's an active AO task, close it so that we can use goto self.scanner.control_ao_task('stop') self.scanner.control_ao_task('close') self.remove_component('daq_ai') except: pass self.scanner.goto([0, 0, 0]) #self.CAP_lockin.amplitude(0.004) #self.SUSC_lockin.amplitude(0.004) utils.scan_to_mat_file(data, real_units=True, interpolator=self.scanner.surface_interp)
def td_cap(self, tdc_params: Dict[str, Any], update_snap: bool = True) -> Tuple[Any]: """Performs a capacitive touchdown. Args: tdc_params: Dict of capacitive touchdown parameters as defined in measurement configuration file. update_snap: Whether to update the microscope snapshot. Default True. (You may want this to be False when getting a plane or approaching.) Returns: Tuple[qcodes.DataSet, plots.TDCPlot]: data, tdc_plot DataSet and plot generated by the touchdown Loop. """ old_pos = self.scanner.position() constants = tdc_params['constants'] daq_config = self.config['instruments']['daq'] daq_name = daq_config['name'] ai_channels = daq_config['channels']['analog_inputs'] meas_channels = tdc_params['channels'] channels = {} for ch in meas_channels: channels.update({ch: ai_channels[ch]}) nchannels = len(channels.keys()) daq_rate = self.Q_(daq_config['rate']).to('Hz').magnitude / nchannels self.set_lockins(tdc_params) self.snapshot(update=update_snap) #: z position voltage step dV = self.Q_(tdc_params['dV']).to('V').magnitude #: Start and end z position voltages startV, endV = sorted( [self.Q_(lim).to('V').magnitude for lim in tdc_params['range']]) delay = constants['wait_factor'] * max( self.CAP_lockin.time_constant(), self.SUSC_lockin.time_constant()) prefactors = self.get_prefactors(tdc_params) #: get channel prefactors in string form so they can be saved in metadata prefactor_strs = {} for ch, prefac in prefactors.items(): unit = tdc_params['channels'][ch]['unit'] pre = prefac.to('{}/V'.format(unit)) prefactor_strs.update( {ch: '{} {}'.format(pre.magnitude, pre.units)}) ai_task = nidaqmx.Task('td_cap_ai_task') self.remove_component('daq_ai') if hasattr(self, 'daq_ai'): #self.daq_ai.clear_instances() self.daq_ai.close() self.daq_ai = DAQAnalogInputs('daq_ai', daq_name, daq_rate, channels, ai_task) loop_counter = utils.Counter() tdc_plot = TDCPlot(tdc_params, self.ureg) loop = qc.Loop(self.scanner.position_z.sweep(startV, endV, dV)).each( qc.Task(time.sleep, delay), self.daq_ai.voltage, qc.Task(self.scanner.check_for_td, tdc_plot, qc.loops.active_data_set, loop_counter), qc.Task(self.scanner.get_td_height, tdc_plot), qc.BreakIf(lambda scanner=self.scanner: scanner.break_loop or scanner.td_has_occurred), qc.Task(loop_counter.advance) ).then( qc .Task(ai_task.stop), qc. Task(ai_task.close ), #qc.Task(self.CAP_lockin.amplitude, 0.004), #qc.Task(self.SUSC_lockin.amplitude, 0.004), qc.Task(self.scanner.retract), qc.Task(tdc_plot.fig.show), qc.Task(tdc_plot.save)) #: loop.metadata will be saved in DataSet loop.metadata.update(tdc_params) loop.metadata.update({'prefactors': prefactor_strs}) for idx, ch in enumerate(meas_channels): loop.metadata['channels'][ch].update({'idx': idx}) data = loop.get_data_set(name=tdc_params['fname'], write_period=None) try: log.info('Starting capacitive touchdown.') loop.run() if self.scanner.td_height is not None: data.metadata['loop']['metadata'].update( {'td_height': self.scanner.td_height}) if abs(old_pos[0]) < 0.01 and abs(old_pos[1]) < 0.01: self.scanner.metadata['plane'].update( {'z': self.scanner.td_height}) except KeyboardInterrupt: log.warning( 'Touchdown interrupted by user. Retracting scanner. DataSet saved to {}.' .format(data.location)) #: Set break_loop = True so that get_plane() and approach() will be aborted self.scanner.break_loop = True finally: try: #: Stop 'td_cap_ai_task' so that we can read our current position ai_task.stop() ai_task.close() self.scanner.retract() #self.CAP_lockin.amplitude(0.004) tdc_plot.fig.show() tdc_plot.save() except: pass utils.td_to_mat_file(data, real_units=True) return data, tdc_plot
step_param.set = step_setter def make_things_right(): prepareZIUHFLI(zi, demod_freq, npts, SRstring, no_of_avgs, meastime, outputpwr, single_channel=single_channel) zi.Scope.prepare_scope() resetTask = qc.Task(make_things_right) make_things_right() awg.ch1_state(1) awg.run() p1 = hightimes[0] p2 = hightimes[-1] num = len(hightimes) try: #innerloop = qc.Loop(step_param.sweep(p1, p2, num=num), delay=0.01).each(zi.scope_full_avg_ch1, # resetTask) #outerloop = qc.Loop(qdac.ch48.v.sweep(-2.658, -2.64, num=50), delay=1).each(innerloop) #data = outerloop.get_data_set(name='testsweep') #plot = qc.QtPlot() #plot.add(data.arrays['ziuhfli_scope_full_avg_ch1']) # add a graph to the plot
def do2Dconductance(outer_param: Parameter, outer_start: Union[float, int], outer_stop: Union[float, int], outer_npts: int, inner_param: Parameter, inner_start: Union[float, int], inner_stop: Union[float, int], inner_npts: int, lockin: SR830_T3, delay: Optional[float]=None): """ Function to perform a sped-up 2D conductance measurement Args: outer_param: The outer loop voltage parameter outer_start: The outer loop start voltage outer_stop: The outer loop stop voltage outer_npts: The number of points in the outer loop inner_param: The inner loop voltage parameter inner_start: The inner loop start voltage inner_stop: The inner loop stop voltage inner_npts: The number of points in the inner loop lockin: The lock-in amplifier to use delay: Delay to wait after setting inner parameter before triggering lockin. If None will use default delay, otherwise used the supplied. """ station = qc.Station.default sr = lockin # Validate the instruments if sr.name not in station.components: raise KeyError('Unknown lock-in! Refusing to proceed until the ' 'lock-in has been added to the station.') if (outer_param._instrument.name not in station.components and outer_param._instrument._parent.name not in station.components): raise KeyError('Unknown instrument for outer parameter. ' 'Please add that instrument to the station.') if (inner_param._instrument.name not in station.components and inner_param._instrument._parent.name not in station.components): raise KeyError('Unknown instrument for inner parameter. ' 'Please add that instrument to the station.') tau = sr.time_constant() min_delay = 0.002 # what's the physics behind this number? if delay is None: delay = tau + min_delay # Prepare for the first iteration # Some of these things have to be repeated during the loop sr.buffer_reset() sr.buffer_start() #sr.buffer_trig_mode('ON') sr.buffer_SR('Trigger') sr.conductance.shape = (inner_npts,) sr.conductance.setpoint_names = (inner_param.name,) sr.conductance.setpoint_labels = (inner_param.label,) sr.conductance.setpoint_units = ('V',) sr.conductance.setpoints = (tuple(np.linspace(inner_start, inner_stop, inner_npts)),) def trigger(): sleep(delay) sr.send_trigger() def prepare_buffer(): # here it should be okay to call ch1_databuffer... I think... sr.ch1_databuffer.prepare_buffer_readout() # For the dataset/plotting, put in the correct setpoints sr.conductance.setpoint_names = (inner_param.name,) sr.conductance.setpoint_labels = (inner_param.label,) sr.conductance.setpoint_units = ('V',) sr.conductance.setpoints = (tuple(np.linspace(inner_start, inner_stop, inner_npts)),) def start_buffer(): sr.buffer_start() sr.conductance.shape = (inner_npts,) # This is something def reset_buffer(): sr.buffer_reset() trig_task = qc.Task(trigger) reset_task = qc.Task(reset_buffer) start_task = qc.Task(start_buffer) inner_loop = qc.Loop(inner_param.sweep(inner_start, inner_stop, num=inner_npts)).each(trig_task) outer_loop = qc.Loop(outer_param.sweep(outer_start, outer_stop, num=outer_npts)).each(start_task, inner_loop, sr.conductance, reset_task) set_params = ((inner_param, inner_start, inner_stop), (outer_param, outer_start, outer_stop)) meas_params = (sr.conductance,) prepare_buffer() qdac = None # ensure that any waveform generator is unbound from the qdac channels that we step if # we are stepping the qdac if isinstance(inner_param._instrument, QDacch): qdacch = inner_param._instrument qdacch.slope('Inf') if isinstance(outer_param._instrument, QDacch): qdacch = outer_param._instrument qdacch.slope('Inf') if qdac: qdac.fast_voltage_set(True) # now that we have unbound the function generators # we don't need to do it in the loop qdac.voltage_set_dont_wait(False) # this is un safe and highly experimental plot, data = _do_measurement(outer_loop, set_params, meas_params, do_plots=True) return plot, data