diff --git a/MANIFEST.in b/MANIFEST.in index 07c56801a3a2..47fe2fa2830a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,6 +4,7 @@ include qiskit/schemas/*.json include qiskit/VERSION.txt include qiskit/transpiler/passes/routing/cython/stochastic_swap/*.pyx include qiskit/transpiler/passes/routing/cython/stochastic_swap/*.pxd +include qiskit/visualization/styles/*.json recursive-include qiskit/test/mock/backends *.json # Include the tests files. diff --git a/postBuild b/postBuild index ddc9f0449702..15e7fe0a1827 100644 --- a/postBuild +++ b/postBuild @@ -8,6 +8,7 @@ # - pillow: for image comparison # - appmode: jupyter extension for executing the notebook pip install matplotlib pylatexenc pillow appmode +pip install . # Activation of appmode extension jupyter nbextension enable --py --sys-prefix appmode diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py index ae43316052a3..eafe5e26fe6b 100644 --- a/qiskit/circuit/quantumcircuit.py +++ b/qiskit/circuit/quantumcircuit.py @@ -1128,172 +1128,223 @@ def draw(self, output=None, scale=None, filename=None, style=None, interactive=False, plot_barriers=True, reverse_bits=False, justify=None, vertical_compression='medium', idle_wires=True, with_layout=True, fold=None, ax=None, initial_state=False, cregbundle=True): - """Draw the quantum circuit. + """Draw the quantum circuit. Use the output parameter to choose the drawing format: **text**: ASCII art TextDrawing that can be printed in the console. - **latex**: high-quality images compiled via LaTeX. + **matplotlib**: images with color rendered purely in Python. - **latex_source**: raw uncompiled LaTeX output. + **latex**: high-quality images compiled via latex. - **matplotlib**: images with color rendered purely in Python. + **latex_source**: raw uncompiled latex output. Args: - output (str): Select the output method to use for drawing the - circuit. Valid choices are ``text``, ``latex``, - ``latex_source``, or ``mpl``. By default the `'text`' drawer is - used unless a user config file has an alternative backend set - as the default. If the output kwarg is set, that backend - will always be used over the default in a user config file. - scale (float): scale of image to draw (shrink if < 1) - filename (str): file path to save image to - style (dict or str): dictionary of style or file name of style - file. This option is only used by the ``mpl`` output type. If a - str is passed in that is the path to a json file which contains - a dictionary of style, then that will be opened, parsed, and used - as the input dict. See: :ref:`Style Dict Doc ` for more + output (str): select the output method to use for drawing the circuit. + Valid choices are ``text``, ``mpl``, ``latex``, ``latex_source``. + By default the `text` drawer is used unless the user config file + (usually ``~/.qiskit/settings.conf``) has an alternative backend set + as the default. For example, ``circuit_drawer = latex``. If the output + kwarg is set, that backend will always be used over the default in + the user config file. + scale (float): scale of image to draw (shrink if < 1.0). Only used by + the `mpl`, `latex` and `latex_source` outputs. Defaults to 1.0. + filename (str): file path to save image to. Defaults to None. + style (dict or str): dictionary of style or file name of style json file. + This option is only used by the `mpl` output type. If a str, it + is used as the path to a json file which contains a style dict. + The file will be opened, parsed, and then any style elements in the + dict will replace the default values in the input dict. A file to + be loaded must end in ``.json``, but the name entered here can omit + ``.json``. For example, ``style='iqx.json'`` or ``style='iqx'``. + If `style` is a dict and the ``'name'`` key is set, that name + will be used to load a json file, followed by loading the other + items in the style dict. For example, ``style={'name': 'iqx'}``. + If `style` is not a str and `name` is not a key in the style dict, + then the default value from the user config file (usually + ``~/.qiskit/settings.conf``) will be used, for example, + ``circuit_mpl_style = iqx``. + If none of these are set, the `default` style will be used. + The search path for style json files can be specified in the user + config, for example, + ``circuit_mpl_style_path = /home/user/styles:/home/user``. + See: :ref:`Style Dict Doc ` for more information on the contents. - interactive (bool): when set true show the circuit in a new window + interactive (bool): when set to true, show the circuit in a new window (for `mpl` this depends on the matplotlib backend being used supporting this). Note when used with either the `text` or the - `latex_source` output type this has no effect and will be - silently ignored. - 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 + `latex_source` output type this has no effect and will be silently + ignored. Defaults to False. + reverse_bits (bool): when set to True, reverse the bit order inside + registers for the output visualization. Defaults to False. + plot_barriers (bool): enable/disable drawing barriers in the output circuit. Defaults to True. - justify (string): Options are ``left``, ``right`` or - ``none``. If anything else is supplied it defaults to left - justified. It refers to where gates should be placed in the - output circuit if there is an option. ``none`` results in - each gate being placed in its own column. + justify (string): options are ``left``, ``right`` or ``none``. If + anything else is supplied, it defaults to left justified. It refers + to where gates should be placed in the output circuit if there is + an option. ``none`` results in each gate being placed in its own + column. vertical_compression (string): ``high``, ``medium`` or ``low``. It - merges the lines generated by the ``text`` output so the - drawing will take less vertical room. Default is ``medium``. - Only used by the ``text`` output, will be silently ignored - otherwise. - idle_wires (bool): Include idle wires (wires with no circuit - elements) in output visualization. Default is True. - with_layout (bool): Include layout information, with labels on the + merges the lines generated by the `text` output so the drawing + will take less vertical room. Default is ``medium``. Only used by + the `text` output, will be silently ignored otherwise. + idle_wires (bool): include idle wires (wires with no circuit elements) + in output visualization. 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 is 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 - number of (visual) layers before folding. Default is 25. - ax (matplotlib.axes.Axes): An optional Axes object to be used for - the visualization output. If none is specified, a new matplotlib - Figure will be created and used. Additionally, if specified, - there will be no returned Figure since it is redundant. This is - only used when the ``output`` kwarg is set to use the ``mpl`` - backend. It will be silently ignored with all other outputs. - initial_state (bool): Optional. Adds ``|0>`` in the beginning of the wire. - Only used by the ``text``, ``latex`` and ``latex_source`` outputs. - Default: ``False``. - cregbundle (bool): Optional. If set True bundle classical registers. Not used by - the ``matplotlib`` output. Default: ``True``. + fold (int): sets pagination. It can be disabled using -1. In `text`, + sets the length of the lines. This is 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`, it is the number of (visual) layers before folding. + Default is 25. + ax (matplotlib.axes.Axes): Only used by the `mpl` backend. An optional + Axes object to be used for the visualization output. If none is + specified, a new matplotlib Figure will be created and used. + Additionally, if specified there will be no returned Figure since + it is redundant. + initial_state (bool): optional. Adds ``|0>`` in the beginning of the wire. + Default is False. + cregbundle (bool): optional. If set True, bundle classical registers. + Default is True. Returns: - :class:`PIL.Image` or :class:`matplotlib.figure` or :class:`str` or - :class:`TextDrawing`: + :class:`TextDrawing` or :class:`matplotlib.figure` or :class:`PIL.Image` or + :class:`str`: - * `PIL.Image` (output='latex') - an in-memory representation of the image of the circuit - diagram. + * `TextDrawing` (output='text') + A drawing that can be printed as ascii art. * `matplotlib.figure.Figure` (output='mpl') - a matplotlib figure object for the circuit diagram. + A matplotlib figure object for the circuit diagram. + * `PIL.Image` (output='latex') + An in-memory representation of the image of the circuit diagram. * `str` (output='latex_source') The LaTeX source code for visualizing the circuit diagram. - * `TextDrawing` (output='text') - A drawing that can be printed as ASCII art. Raises: VisualizationError: when an invalid output method is selected - ImportError: when the output methods require non-installed - libraries + ImportError: when the output methods requires non-installed libraries. - .. _style-dict-circ-doc: + .. _style-dict-doc: **Style Dict Details** - The style dict kwarg contains numerous options that define the style of - the output circuit visualization. The style dict is only used by the - ``mpl`` output. The options available in the style dict are defined - below: + The style dict kwarg contains numerous options that define the style of the + output circuit visualization. The style dict is only used by the `mpl` + output. The options available in the style dict are defined below: Args: - name (str): The name of the style. The name can be set to 'iqx', - 'bw', or 'default'. This overrides the setting in the - '~/.qiskit/settings.conf' file. - textcolor (str): The color code to use for text. Defaults to - `'#000000'` - subtextcolor (str): The color code to use for subtext. Defaults to - `'#000000'` - linecolor (str): The color code to use for lines. Defaults to - `'#000000'` - creglinecolor (str): The color code to use for classical register - lines. Defaults to `'#778899'` - gatetextcolor (str): The color code to use for gate text. Defaults - to `'#000000'` - gatefacecolor (str): The color code to use for gates. Defaults to - `'#ffffff'` - barrierfacecolor (str): The color code to use for barriers. - Defaults to `'#bdbdbd'` - backgroundcolor (str): The color code to use for the background. - Defaults to `'#ffffff'` - fontsize (int): The font size to use for text. Defaults to 13. - subfontsize (int): The font size to use for subtext. Defaults to 8. - displaytext (dict): A dictionary of the text to use for each - element type in the output visualization. The default values - are:: + name (str): the name of the style. The name can be set to ``iqx``, + ``bw``, ``default``, or the name of a user-created json file. This + overrides the setting in the user config file (usually + ``~/.qiskit/settings.conf``). + textcolor (str): the color code to use for all text not inside a gate. + Defaults to ``#000000`` + subtextcolor (str): the color code to use for subtext. Defaults to + ``#000000`` + linecolor (str): the color code to use for lines. Defaults to + ``#000000`` + creglinecolor (str): the color code to use for classical register + lines. Defaults to ``#778899`` + gatetextcolor (str): the color code to use for gate text. Defaults to + ``#000000`` + gatefacecolor (str): the color code to use for a gate if no color + specified in the 'displaycolor' dict. Defaults to ``#BB8BFF`` + barrierfacecolor (str): the color code to use for barriers. Defaults to + ``#BDBDBD`` + backgroundcolor (str): the color code to use for the background. + Defaults to ``#FFFFFF`` + edgecolor (str): the color code to use for gate edges when using the + `bw` style. Defaults to ``#000000``. + fontsize (int): the font size to use for text. Defaults to 13. + subfontsize (int): the font size to use for subtext. Defaults to 8. + showindex (bool): if set to True, show the index numbers at the top. + Defaults to False. + figwidth (int): the maximum width (in inches) for the output figure. + If set to -1, the maximum displayable width will be used. + Defaults to -1. + dpi (int): the DPI to use for the output image. Defaults to 150. + margin (list): a list of margin values to adjust spacing around output + image. Takes a list of 4 ints: [x left, x right, y bottom, y top]. + Defaults to [2.0, 0.1, 0.1, 0.3]. + creglinestyle (str): The style of line to use for classical registers. + Choices are ``solid``, ``doublet``, or any valid matplotlib + `linestyle` kwarg value. Defaults to ``doublet``. + displaytext (dict): a dictionary of the text to use for certain element + types in the output visualization. These items allow the use of + LaTeX formatting for gate names. The 'displaytext' dict can contain + any number of elements from one to the entire dict above.The default + values are (`default.json`):: { - 'id': 'id', - 'u0': 'U_0', - 'u1': 'U_1', - 'u2': 'U_2', - 'u3': 'U_3', + 'u1': '$\\mathrm{U}_1$', + 'u2': '$\\mathrm{U}_2$', + 'u3': '$\\mathrm{U}_3$', + 'u': 'U', + 'p': 'P', + 'id': 'I', 'x': 'X', 'y': 'Y', 'z': 'Z', 'h': 'H', 's': 'S', - 'sdg': 'S^\\dagger', + 'sdg': '$\\mathrm{S}^\\dagger$', + 'sx': '$\\sqrt{\\mathrm{X}}$', + 'sxdg': '$\\sqrt{\\mathrm{X}}^\\dagger$', 't': 'T', - 'tdg': 'T^\\dagger', - 'rx': 'R_x', - 'ry': 'R_y', - 'rz': 'R_z', - 'reset': '\\left|0\\right\\rangle' + 'tdg': '$\\mathrm{T}^\\dagger$', + 'dcx': 'Dcx', + 'iswap': 'Iswap', + 'ms': 'MS', + 'r': 'R', + 'rx': '$\\mathrm{R}_\\mathrm{X}$', + 'ry': '$\\mathrm{R}_\\mathrm{Y}$', + 'rz': '$\\mathrm{R}_\\mathrm{Z}$', + 'rxx': '$\\mathrm{R}_{\\mathrm{XX}}$', + 'ryy': '$\\mathrm{R}_{\\mathrm{YY}}$', + 'rzx': '$\\mathrm{R}_{\\mathrm{ZX}}$', + 'rzz': '$\\mathrm{R}_{\\mathrm{ZZ}}$', + 'reset': '$\\left|0\\right\\rangle$', + 'initialize': '$|\\psi\\rangle$' } - You must specify all the necessary values if using this. There - is no provision for passing an incomplete dict in. - displaycolor (dict): The color codes to use for each circuit - element in the form (gate_color, text_color). - The default values are:: + displaycolor (dict): the color codes to use for each circuit element in + the form (gate_color, text_color). Colors can also be entered without + the text color, such as 'u1': '#FA74A6', in which case the text color + will always be `gatetextcolor`. The `displaycolor` dict can contain + any number of elements from one to the entire dict above. The default + values are (`default.json`):: { 'u1': ('#FA74A6', '#000000'), 'u2': ('#FA74A6', '#000000'), 'u3': ('#FA74A6', '#000000'), 'id': ('#05BAB6', '#000000'), + 'u': ('#BB8BFF', '#000000'), + 'p': ('#BB8BFF', '#000000'), 'x': ('#05BAB6', '#000000'), 'y': ('#05BAB6', '#000000'), 'z': ('#05BAB6', '#000000'), 'h': ('#6FA4FF', '#000000'), 'cx': ('#6FA4FF', '#000000'), + 'ccx': ('#BB8BFF', '#000000'), + 'mcx': ('#BB8BFF', '#000000'), + 'mcx_gray': ('#BB8BFF', '#000000), 'cy': ('#6FA4FF', '#000000'), 'cz': ('#6FA4FF', '#000000'), 'swap': ('#6FA4FF', '#000000'), - 's': ('#6FA4FF', '#000000'), - 'sdg': ('#6FA4FF', '#000000'), + 'cswap': ('#BB8BFF', '#000000'), + 'ccswap': ('#BB8BFF', '#000000'), 'dcx': ('#6FA4FF', '#000000'), + 'cdcx': ('#BB8BFF', '#000000'), + 'ccdcx': ('#BB8BFF', '#000000'), 'iswap': ('#6FA4FF', '#000000'), + 's': ('#6FA4FF', '#000000'), + 'sdg': ('#6FA4FF', '#000000'), 't': ('#BB8BFF', '#000000'), 'tdg': ('#BB8BFF', '#000000'), + 'sx': ('#BB8BFF', '#000000'), + 'sxdg': ('#BB8BFF', '#000000') 'r': ('#BB8BFF', '#000000'), 'rx': ('#BB8BFF', '#000000'), 'ry': ('#BB8BFF', '#000000'), @@ -1304,39 +1355,19 @@ def draw(self, output=None, scale=None, filename=None, style=None, 'reset': ('#000000', #FFFFFF'), 'target': ('#FFFFFF, '#FFFFFF'), 'measure': ('#000000', '#FFFFFF'), - 'ccx': ('#BB8BFF', '#000000'), - 'cdcx': ('#BB8BFF', '#000000'), - 'ccdcx': ('#BB8BFF', '#000000'), - 'cswap': ('#BB8BFF', '#000000'), - 'ccswap': ('#BB8BFF', '#000000'), - 'mcx': ('#BB8BFF', '#000000'), - 'mcx_gray': ('#BB8BFF', '#000000), - 'u': ('#BB8BFF', '#000000'), - 'p': ('#BB8BFF', '#000000'), - 'sx': ('#BB8BFF', '#000000'), - 'sxdg': ('#BB8BFF', '#000000') } - Colors can also be entered without the text color, such as - 'u1': '#FA74A6', in which case the text color will always - be 'gatetextcolor'. The 'displaycolor' dict can contain any - number of elements from one to the entire dict above. - latexdrawerstyle (bool): When set to True, enable LaTeX mode, which - will draw gates like the `latex` output modes. - usepiformat (bool): When set to True, use radians for output. - fold (int): The number of circuit elements to fold the circuit at. - Defaults to 20. - cregbundle (bool): If set True, bundle classical registers - showindex (bool): If set True, draw an index. - compress (bool): If set True, draw a compressed circuit. - figwidth (int): The maximum width (in inches) for the output figure. - dpi (int): The DPI to use for the output image. Defaults to 150. - margin (list): A list of margin values to adjust spacing around - output image. Takes a list of 4 ints: - [x left, x right, y bottom, y top]. - creglinestyle (str): The style of line to use for classical - registers. Choices are `'solid'`, `'doublet'`, or any valid - matplotlib `linestyle` kwarg value. Defaults to `doublet` + Example: + .. jupyter-execute:: + + from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit + from qiskit.tools.visualization import circuit_drawer + q = QuantumRegister(1) + c = ClassicalRegister(1) + qc = QuantumCircuit(q, c) + qc.h(q) + qc.measure(q, c) + qc.draw('mpl', style={'showindex': True}) """ # pylint: disable=cyclic-import diff --git a/qiskit/user_config.py b/qiskit/user_config.py index bd1bf6e2b404..e46a3762a8bc 100644 --- a/qiskit/user_config.py +++ b/qiskit/user_config.py @@ -14,6 +14,7 @@ import configparser import os +from warnings import warn from qiskit import exceptions @@ -29,6 +30,9 @@ class UserConfig: [default] circuit_drawer = mpl circuit_mpl_style = default + circuit_mpl_style_path = ~/.qiskit: + transpile_optimization_level = 1 + suppress_packaging_warnings = False """ def __init__(self, filename=None): @@ -36,7 +40,7 @@ def __init__(self, filename=None): Args: filename (str): The path to the user config file. If one isn't - specified ~/.qiskit/settings.conf is used. + specified, ~/.qiskit/settings.conf is used. """ if filename is None: self.filename = DEFAULT_FILENAME @@ -60,21 +64,35 @@ def read_config_file(self): 'latex_source', 'auto']: raise exceptions.QiskitUserConfigError( "%s is not a valid circuit drawer backend. Must be " - "either 'text', 'mpl', 'latex', 'auto', or " - "'latex_source'" + "either 'text', 'mpl', 'latex', 'latex_source', or " + "'auto'." % circuit_drawer) self.settings['circuit_drawer'] = circuit_drawer + # Parse circuit_mpl_style circuit_mpl_style = self.config_parser.get('default', 'circuit_mpl_style', fallback=None) if circuit_mpl_style: - if circuit_mpl_style not in ['default', 'iqx', 'bw']: - raise exceptions.QiskitUserConfigError( - "%s is not a valid mpl circuit style. Must be " - "either 'default', 'iqx', or bw'" - % circuit_mpl_style) + if not isinstance(circuit_mpl_style, str): + warn("%s is not a valid mpl circuit style. Must be " + "a text string. Will not load style." + % circuit_mpl_style, UserWarning, 2) self.settings['circuit_mpl_style'] = circuit_mpl_style + + # Parse circuit_mpl_style_path + circuit_mpl_style_path = self.config_parser.get('default', + 'circuit_mpl_style_path', + fallback=None) + if circuit_mpl_style_path: + cpath_list = circuit_mpl_style_path.split(':') + for path in cpath_list: + if not os.path.exists(os.path.expanduser(path)): + warn("%s is not a valid circuit mpl style path." + " Correct the path in ~/.qiskit/settings.conf." + % path, UserWarning, 2) + self.settings['circuit_mpl_style_path'] = cpath_list + # Parse transpile_optimization_level transpile_optimization_level = self.config_parser.getint( 'default', 'transpile_optimization_level', fallback=-1) @@ -86,6 +104,7 @@ def read_config_file(self): "0, 1, 2, or 3.") self.settings['transpile_optimization_level'] = ( transpile_optimization_level) + # Parse package warnings package_warnings = self.config_parser.getboolean( 'default', 'suppress_packaging_warnings', fallback=False) diff --git a/qiskit/visualization/__init__.py b/qiskit/visualization/__init__.py index 242932f37df2..a35dbb9f6152 100644 --- a/qiskit/visualization/__init__.py +++ b/qiskit/visualization/__init__.py @@ -113,7 +113,7 @@ plot_state_qsphere) from qiskit.visualization.transition_visualization import visualize_transition -from .circuit_visualization import circuit_drawer, qx_color_scheme +from .circuit_visualization import circuit_drawer from .dag_visualization import dag_drawer from .exceptions import VisualizationError from .gate_map import plot_gate_map, plot_circuit_layout, plot_error_map diff --git a/qiskit/visualization/circuit_visualization.py b/qiskit/visualization/circuit_visualization.py index c7207c2b2ee5..897308c24890 100644 --- a/qiskit/visualization/circuit_visualization.py +++ b/qiskit/visualization/circuit_visualization.py @@ -30,7 +30,6 @@ import os import subprocess import tempfile -from warnings import warn try: from PIL import Image @@ -64,85 +63,99 @@ def circuit_drawer(circuit, ax=None, initial_state=False, cregbundle=True): - """Draw a quantum circuit to different formats (set by output parameter): + """Draw the quantum circuit. Use the output parameter to choose the drawing format: **text**: ASCII art TextDrawing that can be printed in the console. + **matplotlib**: images with color rendered purely in Python. + **latex**: high-quality images compiled via latex. **latex_source**: raw uncompiled latex output. - **matplotlib**: images with color rendered purely in Python. - Args: circuit (QuantumCircuit): the quantum circuit to draw - scale (float): scale of image to draw (shrink if < 1). Only used by the ``mpl``, - ``latex``, and ``latex_source`` outputs. - filename (str): file path to save image to - style (dict or str): dictionary of style or file name of style file. - This option is only used by the ``mpl`` output type. If a str is - passed in that is the path to a json file which contains that will - be open, parsed, and then used just as the input dict. See: - :ref:`Style Dict Doc ` for more information on the - contents. - output (str): Select the output method to use for drawing the circuit. - Valid choices are ``text``, ``latex``, ``latex_source``, ``mpl``. - By default the `'text`' drawer is used unless a user config file - has an alternative backend set as the default. If the output kwarg - is set, that backend will always be used over the default in a user - config file. - interactive (bool): when set true show the circuit in a new window + scale (float): scale of image to draw (shrink if < 1.0). Only used by + the `mpl`, `latex` and `latex_source` outputs. Defaults to 1.0. + filename (str): file path to save image to. Defaults to None. + style (dict or str): dictionary of style or file name of style json file. + This option is only used by the `mpl` output type. If a str, it + is used as the path to a json file which contains a style dict. + The file will be opened, parsed, and then any style elements in the + dict will replace the default values in the input dict. A file to + be loaded must end in ``.json``, but the name entered here can omit + ``.json``. For example, ``style='iqx.json'`` or ``style='iqx'``. + If `style` is a dict and the ``'name'`` key is set, that name + will be used to load a json file, followed by loading the other + items in the style dict. For example, ``style={'name': 'iqx'}``. + If `style` is not a str and `name` is not a key in the style dict, + then the default value from the user config file (usually + ``~/.qiskit/settings.conf``) will be used, for example, + ``circuit_mpl_style = iqx``. + If none of these are set, the `default` style will be used. + The search path for style json files can be specified in the user + config, for example, + ``circuit_mpl_style_path = /home/user/styles:/home/user``. + See: :ref:`Style Dict Doc ` for more + information on the contents. + output (str): select the output method to use for drawing the circuit. + Valid choices are ``text``, ``mpl``, ``latex``, ``latex_source``. + By default the `text` drawer is used unless the user config file + (usually ``~/.qiskit/settings.conf``) has an alternative backend set + as the default. For example, ``circuit_drawer = latex``. If the output + kwarg is set, that backend will always be used over the default in + the user config file. + interactive (bool): when set to true, show the circuit in a new window (for `mpl` this depends on the matplotlib backend being used supporting this). Note when used with either the `text` or the `latex_source` output type this has no effect and will be silently - ignored. - 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 + ignored. Defaults to False. + reverse_bits (bool): when set to True, reverse the bit order inside + registers for the output visualization. Defaults to False. + plot_barriers (bool): enable/disable drawing barriers in the output circuit. Defaults to True. - justify (string): Options are ``left``, ``right`` or ``none``, if - anything else is supplied it defaults to left justified. It refers + justify (string): options are ``left``, ``right`` or ``none``. If + anything else is supplied, it defaults to left justified. It refers to where gates should be placed in the output circuit if there is an option. ``none`` results in each gate being placed in its own column. vertical_compression (string): ``high``, ``medium`` or ``low``. It - merges the lines generated by the ``text`` output so the drawing + merges the lines generated by the `text` output so the drawing will take less vertical room. Default is ``medium``. Only used by - the ``text`` output, will be silently ignored otherwise. - idle_wires (bool): Include idle wires (wires with no circuit elements) + the `text` output, will be silently ignored otherwise. + idle_wires (bool): include idle wires (wires with no circuit elements) in output visualization. Default is True. - with_layout (bool): Include layout information, with labels on the + 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`` it is the number of (visual) layers before - folding. Default is 25. - ax (matplotlib.axes.Axes): An optional Axes object to be used for - the visualization output. If none is specified a new matplotlib - Figure will be created and used. Additionally, if specified there - will be no returned Figure since it is redundant. This is only used - when the ``output`` kwarg is set to use the ``mpl`` backend. It - will be silently ignored with all other outputs. - initial_state (bool): Optional. Adds ``|0>`` in the beginning of the wire. - Default: ``False``. - cregbundle (bool): Optional. If set True bundle classical registers. - Default: ``True``. + fold (int): sets pagination. It can be disabled using -1. In `text`, + sets the length of the lines. This is 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`, it is the number of (visual) layers before folding. + Default is 25. + ax (matplotlib.axes.Axes): Only used by the `mpl` backend. An optional + Axes object to be used for the visualization output. If none is + specified, a new matplotlib Figure will be created and used. + Additionally, if specified there will be no returned Figure since + it is redundant. + initial_state (bool): optional. Adds ``|0>`` in the beginning of the wire. + Default is False. + cregbundle (bool): optional. If set True, bundle classical registers. + Default is True. Returns: - :class:`PIL.Image` or :class:`matplotlib.figure` or :class:`str` or - :class:`TextDrawing`: + :class:`TextDrawing` or :class:`matplotlib.figure` or :class:`PIL.Image` or + :class:`str`: - * `PIL.Image` (output='latex') - an in-memory representation of the image of the circuit diagram. + * `TextDrawing` (output='text') + A drawing that can be printed as ascii art. * `matplotlib.figure.Figure` (output='mpl') - a matplotlib figure object for the circuit diagram. + A matplotlib figure object for the circuit diagram. + * `PIL.Image` (output='latex') + An in-memory representation of the image of the circuit diagram. * `str` (output='latex_source') The LaTeX source code for visualizing the circuit diagram. - * `TextDrawing` (output='text') - A drawing that can be printed as ascii art Raises: VisualizationError: when an invalid output method is selected @@ -153,79 +166,121 @@ def circuit_drawer(circuit, **Style Dict Details** The style dict kwarg contains numerous options that define the style of the - output circuit visualization. The style dict is only used by the ``mpl`` + output circuit visualization. The style dict is only used by the `mpl` output. The options available in the style dict are defined below: Args: - name (str): The name of the style. The name can be set to 'iqx', - 'bw', or 'default'. This overrides the setting in the - '~/.qiskit/settings.conf' file. - textcolor (str): The color code to use for text. Defaults to - `'#000000'` - subtextcolor (str): The color code to use for subtext. Defaults to - `'#000000'` - linecolor (str): The color code to use for lines. Defaults to - `'#000000'` - creglinecolor (str): The color code to use for classical register - lines. Defaults to `'#778899'` - gatetextcolor (str): The color code to use for gate text. Defaults to - `'#000000'` - gatefacecolor (str): The color code to use for gates. Defaults to - `'#ffffff'` - barrierfacecolor (str): The color code to use for barriers. Defaults to - `'#bdbdbd'` - backgroundcolor (str): The color code to use for the background. - Defaults to `'#ffffff'` - fontsize (int): The font size to use for text. Defaults to 13 - subfontsize (int): The font size to use for subtext. Defaults to 8 - displaytext (dict): A dictionary of the text to use for each element - type in the output visualization. The default values are:: + name (str): the name of the style. The name can be set to ``iqx``, + ``bw``, ``default``, or the name of a user-created json file. This + overrides the setting in the user config file (usually + ``~/.qiskit/settings.conf``). + textcolor (str): the color code to use for all text not inside a gate. + Defaults to ``#000000`` + subtextcolor (str): the color code to use for subtext. Defaults to + ``#000000`` + linecolor (str): the color code to use for lines. Defaults to + ``#000000`` + creglinecolor (str): the color code to use for classical register + lines. Defaults to ``#778899`` + gatetextcolor (str): the color code to use for gate text. Defaults to + ``#000000`` + gatefacecolor (str): the color code to use for a gate if no color + specified in the 'displaycolor' dict. Defaults to ``#BB8BFF`` + barrierfacecolor (str): the color code to use for barriers. Defaults to + ``#BDBDBD`` + backgroundcolor (str): the color code to use for the background. + Defaults to ``#FFFFFF`` + edgecolor (str): the color code to use for gate edges when using the + `bw` style. Defaults to ``#000000``. + fontsize (int): the font size to use for text. Defaults to 13. + subfontsize (int): the font size to use for subtext. Defaults to 8. + showindex (bool): if set to True, show the index numbers at the top. + Defaults to False. + figwidth (int): the maximum width (in inches) for the output figure. + If set to -1, the maximum displayable width will be used. + Defaults to -1. + dpi (int): the DPI to use for the output image. Defaults to 150. + margin (list): a list of margin values to adjust spacing around output + image. Takes a list of 4 ints: [x left, x right, y bottom, y top]. + Defaults to [2.0, 0.1, 0.1, 0.3]. + creglinestyle (str): The style of line to use for classical registers. + Choices are ``solid``, ``doublet``, or any valid matplotlib + `linestyle` kwarg value. Defaults to ``doublet``. + displaytext (dict): a dictionary of the text to use for certain element + types in the output visualization. These items allow the use of + LaTeX formatting for gate names. The 'displaytext' dict can contain + any number of elements from one to the entire dict above.The default + values are (`default.json`):: { - 'id': 'id', - 'u0': 'U_0', - 'u1': 'U_1', - 'u2': 'U_2', - 'u3': 'U_3', + 'u1': '$\\mathrm{U}_1$', + 'u2': '$\\mathrm{U}_2$', + 'u3': '$\\mathrm{U}_3$', + 'u': 'U', + 'p': 'P', + 'id': 'I', 'x': 'X', 'y': 'Y', 'z': 'Z', 'h': 'H', 's': 'S', - 'sdg': 'S^\\dagger', + 'sdg': '$\\mathrm{S}^\\dagger$', + 'sx': '$\\sqrt{\\mathrm{X}}$', + 'sxdg': '$\\sqrt{\\mathrm{X}}^\\dagger$', 't': 'T', - 'tdg': 'T^\\dagger', - 'rx': 'R_x', - 'ry': 'R_y', - 'rz': 'R_z', - 'reset': '\\left|0\\right\\rangle' + 'tdg': '$\\mathrm{T}^\\dagger$', + 'dcx': 'Dcx', + 'iswap': 'Iswap', + 'ms': 'MS', + 'r': 'R', + 'rx': '$\\mathrm{R}_\\mathrm{X}$', + 'ry': '$\\mathrm{R}_\\mathrm{Y}$', + 'rz': '$\\mathrm{R}_\\mathrm{Z}$', + 'rxx': '$\\mathrm{R}_{\\mathrm{XX}}$', + 'ryy': '$\\mathrm{R}_{\\mathrm{YY}}$', + 'rzx': '$\\mathrm{R}_{\\mathrm{ZX}}$', + 'rzz': '$\\mathrm{R}_{\\mathrm{ZZ}}$', + 'reset': '$\\left|0\\right\\rangle$', + 'initialize': '$|\\psi\\rangle$' } - You must specify all the necessary values if using this. There is - no provision for passing an incomplete dict in. - displaycolor (dict): The color codes to use for each circuit - element in the form (gate_color, text_color). - The default values are:: + displaycolor (dict): the color codes to use for each circuit element in + the form (gate_color, text_color). Colors can also be entered without + the text color, such as 'u1': '#FA74A6', in which case the text color + will always be `gatetextcolor`. The `displaycolor` dict can contain + any number of elements from one to the entire dict above. The default + values are (`default.json`):: { 'u1': ('#FA74A6', '#000000'), 'u2': ('#FA74A6', '#000000'), 'u3': ('#FA74A6', '#000000'), 'id': ('#05BAB6', '#000000'), + 'u': ('#BB8BFF', '#000000'), + 'p': ('#BB8BFF', '#000000'), 'x': ('#05BAB6', '#000000'), 'y': ('#05BAB6', '#000000'), 'z': ('#05BAB6', '#000000'), 'h': ('#6FA4FF', '#000000'), 'cx': ('#6FA4FF', '#000000'), + 'ccx': ('#BB8BFF', '#000000'), + 'mcx': ('#BB8BFF', '#000000'), + 'mcx_gray': ('#BB8BFF', '#000000), 'cy': ('#6FA4FF', '#000000'), 'cz': ('#6FA4FF', '#000000'), 'swap': ('#6FA4FF', '#000000'), - 's': ('#6FA4FF', '#000000'), - 'sdg': ('#6FA4FF', '#000000'), + 'cswap': ('#BB8BFF', '#000000'), + 'ccswap': ('#BB8BFF', '#000000'), 'dcx': ('#6FA4FF', '#000000'), + 'cdcx': ('#BB8BFF', '#000000'), + 'ccdcx': ('#BB8BFF', '#000000'), 'iswap': ('#6FA4FF', '#000000'), + 's': ('#6FA4FF', '#000000'), + 'sdg': ('#6FA4FF', '#000000'), 't': ('#BB8BFF', '#000000'), 'tdg': ('#BB8BFF', '#000000'), + 'sx': ('#BB8BFF', '#000000'), + 'sxdg': ('#BB8BFF', '#000000') 'r': ('#BB8BFF', '#000000'), 'rx': ('#BB8BFF', '#000000'), 'ry': ('#BB8BFF', '#000000'), @@ -236,39 +291,8 @@ def circuit_drawer(circuit, 'reset': ('#000000', #FFFFFF'), 'target': ('#FFFFFF, '#FFFFFF'), 'measure': ('#000000', '#FFFFFF'), - 'ccx': ('#BB8BFF', '#000000'), - 'cdcx': ('#BB8BFF', '#000000'), - 'ccdcx': ('#BB8BFF', '#000000'), - 'cswap': ('#BB8BFF', '#000000'), - 'ccswap': ('#BB8BFF', '#000000'), - 'mcx': ('#BB8BFF', '#000000'), - 'mcx_gray': ('#BB8BFF', '#000000), - 'u': ('#BB8BFF', '#000000'), - 'p': ('#BB8BFF', '#000000'), - 'sx': ('#BB8BFF', '#000000'), - 'sxdg': ('#BB8BFF', '#000000') } - Colors can also be entered without the text color, such as - 'u1': '#FA74A6', in which case the text color will always - be 'gatetextcolor'. The 'displaycolor' dict can contain any - number of elements from one to the entire dict above. - latexdrawerstyle (bool): When set to True enable latex mode which will - draw gates like the `latex` output modes. - usepiformat (bool): When set to True use radians for output - fold (int): The number of circuit elements to fold the circuit at. - Defaults to 20 - cregbundle (bool): If set True bundle classical registers - showindex (bool): If set True draw an index. - compress (bool): If set True draw a compressed circuit - figwidth (int): The maximum width (in inches) for the output figure. - dpi (int): The DPI to use for the output image. Defaults to 150 - margin (list): A list of margin values to adjust spacing around output - image. Takes a list of 4 ints: [x left, x right, y bottom, y top]. - creglinestyle (str): The style of line to use for classical registers. - Choices are `'solid'`, `'doublet'`, or any valid matplotlib - `linestyle` kwarg value. Defaults to `doublet` - Example: .. jupyter-execute:: @@ -279,7 +303,7 @@ def circuit_drawer(circuit, qc = QuantumCircuit(q, c) qc.h(q) qc.measure(q, c) - circuit_drawer(qc) + circuit_drawer(qc, output='mpl', style={'showindex': True}) """ image = None config = user_config.get_config() @@ -307,8 +331,8 @@ def circuit_drawer(circuit, initial_state=initial_state, cregbundle=cregbundle) elif output == 'latex': - image = _latex_circuit_drawer(circuit, scale=scale, - filename=filename, style=style, + image = _latex_circuit_drawer(circuit, + filename=filename, scale=scale, plot_barriers=plot_barriers, reverse_bits=reverse_bits, justify=justify, @@ -319,7 +343,6 @@ def circuit_drawer(circuit, elif output == 'latex_source': return _generate_latex_source(circuit, filename=filename, scale=scale, - style=style, plot_barriers=plot_barriers, reverse_bits=reverse_bits, justify=justify, @@ -342,86 +365,12 @@ def circuit_drawer(circuit, else: raise exceptions.VisualizationError( 'Invalid output type %s selected. The only valid choices ' - 'are latex, latex_source, text, and mpl' % output) + 'are text, latex, latex_source, and mpl' % output) if image and interactive: image.show() return image -# ----------------------------------------------------------------------------- -# Plot style sheet option -# ----------------------------------------------------------------------------- -def qx_color_scheme(): - """Return default style for matplotlib_circuit_drawer (IBM QX style).""" - warn('The qx_color_scheme function is deprecated as of 0.11, and ' - 'will be removed no earlier than 3 months after that release ' - 'date.', DeprecationWarning, stacklevel=2) - return { - "comment": "Style file for matplotlib_circuit_drawer (IBM QX Composer style)", - "textcolor": "#000000", - "gatetextcolor": "#000000", - "subtextcolor": "#000000", - "linecolor": "#000000", - "creglinecolor": "#b9b9b9", - "gatefacecolor": "#ffffff", - "barrierfacecolor": "#bdbdbd", - "backgroundcolor": "#ffffff", - "fold": 20, - "fontsize": 13, - "subfontsize": 8, - "figwidth": -1, - "dpi": 150, - "displaytext": { - "id": "id", - "u0": "U_0", - "u1": "U_1", - "u2": "U_2", - "u3": "U_3", - "x": "X", - "y": "Y", - "z": "Z", - "h": "H", - "s": "S", - "sdg": "S^\\dagger", - "t": "T", - "tdg": "T^\\dagger", - "rx": "R_x", - "ry": "R_y", - "rz": "R_z", - "reset": "\\left|0\\right\\rangle" - }, - "displaycolor": { - "id": "#ffca64", - "u0": "#f69458", - "u1": "#f69458", - "u2": "#f69458", - "u3": "#f69458", - "x": "#a6ce38", - "y": "#a6ce38", - "z": "#a6ce38", - "h": "#00bff2", - "s": "#00bff2", - "sdg": "#00bff2", - "t": "#ff6666", - "tdg": "#ff6666", - "rx": "#ffca64", - "ry": "#ffca64", - "rz": "#ffca64", - "reset": "#d7ddda", - "target": "#00bff2", - "meas": "#f070aa" - }, - "latexdrawerstyle": True, - "usepiformat": False, - "cregbundle": False, - "showindex": False, - "compress": True, - "margin": [2.0, 0.0, 0.0, 0.3], - "creglinestyle": "solid", - "reversebits": False - } - - # ----------------------------------------------------------------------------- # _text_circuit_drawer # ----------------------------------------------------------------------------- @@ -435,27 +384,30 @@ def _text_circuit_drawer(circuit, filename=None, reverse_bits=False, Args: circuit (QuantumCircuit): Input circuit - filename (str): optional filename to write the result + filename (str): Optional filename to write the result 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 - the circuit should be justified. + the circuit should be justified. vertical_compression (string): `high`, `medium`, or `low`. It merges the lines so the drawing will take less vertical room. Default is `high`. idle_wires (bool): Include idle wires. Default is True. - with_layout (bool): Include layout information, with labels on the physical + 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`. - initial_state (bool): Optional. Adds |0> in the beginning of the line. Default: `True`. - cregbundle (bool): Optional. If set True bundle classical registers. Default: ``False``. + is 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`. + initial_state (bool): Optional. Adds |0> in the beginning of the line. + Default: `False`. + cregbundle (bool): Optional. If set True, bundle classical registers. + Default: ``True``. encoding (str): Optional. Sets the encoding preference of the output. - Default: ``sys.stdout.encoding``. + Default: ``sys.stdout.encoding``. + Returns: - TextDrawing: An instances that, when printed, draws the circuit in ascii art. + TextDrawing: An instance that, when printed, draws the circuit in ascii art. """ qregs, cregs, ops = utils._get_layered_instructions(circuit, reverse_bits=reverse_bits, @@ -486,7 +438,6 @@ def _text_circuit_drawer(circuit, filename=None, reverse_bits=False, def _latex_circuit_drawer(circuit, scale=0.7, filename=None, - style=None, plot_barriers=True, reverse_bits=False, justify=None, @@ -502,18 +453,18 @@ def _latex_circuit_drawer(circuit, circuit (QuantumCircuit): a quantum circuit scale (float): scaling factor filename (str): file path to save image to - style (dict or str): dictionary of style or file name of style file 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 circuit. Defaults to True. justify (str) : `left`, `right` or `none`. Defaults to `left`. Says how - the circuit should be justified. + 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 - initial_state (bool): Optional. Adds |0> in the beginning of the line. Default: `False`. - cregbundle (bool): Optional. If set True bundle classical registers. + initial_state (bool): Optional. Adds |0> in the beginning of the line. + Default: `False`. + cregbundle (bool): Optional. If set True, bundle classical registers. Default: ``False``. Returns: @@ -522,14 +473,13 @@ def _latex_circuit_drawer(circuit, Raises: OSError: usually indicates that ```pdflatex``` or ```pdftocairo``` is missing. - CalledProcessError: usually points errors during diagram creation. + CalledProcessError: usually points to errors during diagram creation. ImportError: if pillow is not installed """ tmpfilename = 'circuit' with tempfile.TemporaryDirectory() as tmpdirname: tmppath = os.path.join(tmpdirname, tmpfilename + '.tex') - _generate_latex_source(circuit, filename=tmppath, - scale=scale, style=style, + _generate_latex_source(circuit, filename=tmppath, scale=scale, plot_barriers=plot_barriers, reverse_bits=reverse_bits, justify=justify, idle_wires=idle_wires, with_layout=with_layout, @@ -578,27 +528,27 @@ def _latex_circuit_drawer(circuit, def _generate_latex_source(circuit, filename=None, - scale=0.7, style=None, reverse_bits=False, + scale=0.7, reverse_bits=False, plot_barriers=True, justify=None, idle_wires=True, with_layout=True, initial_state=False, cregbundle=False): """Convert QuantumCircuit to LaTeX string. Args: - circuit (QuantumCircuit): input circuit - scale (float): image scaling + circuit (QuantumCircuit): a quantum circuit + scale (float): scaling factor filename (str): optional filename to write latex - style (dict or str): dictionary of style or file name of style file 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 circuit. Defaults to True. justify (str) : `left`, `right` or `none`. Defaults to `left`. Says how - the circuit should be justified. + 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 - initial_state (bool): Optional. Adds |0> in the beginning of the line. Default: `False`. - cregbundle (bool): Optional. If set True bundle classical registers. + initial_state (bool): Optional. Adds |0> in the beginning of the line. + Default: `False`. + cregbundle (bool): Optional. If set True, bundle classical registers. Default: ``False``. Returns: @@ -613,9 +563,8 @@ def _generate_latex_source(circuit, filename=None, layout = None global_phase = circuit.global_phase if hasattr(circuit, 'global_phase') else None - qcimg = _latex.QCircuitImage(qregs, cregs, ops, scale, style=style, - plot_barriers=plot_barriers, - reverse_bits=reverse_bits, layout=layout, + qcimg = _latex.QCircuitImage(qregs, cregs, ops, scale, + plot_barriers=plot_barriers, layout=layout, initial_state=initial_state, cregbundle=cregbundle, global_phase=global_phase) @@ -655,7 +604,7 @@ def _matplotlib_circuit_drawer(circuit, scale (float): scaling factor filename (str): file path to save image to style (dict or str): dictionary of style or file name of style file - reverse_bits (bool): When set to True reverse the bit order inside + 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 circuit. Defaults to True. @@ -664,9 +613,9 @@ def _matplotlib_circuit_drawer(circuit, 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. + fold (int): Number of vertical layers allowed before folding. Default is 25. ax (matplotlib.axes.Axes): An optional Axes object to be used for - the visualization output. If none is specified a new matplotlib + the visualization output. If none is specified, a new matplotlib Figure will be created and used. Additionally, if specified there will be no returned Figure since it is redundant. initial_state (bool): Optional. Adds |0> in the beginning of the line. @@ -693,8 +642,7 @@ def _matplotlib_circuit_drawer(circuit, global_phase = circuit.global_phase if hasattr(circuit, 'global_phase') else None qcd = _matplotlib.MatplotlibDrawer(qregs, cregs, ops, scale=scale, style=style, - plot_barriers=plot_barriers, - reverse_bits=reverse_bits, layout=layout, + plot_barriers=plot_barriers, layout=layout, fold=fold, ax=ax, initial_state=initial_state, cregbundle=cregbundle, global_phase=global_phase) return qcd.draw(filename) diff --git a/qiskit/visualization/latex.py b/qiskit/visualization/latex.py index 2a4aa56c9a53..fb63d3430205 100644 --- a/qiskit/visualization/latex.py +++ b/qiskit/visualization/latex.py @@ -16,14 +16,12 @@ import collections import io -import json import math import re import numpy as np from qiskit.circuit.controlledgate import ControlledGate from qiskit.circuit.parameterexpression import ParameterExpression -from qiskit.visualization import qcstyle as _qcstyle from qiskit.visualization import exceptions from qiskit.circuit.tools.pi_check import pi_check from .utils import generate_latex_label @@ -38,8 +36,8 @@ class QCircuitImage: Thanks to Eric Sabo for the initial implementation for Qiskit. """ - def __init__(self, qubits, clbits, ops, scale, style=None, - plot_barriers=True, reverse_bits=False, layout=None, initial_state=False, + def __init__(self, qubits, clbits, ops, scale, + plot_barriers=True, layout=None, initial_state=False, cregbundle=False, global_phase=None): """QCircuitImage initializer. @@ -48,9 +46,6 @@ def __init__(self, qubits, clbits, ops, scale, style=None, clbits (list[Clbit]): list of clbits ops (list[list[DAGNode]]): list of circuit instructions, grouped by layer scale (float): image scaling - style (dict or str): dictionary of style or file name of style file - 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 circuit. Defaults to True. layout (Layout or None): If present, the layout information will be @@ -61,16 +56,6 @@ def __init__(self, qubits, clbits, ops, scale, style=None, Raises: ImportError: If pylatexenc is not installed """ - # style sheet - self._style = _qcstyle.BWStyle() - if style: - if isinstance(style, dict): - self._style.set_style(style) - elif isinstance(style, str): - with open(style) as infile: - dic = json.load(infile) - self._style.set_style(dic) - # list of lists corresponding to layers of the circuit self.ops = ops @@ -113,7 +98,6 @@ def __init__(self, qubits, clbits, ops, scale, style=None, # presence of "box" or "target" determines row spacing self.has_box = False self.has_target = False - self.reverse_bits = reverse_bits self.layout = layout self.initial_state = initial_state self.plot_barriers = plot_barriers diff --git a/qiskit/visualization/matplotlib.py b/qiskit/visualization/matplotlib.py index 3c95522fa2df..5b1e9f92b31a 100644 --- a/qiskit/visualization/matplotlib.py +++ b/qiskit/visualization/matplotlib.py @@ -10,7 +10,7 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -# pylint: disable=invalid-name,missing-docstring,inconsistent-return-statements +# pylint: disable=invalid-name,inconsistent-return-statements """mpl circuit visualization backend.""" @@ -19,6 +19,7 @@ import json import logging import re +import os from warnings import warn import numpy as np @@ -40,7 +41,7 @@ HAS_PYLATEX = False from qiskit.circuit import ControlledGate -from qiskit.visualization.qcstyle import DefaultStyle, IQXStyle, BWStyle +from qiskit.visualization.qcstyle import DefaultStyle, set_style from qiskit.circuit import Delay from qiskit import user_config from qiskit.circuit.tools.pi_check import pi_check @@ -61,6 +62,7 @@ class Anchor: + """Locate the anchors for the gates""" def __init__(self, reg_num, yind, fold): self.__yind = yind self.__fold = fold @@ -69,6 +71,7 @@ def __init__(self, reg_num, yind, fold): self.gate_anchor = 0 def plot_coord(self, index, gate_width, x_offset): + """Set the coord positions for an index""" h_pos = index % self.__fold + 1 # check folding if self.__fold > 0: @@ -85,6 +88,7 @@ def plot_coord(self, index, gate_width, x_offset): return x_pos + x_offset, y_pos def is_locatable(self, index, gate_width): + """Determine if a gate has been placed""" hold = [index + i for i in range(gate_width)] for p in hold: if p in self.__gate_placed: @@ -92,6 +96,7 @@ def is_locatable(self, index, gate_width): return True def set_index(self, index, gate_width): + """Set the index for a gate""" if self.__fold < 2: _index = index else: @@ -106,128 +111,75 @@ def set_index(self, index, gate_width): self.__gate_placed.sort() def get_index(self): + """Getter for the index""" if self.__gate_placed: return self.__gate_placed[-1] + 1 return 0 class MatplotlibDrawer: + """Matplotlib drawer class called from circuit_drawer""" def __init__(self, qregs, cregs, ops, scale=None, style=None, plot_barriers=True, - reverse_bits=False, layout=None, fold=25, ax=None, - initial_state=False, cregbundle=True, global_phase=None): + layout=None, fold=25, ax=None, initial_state=False, + cregbundle=True, global_phase=None): if not HAS_MATPLOTLIB: raise ImportError('The class MatplotlibDrawer needs matplotlib. ' 'To install, run "pip install matplotlib".') - if not HAS_PYLATEX: raise ImportError('The class MatplotlibDrawer needs pylatexenc. ' 'to install, run "pip install pylatexenc".') - - self._ast = None - self._scale = 1.0 if scale is None else scale self._creg = [] self._qreg = [] self._registers(cregs, qregs) - self._ops = ops - self.global_phase = global_phase - self._qreg_dict = collections.OrderedDict() self._creg_dict = collections.OrderedDict() - self._cond = { - 'n_lines': 0, - 'xmax': 0, - 'ymax': 0, - } - if isinstance(style, dict) and 'name' in style.keys(): - if style['name'] == 'iqx': - self._style = IQXStyle() - elif style['name'] == 'bw': - self._style = BWStyle() - else: - self._style = DefaultStyle() - else: - config = user_config.get_config() - if config: - config_style = config.get('circuit_mpl_style', 'default') - if config_style == 'iqx': - self._style = IQXStyle() - elif config_style == 'bw': - self._style = BWStyle() - else: - self._style = DefaultStyle() - elif style is False: - self._style = BWStyle() - else: - self._style = DefaultStyle() - - if style: - if isinstance(style, dict): - self._style.set_style(style) - elif isinstance(style, str): - try: - with open(style) as infile: - dic = json.load(infile) - self._style.set_style(dic) - except FileNotFoundError: - warn("Style JSON file '{}' not found. Will use default style.".format(style), - UserWarning, 2) - except json.JSONDecodeError as e: - warn("Could not decode JSON in file '{}': {}. ".format(style, str(e)) - + "Will use default style.", UserWarning, 2) - except OSError: - warn("Error loading JSON file '{}'. Will use default style.".format(style), - UserWarning, 2) - - self.plot_barriers = plot_barriers - self.reverse_bits = reverse_bits - self.layout = layout - self.initial_state = initial_state - if isinstance(style, dict) and 'cregbundle' in style.keys(): - self.cregbundle = style['cregbundle'] - del style['cregbundle'] - warn("The style dictionary key 'cregbundle' has been deprecated and will be removed" - " in a future release. cregbundle is now a parameter to draw()." - " Example: circuit.draw(output='mpl', cregbundle=False)", DeprecationWarning, 2) - else: - self.cregbundle = cregbundle - + self._ops = ops + self._scale = 1.0 if scale is None else scale + self._style = self._load_style(style) + self._plot_barriers = plot_barriers + self._layout = layout + self._fold = fold + if self._fold < 2: + self._fold = -1 if ax is None: - self.return_fig = True - self.figure = plt.figure() - self.figure.patch.set_facecolor(color=self._style.bg) - self.ax = self.figure.add_subplot(111) + self._return_fig = True + self._figure = plt.figure() + self._figure.patch.set_facecolor(color=self._style['bg']) + self._ax = self._figure.add_subplot(111) else: - self.return_fig = False - self.ax = ax - self.figure = ax.get_figure() + self._return_fig = False + self._ax = ax + self._figure = ax.get_figure() + self._ax.axis('off') + self._ax.set_aspect('equal') + self._ax.tick_params(labelbottom=False, labeltop=False, + labelleft=False, labelright=False) + self._initial_state = initial_state + self._cregbundle = cregbundle + self._global_phase = global_phase - self.x_offset = 0 + self._ast = None + self._n_lines = 0 + self._xmax = 0 + self._ymax = 0 + self._x_offset = 0 self._reg_long_text = 0 + self._style['fs'] *= self._scale + self._style['sfs'] *= self._scale + self._lwidth15 = 1.5 * self._scale + self._lwidth2 = 2.0 * self._scale # default is to use character table for text width, # but get_renderer will work with some mpl backends """fig = plt.figure() if hasattr(fig.canvas, 'get_renderer'): - self.renderer = fig.canvas.get_renderer() + self._renderer = fig.canvas.get_renderer() else: - self.renderer = None""" - self.renderer = None - - self.fold = fold - if self.fold < 2: - self.fold = -1 - - self.ax.axis('off') - self.ax.set_aspect('equal') - self.ax.tick_params(labelbottom=False, labeltop=False, - labelleft=False, labelright=False) - - self._style.fs *= self._scale - self._style.sfs *= self._scale - self._lwidth15 = 1.5 * self._scale - self._lwidth2 = 2.0 * self._scale + self._renderer = None""" + self._renderer = None + self._mathmode_regex = re.compile(r"(?' - initial_cbit = ' 0' - else: - initial_qbit = '' - initial_cbit = '' + longest_reg_name_width = 0 + initial_qbit = ' |0>' if self._initial_state else '' + initial_cbit = ' 0' if self._initial_state else '' - def _fix_double_script(label): - words = label.split(' ') + def _fix_double_script(reg_name): + words = reg_name.split(' ') words = [word.replace('_', r'\_') if word.count('_') > 1 else word for word in words] words = [word.replace('^', r'\^{\ }') if word.count('^') > 1 else word for word in words] - label = ' '.join(words).replace(' ', '\\;') - return label + reg_name = ' '.join(words).replace(' ', '\\;') + return reg_name # quantum register + fs = self._style['fs'] for ii, reg in enumerate(self._qreg): if len(self._qreg) > 1: - if self.layout is None: - label = '${{{name}}}_{{{index}}}$'.format(name=reg.register.name, - index=reg.index) - label = _fix_double_script(label) + initial_qbit - text_width = self._get_text_width(label, self._style.fs) + if self._layout is None: + qreg_name = '${{{name}}}_{{{index}}}$'.format(name=reg.register.name, + index=reg.index) else: - if self.layout[reg.index]: - label = '${{{name}}}_{{{index}}} \\mapsto {{{physical}}}$'.format( - name=self.layout[reg.index].register.name, - index=self.layout[reg.index].index, physical=reg.index) + if self._layout[reg.index]: + qreg_name = '${{{name}}}_{{{index}}} \\mapsto {{{physical}}}$'.format( + name=self._layout[reg.index].register.name, + index=self._layout[reg.index].index, physical=reg.index) else: - label = '${{{physical}}}$'.format(physical=reg.index) - label = _fix_double_script(label) + initial_qbit - text_width = self._get_text_width(label, self._style.fs) + qreg_name = '${{{physical}}}$'.format(physical=reg.index) else: - label = '{name}'.format(name=reg.register.name) - label = _fix_double_script(label) + initial_qbit - text_width = self._get_text_width(label, self._style.fs) - - text_width = text_width * 1.15 # to account for larger font used - if text_width > longest_label_width: - longest_label_width = text_width + qreg_name = '{name}'.format(name=reg.register.name) + qreg_name = _fix_double_script(qreg_name) + initial_qbit + text_width = self._get_text_width(qreg_name, fs) * 1.15 + if text_width > longest_reg_name_width: + longest_reg_name_width = text_width pos = -ii self._qreg_dict[ii] = { - 'y': pos, 'label': label, 'index': reg.index, 'group': reg.register} - self._cond['n_lines'] += 1 + 'y': pos, 'reg_name': qreg_name, 'index': reg.index, 'group': reg.register} + self._n_lines += 1 # classical register if self._creg: @@ -682,81 +694,82 @@ def _fix_double_script(label): y_off = -len(self._qreg) for ii, (reg, nreg) in enumerate(itertools.zip_longest(self._creg, n_creg)): pos = y_off - idx - if self.cregbundle: - label = '{}'.format(reg.register.name) - label = _fix_double_script(label) + initial_cbit - text_width = self._get_text_width(reg.register.name, self._style.fs) * 1.15 - if text_width > longest_label_width: - longest_label_width = text_width - self._creg_dict[ii] = {'y': pos, 'label': label, 'index': reg.index, + if self._cregbundle: + creg_name = '{}'.format(reg.register.name) + creg_name = _fix_double_script(creg_name) + initial_cbit + text_width = self._get_text_width(reg.register.name, fs) * 1.15 + if text_width > longest_reg_name_width: + longest_reg_name_width = text_width + self._creg_dict[ii] = {'y': pos, 'reg_name': creg_name, 'index': reg.index, 'group': reg.register} if not (not nreg or reg.register != nreg.register): continue else: - label = '${}_{{{}}}$'.format(reg.register.name, reg.index) - label = _fix_double_script(label) + initial_cbit - text_width = self._get_text_width(reg.register.name, self._style.fs) * 1.15 - if text_width > longest_label_width: - longest_label_width = text_width - self._creg_dict[ii] = {'y': pos, 'label': label, 'index': reg.index, + creg_name = '${}_{{{}}}$'.format(reg.register.name, reg.index) + creg_name = _fix_double_script(creg_name) + initial_cbit + text_width = self._get_text_width(reg.register.name, fs) * 1.15 + if text_width > longest_reg_name_width: + longest_reg_name_width = text_width + self._creg_dict[ii] = {'y': pos, 'reg_name': creg_name, 'index': reg.index, 'group': reg.register} - self._cond['n_lines'] += 1 + self._n_lines += 1 idx += 1 - self._reg_long_text = longest_label_width - self.x_offset = -1.2 + self._reg_long_text + self._reg_long_text = longest_reg_name_width + self._x_offset = -1.2 + self._reg_long_text def _draw_regs_sub(self, n_fold, feedline_l=False, feedline_r=False): # quantum register + fs = self._style['fs'] for qreg in self._qreg_dict.values(): - label = qreg['label'] - y = qreg['y'] - n_fold * (self._cond['n_lines'] + 1) - self.ax.text(self.x_offset - 0.2, y, label, ha='right', va='center', - fontsize=1.25 * self._style.fs, color=self._style.tc, - clip_on=True, zorder=PORDER_TEXT) - self._line([self.x_offset, y], [self._cond['xmax'], y], + qreg_name = qreg['reg_name'] + y = qreg['y'] - n_fold * (self._n_lines + 1) + self._ax.text(self._x_offset - 0.2, y, qreg_name, ha='right', va='center', + fontsize=1.25 * fs, color=self._style['tc'], + clip_on=True, zorder=PORDER_TEXT) + self._line([self._x_offset, y], [self._xmax, y], zorder=PORDER_REGLINE) # classical register this_creg_dict = {} for creg in self._creg_dict.values(): - label = creg['label'] - y = creg['y'] - n_fold * (self._cond['n_lines'] + 1) + creg_name = creg['reg_name'] + y = creg['y'] - n_fold * (self._n_lines + 1) if y not in this_creg_dict.keys(): - this_creg_dict[y] = {'val': 1, 'label': label} + this_creg_dict[y] = {'val': 1, 'reg_name': creg_name} else: this_creg_dict[y]['val'] += 1 for y, this_creg in this_creg_dict.items(): # cregbundle if this_creg['val'] > 1: - self.ax.plot([self.x_offset + 0.2, self.x_offset + 0.3], [y - 0.1, y + 0.1], - color=self._style.cc, zorder=PORDER_LINE) - self.ax.text(self.x_offset + 0.1, y + 0.1, str(this_creg['val']), ha='left', - va='bottom', fontsize=0.8 * self._style.fs, - color=self._style.tc, clip_on=True, zorder=PORDER_TEXT) - self.ax.text(self.x_offset - 0.2, y, this_creg['label'], ha='right', va='center', - fontsize=1.25 * self._style.fs, color=self._style.tc, - clip_on=True, zorder=PORDER_TEXT) - self._line([self.x_offset, y], [self._cond['xmax'], y], lc=self._style.cc, - ls=self._style.cline, zorder=PORDER_REGLINE) + self._ax.plot([self._x_offset + 0.2, self._x_offset + 0.3], [y - 0.1, y + 0.1], + color=self._style['cc'], zorder=PORDER_LINE) + self._ax.text(self._x_offset + 0.1, y + 0.1, str(this_creg['val']), ha='left', + va='bottom', fontsize=0.8 * fs, + color=self._style['tc'], clip_on=True, zorder=PORDER_TEXT) + self._ax.text(self._x_offset - 0.2, y, this_creg['reg_name'], ha='right', va='center', + fontsize=1.25 * fs, color=self._style['tc'], + clip_on=True, zorder=PORDER_TEXT) + self._line([self._x_offset, y], [self._xmax, y], lc=self._style['cc'], + ls=self._style['cline'], zorder=PORDER_REGLINE) # lf vertical line at either end if feedline_l or feedline_r: - xpos_l = self.x_offset - 0.01 - xpos_r = self.fold + self.x_offset + 0.1 - ypos1 = -n_fold * (self._cond['n_lines'] + 1) - ypos2 = -(n_fold + 1) * (self._cond['n_lines']) - n_fold + 1 + xpos_l = self._x_offset - 0.01 + xpos_r = self._fold + self._x_offset + 0.1 + ypos1 = -n_fold * (self._n_lines + 1) + ypos2 = -(n_fold + 1) * (self._n_lines) - n_fold + 1 if feedline_l: - self.ax.plot([xpos_l, xpos_l], [ypos1, ypos2], - color=self._style.lc, linewidth=self._lwidth15, zorder=PORDER_LINE) + self._ax.plot([xpos_l, xpos_l], [ypos1, ypos2], color=self._style['lc'], + linewidth=self._lwidth15, zorder=PORDER_LINE) if feedline_r: - self.ax.plot([xpos_r, xpos_r], [ypos1, ypos2], - color=self._style.lc, linewidth=self._lwidth15, zorder=PORDER_LINE) + self._ax.plot([xpos_r, xpos_r], [ypos1, ypos2], color=self._style['lc'], + linewidth=self._lwidth15, zorder=PORDER_LINE) def _draw_ops(self, verbose=False): _standard_1q_gates = ['x', 'y', 'z', 'id', 'h', 'r', 's', 'sdg', 't', 'tdg', 'rx', 'ry', - 'rz', 'rxx', 'ryy', 'rzx', 'u1', 'u2', 'u3', 'swap', 'reset', 'sx', - 'sxdg', 'p'] + 'rz', 'rxx', 'ryy', 'rzx', 'u1', 'u2', 'u3', 'u', 'swap', 'reset', + 'sx', 'sxdg', 'p'] _barrier_gates = ['barrier', 'snapshot', 'load', 'save', 'noise'] _barriers = {'coord': [], 'group': []} @@ -765,16 +778,18 @@ def _draw_ops(self, verbose=False): # q_anchors = {} for key, qreg in self._qreg_dict.items(): - q_anchors[key] = Anchor(reg_num=self._cond['n_lines'], - yind=qreg['y'], fold=self.fold) + q_anchors[key] = Anchor(reg_num=self._n_lines, + yind=qreg['y'], 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.fold) + c_anchors[key] = Anchor(reg_num=self._n_lines, + yind=creg['y'], fold=self._fold) # # draw the ops # prev_anc = -1 + fs = self._style['fs'] + sfs = self._style['sfs'] for layer in self._ops: widest_box = 0.0 # @@ -795,17 +810,17 @@ def _draw_ops(self, verbose=False): # small increments at end of the 3 _get_text_width calls are for small # spacing adjustments between gates - ctrl_width = self._get_text_width(ctrl_text, fontsize=self._style.sfs) - 0.05 + ctrl_width = self._get_text_width(ctrl_text, fontsize=sfs) - 0.05 # get param_width, but 0 for gates with array params if (hasattr(op.op, 'params') and not any([isinstance(param, np.ndarray) for param in op.op.params]) and len(op.op.params) > 0): - param = self.param_parse(op.op.params) + param = self._param_parse(op.op.params) if op.name == 'initialize': param = '[%s]' % param param = "${}$".format(param) - param_width = self._get_text_width(param, fontsize=self._style.sfs, + param_width = self._get_text_width(param, fontsize=sfs, param=True) + 0.08 else: param_width = 0.0 @@ -813,15 +828,15 @@ def _draw_ops(self, verbose=False): if op.name == 'cu1' or op.name == 'rzz' or base_name == 'rzz': tname = 'U1' if op.name == 'cu1' else 'zz' gate_width = (self._get_text_width(tname + ' ()', - fontsize=self._style.sfs) + fontsize=sfs) + param_width) * 1.5 else: - gate_width = self._get_text_width(gate_text, fontsize=self._style.fs) + 0.10 + gate_width = self._get_text_width(gate_text, fontsize=fs) + 0.10 # add .21 for the qubit numbers on the left of the multibit gates if (op.name not in _standard_1q_gates and base_name not in _standard_1q_gates): gate_width += 0.21 - box_width = max((gate_width, ctrl_width, param_width, WID)) + box_width = max(gate_width, ctrl_width, param_width, WID) if box_width > widest_box: widest_box = box_width @@ -856,15 +871,15 @@ def _draw_ops(self, verbose=False): # only add the gate to the anchors if it is going to be plotted. # this prevents additional blank wires at the end of the line if # the last instruction is a barrier type - if self.plot_barriers or op.name not in _barrier_gates: + if self._plot_barriers or op.name not in _barrier_gates: for ii in q_idxs: q_anchors[ii].set_index(this_anc, layer_width) # qreg coordinate - q_xy = [q_anchors[ii].plot_coord(this_anc, layer_width, self.x_offset) + q_xy = [q_anchors[ii].plot_coord(this_anc, layer_width, self._x_offset) for ii in q_idxs] # creg coordinate - c_xy = [c_anchors[ii].plot_coord(this_anc, layer_width, self.x_offset) + c_xy = [c_anchors[ii].plot_coord(this_anc, layer_width, self._x_offset) for ii in c_idxs] # bottom and top point of qreg qreg_b = min(q_xy, key=lambda xy: xy[1]) @@ -879,13 +894,13 @@ def _draw_ops(self, verbose=False): # load param if (op.type == 'op' and hasattr(op.op, 'params') and len(op.op.params) > 0 and not any([isinstance(param, np.ndarray) for param in op.op.params])): - param = "{}".format(self.param_parse(op.op.params)) + param = "{}".format(self._param_parse(op.op.params)) else: param = '' # conditional gate if op.condition: - c_xy = [c_anchors[ii].plot_coord(this_anc, layer_width, self.x_offset) for + c_xy = [c_anchors[ii].plot_coord(this_anc, layer_width, self._x_offset) for ii in self._creg_dict] mask = 0 for index, cbit in enumerate(self._creg): @@ -904,19 +919,19 @@ def _draw_ops(self, verbose=False): for xy, m in zip(c_xy, cmask): if m == '1': if xy not in xy_plot: - if vlist[v_ind] == '1' or self.cregbundle: - self._conds(xy, istrue=True) + if vlist[v_ind] == '1' or self._cregbundle: + self._conditional(xy, istrue=True) else: - self._conds(xy, istrue=False) + self._conditional(xy, istrue=False) xy_plot.append(xy) v_ind += 1 creg_b = sorted(xy_plot, key=lambda xy: xy[1])[0] xpos, ypos = creg_b - self.ax.text(xpos, ypos - 0.3 * HIG, hex(val), ha='center', va='top', - fontsize=self._style.sfs, color=self._style.tc, - clip_on=True, zorder=PORDER_TEXT) - self._line(qreg_t, creg_b, lc=self._style.cc, - ls=self._style.cline) + self._ax.text(xpos, ypos - 0.3 * HIG, hex(val), ha='center', va='top', + fontsize=sfs, color=self._style['tc'], + clip_on=True, zorder=PORDER_TEXT) + self._line(qreg_t, creg_b, lc=self._style['cc'], + ls=self._style['cline']) # # draw special gates # @@ -931,7 +946,7 @@ def _draw_ops(self, verbose=False): if q_group not in _barriers['group']: _barriers['group'].append(q_group) _barriers['coord'].append(q_xy[index]) - if self.plot_barriers: + if self._plot_barriers: self._barrier(_barriers) elif op.name == 'initialize': @@ -962,7 +977,7 @@ def _draw_ops(self, verbose=False): num_ctrl_qubits = op.op.num_ctrl_qubits self._set_ctrl_bits(op.op.ctrl_state, num_ctrl_qubits, q_xy, ec=ec, tc=tc, text=ctrl_text, qargs=op.qargs) - tgt_color = self._style.dispcol['target'] + tgt_color = self._style['dispcol']['target'] tgt = tgt_color if isinstance(tgt_color, str) else tgt_color[0] self._x_tgt_qubit(q_xy[num_ctrl_qubits], ec=ec, ac=tgt) self._line(qreg_b, qreg_t, lc=lc) @@ -984,7 +999,7 @@ def _draw_ops(self, verbose=False): self._ctrl_qubit(q_xy[num_ctrl_qubits], fc=ec, ec=ec, tc=tc) if op.name != 'cu1': self._ctrl_qubit(q_xy[num_ctrl_qubits + 1], fc=ec, ec=ec, tc=tc) - stext = self._style.disptex['u1'] if op.name == 'cu1' else 'zz' + stext = self._style['disptex']['u1'] if op.name == 'cu1' else 'zz' self._sidetext(qreg_b, tc=tc, text='{}'.format(stext) + ' ' + '({})'.format(param)) self._line(qreg_b, qreg_t, lc=lc) @@ -1025,7 +1040,7 @@ def _draw_ops(self, verbose=False): # adjust the column if there have been barriers encountered, but not plotted barrier_offset = 0 - if not self.plot_barriers: + if not self._plot_barriers: # only adjust if everything in the layer wasn't plotted barrier_offset = -1 if all([op.name in _barrier_gates for op in layer]) else 0 @@ -1035,15 +1050,15 @@ def _draw_ops(self, verbose=False): # anchors = [q_anchors[ii].get_index() for ii in self._qreg_dict] max_anc = max(anchors) if anchors else 0 - n_fold = max(0, max_anc - 1) // self.fold if self.fold > 0 else 0 + n_fold = max(0, max_anc - 1) // self._fold if self._fold > 0 else 0 # window size - if max_anc > self.fold > 0: - self._cond['xmax'] = self.fold + 1 + self.x_offset - 0.9 - self._cond['ymax'] = (n_fold + 1) * (self._cond['n_lines'] + 1) - 1 + if max_anc > self._fold > 0: + self._xmax = self._fold + 1 + self._x_offset - 0.9 + self._ymax = (n_fold + 1) * (self._n_lines + 1) - 1 else: - self._cond['xmax'] = max_anc + 1 + self.x_offset - 0.9 - self._cond['ymax'] = self._cond['n_lines'] + self._xmax = max_anc + 1 + self._x_offset - 0.9 + self._ymax = self._n_lines # add horizontal lines for ii in range(n_fold + 1): @@ -1052,14 +1067,14 @@ def _draw_ops(self, verbose=False): self._draw_regs_sub(ii, feedline_l, feedline_r) # draw anchor index number - if self._style.index: + if self._style['index']: for ii in range(max_anc): - if self.fold > 0: - x_coord = ii % self.fold + self._reg_long_text - 0.67 - y_coord = - (ii // self.fold) * (self._cond['n_lines'] + 1) + 0.7 + if self._fold > 0: + x_coord = ii % self._fold + self._reg_long_text - 0.67 + y_coord = - (ii // self._fold) * (self._n_lines + 1) + 0.7 else: x_coord = ii + self._reg_long_text - 0.67 y_coord = 0.7 - self.ax.text(x_coord, y_coord, str(ii + 1), ha='center', - va='center', fontsize=self._style.sfs, - color=self._style.tc, clip_on=True, zorder=PORDER_TEXT) + self._ax.text(x_coord, y_coord, str(ii + 1), ha='center', + va='center', fontsize=sfs, + color=self._style['tc'], clip_on=True, zorder=PORDER_TEXT) diff --git a/qiskit/visualization/qcstyle.py b/qiskit/visualization/qcstyle.py index b70f924490c4..7df1cfd6b289 100644 --- a/qiskit/visualization/qcstyle.py +++ b/qiskit/visualization/qcstyle.py @@ -10,9 +10,8 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -# pylint: disable=invalid-name,missing-docstring +"""mpl circuit visualization style.""" -from copy import copy from warnings import warn @@ -20,401 +19,152 @@ class DefaultStyle: """IBM Design Style colors """ def __init__(self): - # Set colors - basis_color = '#FA74A6' # Red - clifford_color = '#6FA4FF' # Blue - non_gate_color = '#000000' # Black - other_color = '#BB8BFF' # Purple - pauli_color = '#05BAB6' # Green - iden_color = '#05BAB6' # Green - - black_font = '#000000' # Black font color - white_font = '#ffffff' # White font color - - self.name = 'default' - self.tc = '#000000' - self.sc = '#000000' - self.lc = '#000000' - self.not_gate_lc = '#ffffff' - self.cc = '#778899' # Medium Gray - self.gc = other_color - self.gt = '#000000' - self.bc = '#bdbdbd' # Dark Gray - self.bg = '#ffffff' - self.edge_color = None - self.math_fs = 15 - self.fs = 13 - self.sfs = 8 - self.disptex = { - 'id': 'I', - 'p': 'P', - 'u': 'U', - 'u1': '$\\mathrm{U}_1$', - 'u2': '$\\mathrm{U}_2$', - 'u3': '$\\mathrm{U}_3$', - 'x': 'X', - 'y': 'Y', - 'z': 'Z', - 'h': 'H', - 's': 'S', - 'sdg': '$\\mathrm{S}^\\dagger$', - 'sx': '$\\sqrt{\\mathrm{X}}$', - 'sxdg': '$\\sqrt{\\mathrm{X}}^\\dagger$', - 't': 'T', - 'tdg': '$\\mathrm{T}^\\dagger$', - 'iswap': 'Iswap', - 'dcx': 'Dcx', - 'ms': 'MS', - 'diagonal': 'Diagonal', - 'unitary': 'Unitary', - 'r': 'R', - 'rx': '$\\mathrm{R}_\\mathrm{X}$', - 'ry': '$\\mathrm{R}_\\mathrm{Y}$', - 'rz': '$\\mathrm{R}_\\mathrm{Z}$', - 'rxx': '$\\mathrm{R}_{\\mathrm{XX}}$', - 'ryy': '$\\mathrm{R}_{\\mathrm{YY}}$', - 'rzx': '$\\mathrm{R}_{\\mathrm{ZX}}$', - 'rzz': '$\\mathrm{R}_{\\mathrm{ZZ}}$', - 'reset': '$\\left|0\\right\\rangle$', - 'initialize': '$|\\psi\\rangle$' - } - self.dispcol = { - 'u1': (basis_color, black_font), - 'u2': (basis_color, black_font), - 'u3': (basis_color, black_font), - 'id': (iden_color, black_font), - 'x': (pauli_color, black_font), - 'y': (pauli_color, black_font), - 'z': (pauli_color, black_font), - 'h': (clifford_color, black_font), - 'cx': (clifford_color, black_font), - 'cy': (clifford_color, black_font), - 'cz': (clifford_color, black_font), - 'swap': (clifford_color, black_font), - 's': (clifford_color, black_font), - 'sdg': (clifford_color, black_font), - 'dcx': (clifford_color, black_font), - 'iswap': (clifford_color, black_font), - 't': (other_color, black_font), - 'tdg': (other_color, black_font), - 'r': (other_color, black_font), - 'rx': (other_color, black_font), - 'ry': (other_color, black_font), - 'rz': (other_color, black_font), - 'rxx': (other_color, black_font), - 'ryy': (other_color, black_font), - 'rzx': (other_color, black_font), - 'reset': (non_gate_color, white_font), - 'target': ('#ffffff', white_font), - 'measure': (non_gate_color, white_font), - 'ccx': (other_color, black_font), - 'cdcx': (other_color, black_font), - 'ccdcx': (other_color, black_font), - 'cswap': (other_color, black_font), - 'ccswap': (other_color, black_font), - 'mcx': (other_color, black_font), - 'mcx_gray': (other_color, black_font), - 'u': (other_color, black_font), - 'p': (other_color, black_font), - 'sx': (other_color, black_font), - 'sxdg': (other_color, black_font) - } - self.latexmode = False - self.index = False - self.figwidth = -1 - self.dpi = 150 - self.margin = [2.0, 0.1, 0.1, 0.3] - self.cline = 'doublet' - - def set_style(self, style_dic): - dic = copy(style_dic) - self.name = dic.pop('name', self.name) - self.tc = dic.pop('textcolor', self.tc) - self.sc = dic.pop('subtextcolor', self.sc) - self.lc = dic.pop('linecolor', self.lc) - self.cc = dic.pop('creglinecolor', self.cc) - self.gt = dic.pop('gatetextcolor', self.gt) - self.gc = dic.pop('gatefacecolor', self.gc) - self.bc = dic.pop('barrierfacecolor', self.bc) - self.bg = dic.pop('backgroundcolor', self.bg) - self.fs = dic.pop('fontsize', self.fs) - self.sfs = dic.pop('subfontsize', self.sfs) - self.disptex = dic.pop('displaytext', self.disptex) - dcol = dic.pop('displaycolor', self.dispcol) - for col in dcol.keys(): - if col in self.dispcol.keys(): - self.dispcol[col] = dcol[col] - self.latexmode = dic.pop('latexdrawerstyle', self.latexmode) - 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 dic: - warn('style option/s ({}) is/are not supported'.format(', '.join(dic.keys())), - DeprecationWarning, 2) - - -class BWStyle: - def __init__(self): - face_gate_color = '#ffffff' # White face color - - self.name = 'bw' - self.tc = '#000000' - self.sc = '#000000' - self.lc = '#000000' - self.not_gate_lc = '#000000' - self.cc = '#778899' - self.gc = '#ffffff' - self.gt = '#000000' - self.bc = '#bdbdbd' - self.bg = '#ffffff' - self.edge_color = '#000000' - self.fs = 13 - self.math_fs = 15 - self.sfs = 8 - self.disptex = { - 'id': 'I', - 'p': 'P', - 'u': 'U', - 'u1': '$\\mathrm{U}_1$', - 'u2': '$\\mathrm{U}_2$', - 'u3': '$\\mathrm{U}_3$', - 'x': 'X', - 'y': 'Y', - 'z': 'Z', - 'h': 'H', - 's': 'S', - 'sdg': '$\\mathrm{S}^\\dagger$', - 't': 'T', - 'tdg': '$\\mathrm{T}^\\dagger$', - 'iswap': 'Iswap', - 'dcx': 'Dcx', - 'ms': 'MS', - 'diagonal': 'Diagonal', - 'unitary': 'Unitary', - 'r': 'R', - 'rx': '$\\mathrm{R}_\\mathrm{X}$', - 'ry': '$\\mathrm{R}_\\mathrm{Y}$', - 'rz': '$\\mathrm{R}_\\mathrm{Z}$', - 'rxx': '$\\mathrm{R}_{\\mathrm{XX}}$', - 'ryy': '$\\mathrm{R}_{\\mathrm{YY}}$', - 'rzx': '$\\mathrm{R}_{\\mathrm{ZX}}$', - 'rzz': '$\\mathrm{R}_{\\mathrm{ZZ}}$', - 'reset': '$\\left|0\\right\\rangle$', - 'initialize': '$|\\psi\\rangle$' + """Creates a Default Style dictionary + """ + colors = { + '### Default Colors': 'Default Colors', + 'basis': '#FA74A6', # Red + 'clifford': '#6FA4FF', # Light Blue + 'pauli': '#05BAB6', # Green + 'def_other': '#BB8BFF', # Purple + '### IQX Colors': 'IQX Colors', + 'classical': '#002D9C', # Dark Blue + 'phase': '#33B1FF', # Cyan + 'hadamard': '#FA4D56', # Light Red + 'non_unitary': '#A8A8A8', # Medium Gray + 'iqx_other': '#9F1853', # Dark Red + '### B/W': 'B/W', + 'black': '#000000', + 'white': '#FFFFFF', + 'dark_gray': '#778899', + 'light_gray': '#BDBDBD' } - self.dispcol = { - 'u1': (face_gate_color, '#000000'), - 'u2': (face_gate_color, '#000000'), - 'u3': (face_gate_color, '#000000'), - 'id': (face_gate_color, '#000000'), - 'x': (face_gate_color, '#000000'), - 'y': (face_gate_color, '#000000'), - 'z': (face_gate_color, '#000000'), - 'h': (face_gate_color, '#000000'), - 'cx': (face_gate_color, '#000000'), - 'cy': (face_gate_color, '#000000'), - 'cz': (face_gate_color, '#000000'), - 'swap': (face_gate_color, '#000000'), - 's': (face_gate_color, '#000000'), - 'sdg': (face_gate_color, '#000000'), - 'dcx': (face_gate_color, '#000000'), - 'iswap': (face_gate_color, '#000000'), - 't': (face_gate_color, '#000000'), - 'tdg': (face_gate_color, '#000000'), - 'r': (face_gate_color, '#000000'), - 'rx': (face_gate_color, '#000000'), - 'ry': (face_gate_color, '#000000'), - 'rz': (face_gate_color, '#000000'), - 'rxx': (face_gate_color, '#000000'), - 'ryy': (face_gate_color, '#000000'), - 'rzx': (face_gate_color, '#000000'), - 'reset': (face_gate_color, '#000000'), - 'target': (face_gate_color, '#000000'), - 'measure': (face_gate_color, '#000000'), - 'ccx': (face_gate_color, '#000000'), - 'cdcx': (face_gate_color, '#000000'), - 'ccdcx': (face_gate_color, '#000000'), - 'cswap': (face_gate_color, '#000000'), - 'ccswap': (face_gate_color, '#000000'), - 'mcx': (face_gate_color, '#000000'), - 'mcx_gray': (face_gate_color, '#000000'), - 'u': (face_gate_color, '#000000'), - 'p': (face_gate_color, '#000000'), - 'sx': (face_gate_color, '#000000'), - 'sxdg': (face_gate_color, '#000000') + self.style = { + 'name': 'default', + 'tc': colors['black'], # Non-gate Text Color + 'gt': colors['black'], # Gate Text Color + 'sc': colors['black'], # Gate Subtext Color + 'lc': colors['black'], # Line Color + 'cc': colors['dark_gray'], # creg Line Color + 'gc': colors['def_other'], # Default Gate Color + 'bc': colors['light_gray'], # Barrier Color + 'bg': colors['white'], # Background Color + 'ec': None, # Edge Color (B/W only) + 'fs': 13, # Gate Font Size + 'sfs': 8, # Subtext Font Size + 'index': False, + 'figwidth': -1, + 'dpi': 150, + 'margin': [2.0, 0.1, 0.1, 0.3], + 'cline': 'doublet', + + 'disptex': { + 'u1': '$\\mathrm{U}_1$', + 'u2': '$\\mathrm{U}_2$', + 'u3': '$\\mathrm{U}_3$', + 'u': 'U', + 'p': 'P', + 'id': 'I', + 'x': 'X', + 'y': 'Y', + 'z': 'Z', + 'h': 'H', + 's': 'S', + 'sdg': '$\\mathrm{S}^\\dagger$', + 'sx': '$\\sqrt{\\mathrm{X}}$', + 'sxdg': '$\\sqrt{\\mathrm{X}}^\\dagger$', + 't': 'T', + 'tdg': '$\\mathrm{T}^\\dagger$', + 'dcx': 'Dcx', + 'iswap': 'Iswap', + 'ms': 'MS', + 'r': 'R', + 'rx': '$\\mathrm{R}_\\mathrm{X}$', + 'ry': '$\\mathrm{R}_\\mathrm{Y}$', + 'rz': '$\\mathrm{R}_\\mathrm{Z}$', + 'rxx': '$\\mathrm{R}_{\\mathrm{XX}}$', + 'ryy': '$\\mathrm{R}_{\\mathrm{YY}}$', + 'rzx': '$\\mathrm{R}_{\\mathrm{ZX}}$', + 'rzz': '$\\mathrm{R}_{\\mathrm{ZZ}}$', + 'reset': '$\\left|0\\right\\rangle$', + 'initialize': '$|\\psi\\rangle$' + }, + 'dispcol': { + 'u1': (colors['basis'], colors['black']), + 'u2': (colors['basis'], colors['black']), + 'u3': (colors['basis'], colors['black']), + 'u': (colors['def_other'], colors['black']), + 'p': (colors['def_other'], colors['black']), + 'id': (colors['pauli'], colors['black']), + 'x': (colors['pauli'], colors['black']), + 'y': (colors['pauli'], colors['black']), + 'z': (colors['pauli'], colors['black']), + 'h': (colors['clifford'], colors['black']), + 'cx': (colors['clifford'], colors['black']), + 'ccx': (colors['def_other'], colors['black']), + 'mcx': (colors['def_other'], colors['black']), + 'mcx_gray': (colors['def_other'], colors['black']), + 'cy': (colors['clifford'], colors['black']), + 'cz': (colors['clifford'], colors['black']), + 'swap': (colors['clifford'], colors['black']), + 'cswap': (colors['def_other'], colors['black']), + 'ccswap': (colors['def_other'], colors['black']), + 'dcx': (colors['clifford'], colors['black']), + 'cdcx': (colors['def_other'], colors['black']), + 'ccdcx': (colors['def_other'], colors['black']), + 'iswap': (colors['clifford'], colors['black']), + 's': (colors['clifford'], colors['black']), + 'sdg': (colors['clifford'], colors['black']), + 't': (colors['def_other'], colors['black']), + 'tdg': (colors['def_other'], colors['black']), + 'sx': (colors['def_other'], colors['black']), + 'sxdg': (colors['def_other'], colors['black']), + 'r': (colors['def_other'], colors['black']), + 'rx': (colors['def_other'], colors['black']), + 'ry': (colors['def_other'], colors['black']), + 'rz': (colors['def_other'], colors['black']), + 'rxx': (colors['def_other'], colors['black']), + 'ryy': (colors['def_other'], colors['black']), + 'rzx': (colors['def_other'], colors['black']), + 'reset': (colors['black'], colors['white']), + 'target': (colors['white'], colors['white']), + 'measure': (colors['black'], colors['white']) + } } - self.latexmode = False - self.index = False - self.figwidth = -1 - self.dpi = 150 - self.margin = [2.0, 0.1, 0.1, 0.3] - self.cline = 'doublet' - def set_style(self, style_dic): - dic = copy(style_dic) - self.name = dic.pop('name', self.name) - self.tc = dic.pop('textcolor', self.tc) - self.sc = dic.pop('subtextcolor', self.sc) - self.lc = dic.pop('linecolor', self.lc) - self.cc = dic.pop('creglinecolor', self.cc) - self.gt = dic.pop('gatetextcolor', self.gt) - self.gc = dic.pop('gatefacecolor', self.gc) - self.bc = dic.pop('barrierfacecolor', self.bc) - self.bg = dic.pop('backgroundcolor', self.bg) - self.fs = dic.pop('fontsize', self.fs) - self.sfs = dic.pop('subfontsize', self.sfs) - self.disptex = dic.pop('displaytext', self.disptex) - dcol = dic.pop('displaycolor', self.dispcol) - for col in dcol.keys(): - if col in self.dispcol.keys(): - self.dispcol[col] = dcol[col] - self.latexmode = dic.pop('latexdrawerstyle', self.latexmode) - 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 dic: - warn('style option/s ({}) is/are not supported'.format(', '.join(dic.keys())), - DeprecationWarning, 2) - - -class IQXStyle: - def __init__(self): - # Set colors - classical_gate_color = '#002D9C' # Dark Blue - phase_gate_color = '#33B1FF' # Cyan - hadamard_color = '#FA4D56' # Red - other_quantum_gate = '#9F1853' # Dark Red - non_unitary_gate = '#A8A8A8' # Grey - - black_font = '#000000' # Black font color - white_font = '#ffffff' # White font color - - self.name = 'iqx' - self.tc = '#000000' - self.sc = '#ffffff' - self.lc = '#000000' - self.not_gate_lc = '#ffffff' - self.cc = '#778899' # Medium Gray - self.gc = other_quantum_gate - self.gt = '#ffffff' - self.bc = non_unitary_gate # Dark Gray - self.bg = '#ffffff' - self.edge_color = None - self.math_fs = 15 - self.fs = 13 - self.sfs = 8 - self.disptex = { - 'id': 'I', - 'p': 'P', - 'u': 'U', - 'u1': '$\\mathrm{U}_1$', - 'u2': '$\\mathrm{U}_2$', - 'u3': '$\\mathrm{U}_3$', - 'x': 'X', - 'y': 'Y', - 'z': 'Z', - 'h': 'H', - 's': 'S', - 'sdg': '$\\mathrm{S}^\\dagger$', - 'sx': '$\\sqrt{\\mathrm{X}}$', - 'sxdg': '$\\sqrt{\\mathrm{X}}^\\dagger$', - 't': 'T', - 'tdg': '$\\mathrm{T}^\\dagger$', - 'iswap': 'Iswap', - 'dcx': 'Dcx', - 'ms': 'MS', - 'diagonal': 'Diagonal', - 'unitary': 'Unitary', - 'r': 'R', - 'rx': '$\\mathrm{R}_\\mathrm{X}$', - 'ry': '$\\mathrm{R}_\\mathrm{Y}$', - 'rz': '$\\mathrm{R}_\\mathrm{Z}$', - 'rxx': '$\\mathrm{R}_{\\mathrm{XX}}$', - 'ryy': '$\\mathrm{R}_{\\mathrm{YY}}$', - 'rzx': '$\\mathrm{R}_{\\mathrm{ZX}}$', - 'rzz': '$\\mathrm{R}_{\\mathrm{ZZ}}$', - 'reset': '$\\left|0\\right\\rangle$', - 'initialize': '$|\\psi\\rangle$' - } - self.dispcol = { - 'u1': (phase_gate_color, black_font), - 'u2': (other_quantum_gate, white_font), - 'u3': (other_quantum_gate, white_font), - 'id': (classical_gate_color, white_font), - 'x': (classical_gate_color, white_font), - 'y': (other_quantum_gate, white_font), - 'z': (phase_gate_color, black_font), - 'h': (hadamard_color, black_font), - 'cx': (classical_gate_color, white_font), - 'cy': (other_quantum_gate, white_font), - 'cz': (other_quantum_gate, white_font), - 'swap': (classical_gate_color, white_font), - 's': (phase_gate_color, black_font), - 'sdg': (phase_gate_color, black_font), - 'dcx': (classical_gate_color, white_font), - 'iswap': (phase_gate_color, black_font), - 't': (phase_gate_color, black_font), - 'tdg': (phase_gate_color, black_font), - 'r': (other_quantum_gate, white_font), - 'rx': (other_quantum_gate, white_font), - 'ry': (other_quantum_gate, white_font), - 'rz': (other_quantum_gate, white_font), - 'rxx': (other_quantum_gate, white_font), - 'ryy': (other_quantum_gate, white_font), - 'rzx': (other_quantum_gate, white_font), - 'reset': (non_unitary_gate, black_font), - 'target': ('#ffffff', '#ffffff'), - 'measure': (non_unitary_gate, black_font), - 'ccx': (classical_gate_color, white_font), - 'cdcx': (classical_gate_color, white_font), - 'ccdcx': (classical_gate_color, white_font), - 'cswap': (classical_gate_color, white_font), - 'ccswap': (classical_gate_color, white_font), - 'mcx': (classical_gate_color, white_font), - 'mcx_gray': (classical_gate_color, white_font), - 'u': (other_quantum_gate, white_font), - 'p': (phase_gate_color, black_font), - 'sx': (other_quantum_gate, white_font), - 'sxdg': (other_quantum_gate, white_font), - } - self.latexmode = False - self.index = False - self.figwidth = -1 - self.dpi = 150 - self.margin = [2.0, 0.1, 0.1, 0.3] - self.cline = 'doublet' - - def set_style(self, style_dic): - dic = copy(style_dic) - self.name = dic.pop('name', self.name) - self.tc = dic.pop('textcolor', self.tc) - self.sc = dic.pop('subtextcolor', self.sc) - self.lc = dic.pop('linecolor', self.lc) - self.cc = dic.pop('creglinecolor', self.cc) - self.gt = dic.pop('gatetextcolor', self.gt) - self.gc = dic.pop('gatefacecolor', self.gc) - self.bc = dic.pop('barrierfacecolor', self.bc) - self.bg = dic.pop('backgroundcolor', self.bg) - self.fs = dic.pop('fontsize', self.fs) - self.sfs = dic.pop('subfontsize', self.sfs) - self.disptex = dic.pop('displaytext', self.disptex) - dcol = dic.pop('displaycolor', self.dispcol) - for col in dcol.keys(): - if col in self.dispcol.keys(): - self.dispcol[col] = dcol[col] - self.latexmode = dic.pop('latexdrawerstyle', self.latexmode) - 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 dic: - warn('style option/s ({}) is/are not supported'.format(', '.join(dic.keys())), - DeprecationWarning, 2) +def set_style(current_style, new_style): + """Utility function to take elements in new_style and + write them into current_style. + """ + current_style['name'] = new_style.pop('name', current_style['name']) + current_style['tc'] = new_style.pop('textcolor', current_style['tc']) + current_style['gt'] = new_style.pop('gatetextcolor', current_style['gt']) + current_style['sc'] = new_style.pop('subtextcolor', current_style['sc']) + current_style['lc'] = new_style.pop('linecolor', current_style['lc']) + current_style['cc'] = new_style.pop('creglinecolor', current_style['cc']) + current_style['gc'] = new_style.pop('gatefacecolor', current_style['gc']) + current_style['bc'] = new_style.pop('barrierfacecolor', current_style['bc']) + current_style['bg'] = new_style.pop('backgroundcolor', current_style['bg']) + current_style['ec'] = new_style.pop('edgecolor', current_style['ec']) + current_style['fs'] = new_style.pop('fontsize', current_style['fs']) + current_style['sfs'] = new_style.pop('subfontsize', current_style['sfs']) + current_style['index'] = new_style.pop('showindex', current_style['index']) + current_style['figwidth'] = new_style.pop('figwidth', current_style['figwidth']) + current_style['dpi'] = new_style.pop('dpi', current_style['dpi']) + current_style['margin'] = new_style.pop('margin', current_style['margin']) + current_style['cline'] = new_style.pop('creglinestyle', current_style['cline']) + dtex = new_style.pop('displaytext', current_style['disptex']) + for tex in dtex.keys(): + if tex in current_style['disptex'].keys(): + current_style['disptex'][tex] = dtex[tex] + dcol = new_style.pop('displaycolor', current_style['dispcol']) + for col in dcol.keys(): + if col in current_style['dispcol'].keys(): + current_style['dispcol'][col] = dcol[col] + + if new_style: + warn('style option/s ({}) is/are not supported'.format(', '.join(new_style.keys())), + DeprecationWarning, 2) + + return current_style diff --git a/qiskit/visualization/styles/bw.json b/qiskit/visualization/styles/bw.json new file mode 100644 index 000000000000..ece05efa37ba --- /dev/null +++ b/qiskit/visualization/styles/bw.json @@ -0,0 +1,213 @@ +{ + "name": "bw", + "textcolor": "#000000", + "gatetextcolor": "#000000", + "subtextcolor": "#000000", + "linecolor": "#000000", + "creglinecolor": "#778899", + "gatefacecolor": "#FFFFFF", + "barrierfacecolor": "#BDBDBD", + "backgroundcolor": "#FFFFFF", + "edgecolor": "#000000", + "fontsize": 13, + "subfontsize": 8, + "showindex": false, + "figwidth": -1, + "dpi": 150, + "margin": [ + 2.0, + 0.1, + 0.1, + 0.3 + ], + "creglinestyle": "doublet", + "displaytext": { + "u1": "$\\mathrm{U}_1$", + "u2": "$\\mathrm{U}_2$", + "u3": "$\\mathrm{U}_3$", + "u": "U", + "p": "P", + "id": "I", + "x": "X", + "y": "Y", + "z": "Z", + "h": "H", + "s": "S", + "sdg": "$\\mathrm{S}^\\dagger$", + "sx": "$\\sqrt{\\mathrm{X}}$", + "sxdg": "$\\sqrt{\\mathrm{X}}^\\dagger$", + "t": "T", + "tdg": "$\\mathrm{T}^\\dagger$", + "dcx": "Dcx", + "iswap": "Iswap", + "ms": "MS", + "r": "R", + "rx": "$\\mathrm{R}_\\mathrm{X}$", + "ry": "$\\mathrm{R}_\\mathrm{Y}$", + "rz": "$\\mathrm{R}_\\mathrm{Z}$", + "rxx": "$\\mathrm{R}_{\\mathrm{XX}}$", + "ryy": "$\\mathrm{R}_{\\mathrm{YY}}$", + "rzx": "$\\mathrm{R}_{\\mathrm{ZX}}$", + "rzz": "$\\mathrm{R}_{\\mathrm{ZZ}}$", + "reset": "$\\left|0\\right\\rangle$", + "initialize": "$|\\psi\\rangle$" + }, + "displaycolor": { + "u1": [ + "#FFFFFF", + "#000000" + ], + "u2": [ + "#FFFFFF", + "#000000" + ], + "u3": [ + "#FFFFFF", + "#000000" + ], + "u": [ + "#FFFFFF", + "#000000" + ], + "p": [ + "#FFFFFF", + "#000000" + ], + "id": [ + "#FFFFFF", + "#000000" + ], + "x": [ + "#FFFFFF", + "#000000" + ], + "y": [ + "#FFFFFF", + "#000000" + ], + "z": [ + "#FFFFFF", + "#000000" + ], + "h": [ + "#FFFFFF", + "#000000" + ], + "cx": [ + "#FFFFFF", + "#000000" + ], + "ccx": [ + "#FFFFFF", + "#000000" + ], + "mcx": [ + "#FFFFFF", + "#000000" + ], + "mcx_gray": [ + "#FFFFFF", + "#000000" + ], + "cy": [ + "#FFFFFF", + "#000000" + ], + "cz": [ + "#FFFFFF", + "#000000" + ], + "swap": [ + "#FFFFFF", + "#000000" + ], + "cswap": [ + "#FFFFFF", + "#000000" + ], + "ccswap": [ + "#FFFFFF", + "#000000" + ], + "dcx": [ + "#FFFFFF", + "#000000" + ], + "cdcx": [ + "#FFFFFF", + "#000000" + ], + "ccdcx": [ + "#FFFFFF", + "#000000" + ], + "iswap": [ + "#FFFFFF", + "#000000" + ], + "s": [ + "#FFFFFF", + "#000000" + ], + "sdg": [ + "#FFFFFF", + "#000000" + ], + "t": [ + "#FFFFFF", + "#000000" + ], + "tdg": [ + "#FFFFFF", + "#000000" + ], + "sx": [ + "#FFFFFF", + "#000000" + ], + "sxdg": [ + "#FFFFFF", + "#000000" + ], + "r": [ + "#FFFFFF", + "#000000" + ], + "rx": [ + "#FFFFFF", + "#000000" + ], + "ry": [ + "#FFFFFF", + "#000000" + ], + "rz": [ + "#FFFFFF", + "#000000" + ], + "rxx": [ + "#FFFFFF", + "#000000" + ], + "ryy": [ + "#FFFFFF", + "#000000" + ], + "rzx": [ + "#FFFFFF", + "#000000" + ], + "reset": [ + "#000000", + "#FFFFFF" + ], + "target": [ + "#FFFFFF", + "#FFFFFF" + ], + "measure": [ + "#000000", + "#FFFFFF" + ] + } +} \ No newline at end of file diff --git a/qiskit/visualization/styles/default.json b/qiskit/visualization/styles/default.json new file mode 100644 index 000000000000..734ae2a7a77b --- /dev/null +++ b/qiskit/visualization/styles/default.json @@ -0,0 +1,213 @@ +{ + "name": "default", + "textcolor": "#000000", + "gatetextcolor": "#000000", + "subtextcolor": "#000000", + "linecolor": "#000000", + "creglinecolor": "#778899", + "gatefacecolor": "#BB8BFF", + "barrierfacecolor": "#BDBDBD", + "backgroundcolor": "#FFFFFF", + "edgecolor": null, + "fontsize": 13, + "subfontsize": 8, + "showindex": false, + "figwidth": -1, + "dpi": 150, + "margin": [ + 2.0, + 0.1, + 0.1, + 0.3 + ], + "creglinestyle": "doublet", + "displaytext": { + "u1": "$\\mathrm{U}_1$", + "u2": "$\\mathrm{U}_2$", + "u3": "$\\mathrm{U}_3$", + "u": "U", + "p": "P", + "id": "I", + "x": "X", + "y": "Y", + "z": "Z", + "h": "H", + "s": "S", + "sdg": "$\\mathrm{S}^\\dagger$", + "sx": "$\\sqrt{\\mathrm{X}}$", + "sxdg": "$\\sqrt{\\mathrm{X}}^\\dagger$", + "t": "T", + "tdg": "$\\mathrm{T}^\\dagger$", + "dcx": "Dcx", + "iswap": "Iswap", + "ms": "MS", + "r": "R", + "rx": "$\\mathrm{R}_\\mathrm{X}$", + "ry": "$\\mathrm{R}_\\mathrm{Y}$", + "rz": "$\\mathrm{R}_\\mathrm{Z}$", + "rxx": "$\\mathrm{R}_{\\mathrm{XX}}$", + "ryy": "$\\mathrm{R}_{\\mathrm{YY}}$", + "rzx": "$\\mathrm{R}_{\\mathrm{ZX}}$", + "rzz": "$\\mathrm{R}_{\\mathrm{ZZ}}$", + "reset": "$\\left|0\\right\\rangle$", + "initialize": "$|\\psi\\rangle$" + }, + "displaycolor": { + "u1": [ + "#FA74A6", + "#000000" + ], + "u2": [ + "#FA74A6", + "#000000" + ], + "u3": [ + "#FA74A6", + "#000000" + ], + "u": [ + "#BB8BFF", + "#000000" + ], + "p": [ + "#BB8BFF", + "#000000" + ], + "id": [ + "#05BAB6", + "#000000" + ], + "x": [ + "#05BAB6", + "#000000" + ], + "y": [ + "#05BAB6", + "#000000" + ], + "z": [ + "#05BAB6", + "#000000" + ], + "h": [ + "#6FA4FF", + "#000000" + ], + "cx": [ + "#6FA4FF", + "#000000" + ], + "ccx": [ + "#BB8BFF", + "#000000" + ], + "mcx": [ + "#BB8BFF", + "#000000" + ], + "mcx_gray": [ + "#BB8BFF", + "#000000" + ], + "cy": [ + "#6FA4FF", + "#000000" + ], + "cz": [ + "#6FA4FF", + "#000000" + ], + "swap": [ + "#6FA4FF", + "#000000" + ], + "cswap": [ + "#BB8BFF", + "#000000" + ], + "ccswap": [ + "#BB8BFF", + "#000000" + ], + "dcx": [ + "#6FA4FF", + "#000000" + ], + "cdcx": [ + "#BB8BFF", + "#000000" + ], + "ccdcx": [ + "#BB8BFF", + "#000000" + ], + "iswap": [ + "#6FA4FF", + "#000000" + ], + "s": [ + "#6FA4FF", + "#000000" + ], + "sdg": [ + "#6FA4FF", + "#000000" + ], + "t": [ + "#BB8BFF", + "#000000" + ], + "tdg": [ + "#BB8BFF", + "#000000" + ], + "sx": [ + "#BB8BFF", + "#000000" + ], + "sxdg": [ + "#BB8BFF", + "#000000" + ], + "r": [ + "#BB8BFF", + "#000000" + ], + "rx": [ + "#BB8BFF", + "#000000" + ], + "ry": [ + "#BB8BFF", + "#000000" + ], + "rz": [ + "#BB8BFF", + "#000000" + ], + "rxx": [ + "#BB8BFF", + "#000000" + ], + "ryy": [ + "#BB8BFF", + "#000000" + ], + "rzx": [ + "#BB8BFF", + "#000000" + ], + "reset": [ + "#000000", + "#FFFFFF" + ], + "target": [ + "#FFFFFF", + "#FFFFFF" + ], + "measure": [ + "#000000", + "#FFFFFF" + ] + } +} \ No newline at end of file diff --git a/qiskit/visualization/styles/iqx.json b/qiskit/visualization/styles/iqx.json new file mode 100644 index 000000000000..b9fc41ee6baa --- /dev/null +++ b/qiskit/visualization/styles/iqx.json @@ -0,0 +1,213 @@ +{ + "name": "iqx", + "textcolor": "#000000", + "gatetextcolor": "#FFFFFF", + "subtextcolor": "#FFFFFF", + "linecolor": "#000000", + "creglinecolor": "#778899", + "gatefacecolor": "#9F1853", + "barrierfacecolor": "#A8A8A8", + "backgroundcolor": "#FFFFFF", + "edgecolor": null, + "fontsize": 13, + "subfontsize": 8, + "showindex": false, + "figwidth": -1, + "dpi": 150, + "margin": [ + 2.0, + 0.1, + 0.1, + 0.3 + ], + "creglinestyle": "doublet", + "displaytext": { + "u1": "$\\mathrm{U}_1$", + "u2": "$\\mathrm{U}_2$", + "u3": "$\\mathrm{U}_3$", + "u": "U", + "p": "P", + "id": "I", + "x": "X", + "y": "Y", + "z": "Z", + "h": "H", + "s": "S", + "sdg": "$\\mathrm{S}^\\dagger$", + "sx": "$\\sqrt{\\mathrm{X}}$", + "sxdg": "$\\sqrt{\\mathrm{X}}^\\dagger$", + "t": "T", + "tdg": "$\\mathrm{T}^\\dagger$", + "dcx": "Dcx", + "iswap": "Iswap", + "ms": "MS", + "r": "R", + "rx": "$\\mathrm{R}_\\mathrm{X}$", + "ry": "$\\mathrm{R}_\\mathrm{Y}$", + "rz": "$\\mathrm{R}_\\mathrm{Z}$", + "rxx": "$\\mathrm{R}_{\\mathrm{XX}}$", + "ryy": "$\\mathrm{R}_{\\mathrm{YY}}$", + "rzx": "$\\mathrm{R}_{\\mathrm{ZX}}$", + "rzz": "$\\mathrm{R}_{\\mathrm{ZZ}}$", + "reset": "$\\left|0\\right\\rangle$", + "initialize": "$|\\psi\\rangle$" + }, + "displaycolor": { + "u1": [ + "#33B1FF", + "#000000" + ], + "u2": [ + "#9F1853", + "#FFFFFF" + ], + "u3": [ + "#9F1853", + "#FFFFFF" + ], + "u": [ + "#9F1853", + "#FFFFFF" + ], + "p": [ + "#33B1FF", + "#000000" + ], + "id": [ + "#002D9C", + "#FFFFFF" + ], + "x": [ + "#002D9C", + "#FFFFFF" + ], + "y": [ + "#9F1853", + "#FFFFFF" + ], + "z": [ + "#33B1FF", + "#000000" + ], + "h": [ + "#FA4D56", + "#000000" + ], + "cx": [ + "#002D9C", + "#000000" + ], + "ccx": [ + "#002D9C", + "#000000" + ], + "mcx": [ + "#002D9C", + "#000000" + ], + "mcx_gray": [ + "#002D9C", + "#000000" + ], + "cy": [ + "#9F1853", + "#FFFFFF" + ], + "cz": [ + "#9F1853", + "#FFFFFF" + ], + "swap": [ + "#002D9C", + "#000000" + ], + "cswap": [ + "#002D9C", + "#000000" + ], + "ccswap": [ + "#002D9C", + "#000000" + ], + "dcx": [ + "#002D9C", + "#FFFFFF" + ], + "cdcx": [ + "#002D9C", + "#FFFFFF" + ], + "ccdcx": [ + "#002D9C", + "#FFFFFF" + ], + "iswap": [ + "#33B1FF", + "#000000" + ], + "s": [ + "#33B1FF", + "#000000" + ], + "sdg": [ + "#33B1FF", + "#000000" + ], + "t": [ + "#33B1FF", + "#000000" + ], + "tdg": [ + "#33B1FF", + "#000000" + ], + "sx": [ + "#9F1853", + "#FFFFFF" + ], + "sxdg": [ + "#9F1853", + "#FFFFFF" + ], + "r": [ + "#9F1853", + "#FFFFFF" + ], + "rx": [ + "#9F1853", + "#FFFFFF" + ], + "ry": [ + "#9F1853", + "#FFFFFF" + ], + "rz": [ + "#9F1853", + "#FFFFFF" + ], + "rxx": [ + "#9F1853", + "#FFFFFF" + ], + "ryy": [ + "#9F1853", + "#FFFFFF" + ], + "rzx": [ + "#9F1853", + "#FFFFFF" + ], + "reset": [ + "#A8A8A8", + "#000000" + ], + "target": [ + "#FFFFFF", + "#FFFFFF" + ], + "measure": [ + "#A8A8A8", + "#000000" + ] + } +} \ No newline at end of file diff --git a/releasenotes/notes/load-user-style-json-files-823590b03f015e4b.yaml b/releasenotes/notes/load-user-style-json-files-823590b03f015e4b.yaml new file mode 100644 index 000000000000..728198e5b8f5 --- /dev/null +++ b/releasenotes/notes/load-user-style-json-files-823590b03f015e4b.yaml @@ -0,0 +1,23 @@ +--- +fixes: + - | + The documentation for the :class:`~qiskit.circuit.QuantumCircuit` method + :meth:`~qiskit.circuit.QuantumCircuit.draw` and the + :func:`~qiskit.visualization.circuit_drawer` function were out-of-sync with + the state of the code. The documentation has been brought up-to-date. As + part of this update, 3 elements of the `mpl` drawer `style` parameter dictionary + have been removed since they were not implemented in the code and not needed. + These are `latexdrawerstyle`, `usepiformat`, and `compress`. +features: + - | + In previous versions of qiskit, there was a rudimentary functionality that + allowed users to load an `mpl` drawer `style` dictionary from a JSON file in + order to customize the colors and other display features of the `mpl` drawer. + This capability has now been expanded so that all `style` dictionaries are + loaded from JSON files, and users can copy and customize the standard style + JSON files included with qiskit - `default.json`, `iqx.json`, and `bw.json`. + Users can indicate the path to be searched for any user style JSON files by + setting ``circuit_mpl_style_path`` under the [Default] heading in the file + ``settings.conf`` in the ``~/.qiskit`` directory. Path entries should be + separated by `:`. For example, + ``circuit_mpl_style_path = ~/.qiskit:~/user_styles`` diff --git a/test/ipynb/mpl/references/bw.png b/test/ipynb/mpl/references/bw.png new file mode 100644 index 000000000000..56b2ce75abd2 Binary files /dev/null and b/test/ipynb/mpl/references/bw.png differ diff --git a/test/ipynb/mpl/references/iqx_color.png b/test/ipynb/mpl/references/iqx_color.png index 2bf9909993a8..7f7201c65b4a 100644 Binary files a/test/ipynb/mpl/references/iqx_color.png and b/test/ipynb/mpl/references/iqx_color.png differ diff --git a/test/ipynb/mpl/references/partial_layout.png b/test/ipynb/mpl/references/partial_layout.png index 86c77b57e4ea..09374d53a3ef 100644 Binary files a/test/ipynb/mpl/references/partial_layout.png and b/test/ipynb/mpl/references/partial_layout.png differ diff --git a/test/ipynb/mpl/references/reverse_bits.png b/test/ipynb/mpl/references/reverse_bits.png new file mode 100644 index 000000000000..05d3a7f26d8c Binary files /dev/null and b/test/ipynb/mpl/references/reverse_bits.png differ diff --git a/test/ipynb/mpl/references/subfont.png b/test/ipynb/mpl/references/subfont.png new file mode 100644 index 000000000000..ea4ebb279c56 Binary files /dev/null and b/test/ipynb/mpl/references/subfont.png differ diff --git a/test/ipynb/mpl/references/user_style.png b/test/ipynb/mpl/references/user_style.png new file mode 100644 index 000000000000..a114e413ccf5 Binary files /dev/null and b/test/ipynb/mpl/references/user_style.png differ diff --git a/test/ipynb/mpl/test_circuit_matplotlib_drawer.py b/test/ipynb/mpl/test_circuit_matplotlib_drawer.py index ea51459da596..87624219b74b 100644 --- a/test/ipynb/mpl/test_circuit_matplotlib_drawer.py +++ b/test/ipynb/mpl/test_circuit_matplotlib_drawer.py @@ -349,7 +349,7 @@ def test_partial_layout(self): circuit = QuantumCircuit(3) circuit.h(1) transpiled = transpile(circuit, backend=FakeTenerife(), - optimization_level=0, initial_layout=list(range(3)), + optimization_level=0, initial_layout=[1, 2, 0], seed_transpiler=0) self.circuit_drawer(transpiled, filename='partial_layout.png') @@ -401,6 +401,70 @@ def test_iqx_colors(self): self.circuit_drawer(circuit, style={'name': 'iqx'}, filename='iqx_color.png') + def test_reverse_bits(self): + """Tests reverse_bits parameter""" + circuit = QuantumCircuit(3) + circuit.h(0) + circuit.cx(0, 1) + circuit.ccx(2, 1, 0) + + self.circuit_drawer(circuit, reverse_bits=True, filename='reverse_bits.png') + + def test_bw(self): + """Tests black and white style parameter""" + circuit = QuantumCircuit(3, 3) + circuit.h(0) + circuit.x(1) + circuit.sdg(2) + circuit.cx(0, 1) + circuit.ccx(2, 1, 0) + circuit.swap(1, 2) + circuit.measure_all() + + self.circuit_drawer(circuit, style={'name': 'bw'}, filename='bw.png') + + def test_user_style(self): + """Tests loading a user style""" + circuit = QuantumCircuit(7) + circuit.h(0) + circuit.x(0) + circuit.cx(0, 1) + circuit.ccx(0, 1, 2) + circuit.swap(0, 1) + circuit.cswap(0, 1, 2) + circuit.append(SwapGate().control(2), [0, 1, 2, 3]) + circuit.dcx(0, 1) + circuit.append(DCXGate().control(1), [0, 1, 2]) + circuit.append(DCXGate().control(2), [0, 1, 2, 3]) + circuit.z(4) + circuit.s(4) + circuit.sdg(4) + circuit.t(4) + circuit.tdg(4) + circuit.p(pi/2, 4) + circuit.u1(pi/2, 4) + circuit.cz(5, 6) + circuit.cu1(pi/2, 5, 6) + circuit.y(5) + circuit.rx(pi/3, 5) + circuit.rzx(pi/2, 5, 6) + circuit.u2(pi/2, pi/2, 5) + circuit.barrier(5, 6) + circuit.reset(5) + + self.circuit_drawer(circuit, style={'name': 'user_style'}, filename='user_style.png') + + def test_subfont_change(self): + """Tests changing the subfont size""" + + circuit = QuantumCircuit(3) + circuit.h(0) + circuit.x(0) + circuit.u(pi/2, pi/2, pi/2, 1) + circuit.p(pi/2, 2) + self.circuit_drawer(circuit, style={'name': 'iqx', 'subfontsize': 11}, + filename='subfont.png') + if __name__ == '__main__': unittest.main(verbosity=1) diff --git a/test/ipynb/mpl/user_style.json b/test/ipynb/mpl/user_style.json new file mode 100644 index 000000000000..2ad603c5ac97 --- /dev/null +++ b/test/ipynb/mpl/user_style.json @@ -0,0 +1,213 @@ +{ + "name": "user_style1", + "textcolor": "#000000", + "gatetextcolor": "#0000FF", + "subtextcolor": "#FFFFFF", + "linecolor": "#223344", + "creglinecolor": "#667799", + "gatefacecolor": "#666600", + "barrierfacecolor": "#A8A8A8", + "backgroundcolor": "#DDDDDD", + "edgecolor": null, + "fontsize": 13, + "subfontsize": 8, + "showindex": true, + "figwidth": -1, + "dpi": 150, + "margin": [ + 2.0, + 0.5, + 0.1, + 0.3 + ], + "creglinestyle": "doublet", + "displaytext": { + "u1": "$\\mathrm{U}_1$", + "u2": "$\\mathrm{U}_2$", + "u3": "$\\mathrm{U}_3$", + "u": "U", + "p": "Phase", + "id": "I", + "x": "X", + "y": "Y", + "z": "Z", + "h": "H", + "s": "S", + "sdg": "$\\mathrm{S}^\\dagger$", + "sx": "$\\sqrt{\\mathrm{X}}$", + "sxdg": "$\\sqrt{\\mathrm{X}}^\\dagger$", + "t": "T", + "tdg": "$\\mathrm{T}^\\dagger$", + "dcx": "Dcx", + "iswap": "Iswap", + "ms": "MS", + "r": "R", + "rx": "$\\mathrm{R}_\\mathrm{X}$", + "ry": "$\\mathrm{R}_\\mathrm{Y}$", + "rz": "$\\mathrm{R}_\\mathrm{Z}$", + "rxx": "$\\mathrm{R}_{\\mathrm{XX}}$", + "ryy": "$\\mathrm{R}_{\\mathrm{YY}}$", + "rzx": "$\\mathrm{R}_{\\mathrm{ZX}}$", + "rzz": "$\\mathrm{R}_{\\mathrm{ZZ}}$", + "reset": "$\\left|0\\right\\rangle$", + "initialize": "$|\\psi\\rangle$" + }, + "displaycolor": { + "u1": [ + "#33B1FF", + "#000000" + ], + "u2": [ + "#9F1853", + "#FFFFFF" + ], + "u3": [ + "#9F1853", + "#FFFFFF" + ], + "u": [ + "#9F1853", + "#FFFFFF" + ], + "p": [ + "#33B1FF", + "#000000" + ], + "id": [ + "#002D9C", + "#FFFFFF" + ], + "x": [ + "#00FF00", + "#000000" + ], + "y": [ + "#00FF00", + "#000000" + ], + "z": [ + "#00FF00", + "#000000" + ], + "h": [ + "#FA4D56", + "#000000" + ], + "cx": [ + "#002D9C", + "#000000" + ], + "ccx": [ + "#002D9C", + "#000000" + ], + "mcx": [ + "#002D9C", + "#000000" + ], + "mcx_gray": [ + "#002D9C", + "#000000" + ], + "cy": [ + "#9F1853", + "#FFFFFF" + ], + "cz": [ + "#9F1853", + "#FFFFFF" + ], + "swap": [ + "#FF0000", + "#000000" + ], + "cswap": [ + "#FF0000", + "#000000" + ], + "ccswap": [ + "#002D9C", + "#000000" + ], + "dcx": [ + "#002D9C", + "#FFFFFF" + ], + "cdcx": [ + "#002D9C", + "#FFFFFF" + ], + "ccdcx": [ + "#FF3333", + "#000000" + ], + "iswap": [ + "#33B1FF", + "#000000" + ], + "s": [ + "#33B1FF", + "#000000" + ], + "sdg": [ + "#33B1FF", + "#000000" + ], + "t": [ + "#33B1FF", + "#000000" + ], + "tdg": [ + "#33B1FF", + "#000000" + ], + "sx": [ + "#9F1853", + "#FFFFFF" + ], + "sxdg": [ + "#9F1853", + "#FFFFFF" + ], + "r": [ + "#9F1853", + "#FFFFFF" + ], + "rx": [ + "#FF3333", + "#000000" + ], + "ry": [ + "#9F1853", + "#FFFFFF" + ], + "rz": [ + "#9F1853", + "#FFFFFF" + ], + "rxx": [ + "#aabbcc", + "#000000" + ], + "ryy": [ + "#aabbcc", + "#000000" + ], + "rzx": [ + "#aabbcc", + "#000000" + ], + "reset": [ + "#A8A8A8", + "#000000" + ], + "target": [ + "#FFFFFF", + "#FFFFFF" + ], + "measure": [ + "#A8A8A8", + "#000000" + ] + } +} \ No newline at end of file diff --git a/test/python/test_user_config.py b/test/python/test_user_config.py index fa38d1daab57..bf0b14b744b4 100644 --- a/test/python/test_user_config.py +++ b/test/python/test_user_config.py @@ -59,7 +59,6 @@ def test_invalid_circuit_drawer(self): test_config = """ [default] circuit_drawer = MSPaint - circuit_mpl_style = default """ self.addCleanup(os.remove, self.file_path) with open(self.file_path, 'w') as file: @@ -73,7 +72,6 @@ def test_circuit_drawer_valid(self): test_config = """ [default] circuit_drawer = latex - circuit_mpl_style = default """ self.addCleanup(os.remove, self.file_path) with open(self.file_path, 'w') as file: @@ -81,8 +79,8 @@ def test_circuit_drawer_valid(self): file.flush() config = user_config.UserConfig(self.file_path) config.read_config_file() - self.assertEqual({'circuit_drawer': 'latex', - 'circuit_mpl_style': 'default'}, config.settings) + self.assertEqual({'circuit_drawer': 'latex'}, + config.settings) def test_optimization_level_valid(self): test_config = """ @@ -131,6 +129,7 @@ def test_all_options_valid(self): [default] circuit_drawer = latex circuit_mpl_style = default + circuit_mpl_style_path = ~:~/.qiskit transpile_optimization_level = 3 suppress_packaging_warnings = true """ @@ -142,6 +141,7 @@ def test_all_options_valid(self): config.read_config_file() self.assertEqual({'circuit_drawer': 'latex', 'circuit_mpl_style': 'default', + 'circuit_mpl_style_path': ['~', '~/.qiskit'], 'transpile_optimization_level': 3, 'suppress_packaging_warnings': True}, config.settings)