Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into prepare-0.9
Browse files Browse the repository at this point in the history
  • Loading branch information
mtreinish committed May 29, 2021
2 parents a8779f8 + aad90f7 commit 0efc2e6
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 45 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
toolchain: stable
- name: Install cibuildwheel
run: |
python -m pip install cibuildwheel==1.9.0 twine
python -m pip install cibuildwheel==1.11.1 twine
- name: Build wheels
run: |
python -m cibuildwheel --output-dir wheelhouse
Expand Down Expand Up @@ -73,7 +73,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Build wheels
uses: joerick/cibuildwheel@v1.9.0
uses: joerick/cibuildwheel@v1.11.1
env:
CIBW_BEFORE_ALL: rustup target add aarch64-apple-darwin
CIBW_ARCHS_MACOS: arm64 universal2
Expand Down Expand Up @@ -113,7 +113,7 @@ jobs:
run: rustup default stable-i686-pc-windows-msvc
- name: Install cibuildwheel
run: |
python -m pip install cibuildwheel==1.9.0 twine
python -m pip install cibuildwheel==1.11.1 twine
- name: Build wheels
run: |
python -m cibuildwheel --output-dir wheelhouse
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ retworkx/*pyd
*.stestr/
*.ps
*.png
*.svg
*.jpg
18 changes: 7 additions & 11 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ jobs:
- CIBW_BEFORE_BUILD="pip install -U setuptools-rust"
- CIBW_SKIP="cp27-* cp34-* cp35-* pp*"
- CIBW_ENVIRONMENT='PATH="$PATH:$HOME/.cargo/bin"'
- CIBW_TEST_REQUIRES=networkx testtools fixtures
- CIBW_TEST_REQUIRES="networkx testtools fixtures"
- TWINE_USERNAME=retworkx-ci
- CIBW_TEST_COMMAND="python -m unittest discover {project}/tests"
if: tag IS present
script:
- pip install -U twine importlib-metadata keyring cibuildwheel==1.9.0
- pip install -U twine importlib-metadata keyring cibuildwheel==1.11.1
- cibuildwheel --output-dir wheelhouse
- twine upload wheelhouse/*
- stage: deploy
Expand All @@ -80,24 +80,20 @@ jobs:
services:
- docker
before_install:
- which python
- sh tools/install_rust.sh
- export PATH=~/.cargo/bin:$PATH
- which python
- pip install -U pip virtualenv tox
- sudo chown travis -R $TRAVIS_HOME/.cargo
install:
- echo ""
env:
- CIBW_BEFORE_ALL="yum install -y wget && rm -rf rust-installer"
- CIBW_BEFORE_BUILD="bash {project}/tools/install_rust.sh"
- CIBW_SKIP="cp27-* cp34-* cp35-* pp*"
- CIBW_ENVIRONMENT='PATH="$PATH:$HOME/.cargo/bin"'
- CIBW_TEST_REQUIRES=networkx testtools fixtures
- CIBW_TEST_REQUIRES="networkx testtools fixtures"
- TWINE_USERNAME=retworkx-ci
- CIBW_TEST_COMMAND="python -m unittest discover {project}/tests"
if: tag IS present
script:
- pip install -U twine importlib-metadata keyring cibuildwheel==1.9.0
- pip install -U twine importlib-metadata keyring cibuildwheel==1.11.1
- cibuildwheel --output-dir wheelhouse
- twine upload wheelhouse/*
- stage: deploy
Expand All @@ -114,11 +110,11 @@ jobs:
- CIBW_BEFORE_BUILD="pip install -U setuptools-rust"
- CIBW_SKIP="cp27-* cp34-* cp35-* pp*"
- CIBW_ENVIRONMENT='PATH="$PATH:$HOME/.cargo/bin"'
- CIBW_TEST_REQUIRES=networkx testtools fixtures
- CIBW_TEST_REQUIRES="networkx testtools fixtures"
- TWINE_USERNAME=retworkx-ci
- CIBW_TEST_COMMAND="python -m unittest discover {project}/tests"
if: tag IS present
script:
- sudo pip install -U twine importlib-metadata keyring cibuildwheel==1.9.0
- sudo pip install -U twine importlib-metadata keyring cibuildwheel==1.11.1
- cibuildwheel --output-dir wheelhouse
- twine upload wheelhouse/*
2 changes: 2 additions & 0 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ type functions in the algorithms API but can be run with a
retworkx.random_layout
retworkx.spring_layout

.. _layout-functions:

Layout Functions
================

Expand Down
64 changes: 64 additions & 0 deletions docs/source/networkx.rst
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,70 @@ This difference with retworkx is primarily because numpy exposes a public C
interface which retworkx can interface with directly, while the other
libraries and types only expose Python APIs.

Visualization Functions
-----------------------

NetworkX provides a native drawer with a matplotlib drawer (the
``networkx_drawer*`` functions) and then functions to interface with
``pygraphviz`` and ``pydot`` to enable visualization with graphviz via those
libraries (in addition to functions to serialize graphs in formats other
graph visualization tools can use). NetworkX also provides several functions
`layout functions <https://networkx.org/documentation/stable/reference/drawing.html#module-networkx.drawing.layout>`__
for generating different layouts that can be used for visualizing the graph.


retworkx has drawer functions with 2 visualization backends, matplotlib
(:func:`~retworkx.visualization.mpl_draw`) and graphviz
(:func:`~retworkx.visualization.graphviz_draw`). Unlike networkx the
:func:`~retworkx.visualization.graphviz_draw` will handle calling graphviz and
generate an image file. For layout functions retworkx has a similar variety of
:ref:`layout-functions`, however it should be noted that retworkx's functions
are strictly 2 dimensional. The also return a :class:`~retworkx.Pos2DMapping`
custom return type which acts as read-only dictionary (which is different from
networkx which returns a normal dictionary that can be modified).

Matplotlib Drawers
^^^^^^^^^^^^^^^^^^

The retwork function :func:`~retworkx.visualization.mpl_draw` function is
basically equivalent to the networkx function ``draw_networkx`` (it was
actually originally forked from the networkx drawer). However, there are some
key differences to keep in mind between the networkx and retworkx matplotlib
drawer.

``networkx.draw_networkx`` and ``retworkx.mpl_draw`` differences:

.. list-table::
:header-rows: 1

* - networkx
- retworkx
- Notes
* - ``nodelist``
- ``node_list``
-
* - ``edgelist``
- ``edge_list``
-
* - ``arrowsize``
- ``arrow_size``
-
* - ``labels``
- ``labels``
- For ``networkx_drawer`` ``labels`` is a dict of nodes to their label,
while retworkx's ``mpl_drawer`` ``labels`` is a callback function
that will be passed a node's data payload and expected to return the
node's label
* - ``networkx.draw_networkx_edge_labels()``
- ``edge_labels``
- NetworkX's ``networkx_drawer`` doesn't have an option for edge labels
and instead adding labels is only exposed via a separate function
``draw_networkx_edge_labels()`` which requires the ``pos`` dictionary
from the original visualization to be used. retworkx's ``edge_labels``
kwarg takes a callback function that will be passed an edge's data
payload and expected to return the label.


.. _networkx_converter:

Converting from a networkx graph
Expand Down
2 changes: 1 addition & 1 deletion docs/source/visualization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ Visualization API
:toctree: stubs

retworkx.visualization.mpl_draw
retworkx.visualization.pydot_draw
retworkx.visualization.graphviz_draw
6 changes: 3 additions & 3 deletions releasenotes/notes/0.9.0/pydot-drawer-c5df0aa830679748.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
features:
- |
Added a new `Graphviz <https://graphviz.org/>`__ based drawer function,
:func:`~retworkx.visualization.pydot_draw`, to the
:func:`~retworkx.visualization.graphviz_draw`, to the
:mod:`retworkx.visualization` module. This function requires that
Graphviz is installed locally and adds two new optional dependencies,
`pydot <https://pypi.org/project/pydot/>`__ which is used to call Graphviz
Expand All @@ -18,7 +18,7 @@ features:
.. jupyter-execute::
import retworkx
from retworkx.visualization import pydot_draw
from retworkx.visualization import graphviz_draw
def node_attr(node):
if node == 0:
Expand All @@ -29,4 +29,4 @@ features:
return {'color': 'red', 'fillcolor': 'red', 'style': 'filled'}
graph = retworkx.generators.directed_star_graph(weights=list(range(32)))
pydot_draw(graph, node_attr_fn=node_attr, method='sfdp')
graphviz_draw(graph, node_attr_fn=node_attr, method='sfdp')
4 changes: 2 additions & 2 deletions retworkx/visualization/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

__all__ = [
"mpl_draw",
"pydot_draw",
"graphviz_draw",
]

from .matplotlib import mpl_draw
from .pydot import pydot_draw
from .graphviz import graphviz_draw
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
except ImportError:
HAS_PYDOT = False

__all__ = ["pydot_draw"]
__all__ = ["graphviz_draw"]


def pydot_draw(
def graphviz_draw(
graph,
node_attr_fn=None,
edge_attr_fn=None,
Expand All @@ -30,7 +30,7 @@ def pydot_draw(
method=None,
):
"""Draw a :class:`~retworkx.PyGraph` or :class:`~retworkx.PyDiGraph` object
using graphviz via pydot
using graphviz
.. note::
Expand Down Expand Up @@ -87,7 +87,7 @@ def pydot_draw(
"""
if not HAS_PYDOT:
raise ImportError(
"Pydot and Pillow are necessary to use pydot_draw() "
"Pydot and Pillow are necessary to use graphviz_draw() "
"it can be installed with 'pip install pydot pillow'"
)
try:
Expand Down
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def readme():


mpl_extras = ['matplotlib>=3.0']
pydot_extras = ['pydot>=1.4', 'pillow>=5.4']
graphviz_extras = ['pydot>=1.4', 'pillow>=5.4']


setup(
Expand Down Expand Up @@ -58,7 +58,7 @@ def readme():
install_requires=['numpy>=1.16.0'],
extras_require={
'mpl': mpl_extras,
'pydot': pydot_extras,
'all': mpl_extras + pydot_extras,
'graphviz': graphviz_extras,
'all': mpl_extras + graphviz_extras,
}
)
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import unittest

import retworkx
from retworkx.visualization import pydot_draw
from retworkx.visualization import graphviz_draw

try:
import pydot
Expand All @@ -37,12 +37,12 @@ def _save_image(image, path):
@unittest.skipUnless(
HAS_PYDOT, "pydot and graphviz are required for running these tests"
)
class TestPyDotDraw(unittest.TestCase):
class TestGraphvizDraw(unittest.TestCase):
def test_draw_no_args(self):
graph = retworkx.generators.star_graph(24)
image = pydot_draw(graph)
image = graphviz_draw(graph)
self.assertIsInstance(image, PIL.Image.Image)
_save_image(image, "test_pydot_draw.png")
_save_image(image, "test_graphviz_draw.png")

def test_draw_node_attr_fn(self):
graph = retworkx.PyGraph()
Expand All @@ -63,9 +63,9 @@ def test_draw_node_attr_fn(self):
}
)
graph.add_edge(0, 1, dict(label="1", name="1"))
image = pydot_draw(graph, lambda node: node)
image = graphviz_draw(graph, lambda node: node)
self.assertIsInstance(image, PIL.Image.Image)
_save_image(image, "test_pydot_draw_node_attr.png")
_save_image(image, "test_graphviz_draw_node_attr.png")

def test_draw_edge_attr_fn(self):
graph = retworkx.PyGraph()
Expand All @@ -86,9 +86,9 @@ def test_draw_edge_attr_fn(self):
}
)
graph.add_edge(0, 1, dict(label="1", name="1"))
image = pydot_draw(graph, lambda node: node, lambda edge: edge)
image = graphviz_draw(graph, lambda node: node, lambda edge: edge)
self.assertIsInstance(image, PIL.Image.Image)
_save_image(image, "test_pydot_draw_edge_attr.png")
_save_image(image, "test_graphviz_draw_edge_attr.png")

def test_draw_graph_attr(self):
graph = retworkx.PyGraph()
Expand All @@ -110,32 +110,32 @@ def test_draw_graph_attr(self):
)
graph.add_edge(0, 1, dict(label="1", name="1"))
graph_attr = {"bgcolor": "red"}
image = pydot_draw(
image = graphviz_draw(
graph, lambda node: node, lambda edge: edge, graph_attr
)
self.assertIsInstance(image, PIL.Image.Image)
_save_image(image, "test_pydot_draw_graph_attr.png")
_save_image(image, "test_graphviz_draw_graph_attr.png")

def test_image_type(self):
graph = retworkx.directed_gnp_random_graph(50, 0.8)
image = pydot_draw(graph, image_type="jpg")
image = graphviz_draw(graph, image_type="jpg")
self.assertIsInstance(image, PIL.Image.Image)
_save_image(image, "test_pydot_draw_image_type.jpg")
_save_image(image, "test_graphviz_draw_image_type.jpg")

def test_method(self):
graph = retworkx.directed_gnp_random_graph(50, 0.8)
image = pydot_draw(graph, method="sfdp")
image = graphviz_draw(graph, method="sfdp")
self.assertIsInstance(image, PIL.Image.Image)
_save_image(image, "test_pydot_method.png")
_save_image(image, "test_graphviz_method.png")

def test_filename(self):
graph = retworkx.generators.grid_graph(20, 20)
pydot_draw(
graphviz_draw(
graph,
filename="test_pydot_filename.svg",
filename="test_graphviz_filename.svg",
image_type="svg",
method="neato",
)
self.assertTrue(os.path.isfile("test_pydot_filename.svg"))
self.assertTrue(os.path.isfile("test_graphviz_filename.svg"))
if not SAVE_IMAGES:
self.addCleanup(os.remove, "test_pydot_filename.svg")
self.addCleanup(os.remove, "test_graphviz_filename.svg")

0 comments on commit 0efc2e6

Please sign in to comment.