Skip to content

Commit

Permalink
Merge pull request #750 from qiboteam/simplify-pulse-2
Browse files Browse the repository at this point in the history
Drop pulse serial
  • Loading branch information
alecandido authored Jan 22, 2024
2 parents 0d08732 + dea5405 commit bf8232d
Show file tree
Hide file tree
Showing 23 changed files with 319 additions and 443 deletions.
2 changes: 1 addition & 1 deletion doc/source/getting-started/experiment.rst
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ We leave to the dedicated tutorial a full explanation of the experiment, but her
results = platform.sweep(sequence, options, sweeper)

# plot the results
amplitudes = results[ro_pulse.serial].magnitude
amplitudes = results[ro_pulse.id].magnitude
frequencies = np.arange(-2e8, +2e8, 1e6) + ro_pulse.frequency

plt.title("Resonator Spectroscopy")
Expand Down
12 changes: 6 additions & 6 deletions doc/source/tutorials/calibration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ In few seconds, the experiment will be finished and we can proceed to plot it.

import matplotlib.pyplot as plt

amplitudes = results[readout_pulse.serial].magnitude
amplitudes = results[readout_pulse.id].magnitude
frequencies = np.arange(-2e8, +2e8, 1e6) + readout_pulse.frequency

plt.title("Resonator Spectroscopy")
Expand Down Expand Up @@ -154,7 +154,7 @@ We can now proceed to launch on hardware:

results = platform.sweep(sequence, options, sweeper)

amplitudes = results[readout_pulse.serial].magnitude
amplitudes = results[readout_pulse.id].magnitude
frequencies = np.arange(-2e8, +2e8, 1e6) + drive_pulse.frequency

plt.title("Resonator Spectroscopy")
Expand Down Expand Up @@ -242,13 +242,13 @@ and its impact on qubit states in the IQ plane.
plt.xlabel("I [a.u.]")
plt.ylabel("Q [a.u.]")
plt.scatter(
results_one[readout_pulse1.serial].voltage_i,
results_one[readout_pulse1.serial].voltage_q,
results_one[readout_pulse1.id].voltage_i,
results_one[readout_pulse1.id].voltage_q,
label="One state",
)
plt.scatter(
results_zero[readout_pulse2.serial].voltage_i,
results_zero[readout_pulse2.serial].voltage_q,
results_zero[readout_pulse2.id].voltage_i,
results_zero[readout_pulse2.id].voltage_q,
label="Zero state",
)
plt.show()
Expand Down
268 changes: 152 additions & 116 deletions examples/pulses_tutorial.ipynb

Large diffs are not rendered by default.

6 changes: 2 additions & 4 deletions src/qibolab/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def assign_measurements(self, measurement_map, readout):
containing the readout measurement shots. This is created in ``execute_circuit``.
"""
for gate, sequence in measurement_map.items():
_samples = (readout[pulse.serial].samples for pulse in sequence)
_samples = (readout[pulse.id].samples for pulse in sequence)
samples = list(filter(lambda x: x is not None, _samples))
gate.result.backend = self
gate.result.register_samples(np.array(samples).T)
Expand Down Expand Up @@ -156,9 +156,7 @@ def execute_circuits(self, circuits, initial_state=None, nshots=1000):
MeasurementOutcomes(circuit.measurements, self, nshots=nshots)
)
for gate, sequence in measurement_map.items():
samples = [
readout[pulse.serial].popleft().samples for pulse in sequence
]
samples = [readout[pulse.id].popleft().samples for pulse in sequence]
gate.result.backend = self
gate.result.register_samples(np.array(samples).T)
return results
4 changes: 2 additions & 2 deletions src/qibolab/instruments/dummy.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def play(

for ro_pulse in sequence.ro_pulses:
values = np.squeeze(self.get_values(options, ro_pulse, shape))
results[ro_pulse.qubit] = results[ro_pulse.serial] = options.results_type(
results[ro_pulse.qubit] = results[ro_pulse.id] = options.results_type(
values
)

Expand Down Expand Up @@ -149,7 +149,7 @@ def sweep(

for ro_pulse in sequence.ro_pulses:
values = self.get_values(options, ro_pulse, shape)
results[ro_pulse.qubit] = results[ro_pulse.serial] = options.results_type(
results[ro_pulse.qubit] = results[ro_pulse.id] = options.results_type(
values
)

Expand Down
10 changes: 5 additions & 5 deletions src/qibolab/instruments/qblox/cluster_qrm_rf.py
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ def process_pulse_sequence(

# Acquisitions
for acquisition_index, pulse in enumerate(sequencer.pulses.ro_pulses):
sequencer.acquisitions[pulse.serial] = {
sequencer.acquisitions[pulse.id] = {
"num_bins": num_bins,
"index": acquisition_index,
}
Expand Down Expand Up @@ -990,7 +990,7 @@ def acquire(self):
pulse = sequencer.pulses.ro_pulses[0]
frequency = self.get_if(pulse)
acquisitions[pulse.qubit] = acquisitions[
pulse.serial
pulse.id
] = AveragedAcquisition(scope, duration, frequency)
else:
raise RuntimeError(
Expand All @@ -1000,16 +1000,16 @@ def acquire(self):
else: # Hardware Demodulation
results = self.device.get_acquisitions(sequencer.number)
for pulse in sequencer.pulses.ro_pulses:
bins = results[pulse.serial]["acquisition"]["bins"]
bins = results[pulse.id]["acquisition"]["bins"]
acquisitions[pulse.qubit] = acquisitions[
pulse.serial
pulse.id
] = DemodulatedAcquisition(bins, duration)

# Provide Scope Data for verification (assuming memory reseet is being done)
if len(sequencer.pulses.ro_pulses) == 1:
pulse = sequencer.pulses.ro_pulses[0]
frequency = self.get_if(pulse)
acquisitions[pulse.serial].averaged = AveragedAcquisition(
acquisitions[pulse.id].averaged = AveragedAcquisition(
scope, duration, frequency
)

Expand Down
18 changes: 9 additions & 9 deletions src/qibolab/instruments/qblox/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,21 +201,21 @@ def _execute_pulse_sequence(
shots_shape = (nshots,) + shape
for ro_pulse in sequence.ro_pulses:
if options.acquisition_type is AcquisitionType.DISCRIMINATION:
_res = acquisition_results[ro_pulse.serial][2]
_res = acquisition_results[ro_pulse.id][2]
_res = np.reshape(_res, shots_shape)
if options.averaging_mode is not AveragingMode.SINGLESHOT:
_res = np.mean(_res, axis=0)
else:
ires = acquisition_results[ro_pulse.serial][0]
qres = acquisition_results[ro_pulse.serial][1]
ires = acquisition_results[ro_pulse.id][0]
qres = acquisition_results[ro_pulse.id][1]
_res = ires + 1j * qres
if options.averaging_mode is AveragingMode.SINGLESHOT:
_res = np.reshape(_res, shots_shape)
else:
_res = np.reshape(_res, shape)

acquisition = options.results_type(np.squeeze(_res))
data[ro_pulse.serial] = data[ro_pulse.qubit] = acquisition
data[ro_pulse.id] = data[ro_pulse.qubit] = acquisition

return data

Expand Down Expand Up @@ -280,7 +280,7 @@ def sweep(

# create a map between the pulse id, which never changes, and the original serial
for pulse in sequence_copy.ro_pulses:
map_id_serial[pulse.id] = pulse.serial
map_id_serial[pulse.id] = pulse.id
id_results[pulse.id] = None
id_results[pulse.qubit] = None

Expand Down Expand Up @@ -392,9 +392,9 @@ def _sweep_recursion(
)
for pulse in sequence.ro_pulses:
if results[pulse.id]:
results[pulse.id] += result[pulse.serial]
results[pulse.id] += result[pulse.id]
else:
results[pulse.id] = result[pulse.serial]
results[pulse.id] = result[pulse.id]
results[pulse.qubit] = results[pulse.id]
else:
# rt sweeps
Expand Down Expand Up @@ -485,9 +485,9 @@ def _sweep_recursion(
)
for pulse in sequence.ro_pulses:
if results[pulse.id]:
results[pulse.id] += result[pulse.serial]
results[pulse.id] += result[pulse.id]
else:
results[pulse.id] = result[pulse.serial]
results[pulse.id] = result[pulse.id]
results[pulse.qubit] = results[pulse.id]
else:
sweepers_repetitions = 1
Expand Down
22 changes: 11 additions & 11 deletions src/qibolab/instruments/qm/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,23 +252,23 @@ def register_pulse(self, qubit, pulse):
instantiation of the Qubit objects. They are named as
"drive0", "drive1", "flux0", "readout0", ...
"""
if pulse.serial not in self.pulses:
if pulse.id not in self.pulses:
if pulse.type is PulseType.DRIVE:
serial_i = self.register_waveform(pulse, "i")
serial_q = self.register_waveform(pulse, "q")
self.pulses[pulse.serial] = {
self.pulses[str(pulse.id)] = {
"operation": "control",
"length": pulse.duration,
"waveforms": {"I": serial_i, "Q": serial_q},
}
# register drive pulse in elements
self.elements[f"drive{qubit.name}"]["operations"][
pulse.serial
] = pulse.serial
str(pulse.id)
] = pulse.id

elif pulse.type is PulseType.FLUX:
serial = self.register_waveform(pulse)
self.pulses[pulse.serial] = {
self.pulses[str(pulse.id)] = {
"operation": "control",
"length": pulse.duration,
"waveforms": {
Expand All @@ -277,14 +277,14 @@ def register_pulse(self, qubit, pulse):
}
# register flux pulse in elements
self.elements[f"flux{qubit.name}"]["operations"][
pulse.serial
] = pulse.serial
str(pulse.id)
] = pulse.id

elif pulse.type is PulseType.READOUT:
serial_i = self.register_waveform(pulse, "i")
serial_q = self.register_waveform(pulse, "q")
self.register_integration_weights(qubit, pulse.duration)
self.pulses[pulse.serial] = {
self.pulses[str(pulse.id)] = {
"operation": "measurement",
"length": pulse.duration,
"waveforms": {
Expand All @@ -300,8 +300,8 @@ def register_pulse(self, qubit, pulse):
}
# register readout pulse in elements
self.elements[f"readout{qubit.name}"]["operations"][
pulse.serial
] = pulse.serial
str(pulse.id)
] = pulse.id

else:
raise_error(TypeError, f"Unknown pulse type {pulse.type.name}.")
Expand Down Expand Up @@ -332,7 +332,7 @@ def register_waveform(self, pulse, mode="i"):
self.waveforms[serial] = {"type": "constant", "sample": pulse.amplitude}
else:
waveform = getattr(pulse, f"envelope_waveform_{mode}")(SAMPLING_RATE)
serial = waveform.serial
serial = hash(waveform)
if serial not in self.waveforms:
self.waveforms[serial] = {
"type": "arbitrary",
Expand Down
2 changes: 1 addition & 1 deletion src/qibolab/instruments/qm/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def fetch_results(result, ro_pulses):
results = {}
for qmpulse in ro_pulses:
pulse = qmpulse.pulse
results[pulse.qubit] = results[pulse.serial] = qmpulse.acquisition.fetch(
results[pulse.qubit] = results[pulse.id] = qmpulse.acquisition.fetch(
handles
)
return results
Expand Down
18 changes: 9 additions & 9 deletions src/qibolab/instruments/qm/sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class QMPulse:

def __post_init__(self):
self.element: str = f"{self.pulse.type.name.lower()}{self.pulse.qubit}"
self.operation: str = self.pulse.serial
self.operation: str = self.pulse.id
self.relative_phase: float = self.pulse.relative_phase / (2 * np.pi)
self.elements_to_align.add(self.element)

Expand Down Expand Up @@ -117,9 +117,9 @@ def declare_output(self, options, threshold=None, angle=None):
average = options.averaging_mode is AveragingMode.CYCLIC
acquisition_type = options.acquisition_type
if acquisition_type is AcquisitionType.RAW:
self.acquisition = RawAcquisition(self.pulse.serial, average)
self.acquisition = RawAcquisition(self.pulse.id, average)
elif acquisition_type is AcquisitionType.INTEGRATION:
self.acquisition = IntegratedAcquisition(self.pulse.serial, average)
self.acquisition = IntegratedAcquisition(self.pulse.id, average)
elif acquisition_type is AcquisitionType.DISCRIMINATION:
if threshold is None or angle is None:
raise_error(
Expand All @@ -128,7 +128,7 @@ def declare_output(self, options, threshold=None, angle=None):
"if threshold and angle are not given.",
)
self.acquisition = ShotsAcquisition(
self.pulse.serial, average, threshold, angle
self.pulse.id, average, threshold, angle
)
else:
raise_error(ValueError, f"Invalid acquisition type {acquisition_type}.")
Expand Down Expand Up @@ -186,8 +186,8 @@ def bake(self, config: QMConfig, durations: DurationsType):
self.calculate_waveform(waveform_i, t),
self.calculate_waveform(waveform_q, t),
]
segment.add_op(self.pulse.serial, self.element, waveform)
segment.play(self.pulse.serial, self.element)
segment.add_op(self.pulse.id, self.element, waveform)
segment.play(self.pulse.id, self.element)
self.segments.append(segment)

@property
Expand Down Expand Up @@ -219,7 +219,7 @@ def find_duration_sweeper_pulses(sweepers):

if sweeper.parameter is Parameter.duration and step % 4 != 0:
for pulse in sweeper.pulses:
duration_sweep_pulses.add(pulse.serial)
duration_sweep_pulses.add(pulse.id)

return duration_sweep_pulses

Expand Down Expand Up @@ -273,7 +273,7 @@ def create(cls, qubits, sequence, sweepers, config, time_of_flight, smearing):
if (
pulse.duration % 4 != 0
or pulse.duration < 16
or pulse.serial in duration_sweep_pulses
or pulse.id in duration_sweep_pulses
):
qmpulse = BakedPulse(pulse)
qmpulse.bake(config, durations=[pulse.duration])
Expand Down Expand Up @@ -301,7 +301,7 @@ def _find_previous(self, pulse):

def add(self, qmpulse: QMPulse):
pulse = qmpulse.pulse
self.pulse_to_qmpulse[pulse.serial] = qmpulse
self.pulse_to_qmpulse[pulse.id] = qmpulse
if pulse.type is PulseType.READOUT:
self.ro_pulses.append(qmpulse)

Expand Down
16 changes: 8 additions & 8 deletions src/qibolab/instruments/qm/sweepers.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ def maximum_sweep_value(values, value0):

def _update_baked_pulses(sweeper, qmsequence, config):
"""Updates baked pulse if duration sweeper is used."""
qmpulse = qmsequence.pulse_to_qmpulse[sweeper.pulses[0].serial]
qmpulse = qmsequence.pulse_to_qmpulse[sweeper.pulses[0].id]
is_baked = isinstance(qmpulse, BakedPulse)
for pulse in sweeper.pulses:
qmpulse = qmsequence.pulse_to_qmpulse[pulse.serial]
qmpulse = qmsequence.pulse_to_qmpulse[pulse.id]
if isinstance(qmpulse, BakedPulse):
if not is_baked:
raise_error(
Expand Down Expand Up @@ -96,7 +96,7 @@ def _sweep_frequency(sweepers, qubits, qmsequence, relaxation_time):
f = declare(int)
with for_(*from_array(f, sweeper.values.astype(int))):
for pulse, f0 in zip(sweeper.pulses, freqs0):
qmpulse = qmsequence.pulse_to_qmpulse[pulse.serial]
qmpulse = qmsequence.pulse_to_qmpulse[pulse.id]
qua.update_frequency(qmpulse.element, f + f0)

_sweep_recursion(sweepers[1:], qubits, qmsequence, relaxation_time)
Expand All @@ -115,7 +115,7 @@ def _sweep_amplitude(sweepers, qubits, qmsequence, relaxation_time):
a = declare(fixed)
with for_(*from_array(a, sweeper.values)):
for pulse in sweeper.pulses:
qmpulse = qmsequence.pulse_to_qmpulse[pulse.serial]
qmpulse = qmsequence.pulse_to_qmpulse[pulse.id]
if isinstance(qmpulse, BakedPulse):
qmpulse.amplitude = a
else:
Expand All @@ -129,7 +129,7 @@ def _sweep_relative_phase(sweepers, qubits, qmsequence, relaxation_time):
relphase = declare(fixed)
with for_(*from_array(relphase, sweeper.values / (2 * np.pi))):
for pulse in sweeper.pulses:
qmpulse = qmsequence.pulse_to_qmpulse[pulse.serial]
qmpulse = qmsequence.pulse_to_qmpulse[pulse.id]
qmpulse.relative_phase = relphase

_sweep_recursion(sweepers[1:], qubits, qmsequence, relaxation_time)
Expand Down Expand Up @@ -169,7 +169,7 @@ def _sweep_start(sweepers, qubits, qmsequence, relaxation_time):

with loop:
for pulse in sweeper.pulses:
qmpulse = qmsequence.pulse_to_qmpulse[pulse.serial]
qmpulse = qmsequence.pulse_to_qmpulse[pulse.id]
# find all pulses that are connected to ``qmpulse`` and update their starts
to_process = {qmpulse}
while to_process:
Expand All @@ -182,7 +182,7 @@ def _sweep_start(sweepers, qubits, qmsequence, relaxation_time):

def _sweep_duration(sweepers, qubits, qmsequence, relaxation_time):
sweeper = sweepers[0]
qmpulse = qmsequence.pulse_to_qmpulse[sweeper.pulses[0].serial]
qmpulse = qmsequence.pulse_to_qmpulse[sweeper.pulses[0].id]
if isinstance(qmpulse, BakedPulse):
values = np.array(sweeper.values).astype(int)
else:
Expand All @@ -191,7 +191,7 @@ def _sweep_duration(sweepers, qubits, qmsequence, relaxation_time):
dur = declare(int)
with for_(*from_array(dur, values)):
for pulse in sweeper.pulses:
qmpulse = qmsequence.pulse_to_qmpulse[pulse.serial]
qmpulse = qmsequence.pulse_to_qmpulse[pulse.id]
qmpulse.swept_duration = dur
# find all pulses that are connected to ``qmpulse`` and align them
to_process = set(qmpulse.next_)
Expand Down
2 changes: 1 addition & 1 deletion src/qibolab/instruments/rfsoc/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def _(
duration=pulse.duration * NS_TO_US,
dac=dac,
adc=adc,
name=pulse.serial,
name=pulse.id,
type=pulse_type,
)
return replace_pulse_shape(rfsoc_pulse, pulse.shape, sampling_rate)
Expand Down
Loading

0 comments on commit bf8232d

Please sign in to comment.