diff --git a/pytopo/cQED/softwarespec.py b/pytopo/cQED/softwarespec.py index 231fb93..b85aee9 100644 --- a/pytopo/cQED/softwarespec.py +++ b/pytopo/cQED/softwarespec.py @@ -9,9 +9,6 @@ from pytopo.rf.alazar import awg_sequences from pytopo.rf.alazar import acquisition_controllers -from plottr import qcodes_dataset -from plottr.qcodes_dataset import QcodesDatasetSubscriber - from qcodes.instrument.parameter import Parameter from qcodes.dataset.plotting import plot_by_id from qcodes.dataset.data_export import get_data_by_id @@ -22,7 +19,6 @@ from pytopo.rf.alazar.awg_sequences import TriggerSequence - class SoftSweepCtl(acquisition_controllers.PostIQCtl): """ An acquisition controller that allows fast software spec. @@ -71,8 +67,6 @@ def _perform_step(self, num): self._settle() else: print('Done!', end='\r') - - awg_tools.trigger_awg_when_ready(awg) def pre_acquire(self): """ @@ -84,7 +78,19 @@ def pre_acquire(self): self._settle() self._step = 0 - qcodes.Station.default.awg.force_trigger() + + awg = qcodes.Station.default.awg + awg.start() + + def post_acquire(self): + data = super().post_acquire() + + awg = qcodes.Station.default.awg + awg.stop() + + time.sleep(0.2) + + return data def buffer_done_callback(self, buffernum): """ @@ -95,7 +101,8 @@ def buffer_done_callback(self, buffernum): def setup_soft_sweep(values, param, time_bin=0.2e-3, integration_time=10e-3, - post_integration_delay=10e-6, setup_awg=True, ctl=None): + post_integration_delay=10e-6, setup_awg=True, ctl=None, + waiting_time_per_value=0): awg = qcodes.Station.default.awg if ctl is None: @@ -106,8 +113,9 @@ def setup_soft_sweep(values, param, time_bin=0.2e-3, integration_time=10e-3, if setup_awg: trig_seq = TriggerSequence(awg, SR=1e7) - trig_seq.wait = 'first' - trig_seq.setup_awg(cycle_time=time_bin, debug_signal=False, ncycles=navgs, plot=False) + trig_seq.wait = 'off' + trig_seq.setup_awg(cycle_time=time_bin, debug_signal=False, ncycles=navgs, plot=False, + final_waiting_time=waiting_time_per_value, start_awg=False) ctl.param = param ctl.values = values @@ -121,36 +129,50 @@ def setup_soft_sweep(values, param, time_bin=0.2e-3, integration_time=10e-3, return ctl -def get_soft_sweep_trace(ctl=None): +def get_soft_sweep_trace(ctl=None, phase_reference_arm=False): if ctl is None: ctl = qcodes.Station.default.softsweep_ctl - data = np.squeeze(ctl.acquisition())[..., 0] - mag, phase = np.abs(data), np.angle(data, deg=True) - return mag, phase + data_AB = np.squeeze(ctl.acquisition()) + data_A = data_AB[...,0] + data_B = data_AB[...,1] + if phase_reference_arm == True: + data = data_A*np.exp(-1.j*(np.angle(data_B))) + else: + data = data_A + mag, phase, re, im = np.abs(data), np.angle(data, deg=True), np.real(data), np.imag(data) + return mag, phase, re, im @hardsweep( ind=[('frequency', 'Hz', 'array')], - dep=[('signal_magnitude', 'V', 'array'), ('signal_phase', 'deg', 'array')] + dep=[('signal_magnitude', 'V', 'array'), ('signal_phase', 'deg', 'array'), ('signal_real', 'V', 'array'), ('signal_imag', 'V', 'array')] ) -def measure_soft_time_avg_spec(frequencies, rf_src, integration_time=10e-3, *arg, **kw): +def measure_soft_time_avg_spec(frequencies, rf_src, integration_time=10e-3, + phase_reference_arm_delay=0, *arg, **kw): """ Use the softspec controller to measure a software-controlled spectrum. time_bin is the time per buffer, integration_time sets how many buffers we'll average per frequency point. """ setup = kw.pop('setup', True) + phase_reference_arm = kw.pop('phase_reference_arm', False) + if setup: ctl = setup_soft_sweep(frequencies, rf_src.frequency, integration_time=integration_time, *arg, **kw) else: ctl = qcodes.Station.default.softsweep_ctl - mag, phase = get_soft_sweep_trace(ctl) - return (frequencies, np.vstack((mag.reshape(-1), phase.reshape(-1)))) + mag, phase, re, im = get_soft_sweep_trace(ctl, phase_reference_arm=phase_reference_arm) + + if phase_reference_arm_delay != 0: + data = (re - 1.j*im)*np.exp(1.j*phase_reference_arm_delay*frequencies) ##not sure why we need to complex conjugate, but else the phase lineshape of the resonator is inverted... (goes from low to high) + mag, phase, re, im = np.abs(data), np.angle(data, deg=True), np.real(data), np.imag(data) + + return (frequencies, np.vstack((mag.reshape(-1), phase.reshape(-1), re.reshape(-1), im.reshape(-1)))) @hardsweep( ind=[('voltage', 'mV', 'array')], - dep=[('signal_magnitude', 'V', 'array'), ('signal_phase', 'deg', 'array')] + dep=[('signal_magnitude', 'V', 'array'), ('signal_phase', 'deg', 'array'), ('signal_real', 'V', 'array'), ('signal_imag', 'V', 'array')] ) def measure_soft_gate_sweep(voltages, ivvi_dac, integration_time=10e-3, *arg, **kw): """ @@ -159,12 +181,15 @@ def measure_soft_gate_sweep(voltages, ivvi_dac, integration_time=10e-3, *arg, ** frequency point. """ setup = kw.pop('setup', True) + phase_reference_arm = kw.pop('phase_reference_arm', False) + if setup: ctl = setup_soft_sweep(voltages, ivvi_dac, integration_time=integration_time, *arg, **kw) else: ctl = qcodes.Station.default.softsweep_ctl - mag, phase = get_soft_sweep_trace(ctl) - return (voltages, np.vstack((mag.reshape(-1), phase.reshape(-1)))) + mag, phase, re, im = get_soft_sweep_trace(ctl, phase_reference_arm=phase_reference_arm) + + return (voltages, np.vstack((mag.reshape(-1), phase.reshape(-1), re.reshape(-1), im.reshape(-1)))) def setup_single_averaged_IQpoint(time_bin, integration_time, setup_awg=True): @@ -220,22 +245,25 @@ def fit_lorentzian(x,y): return out def get_resonator_spec_and_fit(frequencies): - mag, phase = get_soft_sweep_trace() + mag, phase, _, _ = get_soft_sweep_trace() out = fit_lorentzian(frequencies, mag**2) return mag, phase, out @hardsweep( ind=[('frequency', 'Hz', 'array')], - dep=[('signal_magnitude', 'V', 'array'), ('signal_phase', 'deg', 'array'), ('peak_frq', 'Hz', 'array')] + dep=[('signal_magnitude', 'V', 'array'), ('signal_phase', 'deg', 'array'), ('signal_real', 'V', 'array'), ('signal_imag', 'V', 'array'), ('peak_frq', 'Hz', 'array')] ) def measure_qubit_spec_optimize_resonator(resonator_frequencies, resonator_src, - qubit_frequencies, qubit_src, integration_time=10e-3, - *arg, **kw): + qubit_frequencies, qubit_src, integration_time=10e-3, *arg, **kw): """ Takes a resonator spec trace (using software spec), fits a lorentzian line shape, then sets the heterodyne source to the peak frequency, then measures qubit soft-spec. """ + + + phase_reference_arm = kw.pop('phase_reference_arm', False) + ctl = setup_soft_sweep(resonator_frequencies, resonator_src.frequency, integration_time=integration_time, setup_awg=False, **kw) @@ -246,8 +274,7 @@ def measure_qubit_spec_optimize_resonator(resonator_frequencies, resonator_src, ctl = setup_soft_sweep(qubit_frequencies, qubit_src.frequency, integration_time=integration_time, setup_awg=True, **kw) - mag, phase = get_soft_sweep_trace(ctl) - + mag, phase, re, im = get_soft_sweep_trace(ctl, phase_reference_arm=phase_reference_arm) return (qubit_frequencies.reshape(-1), - np.vstack((mag.reshape(-1), phase.reshape(-1), np.ones(qubit_frequencies.size) * peak_frequency))) \ No newline at end of file + np.vstack((mag.reshape(-1), phase.reshape(-1), re.reshape(-1), im.reshape(-1), np.ones(qubit_frequencies.size) * peak_frequency))) \ No newline at end of file diff --git a/pytopo/rf/alazar/awg_sequences.py b/pytopo/rf/alazar/awg_sequences.py index 90e4510..bcd80dc 100644 --- a/pytopo/rf/alazar/awg_sequences.py +++ b/pytopo/rf/alazar/awg_sequences.py @@ -81,7 +81,7 @@ class TriggerSequence(BroadBeanSequence): def sequence(self, trig_time=1e-6, cycle_time=10e-6, pre_trig_time=1e-6, ncycles=1, debug_signal=False, - ro_trigger_always_on=False): + ro_trigger_always_on=False, final_waiting_time=0): end_buffer = 1e-6 low_time = cycle_time - trig_time - pre_trig_time - end_buffer @@ -113,5 +113,58 @@ def sequence(self, trig_time=1e-6, cycle_time=10e-6, bps[k] = [(t0, t1)] elements.append(bbtools.blueprints2element(bps)) + + if final_waiting_time > 0: + bps = bbtools.BluePrints(chan_map=self.chan_map, length=final_waiting_time, sample_rate=self.SR) + bps['pulse'].insertSegment(0, ramp, (0, 0), dur=final_waiting_time) + elements.append(bbtools.blueprints2element(bps)) + + return bbtools.elements2sequence(elements, self.name) + + +class QPTriggerSequence(BroadBeanSequence): + name = 'QPtrigger_sequence' + + def sequence(self, trig_time=1e-6, cycle_time=5e-3, + pre_trig_time=1e-6, use_event_seq=False): + elements = [] + if use_event_seq: + bps = bbtools.BluePrints(chan_map=self.chan_map, length=cycle_time, sample_rate=self.SR) + bps['pulse'].insertSegment(0, ramp, (0, 0), dur=cycle_time) + + elements.append(bbtools.blueprints2element(bps)) + # readout sequence + end_buffer = 1e-6 + low_time = cycle_time - trig_time - pre_trig_time - end_buffer + + bps = bbtools.BluePrints(chan_map=self.chan_map, length=cycle_time, sample_rate=self.SR) + bps['pulse'].insertSegment(0, ramp, (0, 0), dur=cycle_time) + + bps['ats_trigger'] = [(pre_trig_time, trig_time)] + + if 'ro_trigger' in bps.map: + t0, t1 = 0, cycle_time + bps['ro_trigger'] = [(t0, t1)] + + for k, v in bps.map.items(): + if '_trigger' in k and k not in ['ats_trigger', 'ro_trigger']: + t0, t1 = pre_trig_time + trig_time, low_time + bps[k] = [(t0, t1)] + + elements.append(bbtools.blueprints2element(bps)) + + # Adding event seq + return bbtools.elements2sequence(elements, self.name) + + + def load_sequence(self, ncycles=1, **kwargs): + self.setup_awg(**kwargs) + + use_event_seq = kwargs.get('use_event_seq', False) + + if use_event_seq: + #self.awg.set_sqel_event_jump_type(2, 'INDEX') + #self.awg.set_sqel_event_target_index(2, 1) + self.awg.set_sqel_loopcnt(ncycles, 2)