Functionalities
Accessing 3Di model components
threedigrid uses a limited number of main classes to access 3Di model components:
The Lines and Nodes classes have several child classes (e.g. Manholes or Weirs) that allow access to attributes specific to those 3Di model components.
Breaches, Nodes, Lines, and Pumps have time series connected to them through the GridH5ResultAdmin, GridH5AggregateResultAdmin, or GridH5WaterQualityResultAdmin.
Filters and subsets
To make selections of data, you can use Spatial filters, Non-spatial filters, Subsets, and Selecting attributes using only. You can chain these in any way you like. The example below returns all 1D nodes with a storage area >= 1.0 within a specific area.
ga.nodes.subset("1D_ALL").filter(storage_area__gte=1.0).filter(coordinates__intersects_geometry=my_polygon)
The filters and subsets are ‘lazy’, i.e. they are not executed until data is retrieved. To retrieve data you have to call data or timeseries() explicitly:
ga.nodes.filter(node_type__eq=5) # will not return all data
ga.nodes.filter(node_type__eq=5).data # returns all data as an OrderedDict
gr.nodes.timeseries(0, 3600).s1 # time series of the water levels of the first hour of the simulation
Spatial filters
The following filters are available for making spatial selections:
The spatial filters can be used on GeomArrayField subclasses:
Breaches: coordinates or line_geometries
Cells: cell_coords
Levees: coords
Lines: line_coords or line_geometries
Nodes: coordinates
Warning
Spatial filters only work on data in projected coordinate reference systems.
contains_point
The contains_point filter can be used to, e.g., identify a grid cell in which a given point falls:
ga.cells.filter(cell_coords__contains_point=xy).id
from shapely.geometry import Polygon
polygon = Polygon([
[109300.0, 518201.2], [108926.5, 518201.2], [108935.6, 517871.7], [109300.0, 518201.2]
])
ga.nodes.filter(coordinates__intersects_geometry=polygon)
in_bbox
Returns the features that are within a bounding box.
Example:
from shapely.geometry import Polygon
polygon = Polygon([
[109300.0, 518201.2], [108926.5, 518201.2], [108935.6, 517871.7], [109300.0, 518201.2]
])
gr.lines.filter(
line_coords__in_bbox=polygon.bounds
)
in_tile
Example:
ga.nodes.filter(coordinates__in_tile=[0, 0, 0])
intersects_bbox
Returns the features that intersect a bounding box.
Example:
from shapely.geometry import Polygon
polygon = Polygon([
[109300.0, 518201.2], [108926.5, 518201.2], [108935.6, 517871.7], [109300.0, 518201.2]
])
gr.lines.filter(
line_coords__intersects_bbox=polygon.bounds
)
intersects_geometry
Returns the features that intersect the input geometry. It expects a shapely geometry:
from shapely.geometry import Polygon
polygon = Polygon([
[109300.0, 518201.2], [108926.5, 518201.2], [108935.6, 517871.7], [109300.0, 518201.2]
])
ga.cells.filter(cell_coords__intersects_geometry=polygon)
To improve performance, it is recommended to always combine intersects_geometry with intersects_bbox, like this:
gr.lines.filter(
line_coords__intersects_bbox=polygon.bounds
).filter(
line_coords__intersects_geometry=polygon
)
intersects_tile
Example:
ga.nodes.filter(coordinates__intersects_tile=[0, 0, 0])
Non-spatial filters
Non-geometry fields can also be filtered on. For example, to select the nodes with type “2D Boundary” (i.e. node_type = 5), you can use this filter:
ga.nodes.filter(node_type__eq=5)
or both “2D Boundary” and “2D Open water” nodes:
ga.nodes.filter(node_type__in=[5, 6])
The following non-spatial filters are available:
eq: Equals
ne: Not equals
gt: Greater than
gte: Greater than equals
lt: Less than
lte: Less than equals
in: In collection
You combine them with the field name by adding a double underscore __ in between, e.g. crest_level must be greater than 4.33: crest_level__gt=4.33.
Subsets
Subsets are an easy way to retrieve categorized sub parts of the data.
Nodes and Lines have predefined subsets. To those, can call the known_subset property:
ga.lines.known_subset
>>> [u'ACTIVE_BREACH',
>>> u'2D_OPEN_WATER',
>>> u'1D',
>>> u'SHORT_CRESTED_STRUCTURES',
>>> u'2D_GROUNDWATER',
>>> u'LONG_CRESTED_STRUCTURES',
>>> u'1D2D',
>>> u'2D_VERTICAL_INFILTRATION',
>>> u'1D_ALL',
>>> u'2D_ALL',
>>> u'2D_OPEN_WATER_OBSTACLES',
>>> u'GROUNDWATER_ALL']
To retrieve data of a subset use the subset() method like this:
ga.lines.subset('1D_ALL').data # remember, all filtering is lazy
The definitions of the known subsets can be found here:
Nodes: threedigrid/admin/nodes/subsets.py
Lines: threedigrid/admin/lines/subsets.py
You can also define your own subsets.
Selecting attributes using only
If you only need a few attributes, you can use only().
Example:
ga.nodes.only('id', 'coordinates').data
Exporters
Exporters allow you to export model data to files. For example exporting all 2D open water lines to a Shapefile with EPSG code 4326 (WGS84):
from threedigrid.admin.lines.exporters import LinesOgrExporter
line_2d_open_water_wgs84 = ga.lines.subset('2D_OPEN_WATER').reproject_to('4326')
exporter = LinesOgrExporter(line_2d_open_water_wgs84)
exporter.save('/tmp/line.shp', line_2d_open_water_wgs84.data, '4326')
Supported extenstions are:
.shp (Shapefile)
.gpkg (GeoPackage)
.json (GeoJSON)
.geojson (GeoJSON)
Most models have shortcut methods for exporting their data for shapefiles and geopackages, like:
# Shapefile
ga.lines.subset('2D_OPEN_WATER').reproject_to('4326').to_shape('/tmp/line.shp')
# Geopackage
ga.lines.subset('2D_OPEN_WATER').reproject_to('4326').to_gpkg('/tmp/line.gpkg')
Command line interfaces
3digrid_explore
Using the 3digrid_explore shortcut, simply run:
$ 3digrid_explore --grid-file=<path to grid file> --ipy
This will invoke an ipython session with a GridH5Admin instance already loaded.
To get a quick overview of the threedimodels meta data omit the --ipy option or
explicitly run:
$ 3digrid_explore --grid-file=<the to grid file> --no-ipy
This will give you output like this:
Overview of model specifics:
model slug: v2_bergermeer-v2_bergermeer_bres_maalstop-58-b1f8179f1f3c2333adb08c9e6933fa7b9a8cd163
threedicore version: 0-20180315-3578e9b-1
threedi version: 1.63.dev0
has 1d: True
has 2d: True
has groundwater: True
has levees: True
has breaches: True
has pumpstations: True
3digrid_export
To quickly export data of a model (or a models subset) you can use the 3digrid_export shortcut. To get an overview of the options run:
$ 3digrid_export --help
Usage: 3digrid_export [OPTIONS]
Options:
--grid-file PATH Path to the admin file
--file-type [shape|gpkg]
--output-file PATH Path to the output file
--model [nodes|lines|breaches|levees]
--subset TEXT Filter by a subset like 1D_all (applies only
for models nodes and lines
--help Show this message and exit.
So to export the all 1D nodes:
$ 3digrid_export --grid-file=<path to grid file> --file-type=shape --output-file=<name>.shp --model=nodes --subset=1d_all
Remote procedure calls
Note
This is an advanced feature used inside the 3Di stack, probably you do not need this.
Currently only the client-side is included. The server-side might be added in a later stage.
Installation:
$ pip install threedigrid[rpc]
Basic usage:
ga = GridH5ResultAdmin('rpc://REDIS_HOST/SIMULATION_ID', 'rpc://REDIS_HOST/SIMULATION_ID')
# Replace REDIS_HOST and SIMULATION_ID with actual values.
future_result = ga.nodes.filter(lik__eq=4).data
data = await future_result.resolve()
Subscription usage:
subscription = await future_result.subscribe()
async for item in subscription.enumerate():
# do something with item