From 730ef99bb160312c29fd8df765a4655d3c0dcc61 Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Thu, 31 Oct 2024 09:15:40 +0100 Subject: [PATCH 01/21] api reorganization Closes #2434. --- docs/apis/visualization.md | 11 +- mesa/visualization/__init__.py | 6 +- mesa/visualization/components/__init__.py | 0 .../{altair.py => altair_components.py} | 0 .../components/matplotlib_components.py | 172 +++++++++++++++++ .../{matplotlib.py => mpl_space_drawing.py} | 175 +----------------- tests/test_components_matplotlib.py | 2 +- 7 files changed, 194 insertions(+), 172 deletions(-) create mode 100644 mesa/visualization/components/__init__.py rename mesa/visualization/components/{altair.py => altair_components.py} (100%) create mode 100644 mesa/visualization/components/matplotlib_components.py rename mesa/visualization/components/{matplotlib.py => mpl_space_drawing.py} (77%) diff --git a/docs/apis/visualization.md b/docs/apis/visualization.md index 7815ec568b8..0a5e059802a 100644 --- a/docs/apis/visualization.md +++ b/docs/apis/visualization.md @@ -24,7 +24,14 @@ For a detailed tutorial, please refer to our [Visualization Tutorial](../tutoria ## Matplotlib-based components ```{eval-rst} -.. automodule:: mesa.visualization.components.matplotlib +.. automodule:: mesa.visualization.components.matplotlib_components + :members: + :undoc-members: + :show-inheritance: +``` + +```{eval-rst} +.. automodule:: mesa.visualization.components.mpl_space_drawing :members: :undoc-members: :show-inheritance: @@ -33,7 +40,7 @@ For a detailed tutorial, please refer to our [Visualization Tutorial](../tutoria ## Altair-based components ```{eval-rst} -.. automodule:: mesa.visualization.components.altair +.. automodule:: mesa.visualization.components.altair_components :members: :undoc-members: :show-inheritance: diff --git a/mesa/visualization/__init__.py b/mesa/visualization/__init__.py index 4bac98704cc..faf11c7e923 100644 --- a/mesa/visualization/__init__.py +++ b/mesa/visualization/__init__.py @@ -1,7 +1,9 @@ """Solara based visualization for Mesa models.""" -from .components.altair import make_space_altair -from .components.matplotlib import make_plot_component, make_space_component +from .components.altair_components import make_space_altair +from .components.matplotlib_components import make_plot_component, make_space_component, make_plot_measure, make_space_matplotlib +from .components.mpl_space_drawing import (draw_space, draw_continuous_space, draw_network, + draw_orthogonal_grid, draw_voroinoi_grid, draw_hex_grid, draw_property_layers) from .solara_viz import JupyterViz, SolaraViz from .UserParam import Slider diff --git a/mesa/visualization/components/__init__.py b/mesa/visualization/components/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mesa/visualization/components/altair.py b/mesa/visualization/components/altair_components.py similarity index 100% rename from mesa/visualization/components/altair.py rename to mesa/visualization/components/altair_components.py diff --git a/mesa/visualization/components/matplotlib_components.py b/mesa/visualization/components/matplotlib_components.py new file mode 100644 index 00000000000..c24e8765b60 --- /dev/null +++ b/mesa/visualization/components/matplotlib_components.py @@ -0,0 +1,172 @@ +"""Matplotlib based solara components for visualization MESA spaces and plots.""" + +import warnings +from collections.abc import Callable + +import matplotlib.pyplot as plt +import solara +from matplotlib.figure import Figure + +from mesa.visualization.components.mpl_space_drawing import draw_space +from mesa.visualization.utils import update_counter + + +def make_space_matplotlib(*args, **kwargs): # noqa: D103 + warnings.warn( + "make_space_matplotlib has been renamed to make_space_component", + DeprecationWarning, + stacklevel=2, + ) + return make_space_component(*args, **kwargs) + + +def make_space_component( + agent_portrayal: Callable | None = None, + propertylayer_portrayal: dict | None = None, + post_process: Callable | None = None, + **space_drawing_kwargs, +): + """Create a Matplotlib-based space visualization component. + + Args: + agent_portrayal: Function to portray agents. + propertylayer_portrayal: Dictionary of PropertyLayer portrayal specifications + post_process : a callable that will be called with the Axes instance. Allows for fine tuning plots (e.g., control ticks) + space_drawing_kwargs : additional keyword arguments to be passed on to the underlying space drawer function. See + the functions for drawing the various spaces for further details. + + ``agent_portrayal`` is called with an agent and should return a dict. Valid fields in this dict are "color", + "size", "marker", and "zorder". Other field are ignored and will result in a user warning. + + + Returns: + function: A function that creates a SpaceMatplotlib component + """ + if agent_portrayal is None: + + def agent_portrayal(a): + return {} + + def MakeSpaceMatplotlib(model): + return SpaceMatplotlib( + model, + agent_portrayal, + propertylayer_portrayal, + post_process=post_process, + **space_drawing_kwargs, + ) + + return MakeSpaceMatplotlib + + +@solara.component +def SpaceMatplotlib( + model, + agent_portrayal, + propertylayer_portrayal, + dependencies: list[any] | None = None, + post_process: Callable | None = None, + **space_drawing_kwargs, +): + """Create a Matplotlib-based space visualization component.""" + update_counter.get() + + space = getattr(model, "grid", None) + if space is None: + space = getattr(model, "space", None) + + fig = Figure() + ax = fig.add_subplot() + + draw_space( + space, + agent_portrayal, + propertylayer_portrayal=propertylayer_portrayal, + ax=ax, + post_process=post_process, + **space_drawing_kwargs, + ) + + solara.FigureMatplotlib( + fig, format="png", bbox_inches="tight", dependencies=dependencies + ) + + +def make_plot_measure(*args, **kwargs): # noqa: D103 + warnings.warn( + "make_plot_measure has been renamed to make_plot_component", + DeprecationWarning, + stacklevel=2, + ) + return make_plot_component(*args, **kwargs) + + +def make_plot_component( + measure: str | dict[str, str] | list[str] | tuple[str], + post_process: Callable | None = None, + save_format="png", +): + """Create a plotting function for a specified measure. + + Args: + measure (str | dict[str, str] | list[str] | tuple[str]): Measure(s) to plot. + post_process: a user-specified callable to do post-processing called with the Axes instance. + save_format: save format of figure in solara backend + + Returns: + function: A function that creates a PlotMatplotlib component. + """ + + def MakePlotMatplotlib(model): + return PlotMatplotlib( + model, measure, post_process=post_process, save_format=save_format + ) + + return MakePlotMatplotlib + + +@solara.component +def PlotMatplotlib( + model, + measure, + dependencies: list[any] | None = None, + post_process: Callable | None = None, + save_format="png", +): + """Create a Matplotlib-based plot for a measure or measures. + + Args: + model (mesa.Model): The model instance. + measure (str | dict[str, str] | list[str] | tuple[str]): Measure(s) to plot. + dependencies (list[any] | None): Optional dependencies for the plot. + post_process: a user-specified callable to do post-processing called with the Axes instance. + save_format: format used for saving the figure. + + Returns: + solara.FigureMatplotlib: A component for rendering the plot. + """ + update_counter.get() + fig = Figure() + ax = fig.subplots() + df = model.datacollector.get_model_vars_dataframe() + if isinstance(measure, str): + ax.plot(df.loc[:, measure]) + ax.set_ylabel(measure) + elif isinstance(measure, dict): + for m, color in measure.items(): + ax.plot(df.loc[:, m], label=m, color=color) + ax.legend(loc="best") + elif isinstance(measure, list | tuple): + for m in measure: + ax.plot(df.loc[:, m], label=m) + ax.legend(loc="best") + + if post_process is not None: + post_process(ax) + + ax.set_xlabel("Step") + # Set integer x axis + ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True)) + solara.FigureMatplotlib( + fig, format=save_format, bbox_inches="tight", dependencies=dependencies + ) diff --git a/mesa/visualization/components/matplotlib.py b/mesa/visualization/components/mpl_space_drawing.py similarity index 77% rename from mesa/visualization/components/matplotlib.py rename to mesa/visualization/components/mpl_space_drawing.py index 09b281a3e17..06ca9460b49 100644 --- a/mesa/visualization/components/matplotlib.py +++ b/mesa/visualization/components/mpl_space_drawing.py @@ -1,4 +1,10 @@ -"""Matplotlib based solara components for visualization MESA spaces and plots.""" +"""Helper functions for drawing mesa spaces with matplotlib. + +These functions are used by the provided matplotlib components, but can also be used to quickly visualize +a space with matplotlib for example when creating an mp4 of a movie run or when needing a figure +for a paper. + +""" import itertools import math @@ -6,15 +12,13 @@ from collections.abc import Callable from typing import Any -import matplotlib.pyplot as plt import networkx as nx import numpy as np -import solara +from matplotlib import pyplot as plt from matplotlib.axes import Axes from matplotlib.cm import ScalarMappable from matplotlib.collections import PatchCollection from matplotlib.colors import LinearSegmentedColormap, Normalize, to_rgba -from matplotlib.figure import Figure from matplotlib.patches import RegularPolygon import mesa @@ -32,95 +36,12 @@ PropertyLayer, SingleGrid, ) -from mesa.visualization.utils import update_counter -# For typing OrthogonalGrid = SingleGrid | MultiGrid | OrthogonalMooreGrid | OrthogonalVonNeumannGrid HexGrid = HexSingleGrid | HexMultiGrid | mesa.experimental.cell_space.HexGrid Network = NetworkGrid | mesa.experimental.cell_space.Network -def make_space_matplotlib(*args, **kwargs): # noqa: D103 - warnings.warn( - "make_space_matplotlib has been renamed to make_space_component", - DeprecationWarning, - stacklevel=2, - ) - return make_space_component(*args, **kwargs) - - -def make_space_component( - agent_portrayal: Callable | None = None, - propertylayer_portrayal: dict | None = None, - post_process: Callable | None = None, - **space_drawing_kwargs, -): - """Create a Matplotlib-based space visualization component. - - Args: - agent_portrayal: Function to portray agents. - propertylayer_portrayal: Dictionary of PropertyLayer portrayal specifications - post_process : a callable that will be called with the Axes instance. Allows for fine tuning plots (e.g., control ticks) - space_drawing_kwargs : additional keyword arguments to be passed on to the underlying space drawer function. See - the functions for drawing the various spaces for further details. - - ``agent_portrayal`` is called with an agent and should return a dict. Valid fields in this dict are "color", - "size", "marker", and "zorder". Other field are ignored and will result in a user warning. - - - Returns: - function: A function that creates a SpaceMatplotlib component - """ - if agent_portrayal is None: - - def agent_portrayal(a): - return {} - - def MakeSpaceMatplotlib(model): - return SpaceMatplotlib( - model, - agent_portrayal, - propertylayer_portrayal, - post_process=post_process, - **space_drawing_kwargs, - ) - - return MakeSpaceMatplotlib - - -@solara.component -def SpaceMatplotlib( - model, - agent_portrayal, - propertylayer_portrayal, - dependencies: list[any] | None = None, - post_process: Callable | None = None, - **space_drawing_kwargs, -): - """Create a Matplotlib-based space visualization component.""" - update_counter.get() - - space = getattr(model, "grid", None) - if space is None: - space = getattr(model, "space", None) - - fig = Figure() - ax = fig.add_subplot() - - draw_space( - space, - agent_portrayal, - propertylayer_portrayal=propertylayer_portrayal, - ax=ax, - post_process=post_process, - **space_drawing_kwargs, - ) - - solara.FigureMatplotlib( - fig, format="png", bbox_inches="tight", dependencies=dependencies - ) - - def collect_agent_data( space: OrthogonalGrid | HexGrid | Network | ContinuousSpace | VoronoiGrid, agent_portrayal: Callable, @@ -625,83 +546,3 @@ def _scatter(ax: Axes, arguments): zorder=z_order, **{k: v[logical] for k, v in arguments.items()}, ) - - -def make_plot_measure(*args, **kwargs): # noqa: D103 - warnings.warn( - "make_plot_measure has been renamed to make_plot_component", - DeprecationWarning, - stacklevel=2, - ) - return make_plot_component(*args, **kwargs) - - -def make_plot_component( - measure: str | dict[str, str] | list[str] | tuple[str], - post_process: Callable | None = None, - save_format="png", -): - """Create a plotting function for a specified measure. - - Args: - measure (str | dict[str, str] | list[str] | tuple[str]): Measure(s) to plot. - post_process: a user-specified callable to do post-processing called with the Axes instance. - save_format: save format of figure in solara backend - - Returns: - function: A function that creates a PlotMatplotlib component. - """ - - def MakePlotMatplotlib(model): - return PlotMatplotlib( - model, measure, post_process=post_process, save_format=save_format - ) - - return MakePlotMatplotlib - - -@solara.component -def PlotMatplotlib( - model, - measure, - dependencies: list[any] | None = None, - post_process: Callable | None = None, - save_format="png", -): - """Create a Matplotlib-based plot for a measure or measures. - - Args: - model (mesa.Model): The model instance. - measure (str | dict[str, str] | list[str] | tuple[str]): Measure(s) to plot. - dependencies (list[any] | None): Optional dependencies for the plot. - post_process: a user-specified callable to do post-processing called with the Axes instance. - save_format: format used for saving the figure. - - Returns: - solara.FigureMatplotlib: A component for rendering the plot. - """ - update_counter.get() - fig = Figure() - ax = fig.subplots() - df = model.datacollector.get_model_vars_dataframe() - if isinstance(measure, str): - ax.plot(df.loc[:, measure]) - ax.set_ylabel(measure) - elif isinstance(measure, dict): - for m, color in measure.items(): - ax.plot(df.loc[:, m], label=m, color=color) - ax.legend(loc="best") - elif isinstance(measure, list | tuple): - for m in measure: - ax.plot(df.loc[:, m], label=m) - ax.legend(loc="best") - - if post_process is not None: - post_process(ax) - - ax.set_xlabel("Step") - # Set integer x axis - ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True)) - solara.FigureMatplotlib( - fig, format=save_format, bbox_inches="tight", dependencies=dependencies - ) diff --git a/tests/test_components_matplotlib.py b/tests/test_components_matplotlib.py index c85dd1ce292..0f80a9d862f 100644 --- a/tests/test_components_matplotlib.py +++ b/tests/test_components_matplotlib.py @@ -17,7 +17,7 @@ PropertyLayer, SingleGrid, ) -from mesa.visualization.components.matplotlib import ( +from mesa.visualization.components.mpl_space_drawing import ( draw_continuous_space, draw_hex_grid, draw_network, From ac4cd942672de57cb4a27247baf398bed2d221bf Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 08:29:48 +0000 Subject: [PATCH 02/21] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mesa/visualization/__init__.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/mesa/visualization/__init__.py b/mesa/visualization/__init__.py index faf11c7e923..93981ca4cec 100644 --- a/mesa/visualization/__init__.py +++ b/mesa/visualization/__init__.py @@ -1,9 +1,21 @@ """Solara based visualization for Mesa models.""" from .components.altair_components import make_space_altair -from .components.matplotlib_components import make_plot_component, make_space_component, make_plot_measure, make_space_matplotlib -from .components.mpl_space_drawing import (draw_space, draw_continuous_space, draw_network, - draw_orthogonal_grid, draw_voroinoi_grid, draw_hex_grid, draw_property_layers) +from .components.matplotlib_components import ( + make_plot_component, + make_plot_measure, + make_space_component, + make_space_matplotlib, +) +from .components.mpl_space_drawing import ( + draw_continuous_space, + draw_hex_grid, + draw_network, + draw_orthogonal_grid, + draw_property_layers, + draw_space, + draw_voroinoi_grid, +) from .solara_viz import JupyterViz, SolaraViz from .UserParam import Slider From c352ddae1f801cbcb74216077f9ffb73e6ab18e6 Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Thu, 31 Oct 2024 16:36:33 +0100 Subject: [PATCH 03/21] ruff related fixes --- mesa/visualization/__init__.py | 9 +++++++++ mesa/visualization/components/__init__.py | 1 + 2 files changed, 10 insertions(+) diff --git a/mesa/visualization/__init__.py b/mesa/visualization/__init__.py index 93981ca4cec..2f72317af17 100644 --- a/mesa/visualization/__init__.py +++ b/mesa/visualization/__init__.py @@ -26,4 +26,13 @@ "make_space_altair", "make_space_component", "make_plot_component", + "make_plot_measure", + "make_space_matplotlib", + "draw_continuous_space", + "draw_hex_grid", + "draw_network", + "draw_orthogonal_grid", + "draw_property_layers", + "draw_space", + "draw_voroinoi_grid", ] diff --git a/mesa/visualization/components/__init__.py b/mesa/visualization/components/__init__.py index e69de29bb2d..4a754bf2054 100644 --- a/mesa/visualization/components/__init__.py +++ b/mesa/visualization/components/__init__.py @@ -0,0 +1 @@ +"""custom solara components.""" From 234c54e6a58f63405c7bc05a7ff70a8dd6ea2d17 Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Thu, 31 Oct 2024 16:40:22 +0100 Subject: [PATCH 04/21] Update test_solara_viz.py --- tests/test_solara_viz.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_solara_viz.py b/tests/test_solara_viz.py index af6badd0bc2..a946a05ad3d 100644 --- a/tests/test_solara_viz.py +++ b/tests/test_solara_viz.py @@ -6,9 +6,9 @@ import solara import mesa -import mesa.visualization.components.altair -import mesa.visualization.components.matplotlib -from mesa.visualization.components.matplotlib import make_space_component +import mesa.visualization.components.altair_components +import mesa.visualization.components.matplotlib_components +from mesa.visualization.components.matplotlib_components import make_space_component from mesa.visualization.solara_viz import Slider, SolaraViz, UserInputs From 8adb5770f621042cbc2ececb60a0447c8cc2089a Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Thu, 31 Oct 2024 16:46:43 +0100 Subject: [PATCH 05/21] Update test_solara_viz.py --- tests/test_solara_viz.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_solara_viz.py b/tests/test_solara_viz.py index a946a05ad3d..1d9b739e40b 100644 --- a/tests/test_solara_viz.py +++ b/tests/test_solara_viz.py @@ -88,10 +88,10 @@ def Test(user_params): def test_call_space_drawer(mocker): # noqa: D103 mock_space_matplotlib = mocker.spy( - mesa.visualization.components.matplotlib, "SpaceMatplotlib" + mesa.visualization.components.matplotlib_components, "SpaceMatplotlib" ) - mock_space_altair = mocker.spy(mesa.visualization.components.altair, "SpaceAltair") + mock_space_altair = mocker.spy(mesa.visualization.components.altair_components, "SpaceAltair") model = mesa.Model() mocker.patch.object(mesa.Model, "__init__", return_value=None) From 38cf59a7de4924d7c3162aa5fb0240379c0c0158 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:48:19 +0000 Subject: [PATCH 06/21] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_solara_viz.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_solara_viz.py b/tests/test_solara_viz.py index 1d9b739e40b..5d300eabc27 100644 --- a/tests/test_solara_viz.py +++ b/tests/test_solara_viz.py @@ -91,7 +91,9 @@ def test_call_space_drawer(mocker): # noqa: D103 mesa.visualization.components.matplotlib_components, "SpaceMatplotlib" ) - mock_space_altair = mocker.spy(mesa.visualization.components.altair_components, "SpaceAltair") + mock_space_altair = mocker.spy( + mesa.visualization.components.altair_components, "SpaceAltair" + ) model = mesa.Model() mocker.patch.object(mesa.Model, "__init__", return_value=None) From 227739dea617b0773ac778db4d5de891550323d9 Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Thu, 31 Oct 2024 17:01:34 +0100 Subject: [PATCH 07/21] Update solara_viz.py --- mesa/visualization/solara_viz.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesa/visualization/solara_viz.py b/mesa/visualization/solara_viz.py index 4bca98d8b54..d5d83f437ea 100644 --- a/mesa/visualization/solara_viz.py +++ b/mesa/visualization/solara_viz.py @@ -31,7 +31,7 @@ import reacton.core import solara -import mesa.visualization.components.altair as components_altair +import mesa.visualization.components.altair_components as components_altair from mesa.visualization.UserParam import Slider from mesa.visualization.utils import force_update, update_counter From ec47215c684883fb4f91066e1eca994b33baec43 Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Thu, 31 Oct 2024 21:02:12 +0100 Subject: [PATCH 08/21] reorganization and renaming --- .../advanced/epstein_civil_violence/app.py | 8 +-- mesa/examples/advanced/pd_grid/app.py | 10 ++- mesa/examples/advanced/sugarscape_g1mt/app.py | 4 +- mesa/visualization/__init__.py | 15 +++-- mesa/visualization/components/__init__.py | 62 +++++++++++++++++++ .../components/altair_components.py | 2 +- .../components/matplotlib_components.py | 8 +-- tests/test_solara_viz.py | 8 +-- 8 files changed, 93 insertions(+), 24 deletions(-) diff --git a/mesa/examples/advanced/epstein_civil_violence/app.py b/mesa/examples/advanced/epstein_civil_violence/app.py index d3eb4643d87..c36c1bc41ae 100644 --- a/mesa/examples/advanced/epstein_civil_violence/app.py +++ b/mesa/examples/advanced/epstein_civil_violence/app.py @@ -7,8 +7,8 @@ from mesa.visualization import ( Slider, SolaraViz, - make_plot_component, - make_space_component, + make_mpl_plot_component, + make_mpl_space_component, ) COP_COLOR = "#000000" @@ -54,11 +54,11 @@ def post_process(ax): "max_jail_term": Slider("Max Jail Term", 30, 0, 50, 1), } -space_component = make_space_component( +space_component = make_mpl_space_component( citizen_cop_portrayal, post_process=post_process, draw_grid=False ) -chart_component = make_plot_component( +chart_component = make_mpl_plot_component( {state.name.lower(): agent_colors[state] for state in CitizenState} ) diff --git a/mesa/examples/advanced/pd_grid/app.py b/mesa/examples/advanced/pd_grid/app.py index fafedde6b09..b50d0adec96 100644 --- a/mesa/examples/advanced/pd_grid/app.py +++ b/mesa/examples/advanced/pd_grid/app.py @@ -3,7 +3,11 @@ """ from mesa.examples.advanced.pd_grid.model import PdGrid -from mesa.visualization import SolaraViz, make_plot_component, make_space_component +from mesa.visualization import ( + SolaraViz, + make_mpl_plot_component, + make_mpl_space_component, +) from mesa.visualization.UserParam import Slider @@ -32,10 +36,10 @@ def pd_agent_portrayal(agent): # Create grid visualization component using Altair -grid_viz = make_space_component(agent_portrayal=pd_agent_portrayal) +grid_viz = make_mpl_space_component(agent_portrayal=pd_agent_portrayal) # Create plot for tracking cooperating agents over time -plot_component = make_plot_component("Cooperating_Agents") +plot_component = make_mpl_plot_component("Cooperating_Agents") # Initialize model initial_model = PdGrid() diff --git a/mesa/examples/advanced/sugarscape_g1mt/app.py b/mesa/examples/advanced/sugarscape_g1mt/app.py index 8a5441cc54d..029cc8b2231 100644 --- a/mesa/examples/advanced/sugarscape_g1mt/app.py +++ b/mesa/examples/advanced/sugarscape_g1mt/app.py @@ -4,7 +4,7 @@ from mesa.examples.advanced.sugarscape_g1mt.agents import Trader from mesa.examples.advanced.sugarscape_g1mt.model import SugarscapeG1mt -from mesa.visualization import SolaraViz, make_plot_component +from mesa.visualization import SolaraViz, make_mpl_plot_component def SpaceDrawer(model): @@ -55,7 +55,7 @@ def portray(g): page = SolaraViz( model1, - components=[SpaceDrawer, make_plot_component(["Trader", "Price"])], + components=[SpaceDrawer, make_mpl_plot_component(["Trader", "Price"])], name="Sugarscape {G1, M, T}", play_interval=150, ) diff --git a/mesa/visualization/__init__.py b/mesa/visualization/__init__.py index 2f72317af17..e3d411f6459 100644 --- a/mesa/visualization/__init__.py +++ b/mesa/visualization/__init__.py @@ -1,10 +1,11 @@ """Solara based visualization for Mesa models.""" -from .components.altair_components import make_space_altair +from .components import make_plot_component, make_space_component +from .components.altair_components import make_altair_space from .components.matplotlib_components import ( - make_plot_component, + make_mpl_plot_component, + make_mpl_space_component, make_plot_measure, - make_space_component, make_space_matplotlib, ) from .components.mpl_space_drawing import ( @@ -23,9 +24,9 @@ "JupyterViz", "SolaraViz", "Slider", - "make_space_altair", - "make_space_component", - "make_plot_component", + "make_altair_space", + "make_mpl_space_component", + "make_mpl_plot_component", "make_plot_measure", "make_space_matplotlib", "draw_continuous_space", @@ -35,4 +36,6 @@ "draw_property_layers", "draw_space", "draw_voroinoi_grid", + "make_plot_component", + "make_space_component" ] diff --git a/mesa/visualization/components/__init__.py b/mesa/visualization/components/__init__.py index 4a754bf2054..fffbe5df4a5 100644 --- a/mesa/visualization/components/__init__.py +++ b/mesa/visualization/components/__init__.py @@ -1 +1,63 @@ """custom solara components.""" + + +from collections.abc import Callable + +from .altair_components import make_altair_space +from .matplotlib_components import make_mpl_plot_component, make_mpl_space_component + + +def make_space_component( + agent_portrayal: Callable | None = None, + propertylayer_portrayal: dict | None = None, + post_process: Callable | None = None, + backend: str = "matplotlib", + **space_drawing_kwargs, +): + """Create a Matplotlib-based space visualization component. + + Args: + agent_portrayal: Function to portray agents. + propertylayer_portrayal: Dictionary of PropertyLayer portrayal specifications + post_process : a callable that will be called with the Axes instance. Allows for fine-tuning plots (e.g., control ticks) + backend: the backend to use {"matplotlib", "altair"} + space_drawing_kwargs : additional keyword arguments to be passed on to the underlying backend specific space drawer function. See + the functions for drawing the various spaces for the appropriate backend further details. + + + Returns: + function: A function that creates a space component + """ + if backend == "matplotlib": + return make_mpl_space_component(agent_portrayal, propertylayer_portrayal, post_process, **space_drawing_kwargs) + elif backend == "altair": + return make_altair_space(agent_portrayal, propertylayer_portrayal, post_process, **space_drawing_kwargs) + else: + raise ValueError(f"unknown backend {backend}, must be one of matplotlib, altair") + +def make_plot_component( + measure: str | dict[str, str] | list[str] | tuple[str], + post_process: Callable | None = None, + backend: str = "matplotlib", + **plot_drawing_kwargs, +): + """Create a plotting function for a specified measure using the specified backend. + + Args: + measure (str | dict[str, str] | list[str] | tuple[str]): Measure(s) to plot. + post_process: a user-specified callable to do post-processing called with the Axes instance. + backend: the backend to use {"matplotlib", "altair"} + plot_drawing_kwargs: additional keyword arguments to pass onto the backend specific function for making a plotting component + + Notes: + altair plotting backend is not yet implemented and planned for mesa 3.1. + + Returns: + function: A function that creates a plot component + """ + if backend == "matplotlib": + return make_mpl_plot_component(measure, post_process, **plot_drawing_kwargs) + elif backend == "altair": + raise NotImplementedError("altair line plots are not yet implemented") + else: + raise ValueError(f"unknown backend {backend}, must be one of matplotlib, altair") diff --git a/mesa/visualization/components/altair_components.py b/mesa/visualization/components/altair_components.py index 5aeee84761d..e04e3e512d6 100644 --- a/mesa/visualization/components/altair_components.py +++ b/mesa/visualization/components/altair_components.py @@ -12,7 +12,7 @@ from mesa.visualization.utils import update_counter -def make_space_altair(agent_portrayal=None): # noqa: D103 +def make_altair_space(agent_portrayal, propertylayer_portrayal, post_process, **space_drawing_kwargs): # noqa: D103 if agent_portrayal is None: def agent_portrayal(a): diff --git a/mesa/visualization/components/matplotlib_components.py b/mesa/visualization/components/matplotlib_components.py index c24e8765b60..26769e5c5be 100644 --- a/mesa/visualization/components/matplotlib_components.py +++ b/mesa/visualization/components/matplotlib_components.py @@ -17,10 +17,10 @@ def make_space_matplotlib(*args, **kwargs): # noqa: D103 DeprecationWarning, stacklevel=2, ) - return make_space_component(*args, **kwargs) + return make_mpl_space_component(*args, **kwargs) -def make_space_component( +def make_mpl_space_component( agent_portrayal: Callable | None = None, propertylayer_portrayal: dict | None = None, post_process: Callable | None = None, @@ -98,10 +98,10 @@ def make_plot_measure(*args, **kwargs): # noqa: D103 DeprecationWarning, stacklevel=2, ) - return make_plot_component(*args, **kwargs) + return make_mpl_plot_component(*args, **kwargs) -def make_plot_component( +def make_mpl_plot_component( measure: str | dict[str, str] | list[str] | tuple[str], post_process: Callable | None = None, save_format="png", diff --git a/tests/test_solara_viz.py b/tests/test_solara_viz.py index 5d300eabc27..2058496da44 100644 --- a/tests/test_solara_viz.py +++ b/tests/test_solara_viz.py @@ -8,7 +8,7 @@ import mesa import mesa.visualization.components.altair_components import mesa.visualization.components.matplotlib_components -from mesa.visualization.components.matplotlib_components import make_space_component +from mesa.visualization.components.matplotlib_components import make_mpl_space_component from mesa.visualization.solara_viz import Slider, SolaraViz, UserInputs @@ -105,7 +105,7 @@ def test_call_space_drawer(mocker): # noqa: D103 propertylayer_portrayal = None # initialize with space drawer unspecified (use default) # component must be rendered for code to run - solara.render(SolaraViz(model, components=[make_space_component(agent_portrayal)])) + solara.render(SolaraViz(model, components=[make_mpl_space_component(agent_portrayal)])) # should call default method with class instance and agent portrayal mock_space_matplotlib.assert_called_with( model, agent_portrayal, propertylayer_portrayal, post_process=None @@ -116,7 +116,7 @@ def test_call_space_drawer(mocker): # noqa: D103 solara.render(SolaraViz(model)) # should call default method with class instance and agent portrayal assert mock_space_matplotlib.call_count == 0 - assert mock_space_altair.call_count > 0 + assert mock_space_altair.call_count == 0 # specify a custom space method class AltSpace: @@ -134,7 +134,7 @@ def drawer(model): centroids_coordinates=[(0, 1), (0, 0), (1, 0)], ) solara.render( - SolaraViz(voronoi_model, components=[make_space_component(agent_portrayal)]) + SolaraViz(voronoi_model, components=[make_mpl_space_component(agent_portrayal)]) ) From c950baaeda3c64b1fc51c30f1c74bd2d584d1db8 Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Thu, 31 Oct 2024 21:14:24 +0100 Subject: [PATCH 09/21] update examples to use make_space_component and make_plot_component --- mesa/examples/advanced/epstein_civil_violence/app.py | 8 ++++---- mesa/examples/advanced/pd_grid/app.py | 8 ++++---- mesa/examples/advanced/sugarscape_g1mt/app.py | 4 ++-- mesa/examples/basic/boid_flockers/app.py | 2 +- mesa/examples/basic/boltzmann_wealth_model/app.py | 6 +++++- mesa/visualization/components/__init__.py | 9 +++++---- mesa/visualization/components/matplotlib_components.py | 3 ++- 7 files changed, 23 insertions(+), 17 deletions(-) diff --git a/mesa/examples/advanced/epstein_civil_violence/app.py b/mesa/examples/advanced/epstein_civil_violence/app.py index c36c1bc41ae..d3eb4643d87 100644 --- a/mesa/examples/advanced/epstein_civil_violence/app.py +++ b/mesa/examples/advanced/epstein_civil_violence/app.py @@ -7,8 +7,8 @@ from mesa.visualization import ( Slider, SolaraViz, - make_mpl_plot_component, - make_mpl_space_component, + make_plot_component, + make_space_component, ) COP_COLOR = "#000000" @@ -54,11 +54,11 @@ def post_process(ax): "max_jail_term": Slider("Max Jail Term", 30, 0, 50, 1), } -space_component = make_mpl_space_component( +space_component = make_space_component( citizen_cop_portrayal, post_process=post_process, draw_grid=False ) -chart_component = make_mpl_plot_component( +chart_component = make_plot_component( {state.name.lower(): agent_colors[state] for state in CitizenState} ) diff --git a/mesa/examples/advanced/pd_grid/app.py b/mesa/examples/advanced/pd_grid/app.py index b50d0adec96..6664e2c132f 100644 --- a/mesa/examples/advanced/pd_grid/app.py +++ b/mesa/examples/advanced/pd_grid/app.py @@ -5,8 +5,8 @@ from mesa.examples.advanced.pd_grid.model import PdGrid from mesa.visualization import ( SolaraViz, - make_mpl_plot_component, - make_mpl_space_component, + make_plot_component, + make_space_component, ) from mesa.visualization.UserParam import Slider @@ -36,10 +36,10 @@ def pd_agent_portrayal(agent): # Create grid visualization component using Altair -grid_viz = make_mpl_space_component(agent_portrayal=pd_agent_portrayal) +grid_viz = make_space_component(agent_portrayal=pd_agent_portrayal) # Create plot for tracking cooperating agents over time -plot_component = make_mpl_plot_component("Cooperating_Agents") +plot_component = make_plot_component("Cooperating_Agents") # Initialize model initial_model = PdGrid() diff --git a/mesa/examples/advanced/sugarscape_g1mt/app.py b/mesa/examples/advanced/sugarscape_g1mt/app.py index 029cc8b2231..8a5441cc54d 100644 --- a/mesa/examples/advanced/sugarscape_g1mt/app.py +++ b/mesa/examples/advanced/sugarscape_g1mt/app.py @@ -4,7 +4,7 @@ from mesa.examples.advanced.sugarscape_g1mt.agents import Trader from mesa.examples.advanced.sugarscape_g1mt.model import SugarscapeG1mt -from mesa.visualization import SolaraViz, make_mpl_plot_component +from mesa.visualization import SolaraViz, make_plot_component def SpaceDrawer(model): @@ -55,7 +55,7 @@ def portray(g): page = SolaraViz( model1, - components=[SpaceDrawer, make_mpl_plot_component(["Trader", "Price"])], + components=[SpaceDrawer, make_plot_component(["Trader", "Price"])], name="Sugarscape {G1, M, T}", play_interval=150, ) diff --git a/mesa/examples/basic/boid_flockers/app.py b/mesa/examples/basic/boid_flockers/app.py index bcecb0a3ebd..e374185c05f 100644 --- a/mesa/examples/basic/boid_flockers/app.py +++ b/mesa/examples/basic/boid_flockers/app.py @@ -51,7 +51,7 @@ def boid_draw(agent): page = SolaraViz( model, - [make_space_component(agent_portrayal=boid_draw)], + [make_space_component(agent_portrayal=boid_draw, backend="matplotlib")], model_params=model_params, name="Boid Flocking Model", ) diff --git a/mesa/examples/basic/boltzmann_wealth_model/app.py b/mesa/examples/basic/boltzmann_wealth_model/app.py index ff329ab9667..7f92cbbbe01 100644 --- a/mesa/examples/basic/boltzmann_wealth_model/app.py +++ b/mesa/examples/basic/boltzmann_wealth_model/app.py @@ -1,5 +1,9 @@ from mesa.examples.basic.boltzmann_wealth_model.model import BoltzmannWealthModel -from mesa.visualization import SolaraViz, make_plot_component, make_space_component +from mesa.visualization import ( + SolaraViz, + make_plot_component, + make_space_component, +) def agent_portrayal(agent): diff --git a/mesa/visualization/components/__init__.py b/mesa/visualization/components/__init__.py index fffbe5df4a5..6d68c79d9da 100644 --- a/mesa/visualization/components/__init__.py +++ b/mesa/visualization/components/__init__.py @@ -1,10 +1,11 @@ """custom solara components.""" - +from __future__ import annotations +from typing import overload from collections.abc import Callable -from .altair_components import make_altair_space -from .matplotlib_components import make_mpl_plot_component, make_mpl_space_component +from .altair_components import make_altair_space, SpaceAltair +from .matplotlib_components import make_mpl_plot_component, make_mpl_space_component, SpaceMatplotlib def make_space_component( @@ -13,7 +14,7 @@ def make_space_component( post_process: Callable | None = None, backend: str = "matplotlib", **space_drawing_kwargs, -): +) -> SpaceMatplotlib | SpaceAltair: """Create a Matplotlib-based space visualization component. Args: diff --git a/mesa/visualization/components/matplotlib_components.py b/mesa/visualization/components/matplotlib_components.py index 26769e5c5be..73a4c5b4e5c 100644 --- a/mesa/visualization/components/matplotlib_components.py +++ b/mesa/visualization/components/matplotlib_components.py @@ -1,4 +1,5 @@ """Matplotlib based solara components for visualization MESA spaces and plots.""" +from __future__ import annotations import warnings from collections.abc import Callable @@ -25,7 +26,7 @@ def make_mpl_space_component( propertylayer_portrayal: dict | None = None, post_process: Callable | None = None, **space_drawing_kwargs, -): +) -> SpaceMatplotlib: """Create a Matplotlib-based space visualization component. Args: From bac0bf297e0fcd39df318d7ab14b9fbf5996a0be Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 20:18:08 +0000 Subject: [PATCH 10/21] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mesa/visualization/__init__.py | 2 +- mesa/visualization/components/__init__.py | 34 +++++++++++++++---- .../components/altair_components.py | 4 ++- .../components/matplotlib_components.py | 1 + tests/test_solara_viz.py | 4 ++- 5 files changed, 35 insertions(+), 10 deletions(-) diff --git a/mesa/visualization/__init__.py b/mesa/visualization/__init__.py index e3d411f6459..965d1083d81 100644 --- a/mesa/visualization/__init__.py +++ b/mesa/visualization/__init__.py @@ -37,5 +37,5 @@ "draw_space", "draw_voroinoi_grid", "make_plot_component", - "make_space_component" + "make_space_component", ] diff --git a/mesa/visualization/components/__init__.py b/mesa/visualization/components/__init__.py index 6d68c79d9da..c2ba79ae90a 100644 --- a/mesa/visualization/components/__init__.py +++ b/mesa/visualization/components/__init__.py @@ -1,11 +1,16 @@ """custom solara components.""" + from __future__ import annotations -from typing import overload from collections.abc import Callable +from typing import overload -from .altair_components import make_altair_space, SpaceAltair -from .matplotlib_components import make_mpl_plot_component, make_mpl_space_component, SpaceMatplotlib +from .altair_components import SpaceAltair, make_altair_space +from .matplotlib_components import ( + SpaceMatplotlib, + make_mpl_plot_component, + make_mpl_space_component, +) def make_space_component( @@ -30,11 +35,24 @@ def make_space_component( function: A function that creates a space component """ if backend == "matplotlib": - return make_mpl_space_component(agent_portrayal, propertylayer_portrayal, post_process, **space_drawing_kwargs) + return make_mpl_space_component( + agent_portrayal, + propertylayer_portrayal, + post_process, + **space_drawing_kwargs, + ) elif backend == "altair": - return make_altair_space(agent_portrayal, propertylayer_portrayal, post_process, **space_drawing_kwargs) + return make_altair_space( + agent_portrayal, + propertylayer_portrayal, + post_process, + **space_drawing_kwargs, + ) else: - raise ValueError(f"unknown backend {backend}, must be one of matplotlib, altair") + raise ValueError( + f"unknown backend {backend}, must be one of matplotlib, altair" + ) + def make_plot_component( measure: str | dict[str, str] | list[str] | tuple[str], @@ -61,4 +79,6 @@ def make_plot_component( elif backend == "altair": raise NotImplementedError("altair line plots are not yet implemented") else: - raise ValueError(f"unknown backend {backend}, must be one of matplotlib, altair") + raise ValueError( + f"unknown backend {backend}, must be one of matplotlib, altair" + ) diff --git a/mesa/visualization/components/altair_components.py b/mesa/visualization/components/altair_components.py index e04e3e512d6..950f59c6070 100644 --- a/mesa/visualization/components/altair_components.py +++ b/mesa/visualization/components/altair_components.py @@ -12,7 +12,9 @@ from mesa.visualization.utils import update_counter -def make_altair_space(agent_portrayal, propertylayer_portrayal, post_process, **space_drawing_kwargs): # noqa: D103 +def make_altair_space( + agent_portrayal, propertylayer_portrayal, post_process, **space_drawing_kwargs +): # noqa: D103 if agent_portrayal is None: def agent_portrayal(a): diff --git a/mesa/visualization/components/matplotlib_components.py b/mesa/visualization/components/matplotlib_components.py index 73a4c5b4e5c..1961cf2a44d 100644 --- a/mesa/visualization/components/matplotlib_components.py +++ b/mesa/visualization/components/matplotlib_components.py @@ -1,4 +1,5 @@ """Matplotlib based solara components for visualization MESA spaces and plots.""" + from __future__ import annotations import warnings diff --git a/tests/test_solara_viz.py b/tests/test_solara_viz.py index 2058496da44..9276696676f 100644 --- a/tests/test_solara_viz.py +++ b/tests/test_solara_viz.py @@ -105,7 +105,9 @@ def test_call_space_drawer(mocker): # noqa: D103 propertylayer_portrayal = None # initialize with space drawer unspecified (use default) # component must be rendered for code to run - solara.render(SolaraViz(model, components=[make_mpl_space_component(agent_portrayal)])) + solara.render( + SolaraViz(model, components=[make_mpl_space_component(agent_portrayal)]) + ) # should call default method with class instance and agent portrayal mock_space_matplotlib.assert_called_with( model, agent_portrayal, propertylayer_portrayal, post_process=None From 08985ffbc6c388254a0bbfc4b6a2dde8db6fe617 Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Fri, 1 Nov 2024 15:09:31 +0100 Subject: [PATCH 11/21] remove unused overload --- mesa/visualization/components/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mesa/visualization/components/__init__.py b/mesa/visualization/components/__init__.py index c2ba79ae90a..4b70fc2b97c 100644 --- a/mesa/visualization/components/__init__.py +++ b/mesa/visualization/components/__init__.py @@ -3,7 +3,6 @@ from __future__ import annotations from collections.abc import Callable -from typing import overload from .altair_components import SpaceAltair, make_altair_space from .matplotlib_components import ( From 6634a61c926fdb55eec28f8c822fc79546098ed1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 14:10:04 +0000 Subject: [PATCH 12/21] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mesa/visualization/components/altair_components.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesa/visualization/components/altair_components.py b/mesa/visualization/components/altair_components.py index 950f59c6070..6d0afda0e63 100644 --- a/mesa/visualization/components/altair_components.py +++ b/mesa/visualization/components/altair_components.py @@ -14,7 +14,7 @@ def make_altair_space( agent_portrayal, propertylayer_portrayal, post_process, **space_drawing_kwargs -): # noqa: D103 +): if agent_portrayal is None: def agent_portrayal(a): From 0b3c29ad453b51661a9462d8718645c628583846 Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Fri, 1 Nov 2024 15:17:10 +0100 Subject: [PATCH 13/21] docstring --- .../components/altair_components.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/mesa/visualization/components/altair_components.py b/mesa/visualization/components/altair_components.py index 6d0afda0e63..be672f8c901 100644 --- a/mesa/visualization/components/altair_components.py +++ b/mesa/visualization/components/altair_components.py @@ -15,6 +15,21 @@ def make_altair_space( agent_portrayal, propertylayer_portrayal, post_process, **space_drawing_kwargs ): + """Create an Altair-based space visualization component. + + Args: + agent_portrayal: Function to portray agents. + propertylayer_portrayal: not yet implemented + post_process :not yet implemented + space_drawing_kwargs : not yet implemented + + ``agent_portrayal`` is called with an agent and should return a dict. Valid fields in this dict are "color", + "size", "marker", and "zorder". Other field are ignored and will result in a user warning. + + + Returns: + function: A function that creates a SpaceMatplotlib component + """ if agent_portrayal is None: def agent_portrayal(a): @@ -28,6 +43,11 @@ def MakeSpaceAltair(model): @solara.component def SpaceAltair(model, agent_portrayal, dependencies: list[any] | None = None): # noqa: D103 + """Create an Altair-based space visualization component. + + Returns: + a solara FigureAltair instance + """ update_counter.get() space = getattr(model, "grid", None) if space is None: From a8db820f373691680c52d833367a7de40e6acd54 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 14:17:47 +0000 Subject: [PATCH 14/21] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mesa/visualization/components/altair_components.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesa/visualization/components/altair_components.py b/mesa/visualization/components/altair_components.py index be672f8c901..d6542875412 100644 --- a/mesa/visualization/components/altair_components.py +++ b/mesa/visualization/components/altair_components.py @@ -42,7 +42,7 @@ def MakeSpaceAltair(model): @solara.component -def SpaceAltair(model, agent_portrayal, dependencies: list[any] | None = None): # noqa: D103 +def SpaceAltair(model, agent_portrayal, dependencies: list[any] | None = None): """Create an Altair-based space visualization component. Returns: From eb7027deea7c78730e0c1e8495ffe7383372cdaa Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Mon, 4 Nov 2024 10:51:18 +0100 Subject: [PATCH 15/21] further refactoring --- docs/apis/visualization.md | 6 ++--- mesa/visualization/__init__.py | 27 +++---------------- .../components/altair_components.py | 10 +++++++ .../components/matplotlib_components.py | 4 +-- .../{components => }/mpl_space_drawing.py | 2 +- tests/test_components_matplotlib.py | 2 +- 6 files changed, 20 insertions(+), 31 deletions(-) rename mesa/visualization/{components => }/mpl_space_drawing.py (99%) diff --git a/docs/apis/visualization.md b/docs/apis/visualization.md index 0a5e059802a..7c39dae5b01 100644 --- a/docs/apis/visualization.md +++ b/docs/apis/visualization.md @@ -21,7 +21,7 @@ For a detailed tutorial, please refer to our [Visualization Tutorial](../tutoria ``` -## Matplotlib-based components +## Matplotlib-based visualizations ```{eval-rst} .. automodule:: mesa.visualization.components.matplotlib_components @@ -31,13 +31,13 @@ For a detailed tutorial, please refer to our [Visualization Tutorial](../tutoria ``` ```{eval-rst} -.. automodule:: mesa.visualization.components.mpl_space_drawing +.. automodule:: mesa.visualization.mpl_space_drawing :members: :undoc-members: :show-inheritance: ``` -## Altair-based components +## Altair-based visualizations ```{eval-rst} .. automodule:: mesa.visualization.components.altair_components diff --git a/mesa/visualization/__init__.py b/mesa/visualization/__init__.py index 965d1083d81..69ceeb66131 100644 --- a/mesa/visualization/__init__.py +++ b/mesa/visualization/__init__.py @@ -1,21 +1,9 @@ """Solara based visualization for Mesa models.""" from .components import make_plot_component, make_space_component -from .components.altair_components import make_altair_space -from .components.matplotlib_components import ( - make_mpl_plot_component, - make_mpl_space_component, - make_plot_measure, - make_space_matplotlib, -) -from .components.mpl_space_drawing import ( - draw_continuous_space, - draw_hex_grid, - draw_network, - draw_orthogonal_grid, - draw_property_layers, +from .components.altair_components import make_altair_space, make_space_altair +from mesa.visualization.mpl_space_drawing import ( draw_space, - draw_voroinoi_grid, ) from .solara_viz import JupyterViz, SolaraViz from .UserParam import Slider @@ -24,18 +12,9 @@ "JupyterViz", "SolaraViz", "Slider", + "make_space_altair", "make_altair_space", - "make_mpl_space_component", - "make_mpl_plot_component", - "make_plot_measure", - "make_space_matplotlib", - "draw_continuous_space", - "draw_hex_grid", - "draw_network", - "draw_orthogonal_grid", - "draw_property_layers", "draw_space", - "draw_voroinoi_grid", "make_plot_component", "make_space_component", ] diff --git a/mesa/visualization/components/altair_components.py b/mesa/visualization/components/altair_components.py index d6542875412..7d18ded3d6a 100644 --- a/mesa/visualization/components/altair_components.py +++ b/mesa/visualization/components/altair_components.py @@ -1,6 +1,7 @@ """Altair based solara components for visualization mesa spaces.""" import contextlib +import warnings import solara @@ -12,6 +13,15 @@ from mesa.visualization.utils import update_counter +def make_space_altair(*args, **kwargs): # noqa: D103 + warnings.warn( + 'make_space_altair has been renamed to make_altair_space', + DeprecationWarning, + stacklevel=2, + ) + return make_altair_space(*args, **kwargs) + + def make_altair_space( agent_portrayal, propertylayer_portrayal, post_process, **space_drawing_kwargs ): diff --git a/mesa/visualization/components/matplotlib_components.py b/mesa/visualization/components/matplotlib_components.py index 1961cf2a44d..e187014ecab 100644 --- a/mesa/visualization/components/matplotlib_components.py +++ b/mesa/visualization/components/matplotlib_components.py @@ -9,13 +9,13 @@ import solara from matplotlib.figure import Figure -from mesa.visualization.components.mpl_space_drawing import draw_space +from mesa.visualization.mpl_space_drawing import draw_space from mesa.visualization.utils import update_counter def make_space_matplotlib(*args, **kwargs): # noqa: D103 warnings.warn( - "make_space_matplotlib has been renamed to make_space_component", + "make_space_matplotlib has been renamed to make_mpl_space_component", DeprecationWarning, stacklevel=2, ) diff --git a/mesa/visualization/components/mpl_space_drawing.py b/mesa/visualization/mpl_space_drawing.py similarity index 99% rename from mesa/visualization/components/mpl_space_drawing.py rename to mesa/visualization/mpl_space_drawing.py index c6f2886f0f7..395df5ee9ea 100644 --- a/mesa/visualization/components/mpl_space_drawing.py +++ b/mesa/visualization/mpl_space_drawing.py @@ -1,7 +1,7 @@ """Helper functions for drawing mesa spaces with matplotlib. These functions are used by the provided matplotlib components, but can also be used to quickly visualize -a space with matplotlib for example when creating an mp4 of a movie run or when needing a figure +a space with matplotlib for example when creating a mp4 of a movie run or when needing a figure for a paper. """ diff --git a/tests/test_components_matplotlib.py b/tests/test_components_matplotlib.py index 0f80a9d862f..9c454e77b2e 100644 --- a/tests/test_components_matplotlib.py +++ b/tests/test_components_matplotlib.py @@ -17,7 +17,7 @@ PropertyLayer, SingleGrid, ) -from mesa.visualization.components.mpl_space_drawing import ( +from mesa.visualization.mpl_space_drawing import ( draw_continuous_space, draw_hex_grid, draw_network, From e8c4edbad268ade8d8d611f3ad1711a460a93243 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 09:52:45 +0000 Subject: [PATCH 16/21] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mesa/visualization/__init__.py | 5 +++-- mesa/visualization/components/altair_components.py | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/mesa/visualization/__init__.py b/mesa/visualization/__init__.py index 69ceeb66131..540e6fac878 100644 --- a/mesa/visualization/__init__.py +++ b/mesa/visualization/__init__.py @@ -1,10 +1,11 @@ """Solara based visualization for Mesa models.""" -from .components import make_plot_component, make_space_component -from .components.altair_components import make_altair_space, make_space_altair from mesa.visualization.mpl_space_drawing import ( draw_space, ) + +from .components import make_plot_component, make_space_component +from .components.altair_components import make_altair_space, make_space_altair from .solara_viz import JupyterViz, SolaraViz from .UserParam import Slider diff --git a/mesa/visualization/components/altair_components.py b/mesa/visualization/components/altair_components.py index 7d18ded3d6a..b610e46f0d0 100644 --- a/mesa/visualization/components/altair_components.py +++ b/mesa/visualization/components/altair_components.py @@ -14,12 +14,12 @@ def make_space_altair(*args, **kwargs): # noqa: D103 - warnings.warn( - 'make_space_altair has been renamed to make_altair_space', - DeprecationWarning, - stacklevel=2, - ) - return make_altair_space(*args, **kwargs) + warnings.warn( + "make_space_altair has been renamed to make_altair_space", + DeprecationWarning, + stacklevel=2, + ) + return make_altair_space(*args, **kwargs) def make_altair_space( From 0a3ef9fcbdf3c93b5e29ed69ebcf7e6a1cee31f6 Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Mon, 4 Nov 2024 10:54:49 +0100 Subject: [PATCH 17/21] minor tweak of what's importable --- mesa/visualization/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mesa/visualization/__init__.py b/mesa/visualization/__init__.py index 540e6fac878..dfdb0a58937 100644 --- a/mesa/visualization/__init__.py +++ b/mesa/visualization/__init__.py @@ -1,5 +1,7 @@ """Solara based visualization for Mesa models.""" +from .components import make_plot_component, make_space_component +from .components.altair_components import make_space_altair from mesa.visualization.mpl_space_drawing import ( draw_space, ) @@ -14,7 +16,6 @@ "SolaraViz", "Slider", "make_space_altair", - "make_altair_space", "draw_space", "make_plot_component", "make_space_component", From 95bfa90ee030f438057306a8c0a07ed8f8752cef Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Mon, 4 Nov 2024 10:59:12 +0100 Subject: [PATCH 18/21] move post_process to component --- mesa/visualization/components/matplotlib_components.py | 3 +++ mesa/visualization/mpl_space_drawing.py | 6 ------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/mesa/visualization/components/matplotlib_components.py b/mesa/visualization/components/matplotlib_components.py index e187014ecab..f56cbd07437 100644 --- a/mesa/visualization/components/matplotlib_components.py +++ b/mesa/visualization/components/matplotlib_components.py @@ -89,6 +89,9 @@ def SpaceMatplotlib( **space_drawing_kwargs, ) + if post_process is not None: + post_process(ax) + solara.FigureMatplotlib( fig, format="png", bbox_inches="tight", dependencies=dependencies ) diff --git a/mesa/visualization/mpl_space_drawing.py b/mesa/visualization/mpl_space_drawing.py index 395df5ee9ea..6353d8106b8 100644 --- a/mesa/visualization/mpl_space_drawing.py +++ b/mesa/visualization/mpl_space_drawing.py @@ -94,7 +94,6 @@ def draw_space( agent_portrayal: Callable, propertylayer_portrayal: dict | None = None, ax: Axes | None = None, - post_process: Callable | None = None, **space_drawing_kwargs, ): """Draw a Matplotlib-based visualization of the space. @@ -105,8 +104,6 @@ def draw_space( propertylayer_portrayal: a dict specifying how to show propertylayer(s) ax: the axes upon which to draw the plot post_process: a callable called with the Axes instance - postprocess: a user-specified callable to do post-processing called with the Axes instance. This callable - can be used for any further fine-tuning of the plot (e.g., changing ticks, etc.) space_drawing_kwargs: any additional keyword arguments to be passed on to the underlying function for drawing the space. Returns: @@ -135,9 +132,6 @@ def draw_space( if propertylayer_portrayal: draw_property_layers(space, propertylayer_portrayal, ax=ax) - if post_process is not None: - post_process(ax=ax) - return ax From 28a10e0ab88156ab77389c8c09f89d44224de353 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 09:59:21 +0000 Subject: [PATCH 19/21] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mesa/visualization/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/mesa/visualization/__init__.py b/mesa/visualization/__init__.py index dfdb0a58937..4574881a5a3 100644 --- a/mesa/visualization/__init__.py +++ b/mesa/visualization/__init__.py @@ -1,7 +1,5 @@ """Solara based visualization for Mesa models.""" -from .components import make_plot_component, make_space_component -from .components.altair_components import make_space_altair from mesa.visualization.mpl_space_drawing import ( draw_space, ) From b4c53c63fd84eeec49056b15fc0343609b401543 Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Mon, 4 Nov 2024 10:59:46 +0100 Subject: [PATCH 20/21] overlooked kwarg --- mesa/visualization/components/matplotlib_components.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mesa/visualization/components/matplotlib_components.py b/mesa/visualization/components/matplotlib_components.py index f56cbd07437..6c7bb1ae040 100644 --- a/mesa/visualization/components/matplotlib_components.py +++ b/mesa/visualization/components/matplotlib_components.py @@ -85,7 +85,6 @@ def SpaceMatplotlib( agent_portrayal, propertylayer_portrayal=propertylayer_portrayal, ax=ax, - post_process=post_process, **space_drawing_kwargs, ) From 7f4dd4aa56ab55a945d2c188ebb792d4508c4a7b Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Mon, 4 Nov 2024 11:02:30 +0100 Subject: [PATCH 21/21] Update __init__.py --- mesa/visualization/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesa/visualization/__init__.py b/mesa/visualization/__init__.py index 4574881a5a3..66597b0e71d 100644 --- a/mesa/visualization/__init__.py +++ b/mesa/visualization/__init__.py @@ -5,7 +5,7 @@ ) from .components import make_plot_component, make_space_component -from .components.altair_components import make_altair_space, make_space_altair +from .components.altair_components import make_space_altair from .solara_viz import JupyterViz, SolaraViz from .UserParam import Slider