Skip to content

Commit

Permalink
feat: draft implementation of tof routine for qblox
Browse files Browse the repository at this point in the history
  • Loading branch information
PiergiorgioButtarini committed Dec 26, 2023
1 parent 71654af commit f0a9bd9
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 27 deletions.
20 changes: 12 additions & 8 deletions src/qibolab/instruments/qblox/acquisition.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,17 @@ class DemodulatedAcquisition:
It is advisable to have a power level at least higher than 5mV.
"""

scope: dict
"""Data returned by scope qblox acquisition."""
bins: dict
"""Binned acquisition data returned by qblox."""
duration: int
"""Duration of the readout pulse."""

@property
def raw(self):
return self.scope["acquisition"]["scope"]

@property
def integration(self):
return self.bins["integration"]
Expand All @@ -115,16 +121,14 @@ def shots_q(self):
return np.array(self.integration["path1"]) / self.duration

@property
def averaged_i(self):
"""I-component after demodulating and integrating every shot waveform
and then averaging over shots."""
return np.mean(self.shots_i)
def raw_i(self):
"""Average of the raw i waveforms for every readout pulse."""
return np.array(self.raw["path0"]["data"][0 : self.duration])

@property
def averaged_q(self):
"""Q-component after demodulating and integrating every shot waveform
and then averaging over shots."""
return np.mean(self.shots_q)
def raw_q(self):
"""Average of the raw q waveforms for every readout pulse."""
return np.array(self.raw["path1"]["data"][0 : self.duration])

@property
def classified(self):
Expand Down
19 changes: 9 additions & 10 deletions src/qibolab/instruments/qblox/cluster_qrm_rf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1026,14 +1026,14 @@ def acquire(self):
for port in self._output_ports_keys:
for sequencer in self._sequencers[port]:
# Store scope acquisition data on 'scope_acquisition' acquisition of the default sequencer
# TODO: Maybe this store_scope can be done only if needed to optimize the process!
if sequencer.number == self.DEFAULT_SEQUENCERS[port]:
self.device.store_scope_acquisition(
sequencer.number, "scope_acquisition"
)
scope = self.device.get_acquisitions(sequencer.number)[
"scope_acquisition"
]

if not hardware_demod_enabled: # Software Demodulation
if len(sequencer.pulses.ro_pulses) == 1:
pulse = sequencer.pulses.ro_pulses[0]
Expand All @@ -1052,19 +1052,18 @@ def acquire(self):
bins = results[pulse.serial]["acquisition"]["bins"]
acquisitions[pulse.qubit] = acquisitions[
pulse.serial
] = DemodulatedAcquisition(bins, duration)

] = DemodulatedAcquisition(scope, 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(
scope, duration, frequency
)
# if len(sequencer.pulses.ro_pulses) == 1:
# pulse = sequencer.pulses.ro_pulses[0]
# frequency = self.get_if(pulse)
# acquisitions[pulse.serial].averaged = AveragedAcquisition(
# scope, duration, frequency
# )

# grab only the data required by the platform
# TODO: to be updated once the functionality of ExecutionResults is extended
return {key: acquisition.data for key, acquisition in acquisitions.items()}
return {key: acquisition for key, acquisition in acquisitions.items()}

def start(self):
"""Empty method to comply with Instrument interface."""
Expand Down
17 changes: 8 additions & 9 deletions src/qibolab/instruments/qblox/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,25 +201,24 @@ def _execute_pulse_sequence(
and not module_pulses[name].ro_pulses.is_empty
):
results = module.acquire()
existing_keys = set(acquisition_results.keys()) & set(results.keys())
for key, value in results.items():
if key in existing_keys:
acquisition_results[key].update(value)
else:
acquisition_results[key] = value

acquisition_results[key] = value
# TODO: move to QRM_RF.acquire()
shape = tuple(len(sweeper.values) for sweeper in reversed(sweepers))
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.serial].classified
_res = np.reshape(_res, shots_shape)
if options.averaging_mode is not AveragingMode.SINGLESHOT:
_res = np.mean(_res, axis=0)
elif options.acquisition_type is AcquisitionType.RAW:
i_raw = acquisition_results[ro_pulse.serial].raw_i
q_raw = acquisition_results[ro_pulse.serial].raw_q
_res = i_raw + 1j * q_raw
else:
ires = acquisition_results[ro_pulse.serial][0]
qres = acquisition_results[ro_pulse.serial][1]
ires = acquisition_results[ro_pulse.serial].shots_i
qres = acquisition_results[ro_pulse.serial].shots_q
_res = ires + 1j * qres
if options.averaging_mode is AveragingMode.SINGLESHOT:
_res = np.reshape(_res, shots_shape)
Expand Down

0 comments on commit f0a9bd9

Please sign in to comment.