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