From f422b4c24b92d0c054f24129bb8bda89c5004d19 Mon Sep 17 00:00:00 2001 From: kevin-lozada-santos Date: Wed, 16 Sep 2026 21:04:18 -0400 Subject: [PATCH 1/4] feat: support drawing colors and transparent backgrounds --- README.md | 4 +- examples/classic/draw_planar_colors.py | 24 +++++ examples/classic/output/K5-minus-edge.png | Bin 15768 -> 7744 bytes planarity/classic/planarity.pyx | 50 +++++++--- planarity/classic/planarity_functions.py | 7 +- tests/test_draw_colors.py | 116 ++++++++++++++++++++++ 6 files changed, 184 insertions(+), 17 deletions(-) create mode 100644 examples/classic/draw_planar_colors.py create mode 100644 tests/test_draw_colors.py diff --git a/README.md b/README.md index 7378192..7c8b24c 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ In [11]: print(planarity.ascii(edgelist)) ```python -In [12]: planarity.draw(edgelist, outfileName='K5-minus-edge.png') +In [12]: planarity.draw(edgelist, outfileName='K5-minus-edge.png', vertex_bordercolor='black') ``` ![K_5-minus-edge](/examples/classic/output/K5-minus-edge.png "Matplotlib render of $K_5$-minus-edge") @@ -93,4 +93,4 @@ license](https://github.com/graph-algorithms/planarity/blob/master/LICENSE.txt).     Planarity includes the Edge Addition Planarity Suite, which is
    Copyright (c) 1997-2026, John M. Boyer.
    The BSD-3-Clause license for the Edge Additional Planarity Suite
-    included in Planarity appears [here](https://github.com/graph-algorithms/planarity/blob/master/planarity/c/LICENSE.TXT). \ No newline at end of file +    included in Planarity appears [here](https://github.com/graph-algorithms/planarity/blob/master/planarity/c/LICENSE.TXT). diff --git a/examples/classic/draw_planar_colors.py b/examples/classic/draw_planar_colors.py new file mode 100644 index 0000000..a815d4d --- /dev/null +++ b/examples/classic/draw_planar_colors.py @@ -0,0 +1,24 @@ +"""Run from the desired output directory to generate seven color examples.""" + +import planarity + + +edgelist = [('a', 'c'), ('a', 'd'), ('a', 'e'), ('b', 'c'), ('b', 'd'), + ('b', 'e'), ('c', 'd'), ('c', 'e'), ('d', 'e')] + +colors = { + 'facecolor': 'lightyellow', + 'transparent': True, + 'vertex_facecolor': 'lightgreen', + 'vertex_bordercolor': 'black', + 'vertex_label_facecolor': 'lavender', + 'vertex_label_bordercolor': 'red', + 'edge_linecolor': 'darkorange', +} + +for property_name, value in colors.items(): + planarity.draw( + edgelist, + outfileName=f'K5-minus-edge_{property_name}.png', + **{property_name: value}, + ) diff --git a/examples/classic/output/K5-minus-edge.png b/examples/classic/output/K5-minus-edge.png index 27922e4a35bb965e5cc34bf01990a3eff03fce6c..f3985e74a46162c155cb549622f644796d34e212 100644 GIT binary patch literal 7744 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 V>_=WD_{bEvXk>0!bpHCi{{lfTi+BJ4 literal 15768 zcmeHuX;f3$w(bHH^eAErNUv6j9Uvlo6RJ?LLsV2yTA>7#&ImC;Ac;j4NE@qEKtMnd zK|m0co+PM*s7NPGK$>7c=?MsFAS8Kf<2k3!d-t9D?w>ox8{^6tj5K@gwbzG_rvX?F-%8c4kcKZ;dfP+bi%HNyhakHE&mio@YnOn{#h|Oc z0YSc(-8HUXx)yjjz+X>WS65qikA`FU5g=lt>{T*`%S#I^>+vxNV&52ER zbZnye-}XOxd^G#?PTY#jvU8jQ63^+Xk6GnI`U4pVW!yjhmQeBKwhXOo(l5cNJ(&l7 zlMWKx)WpVJJ}rl__4QI$L7ZSJ%^6b%M$cK zdaUK!WtM;_U5cN#Yb8%}9jXV)9K^jIuS=|ZQm;qr>J1+lj_YnUxEOV@TM7`h5ZIw~ zJey#(NAOadFtxmVjliYjSw%@`_2-^eP*Ns^tTKk{f=F9D}G z43+_J4ccz8O9EkXa&o4-8E7U2ueCdz|nSQQf`4Kd-NI9x0_U(XjikrR0d z1%SclU9}K6x(ip?u1V)Q#uMzFF=xZZ>@t+f`1WVRC&tt|$a%PPXT5SMVhsRFw*X17 z|7Pi`0A(k!kSPvVLD#L*@2Re03|sIjU!t%&!5Db}B9p)h(4t|G;NQ`P_wgGvH%#~g zfYmw>l4VNF6*+Gn&v11r;4ul}E;L=$$Kv$~)5(p3$#U0X7jf@kE0dh}MGt`eTfdFx z)fiRuhx7W5rFsmKWvX27uLQ(T+mMA2kGk>(LMOV4vm15&dn;aYESVoad;!4w2T2WJ zX_dRW@WO=)M^jm)II7780A5=|DM4kagC`094j=#DKNgfuK;)Pk(AU>jeD%|-;Dyl~ zkM5F7t=-+5+j4A4=bwAha!+NwQD?VgJ$vy($b<0H<_}{tk;3e6Dx@T)cAumJ+Bk{4FeW-dvH4N8T>j; z){C|i%3-B&Rh+jwYXMk1N3vM(-sA90<6NQBW-^(4>dBcH0i)2_F)VE4K~xNHrHXmz zi>#I4q!%JOgM2C#CE~b>^_x)Q#o&ozI)40A9z}D2+Y`X{mIUpa;lU9Z=F9mwrl9{A zb$?k|y=nhU0#wFO-{*}6t(~3cdR@cM4osFaT?!0+y9N%!o3U8Z_xDrig8_JDac46t384UV#DlkvyR0%+fgzUy^QM&FEu@MY^Svx$ZV?o+g>PX zKBtJ_92O?%VT!6|ipCzN`d^y^U@Q$PW$pHlJw2`)Bn^iVso~gUMynLa4O}`Pqv=|y zSW>LKR!ppRmG|vtsGh=^2Xf&%%KEN5E=`Zf)0d?qV(CZ^x^T8?unA(pAaY`}%_x)w z|D{|#UNEVUWlc(;3VW!SrH97Cd!9vKZhK6V!%s&TiTHzq_q@`h#e9-@hksG7bnV#h zKNnU{nf&#D&YxsdHzEhJPBc}`ri_e^M(?zHT=!B&-KjV4I#d)R;apoRCt24+

~} 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 V=I$73M^yI6!4n4xe|G!ze*rlvGFt!u diff --git a/planarity/classic/planarity.pyx b/planarity/classic/planarity.pyx index bc6b5cd..dea2174 100644 --- a/planarity/classic/planarity.pyx +++ b/planarity/classic/planarity.pyx @@ -499,11 +499,21 @@ cdef class PGraph: outfileName (:obj:`str`): File to which to output a Matplotlib rendering of the planar graph. If not given, then the caller can call :external+matplotlib:py:func:`matplotlib.pyplot.savefig`. - **kwargs: Optional figure-level parameters to apply to the - current figure after it is cleared. Supported keys are - ``figsize`` and ``dpi``. If none are given, Matplotlib's - default figure size and DPI are used, matching prior - behavior. + **kwargs: Optional drawing parameters. ``figsize`` and ``dpi`` + control the figure size and resolution. ``facecolor`` sets + the figure background (default ``'#f0f0f0'``). + ``vertex_facecolor`` and ``vertex_bordercolor`` set vertex + rectangle colors; omitted values use Matplotlib's patch + defaults. ``vertex_label_facecolor`` and + ``vertex_label_bordercolor`` set label rectangle colors + (defaults ``'white'`` and ``'black'``). ``edge_linecolor`` + sets edge colors (default Matplotlib line color). All color + values accept Matplotlib color specifications. + ``transparent`` (default ``False``) makes the figure and + axes backgrounds transparent when saving to ``outfileName``; + it does not remove matching colors from vertices or labels. + When saving the figure later yourself, pass ``transparent`` + to :external+matplotlib:py:func:`matplotlib.pyplot.savefig`. Raises: ValueError: if an unsupported keyword argument is given. @@ -531,18 +541,24 @@ cdef class PGraph: plt.clf() fig = plt.gcf() - valid_fig_kwargs = ('figsize', 'dpi') + valid_draw_kwargs = ( + 'figsize', 'dpi', 'facecolor', 'transparent', 'vertex_facecolor', + 'vertex_bordercolor', 'vertex_label_facecolor', + 'vertex_label_bordercolor', 'edge_linecolor', + ) for key, value in kwargs.items(): - if key not in valid_fig_kwargs: + if key not in valid_draw_kwargs: raise ValueError( f"planarity: '{key}' is not a supported draw() keyword " - f"argument. Supported options are: {valid_fig_kwargs}." + f"argument. Supported options are: {valid_draw_kwargs}." ) if key == 'figsize': fig.set_size_inches(value) elif key == 'dpi': fig.set_dpi(value) + fig.set_facecolor(kwargs.get('facecolor', '#f0f0f0')) + self.embed_drawplanar() if self._embedding_workflow_status != cplanarity.OK: @@ -582,9 +598,13 @@ cdef class PGraph: ye = drawplanar_edge_info['edge_end'] ys.extend([yb, ye]) xs.append(x) - plt.vlines([x], [yb], [ye]) + plt.vlines([x], [yb], [ye], colors=kwargs.get('edge_linecolor')) - p = PatchCollection(patches) + p = PatchCollection( + patches, + facecolors=kwargs.get('vertex_facecolor'), + edgecolors=kwargs.get('vertex_bordercolor'), + ) ax = plt.gca() ax.add_collection(p) plt.axis('equal') @@ -614,8 +634,8 @@ cdef class PGraph: verticalalignment='center', bbox = dict( boxstyle='round', - ec=(0.0, 0.0, 0.0), - fc=(1.0, 1.0, 1.0), + ec=kwargs.get('vertex_label_bordercolor', 'black'), + fc=kwargs.get('vertex_label_facecolor', 'white'), ) ) @@ -634,7 +654,11 @@ cdef class PGraph: ).transformed(inv) if outfileName: - plt.savefig(outfileName, dpi=fig.dpi) + transparent = kwargs.get('transparent', False) + plt.savefig( + outfileName, dpi=fig.dpi, transparent=transparent, + facecolor='none' if transparent else fig.get_facecolor(), + ) def write( self, str path='stdout', int writeMode=cplanarity.WRITE_ADJLIST diff --git a/planarity/classic/planarity_functions.py b/planarity/classic/planarity_functions.py index 47312de..7d46abc 100644 --- a/planarity/classic/planarity_functions.py +++ b/planarity/classic/planarity_functions.py @@ -120,9 +120,12 @@ def draw(graph, labels=True, outfileName=None, **kwargs): outfileName (:obj:`str`): File to which to output a Matplotlib rendering of the planar graph. If not given, then the caller can call :external+matplotlib:py:func:`matplotlib.pyplot.savefig`. - **kwargs: Optional figure-level parameters forwarded to + **kwargs: Optional drawing parameters forwarded to :py:meth:`~planarity.classic.planarity.PGraph.draw`. Supported - keys are ``figsize`` and ``dpi``. + keys are ``figsize``, ``dpi``, ``facecolor``, ``transparent``, + ``vertex_facecolor``, ``vertex_bordercolor``, + ``vertex_label_facecolor``, ``vertex_label_bordercolor`` and + ``edge_linecolor``. See the method documentation for defaults. Raises: ValueError: if the given graph is already a diff --git a/tests/test_draw_colors.py b/tests/test_draw_colors.py new file mode 100644 index 0000000..779b024 --- /dev/null +++ b/tests/test_draw_colors.py @@ -0,0 +1,116 @@ +"""Exercise color controls on real artists and rendered PNGs.""" + +import matplotlib + +matplotlib.use('Agg') + +import matplotlib.pyplot as plt +from matplotlib.collections import LineCollection, PatchCollection +from matplotlib.colors import to_rgba +from PIL import Image +import pytest + +import planarity + + +EDGES = [('a', 'c'), ('a', 'd'), ('a', 'e'), ('b', 'c'), ('b', 'd'), + ('b', 'e'), ('c', 'd'), ('c', 'e'), ('d', 'e')] + + +@pytest.fixture(autouse=True) +def isolated_figures(): + with matplotlib.rc_context(): + yield + plt.close('all') + + +@pytest.fixture(params=['function', 'method']) +def draw(request): + if request.param == 'function': + return lambda **kwargs: planarity.draw(EDGES, **kwargs) + return lambda **kwargs: planarity.PGraph(EDGES).draw(**kwargs) + + +@pytest.mark.parametrize('option,color', [ + ('facecolor', '#abcdef'), + ('vertex_facecolor', 'gold'), + ('vertex_bordercolor', (0.3, 0.2, 0.8)), + ('vertex_label_facecolor', 'lightgreen'), + ('vertex_label_bordercolor', '#aabbcc'), + ('edge_linecolor', 'magenta'), +]) +def test_individual_colors_reach_artists(draw, option, color): + draw(**{option: color}) + ax = plt.gca() + if option == 'facecolor': + actual = [plt.gcf().get_facecolor()] + elif option.startswith('vertex_label_'): + method = ('get_facecolor' if option.endswith('facecolor') + else 'get_edgecolor') + actual = [getattr(text.get_bbox_patch(), method)() for text in ax.texts] + assert len(actual) == 5 + elif option.startswith('vertex_'): + vertices = next(c for c in ax.collections if isinstance(c, PatchCollection)) + actual = (vertices.get_facecolors() if option.endswith('facecolor') + else vertices.get_edgecolors()) + else: + actual = [c.get_colors()[0] for c in ax.collections + if isinstance(c, LineCollection)] + assert len(actual) == 9 + assert len(actual) > 0 + for rgba in actual: + assert tuple(rgba) == pytest.approx(to_rgba(color)) + + +@pytest.mark.parametrize('transparent', [False, True]) +def test_png_background_and_transparency(draw, tmp_path, transparent): + output = tmp_path / 'colors.png' + # A user's savefig style must not override an explicit draw() facecolor. + matplotlib.rcParams['savefig.facecolor'] = 'red' + draw(outfileName=str(output), facecolor='#abcdef', transparent=transparent, + figsize=(4, 3), dpi=100) + with Image.open(output) as image: + assert image.size == (400, 300) + rgba = image.convert('RGBA') + if transparent: + assert rgba.getpixel((0, 0))[3] == 0 + assert rgba.getextrema()[3][1] == 255 # Graph remains visible. + else: + assert rgba.getpixel((0, 0)) == (171, 205, 239, 255) + assert plt.gcf().get_facecolor() == pytest.approx(to_rgba('#abcdef')) + + +def test_color_controls_combine_without_labels(draw, tmp_path): + draw(labels=False, outfileName=str(tmp_path / 'no-labels.png'), + facecolor='white', transparent=True, vertex_facecolor='yellow', + vertex_bordercolor='black', vertex_label_facecolor='pink', + vertex_label_bordercolor='green', edge_linecolor='red') + assert not plt.gca().texts + vertices = next(c for c in plt.gca().collections if isinstance(c, PatchCollection)) + assert tuple(vertices.get_facecolors()[0]) == pytest.approx(to_rgba('yellow')) + assert tuple(vertices.get_edgecolors()[0]) == pytest.approx(to_rgba('black')) + + +def test_default_background_resets_after_custom_draw(draw): + draw(facecolor='red') + draw() + assert plt.gcf().get_facecolor() == pytest.approx(to_rgba('#f0f0f0')) + for text in plt.gca().texts: + assert text.get_bbox_patch().get_facecolor() == to_rgba('white') + assert text.get_bbox_patch().get_edgecolor() == to_rgba('black') + + +def test_existing_figure_options(draw): + draw(figsize=(4, 3), dpi=120) + assert tuple(plt.gcf().get_size_inches()) == pytest.approx((4, 3)) + assert plt.gcf().dpi == 120 + + +def test_unknown_keyword_still_rejected(draw): + with pytest.raises(ValueError, match='not a supported draw'): + draw(vertex_colour='red') + + +def test_invalid_color_rejected(draw): + with pytest.raises(ValueError, match='not-a-color'): + draw(vertex_facecolor='not-a-color') From a3209f56d829f7cbfe155cf67e35aff758af664b Mon Sep 17 00:00:00 2001 From: john-boyer-phd Date: Thu, 17 Sep 2026 11:47:43 -0700 Subject: [PATCH 2/4] Changed facecolor default to match fix in issue specification --- planarity/classic/planarity.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/planarity/classic/planarity.pyx b/planarity/classic/planarity.pyx index dea2174..571a495 100644 --- a/planarity/classic/planarity.pyx +++ b/planarity/classic/planarity.pyx @@ -501,7 +501,7 @@ cdef class PGraph: call :external+matplotlib:py:func:`matplotlib.pyplot.savefig`. **kwargs: Optional drawing parameters. ``figsize`` and ``dpi`` control the figure size and resolution. ``facecolor`` sets - the figure background (default ``'#f0f0f0'``). + the figure background (default ``'#ffffff'``). ``vertex_facecolor`` and ``vertex_bordercolor`` set vertex rectangle colors; omitted values use Matplotlib's patch defaults. ``vertex_label_facecolor`` and @@ -557,7 +557,7 @@ cdef class PGraph: elif key == 'dpi': fig.set_dpi(value) - fig.set_facecolor(kwargs.get('facecolor', '#f0f0f0')) + fig.set_facecolor(kwargs.get('facecolor', '#ffffff')) self.embed_drawplanar() From 67ff31b34b485518d676579d38969724bcdf6dd5 Mon Sep 17 00:00:00 2001 From: kevin-lozada-santos Date: Thu, 17 Sep 2026 15:50:58 -0400 Subject: [PATCH 3/4] test: align draw default with corrected white background --- tests/test_draw_colors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_draw_colors.py b/tests/test_draw_colors.py index 779b024..f19bffc 100644 --- a/tests/test_draw_colors.py +++ b/tests/test_draw_colors.py @@ -94,7 +94,7 @@ def test_color_controls_combine_without_labels(draw, tmp_path): def test_default_background_resets_after_custom_draw(draw): draw(facecolor='red') draw() - assert plt.gcf().get_facecolor() == pytest.approx(to_rgba('#f0f0f0')) + assert plt.gcf().get_facecolor() == pytest.approx(to_rgba('#ffffff')) for text in plt.gca().texts: assert text.get_bbox_patch().get_facecolor() == to_rgba('white') assert text.get_bbox_patch().get_edgecolor() == to_rgba('black') From 7ce1ba308a75e408c3109f46c5ac0f4f932387c4 Mon Sep 17 00:00:00 2001 From: john-boyer-phd Date: Thu, 17 Sep 2026 12:54:13 -0700 Subject: [PATCH 4/4] Fix vertex border color (put edges behind vertices) --- examples/classic/draw.py | 6 +++--- examples/classic/output/K5-minus-edge.png | Bin 7744 -> 7659 bytes planarity/classic/planarity.pyx | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/classic/draw.py b/examples/classic/draw.py index 0d920ad..2765dfa 100644 --- a/examples/classic/draw.py +++ b/examples/classic/draw.py @@ -34,13 +34,13 @@ print(planar_rendition) # Output Matplotlib rendering - P2.draw(outfileName='K5-minus-edge.png') + P2.draw(outfileName='K5-minus-edge.png', vertex_bordercolor='black') # Verify fig_kwargs (#87): generate 300dpi and 600dpi variants P3 = planarity.PGraph(edgelist) - P3.draw(outfileName='K5-minus-edge-300dpi.png', dpi=300) + P3.draw(outfileName='K5-minus-edge-300dpi.png', dpi=300, vertex_bordercolor='black') P4 = planarity.PGraph(edgelist) - P4.draw(outfileName='K5-minus-edge-600dpi.png', dpi=600) + P4.draw(outfileName='K5-minus-edge-600dpi.png', dpi=600, vertex_bordercolor='black') else: print("The graph cannot be drawn because it is non-planar.") diff --git a/examples/classic/output/K5-minus-edge.png b/examples/classic/output/K5-minus-edge.png index f3985e74a46162c155cb549622f644796d34e212..87ad4a5bb0d2f3898996df7e7f2ab545bfdf9b3c 100644 GIT binary patch literal 7659 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 literal 7744 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 V>_=WD_{bEvXk>0!bpHCi{{lfTi+BJ4 diff --git a/planarity/classic/planarity.pyx b/planarity/classic/planarity.pyx index 571a495..eff7644 100644 --- a/planarity/classic/planarity.pyx +++ b/planarity/classic/planarity.pyx @@ -598,12 +598,13 @@ cdef class PGraph: ye = drawplanar_edge_info['edge_end'] ys.extend([yb, ye]) xs.append(x) - plt.vlines([x], [yb], [ye], colors=kwargs.get('edge_linecolor')) + plt.vlines([x], [yb], [ye], colors=kwargs.get('edge_linecolor'), zorder=1) p = PatchCollection( patches, facecolors=kwargs.get('vertex_facecolor'), edgecolors=kwargs.get('vertex_bordercolor'), + zorder = 2, ) ax = plt.gca() ax.add_collection(p)