Skip to content

Commit

Permalink
bug loading MPL style from the configuration (#11750)
Browse files Browse the repository at this point in the history
* config path fixing

* reno

* add test

* temp file creation

* Avoid using more internal details in style test

---------

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
(cherry picked from commit 19c15b7)

# Conflicts:
#	qiskit/visualization/circuit/qcstyle.py
#	test/python/visualization/test_circuit_drawer.py
  • Loading branch information
1ucian0 authored and mergify[bot] committed May 28, 2024
1 parent 0c6f85f commit 36f10d9
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 2 deletions.
72 changes: 72 additions & 0 deletions qiskit/visualization/circuit/qcstyle.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,3 +418,75 @@ def set_style(current_style, new_style):
UserWarning,
2,
)
<<<<<<< HEAD
=======
style_name = "default"

if style_name in ["iqp", "default"]:
current_style = DefaultStyle().style
else:
# Search for file in 'styles' dir, then config_path, and finally the current directory
style_name = style_name + ".json"
style_paths = []

default_path = Path(__file__).parent / "styles" / style_name
style_paths.append(default_path)

# check configured paths, if there are any
if config:
config_path = config.get("circuit_mpl_style_path", "")
if config_path:
for path in config_path:
style_paths.append(Path(path) / style_name)

# check current directory
cwd_path = Path("") / style_name
style_paths.append(cwd_path)

for path in style_paths:
# expand ~ to the user directory and check if the file exists
exp_user = path.expanduser()
if os.path.isfile(exp_user):
try:
with open(exp_user) as infile:
json_style = json.load(infile)

current_style = StyleDict(json_style)
break
except json.JSONDecodeError as err:
warn(
f"Could not decode JSON in file '{path}': {str(err)}. "
"Will use default style.",
UserWarning,
2,
)
break
except (OSError, FileNotFoundError):
warn(
f"Error loading JSON file '{path}'. Will use default style.",
UserWarning,
2,
)
break
else:
warn(
f"Style JSON file '{style_name}' not found in any of these locations: "
f"{', '.join(map(str, style_paths))}. "
"Will use default style.",
UserWarning,
2,
)
current_style = DefaultStyle().style

# if the style is a dictionary, update the defaults with the new values
# this _needs_ to happen after loading by name to cover cases like
# style = {"name": "bw", "edgecolor": "#FF0000"}
if isinstance(style, dict):
current_style.update(style)

# this is the default font ratio
# if the font- or subfont-sizes are changed, the new size is based on this ratio
def_font_ratio = 13 / 8

return current_style, def_font_ratio
>>>>>>> 19c15b749 (bug loading MPL style from the configuration (#11750))
13 changes: 13 additions & 0 deletions qiskit/visualization/circuit/styles/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2014.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""Empty init for data directory."""
4 changes: 4 additions & 0 deletions releasenotes/notes/fix_11536-c87d192a133b3dc3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
fixes:
- |
A bug when loading MPL style from the configuration was fixed.
43 changes: 41 additions & 2 deletions test/python/visualization/test_circuit_drawer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,22 @@

# pylint: disable=missing-docstring

import unittest
import os
<<<<<<< HEAD
=======
import pathlib
import shutil
import tempfile
import unittest
import warnings
>>>>>>> 19c15b749 (bug loading MPL style from the configuration (#11750))
from unittest.mock import patch

from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.test import QiskitTestCase
from qiskit.utils import optionals
from qiskit import visualization
from qiskit.visualization.circuit import text
from qiskit.visualization.circuit import text, styles
from qiskit.visualization.exceptions import VisualizationError

if optionals.HAS_MATPLOTLIB:
Expand Down Expand Up @@ -49,6 +56,38 @@ def test_default_output(self):
out = visualization.circuit_drawer(circuit)
self.assertIsInstance(out, text.TextDrawing)

@unittest.skipUnless(optionals.HAS_MATPLOTLIB, "Skipped because matplotlib is not available")
def test_mpl_config_with_path(self):
# It's too easy to get too nested in a test with many context managers.
tempdir = tempfile.TemporaryDirectory() # pylint: disable=consider-using-with
self.addCleanup(tempdir.cleanup)

clifford_style = pathlib.Path(styles.__file__).parent / "clifford.json"
shutil.copyfile(clifford_style, pathlib.Path(tempdir.name) / "my_clifford.json")

circuit = QuantumCircuit(1)
circuit.h(0)

def config(style_name):
return {
"circuit_drawer": "mpl",
"circuit_mpl_style": style_name,
"circuit_mpl_style_path": [tempdir.name],
}

with warnings.catch_warnings():
warnings.filterwarnings("error", message="Style JSON file.*not found")

# Test that a non-standard style can be loaded by name.
with patch("qiskit.user_config.get_config", return_value=config("my_clifford")):
self.assertIsInstance(visualization.circuit_drawer(circuit), figure.Figure)

# Test that a non-existent style issues a warning, but still draws something.
with patch("qiskit.user_config.get_config", return_value=config("NONEXISTENT")):
with self.assertWarnsRegex(UserWarning, "Style JSON file.*not found"):
fig = visualization.circuit_drawer(circuit)
self.assertIsInstance(fig, figure.Figure)

@unittest.skipUnless(optionals.HAS_MATPLOTLIB, "Skipped because matplotlib is not available")
def test_user_config_default_output(self):
with patch("qiskit.user_config.get_config", return_value={"circuit_drawer": "mpl"}):
Expand Down

0 comments on commit 36f10d9

Please sign in to comment.