GithubHelp home page GithubHelp logo

projectmesa / mesa-geo Goto Github PK

View Code? Open in Web Editor NEW
143.0 15.0 51.0 2 MB

GIS Extension for Mesa Agent-Based Modeling

License: Other

Python 97.12% JavaScript 2.88%
agent-based-modeling complex-systems geospatial-modeling gis mesa python simulation mesa-geo

mesa-geo's Introduction

Mesa-Geo: GIS Extension for Mesa Agent-Based Modeling

GitHub CI Read the Docs Codecov Code Style PyPI PyPI - License PyPI - Downloads Matrix Chat DOI

Mesa-Geo implements a GeoSpace that can host GIS-based GeoAgents, which are like normal Agents, except they have a geometry attribute that is a Shapely object and a crs attribute for its Coordinate Reference System. You can use Shapely directly to create arbitrary geometries, but in most cases you will want to import your geometries from a file. Mesa-Geo allows you to create GeoAgents from any vector data file (e.g. shapefiles), valid GeoJSON objects or a GeoPandas GeoDataFrame.

Using Mesa-Geo

To install Mesa-Geo on linux or macOS run

pip install mesa-geo

On windows you should first use Anaconda to install some of the requirements with

conda install fiona pyproj rtree shapely
pip install mesa-geo

Since Mesa-Geo is in early development you could also install the latest version directly from Github via

pip install -e git+https://github.com/projectmesa/mesa-geo.git#egg=mesa-geo

Take a look at the examples folder for sample models demonstrating Mesa-Geo features.

For more help on using Mesa-Geo, check out the following resources:

Contributing to Mesa-Geo

Want to join the team or just curious about what is happening with Mesa & Mesa-Geo? You can...

  • Join our Matrix chat room in which questions, issues, and ideas can be (informally) discussed.
  • Come to a monthly dev session (you can find dev session times, agendas and notes at Mesa discussions.
  • Just check out the code at GitHub.

If you run into an issue, please file a ticket for us to discuss. If possible, follow up with a pull request.

If you would like to add a feature, please reach out via ticket or join a dev session (see Mesa discussions). A feature is most likely to be added if you build it!

Don't forget to check out the Contributors guide.

Citing Mesa-Geo

To cite Mesa-Geo in your publication, you can use the CITATION.bib.

mesa-geo's People

Contributors

corvince avatar dependabot[bot] avatar dhruv4 avatar glicerico avatar holzhauer avatar majdal avatar pre-commit-ci[bot] avatar rht avatar tpike3 avatar wang-boyu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mesa-geo's Issues

Consistency in README tutorial

Going through the tutorial in README, there's a small error that that took me a bit of investigating to figure out, so maybe it's worthwhile to correct. I'm happy to create a pull request, but first I'd like to hear from the author/community about what's the best way to correct it.

The GeoJSON that you provide in the example is in WGS84 (EPSG:4326), not in WGS 84 / Pseudo-Mercator (EPSG:3857). With the default CRS (3857), the example shows a blank box instead of the map of Arizona. Setting the CRS explicitly in the AgentCreator to 4326 fixes the issue. The image attached should be corrected to look like the following:

Arizona map at epsg:4326

The image currently in the tutorial is the one below, and it's in epsg:2163. The difference might create some unnecessary confusion to a beginner.

Arizona map at epsg:2163

This also means that the distance calculation (m.grid.get_neighbors_within_distance(agent, 600000)) has the wrong distance/units.

Should we move the reference to explicitly setting the CRS to be just after the model definition?

Other map visualization

I would be nice to have another map visualization like google maps, i know its paid but you would just have to get an activation key

Creating agents using latitude and longitude

Hi all,
I have a csv file with just the latitude and longitude of agents, is there a way I can represent these agents on a geospatial grid?
I will be very grateful for any suggestions.

GeoAgent portrayal

What's the problem this feature will solve?

Currently it is possible to change the color of polylines and polygons, and radius and color of points:

agentLayer = L.geoJSON(agents, {
onEachFeature: PopUpProperties,
style: function (feature) {
return {color: feature.properties.color};
},
pointToLayer: function (feature, latlang) {
return L.circleMarker(latlang, {radius: feature.properties.radius, color: feature.properties.color});
}
}).addTo(Lmap)

But Leaflet.js supports many other styling properties for GeoJSON:

Describe the solution you'd like

Make full use of what's supported by Leaflet.js.

Mobility_range value

Hi I have a question, regarding mesa-geo/examples/GeoSIR/model.py
Could you tell me what the mobility_range value represents? I understand it is a measure of how much the agent should move but I don't understand if the value is in meters, kilometres, miles...

Thank you!

GeoSIR error: _recreate_rtree() missing 1 required positional argument: 'new_agents'

Dear GeoSIR friends:
I have tried to run GeoSIR project but I have two issues:

  1. Firefox does not display neither map nor data
    How can I configure my browser in order to display the map?

  2. Chromium displays the map and data, but when I tried to run the model, I get the next message:

ERROR:tornado.application:Uncaught exception GET /ws (127.0.0.1)
HTTPServerRequest(protocol='http', host='127.0.0.1:8521', method='GET', uri='/ws', version='HTTP/1.1', remote_ip='127.0.0.1')
Traceback (most recent call last):
File "/lib/python3.7/site-packages/tornado/websocket.py", line 649, in _run_callback
result = callback(*args, **kwargs)
File "/lib/python3.7/site-packages/mesa_geo/visualization/ModularVisualization.py", line 199, in on_message
self.application.model.step()
File "/mesa-geo-master/examples/GeoSIR/model.py", line 217, in step
self.grid._recreate_rtree() # Recalculate spatial tree, because agents are moving
TypeError: _recreate_rtree() missing 1 required positional argument: 'new_agents'

Do you know how can I fix it?

My platform is LinuxUbuntu 18.04 and python 3.7 .

Thanks.

Off by 1 error in create_rtree

Hi,

I've been working on a model using Mesa and mesa-geo and I think I found an off-by-one error in create_rtree. Fix is included in the following example, but I can also send you a pull request if you like.

Cheers,
Berend

from mesa_geo import GeoSpace, GeoAgent
from rtree import index
import numpy as np

### A point and an area on the map (taken randomly from an area I was working on).
geojson = {
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "properties": {
                "name": "Place 1"
            },
            "geometry": {
                "type": "Point",
                "coordinates": (77.51153557398285, 12.99263321577877)
            }
        },
        {
            "type": "Feature",
            "properties": {
                "name": "Polygon 1"
            },
            "geometry": {
                "type": "Polygon",
                "coordinates": (
                    ((77.51123346718991, 12.992670785882310, 0.0),
                     (77.51152849328670, 12.992644874747185, 0.0),
                     (77.51163657102643, 12.992596162126380, 0.0),
                     (77.51141598069705, 12.992492901787061, 0.0),
                     (77.51107841065166, 12.992325112397564, 0.0),
                     (77.51093841043954, 12.992298472878362, 0.0),
                     (77.51100798363507, 12.992609158241951, 0.0),
                     (77.51115273788980, 12.992670631920141, 0.0),
                     (77.51111122952850, 12.992710069434820, 0.0),
                     (77.51101370887120, 12.992953447818099, 0.0),
                     (77.51130135960666, 12.993078282112991, 0.0),
                     (77.51138271453809, 12.993073876211817, 0.0),
                     (77.51127776250400, 12.992831987550323, 0.0),
                     (77.51136227169478, 12.992745508748830, 0.0),
                     (77.51123346718991, 12.992670785882310, 0.0)),
                )
            }
        }
    ]
}

# Create a geospace and load the agents
grid = GeoSpace(crs='epsg:4326')
grid.create_agents_from_GeoJSON(geojson, agent=GeoAgent, model=None, unique_id="name")

# They're loaded successfully
print("Grid size: ", len(grid.agents))
print(grid.agents[0].unique_id, "Shape: ", grid.agents[0].shape)
print(grid.agents[1].unique_id, "Shape:", grid.agents[1].shape)

# Shapely shows the point is indeed in the area
print("\nShapely within/contains:")
print("Point within area:", grid.agents[0].shape.within(grid.agents[1].shape))
print("Area contains point:", grid.agents[1].shape.contains(grid.agents[0].shape))

# The area has intersections with the point, but the point does not with the area, strange
point_intersections = grid.get_rtree_intersections(grid.agents[0])
area_intersections = grid.get_rtree_intersections(grid.agents[1])
print("\nDefault rtree")
print("Point intersections", [a.unique_id for a in point_intersections])
print("Area intersections", [a.unique_id for a in area_intersections])


##### Fix is here
def create_rtree_fixed(self):
    """Create a new rtree index from agents shapes."""
    shapes = []
    i = 0
    for i, agent in enumerate(self.agents):
        agent.idx_id = i
        shapes.append(agent.shape)

    index_ids = range(i+1)  # Off by one error

    # Bulk load the shapes
    def data_gen():
        for index_id, shape in zip(index_ids, shapes):
            yield (index_id, shape.bounds, shape)

    self.idx = index.Index(data_gen())
    self.idx.maxid = i

# Apply the new rtree
create_rtree_fixed(grid)

point_intersections = [a.unique_id for a in grid.get_rtree_intersections(grid.agents[0])]
area_intersections = [a.unique_id for a in grid.get_rtree_intersections(grid.agents[1])]

# Indeed the fix works
print("\nFixed rtree")
print("Point intersections", point_intersections)
print("Area intersections", area_intersections)

Output generated by this script:

Grid size:  2
Place 1 Shape:  POINT (77.51153557398285 12.99263321577877)
Polygon 1 Shape: POLYGON Z ((77.51123346718991 12.99267078588231 0, 77.5115284932867 12.99264487474719 0, 77.51163657102643 12.99259616212638 0, 77.51141598069705 12.99249290178706 0, 77.51107841065166 12.99232511239756 0, 77.51093841043954 12.99229847287836 0, 77.51100798363507 12.99260915824195 0, 77.5111527378898 12.99267063192014 0, 77.5111112295285 12.99271006943482 0, 77.5110137088712 12.9929534478181 0, 77.51130135960666 12.99307828211299 0, 77.51138271453809 12.99307387621182 0, 77.51127776250399 12.99283198755032 0, 77.51136227169478 12.99274550874883 0, 77.51123346718991 12.99267078588231 0))

Shapely within/contains:
Point within area: True
Area contains point: True

Default rtree
Point intersections []
Area intersections ['Place 1']

Fixed rtree
Point intersections ['Polygon 1']
Area intersections ['Place 1']

Add getting started instructions

Hey! Really excited about this! Can you add 'getting started' instructions to the Read me for folks that want to play around with it. :-)

How can I get step count?

So, I am saving the results of each step in a CSV file. I want to save the step number too. How can I get the step count?
I tried counting through a variable like count=0 and then count+=1, but that doesn't work properly as it increments the count for each agent (eg I have 4 different types of agents like I have 100 agent 1's 50 agent 2's etc, so the count variable will increment the count 100 times just for agent 1).
On the command line, when I click step I can see a dictionary that has steps inside it. If somehow I can access that, that would work too (I have looked through the root code and I couldn't find it).
Sorry if the question is confusing, please let me know If anyone wants me to explain more.
I will be very grateful for any suggestions.

How to debug mesa-geo? AttributeError: module 'ntpath' has no attribute 'sep'

If I try to debug a mesa-geo application in PyCharm on Windows ... for the line

tornado.ioloop.IOLoop.current().start()

in ModularViualization.py

I get:

C:\python_env\App\PyCharm\..\..\App\WinPython\python-3.10.2.amd64\python.exe C:\python_env\App\PyCharm\plugins\python-ce\helpers\pydev\pydevd.py --multiproc --qt-support=auto --client 127.0.0.1 --port 52260 --file C:/python_env/workspace/TechDiff/src/main.py
Connected to pydev debugger (build 213.6777.50)
Interface starting at http://127.0.0.1:8521
ERROR:tornado.application:Uncaught exception GET /static/css/bootstrap.min.css (127.0.0.1)
HTTPServerRequest(protocol='http', host='127.0.0.1:8521', method='GET', uri='/static/css/bootstrap.min.css', version='HTTP/1.1', remote_ip='127.0.0.1')
Traceback (most recent call last):
  File "C:\python_env\App\WinPython\python-3.10.2.amd64\lib\site-packages\tornado\web.py", line 1704, in _execute
    result = await result
  File "C:\python_env\App\WinPython\python-3.10.2.amd64\lib\site-packages\tornado\web.py", line 2573, in get
    self.path = self.parse_url_path(path)
  File "C:\python_env\App\WinPython\python-3.10.2.amd64\lib\site-packages\tornado\web.py", line 2961, in parse_url_path
    if os.path.sep != "/":
AttributeError: module 'ntpath' has no attribute 'sep'

If I run mesa-geo without debugging I do not get this error.

versions:
mesa-geo: 0.2.0
tornado: 6.1
pycharm: 2021.3.2 (Community Edition)

=> Do I need to consider something special if I want to debug mesa-geo?

Issue with GeoSchelling example

Hi, I'm trying to run the GeoSchelling examply and i'm getting an error, i suppose it would be a library that i need to install but i cant find out which one is, hope you can help me.

Traceback (most recent call last):
File "run.py", line 1, in
from server import server
File "C:\Users\alrot\OneDrive\Escritorio\TFG - Alberto Lรณpez Santiago\mesa-geo-master\examples\GeoSchelling\server.py", line 46, in
SchellingModel, [map_element, happy_element, happy_chart], "Schelling", model_params
File "c:\users\alrot\src\mesa-geo\mesa_geo\visualization\ModularVisualization.py", line 276, in init
self.reset_model()
File "c:\users\alrot\src\mesa-geo\mesa_geo\visualization\ModularVisualization.py", line 302, in reset_model
self.model = self.model_cls(**model_params)
File "C:\Users\alrot\OneDrive\Escritorio\TFG - Alberto Lรณpez Santiago\mesa-geo-master\examples\GeoSchelling\model.py", line 61, in init
self.grid = GeoSpace(crs={"init": "epsg:4326"})
File "c:\users\alrot\src\mesa-geo\mesa_geo\geospace.py", line 36, in init
self.crs = pyproj.Proj(crs)
File "C:\Users\alrot\Anaconda3\lib\site-packages\pyproj_init_.py", line 358, in new
return _proj.Proj.new(self, projstring)
File "_proj.pyx", line 84, in _proj.Proj.cinit
RuntimeError: b'No such file or directory'

Exclude some GeoAgents attributes from visualization

I already encountered two situations where some GeoAgents' attributes are causing the impossibility of visualizing the model interactively. 1) When they cause the agent to not be JSON serializable (for instance causing reciprocal references of agents or being pandas data structures), which causes an error 2) When they store lots of data, which makes the initialization of the visualization too long.

Is there a way to exclude some attributes of the GeoAgents from the interactive visualization? Thanks!

Syntax change in pyproj raising FutureWarning

First of all, nice work! This is a very exciting project :)

I was going through the tutorial, and I got the following warning:

/Users/me/.local/share/virtualenvs/thesis-PKkYFUSX/lib/python3.6/site-packages/pyproj
/crs/crs.py:55: FutureWarning: '+init=<authority>:<code>' syntax is deprecated. '<authority>:
<code>' is the preferred initialization method. When making the change, be mindful of axis order 
changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6

Following the link in the warning, it's clear that there's a syntax change in pyproj. I dug through mesa-geo's code, and fixed the issue. I'm creating a pull request to go along.

Puzzling result when modifying GeoSIR example

I aim to use Mesa, and potentially Mesa-geo, to model virus transmission within a building (specifically, a hospital). So I tried substituting a geojson file derived from a polygon Shapefile representing the internal layout of a building, for the file of Toronto neighbourhoods. I attach the zipped file below (the building is a university building in Chicago, the Edward D Anderson Building, as I don't yet have the hospital floor plans).

The model appears to run successfully, but the visualization does not work properly. A map appears, and I can zoom in on the building. No internal structure or agents show up - perhaps not surprising given the source of the "Leaflet" maps - but the steps counter does not appear, and the chart has the wrong Y-axis, and nothing appears on it as the model runs. I have (accidentally) discovered that running the original model within a Jupyter notebook, preceded by the command:
%matplotlib widget
reproduces the same faulty visualization.

I can't see any feature of the geojson file that differs in any obvious way from the original. Using a different alternative - a map of postal districts in part of London - does not cause the same problem. Using a geopandas GeoDataFrame, or the Shapefile itself, gives the same result as using the geojson file. Removing "map_element" from the list of visualization elements used to define "server" results in the steps counter and correct chart appearing.

Any ideas what is happening? Thanks.
Nick Gotts ([email protected] - new work email)

Rooms2_fixed_4326.zip

Convenient methods in RasterLayer

What's the problem this feature will solve?

  1. Load/save raster cell values directly from/to files.
  2. Get random coordinates within cells based on cell coordinates. In situations like population in the same cell, they don't need to have exactly the same coordinates.

Describe the solution you'd like

  1. Have a RasterLayer.from_file(file_path, name, compression) class method to create RasterLayer with cell attribute name. The file can optionally be a gzip file.
    Similarly for saving to files: RasterLayer.to_file(file_path, compression).
  2. Implement a raster_layer.get_random_coord(cell.pos) method.

Additional context

See comments from #90 (comment) and #90 (comment).

Exception when adding raster cells to scheduler as agents

Describe the bug

When adding raster cells to a model scheduler as agents, the following error appears:

Exception: Agent with unique id None already added to scheduler

Expected behavior

Raster cells can be added into model schedulers as normal agents.

Additional context

mesa.time.BaseScheduler requires an agent to have a unique id.

Error in extracting agents from GeoSpace.agents

Hi! I'm following the README tutorial and I'm getting an error in the passage to extract the list of agents.

If I run the line agent = m.grid.agents[0] I get the TypeError "'dict_values' object is not subscriptable". I checked the module and, in fact, when I call the agents attribute I get a dict_values object.
Shouldn't it be converted to a list in order to be indexable? To make it work I have to use agent = list(m.grid.agents)[0].

Thanks!

Create tests

Mesa-geo only includes one very small test so far. We need more tests for the different functions of GeoSpace.

GeoSpace.get_neighbors_within_distance(... center=True ...) fails

The center=True parameter to get_neighbors_within_distance results in an error due to the use of shape.center(), which apparently does not exist. Should use shape.centroid instead.

Relevant code fragment, here I have agents that are circles, I want to know if the centers are within a certain distance.

violaters = [b for b in self.model.grid.get_neighbors_within_distance(self,
                                                                      self.model.mile_buffer*6075,
                                                                      center=True) if b.type == 'buffer']

Results in the following error:

Traceback (most recent call last):
  File "/home/rcriii/workspace/Steelhead/venv/lib/python3.8/site-packages/tornado/websocket.py", line 647, in _run_callback
    result = callback(*args, **kwargs)
  File "/home/rcriii/workspace/Steelhead/./mesa-geo/mesa_geo/visualization/ModularVisualization.py", line 199, in on_message
    self.application.model.step()
  File "/home/rcriii/workspace/Steelhead/model.py", line 233, in step
    self.schedule.step()
  File "/home/rcriii/workspace/Steelhead/venv/lib/python3.8/site-packages/mesa/time.py", line 84, in step
    agent.step()
  File "/home/rcriii/workspace/Steelhead/DredgeAgent.py", line 257, in step
    violaters = [b for b in self.model.grid.get_neighbors_within_distance(self,
  File "/home/rcriii/workspace/Steelhead/DredgeAgent.py", line 257, in <listcomp>
    violaters = [b for b in self.model.grid.get_neighbors_within_distance(self,
  File "/home/rcriii/workspace/Steelhead/./mesa-geo/mesa_geo/geospace.py", line 107, in get_neighbors_within_distance
    shape = agent.shape.center().buffer(distance)
AttributeError: 'Polygon' object has no attribute 'center'

Using Python 3.8.10, Shapely 1.8.0, Unbuntu SMP

Agent collisions

What's the problem this feature will solve?

Solves the problem that two agents are in the exact same coordinates, in the real world two poeple cant be in the exact same spot

DeprecationWarning: skip_equivalent is deprecated with mesa-geo 0.2.0 and pyproj 3.3.0

I get following warning from mesa-geo during my tests:

  C:\python_env\App\WinPython\python-3.10.2.amd64\lib\site-packages\mesa_geo\geospace.py:40: DeprecationWarning: skip_equivalent is deprecated.
    self.Transformer = pyproj.Transformer.from_crs(

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html

=> Please update mesa-geo for pyproj 3.3.0

JS/CSS dependencies management in mesa-geo

What's the problem this feature will solve?

Some JS/CSS files and their corresponding python modules are copied over from mesa, and may be incomplete or out-of-date.

This also leads to confusion from users on which frontend files belong to mesa-geo (e.g. projectmesa/mesa#1537).

Describe the solution you'd like

The solution will depend on how mesa manages the frontend files in the future.

Besides, there have been some fixes and some ongoing efforts to improve the frontend elements in mesa, such as

These fixes and improvements should be automatically applied to mesa-geo.

Lastly, the solution should be flexible in that, extensions and modifications to existing frontend elements can be done easily in mesa-geo.

Additional context

Installing mesa-geo in Windows 10

Has anyone succeeded in installing mesa-geo on Windows 10? I have tried both methods suggested, in Anaconda. HEre's the error message:

ERROR: Command errored out with exit status 1:
command: 'C:\Users\NMG\anaconda3\python.exe' -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'C:\Users\NMG\AppData\Local\Temp\pip-install-x7ykh3k9\fiona\setup.py'"'"'; file='"'"'C:\Users\NMG\AppData\Local\Temp\pip-install-x7ykh3k9\fiona\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(file);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, file, '"'"'exec'"'"'))' egg_info --egg-base 'C:\Users\NMG\AppData\Local\Temp\pip-pip-egg-info-sxn218qg'
cwd: C:\Users\NMG\AppData\Local\Temp\pip-install-x7ykh3k9\fiona
Complete output (1 lines):
A GDAL API version must be specified. Provide a path to gdal-config using a GDAL_CONFIG environment variable or use a GDAL_VERSION environment variable.
----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

So I try installing gdal, using the recommended command:
conda install -c conda-forge gdal
This comes up with pages of "conflicts", and does not appear to work.
Any advice gratefully received.

Import shapes from various formats

Currently, one can import Agent from shapes if data is in the GeoJSON format. A more user-friendly way would be to support various file formats. Changing the internal GeoSpace representation to a GeoPandas GeoDataFrame we should be able to import most formats with a .from_file() function (passed directly to GeoPandas). Additionaly we should keep the .from_GeoJSON() (for example for accessing web ressources) and also include .from_GDF() (for direct import of GeoDataFrames).

Any more ideas/wishes for data formats?

@ljwolf
1 .OK; I think that's pretty straight forward, then! I can help implement this as needed, but I do not have the same amount of time for this stuff now that the scipy sprints are over ๐Ÿ˜„

Thanks for offering help, but I guess I will implement the GeoPandas part myself and then there is nothing left to do on this issue ;)

Performance and Scalability

Hi
Can you give some tips on how to improve step performance for a large scale simulation?

Regards

/Imran

Cell aggregation API in raster layer

What's the problem this feature will solve?

Currently if the users would like to find the min/max cell based on certain criteria, they'll have to it manually like this:

min(raster_layer.get_neighboring_cells(pos, ...),
    key=lambda cell: cell.attribute)

Describe the solution you'd like

To have a more powerful and fluent API for cell aggregation similar to Pandas, e.g.,

raster_layer.get_neighboring_cells(pos, ...).by("attribute").min()
raster_layer.get_neighboring_cells(pos, ...).by(lambda cell: cell.attribute).min()
raster_layer.get_neighboring_cells(pos, ...).by(["attribute_0", "attribute_1"]).agg(["min", "max"])
raster_layer.get_neighboring_cells(pos, ...).by("attribute").agg(lambda cell_list: random.choice(cell_list))

Additional context

See comments from #75 (comment).

Option to turn on/off basemap

What's the problem this feature will solve?

Currently an OpenStreetMap layer is used as base map, but not everyone needs it as the background for visualisation. For some cases the coordinate reference system (CRS) isn't available (corrupted, missing, or the GIS data is demo files with no link to the real world), making it impossible to use a base map.

Describe the solution you'd like

In MapModule add an additional parameter to turn on/off basemap, e.g.,

map_element = MapModule(..., basemap=True, ...)

Additional context

Leaflet has many basemap providers apart from OpenStreetMap. It would be nice to have a systematic way to integrate more basemaps. Perhaps this can be raised as a separate feature request.

Then the basemap parameter can be either boolean (True/False) or string (name of the basemap provider).

Third-party libraries that might be useful: leaflet-providers (javascript), xyzservices (python)

Similar function in the lets-plot library: Configuring Basemap Tiles for Interactive Maps

Update for Mesa v1.0.0

What's the problem this feature will solve?

Make Mesa-Geo updated with Mesa v1.0.0

Describe the solution you'd like

  • Specify Mesa version 1.x as a requirement in setup.cfg and pyproject.toml.
  • Change the CSS dependency as mentioned in #52 (comment)
  • Remove jQuery usage in MapModule.js.
  • Use Slider instead of UserSettableParameter in examples

Attributes

Hello everyone,
How can I access the attributes of the Geodataframe that I use to add the agents?
In the project, I am working on I want to access the coordinates of each agent and use them. Is there a way I can do that?
I already did "set_attributes = True", but I am confused as to how can I access their attributes.

I will be very grateful if anyone can point me in the right direction.

With kindest regards,
Harsh Panday

Agent Not Proper Removed With GeoSpace.remove_agent

It seems like the dictionary index.agents is not properly updated after remove_agent takes place. This results in issue such that when referencing grid.agents in a model, the removed agent still exists.

Simple and consistent settings for coordinate reference system (CRS)

What's the problem this feature will solve?

Consistent coordinate reference system (CRS) is important for map processing and visualisation. Incorrect CRS settings can lead to incorrect or empty map in mesa-geo.

Currently the workflow is:

flowchart TD
    A["Shapefiles<br><br>arbitrary CRS<br>(might be missing)"] --> |read by| B["GeoPandas"];
    B --> |create| C["GeoDataFrame<br><br>same CRS as shapefiles<br>(might be missing)"]
    C -->|loaded by| D["AgentCreator<br><br>user-defined CRS<br>(default: epsg:3857)"];
    E["GeoJSON<br><br>assuming no CRS"] --> |loaded by| F["GeoPandas"] --> |create| G["GeoDataFrame<br><br>hard-coded CRS<br>(set to epsg:4326)"] --> |loaded by| D;
    D --> |create| H["GeoAgent<br><br>no explicit CRS<br>implicitly same as AgentCreator<br>(default: epsg:3857)"]
    H --> |added into| I["GeoSpace<br><br>user-defined CRS<br>(default: epsg:3857)"]
    I --> |rendered by| J["MapModule<br><br>hard-coded CRS in GeoSpace<br>(set to epsg:4326)"]
    J --> |displayed by| K["LeafletMap.js<br><br>expects input as epsg:4326<br>internally transforms into epsg:3857"]

The following issues should be fixed:

  1. CRS is an optional field in GeoJSON. When it's present, it should be loaded correctly instead of overwritten by the default epsg:4326.
  2. The CRS of frontend element (e.g., LeafletMap.js) should be inside its corresponding Python module (e.g., MapModule.py). Similarly the coordinate transformation from GeoSpace to map elements should be done inside the map elements.
  3. Account for empty CRS if it's not available from input files or GeoJSON. This relates to #48.

Describe the solution you'd like

The solution should make sure the following constraints are met:

  1. AgentCreator, GeoAgent and GeoSpace have exactly the same CRS. At the moment they share the same defaults, but there's a chance for users to set them into different CRS, thereby resulting in incorrect map.
  2. MapModule has the same CRS as the frontend JavaScript map element. Right now the default CRS of Leaflet.js is set correctly, but inside GeoSpace instead of MapModule, making it difficult to use different frontend map elements of other CRS.

Additional context

idx_id not set when adding agents.

Hi,

When adding agents to the index, no matter which way, the add function does not set the idx_id on the agent, which means that the delete function does not work:

File "/Users/bweel/Software/projects/dynaslum/residential-choice-model/rcm/model/model.py", line 168, in remove_location
    self.grid.remove_agent(agent)
  File "/usr/local/lib/python3.6/site-packages/mesa_geo/geospace.py", line 67, in remove_agent
    self.idx.delete(agent.idx_id, agent.shape.bounds)
AttributeError: 'SlumLocationAgent' object has no attribute 'idx_id'

Virus on network issue

Hi,
I'm trying to run Virus on Network Example.

When I execute the run.py, I get this error:
AttributeError: module 'server' has no attribute 'launch'

There is no launch function on the server.py.
Any idea on how to resolve this, please?

How to get data from Google Maps

Hi, Iยดm trying to get data from roads to draw it and analize it's traffic, i had been searching for a long but i can't afford a way to get JSON or GeoJSON. Anyone could help me?

ValueError when adding vector layers into GeoSpace

Describe the bug

When adding a vector layer (geopandas.GeoDataFrame) into GeoSpace, the following error appears:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Expected behavior

Vector layers can be added into GeoSpace without errors.

Use ModularServer from Mesa

What's the problem this feature will solve?

Currently Mesa-Geo users need to use ModularServer from mesa_geo.visualization.ModularVisualization, instead of mesa.visualization.ModularVisualization, which could be confusing and lead to errors.

Describe the solution you'd like

Use ModularServer directly from mesa.visualization.ModularVisualization.

Additional context

See comments from projectmesa/mesa#1369

MapModule documentation + simpler visualization

Hi!
I'm using the MapModule to visualize my model.

I had a problem with the module, the step was not running and after some minutes I got an error that my GeoAgent class was not JSON serializable and I discovered that it was because I had a reciprocal reference that created an infinite loop. I think that in general, adding some documentation on how to use the MapModule would be really useful! Especially on requirements that should be met to avoid these problems (difficult to spot for who is not used to work with JSON files).

A second thing that I'd like to suggest is to provide a module to visualize just the grid of the model without the underlying map, that can be simpler and cleaner in some cases.

Use GeoPandas and PySAL for internal representation and calculation

Based on the discussions in projectmesa/mesa#513, we should use established libraries for data manipulation and querying and not try to ship own versions.

My idea would be to base the GeoSpace on a GeoPandas GeoDataFrame and internally just use the GeoPandas functions or PySAL.

@ljwolf can you confirm that if the data is stored in a GeoDataFrame we can just use PySAL functions for certain type of operations? Like in the link you posted

def graph_pysal(gdf):
    w = weights.Contiguity.Queen.from_dataframe(gdf)
    return w.neighbors

Would be sufficient to benefit from the speed ups? (Of course maybe with some output modification)

I agree that neighbordhood look-ups is something that will be very important for ABMs and it makes sense to go fort the fastest implementation. Do you know any other methods we should import form PySAL for significant performance (or other) improvements?

v0.3.0 release

  • Release the changes done in recent months as v0.3.0.
  • Publish the release to PyPI.

May still have a few pending items from #46.

The following tickets can be moved to the next release:

Portrayal shapes in mesa-geo

Discussed in #64

Originally posted by joshuashakya April 28, 2022
I am using mesa-geo for a project but am unable to change the shape of the GeoAgent using portrayal, only "circle" shape works.
I would like to get a rectangle:

portrayal["Shape"] = "rect"
portrayal["w"] = 2
portrayal["h"] = 2

Does anybody have a suggestion regarding this ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.