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

Qiskit / qiskit / 14034596400

24 Mar 2025 11:24AM UTC coverage: 88.076% (+0.008%) from 88.068%
14034596400

push

github

web-flow
Fixes to various graphs in the docs (#14055)

* Fixes to various graphs in the docs

* Fix a bug caused by `tight_layout` crashing on some images

* Apply the fix to the timeline plotter

* Remove release note and fix bloch sphere visualization

* Additional bloch fix

* Slighly relax image compairson for bloch sphere due to small discrepancies between the server and local versions.

6 of 22 new or added lines in 4 files covered. (27.27%)

4 existing lines in 3 files now uncovered.

72629 of 82462 relevant lines covered (88.08%)

371867.75 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 http://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
# pylint: disable=invalid-name
14

15
"""Matplotlib plotter API."""
16

17
from typing import Optional, Tuple
×
18

19
import matplotlib
×
20
import matplotlib.pyplot as plt
×
21
import numpy as np
×
22
from matplotlib.collections import PatchCollection
×
23
from matplotlib.patches import Rectangle
×
24

25
from qiskit.visualization.exceptions import VisualizationError
×
26
from qiskit.visualization.timeline import core, types, drawings
×
27
from qiskit.visualization.timeline.plotters.base_plotter import BasePlotter
×
28
from qiskit.visualization.utils import matplotlib_close_if_inline
×
29

30

31
class MplPlotter(BasePlotter):
×
32
    """Matplotlib API for pulse drawer.
33

34
    This plotter arranges bits along y axis of 2D canvas with vertical offset.
35
    """
36

37
    def __init__(self, canvas: core.DrawerCanvas, axis: Optional[plt.Axes] = None):
×
38
        """Create new plotter.
39

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

48
        if axis is None:
×
49
            fig_height = self.canvas.vmax - self.canvas.vmin
×
50
            fig_h = self.canvas.formatter["general.fig_unit_height"] * fig_height
×
51
            fig_w = self.canvas.formatter["general.fig_width"]
×
52

53
            self.figure = plt.figure(figsize=(fig_w, fig_h))
×
54
            self.ax = self.figure.add_subplot(1, 1, 1)
×
55
        else:
56
            self.figure = axis.figure
×
57
            self.ax = axis
×
58

59
        self.initialize_canvas()
×
60

61
    def initialize_canvas(self):
×
62
        """Format appearance of matplotlib canvas."""
63
        self.ax.set_facecolor(self.canvas.formatter["color.background"])
×
64

65
        # axis lines
66
        self.ax.spines["right"].set_color("none")
×
67
        self.ax.spines["left"].set_color("none")
×
68
        self.ax.spines["top"].set_color("none")
×
69

70
        # axis labels
71
        self.ax.set_yticks([])
×
72
        axis_config = self.canvas.layout["time_axis_map"](time_window=self.canvas.time_range)
×
73

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

83
        # boundary
84
        self.ax.set_xlim(*self.canvas.time_range)
×
85
        self.ax.set_ylim(self.canvas.vmin, self.canvas.vmax)
×
86

87
    def draw(self):
×
88
        """Output drawings stored in canvas object."""
89

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

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

107
                else:
108
                    # draw a rectangle
109
                    x0, x1 = xvals
×
110
                    y0, y1 = yvals + offsets[0]
×
111

112
                    rect = Rectangle(xy=(x0, y0), width=x1 - x0, height=y1 - y0)
×
113
                    pc = PatchCollection([rect], **data.styles)
×
114
                    self.ax.add_collection(pc)
×
115

116
            elif isinstance(data, drawings.LineData):
×
117
                # line data
118
                self.ax.plot(xvals, yvals + offsets[0], **data.styles)
×
119

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

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

129
            elif isinstance(data, drawings.GateLinkData):
×
130
                # gate link data
131
                self.ax.plot(xvals.repeat(len(offsets)), offsets, **data.styles)
×
132

133
            else:
134
                raise VisualizationError(
×
135
                    f"Data {data} is not supported by {self.__class__.__name__}"
136
                )
137

138
    def _time_bucket_outline(
×
139
        self, xvals: np.ndarray, yvals: np.ndarray
140
    ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
141
        """Generate outline of time bucket. Edges are smoothly faded.
142

143
        Args:
144
            xvals: Left and right point coordinates.
145
            yvals: Bottom and top point coordinates.
146

147
        Returns:
148
            Coordinate vectors of time bucket fringe.
149
        """
150
        x0, x1 = xvals
×
151
        y0, y1 = yvals
×
152

153
        width = x1 - x0
×
154
        y_mid = 0.5 * (y0 + y1)
×
155

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

159
        xs = np.concatenate(
×
160
            [
161
                np.arange(x0, x0 + risefall),
162
                [x0 + risefall, x1 - risefall],
163
                np.arange(x1 - risefall + 1, x1 + 1),
164
            ]
165
        )
166

167
        l1 = (y1 - y_mid) * np.concatenate([edge, [1, 1], edge[::-1]])
×
168
        l2 = (y0 - y_mid) * np.concatenate([edge, [1, 1], edge[::-1]])
×
169

170
        return xs, l1, l2
×
171

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

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

189
        if self.figure and interactive:
×
190
            self.figure.show()
×
NEW
191
        try:
×
NEW
192
            self.figure.tight_layout()
×
NEW
193
        except AttributeError:
×
NEW
194
            pass
×
UNCOV
195
        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