diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py index e79b2c59ec12..81f4b99a379a 100644 --- a/qiskit/circuit/quantumcircuit.py +++ b/qiskit/circuit/quantumcircuit.py @@ -560,8 +560,8 @@ def qasm(self): def draw(self, scale=0.7, filename=None, style=None, output=None, interactive=False, line_length=None, plot_barriers=True, - reverse_bits=False, justify=None, vertical_compression='medium', idle_wires=True, - with_layout=True): + reverse_bits=False, justify=None, idle_wires=True, vertical_compression='medium', + with_layout=True, fold=None): """Draw the quantum circuit Using the output parameter you can specify the format. The choices are: @@ -604,6 +604,12 @@ def draw(self, scale=0.7, filename=None, style=None, output=None, idle_wires (bool): Include idle wires. Default is True. with_layout (bool): Include layout information, with labels on the physical layout. Default is True. + fold (int): Sets pagination. It can be disabled using -1. + In `text`, sets the length of the lines. This useful when the + drawing does not fit in the console. If None (default), it will try to + guess the console width using `shutil.get_terminal_size()`. However, if + running in jupyter, the default line length is set to 80 characters. + In `mpl` is the amount of operations before folding. Default is 25. Returns: PIL.Image or matplotlib.figure or str or TextDrawing: * PIL.Image: (output `latex`) an in-memory representation of the @@ -629,7 +635,7 @@ def draw(self, scale=0.7, filename=None, style=None, output=None, justify=justify, vertical_compression=vertical_compression, idle_wires=idle_wires, - with_layout=with_layout) + with_layout=with_layout, fold=fold) def size(self): """Returns total number of gate operations in circuit. diff --git a/qiskit/visualization/circuit_visualization.py b/qiskit/visualization/circuit_visualization.py index d0e320622446..9e671535ad2e 100644 --- a/qiskit/visualization/circuit_visualization.py +++ b/qiskit/visualization/circuit_visualization.py @@ -12,8 +12,6 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -# TODO: Remove after 0.7 and the deprecated methods are removed - """ Two quantum circuit drawers based on: @@ -27,6 +25,7 @@ import os import subprocess import tempfile +from warnings import warn try: from PIL import Image @@ -56,7 +55,8 @@ def circuit_drawer(circuit, justify=None, vertical_compression='medium', idle_wires=True, - with_layout=True): + with_layout=True, + fold=None): """Draw a quantum circuit to different formats (set by output parameter): 0. text: ASCII art TextDrawing that can be printed in the console. 1. latex: high-quality images, but heavy external software dependencies @@ -81,12 +81,7 @@ def circuit_drawer(circuit, supporting this). Note when used with either the `text` or the `latex_source` output type this has no effect and will be silently ignored. - line_length (int): Sets the length of the lines generated by `text` - output type. This useful when the drawing does not fit in the - console. If None (default), it will try to guess the console width - using shutil.get_terminal_size(). However, if you're running in - jupyter the default line length is set to 80 characters. If you - don't want pagination at all, set `line_length=-1`. + line_length (int): Deprecated. See `fold`. reverse_bits (bool): When set to True reverse the bit order inside registers for the output visualization. plot_barriers (bool): Enable/disable drawing barriers in the output @@ -102,6 +97,12 @@ def circuit_drawer(circuit, idle_wires (bool): Include idle wires. Default is True. with_layout (bool): Include layout information, with labels on the physical layout. + fold (int): Sets pagination. It can be disabled using -1. + In `text`, sets the length of the lines. This useful when the + drawing does not fit in the console. If None (default), it will try to + guess the console width using `shutil.get_terminal_size()`. However, if + running in jupyter, the default line length is set to 80 characters. + In `mpl` is the amount of operations before folding. Default is 25. Returns: PIL.Image: (output `latex`) an in-memory representation of the image of the circuit diagram. @@ -229,7 +230,8 @@ def circuit_drawer(circuit, justify=justify, vertical_compression=vertical_compression, idle_wires=idle_wires, - with_layout=with_layout) + with_layout=with_layout, + fold=fold) elif output == 'latex': image = _latex_circuit_drawer(circuit, scale=scale, filename=filename, style=style, @@ -254,7 +256,8 @@ def circuit_drawer(circuit, reverse_bits=reverse_bits, justify=justify, idle_wires=idle_wires, - with_layout=with_layout) + with_layout=with_layout, + fold=fold) else: raise exceptions.VisualizationError( 'Invalid output type %s selected. The only valid choices ' @@ -342,17 +345,13 @@ def qx_color_scheme(): def _text_circuit_drawer(circuit, filename=None, line_length=None, reverse_bits=False, plot_barriers=True, justify=None, vertical_compression='high', - idle_wires=True, with_layout=True): + idle_wires=True, with_layout=True, fold=None,): """ Draws a circuit using ascii art. Args: circuit (QuantumCircuit): Input circuit filename (str): optional filename to write the result - line_length (int): Optional. Breaks the circuit drawing to this length. This - useful when the drawing does not fit in the console. If - None (default), it will try to guess the console width using - shutil.get_terminal_size(). If you don't want pagination - at all, set line_length=-1. + line_length (int): Deprecated. See `fold`. reverse_bits (bool): Rearrange the bits in reverse order. plot_barriers (bool): Draws the barriers when they are there. justify (str) : `left`, `right` or `none`. Defaults to `left`. Says how @@ -362,6 +361,11 @@ def _text_circuit_drawer(circuit, filename=None, line_length=None, reverse_bits= idle_wires (bool): Include idle wires. Default is True. with_layout (bool): Include layout information, with labels on the physical layout. Default: True + fold (int): Optional. Breaks the circuit drawing to this length. This + useful when the drawing does not fit in the console. If + None (default), it will try to guess the console width using + `shutil.get_terminal_size()`. If you don't want pagination + at all, set `fold=-1`. Returns: TextDrawing: An instances that, when printed, draws the circuit in ascii art. """ @@ -373,9 +377,12 @@ def _text_circuit_drawer(circuit, filename=None, line_length=None, reverse_bits= layout = circuit._layout else: layout = None + if line_length: + warn('The parameter "line_length" is being replaced by "fold"', DeprecationWarning, 3) + fold = line_length text_drawing = _text.TextDrawing(qregs, cregs, ops, layout=layout) text_drawing.plotbarriers = plot_barriers - text_drawing.line_length = line_length + text_drawing.line_length = fold text_drawing.vertical_compression = vertical_compression if filename: @@ -530,7 +537,8 @@ def _matplotlib_circuit_drawer(circuit, reverse_bits=False, justify=None, idle_wires=True, - with_layout=True): + with_layout=True, + fold=None): """Draw a quantum circuit based on matplotlib. If `%matplotlib inline` is invoked in a Jupyter notebook, it visualizes a circuit inline. We recommend `%config InlineBackend.figure_format = 'svg'` for the inline visualization. @@ -544,11 +552,12 @@ def _matplotlib_circuit_drawer(circuit, registers for the output visualization. plot_barriers (bool): Enable/disable drawing barriers in the output circuit. Defaults to True. - justify (str) : `left`, `right` or `none`. Defaults to `left`. Says how + justify (str): `left`, `right` or `none`. Defaults to `left`. Says how the circuit should be justified. idle_wires (bool): Include idle wires. Default is True. with_layout (bool): Include layout information, with labels on the physical layout. Default: True. + fold (int): amount ops allowed before folding. Default is 25. Returns: matplotlib.figure: a matplotlib figure object for the circuit diagram """ @@ -562,7 +571,10 @@ def _matplotlib_circuit_drawer(circuit, else: layout = None + if fold is None: + fold = 25 + qcd = _matplotlib.MatplotlibDrawer(qregs, cregs, ops, scale=scale, style=style, plot_barriers=plot_barriers, - reverse_bits=reverse_bits, layout=layout) + reverse_bits=reverse_bits, layout=layout, fold=fold) return qcd.draw(filename) diff --git a/qiskit/visualization/matplotlib.py b/qiskit/visualization/matplotlib.py index 9a59a8213a5e..70acf678fe05 100644 --- a/qiskit/visualization/matplotlib.py +++ b/qiskit/visualization/matplotlib.py @@ -103,7 +103,7 @@ def get_index(self): class MatplotlibDrawer: def __init__(self, qregs, cregs, ops, scale=1.0, style=None, plot_barriers=True, - reverse_bits=False, layout=None): + reverse_bits=False, layout=None, fold=25): if not HAS_MATPLOTLIB: raise ImportError('The class MatplotlibDrawer needs matplotlib. ' @@ -146,6 +146,10 @@ def __init__(self, qregs, cregs, ops, dic = json.load(infile) self._style.set_style(dic) + self.fold = self._style.fold or fold # self._style.fold should be removed after 0.10 + if self.fold < 2: + self.fold = -1 + self.figure = plt.figure() self.figure.patch.set_facecolor(color=self._style.bg) self.ax = self.figure.add_subplot(111) @@ -457,8 +461,8 @@ def _barrier(self, config, anc): y_reg.append(qreg['y']) x0 = xys[0][0] - box_y0 = min(y_reg) - int(anc / self._style.fold) * (self._cond['n_lines'] + 1) - 0.5 - box_y1 = max(y_reg) - int(anc / self._style.fold) * (self._cond['n_lines'] + 1) + 0.5 + box_y0 = min(y_reg) - int(anc / self.fold) * (self._cond['n_lines'] + 1) - 0.5 + box_y1 = max(y_reg) - int(anc / self.fold) * (self._cond['n_lines'] + 1) + 0.5 box = patches.Rectangle(xy=(x0 - 0.3 * WID, box_y0), width=0.6 * WID, height=box_y1 - box_y0, fc=self._style.bc, ec=None, alpha=0.6, @@ -616,7 +620,7 @@ def _draw_regs_sub(self, n_fold, feedline_l=False, feedline_r=False): # lf line if feedline_r: - self._linefeed_mark((self._style.fold + 1 - 0.1, + self._linefeed_mark((self.fold + 1 - 0.1, - n_fold * (self._cond['n_lines'] + 1))) if feedline_l: self._linefeed_mark((0.1, @@ -633,12 +637,12 @@ def _draw_ops(self, verbose=False): for key, qreg in self._qreg_dict.items(): q_anchors[key] = Anchor(reg_num=self._cond['n_lines'], yind=qreg['y'], - fold=self._style.fold) + fold=self.fold) c_anchors = {} for key, creg in self._creg_dict.items(): c_anchors[key] = Anchor(reg_num=self._cond['n_lines'], yind=creg['y'], - fold=self._style.fold) + fold=self.fold) # # draw gates # @@ -947,10 +951,10 @@ def _draw_ops(self, verbose=False): max_anc = max(anchors) else: max_anc = 0 - n_fold = max(0, max_anc - 1) // self._style.fold + n_fold = max(0, max_anc - 1) // self.fold # window size - if max_anc > self._style.fold > 0: - self._cond['xmax'] = self._style.fold + 1 + self.x_offset + if max_anc > self.fold > 0: + self._cond['xmax'] = self.fold + 1 + self.x_offset self._cond['ymax'] = (n_fold + 1) * (self._cond['n_lines'] + 1) - 1 else: self._cond['xmax'] = max_anc + 1 + self.x_offset @@ -963,9 +967,9 @@ def _draw_ops(self, verbose=False): # draw gate number if self._style.index: for ii in range(max_anc): - if self._style.fold > 0: - x_coord = ii % self._style.fold + 1 - y_coord = - (ii // self._style.fold) * (self._cond['n_lines'] + 1) + 0.7 + if self.fold > 0: + x_coord = ii % self.fold + 1 + y_coord = - (ii // self.fold) * (self._cond['n_lines'] + 1) + 0.7 else: x_coord = ii + 1 y_coord = 0.7 diff --git a/qiskit/visualization/qcstyle.py b/qiskit/visualization/qcstyle.py index f5beafdde21b..34b712b8a7a3 100644 --- a/qiskit/visualization/qcstyle.py +++ b/qiskit/visualization/qcstyle.py @@ -90,7 +90,7 @@ def __init__(self): 'meas': non_gate_color } self.latexmode = False - self.fold = 25 + self.fold = None # To be removed after 0.10 is released self.bundle = True self.index = False self.figwidth = -1 @@ -113,18 +113,22 @@ def set_style(self, style_dic): self.disptex = dic.pop('displaytext', self.disptex) self.dispcol = dic.pop('displaycolor', self.dispcol) self.latexmode = dic.pop('latexdrawerstyle', self.latexmode) - self.fold = dic.pop('fold', self.fold) - if self.fold < 2: - self.fold = -1 self.bundle = dic.pop('cregbundle', self.bundle) self.index = dic.pop('showindex', self.index) self.figwidth = dic.pop('figwidth', self.figwidth) self.dpi = dic.pop('dpi', self.dpi) self.margin = dic.pop('margin', self.margin) self.cline = dic.pop('creglinestyle', self.cline) + if 'fold' in dic: + warn('The key "fold" in the argument "style" is being replaced by the argument "fold"', + DeprecationWarning, 5) + self.fold = dic.pop('fold', self.fold) + if self.fold < 2: + self.fold = -1 + if dic: - warn('style option/s ({}) is/are not ' - 'supported'.format(', '.join(dic.keys())), DeprecationWarning, 2) + warn('style option/s ({}) is/are not supported'.format(', '.join(dic.keys())), + DeprecationWarning, 2) class BWStyle: @@ -213,15 +217,19 @@ def set_style(self, style_dic): self.dispcol[key] = self.gc self.dispcol = dic.pop('displaycolor', self.dispcol) self.latexmode = dic.pop('latexdrawerstyle', self.latexmode) - self.fold = dic.pop('fold', self.fold) - if self.fold < 2: - self.fold = -1 self.bundle = dic.pop('cregbundle', self.bundle) self.index = dic.pop('showindex', self.index) self.figwidth = dic.pop('figwidth', self.figwidth) self.dpi = dic.pop('dpi', self.dpi) self.margin = dic.pop('margin', self.margin) self.cline = dic.pop('creglinestyle', self.cline) + if 'fold' in dic: + warn('The key "fold" in the argument "style" is being replaced by the argument "fold"', + DeprecationWarning, 5) + self.fold = dic.pop('fold', self.fold) + if self.fold < 2: + self.fold = -1 + if dic: - warn('style option/s ({}) is/are not ' - 'supported'.format(', '.join(dic.keys())), DeprecationWarning, 2) + warn('style option/s ({}) is/are not supported'.format(', '.join(dic.keys())), + DeprecationWarning, 2)