Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix v2 pulse drawer (backport #12608) #12614

Merged
merged 1 commit into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 58 additions & 31 deletions qiskit/visualization/pulse_v2/device_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class :py:class:``DrawerBackendInfo`` with necessary methods to generate drawing

from qiskit import pulse
from qiskit.providers import BackendConfigurationError
from qiskit.providers.backend import Backend
from qiskit.providers.backend import Backend, BackendV2


class DrawerBackendInfo(ABC):
Expand Down Expand Up @@ -106,40 +106,67 @@ def create_from_backend(cls, backend: Backend):
Returns:
OpenPulseBackendInfo: New configured instance.
"""
configuration = backend.configuration()
defaults = backend.defaults()

# load name
name = backend.name()

# load cycle time
dt = configuration.dt

# load frequencies
chan_freqs = {}

chan_freqs.update(
{pulse.DriveChannel(qind): freq for qind, freq in enumerate(defaults.qubit_freq_est)}
)
chan_freqs.update(
{pulse.MeasureChannel(qind): freq for qind, freq in enumerate(defaults.meas_freq_est)}
)
for qind, u_lo_mappers in enumerate(configuration.u_channel_lo):
temp_val = 0.0 + 0.0j
for u_lo_mapper in u_lo_mappers:
temp_val += defaults.qubit_freq_est[u_lo_mapper.q] * u_lo_mapper.scale
chan_freqs[pulse.ControlChannel(qind)] = temp_val.real

# load qubit channel mapping
qubit_channel_map = defaultdict(list)
for qind in range(configuration.n_qubits):
qubit_channel_map[qind].append(configuration.drive(qubit=qind))
qubit_channel_map[qind].append(configuration.measure(qubit=qind))
for tind in range(configuration.n_qubits):

if hasattr(backend, "configuration") and hasattr(backend, "defaults"):
configuration = backend.configuration()
defaults = backend.defaults()

name = configuration.backend_name
dt = configuration.dt

# load frequencies
chan_freqs.update(
{
pulse.DriveChannel(qind): freq
for qind, freq in enumerate(defaults.qubit_freq_est)
}
)
chan_freqs.update(
{
pulse.MeasureChannel(qind): freq
for qind, freq in enumerate(defaults.meas_freq_est)
}
)
for qind, u_lo_mappers in enumerate(configuration.u_channel_lo):
temp_val = 0.0 + 0.0j
for u_lo_mapper in u_lo_mappers:
temp_val += defaults.qubit_freq_est[u_lo_mapper.q] * u_lo_mapper.scale
chan_freqs[pulse.ControlChannel(qind)] = temp_val.real

# load qubit channel mapping
for qind in range(configuration.n_qubits):
qubit_channel_map[qind].append(configuration.drive(qubit=qind))
qubit_channel_map[qind].append(configuration.measure(qubit=qind))
for tind in range(configuration.n_qubits):
try:
qubit_channel_map[qind].extend(configuration.control(qubits=(qind, tind)))
except BackendConfigurationError:
pass
elif isinstance(backend, BackendV2):
# Pure V2 model doesn't contain channel frequency information.
name = backend.name
dt = backend.dt

# load qubit channel mapping
for qind in range(backend.num_qubits):
# channels are NotImplemented by default so we must catch arbitrary error.
try:
qubit_channel_map[qind].append(backend.drive_channel(qind))
except Exception: # pylint: disable=broad-except
pass
try:
qubit_channel_map[qind].extend(configuration.control(qubits=(qind, tind)))
except BackendConfigurationError:
qubit_channel_map[qind].append(backend.measure_channel(qind))
except Exception: # pylint: disable=broad-except
pass
for tind in range(backend.num_qubits):
try:
qubit_channel_map[qind].extend(backend.control_channel(qubits=(qind, tind)))
except Exception: # pylint: disable=broad-except
pass
else:
raise RuntimeError("Backend object not yet supported")

return OpenPulseBackendInfo(
name=name, dt=dt, channel_frequency_map=chan_freqs, qubit_channel_map=qubit_channel_map
Expand Down
7 changes: 7 additions & 0 deletions releasenotes/notes/fix-v2-pulse-drawer-d05e4e392766909f.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
fixes:
- |
Fixed a bug in :func:`qiskit.visualization.pulse_v2.interface.draw` that didn't
draw pulse schedules when the draw function was called with a :class:`.BackendV2` argument.
Because the V2 backend doesn't report hardware channel frequencies,
the generated drawing will show 'no freq.' below each channel label.
Loading