• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Qiskit / qiskit / 22348708976

24 Feb 2026 11:23AM UTC coverage: 87.862% (-0.1%) from 87.959%
22348708976

Pull #15366

github

web-flow
Merge de9e13733 into d9566f0d2
Pull Request #15366: Simplify SabrePreLayout based on recent improvements to the VF2 search

3 of 3 new or added lines in 1 file covered. (100.0%)

2132 existing lines in 128 files now uncovered.

100215 of 114060 relevant lines covered (87.86%)

1147339.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/qiskit/visualization/timeline/plotters/matplotlib.py
1
# This code is part of Qiskit.
2
#
3
# (C) Copyright IBM 2020.
4
#
5
# This code is licensed under the Apache License, Version 2.0. You may
6
# obtain a copy of this license in the LICENSE.txt file in the root directory
7
# of this source tree or at https://www.apache.org/licenses/LICENSE-2.0.
8
#
9
# Any modifications or derivative works of this code must retain this
10
# copyright notice, and modified files need to carry a notice indicating
11
# that they have been altered from the originals.
12

13

14
"""Matplotlib plotter API."""
15

UNCOV
16
import matplotlib
×
17
import matplotlib.pyplot as plt
×
UNCOV
18
import numpy as np
×
19
from matplotlib.collections import PatchCollection
×
20
from matplotlib.patches import Rectangle
×
21

22
from qiskit.visualization.exceptions import VisualizationError
×
23
from qiskit.visualization.timeline import core, types, drawings
×
UNCOV
24
from qiskit.visualization.timeline.plotters.base_plotter import BasePlotter
×
25
from qiskit.visualization.utils import matplotlib_close_if_inline
×
26

27

28
class MplPlotter(BasePlotter):
×
29
    """Matplotlib API for pulse drawer.
30

31
    This plotter arranges bits along y axis of 2D canvas with vertical offset.
32
    """
33

UNCOV
34
    def __init__(self, canvas: core.DrawerCanvas, axis: plt.Axes | None = None):
×
35
        """Create new plotter.
36

37
        Args:
38
            canvas: Configured drawer canvas object. Canvas object should be updated
39
                with `.update` method before initializing the plotter.
40
            axis: Matplotlib axis object. When `axis` is provided, the plotter updates
41
                given axis instead of creating and returning new matplotlib figure.
42
        """
UNCOV
43
        super().__init__(canvas=canvas)
×
44

UNCOV
45
        if axis is None:
×
46
            fig_height = self.canvas.vmax - self.canvas.vmin
×
UNCOV
47
            fig_h = self.canvas.formatter["general.fig_unit_height"] * fig_height
×
48
            fig_w = self.canvas.formatter["general.fig_width"]
×
49

50
            self.figure = plt.figure(figsize=(fig_w, fig_h))
×
51
            self.ax = self.figure.add_subplot(1, 1, 1)
×
52
        else:
53
            self.figure = axis.figure
×
54
            self.ax = axis
×
55

56
        self.initialize_canvas()
×
57

UNCOV
58
    def initialize_canvas(self):
×
59
        """Format appearance of matplotlib canvas."""
UNCOV
60
        self.ax.set_facecolor(self.canvas.formatter["color.background"])
×
61

62
        # axis lines
63
        self.ax.spines["right"].set_color("none")
×
UNCOV
64
        self.ax.spines["left"].set_color("none")
×
UNCOV
65
        self.ax.spines["top"].set_color("none")
×
66

67
        # axis labels
68
        self.ax.set_yticks([])
×
UNCOV
69
        axis_config = self.canvas.layout["time_axis_map"](time_window=self.canvas.time_range)
×
70

71
        self.ax.set_xticks(list(axis_config.axis_map.keys()))
×
72
        self.ax.set_xticklabels(
×
73
            list(axis_config.axis_map.values()),
74
            fontsize=self.canvas.formatter["text_size.axis_label"],
75
        )
UNCOV
76
        self.ax.set_xlabel(
×
77
            axis_config.label, fontsize=self.canvas.formatter["text_size.axis_label"]
78
        )
79

80
        # boundary
UNCOV
81
        self.ax.set_xlim(*self.canvas.time_range)
×
UNCOV
82
        self.ax.set_ylim(self.canvas.vmin, self.canvas.vmax)
×
83

84
    def draw(self):
×
85
        """Output drawings stored in canvas object."""
86

87
        for _, data in self.canvas.collections:
×
UNCOV
88
            xvals = np.asarray(data.xvals, dtype=float)
×
UNCOV
89
            yvals = np.asarray(data.yvals, dtype=float)
×
90
            offsets = [self.canvas.assigned_coordinates[bit] for bit in data.bits]
×
91

92
            if isinstance(data, drawings.BoxData):
×
93
                # box data
UNCOV
94
                if data.data_type in [
×
95
                    str(types.BoxType.SCHED_GATE.value),
96
                    str(types.BoxType.DELAY.value),
97
                ]:
98
                    # draw a smoothly rounded rectangle
UNCOV
99
                    xs, ys1, ys2 = self._time_bucket_outline(xvals, yvals)
×
UNCOV
100
                    self.ax.fill_between(
×
101
                        x=xs, y1=ys1 + offsets[0], y2=ys2 + offsets[0], **data.styles
102
                    )
103

104
                else:
105
                    # draw a rectangle
UNCOV
106
                    x0, x1 = xvals
×
UNCOV
107
                    y0, y1 = yvals + offsets[0]
×
108

109
                    rect = Rectangle(xy=(x0, y0), width=x1 - x0, height=y1 - y0)
×
110
                    pc = PatchCollection([rect], **data.styles)
×
UNCOV
111
                    self.ax.add_collection(pc)
×
112

113
            elif isinstance(data, drawings.LineData):
×
114
                # line data
UNCOV
115
                self.ax.plot(xvals, yvals + offsets[0], **data.styles)
×
116

UNCOV
117
            elif isinstance(data, drawings.TextData):
×
118
                # text data
UNCOV
119
                if data.latex is not None:
×
120
                    s = rf"${data.latex}$"
×
121
                else:
122
                    s = data.text
×
123

UNCOV
124
                self.ax.text(x=xvals[0], y=yvals[0] + offsets[0], s=s, **data.styles)
×
125

UNCOV
126
            elif isinstance(data, drawings.GateLinkData):
×
127
                # gate link data
UNCOV
128
                self.ax.plot(xvals.repeat(len(offsets)), offsets, **data.styles)
×
129

130
            else:
131
                raise VisualizationError(
×
132
                    f"Data {data} is not supported by {self.__class__.__name__}"
133
                )
134

UNCOV
135
    def _time_bucket_outline(
×
136
        self, xvals: np.ndarray, yvals: np.ndarray
137
    ) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
138
        """Generate outline of time bucket. Edges are smoothly faded.
139

140
        Args:
141
            xvals: Left and right point coordinates.
142
            yvals: Bottom and top point coordinates.
143

144
        Returns:
145
            Coordinate vectors of time bucket fringe.
146
        """
UNCOV
147
        x0, x1 = xvals
×
UNCOV
148
        y0, y1 = yvals
×
149

150
        width = x1 - x0
×
151
        y_mid = 0.5 * (y0 + y1)
×
152

153
        risefall = int(min(self.canvas.formatter["time_bucket.edge_dt"], max(width / 2 - 2, 0)))
×
154
        edge = np.sin(np.pi / 2 * np.arange(0, risefall) / risefall)
×
155

156
        xs = np.concatenate(
×
157
            [
158
                np.arange(x0, x0 + risefall),
159
                [x0 + risefall, x1 - risefall],
160
                np.arange(x1 - risefall + 1, x1 + 1),
161
            ]
162
        )
163

UNCOV
164
        l1 = (y1 - y_mid) * np.concatenate([edge, [1, 1], edge[::-1]])
×
UNCOV
165
        l2 = (y0 - y_mid) * np.concatenate([edge, [1, 1], edge[::-1]])
×
166

167
        return xs, l1, l2
×
168

UNCOV
169
    def save_file(self, filename: str):
×
170
        """Save image to file.
171
        Args:
172
            filename: File path to output image data.
173
        """
UNCOV
174
        plt.savefig(filename, bbox_inches="tight", dpi=self.canvas.formatter["general.dpi"])
×
175

UNCOV
176
    def get_image(self, interactive: bool = False) -> matplotlib.pyplot.Figure:
×
177
        """Get image data to return.
178
        Args:
179
            interactive: When set `True` show the circuit in a new window.
180
                This depends on the matplotlib backend being used supporting this.
181
        Returns:
182
            Matplotlib figure data.
183
        """
UNCOV
184
        matplotlib_close_if_inline(self.figure)
×
185

UNCOV
186
        if self.figure and interactive:
×
187
            self.figure.show()
×
UNCOV
188
        try:
×
189
            self.figure.tight_layout()
×
190
        except AttributeError:
×
191
            pass
×
192
        return self.figure
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc