Skip to content

Commit

Permalink
Merge pull request #639 from qiboteam/fix-ros-zurich2
Browse files Browse the repository at this point in the history
fix ros2 zurich
  • Loading branch information
Jacfomg authored Nov 13, 2023
2 parents c95797c + 5b33a33 commit f08149e
Showing 1 changed file with 66 additions and 59 deletions.
125 changes: 66 additions & 59 deletions src/qibolab/instruments/zhinst.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,13 @@ def select_pulse(pulse, pulse_type):
can_compress=True,
)
else:
# TODO: Test this when we have pulses that use it
# Test this when we have pulses that use it
return sampled_pulse_complex(
uid=(f"{pulse_type}_{pulse.qubit}_"),
samples=pulse.envelope_waveform_i.data + (1j * pulse.envelope_waveform_q.data),
can_compress=True,
)

# TODO: if "Slepian" in str(pulse.shape):
# Implement Slepian shaped flux pulse https://arxiv.org/pdf/0909.5368.pdf

# """
Expand Down Expand Up @@ -228,7 +227,7 @@ def __init__(self, sweeper, qubit=None, sequence=None, pulse=None):
self.sweeper = sweeper
"""Qibolab sweeper"""

# TODO: Do something with the pulse coming here
# Do something with the pulse coming here
if sweeper.parameter is Parameter.bias:
if isinstance(qubit, Qubit):
pulse = FluxPulse(
Expand Down Expand Up @@ -436,7 +435,7 @@ def register_readout_line(self, qubit, intermediate_frequency):
modulation_type=lo.ModulationType.SOFTWARE,
),
local_oscillator=lo.Oscillator(
uid="lo_shfqa",
uid="lo_shfqa_m" + str(q),
frequency=int(qubit.readout.local_oscillator.frequency),
),
range=qubit.readout.power_range,
Expand All @@ -453,7 +452,7 @@ def register_readout_line(self, qubit, intermediate_frequency):
modulation_type=lo.ModulationType.SOFTWARE,
),
local_oscillator=lo.Oscillator(
uid="lo_shfqa",
uid="lo_shfqa_a" + str(q),
frequency=int(qubit.readout.local_oscillator.frequency),
),
range=qubit.feedback.power_range,
Expand All @@ -471,7 +470,7 @@ def register_drive_line(self, qubit, intermediate_frequency):
modulation_type=lo.ModulationType.HARDWARE,
),
local_oscillator=lo.Oscillator(
uid="lo_shfqc",
uid="lo_shfqc" + str(q),
frequency=int(qubit.drive.local_oscillator.frequency),
),
range=qubit.drive.power_range,
Expand Down Expand Up @@ -505,13 +504,15 @@ def register_couplerflux_line(self, coupler):

def run_exp(self):
"""Compilation settings, compilation step, execution step and data retrival"""
# self.experiment.save("saved_exp")
self.exp = self.session.compile(self.experiment, compiler_settings=COMPILER_SETTINGS)
# self.exp.save_compiled_experiment("saved_exp")
self.results = self.session.run(self.exp)

@staticmethod
def frequency_from_pulses(qubits, sequence):
"""Gets the frequencies from the pulses to the qubits"""
# FIXME: Dual drive frequency experiments
# Implement Dual drive frequency experiments, we don't have any for now
for pulse in sequence:
qubit = qubits[pulse.qubit]
if pulse.type is PulseType.READOUT:
Expand Down Expand Up @@ -539,6 +540,7 @@ def play(self, qubits, couplers, sequence, options):
self.frequency_from_pulses(qubits, sequence)

self.experiment_flow(qubits, couplers, sequence, options)

self.run_exp()

# Get the results back
Expand All @@ -552,7 +554,7 @@ def play(self, qubits, couplers, sequence, options):
data = (
np.array([exp_res]) if options.averaging_mode is AveragingMode.CYCLIC else np.array(exp_res)
)
data = np.ones(data.shape) - data.real # FIXME: Probability inversion
data = np.ones(data.shape) - data.real # Probability inversion patch
results[ropulse.pulse.serial] = options.results_type(data)
results[ropulse.pulse.qubit] = options.results_type(data)
else:
Expand Down Expand Up @@ -615,15 +617,14 @@ def nt_loop(sweeper):
aux_list[aux_list.index(element)].add_sweeper(sweeper, qubits[pulse.qubit])

if sweeper.parameter.name in SWEEPER_BIAS:
# TODO: This should be joined
if sweeper.qubits:
for qubit in sweeper.qubits:
zhsequence[f"flux{qubit.name}"] = [ZhSweeperLine(sweeper, qubit, sequence)]
if sweeper.couplers:
for coupler in sweeper.couplers:
zhsequence[f"couplerflux{coupler.name}"] = [ZhSweeperLine(sweeper, coupler, sequence)]

# FIXME: This may not place the Zhsweeper when the start occurs among different sections or lines
# This may not place the Zhsweeper when the start occurs among different sections or lines
if sweeper.parameter.name in SWEEPER_START:
pulse = sweeper.pulses[0]
aux_list = zhsequence[f"{pulse.type.name.lower()}{pulse.qubit}"]
Expand Down Expand Up @@ -745,7 +746,7 @@ def play_sweep_select_single(exp, qubit, pulse, section, parameters, partial_swe
phase=pulse.pulse.relative_phase,
)

# FIXME: Now hardcoded for the flux pulse for 2q gates
# Hardcoded for the flux pulse for 2q gates
@staticmethod
def play_sweep_select_dual(exp, qubit, pulse, section, parameters):
"""Play Zurich pulse when two sweepers are involved on the same pulse"""
Expand Down Expand Up @@ -794,8 +795,6 @@ def couplerflux(self, exp, couplers):
i = 0
time = 0
for pulse in self.sequence[f"couplerflux{c}"]:
# TODO: Needed ?
# if not isinstance(pulse, ZhSweeperLine):
pulse.zhpulse.uid += str(i)
exp.delay(
signal=f"couplerflux{c}",
Expand All @@ -804,7 +803,6 @@ def couplerflux(self, exp, couplers):
time = round(pulse.pulse.duration * NANO_TO_SECONDS, 9) + round(
pulse.pulse.start * NANO_TO_SECONDS, 9
)
# TODO: Check of play sweep doesnt need changes
if isinstance(pulse, ZhSweeperLine):
self.play_sweep(exp, coupler, pulse, section="couplerflux")
elif isinstance(pulse, ZhSweeper):
Expand Down Expand Up @@ -868,7 +866,7 @@ def drive(self, exp, qubits):
elif isinstance(pulse, ZhSweeperLine):
exp.delay(signal=f"drive{q}", time=pulse.zhsweeper)

# TODO: Patch for T1 start, general ?
# Patch for T1 start, general ?
if len(self.sequence[f"readout{q}"]) > 0 and isinstance(
self.sequence[f"readout{q}"][0], ZhSweeperLine
):
Expand All @@ -892,7 +890,6 @@ def measure_relax(self, exp, qubits, relaxation_time, acquisition_type):
"""qubit readout pulse, data acquisition and qubit relaxation"""
play_after = None

# TODO: This need to be simplified !!!
if len(self.sequence_qibo.qf_pulses) != 0 and len(self.sequence_qibo.qd_pulses) != 0:
play_after = (
self.play_after_set(self.sequence_qibo.qf_pulses, "bias")
Expand Down Expand Up @@ -938,6 +935,7 @@ def measure_relax(self, exp, qubits, relaxation_time, acquisition_type):
qubit_readout_schedule[i].append(q)
iq_angle_readout_schedule[i].append(iq_angle)

weights = {}
for i, (pulses, qubits, iq_angles) in enumerate(
zip(readout_schedule.values(), qubit_readout_schedule.values(), iq_angle_readout_schedule.values())
):
Expand All @@ -958,52 +956,65 @@ def measure_relax(self, exp, qubits, relaxation_time, acquisition_type):
time=self.sequence_qibo.start * NANO_TO_SECONDS,
)

# Integration weights definition or load from the chip folder
weights_file = (
INSTRUMENTS_DATA_FOLDER / f"{self.chip}/weights/integration_weights_optimization_qubit_{q}.npy"
)
if weights_file.is_file():
samples = np.load(
weights_file,
allow_pickle=True,
if i == 0:
# Integration weights definition or load from the chip folder
weights_file = (
INSTRUMENTS_DATA_FOLDER
/ f"{self.chip}/weights/integration_weights_optimization_qubit_{q}.npy"
)
if acquisition_type == lo.AcquisitionType.DISCRIMINATION:
weight = lo.pulse_library.sampled_pulse_complex(
uid="weight" + pulse.zhpulse.uid,
# samples=samples[0] * np.exp(1j * qubit.iq_angle),
samples=samples[0] * np.exp(1j * iq_angle),
if weights_file.is_file():
samples = np.load(
weights_file,
allow_pickle=True,
)
if acquisition_type == lo.AcquisitionType.DISCRIMINATION:
weight = lo.pulse_library.sampled_pulse_complex(
uid="weight" + str(q),
# samples=samples[0] * np.exp(1j * qubit.iq_angle),
samples=samples[0] * np.exp(1j * iq_angle),
)
else:
weight = lo.pulse_library.sampled_pulse_complex(
uid="weight" + str(q),
samples=samples[0],
)
else:
weight = lo.pulse_library.sampled_pulse_complex(
uid="weight" + pulse.zhpulse.uid,
samples=samples[0],
# We adjust for smearing and remove smearing/2 at the end
exp.delay(
signal=f"acquire{q}",
time=self.smearing * NANO_TO_SECONDS,
)
else:
# We adjust for smearing and remove smearing/2 at the end
if acquisition_type == lo.AcquisitionType.DISCRIMINATION:
weight = lo.pulse_library.sampled_pulse_complex(
samples=np.ones(
[int(pulse.pulse.duration * 2 - 3 * self.smearing * NANO_TO_SECONDS)]
)
* np.exp(1j * iq_angle),
uid="weights" + str(q),
)
weights[q] = weight
else:
# TODO: Patch for multiple readouts: Remove different uids
weight = lo.pulse_library.const(
uid="weight" + str(q),
length=round(pulse.pulse.duration * NANO_TO_SECONDS, 9)
- 1.5 * self.smearing * NANO_TO_SECONDS,
amplitude=1,
)
weights[q] = weight
elif i != 0:
exp.delay(
signal=f"acquire{q}",
time=self.smearing * NANO_TO_SECONDS,
)
if acquisition_type == lo.AcquisitionType.DISCRIMINATION:
weight = lo.pulse_library.sampled_pulse_complex(
np.ones([int(pulse.pulse.duration * 2 - 3 * self.smearing * NANO_TO_SECONDS)])
* np.exp(1j * iq_angle)
)
else:
# TODO: Patch for multiple readouts: Remove different uids
weight = lo.pulse_library.const(
uid="weight",
length=round(pulse.pulse.duration * NANO_TO_SECONDS, 9)
- 1.5 * self.smearing * NANO_TO_SECONDS,
amplitude=1,
)
weight = weights[q]

measure_pulse_parameters = {"phase": 0}

if i == len(self.sequence[f"readout{q}"]) - 1:
reset_delay = relaxation_time * NANO_TO_SECONDS
else:
# FIXME: Here time of flight or not ?
# Here time of flight or not ?
reset_delay = 0 # self.time_of_flight * NANO_TO_SECONDS

exp.measure(
Expand Down Expand Up @@ -1108,7 +1119,7 @@ def sweep(self, qubits, couplers, sequence: PulseSequence, options, *sweepers):
np.array([exp_res]) if options.averaging_mode is AveragingMode.CYCLIC else np.array(exp_res)
)
data = data.real
data = np.ones(data.shape) - data # FIXME: Probability inversion
data = np.ones(data.shape) - data # Probability inversion patch
results[self.sequence[f"readout{q}"][i].pulse.serial] = options.results_type(data)
results[self.sequence[f"readout{q}"][i].pulse.qubit] = options.results_type(data)
else:
Expand All @@ -1127,10 +1138,9 @@ def sweep(self, qubits, couplers, sequence: PulseSequence, options, *sweepers):
self.offsets_off()

# html containing the pulse sequence schedule
lo.show_pulse_sheet("pulses", self.exp)
# lo.show_pulse_sheet("pulses", self.exp)
return results

# TODO: This may work without changes due to couplers
def sweep_recursion(self, qubits, couplers, exp, exp_calib, exp_options):
"""Sweepers recursion for multiple nested Real Time sweepers"""

Expand All @@ -1144,7 +1154,7 @@ def sweep_recursion(self, qubits, couplers, exp, exp_calib, exp_options):
for pulse in sweeper.pulses:
line = "drive" if pulse.type is PulseType.DRIVE else "measure"
zhsweeper = ZhSweeper(pulse, sweeper, qubits[sweeper.pulses[0].qubit]).zhsweeper
zhsweeper.uid = "frequency" # TODO: Changing the name from "frequency" breaks it f"frequency_{i}
zhsweeper.uid = "frequency" # Changing the name from "frequency" breaks it f"frequency_{i}
exp_calib[f"{line}{pulse.qubit}"] = lo.SignalCalibration(
oscillator=lo.Oscillator(
frequency=zhsweeper,
Expand All @@ -1156,7 +1166,7 @@ def sweep_recursion(self, qubits, couplers, exp, exp_calib, exp_options):
pulse = pulse.copy()
pulse.amplitude *= max(abs(sweeper.values))

# FIXME: Proper copy(sweeper) here
# Proper copy(sweeper) here if we want to keep the sweepers
# sweeper_aux = copy.copy(sweeper)
aux_max = max(abs(sweeper.values))

Expand All @@ -1179,16 +1189,15 @@ def sweep_recursion(self, qubits, couplers, exp, exp_calib, exp_options):
parameter = ZhSweeper(sweeper.pulses[0], sweeper, qubits[sweeper.pulses[0].qubit]).zhsweeper

with exp.sweep(
uid=f"sweep_{sweeper.parameter.name.lower()}_{i}", # FIXME: This uid trouble double freq ???
uid=f"sweep_{sweeper.parameter.name.lower()}_{i}", # This uid trouble double freq ???
parameter=parameter,
reset_oscillator_phase=True, # FIXME: Should we reset this phase ???
reset_oscillator_phase=True, # Should we reset this phase ???
):
if len(self.sweepers) > 0:
self.sweep_recursion(qubits, couplers, exp, exp_calib, exp_options)
else:
self.select_exp(exp, qubits, couplers, exp_options)

# TODO: This may work without changes due to couplers
def sweep_recursion_nt(self, qubits, couplers, options, exp, exp_calib):
"""
Sweepers recursion for Near Time sweepers. Faster than regular software sweepers as
Expand All @@ -1211,7 +1220,7 @@ def sweep_recursion_nt(self, qubits, couplers, options, exp, exp_calib):
pulse = pulse.copy()
pulse.amplitude *= max(abs(sweeper.values))

# FIXME: Proper copy(sweeper) here
# Proper copy(sweeper) here
# sweeper_aux = copy.copy(sweeper)
aux_max = max(abs(sweeper.values))

Expand Down Expand Up @@ -1251,8 +1260,6 @@ def play_sim(self, qubits, sequence, options, sim_time):
self.experiment_flow(qubits, sequence, options)
self.run_sim(sim_time)

# TODO: Implement further pulse viewing functions from 2.2.0
# should this be added in a way so the user can check how the sequence looks like ?
def run_sim(self, sim_time):
"""Run the simulation
Expand Down

0 comments on commit f08149e

Please sign in to comment.