Spaces:
Running
Running
import pytest | |
import networkx as nx | |
def test_tikz_attributes(): | |
G = nx.path_graph(4, create_using=nx.DiGraph) | |
pos = {n: (n, n) for n in G} | |
G.add_edge(0, 0) | |
G.edges[(0, 0)]["label"] = "Loop" | |
G.edges[(0, 0)]["label_options"] = "midway" | |
G.nodes[0]["style"] = "blue" | |
G.nodes[1]["style"] = "line width=3,draw" | |
G.nodes[2]["style"] = "circle,draw,blue!50" | |
G.nodes[3]["label"] = "Stop" | |
G.edges[(0, 1)]["label"] = "1st Step" | |
G.edges[(0, 1)]["label_options"] = "near end" | |
G.edges[(2, 3)]["label"] = "3rd Step" | |
G.edges[(2, 3)]["label_options"] = "near start" | |
G.edges[(2, 3)]["style"] = "bend left,green" | |
G.edges[(1, 2)]["label"] = "2nd" | |
G.edges[(1, 2)]["label_options"] = "pos=0.5" | |
G.edges[(1, 2)]["style"] = ">->,bend right,line width=3,green!90" | |
output_tex = nx.to_latex( | |
G, | |
pos=pos, | |
as_document=False, | |
tikz_options="[scale=3]", | |
node_options="style", | |
edge_options="style", | |
node_label="label", | |
edge_label="label", | |
edge_label_options="label_options", | |
) | |
expected_tex = r"""\begin{figure} | |
\begin{tikzpicture}[scale=3] | |
\draw | |
(0, 0) node[blue] (0){0} | |
(1, 1) node[line width=3,draw] (1){1} | |
(2, 2) node[circle,draw,blue!50] (2){2} | |
(3, 3) node (3){Stop}; | |
\begin{scope}[->] | |
\draw (0) to node[near end] {1st Step} (1); | |
\draw[loop,] (0) to node[midway] {Loop} (0); | |
\draw[>->,bend right,line width=3,green!90] (1) to node[pos=0.5] {2nd} (2); | |
\draw[bend left,green] (2) to node[near start] {3rd Step} (3); | |
\end{scope} | |
\end{tikzpicture} | |
\end{figure}""" | |
assert output_tex == expected_tex | |
# print(output_tex) | |
# # Pretty way to assert that A.to_document() == expected_tex | |
# content_same = True | |
# for aa, bb in zip(expected_tex.split("\n"), output_tex.split("\n")): | |
# if aa != bb: | |
# content_same = False | |
# print(f"-{aa}|\n+{bb}|") | |
# assert content_same | |
def test_basic_multiple_graphs(): | |
H1 = nx.path_graph(4) | |
H2 = nx.complete_graph(4) | |
H3 = nx.path_graph(8) | |
H4 = nx.complete_graph(8) | |
captions = [ | |
"Path on 4 nodes", | |
"Complete graph on 4 nodes", | |
"Path on 8 nodes", | |
"Complete graph on 8 nodes", | |
] | |
labels = ["fig2a", "fig2b", "fig2c", "fig2d"] | |
latex_code = nx.to_latex( | |
[H1, H2, H3, H4], | |
n_rows=2, | |
sub_captions=captions, | |
sub_labels=labels, | |
) | |
# print(latex_code) | |
assert "begin{document}" in latex_code | |
assert "begin{figure}" in latex_code | |
assert latex_code.count("begin{subfigure}") == 4 | |
assert latex_code.count("tikzpicture") == 8 | |
assert latex_code.count("[-]") == 4 | |
def test_basic_tikz(): | |
expected_tex = r"""\documentclass{report} | |
\usepackage{tikz} | |
\usepackage{subcaption} | |
\begin{document} | |
\begin{figure} | |
\begin{subfigure}{0.5\textwidth} | |
\begin{tikzpicture}[scale=2] | |
\draw[gray!90] | |
(0.749, 0.702) node[red!90] (0){0} | |
(1.0, -0.014) node[red!90] (1){1} | |
(-0.777, -0.705) node (2){2} | |
(-0.984, 0.042) node (3){3} | |
(-0.028, 0.375) node[cyan!90] (4){4} | |
(-0.412, 0.888) node (5){5} | |
(0.448, -0.856) node (6){6} | |
(0.003, -0.431) node[cyan!90] (7){7}; | |
\begin{scope}[->,gray!90] | |
\draw (0) to (4); | |
\draw (0) to (5); | |
\draw (0) to (6); | |
\draw (0) to (7); | |
\draw (1) to (4); | |
\draw (1) to (5); | |
\draw (1) to (6); | |
\draw (1) to (7); | |
\draw (2) to (4); | |
\draw (2) to (5); | |
\draw (2) to (6); | |
\draw (2) to (7); | |
\draw (3) to (4); | |
\draw (3) to (5); | |
\draw (3) to (6); | |
\draw (3) to (7); | |
\end{scope} | |
\end{tikzpicture} | |
\caption{My tikz number 1 of 2}\label{tikz_1_2} | |
\end{subfigure} | |
\begin{subfigure}{0.5\textwidth} | |
\begin{tikzpicture}[scale=2] | |
\draw[gray!90] | |
(0.749, 0.702) node[green!90] (0){0} | |
(1.0, -0.014) node[green!90] (1){1} | |
(-0.777, -0.705) node (2){2} | |
(-0.984, 0.042) node (3){3} | |
(-0.028, 0.375) node[purple!90] (4){4} | |
(-0.412, 0.888) node (5){5} | |
(0.448, -0.856) node (6){6} | |
(0.003, -0.431) node[purple!90] (7){7}; | |
\begin{scope}[->,gray!90] | |
\draw (0) to (4); | |
\draw (0) to (5); | |
\draw (0) to (6); | |
\draw (0) to (7); | |
\draw (1) to (4); | |
\draw (1) to (5); | |
\draw (1) to (6); | |
\draw (1) to (7); | |
\draw (2) to (4); | |
\draw (2) to (5); | |
\draw (2) to (6); | |
\draw (2) to (7); | |
\draw (3) to (4); | |
\draw (3) to (5); | |
\draw (3) to (6); | |
\draw (3) to (7); | |
\end{scope} | |
\end{tikzpicture} | |
\caption{My tikz number 2 of 2}\label{tikz_2_2} | |
\end{subfigure} | |
\caption{A graph generated with python and latex.} | |
\end{figure} | |
\end{document}""" | |
edges = [ | |
(0, 4), | |
(0, 5), | |
(0, 6), | |
(0, 7), | |
(1, 4), | |
(1, 5), | |
(1, 6), | |
(1, 7), | |
(2, 4), | |
(2, 5), | |
(2, 6), | |
(2, 7), | |
(3, 4), | |
(3, 5), | |
(3, 6), | |
(3, 7), | |
] | |
G = nx.DiGraph() | |
G.add_nodes_from(range(8)) | |
G.add_edges_from(edges) | |
pos = { | |
0: (0.7490296171687696, 0.702353520257394), | |
1: (1.0, -0.014221357723796535), | |
2: (-0.7765783344161441, -0.7054170966808919), | |
3: (-0.9842690223417624, 0.04177547602465483), | |
4: (-0.02768523817180917, 0.3745724439551441), | |
5: (-0.41154855146767433, 0.8880106515525136), | |
6: (0.44780153389148264, -0.8561492709269164), | |
7: (0.0032499953371383505, -0.43092436645809945), | |
} | |
rc_node_color = {0: "red!90", 1: "red!90", 4: "cyan!90", 7: "cyan!90"} | |
gp_node_color = {0: "green!90", 1: "green!90", 4: "purple!90", 7: "purple!90"} | |
H = G.copy() | |
nx.set_node_attributes(G, rc_node_color, "color") | |
nx.set_node_attributes(H, gp_node_color, "color") | |
sub_captions = ["My tikz number 1 of 2", "My tikz number 2 of 2"] | |
sub_labels = ["tikz_1_2", "tikz_2_2"] | |
output_tex = nx.to_latex( | |
[G, H], | |
[pos, pos], | |
tikz_options="[scale=2]", | |
default_node_options="gray!90", | |
default_edge_options="gray!90", | |
node_options="color", | |
sub_captions=sub_captions, | |
sub_labels=sub_labels, | |
caption="A graph generated with python and latex.", | |
n_rows=2, | |
as_document=True, | |
) | |
assert output_tex == expected_tex | |
# print(output_tex) | |
# # Pretty way to assert that A.to_document() == expected_tex | |
# content_same = True | |
# for aa, bb in zip(expected_tex.split("\n"), output_tex.split("\n")): | |
# if aa != bb: | |
# content_same = False | |
# print(f"-{aa}|\n+{bb}|") | |
# assert content_same | |
def test_exception_pos_single_graph(to_latex=nx.to_latex): | |
# smoke test that pos can be a string | |
G = nx.path_graph(4) | |
to_latex(G, pos="pos") | |
# must include all nodes | |
pos = {0: (1, 2), 1: (0, 1), 2: (2, 1)} | |
with pytest.raises(nx.NetworkXError): | |
to_latex(G, pos) | |
# must have 2 values | |
pos[3] = (1, 2, 3) | |
with pytest.raises(nx.NetworkXError): | |
to_latex(G, pos) | |
pos[3] = 2 | |
with pytest.raises(nx.NetworkXError): | |
to_latex(G, pos) | |
# check that passes with 2 values | |
pos[3] = (3, 2) | |
to_latex(G, pos) | |
def test_exception_multiple_graphs(to_latex=nx.to_latex): | |
G = nx.path_graph(3) | |
pos_bad = {0: (1, 2), 1: (0, 1)} | |
pos_OK = {0: (1, 2), 1: (0, 1), 2: (2, 1)} | |
fourG = [G, G, G, G] | |
fourpos = [pos_OK, pos_OK, pos_OK, pos_OK] | |
# input single dict to use for all graphs | |
to_latex(fourG, pos_OK) | |
with pytest.raises(nx.NetworkXError): | |
to_latex(fourG, pos_bad) | |
# input list of dicts to use for all graphs | |
to_latex(fourG, fourpos) | |
with pytest.raises(nx.NetworkXError): | |
to_latex(fourG, [pos_bad, pos_bad, pos_bad, pos_bad]) | |
# every pos dict must include all nodes | |
with pytest.raises(nx.NetworkXError): | |
to_latex(fourG, [pos_OK, pos_OK, pos_bad, pos_OK]) | |
# test sub_captions and sub_labels (len must match Gbunch) | |
with pytest.raises(nx.NetworkXError): | |
to_latex(fourG, fourpos, sub_captions=["hi", "hi"]) | |
with pytest.raises(nx.NetworkXError): | |
to_latex(fourG, fourpos, sub_labels=["hi", "hi"]) | |
# all pass | |
to_latex(fourG, fourpos, sub_captions=["hi"] * 4, sub_labels=["lbl"] * 4) | |
def test_exception_multigraph(): | |
G = nx.path_graph(4, create_using=nx.MultiGraph) | |
G.add_edge(1, 2) | |
with pytest.raises(nx.NetworkXNotImplemented): | |
nx.to_latex(G) | |