Skip to content

Commit

Permalink
Fix v2 pulse drawer (#12608) (#12613)
Browse files Browse the repository at this point in the history
* fix error when V2 model is set

* Apply suggestions from code review

* Fix black

---------

Co-authored-by: Elena Peña Tapia <[email protected]>
Co-authored-by: Elena Peña Tapia <[email protected]>
(cherry picked from commit 7d1731b)

Co-authored-by: Naoki Kanazawa <[email protected]>
  • Loading branch information
mergify[bot] and nkanazawa1989 authored Jun 20, 2024
1 parent 7666771 commit d9c40e1
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 31 deletions.
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.

0 comments on commit d9c40e1

Please sign in to comment.