Skip to content

Updating Examples and Docs inline with the new API. #2819

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 18 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions mesa/examples/advanced/epstein_civil_violence/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
from mesa.visualization import (
Slider,
SolaraViz,
SpaceRenderer,
make_plot_component,
make_space_component,
)
from mesa.visualization.components import AgentPortrayalStyle

COP_COLOR = "#000000"

Expand All @@ -24,14 +25,12 @@ def citizen_cop_portrayal(agent):
if agent is None:
return

portrayal = {
"size": 50,
}
portrayal = AgentPortrayalStyle(size=200)

if isinstance(agent, Citizen):
portrayal["color"] = agent_colors[agent.state]
portrayal.update(("color", agent_colors[agent.state]))
elif isinstance(agent, Cop):
portrayal["color"] = COP_COLOR
portrayal.update(("color", COP_COLOR))

return portrayal

Expand Down Expand Up @@ -59,19 +58,20 @@ def post_process(ax):
"max_jail_term": Slider("Max Jail Term", 30, 0, 50, 1),
}

space_component = make_space_component(
citizen_cop_portrayal, post_process=post_process, draw_grid=False
)

chart_component = make_plot_component(
{state.name.lower(): agent_colors[state] for state in CitizenState}
)

epstein_model = EpsteinCivilViolence()
renderer = SpaceRenderer(epstein_model, backend="matplotlib")
renderer.draw_agents(citizen_cop_portrayal)
renderer.post_process = post_process

page = SolaraViz(
epstein_model,
components=[space_component, chart_component],
renderer,
components=[chart_component],
model_params=model_params,
name="Epstein Civil Violence",
)
Expand Down
21 changes: 10 additions & 11 deletions mesa/examples/advanced/pd_grid/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,19 @@
from mesa.visualization import (
Slider,
SolaraViz,
SpaceRenderer,
make_plot_component,
make_space_component,
)
from mesa.visualization.components import AgentPortrayalStyle


def pd_agent_portrayal(agent):
"""
Portrayal function for rendering PD agents in the visualization.
"""
return {
"color": "blue" if agent.move == "C" else "red",
"marker": "s", # square marker
"size": 25,
}
return AgentPortrayalStyle(
color="blue" if agent.move == "C" else "red", marker="s", size=25
)


# Model parameters
Expand All @@ -40,19 +39,19 @@ def pd_agent_portrayal(agent):
}


# Create grid visualization component using Altair
grid_viz = make_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_plot_component("Cooperating_Agents", backend="altair", grid=True)

# Initialize model
initial_model = PdGrid()
# Create grid and agent visualization component using Altair
renderer = SpaceRenderer(initial_model, backend="altair").render(pd_agent_portrayal)

# Create visualization with all components
page = SolaraViz(
model=initial_model,
components=[grid_viz, plot_component],
renderer=renderer,
components=[plot_component],
model_params=model_params,
name="Spatial Prisoner's Dilemma",
)
Expand Down
21 changes: 12 additions & 9 deletions mesa/examples/advanced/sugarscape_g1mt/app.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from mesa.examples.advanced.sugarscape_g1mt.model import SugarscapeG1mt
from mesa.visualization import Slider, SolaraViz, make_plot_component
from mesa.visualization import Slider, SolaraViz, SpaceRenderer, make_plot_component
from mesa.visualization.components import AgentPortrayalStyle, PropertyLayerStyle
from mesa.visualization.components.matplotlib_components import make_mpl_space_component


def agent_portrayal(agent):
Expand All @@ -23,12 +22,10 @@ def propertylayer_portrayal(layer):
return PropertyLayerStyle(color="red", alpha=0.8, colorbar=True, vmin=0, vmax=10)


sugarscape_space = make_mpl_space_component(
agent_portrayal=agent_portrayal,
propertylayer_portrayal=propertylayer_portrayal,
post_process=None,
draw_grid=False,
)
def post_process(chart):
chart = chart.properties(width=400, height=400)
return chart


model_params = {
"seed": {
Expand Down Expand Up @@ -57,10 +54,16 @@ def propertylayer_portrayal(layer):

model = SugarscapeG1mt()

renderer = SpaceRenderer(model, backend="altair").render(
agent_portrayal=agent_portrayal,
propertylayer_portrayal=propertylayer_portrayal,
post_process=post_process,
)

page = SolaraViz(
model,
renderer,
components=[
sugarscape_space,
make_plot_component("#Traders"),
make_plot_component("Price"),
],
Expand Down
39 changes: 21 additions & 18 deletions mesa/examples/advanced/wolf_sheep/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,32 @@
CommandConsole,
Slider,
SolaraViz,
SpaceRenderer,
make_plot_component,
make_space_component,
)
from mesa.visualization.components import AgentPortrayalStyle


def wolf_sheep_portrayal(agent):
if agent is None:
return

portrayal = {
"size": 25,
}
portrayal = AgentPortrayalStyle(
size=50,
marker="o",
zorder=2,
)

if isinstance(agent, Wolf):
portrayal["color"] = "tab:red"
portrayal["marker"] = "o"
portrayal["zorder"] = 2
portrayal.update(("color", "red"))
elif isinstance(agent, Sheep):
portrayal["color"] = "tab:cyan"
portrayal["marker"] = "o"
portrayal["zorder"] = 2
portrayal.update(("color", "cyan"))
elif isinstance(agent, GrassPatch):
if agent.fully_grown:
portrayal["color"] = "tab:green"
portrayal.update(("color", "tab:green"))
else:
portrayal["color"] = "tab:brown"
portrayal["marker"] = "s"
portrayal["size"] = 75
portrayal.update(("color", "tab:brown"))
portrayal.update(("marker", "s"), ("size", 125), ("zorder", 1))

return portrayal

Expand Down Expand Up @@ -75,9 +73,6 @@ def post_process_lines(ax):
ax.legend(loc="center left", bbox_to_anchor=(1, 0.9))


space_component = make_space_component(
wolf_sheep_portrayal, draw_grid=False, post_process=post_process_space
)
lineplot_component = make_plot_component(
{"Wolves": "tab:orange", "Sheep": "tab:cyan", "Grass": "tab:green"},
post_process=post_process_lines,
Expand All @@ -86,9 +81,17 @@ def post_process_lines(ax):
simulator = ABMSimulator()
model = WolfSheep(simulator=simulator, grass=True)

renderer = SpaceRenderer(
model,
backend="matplotlib",
)
renderer.draw_agents(wolf_sheep_portrayal)
renderer.post_process = post_process_space

page = SolaraViz(
model,
components=[space_component, lineplot_component, CommandConsole],
renderer,
components=[lineplot_component, CommandConsole],
model_params=model_params,
name="Wolf Sheep",
simulator=simulator,
Expand Down
26 changes: 15 additions & 11 deletions mesa/examples/basic/boid_flockers/app.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
import os
import sys

from matplotlib.markers import MarkerStyle

sys.path.insert(0, os.path.abspath("../../../.."))

from mesa.examples.basic.boid_flockers.model import BoidFlockers
from mesa.visualization import Slider, SolaraViz, make_space_component
from mesa.visualization import Slider, SolaraViz, SpaceRenderer
from mesa.visualization.components import AgentPortrayalStyle

# Pre-compute markers for different angles (e.g., every 10 degrees)
MARKER_CACHE = {}
Expand All @@ -25,10 +21,12 @@ def boid_draw(agent):
rounded_deg = round(deg / 10) * 10 % 360

# using cached markers to speed things up
if neighbors <= 1:
return {"color": "red", "size": 20, "marker": MARKER_CACHE[rounded_deg]}
elif neighbors >= 2:
return {"color": "green", "size": 20, "marker": MARKER_CACHE[rounded_deg]}
boid_style = AgentPortrayalStyle(
color="red", size=20, marker=MARKER_CACHE[rounded_deg]
)
if neighbors >= 2:
boid_style.update(("color", "green"), ("marker", MARKER_CACHE[rounded_deg]))
return boid_style


model_params = {
Expand Down Expand Up @@ -71,9 +69,15 @@ def boid_draw(agent):

model = BoidFlockers()

# Quickest way to visualize grid along with agents or property layers.
renderer = SpaceRenderer(
model,
backend="matplotlib",
).render(agent_portrayal=boid_draw)

page = SolaraViz(
model,
components=[make_space_component(agent_portrayal=boid_draw, backend="matplotlib")],
renderer,
model_params=model_params,
name="Boid Flocking Model",
)
Expand Down
71 changes: 39 additions & 32 deletions mesa/examples/basic/boltzmann_wealth_model/app.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import altair as alt

from mesa.examples.basic.boltzmann_wealth_model.model import BoltzmannWealth
from mesa.mesa_logging import INFO, log_to_stderr
from mesa.visualization import (
SolaraViz,
SpaceRenderer,
make_plot_component,
make_space_component,
)
from mesa.visualization.components import AgentPortrayalStyle

log_to_stderr(INFO)


def agent_portrayal(agent):
color = agent.wealth # we are using a colormap to translate wealth to color
return {"color": color}
return AgentPortrayalStyle(
color=agent.wealth
) # we are using a colormap to translate wealth to color


model_params = {
Expand All @@ -33,45 +37,48 @@ def agent_portrayal(agent):
}


def post_process(ax):
ax.get_figure().colorbar(ax.collections[0], label="wealth", ax=ax)
def post_process(chart):
"""Post-process the Altair chart to add a colorbar legend."""
chart = chart.encode(
color=alt.Color(
"color:N",
scale=alt.Scale(scheme="viridis", domain=[0, 10]),
legend=alt.Legend(
title="Wealth",
orient="right",
type="gradient",
gradientLength=200,
),
),
)
return chart


# Create initial model instance
model = BoltzmannWealth(50, 10, 10)

# Create visualization elements. The visualization elements are solara components
# that receive the model instance as a "prop" and display it in a certain way.
# Under the hood these are just classes that receive the model instance.
# You can also author your own visualization elements, which can also be functions
# that receive the model instance and return a valid solara component.
# The SpaceRenderer is responsible for drawing the model's space and agents.
# It builds the visualization in layers, first drawing the grid structure,
# and then drawing the agents on top. It uses a specified backend
# (like "altair" or "matplotlib") for creating the plots.
renderer = SpaceRenderer(model, backend="altair")
# Can customize the grid appearance.
renderer.draw_structure(grid_color="black", grid_dash=[6, 2], grid_opacity=0.3)
renderer.draw_agents(agent_portrayal=agent_portrayal, cmap="viridis", vmin=0, vmax=10)

SpaceGraph = make_space_component(
agent_portrayal, cmap="viridis", vmin=0, vmax=10, post_process=post_process
)
# The post_process function is used to modify the Altair chart after it has been created.
# It can be used to add legends, colorbars, or other visual elements.
renderer.post_process = post_process

# Creates a line plot component from the model's "Gini" datacollector.
GiniPlot = make_plot_component("Gini")

# Create the SolaraViz page. This will automatically create a server and display the
# visualization elements in a web browser.
# Display it using the following command in the example directory:
# solara run app.py
# It will automatically update and display any changes made to this file
# The SolaraViz page combines the model, renderer, and components into a web interface.
# To run the visualization, save this code as app.py and run `solara run app.py`
page = SolaraViz(
model,
components=[SpaceGraph, GiniPlot],
renderer,
components=[GiniPlot],
model_params=model_params,
name="Boltzmann Wealth Model",
)
page # noqa


# In a notebook environment, we can also display the visualization elements directly
# SpaceGraph(model1)
# GiniPlot(model1)

# The plots will be static. If you want to pick up model steps,
# you have to make the model reactive first
# reactive_model = solara.reactive(model1)
# SpaceGraph(reactive_model)
# In a different notebook block:
# reactive_model.value.step()
Loading
Loading