Skip to content
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

add method to make geospace as a solara component #246

Merged
merged 2 commits into from
Sep 26, 2024

Conversation

wang-boyu
Copy link
Member

@wang-boyu wang-boyu commented Sep 6, 2024

This PR:

As a result, instead of

import mesa_geo.visualization as mgv

mgv.GeoJupyterViz(
    GeoSIR,
    model_params,
    measures= [["infected", "susceptible", "recovered", "dead"], ["safe", "hotspot"]],
    name="GeoSIR",
    agent_portrayal=SIR_draw,
    zoom=12,
    scroll_wheel_zoom=False
)

we can now do

# importing from Mesa now, not Mesa-Geo
from mesa.visualization import SolaraViz

model = GeoSIR()
SolaraViz(
    model,
    name="GeoSIR",
    components=[
        mgv.make_geospace_leaflet(SIR_draw, zoom=12, scroll_wheel_zoom=False),
        mesa.visualization.make_plot_measure(["infected", "susceptible", "recovered", "dead"]),
        mesa.visualization.make_plot_measure(["safe", "hotspot"]),
    ]
)

A few other things to consider (could be separate PRs, or to be addressed in this one):

@tpike3 would you like to test this out and see if it's working as expected?

@wang-boyu wang-boyu added enhancement Release notes label breaking Release notes label labels Sep 6, 2024
@Corvince
Copy link
Contributor

Corvince commented Sep 6, 2024

Great work! Looks pretty good from a brief look, but as said earlier can't test it atm

@EwoutH
Copy link
Member

EwoutH commented Sep 6, 2024

I will make time for full review Monday, but the fact that this replaces 428 lines of code with only 84 is always a good sign!

@EwoutH
Copy link
Member

EwoutH commented Sep 8, 2024

Looks like an awesome, almost drop-in replacement!

Could we add aliases the old names at some place to keep those working (maybe with a deprecation warning to use the new name)?

Is there anything in particular you would like me to review or test in detail?

@wang-boyu
Copy link
Member Author

Thanks for your comments!

Could we add aliases the old names at some place to keep those working (maybe with a deprecation warning to use the new name)?

Certainly! I've added another item into the todo list. Will bring back GeoJupyterViz together with some deprecation warnings.

Is there anything in particular you would like me to review or test in detail?

Mostly about how make_geospace_leaflet is implemented. Would also be great if you could verify if it's working for the intro tutorial (btw mesa needs to be installed from main branch), to make sure that it's not just working on my laptop : )

Thanks agin for looking into this.

@wang-boyu
Copy link
Member Author

Rebased to main branch

Copy link

codecov bot commented Sep 10, 2024

Codecov Report

Attention: Patch coverage is 77.35849% with 24 lines in your changes missing coverage. Please review.

Project coverage is 73.48%. Comparing base (ce501b6) to head (70fd9f5).
Report is 68 commits behind head on main.

Files with missing lines Patch % Lines
...a_geo/visualization/components/geospace_leaflet.py 76.04% 17 Missing and 6 partials ⚠️
mesa_geo/geospace.py 83.33% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #246      +/-   ##
==========================================
- Coverage   78.21%   73.48%   -4.73%     
==========================================
  Files          10       10              
  Lines         693      856     +163     
  Branches      151      182      +31     
==========================================
+ Hits          542      629      +87     
- Misses        127      194      +67     
- Partials       24       33       +9     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@EwoutH
Copy link
Member

EwoutH commented Sep 10, 2024

Nice! Test pass, that's a good thing.

Let's us know if you need any input!

@wang-boyu
Copy link
Member Author

Brought back GeoJupyterViz and rebased to main branch. I'll leave the update to intro tutorial and deprecation warnings to future PRs.

Ready for merging now.

@wang-boyu wang-boyu marked this pull request as ready for review September 17, 2024 19:27
@wang-boyu wang-boyu removed the breaking Release notes label label Sep 17, 2024
@EwoutH
Copy link
Member

EwoutH commented Sep 17, 2024

Any specific input/testing/review you need?

@wang-boyu
Copy link
Member Author

Thanks @EwoutH. I experienced some slowness while trying the new solara api (also reported here projectmesa/mesa#2289 (comment)), for both this intro tutorial as well as Mesa's viz tutorial. Would be great if you could confirm this (or it could be just my machine).

But I think this is outside the scope of this PR, since GeoJupyterViz isn't really touched here.

@rht
Copy link
Contributor

rht commented Sep 19, 2024

@tpike3 this needs your review.

@rht
Copy link
Contributor

rht commented Sep 25, 2024

This PR has been stuck for a while, and given that @tpike3 hasn't responded, I am going to unblock by approving.

@rht
Copy link
Contributor

rht commented Sep 25, 2024

@wang-boyu test GIS examples are still failing.

@EwoutH
Copy link
Member

EwoutH commented Sep 25, 2024

I resolved almost all errors and warnings in the GIS examples (only one left is projectmesa/mesa-examples#209).

@EwoutH
Copy link
Member

EwoutH commented Sep 25, 2024

I would love to do a Mesa-geo pre-release this week, since now all the gis examples work with the latest Mesa 3.0 pre-release. It would be really nice to have this in!

@wang-boyu
Copy link
Member Author

Thanks @rht for approving and @EwoutH for fixing the tests and intro tutorial. I would suggest to go ahead and merge this, since the existing GeoJupyterViz is not touched.

Copy link
Member

@EwoutH EwoutH left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s give @tpike3 a few more hours, most of the time he’s online between 10 and 12 CET.

@tpike3
Copy link
Member

tpike3 commented Sep 26, 2024

Sorry for the delay --- very cool wrapping this in the SolaraViz!

Only concern is the build is failing

image

I lost the thread of the conversation is the intro tutorial going to be updated in a different pull request?

@EwoutH
Copy link
Member

EwoutH commented Sep 26, 2024

Thanks for reviewing, did you try it yourself?

Only concern is the build is failing

That's not related to this PR, and we already fixed that in #251

@EwoutH
Copy link
Member

EwoutH commented Sep 26, 2024

Okay so I tested this by building a viz app for geo_sir

import sys
import os

# Add the directory containing mesa-geo to the Python path
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..')))

from mesa.visualization import SolaraViz, make_plot_measure
from agents import PersonAgent
from model import GeoSir

# Import the make_geospace_leaflet function directly
from mesa_geo.visualization import make_geospace_leaflet

def SIR_draw(agent):
    """
    Portrayal Method for canvas
    """
    portrayal = {}
    if isinstance(agent, PersonAgent):
        portrayal["marker_type"] = "Circle"
        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_params = {
    "pop_size": {
        "type": "SliderInt",
        "value": 30,
        "min": 10,
        "max": 100,
        "step": 10,
        "label": "Population size",
    },
    "init_infected": {
        "type": "SliderFloat",
        "value": 0.2,
        "min": 0.0,
        "max": 1.0,
        "step": 0.05,
        "label": "Fraction initial infection",
    },
    "exposure_distance": {
        "type": "SliderInt",
        "value": 500,
        "min": 100,
        "max": 1000,
        "step": 100,
        "label": "Exposure distance",
    },
}

model1 = GeoSir()

page = SolaraViz(
    model1,
    model_params=model_params,
    name="Basic agent-based SIR model",
    components=[
        make_geospace_leaflet(SIR_draw, zoom=12, scroll_wheel_zoom=False),
        make_plot_measure(["infected", "susceptible", "recovered", "dead"]),
        make_plot_measure(["safe", "hotspot"]),
    ]
)

Running with:

solara run "docs/examples/projectmesa mesa-examples main gis-geo_sir/app.py"

(yeah I named my folder terribly)

It runs, which is great:
image
However, when I press reset I and then run, it directly crashes on the first step:

Traceback (most recent call last):
  File "C:\Users\Ewout\.virtualenvs\Py312\Lib\site-packages\reacton\core.py", line 1707, in _render
    root_element = el.component.f(*el.args, **el.kwargs)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Ewout\.virtualenvs\Py312\Lib\site-packages\mesa\visualization\solara_viz.py", line 243, in ModelController
    solara.lab.use_task(step, dependencies=[playing.value], prefer_threaded=False)
  File "C:\Users\Ewout\.virtualenvs\Py312\Lib\site-packages\solara\tasks.py", line 846, in use_task
    return wrapper(f)
           ^^^^^^^^^^
  File "C:\Users\Ewout\.virtualenvs\Py312\Lib\site-packages\solara\tasks.py", line 840, in wrapper
    raise task_instance.exception
  File "C:\Users\Ewout\.virtualenvs\Py312\Lib\site-packages\solara\tasks.py", line 259, in runner
    self._last_value = value = await self.function(*args, **kwargs)
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Ewout\.virtualenvs\Py312\Lib\site-packages\mesa\visualization\solara_viz.py", line 241, in step
    do_step()
  File "C:\Users\Ewout\.virtualenvs\Py312\Lib\site-packages\mesa\visualization\solara_viz.py", line 247, in do_step
    model.value.step()
  File "C:\Users\Ewout\.virtualenvs\Py312\Lib\site-packages\mesa\visualization\solara_viz.py", line 152, in step
    original_step()
  File "C:\Users\Ewout\.virtualenvs\Py312\Lib\site-packages\mesa\model.py", line 73, in _wrapped_step
    self._user_step(*args, **kwargs)
  File "C:\Users\Ewout\Documents\GitHub\mesa-geo\docs\examples\projectmesa mesa-examples main gis-geo_sir\model.py", line 108, in step
    self.agents_by_type[PersonAgent].shuffle_do("step")
  File "C:\Users\Ewout\.virtualenvs\Py312\Lib\site-packages\mesa\agent.py", line 306, in shuffle_do
    getattr(agent, method)(*args, **kwargs)
  File "C:\Users\Ewout\Documents\GitHub\mesa-geo\docs\examples\projectmesa mesa-examples main gis-geo_sir\agents.py", line 55, in step
    for neighbor in neighbors:
                    ^^^^^^^^^
  File "C:\Users\Ewout\Documents\GitHub\mesa-geo\mesa_geo\geospace.py", line 205, in get_neighbors_within_distance
    yield from self._agent_layer.get_neighbors_within_distance(
  File "C:\Users\Ewout\Documents\GitHub\mesa-geo\mesa_geo\geospace.py", line 397, in get_neighbors_within_distance
    possible_neighbors = self._get_rtree_intersections(geometry)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Ewout\Documents\GitHub\mesa-geo\mesa_geo\geospace.py", line 287, in _get_rtree_intersections
    self._id_to_agent[i] for i in self._idx.intersection(geometry.bounds)
    ~~~~~~~~~~~~~~~~~^^^
KeyError: 2287846026144

@tpike3
Copy link
Member

tpike3 commented Sep 26, 2024

Okay so I tested this by building a viz app for geo_sir

...

self._id_to_agent[i] for i in self._idx.intersection(geometry.bounds)
~~~~~~~~~~~~~~~~~^^^

KeyError: 2287846026144

OK thats because mesa-geo assigns a very large number to plygon agents, which should now be replaced just the auto created id. I am looking for the line(s)

@tpike3
Copy link
Member

tpike3 commented Sep 26, 2024

@EwoutH I think the problem is here --mesa-geo agents property

This is using agents as a property and may be causing a collision with agents in Mesa now.

Mesa-geo creates a rtree index for spatial indexing, so I think the agent_ids are coming into conflict.

@wang-boyu
Copy link
Member Author

Is it because of this:

index_data = ((id(agent), agent.geometry.bounds, None) for agent in agents)

We used the agent object id as key, and the agent object may be deleted and recreated during model reset, resulting in a different object id. Changing this to agent.unique_id may help? Not very sure about it.

@wang-boyu
Copy link
Member Author

Replaced id(agent) with agent.unique_id in geospace. Would you like to try again @EwoutH ? Thanks for testing this btw.

@EwoutH
Copy link
Member

EwoutH commented Sep 26, 2024

Awesome, resetting the model now works!

@EwoutH
Copy link
Member

EwoutH commented Sep 26, 2024

I'm good with merging. It works, run well, and it's great that it now uses SolaraViz directly, it's nice to have a single interface.

It might even help with projectmesa/mesa#2330 ;)

Thanks for the effort!

@wang-boyu
Copy link
Member Author

Thank you @Corvince @EwoutH @rht @tpike3. I'll merge this now.

@wang-boyu wang-boyu merged commit 397fa42 into projectmesa:main Sep 26, 2024
10 of 13 checks passed
@wang-boyu wang-boyu deleted the viz/new-solara-api branch September 26, 2024 20:39
@EwoutH
Copy link
Member

EwoutH commented Sep 26, 2024

Congrats!

Are there any old viz components that should be removed or deprecated?

@wang-boyu
Copy link
Member Author

No I would prefer to keep the current GeoJupyterViz for now until the new API is ready and we figure out what to do with GeoJupyterViz. Would you like to make a prerelease now? I can start updating the gis examples to use the solara viz.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Release notes label
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants