Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add matplotlib style configuration for circuit drawing #1811

Merged
merged 61 commits into from
Dec 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
bef8060
add mpl drawer styles
albi3ro Oct 27, 2021
0384d9c
Merge branch 'master' into drawer_styles
albi3ro Nov 9, 2021
6e5a4e3
inverted style, tests
albi3ro Nov 9, 2021
1f71430
Merge branch 'master' into drawer_styles
albi3ro Nov 15, 2021
cd694dc
Merge branch 'master' into drawer_styles
albi3ro Nov 16, 2021
aa11e19
Merge branch 'master' into drawer_styles
albi3ro Nov 18, 2021
23796d5
Merge branch 'master' into drawer_styles
albi3ro Nov 18, 2021
d9084a9
dark own function, docs
albi3ro Nov 19, 2021
682451a
Merge branch 'master' into drawer_styles
albi3ro Nov 19, 2021
b00d86d
doc for available attribute
albi3ro Nov 19, 2021
e6cb360
Merge branch 'master' into drawer_styles
albi3ro Nov 23, 2021
69aa552
renaming, black, tests
albi3ro Nov 23, 2021
42adc1b
reset styles at end of tests
albi3ro Nov 23, 2021
7d3eacc
fix documentation
albi3ro Nov 23, 2021
3648b6f
changelog
albi3ro Nov 23, 2021
3acc771
Merge branch 'master' into drawer_styles
Jaybsoni Nov 24, 2021
8ac6424
Merge branch 'master' into drawer_styles
albi3ro Nov 25, 2021
93910e3
Merge branch 'master' into drawer_styles
Jaybsoni Nov 26, 2021
2e27556
styles to style, add use and context functions
albi3ro Nov 26, 2021
5c4d206
Merge branch 'drawer_styles' of https://github.com/PennyLaneAI/pennyl…
albi3ro Nov 26, 2021
239f2ba
Merge branch 'master' into drawer_styles
Jaybsoni Nov 29, 2021
bf8f4d7
structural changes
albi3ro Nov 29, 2021
d10ee07
Merge branch 'drawer_styles' of https://github.com/PennyLaneAI/pennyl…
albi3ro Nov 29, 2021
66f9ed0
merge
albi3ro Nov 30, 2021
5188ceb
Merge branch 'master' into drawer_styles
albi3ro Nov 30, 2021
6b1e5a9
some doc changes
albi3ro Dec 1, 2021
3ba7dee
merge master
albi3ro Dec 1, 2021
4eb731c
change the api again
albi3ro Dec 1, 2021
2666454
did that fix the problem?
albi3ro Dec 1, 2021
cf72baf
Merge branch 'master' into drawer_styles
albi3ro Dec 1, 2021
8cbe404
tests, more docs
albi3ro Dec 1, 2021
1dbe78f
Merge branch 'master' into drawer_styles
albi3ro Dec 1, 2021
4de1eee
trying something else
albi3ro Dec 1, 2021
65d88d6
Merge branch 'master' into drawer_styles
albi3ro Dec 1, 2021
daff796
Merge branch 'master' into drawer_styles
albi3ro Dec 2, 2021
f54bdcc
trying something else
albi3ro Dec 2, 2021
aa81454
Merge branch 'master' into drawer_styles
albi3ro Dec 2, 2021
19ea66f
Merge branch 'master' into drawer_styles
albi3ro Dec 2, 2021
f24ea26
trying this instead
albi3ro Dec 2, 2021
27a9365
images in a table
albi3ro Dec 2, 2021
0f40f13
remove image scaling, add title to graphs
albi3ro Dec 2, 2021
2091844
Merge branch 'master' into drawer_styles
albi3ro Dec 2, 2021
6d4efe0
hopefully this finally works
albi3ro Dec 2, 2021
6db4256
I do not understand how width works
albi3ro Dec 2, 2021
c8eceb3
size tables the same , test coverage
albi3ro Dec 2, 2021
a9655c1
Merge branch 'master' into drawer_styles
albi3ro Dec 2, 2021
29d1a2d
fix test, black
albi3ro Dec 2, 2021
e2f248f
Merge branch 'master' into drawer_styles
albi3ro Dec 2, 2021
75560c5
Merge branch 'master' into drawer_styles
Jaybsoni Dec 2, 2021
5e2e238
Merge branch 'master' into drawer_styles
Jaybsoni Dec 2, 2021
582ee74
Merge branch 'master' into drawer_styles
Jaybsoni Dec 2, 2021
f9df22d
Update pennylane/drawer/tape_mpl.py
albi3ro Dec 3, 2021
12d72a0
Merge branch 'master' into drawer_styles
albi3ro Dec 3, 2021
8790b99
improved phrasing
albi3ro Dec 3, 2021
03ef9f4
Merge branch 'drawer_styles' of https://github.com/PennyLaneAI/pennyl…
albi3ro Dec 3, 2021
8a55ddd
more docstring changes
albi3ro Dec 3, 2021
875eedd
Merge branch 'master' into drawer_styles
albi3ro Dec 3, 2021
5fa9f1f
Merge branch 'master' into drawer_styles
albi3ro Dec 3, 2021
fb9fb65
updated images
albi3ro Dec 3, 2021
ba5224b
more image fixing
albi3ro Dec 3, 2021
386e9b7
Merge branch 'master' into drawer_styles
Jaybsoni Dec 3, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed doc/_static/draw_mpl/Solarize_Light2.png
Binary file not shown.
Binary file added doc/_static/draw_mpl/black_white_style.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 20 additions & 11 deletions doc/_static/draw_mpl/draw_mpl_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,23 +71,32 @@ def postprocessing(circuit):
plt.close()

def rcparams(circuit):
plt.rcParams['patch.facecolor'] = 'white'
plt.rcParams['patch.edgecolor'] = 'black'
plt.rcParams['patch.linewidth'] = 2
plt.rcParams['patch.facecolor'] = 'mistyrose'
plt.rcParams['patch.edgecolor'] = 'maroon'
plt.rcParams['text.color'] = 'maroon'
plt.rcParams['font.weight'] = 'bold'
plt.rcParams['patch.linewidth'] = 4
plt.rcParams['patch.force_edgecolor'] = True
plt.rcParams['lines.color'] = 'black'
plt.rcParams['lines.color'] = 'indigo'
plt.rcParams['lines.linewidth'] = 5
plt.rcParams['figure.facecolor'] = 'ghostwhite'

fig, ax = draw_mpl(circuit)(1.2345,1.2345)

fig, ax = qml.draw_mpl(circuit)(1.2345,1.2345)

plt.savefig(folder / "rcparams.png")
plt.close()
plt.style.use('default')

def Solarize_Light2(circuit):
with plt.style.context("Solarize_Light2"):
fig, ax = draw_mpl(circuit)(1.2345,1.2345)
plt.savefig(folder / "Solarize_Light2.png")
plt.close()
def use_style(circuit):

qml.drawer.use_style('black_white')

fig, ax = qml.draw_mpl(circuit)(1.2345,1.2345)

plt.savefig(folder / "black_white_style.png")
plt.close()
plt.style.use('default')

def wires_labels(circuit):
fig, ax = draw_mpl(circuit, wire_options={'color':'black', 'linewidth': 5},
Expand All @@ -114,6 +123,6 @@ def circuit(x, z):
wire_order(circuit)
show_all_wires(circuit)
postprocessing(circuit)
use_style(circuit)
rcparams(circuit)
Solarize_Light2(circuit)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rip solarize_light2

wires_labels(circuit)
Binary file modified doc/_static/draw_mpl/rcparams.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed doc/_static/drawer/SWAP_formatted.png
Binary file not shown.
Binary file added doc/_static/drawer/black_white_style.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed doc/_static/drawer/example_Solarize_Light2.png
Binary file not shown.
Binary file modified doc/_static/drawer/example_rcParams.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed doc/_static/drawer/measure_formatted.png
Binary file not shown.
27 changes: 16 additions & 11 deletions doc/_static/drawer/mpldrawer_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import pathlib
import matplotlib.pyplot as plt

from pennylane.drawer import MPLDrawer
from pennylane.drawer import MPLDrawer, use_style

folder = pathlib.Path(__file__).parent

Expand Down Expand Up @@ -123,7 +123,7 @@ def measure(savefile="measure.png"):
plt.close()

def integration(style="default", savefile="example_basic.png"):
plt.style.use(style)
use_style(style)
drawer = MPLDrawer(n_wires=5, n_layers=6)

drawer.label(["0", "a", r"$|\Psi\rangle$", r"$|\theta\rangle$", "aux"])
Expand Down Expand Up @@ -152,23 +152,28 @@ def integration(style="default", savefile="example_basic.png"):


def integration_rcParams(savefile="example_rcParams.png"):
plt.rcParams["patch.facecolor"] = "white"
plt.rcParams["patch.edgecolor"] = "black"
plt.rcParams["patch.linewidth"] = 2
plt.rcParams["patch.force_edgecolor"] = True

plt.rcParams["lines.color"] = "black"
plt.rcParams['patch.facecolor'] = 'mistyrose'
plt.rcParams['patch.edgecolor'] = 'maroon'
plt.rcParams['text.color'] = 'maroon'
plt.rcParams['font.weight'] = 'bold'
plt.rcParams['patch.linewidth'] = 4
plt.rcParams['patch.force_edgecolor'] = True
plt.rcParams['lines.color'] = 'indigo'
plt.rcParams['lines.linewidth'] = 5
plt.rcParams['figure.facecolor'] = 'ghostwhite'

drawer = MPLDrawer(n_wires=5, n_layers=5)

drawer = MPLDrawer(n_wires=5, n_layers=6)

drawer.label(["0", "a", r"$|\Psi\rangle$", r"$|\theta\rangle$", "aux"])

drawer.box_gate(0, [0, 1, 2, 3, 4], "Entangling Layers")
drawer.box_gate(1, [0, 1], "U(θ)")
drawer.box_gate(1, [0, 2, 3], "U(θ)")

drawer.box_gate(1, 4, "Z")

drawer.SWAP(1, (2, 3))
drawer.SWAP(2, (3,4))
drawer.CNOT(2, (0, 2))

drawer.ctrl(3, [1, 3], control_values=[True, False])
Expand Down Expand Up @@ -241,6 +246,6 @@ def float_layer(savefile="float_layer.png"):
measure()
integration()
float_layer()
integration(style="Solarize_Light2", savefile="example_Solarize_Light2.png")
integration(style="black_white", savefile="black_white_style.png")
integration_rcParams()
integration_formatted()
Binary file added doc/_static/style/black_white_dark_style.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/_static/style/black_white_style.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/_static/style/default_style.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 52 additions & 0 deletions doc/_static/style/style_examples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright 2018-2021 Xanadu Quantum Technologies Inc.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
This file automatically generates and saves a series of example pictures for the
circuit drawer. This will be useful during early stages when the project is still
undergoing cosmetic changes.
"""

import pathlib
import matplotlib.pyplot as plt

import pennylane as qml
import matplotlib.pyplot as plt

folder = pathlib.Path(__file__).parent

def make_imag(circuit, style):
qml.drawer.use_style(style)

fig, ax = qml.draw_mpl(circuit)(1.2345,1.2345)
fig.suptitle(style, fontsize='xx-large')

plt.savefig(folder / (style + "_style.png"))
plt.close()
qml.drawer.use_style('default')

if __name__ == "__main__":

dev = qml.device('lightning.qubit', wires=(0,1,2,3))
@qml.qnode(dev)
def circuit(x, z):
qml.QFT(wires=(0,1,2,3))
qml.Toffoli(wires=(0,1,2))
qml.CSWAP(wires=(0,2,3))
qml.RX(x, wires=0)
qml.CRZ(z, wires=(3,0))
return qml.expval(qml.PauliZ(0))

for style in qml.drawer.available_styles():
make_imag(circuit, style)

Binary file added doc/_static/tape_mpl/black_white_style.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/_static/tape_mpl/rcparams.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 19 additions & 12 deletions doc/_static/tape_mpl/tape_mpl_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,27 +59,34 @@ def show_all_wires(tape):
plt.savefig(folder / "show_all_wires.png")
plt.close()

def mpl_style(tape):

with plt.style.context("Solarize_Light2"):
fig, ax = tape_mpl(tape)
plt.savefig(folder/"Solarize_Light2.png")
plt.close()

def rcparams(tape):

plt.rcParams['patch.facecolor'] = 'white'
plt.rcParams['patch.edgecolor'] = 'black'
plt.rcParams['patch.linewidth'] = 2
plt.rcParams['patch.facecolor'] = 'mistyrose'
plt.rcParams['patch.edgecolor'] = 'maroon'
plt.rcParams['text.color'] = 'maroon'
plt.rcParams['font.weight'] = 'bold'
plt.rcParams['patch.linewidth'] = 4
plt.rcParams['patch.force_edgecolor'] = True
plt.rcParams['lines.color'] = 'black'
plt.rcParams['lines.color'] = 'indigo'
plt.rcParams['lines.linewidth'] = 5
plt.rcParams['figure.facecolor'] = 'ghostwhite'

fig, ax = tape_mpl(tape)

plt.savefig(folder / "rcparams.png")
plt.close()
plt.style.use('default')

def use_style(tape):

qml.drawer.use_style('black_white')

fig, ax = tape_mpl(tape)

plt.savefig(folder / "black_white_style.png")
plt.close()
plt.style.use('default')

def wires_and_labels(tape):

fig, ax = tape_mpl(tape, wire_options={'color':'black', 'linewidth': 5},
Expand Down Expand Up @@ -118,7 +125,7 @@ def postprocessing(tape):
decimals()
wire_order(tape)
show_all_wires(tape)
mpl_style(tape)
use_style(tape)
rcparams(tape)
wires_and_labels(tape)
postprocessing(tape)
57 changes: 53 additions & 4 deletions doc/code/qml_drawer.rst
Original file line number Diff line number Diff line change
@@ -1,14 +1,63 @@
qml.drawer
==========

The ``drawer`` module contains the code for generating visuals
of circuits.

.. currentmodule:: pennylane.drawer

.. warning::
Styling Matplotlib Circuit Graphics
-----------------------------------

The ``drawer`` module provides two functions for modifying the style of matplotlib
graphics, such as those generated by ``qml.draw_mpl``. The ``qml.drawer.use_style``
function modifies the ``plt.rcParams`` global styling variable. Any styling can
be reset with ``qml.drawer.use_style('default')`` or ``plt.style.use('default')``.

.. autosummary::
:toctree: api

available_styles
use_style

The following images are generated via the code:

.. code-block:: python

@qml.qnode(qml.device('lightning.qubit', wires=(0,1,2,3)))
def circuit(x, z):
qml.QFT(wires=(0,1,2,3))
qml.Toffoli(wires=(0,1,2))
qml.CSWAP(wires=(0,2,3))
qml.RX(x, wires=0)
qml.CRZ(z, wires=(3,0))
return qml.expval(qml.PauliZ(0))

qml.drawer.use_style(style)
fig, ax = qml.draw_mpl(circuit)(1.2345, 1.2345)

Currently Available Styles
^^^^^^^^^^^^^^^^^^^^^^^^^^
.. |bws| image:: ../_static/style/black_white_style.png
:width: 100%

.. |bwd| image:: ../_static/style/black_white_dark_style.png
:width: 100%

.. |def| image:: ../_static/style/default_style.png
:width: 100%

+-----+-----+-----+
+|bws|+|bwd|+|def|+
+-----+-----+-----+


Unless you are a PennyLane or plugin developer, you likely do not need
to use these classes directly.
Developer Methods
-----------------

.. automodapi:: pennylane.drawer
:no-heading:
:no-inheritance-diagram:
:no-inherited-members:
:no-inherited-members:
:skip: available_styles
:skip: use_style
5 changes: 4 additions & 1 deletion doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@

* PennyLane now supports drawing a QNode with matplotlib!
[(#1803)](https://github.com/PennyLaneAI/pennylane/pull/1803)
[(#1811)](https://github.com/PennyLaneAI/pennylane/pull/1811)
[(#1954)](https://github.com/PennyLaneAI/pennylane/pull/1954)

```python
Expand All @@ -164,11 +165,13 @@
qml.RX(x, wires=0)
qml.CRZ(z, wires=(3,0))
return qml.expval(qml.PauliZ(0))

qml.drawer.use_style('black_white')
fig, ax = qml.draw_mpl(circuit)(1.2345, 1.2345)
fig.show()
```

<img src="https://pennylane.readthedocs.io/en/latest/_static/draw_mpl_qnode/main_example.png" width=70%/>
<img src="https://pennylane.readthedocs.io/en/latest/_static/draw_mpl/black_white_style.png" width=70%/>

* It is now possible to use TensorFlow's [AutoGraph
mode](https://www.tensorflow.org/guide/function) with QNodes on all devices and with arbitrary
Expand Down
4 changes: 2 additions & 2 deletions pennylane/drawer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""
This subpackage provides the circuit drawing functionality used to render QNodes
as circuit diagrams.
This module provides the circuit drawing functionality used to display circuits visually.

.. currentmodule:: pennylane.circuit_drawer
.. autosummary::
Expand All @@ -27,3 +26,4 @@
from .mpldrawer import MPLDrawer
from .drawable_layers import drawable_layers, drawable_grid
from .utils import convert_wire_order
from .style import available_styles, use_style
35 changes: 19 additions & 16 deletions pennylane/drawer/mpldrawer.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,33 +114,37 @@ class MPLDrawer:

**Formatting**

You can globally control the style with ``plt.rcParams`` and styles, see the
`matplotlib docs <https://matplotlib.org/stable/tutorials/introductory/customizing.html>`_ .
If we customize ``plt.rcParams`` before executing our example function, we get a
different style:
PennyLane has inbuilt styles for controlling the appearance of the circuit drawings.
All available styles can be determined by evaluating ``qml.drawer.available_styles()``.
Any available string can then be passed to ``qml.drawer.use_style``.

.. code-block:: python

plt.rcParams['patch.facecolor'] = 'white'
plt.rcParams['patch.edgecolor'] = 'black'
plt.rcParams['patch.linewidth'] = 2
plt.rcParams['patch.force_edgecolor'] = True
plt.rcParams['lines.color'] = 'black'
qml.drawer.use_style('black_white')

.. figure:: ../../_static/drawer/example_rcParams.png
.. figure:: ../../_static/drawer/black_white_style.png
:align: center
:width: 60%
:target: javascript:void(0);

Instead of manually customizing everything, you can choose one of
the provided styles. You can see available styles with ``plt.style.available``.
We can set the ``'Solarize_Light2'`` style with the same graph as drawn above and instead get:
You can also control the appearance with matplotlib's provided tools, see the
`matplotlib docs <https://matplotlib.org/stable/tutorials/introductory/customizing.html>`_ .
For example, we can customize ``plt.rcParams``:

.. code-block:: python

plt.style.use('Solarize_Light2')
plt.rcParams['patch.facecolor'] = 'mistyrose'
plt.rcParams['patch.edgecolor'] = 'maroon'
plt.rcParams['text.color'] = 'maroon'
plt.rcParams['font.weight'] = 'bold'
plt.rcParams['patch.linewidth'] = 4
plt.rcParams['patch.force_edgecolor'] = True
plt.rcParams['lines.color'] = 'indigo'
plt.rcParams['lines.linewidth'] = 5
plt.rcParams['figure.facecolor'] = 'ghostwhite'


.. figure:: ../../_static/drawer/example_Solarize_Light2.png
.. figure:: ../../_static/drawer/example_rcParams.png
:align: center
:width: 60%
:target: javascript:void(0);
Expand All @@ -151,7 +155,6 @@ class MPLDrawer:
to the dictionary controlling how to format a rectangle. For the control-type gates ``CNOT`` and
``ctrl`` the options dictionary can only contain ``'linewidth'``, ``'color'``, or ``'zorder'`` keys.


This example demonstrates the different ways you can format the individual elements:

.. code-block:: python
Expand Down
Loading