-
Notifications
You must be signed in to change notification settings - Fork 58
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
frontend: python frontend for Mesa-Geo #157
Comments
Hi @Corvince, will you be interested in taking a look at this? @tpike3 and I are probably going to talk about Mesa & Mesa-Geo in an upcoming conference in early Nov. We're thinking to create a tutorial using one of our example models. Sorry about this short notice. But having a Solora frontend for Mesa-Geo would be super useful : ) |
Sorry, I thought I had already answered here. Yes, I would be interested to implement a solara-based frontend. In fact I am working in this right now |
Great! Looking forward to your implementation. This will be very helpful. |
An update on things I tried so far: I wanted to leverage Ipyleaflet to have a leaflet map that is similar to what is included currently with the old frontend. After some troubles converting the agents to a compatible GeoJSON format (solara had some issues), I realized this is not needed and we can just pass in a GeoDataFrame. We can get that easily with gdf = model.space.get_agents_as_GeoDataFrame().to_crs("epsg:4326") With this we can create a ipyleaflet map with something like this import ipyleaflet
center_default = (53.2305799, 6.5323552)
zoom_default = 5
ipyleaflet.Map(
center=center_default,
zoom=zoom_default,
layers=[
ipyleaflet.TileLayer(),
ipyleaflet.GeoData(
geo_dataframe=gdf,
style={
"color": "blue",
"fillColor": "#3366cc",
"opacity": 0.05,
"weight": 1.9,
"dashArray": "2",
"fillOpacity": 0.6,
},
),
],
) The problematic thing is coloring the agents based on some property. In leaflet we could define the color in terms of its feature with a function that maps a feature to a color. But this doesn't seem to be possible with IPyleaflet. We could probably create different layers for each color, but I haven't tried. The other possibility would be to leverage Altair. Here we can define the colors decleratively like so: import altair as alt
alt.Chart(data=gdf).mark_geoshape().encode(color="atype:O") However, including a basemap is not super well supported, but might be possible, see vega/vega-lite#5758 And the output needs some finetuning. But I won't be able to investigate this further until beginning of November. So whats the current timeline for the tutorial @wang-boyu ? |
I'm so glad that you're looking into this! Thank you! Was worried about it in the past few days. There is a dev meeting tomorrow and I'll discuss with @tpike3 about the tutorial. After that I'll post an update here. |
The tutorial is at the beginning of November (Nov2nd or 3rd) @Corvince would you have a branch you can push so I can just build off what you have already done? |
Unfortunately not, but it boils down to the code snippets I posted. I can try to assist if you have questions, but I don't have access to my laptop until Nov. But both approaches should be possible to wrap in a function like the current grid or space views that accept model and agent_portrayal as their arguments. From there you can generate the geodataframe and return either the solara leaflet or Altair figure |
Since we're not really ready for the tutorial, we're going to skip the CSSSA session this year (@tpike3 will still be there to give a Mesa tutorial and may possibly mention Mesa-Geo briefly, but not a full tutorial for Mesa-Geo). The next window is the online tutorial series from CSSSA (link to the Mesa online tutorial by @tpike3: youtu.be/8P5P7NpCx5o) which is currently scheduled at Feb 2024 for Mesa-Geo. Would be great if we can have the feature and the tutorial ready by then : ) |
That sounds doable! |
I looked at the Solara frontend in Mesa (long overdue) and am wondering whether a dedicated frontend for Mesa-Geo is needed at all, since we can simple feed a matplotlib figure (i.e., For example users could define such a function in this way: def space_drawer(model):
agents_gdf = model.space.get_agents_as_GeoDataFrame()
fig, ax = plt.subplots()
# users do some plotting here with geopandas, for example:
agents_gdf.plot(column="some_col", ax=ax)
# similarly for raster layers
for layer in model.space.layers:
if isinstance(layer, RasterLayer):
... # plot it using rasterio or matplotlib or any other library that is based on matplotlib
return solara.FigureMatplotlib(fig) The benefits are that, for the users, they don't need to learn how to make plots in Mesa (e.g., is it "color" or "Color" in The catch here is that On a side note, if Mesa agents could be retrieved as dataframe in a similar way, then probably Any thoughts on this? |
That's a good idea. If the redraws performance is reasonable (with PNG output, projectmesa/mesa#1819), this should do. Then the
|
Made a simple demo for this with the GeoSchellingPoints model: https://github.com/wang-boyu/mesa-examples/blob/gis%2Fsolara-frontend/gis/geo_schelling_points/app.ipynb |
What functionalities are missing in that demo in comparison to the mesa-viz-tornado version? |
Good question! One thing that I didn't do in the demo is to have some popup properties, so that users can click an agent on the map and see some descriptions. Not sure how this will work with Solara. It is mainly a different way of doing things with these two approaches. Previously in # `agent` is an object of type `GeoAgent`
if agent.red_cnt > agent.blue_cnt:
portrayal["color"] = "Red"
elif agent.red_cnt < agent.blue_cnt:
portrayal["color"] = "Blue"
else:
portrayal["color"] = "Grey" whereas now we need to do # `region_agents` is a GeoDataFrame
region_agents["is_red"] = region_agents["red_cnt"] > region_agents["blue_cnt"]
# Then figure out the color palette you want with geopandas plot, or simply use the default (do nothing)
color_map = mpl.colors.ListedColormap(plt.cm.Set2.colors[:2])
region_agents.plot(column="is_red", cmap=color_map, alpha=0.5, ax=space_ax) Operating at the GeoDataFrame level may appear simple in this demo. But back in In this case we may need to go back to the geoagent code, and think about how to write what we want as an attribute, so that it could be exported as a column of the GeoDataFrame. In fact this sounds a good practice even for the |
That makes sense, in that the agent_portrayal should be about declaring the output detail. The DF output would constraint the user to do this. I think it is sufficient to merge the Solara demo, with a documentation that says the rendering is not clickable, and that the clickable version is still in the work, pointing to this issue. We should discuss about removing the |
How about making it optional... Now I think about it, removing it would need users to know how to use pandas to manipulate and plot dataframes, whereas |
I would be interested in this feature a lot. Is there any news on the progress? |
I think we're stabilizing JupyterViz in main Mesa first (see projectmesa/mesa#2090), then build the mesa-geo on it. Except if @wang-boyu has an other vision on it. |
@tpike3 has been working on it with a recent PR #199 as well as an example projectmesa/mesa-examples#117. But they are not merged yet. |
Thanks for the feedback, I ll have a look at the examples above. |
|
What's the problem this feature will solve?
Mesa v2.1 has introduced a
mesa.experimental
namespace that containsJupyterViz
for model visualization in Jupyter notebooks (see projectmesa/mesa#1698 and projectmesa/mesa#1726).It would be great to similarly have a corresponding set of widgets to visualize GeoSpaces in Jupyter notebooks and web apps too.
Describe the solution you'd like
Either extend the
JupyterViz
class or have a new class for Mesa-Geo. Currently Mesa uses the Solara framework to create UI components.Additional context
The text was updated successfully, but these errors were encountered: