Skip to content

Commit abc97b3

Browse files
committed
extract draw_plot method for plotting measures using matplotlib
1 parent 87d937e commit abc97b3

File tree

4 files changed

+45
-22
lines changed

4 files changed

+45
-22
lines changed

mesa/visualization/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Solara based visualization for Mesa models."""
22

3-
from mesa.visualization.mpl_space_drawing import (
3+
from mesa.visualization.mpl_drawing import (
4+
draw_plot,
45
draw_space,
56
)
67

@@ -15,6 +16,7 @@
1516
"Slider",
1617
"make_space_altair",
1718
"draw_space",
19+
"draw_plot",
1820
"make_plot_component",
1921
"make_space_component",
2022
]

mesa/visualization/components/matplotlib_components.py

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
import warnings
66
from collections.abc import Callable
77

8-
import matplotlib.pyplot as plt
98
import solara
109
from matplotlib.figure import Figure
1110

12-
from mesa.visualization.mpl_space_drawing import draw_space
11+
from mesa.visualization.mpl_drawing import draw_plot, draw_space
1312
from mesa.visualization.utils import update_counter
1413

1514

@@ -151,26 +150,10 @@ def PlotMatplotlib(
151150
"""
152151
update_counter.get()
153152
fig = Figure()
154-
ax = fig.subplots()
155-
df = model.datacollector.get_model_vars_dataframe()
156-
if isinstance(measure, str):
157-
ax.plot(df.loc[:, measure])
158-
ax.set_ylabel(measure)
159-
elif isinstance(measure, dict):
160-
for m, color in measure.items():
161-
ax.plot(df.loc[:, m], label=m, color=color)
162-
ax.legend(loc="best")
163-
elif isinstance(measure, list | tuple):
164-
for m in measure:
165-
ax.plot(df.loc[:, m], label=m)
166-
ax.legend(loc="best")
167-
153+
ax = fig.add_subplot()
154+
draw_plot(model, measure, ax)
168155
if post_process is not None:
169156
post_process(ax)
170-
171-
ax.set_xlabel("Step")
172-
# Set integer x axis
173-
ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True))
174157
solara.FigureMatplotlib(
175158
fig, format=save_format, bbox_inches="tight", dependencies=dependencies
176159
)

mesa/visualization/mpl_space_drawing.py renamed to mesa/visualization/mpl_drawing.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,3 +556,41 @@ def _scatter(ax: Axes, arguments, **kwargs):
556556
**{k: v[logical] for k, v in arguments.items()},
557557
**kwargs,
558558
)
559+
560+
561+
def draw_plot(
562+
model,
563+
measure,
564+
ax: Axes | None = None,
565+
):
566+
"""Create a Matplotlib-based plot for a measure or measures.
567+
568+
Args:
569+
model (mesa.Model): The model instance.
570+
measure (str | dict[str, str] | list[str] | tuple[str]): Measure(s) to plot.
571+
ax: the axes upon which to draw the plot
572+
post_process: a user-specified callable to do post-processing called with the Axes instance.
573+
574+
Returns:
575+
plt.Axes: The Axes object with the plot drawn onto it.
576+
"""
577+
if ax is None:
578+
_, ax = plt.subplots()
579+
df = model.datacollector.get_model_vars_dataframe()
580+
if isinstance(measure, str):
581+
ax.plot(df.loc[:, measure])
582+
ax.set_ylabel(measure)
583+
elif isinstance(measure, dict):
584+
for m, color in measure.items():
585+
ax.plot(df.loc[:, m], label=m, color=color)
586+
ax.legend(loc="best")
587+
elif isinstance(measure, list | tuple):
588+
for m in measure:
589+
ax.plot(df.loc[:, m], label=m)
590+
ax.legend(loc="best")
591+
592+
ax.set_xlabel("Step")
593+
# Set integer x axis
594+
ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True))
595+
596+
return ax

tests/test_components_matplotlib.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
PropertyLayer,
1818
SingleGrid,
1919
)
20-
from mesa.visualization.mpl_space_drawing import (
20+
from mesa.visualization.mpl_drawing import (
2121
draw_continuous_space,
2222
draw_hex_grid,
2323
draw_network,

0 commit comments

Comments
 (0)