Skip to content

Commit

Permalink
gis: update three examples to use solara viz
Browse files Browse the repository at this point in the history
  • Loading branch information
wang-boyu committed Sep 28, 2024
1 parent 84542d4 commit 14872eb
Show file tree
Hide file tree
Showing 20 changed files with 167 additions and 192 deletions.
6 changes: 3 additions & 3 deletions gis/geo_schelling/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ NUTS-2 regions are the GeoAgents. The neighbors of a polygon are considered thos

## How to Run

To run the model interactively, run `mesa runserver` in this directory. e.g.
To run the model interactively, run `solara run app.py` in this directory. e.g.

```bash
mesa runserver
solara run app.py
```

Then open your browser to [http://127.0.0.1:8521/](http://127.0.0.1:8521/) and press `Start`.
Then open your browser to [http://127.0.0.1:8765/](http://127.0.0.1:8765/) and press the play button ``.
44 changes: 44 additions & 0 deletions gis/geo_schelling/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import solara
from mesa.visualization import Slider, SolaraViz, make_plot_measure
from mesa_geo.visualization import make_geospace_leaflet
from model import GeoSchelling


def make_plot_happiness(model):
return solara.Markdown(f"**Happy agents: {model.happy}**")


model_params = {
"density": Slider("Agent density", 0.6, 0.1, 1.0, 0.1),
"minority_pc": Slider("Fraction minority", 0.2, 0.00, 1.0, 0.05),
"export_data": False,
}


def schelling_draw(agent):
"""
Portrayal Method for canvas
"""
portrayal = {}
if agent.atype is None:
portrayal["color"] = "Grey"
elif agent.atype == 0:
portrayal["color"] = "Red"
else:
portrayal["color"] = "Blue"
return portrayal


model = GeoSchelling()
page = SolaraViz(
model,
[
make_geospace_leaflet(schelling_draw, zoom=4),
make_plot_happiness,
make_plot_measure(["happy"]),
],
model_params=model_params,
name="GeoSchelling",
)

page # noqa
2 changes: 1 addition & 1 deletion gis/geo_schelling/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
mesa-geo~=0.7
mesa-geo~=0.9.0a0
3 changes: 0 additions & 3 deletions gis/geo_schelling/run.py

This file was deleted.

45 changes: 0 additions & 45 deletions gis/geo_schelling/server.py

This file was deleted.

8 changes: 4 additions & 4 deletions gis/geo_schelling_points/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ The NUTS-2 regions are considered as a shared definition of neighborhood among a

There are two types of GeoAgents: people and regions. Each person resides in a randomly assigned region, and checks the color ratio of its region against a pre-defined "happiness" threshold at every time step. If the ratio falls below a certain threshold (e.g., 40%), the agent is found to be "unhappy", and randomly moves to another region. People are represented as points, with locations randomly chosen within their regions. The color of a region depends on the color of the majority population it contains (i.e., point in polygon calculations).

## How to run
## How to Run

To run the model interactively, run `mesa runserver` in this directory. e.g.
To run the model interactively, run `solara run app.py` in this directory. e.g.

```bash
mesa runserver
solara run app.py
```

Then open your browser to [http://127.0.0.1:8521/](http://127.0.0.1:8521/) and press `Start`.
Then open your browser to [http://127.0.0.1:8765/](http://127.0.0.1:8765/) and press the play button ``.
46 changes: 46 additions & 0 deletions gis/geo_schelling_points/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import solara
from geo_schelling_points.agents import PersonAgent, RegionAgent
from geo_schelling_points.model import GeoSchellingPoints
from mesa.visualization import Slider, SolaraViz, make_plot_measure
from mesa_geo.visualization import make_geospace_leaflet


def make_plot_happiness(model):
return solara.Markdown(f"**Happy agents: {model.happy}**")


model_params = {
"red_percentage": Slider("% red", 0.5, 0.00, 1.0, 0.05),
"similarity_threshold": Slider("% similar wanted", 0.5, 0.00, 1.0, 0.05),
}


def schelling_draw(agent):
portrayal = {}
if isinstance(agent, RegionAgent):
if agent.red_cnt > agent.blue_cnt:
portrayal["color"] = "Red"
elif agent.red_cnt < agent.blue_cnt:
portrayal["color"] = "Blue"
else:
portrayal["color"] = "Grey"
elif isinstance(agent, PersonAgent):
portrayal["radius"] = 1
portrayal["shape"] = "circle"
portrayal["color"] = "Red" if agent.is_red else "Blue"
return portrayal


model = GeoSchellingPoints()
page = SolaraViz(
model,
[
make_geospace_leaflet(schelling_draw, zoom=4),
make_plot_happiness,
make_plot_measure(["happy", "unhappy"]),
],
model_params=model_params,
name="GeoSchellingPoints",
)

page # noqa
Empty file.
21 changes: 20 additions & 1 deletion gis/geo_schelling_points/geo_schelling_points/model.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import random
from pathlib import Path

import geopandas as gpd
import libpysal
import mesa
import mesa_geo as mg

Expand All @@ -10,6 +12,21 @@
script_directory = Path(__file__).resolve().parent


def get_largest_connected_components(gdf):
"""Get the largest connected component of a GeoDataFrame."""
# create spatial weights matrix
W = libpysal.weights.Queen.from_dataframe(
gdf, use_index=True, silence_warnings=True
)
# get component labels
gdf["component"] = W.component_labels
# get the largest component
largest_component = gdf["component"].value_counts().idxmax()
# subset the GeoDataFrame
gdf = gdf[gdf["component"] == largest_component]
return gdf


class GeoSchellingPoints(mesa.Model):
def __init__(self, red_percentage=0.5, similarity_threshold=0.5):
super().__init__()
Expand All @@ -26,7 +43,9 @@ def __init__(self, red_percentage=0.5, similarity_threshold=0.5):
# Set up the grid with patches for every NUTS region
ac = mg.AgentCreator(RegionAgent, model=self)
data_path = script_directory / "../data/nuts_rg_60M_2013_lvl_2.geojson"
regions = ac.from_file(data_path)
regions_gdf = gpd.read_file(data_path)
regions_gdf = get_largest_connected_components(regions_gdf)
regions = ac.from_GeoDataFrame(regions_gdf)
self.space.add_regions(regions)

for region in regions:
Expand Down
59 changes: 0 additions & 59 deletions gis/geo_schelling_points/geo_schelling_points/server.py

This file was deleted.

2 changes: 1 addition & 1 deletion gis/geo_schelling_points/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
mesa-geo~=0.7
mesa-geo~=0.9.0a0
3 changes: 0 additions & 3 deletions gis/geo_schelling_points/run.py

This file was deleted.

8 changes: 4 additions & 4 deletions gis/geo_sir/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ Susceptible agents (those who have never been infected) who come in proximity wi
Neighbourhood agents represent neighbourhoods in the Toronto, and become hot-spots (colored red) if there are infected agents inside them.
Data obtained from [this link](http://adamw523.com/toronto-geojson/).

## How to run
## How to Run

To run the model interactively, run `mesa runserver` in this directory. e.g.
To run the model interactively, run `solara run app.py` in this directory. e.g.

```bash
mesa runserver
solara run app.py
```

Then open your browser to [http://127.0.0.1:8521/](http://127.0.0.1:8521/) and press `Start`.
Then open your browser to [http://127.0.0.1:8765/](http://127.0.0.1:8765/) and press the play button ``.
42 changes: 42 additions & 0 deletions gis/geo_sir/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from geo_sir.agents import PersonAgent
from geo_sir.model import GeoSir
from mesa.visualization import Slider, SolaraViz, make_plot_measure
from mesa_geo.visualization import make_geospace_leaflet

model_params = {
"pop_size": Slider("Population size", 30, 10, 100, 10),
"init_infected": Slider("Fraction initial infection", 0.2, 0.00, 1.0, 0.05),
"exposure_distance": Slider("Exposure distance", 500, 100, 1000, 100),
}


def infected_draw(agent):
"""
Portrayal Method for canvas
"""
portrayal = {}
if isinstance(agent, PersonAgent):
portrayal["radius"] = "2"
if agent.atype in ["hotspot", "infected"]:
portrayal["color"] = "Red"
elif agent.atype in ["safe", "susceptible"]:
portrayal["color"] = "Green"
elif agent.atype in ["recovered"]:
portrayal["color"] = "Blue"
elif agent.atype in ["dead"]:
portrayal["color"] = "Black"
return portrayal


model = GeoSir()
page = SolaraViz(
model,
[
make_geospace_leaflet(infected_draw, zoom=12),
make_plot_measure(["infected", "susceptible", "recovered", "dead"]),
],
name="Basic agent-based SIR model",
model_params=model_params,
)

page # noqa
Empty file added gis/geo_sir/geo_sir/__init__.py
Empty file.
File renamed without changes.
2 changes: 1 addition & 1 deletion gis/geo_sir/model.py → gis/geo_sir/geo_sir/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class GeoSir(mesa.Model):
"""Model class for a simplistic infection model."""

# Geographical parameters for desired map
geojson_regions = script_directory / "data/TorontoNeighbourhoods.geojson"
geojson_regions = script_directory / "../data/TorontoNeighbourhoods.geojson"
unique_id = "HOODNUM"

def __init__(
Expand Down
2 changes: 1 addition & 1 deletion gis/geo_sir/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
mesa-geo~=0.7
mesa-geo~=0.9.0a0
3 changes: 0 additions & 3 deletions gis/geo_sir/run.py

This file was deleted.

Loading

0 comments on commit 14872eb

Please sign in to comment.