Recipes
ABM Integration
Currently, SHoBNetPy supports mesa as agent-based modelling framework. You may want to have a look at the examples that come with SHoBNetPy.
Mesa models: Requirements
The model’s agents need to implement NetworkedGeoAgent and be added to the model’s mesa.geo.GeoSpace.
In case your agents are not yet within mesa.geo.GeoSpace but related objects are (e.g. buildings), consider passing the attributes geometry and crs from the related object to GeoAgent.__init__() inside the agent’s __init__() method. This way the agent will be considered to be placed at the same location as the related object, and spatial networking will be possible. In case the related spatial object is a polygon, consider assigning geometry.centroid to the agent’s geometry attribute.
GeoAgent.__init__(self,
unique_id=unique_id,
model=model,
geometry=geometry,
crs=crs
)
Mesa models: Network initialisation
# to me called from the model:
self.grid = sn.SHoBNetworkGrid(agents, self, self.space)
Mesa models: Using the network
# to me called from the agent:
for neighbour in self.grid.get_neighbors(self):
neighour.visit()
Hint
When importing agents, per default mesa geo assigns the index of the feature
to agent’s unique_id. However, you can explicitly specify the unique_id
column with the named parameter unique_id=<column> when calling
`` mg.AgentCreator.from_file()``.
Mesa models: Running the model
Before simulation, you should configure SHoBNetPy! After network creation, you may want to analyse or _app_recipes_visualise generated networks.
Defining Distributions
For degree and distance, agent-type (milieu)-specific random number distributions need to be defined. This is done in an excel file (settings.input.param_file_agent) and according sheets:
type |
distribution |
n |
p |
loc |
|---|---|---|---|---|
0 |
nbinom |
3.6 |
0.2 |
0 |
1 |
nbinom |
2.57 |
0.14 |
0 |
2 |
nbinom |
3.35 |
0.21 |
0 |
3 |
nbinom |
2.63 |
0.14 |
0 |
4 |
nbinom |
3.18 |
0.17 |
0 |
The distributions are imported from SciPy. Supported distributions are listed at https://docs.scipy.org/doc/scipy/reference/stats.html.
The column headers of parameters must correspond to the parameter names of the distribution function, e.g. “loc” and “scale” for “norm”.
Creating Hexagon Shapefiles
Hexagon shapefiles are required to determine distances between agents. Since the size of hexagons depends on the simulation region and desired performance, often according hexagon shapefiles need to be created anew.
By default, this is performed within SHoBNetPy, but shapefiles can also
be created beforehand (and the filename assigned to parameter
geo.hexagon1_shapefile and geo.hexagon2_shapefile).
- ..note::
The hexagon shapefile must cover all agent positions and should not be much larger since it is used to calculated the area’s diameter which is used to initialised the distance distributions!
Using SHoBNetPy (default)
If no input shapefile is given or the specified file not existing, SHoBNetPy generates shapefiles automatically.
QGIS installation is a pre-requisite:
https://www.qgis.org/en/site/forusers/alldownloads.html#
To resolve issues with not finding qgis module or shared object files, visit https://docs.qgis.org/2.18/de/docs/pyqgis_developer_cookbook/intro.html#running-custom-applications
Using your own hexagon initialiser
For the hexagon initialisers, SHoBNetPy offers a plugin mechanism.
Write your own initialiser implementing HexagonInitialiser, register the
plugin and use it:
sn.register_plugin(
"yourinitialiser",
"shopnetpy_hexgoninit",
"yourapp.geo.hexagon:YourHexagonInitialiser")
sn.settings.geo.hexagon_initialiser = "yourinitialiser"
Manually in QGIS
Download and install QuantumGIS
Download and install the python plugin mmqgis
Settings > Project Properties > Select “WTS 84 / UTM zone 32N”
Choose plugins > mmqgis > create > Create Grid Layer
Select Hexagon (polygon) at the bottom
Adapt and use these values (here for a 1km x 1km area with 200m wide hexagons; note that the hexagon shapefile’s boundary exceeds the actual area in order to cover the entire region.):
Left X
-150
Width
1300
Bottom Y
-150
Height
1200
H Spacing
200
V Spacing
auto
Make sure that the shapefile defines the correct CRS by inspecting the
*.prjfile (usually the plugin does not assign a CRS). If not, right-click on the layer in QGIS and save as a new file. You can choose the CRS in the “Save vector layer as…” dialog.
Visualise Generated Networks
Output network as edgelist when generating:
[output]
output_agentshapes = false
output_agentshapes_folder = "agentsshapes"
output_agentshapes_file = "agents.geojson"
output_edgescsv = true
output_edgescsv_folder = "edgecsv"
output_edgescsv_filename = "edges.csv"
Import agent GIS data into QGIS
Layer > Add Layer > Add Vector Layer
Select according file
Add
Import the edgelist to QGIS
Layer > Add Delimited Text Layer or choose “Delimited Text” in the previous menu
Select output edge list file
File Format: Custom delimiter > Semicolon
Add
Add virtual layer
Layer > Add Layer > Add/Edit Virtual Layer or choose “Virtual Layer” in the previous menu
Name it “agents_edges”
Add the SQL statement into the “Query” field:
SELECT field_1, field_2, makeline(a.geometry, b.geometry) FROM edges JOIN agents a ON edges.field_1 = a.unique_id JOIN agents b ON edges.field_2 = b.unique_id WHERE a.unique_id != b.unique_id
Geometry > Autodetect
Add
Close
Add line style
Rightclick on layer agent_edges > Properties > Symbology
Select “Simple line” entry
“Add symbol layer” (+ sign)
Select “Geometry Generator” as Symbol layer type
Copy to the input field:
difference( difference( make_line( start_point($geometry), centroid( offset_curve( $geometry, length($geometry)/-5.0 ) ), end_point($geometry) ), buffer(start_point($geometry), 0.0003) ), buffer(end_point($geometry), 0.0003) )
Add
Set edge colours according to attributes:
Select “Simple Fill”
In line “Fill colour”, press the right-most button and choose “edit…”
Enter the following code:
CASE WHEN milieu_1 = 1 THEN '#4AAC96' WHEN milieu_1 = 2 THEN '#C7105C' WHEN milieu_1 = 3 THEN '#5095C8' WHEN milieu_1 = 4 THEN '#EAC372' WHEN milieu_1 = 5 THEN '#153824' ELSE '#ff7f00' END
OK