Skip to content
Open
83 changes: 55 additions & 28 deletions pytopo/cQED/softwarespec.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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):
"""
Expand All @@ -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):
"""
Expand All @@ -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:
Expand All @@ -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
Expand All @@ -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):
"""
Expand All @@ -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):
Expand Down Expand Up @@ -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)

Expand All @@ -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)))
np.vstack((mag.reshape(-1), phase.reshape(-1), re.reshape(-1), im.reshape(-1), np.ones(qubit_frequencies.size) * peak_frequency)))
55 changes: 54 additions & 1 deletion pytopo/rf/alazar/awg_sequences.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)