Add argument to ignore framechange only channels for schedules drawing (#3441)

* use update method of set() for readability

* Add unittest test_schedule_matplotlib_drawer_show_framechange

* Style and Lint

* Style and Lint
This commit is contained in:
AzizNgoueya 2019-12-09 12:16:54 +01:00 committed by mergify[bot]
parent bab3a8e553
commit 6f565d4741
5 changed files with 41 additions and 10 deletions

View File

@ -363,7 +363,8 @@ class Schedule(ScheduleComponent):
scaling: float = None, channels_to_plot: Optional[List[Channel]] = None,
plot_all: bool = False, plot_range: Optional[Tuple[float]] = None,
interactive: bool = False, table: bool = True, label: bool = False,
framechange: bool = True, channels: Optional[List[Channel]] = None):
framechange: bool = True, channels: Optional[List[Channel]] = None,
show_framechange_channels: bool = True):
"""Plot the schedule.
Args:
@ -381,6 +382,7 @@ class Schedule(ScheduleComponent):
label: Label individual instructions
framechange: Add framechange indicators
channels: A list of channel names to plot
show_framechange_channels: Plot channels with only framechanges
Returns:
matplotlib.figure: A matplotlib figure object of the pulse schedule.
@ -399,7 +401,8 @@ class Schedule(ScheduleComponent):
scaling=scaling, plot_all=plot_all,
plot_range=plot_range, interactive=interactive,
table=table, label=label,
framechange=framechange, channels=channels)
framechange=framechange, channels=channels,
show_framechange_channels=show_framechange_channels)
def __eq__(self, other: ScheduleComponent) -> bool:
"""Test if two ScheduleComponents are equal.

View File

@ -34,6 +34,7 @@ from qiskit.pulse.channels import (DriveChannel, ControlChannel,
SnapshotChannel)
from qiskit.pulse import (SamplePulse, FrameChange, PersistentValue, Snapshot,
Acquire, PulseError)
from qiskit.pulse.commands.frame_change import FrameChangeInstruction
class EventsOutputChannels:
@ -281,17 +282,23 @@ class ScheduleDrawer:
"""
self.style = style or SchedStyle()
def _build_channels(self, schedule, channels, t0, tf):
def _build_channels(self, schedule, channels, t0, tf, show_framechange_channels=True):
# prepare waveform channels
drive_channels = collections.OrderedDict()
measure_channels = collections.OrderedDict()
control_channels = collections.OrderedDict()
acquire_channels = collections.OrderedDict()
snapshot_channels = collections.OrderedDict()
_channels = set()
if show_framechange_channels:
_channels.update(schedule.channels)
# take channels that do not only contain framechanges
else:
for start_time, instruction in schedule.instructions:
if not isinstance(instruction, FrameChangeInstruction):
_channels.update(instruction.channels)
_channels = list(schedule.channels) + channels
_channels = list(set(_channels))
_channels.update(channels)
for chan in _channels:
if isinstance(chan, DriveChannel):
try:
@ -550,7 +557,7 @@ class ScheduleDrawer:
def draw(self, schedule, dt, interp_method, plot_range,
scaling=None, channels_to_plot=None, plot_all=True,
table=True, label=False, framechange=True,
channels=None):
channels=None, show_framechange_channels=True):
"""Draw figure.
Args:
@ -566,6 +573,7 @@ class ScheduleDrawer:
label (bool): Label individual instructions
framechange (bool): Add framechange indicators
channels (list[OutputChannel]): channels to draw
show_framechange_channels (bool): Plot channels with only framechanges
Returns:
matplotlib.figure: A matplotlib figure object for the pulse schedule
@ -600,7 +608,8 @@ class ScheduleDrawer:
# prepare waveform channels
(schedule_channels, output_channels,
snapshot_channels) = self._build_channels(schedule, channels, t0, tf)
snapshot_channels) = self._build_channels(schedule, channels, t0, tf,
show_framechange_channels)
# count numbers of valid waveform
n_valid_waveform, v_max = self._count_valid_waveforms(output_channels, scaling=scaling,

View File

@ -31,7 +31,7 @@ def pulse_drawer(data, dt=1, style=None, filename=None,
interp_method=None, scaling=None, channels_to_plot=None,
plot_all=False, plot_range=None, interactive=False,
table=True, label=False, framechange=True,
channels=None):
channels=None, show_framechange_channels=True):
"""Plot the interpolated envelope of pulse
Args:
@ -52,6 +52,7 @@ def pulse_drawer(data, dt=1, style=None, filename=None,
label (bool): Label individual instructions
framechange (bool): Add framechange indicators
channels (list): A list of channel names to plot
show_framechange_channels (bool): Plot channels with only framechanges
Returns:
matplotlib.figure: A matplotlib figure object for the pulse envelope
@ -74,7 +75,8 @@ def pulse_drawer(data, dt=1, style=None, filename=None,
drawer = _matplotlib.ScheduleDrawer(style=style)
image = drawer.draw(data, dt=dt, interp_method=interp_method, scaling=scaling,
plot_range=plot_range, plot_all=plot_all, table=table,
label=label, framechange=framechange, channels=channels)
label=label, framechange=framechange, channels=channels,
show_framechange_channels=show_framechange_channels)
else:
raise VisualizationError('This data cannot be visualized.')

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -35,6 +35,7 @@ class TestPulseVisualizationImplementation(QiskitVisualizationTestCase):
pulse_matplotlib_reference = path_to_diagram_reference('pulse_matplotlib_ref.png')
instr_matplotlib_reference = path_to_diagram_reference('instruction_matplotlib_ref.png')
schedule_matplotlib_reference = path_to_diagram_reference('schedule_matplotlib_ref.png')
schedule_show_framechange_ref = path_to_diagram_reference('schedule_show_framechange_ref.png')
def setUp(self):
self.schedule = Schedule()
@ -120,6 +121,22 @@ class TestPulseVisualizationImplementation(QiskitVisualizationTestCase):
# Check ValueError is not thrown
sched.draw(plot_range=(0, 15))
# TODO: Enable for refactoring purposes and enable by default when we can
# decide if the backend is available or not.
@unittest.skipIf(not HAS_MATPLOTLIB, 'matplotlib not available.')
@unittest.skip('Useful for refactoring purposes, skipping by default.')
def test_schedule_drawer_show_framechange(self):
filename = self._get_resource_path('current_show_framechange_ref.png')
gp0 = pulse_lib.gaussian(duration=20, amp=1.0, sigma=1.0)
sched = Schedule()
sched = sched.append(gp0(DriveChannel(0)))
sched = sched.insert(60, FrameChange(phase=-1.57)(DriveChannel(0)))
sched = sched.insert(30, FrameChange(phase=-1.50)(DriveChannel(1)))
sched = sched.insert(70, FrameChange(phase=1.50)(DriveChannel(1)))
pulse_drawer(sched, filename=filename, show_framechange_channels=False)
self.assertImagesAreEqual(filename, self.schedule_show_framechange_ref)
os.remove(filename)
if __name__ == '__main__':
unittest.main(verbosity=2)