Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 007ee07

Browse files
committed
Move the debug-mode TransformNode.write_graphviz out.
It was only accessible by modifying the source of transforms.py to set DEBUG to True (before the module is imported), and anyways broken because transforms are not hashable in Py3 (so the call to hash() fails). Instead move it to a private module. Example use: ``` from matplotlib._internal_utils import graphviz_dump_transform graphviz_dump_transform(plt.gca().transAxes, "/tmp/test.png") ``` Also, stop tracking transform node children even in debug mode, as it was only used when dumping the transform but that's not even necessary -- one can just inspect `vars(node)` to look for children.
1 parent db55918 commit 007ee07

File tree

2 files changed

+64
-58
lines changed

2 files changed

+64
-58
lines changed

lib/matplotlib/_internal_utils.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""
2+
Internal debugging utilities, that are not expected to be used in the rest of
3+
the codebase.
4+
5+
WARNING: Code in this module may change without prior notice!
6+
"""
7+
8+
from io import StringIO
9+
from pathlib import Path
10+
import subprocess
11+
12+
from matplotlib.transforms import TransformNode
13+
14+
15+
def graphviz_dump_transform(transform, dest, *, highlight=None):
16+
"""
17+
Generate a graphical representation of the transform tree for *transform*
18+
using the :program:`dot` program (which this function depends on). The
19+
output format (png, dot, etc.) is determined from the suffix of *dest*.
20+
21+
Parameters
22+
----------
23+
transform : `~matplotlib.transform.Transform`
24+
The represented transform.
25+
dest : str
26+
Output filename. The extension must be one of the formats supported
27+
by :program:`dot`, e.g. png, svg, dot, ...
28+
(see https://www.graphviz.org/doc/info/output.html).
29+
highlight : list of `~matplotlib.transform.Transform` or None
30+
The transforms in the tree to be drawn in bold.
31+
If *None*, *transform* is highlighted.
32+
"""
33+
34+
if highlight is None:
35+
highlight = [transform]
36+
seen = set()
37+
38+
def recurse(root, buf):
39+
if id(root) in seen:
40+
return
41+
seen.add(id(root))
42+
props = {}
43+
label = type(root).__name__
44+
if root._invalid:
45+
label = f'[{label}]'
46+
if root in highlight:
47+
props['style'] = 'bold'
48+
props['shape'] = 'box'
49+
props['label'] = '"%s"' % label
50+
props = ' '.join(map('{0[0]}={0[1]}'.format, props.items()))
51+
buf.write(f'{id(root)} [{props}];\n')
52+
for key, val in vars(root).items():
53+
if isinstance(val, TransformNode) and id(root) in val._parents:
54+
buf.write(f'"{id(root)}" -> "{id(val)}" '
55+
f'[label="{key}", fontsize=10];\n')
56+
recurse(val, buf)
57+
58+
buf = StringIO()
59+
buf.write('digraph G {\n')
60+
recurse(transform, buf)
61+
buf.write('}\n')
62+
subprocess.run(
63+
['dot', '-T', Path(dest).suffix[1:], '-o', dest],
64+
input=buf.getvalue().encode('utf-8'), check=True)

lib/matplotlib/transforms.py

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -200,14 +200,6 @@ def set_children(self, *children):
200200
self, lambda _, pop=child._parents.pop, k=id(self): pop(k))
201201
child._parents[id(self)] = ref
202202

203-
if DEBUG:
204-
_set_children = set_children
205-
206-
def set_children(self, *children):
207-
self._set_children(*children)
208-
self._children = children
209-
set_children.__doc__ = _set_children.__doc__
210-
211203
def frozen(self):
212204
"""
213205
Returns a frozen copy of this transform node. The frozen copy
@@ -217,56 +209,6 @@ def frozen(self):
217209
"""
218210
return self
219211

220-
if DEBUG:
221-
def write_graphviz(self, fobj, highlight=[]):
222-
"""
223-
For debugging purposes.
224-
225-
Writes the transform tree rooted at 'self' to a graphviz "dot"
226-
format file. This file can be run through the "dot" utility
227-
to produce a graph of the transform tree.
228-
229-
Affine transforms are marked in blue. Bounding boxes are
230-
marked in yellow.
231-
232-
*fobj*: A Python file-like object
233-
234-
Once the "dot" file has been created, it can be turned into a
235-
png easily with::
236-
237-
$> dot -Tpng -o $OUTPUT_FILE $DOT_FILE
238-
239-
"""
240-
seen = set()
241-
242-
def recurse(root):
243-
if root in seen:
244-
return
245-
seen.add(root)
246-
props = {}
247-
label = root.__class__.__name__
248-
if root._invalid:
249-
label = '[%s]' % label
250-
if root in highlight:
251-
props['style'] = 'bold'
252-
props['shape'] = 'box'
253-
props['label'] = '"%s"' % label
254-
props = ' '.join(map('{0[0]}={0[1]}'.format, props.items()))
255-
256-
fobj.write('%s [%s];\n' % (hash(root), props))
257-
258-
if hasattr(root, '_children'):
259-
for child in root._children:
260-
name = next((key for key, val in root.__dict__.items()
261-
if val is child), '?')
262-
fobj.write('"%s" -> "%s" [label="%s", fontsize=10];\n'
263-
% (hash(root), hash(child), name))
264-
recurse(child)
265-
266-
fobj.write("digraph G {\n")
267-
recurse(self)
268-
fobj.write("}\n")
269-
270212

271213
class BboxBase(TransformNode):
272214
"""

0 commit comments

Comments
 (0)