Skip to content

Commit 76101fc

Browse files
committed
Improved the tikz plotting, use classes for nodes and paths
1 parent 5d42566 commit 76101fc

File tree

4 files changed

+190
-54
lines changed

4 files changed

+190
-54
lines changed

src/maxplotlib/canvas/canvas.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,9 @@ def plot_matplotlib(self, show=True, savefig=False):
142142
print(fig_width, fig_height, fig_width / self._dpi, fig_height / self._dpi)
143143
fig, axes = plt.subplots(self.nrows, self.ncols, figsize=(fig_width / self._dpi, fig_height / self._dpi), squeeze=False, dpi = self._dpi)
144144

145-
for (row, col), line_plot in self.subplots.items():
145+
for (row, col), subplot in self.subplots.items():
146146
ax = axes[row][col]
147-
line_plot.plot(ax) # Assuming LinePlot's `plot` method accepts an axis object
147+
subplot.plot_matplotlib(ax)
148148
# ax.set_title(f"Subplot ({row}, {col})")
149149

150150
# Set caption, labels, etc., if needed

src/maxplotlib/subfigure/line_plot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def add_line(self, x_data, y_data, **kwargs):
5454
'kwargs': kwargs
5555
})
5656

57-
def plot(self, ax):
57+
def plot_matplotlib(self, ax):
5858
"""
5959
Plot all lines on the provided axis.
6060

src/maxplotlib/subfigure/tikz_figure.py

Lines changed: 97 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,61 @@
11
import subprocess
22
import os
33
import tempfile
4+
from matplotlib.image import imread
5+
6+
class Node:
7+
def __init__(self, x, y, label="", content="",**kwargs):
8+
"""
9+
Represents a TikZ node.
10+
11+
Parameters:
12+
- x (float): X-coordinate of the node.
13+
- y (float): Y-coordinate of the node.
14+
- name (str, optional): Name of the node. If None, a default name will be assigned.
15+
- **kwargs: Additional TikZ node options (e.g., shape, color).
16+
"""
17+
self.x = x
18+
self.y = y
19+
self.label = label
20+
self.content = content
21+
self.options = kwargs
22+
23+
def to_tikz(self):
24+
"""
25+
Generate the TikZ code for this node.
26+
27+
Returns:
28+
- tikz_str (str): TikZ code string for the node.
29+
"""
30+
options = ', '.join(f"{k.replace('_', ' ')}={{{v}}}" for k, v in self.options.items())
31+
if options:
32+
options = f"[{options}]"
33+
return f" \\node{options} ({self.label}) at ({self.x}, {self.y}) {{{self.content}}};\n"
34+
35+
class Path:
36+
def __init__(self, nodes, **kwargs):
37+
"""
38+
Represents a path (line) connecting multiple nodes.
39+
40+
Parameters:
41+
- nodes (list of str): List of node names to connect.
42+
- **kwargs: Additional TikZ path options (e.g., style, color).
43+
"""
44+
self.nodes = nodes
45+
self.options = kwargs
46+
47+
def to_tikz(self):
48+
"""
49+
Generate the TikZ code for this path.
50+
51+
Returns:
52+
- tikz_str (str): TikZ code string for the path.
53+
"""
54+
options = ', '.join(f"{k.replace('_', ' ')}={{{v}}}" for k, v in self.options.items())
55+
if options:
56+
options = f"[{options}]"
57+
path_str = ' -- '.join(f"({node_label})" for node_label in self.nodes)
58+
return f" \\draw{options} {path_str};\n"
459

560
class TikzFigure:
661
def __init__(self, **kwargs):
@@ -23,48 +78,58 @@ def __init__(self, **kwargs):
2378
self._label = kwargs.get('label', None)
2479
self._grid = kwargs.get('grid', False)
2580

26-
# Initialize nodes and lines
81+
# Initialize lists to hold Node and Path objects
2782
self.nodes = []
28-
self.lines = []
83+
self.paths = []
84+
85+
# Counter for unnamed nodes
86+
self._node_counter = 0
2987

30-
def add_node(self, name, x, y, **kwargs):
88+
def add_node(self, x, y, label=None, content="", **kwargs):
3189
"""
3290
Add a node to the TikZ figure.
3391
3492
Parameters:
35-
- name (str): Name of the node.
3693
- x (float): X-coordinate of the node.
3794
- y (float): Y-coordinate of the node.
95+
- label (str, optional): Label of the node. If None, a default label will be assigned.
3896
- **kwargs: Additional TikZ node options (e.g., shape, color).
97+
98+
Returns:
99+
- node (Node): The Node object that was added.
39100
"""
40-
node = {
41-
'name': name,
42-
'x': x,
43-
'y': y,
44-
'options': kwargs
45-
}
101+
if label is None:
102+
label = f"node{self._node_counter}"
103+
node = Node(x=x, y=y, label=label, content=content, **kwargs)
46104
self.nodes.append(node)
105+
self._node_counter += 1
106+
return node
47107

48-
def add_line(self, nodes, **kwargs):
108+
def add_path(self, nodes, **kwargs):
49109
"""
50110
Add a line or path connecting multiple nodes.
51111
52112
Parameters:
53113
- nodes (list of str): List of node names to connect.
54-
- **kwargs: Additional TikZ line options (e.g., style, color).
114+
- **kwargs: Additional TikZ path options (e.g., style, color).
55115
56116
Examples:
57-
- add_line(['A', 'B', 'C'], color='blue')
117+
- add_path(['A', 'B', 'C'], color='blue')
58118
Connects nodes A -> B -> C with a blue line.
59119
"""
60120
if not isinstance(nodes, list):
61121
raise ValueError("nodes parameter must be a list of node names.")
62-
63-
line = {
64-
'nodes': nodes,
65-
'options': kwargs
66-
}
67-
self.lines.append(line)
122+
123+
nodes = [
124+
node.label if isinstance(node, Node)
125+
else node if isinstance(node, str)
126+
else ValueError(f"Invalid node type: {type(node)}")
127+
for node in nodes
128+
]
129+
130+
path = Path(nodes, **kwargs)
131+
self.paths.append(path)
132+
return path
68133

69134
def generate_tikz(self):
70135
"""
@@ -81,19 +146,11 @@ def generate_tikz(self):
81146

82147
# Add nodes
83148
for node in self.nodes:
84-
options = ', '.join(f"{k.replace('_',' ')}={{{v}}}" for k, v in node['options'].items())
85-
if options:
86-
options = f"[{options}]"
87-
tikz_script += f" \\node{options} ({node['name']}) at ({node['x']}, {node['y']}) {{{node['name']}}};\n"
88-
89-
# Add lines
90-
for line in self.lines:
91-
options = ', '.join(f"{k.replace('_',' ')}={{{v}}}" for k, v in line['options'].items())
92-
if options:
93-
options = f"[{options}]"
94-
# Create the path by connecting all nodes in the list
95-
path = ' -- '.join(f"({node_name})" for node_name in line['nodes'])
96-
tikz_script += f" \\draw{options} {path};\n"
149+
tikz_script += node.to_tikz()
150+
151+
# Add paths
152+
for path in self.paths:
153+
tikz_script += path.to_tikz()
97154

98155
tikz_script += "\\end{tikzpicture}"
99156

@@ -157,3 +214,11 @@ def compile_pdf(self, filename='output.pdf'):
157214
print(f"PDF successfully compiled and saved as '{filename}'.")
158215
else:
159216
print("PDF compilation failed. Please check the LaTeX log for details.")
217+
def plot_matplotlib(self, ax):
218+
"""
219+
Plot all lines on the provided axis.
220+
221+
Parameters:
222+
ax (matplotlib.axes.Axes): Axis on which to plot the lines.
223+
"""
224+

tutorials/tutorial_02.ipynb

Lines changed: 90 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,45 @@
22
"cells": [
33
{
44
"cell_type": "code",
5-
"execution_count": 1,
5+
"execution_count": 37,
66
"id": "3816e8ed-5107-4d8c-9e78-f801af118811",
77
"metadata": {},
8-
"outputs": [],
8+
"outputs": [
9+
{
10+
"name": "stdout",
11+
"output_type": "stream",
12+
"text": [
13+
"The autoreload extension is already loaded. To reload it, use:\n",
14+
" %reload_ext autoreload\n"
15+
]
16+
}
17+
],
918
"source": [
1019
"import maxplotlib.canvas.canvas as canvas\n",
11-
"\n",
20+
"from IPython.display import IFrame\n",
1221
"%load_ext autoreload\n",
1322
"%autoreload 2"
1423
]
1524
},
1625
{
1726
"cell_type": "code",
18-
"execution_count": 34,
27+
"execution_count": 62,
1928
"id": "650f0afa-f719-4495-b020-fc2b2df36bd7",
2029
"metadata": {},
2130
"outputs": [
2231
{
2332
"name": "stdout",
2433
"output_type": "stream",
2534
"text": [
35+
"A\n",
2636
"\\begin{tikzpicture}\n",
27-
" \\node[shape={circle}, draw={black}, fill={blue!20}] (A) at (0, 0) {A};\n",
28-
" \\node[shape={rectangle}, draw={red}] (B) at (2, 2) {B};\n",
29-
" \\node[shape={rectangle}, draw={red}] (C) at (2, 5) {C};\n",
30-
" \\node[shape={rectangle}, draw={red}] (D) at (1, 5) {D};\n",
31-
" \\draw[color={darkgreen}, style={dashed}, line width={2pt}] (A) -- (B) -- (C) -- (A) -- (D);\n",
37+
" \\node[shape={circle}, draw={black}, fill={blue!20}] (A) at (0, 0) {Origin node};\n",
38+
" \\node[shape={rectangle}, draw={red}] (B) at (2, 2) {};\n",
39+
" \\node[shape={rectangle}, draw={red}] (C) at (2, 5) {};\n",
40+
" \\node[shape={rectangle}, draw={red}] (node3) at (1, 5) {};\n",
41+
" \\draw[color={green}, style={solid}, line width={2pt}] (A) -- (B) -- (C) -- (A) -- (node3);\n",
3242
"\\end{tikzpicture}\n",
33-
"An error occurred while compiling the LaTeX document:\n",
34-
"\n"
43+
"PDF successfully compiled and saved as 'my_figure.pdf'.\n"
3544
]
3645
}
3746
],
@@ -40,32 +49,94 @@
4049
"tikz = c.add_tikzfigure(grid=False)\n",
4150
"\n",
4251
"# Add nodes\n",
43-
"tikz.add_node('A', 0, 0, shape='circle', draw='black', fill='blue!20')\n",
44-
"tikz.add_node('B', 2, 2, shape='rectangle', draw='red')\n",
45-
"tikz.add_node('C', 2, 5, shape='rectangle', draw='red')\n",
46-
"tikz.add_node('D', 1, 5, shape='rectangle', draw='red')\n",
52+
"node_a = tikz.add_node(0, 0, 'A', content='Origin node', shape='circle', draw='black', fill='blue!20')\n",
53+
"tikz.add_node(2, 2, 'B', shape='rectangle', draw='red')\n",
54+
"tikz.add_node(2, 5, 'C', shape='rectangle', draw='red')\n",
55+
"last_node = tikz.add_node(1, 5, shape='rectangle', draw='red')\n",
56+
"\n",
57+
"print(node_a.label)\n",
4758
"\n",
4859
"# Add a line between nodes \n",
49-
"tikz.add_line(['A', 'B', 'C', 'A', 'D'], color='darkgreen', style='dashed', line_width='2pt')\n",
60+
"tikz.add_path([node_a, 'B', 'C', 'A', last_node], color='green', style='solid', line_width='2pt')\n",
5061
"\n",
5162
"# Generate the TikZ script\n",
5263
"script = tikz.generate_tikz()\n",
5364
"print(script)\n",
54-
"tikz.compile_pdf('my_figure.pdf')"
65+
"tikz.compile_pdf('my_figure.pdf')\n",
66+
"# Replace 'path_to_pdf' with the path to your PDF file\n",
67+
"\n"
5568
]
5669
},
5770
{
5871
"cell_type": "code",
59-
"execution_count": null,
72+
"execution_count": 73,
6073
"id": "344589d9-c60f-4d01-8171-e35db585f1ad",
6174
"metadata": {},
75+
"outputs": [
76+
{
77+
"name": "stdout",
78+
"output_type": "stream",
79+
"text": [
80+
"A\n",
81+
"800 400.0 2.6666666666666665 1.3333333333333333\n"
82+
]
83+
},
84+
{
85+
"data": {
86+
"image/png": "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",
87+
"text/plain": [
88+
"<Figure size 800x400 with 2 Axes>"
89+
]
90+
},
91+
"metadata": {},
92+
"output_type": "display_data"
93+
},
94+
{
95+
"data": {
96+
"text/plain": [
97+
"(<Figure size 800x400 with 2 Axes>,\n",
98+
" array([[<Axes: >, <Axes: >]], dtype=object))"
99+
]
100+
},
101+
"execution_count": 73,
102+
"metadata": {},
103+
"output_type": "execute_result"
104+
}
105+
],
106+
"source": [
107+
"c = canvas.Canvas(ncols=2,width=800, ratio=0.5)\n",
108+
"tikz = c.add_tikzfigure(grid=False)\n",
109+
"\n",
110+
"# Add nodes\n",
111+
"node_a = tikz.add_node(0, 0, 'A', content='Origin node', shape='circle', draw='black', fill='blue!20')\n",
112+
"tikz.add_node(2, 2, 'B', shape='rectangle', draw='red')\n",
113+
"tikz.add_node(2, 5, 'C', shape='rectangle', draw='red')\n",
114+
"last_node = tikz.add_node(1, 5, shape='rectangle', draw='red')\n",
115+
"\n",
116+
"print(node_a.label)\n",
117+
"\n",
118+
"# Add a line between nodes \n",
119+
"tikz.add_path([node_a, 'B', 'C', 'A', last_node], color='green', style='solid', line_width='2pt')\n",
120+
"\n",
121+
"# Generate the TikZ script\n",
122+
"#script = tikz.generate_tikz()\n",
123+
"\n",
124+
"# Replace 'path_to_pdf' with the path to your PDF file\n",
125+
"c.plot(backend='matplotlib')"
126+
]
127+
},
128+
{
129+
"cell_type": "code",
130+
"execution_count": null,
131+
"id": "7c37d9b8-256b-4907-9c95-288b18cb396d",
132+
"metadata": {},
62133
"outputs": [],
63134
"source": []
64135
},
65136
{
66137
"cell_type": "code",
67138
"execution_count": null,
68-
"id": "7c37d9b8-256b-4907-9c95-288b18cb396d",
139+
"id": "3081683f-8f1e-47ad-83bd-5a38899dde33",
69140
"metadata": {},
70141
"outputs": [],
71142
"source": []

0 commit comments

Comments
 (0)