Skip to main content

dggrid4py - a Python library to run highlevel functions of DGGRID

PyPI version DOI Documentation Status GitHub

Population Gridded

GNU AFFERO GENERAL PUBLIC LICENSE

DGGRID is a free software program for creating and manipulating Discrete Global Grids created and maintained by Kevin Sahr. DGGRID version 9.1 was released 23. October 2026 (version 8.44 on 2. April 2026).

dggrid4py runs the dggrid command line tool, which has to be available on the system.

The easiest way to get started is a pixi environment. DGGRID (with GDAL) and the geospatial stack come from conda-forge, dggrid4py (and pygeodesy) from PyPI:

pixi init my-dggs-project -c conda-forge
cd my-dggs-project
pixi add python=3.12 dggrid geopandas pyogrio
pixi add --pypi dggrid4py
pixi run dggrid   # prints "usage: dggrid metaFileName"

Inside the environment, dggrid is on the PATH:

import shutil, tempfile
from dggrid4py import DGGRIDv8

dggrid_instance = DGGRIDv8(executable=shutil.which("dggrid"), working_dir=tempfile.mkdtemp(), capture_logs=False, silent=True)

Basic usage

Besides some low-level access to influence the metafile creation of the DGGRID operations, a few high-level functions are integrated to work with the more comfortable geopython libraries, like shapely and geopandas:

  • grid_cell_polygons_for_extent(): fill extent/subset with cells at resolution (clip or world);
  • grid_cell_centroids_for_extent(): the same for the cell centroids;
  • grid_cell_polygons_from_cellids(): geometry_from_cellid for dggs at resolution (from id list);
  • grid_cellids_for_extent(): get_all_indexes/cell_ids for dggs at resolution (clip or world);
  • cells_for_geo_points(): poly_outline for point/centre at resolution;
  • address_transform(): conversion between cell_id address types, like SEQNUM, Q2DI or the hierarchical indexes;
  • grid_stats_table(): number of cells, cell area and spacing per resolution.

Use the DGGRIDv8 class with DGGRID 8.42 or newer, including DGGRID 9.1. IGEO7 with DGGRID 9.1, the current version on conda-forge, needs dggrid4py 0.6.1 or newer: dggrid4py 0.6.0 returns wrong cell identifiers there without an error, see IGEO7 in DGGRID 9.1. The DGGRIDv7 class for DGGRID 7 is deprecated since version 0.6.0 and will be removed in a future version.

import shutil
import tempfile

import geopandas
import shapely

from dggrid4py import DGGRIDv8

# create an initial instance that knows where the dggrid tool lives, configure temp workspace and log/stdout output
dggrid_instance = DGGRIDv8(executable=shutil.which("dggrid"), working_dir=tempfile.mkdtemp(), capture_logs=False, silent=True)

# global ISEA4T grid at resolution 5 into GeoDataFrame to Shapefile
gdf1 = dggrid_instance.grid_cell_polygons_for_extent('ISEA4T', 5)
print(gdf1.head())
gdf1.to_file('isea4t_5.shp')

# cell centroids of the global ISEA7H grid at resolution 4
gdf_centroids = dggrid_instance.grid_cell_centroids_for_extent(dggs_type='ISEA7H', resolution=4, mixed_aperture_level=None, clip_geom=None)
print(gdf_centroids.head())

# clip extent
clip_bound = shapely.geometry.box(20.2, 57.00, 28.4, 60.0)

# ISEA7H grid at resolution 9, for extent of provided WGS84 rectangle into GeoDataFrame to Shapefile
gdf3 = dggrid_instance.grid_cell_polygons_for_extent('ISEA7H', 9, clip_geom=clip_bound)
print(gdf3.head())
gdf3.to_file('est_shape_isea7h_9.shp')

# generate cell and areal statistics for a ISEA7H grids from resolution 0 to 8 (return a pandas DataFrame)
df1 = dggrid_instance.grid_stats_table('ISEA7H', 8)
print(df1.head(8))
df1.to_csv('isea7h_8_stats.csv', index=False)

# generate the DGGS grid cells that would cover a GeoDataFrame of points, return Polygons with cell IDs as GeoDataFrame
points = [shapely.Point(20.5, 57.5), shapely.Point(23.5, 58.5)]
geodf_points_wgs84 = geopandas.GeoDataFrame({'site': ['A', 'B']}, geometry=points, crs='EPSG:4326')
gdf4 = dggrid_instance.cells_for_geo_points(geodf_points_wgs84, False, 'ISEA7H', 5)
print(gdf4.head())
gdf4.to_file('polycells_from_points_isea7h_5.shp')

# generate the DGGS grid cells that would cover a GeoDataFrame of points, return a copy of the points with the cell IDs in the column 'name'
gdf5 = dggrid_instance.cells_for_geo_points(geodf_points_wgs84=geodf_points_wgs84, cell_ids_only=True, dggs_type='ISEA4H', resolution=8)
print(gdf5.head())
gdf5.to_file('geopoint_cellids_from_points_isea4h_8.shp')

# generate DGGS grid cell polygons based on 'cell_id_list' (a list or np.array of provided cell_ids)
gdf6 = dggrid_instance.grid_cell_polygons_from_cellids(cell_id_list=[1, 4, 8], dggs_type='ISEA7H', resolution=5)
print(gdf6.head())
gdf6.to_file('from_seqnums_isea7h_5.shp')

# split cells at the dateline for cartesian GIS tools
gdf7 = dggrid_instance.grid_cell_polygons_for_extent('ISEA7H', 3, split_dateline=True)
gdf7.to_file('global_isea7h_3_interrupted.shp')

# convert cell IDs between address types, here from sequence numbers to Q2DI (quad number and i, j coordinates)
df_q2di = dggrid_instance.address_transform([1, 4, 8], 'ISEA7H', 5, input_address_type='SEQNUM', output_address_type='Q2DI')
print(df_q2di.head(3))

# cells at resolution 6 that intersect a coarser cell at resolution 5 (a spatial clip, it includes overlapping neighbours)
gdf8 = dggrid_instance.grid_cell_polygons_from_cellids([100], 'ISEA7H', 6, clip_subset_type='COARSE_CELLS', clip_cell_res=5)
print(len(gdf8))

All functions that return geometries return a GeoDataFrame with the cell identifier in the column name and with EPSG:4326 as coordinate reference system. An input or output address type that the DGGRID class does not know raises a ValueError.

IGEO7 and the Z7 index

IGEO7 is the ISEA7H grid with the Z7 hierarchical index. The IGEO7 used in dggrid4py is defined with dggs_vert0_lon = 11.20 (the DGGRID default is 11.25) and on the WGS84 ellipsoid, which requires a conversion to authalic latitudes around each DGGRID call. The wrappers in dggrid4py.igeo7_ext apply both, so that WGS84 data goes in and WGS84 data comes out:

from dggrid4py import igeo7_ext

# Tartu bbox in wgs84, IGEO7 cell polygons at resolution 9 with Z7 cell ids in the column 'name'
extent = shapely.box(26.664593, 58.348705, 26.785607, 58.422495)
cells = igeo7_ext.dggrid_igeo7_grid_cell_polygons_for_extent(extent, 9, dggrid_instance)

# Z7 cell ids for wgs84 points
sites = geopandas.GeoDataFrame({'site': ['Lisbon', 'Tartu']}, geometry=geopandas.points_from_xy([-9.1393, 26.7220], [38.7223, 58.3776]), crs=4326)
sites = igeo7_ext.dggrid_igeo7_cells_for_geo_points(sites, 9, dggrid_instance)
print(sites['name'].tolist())   # ['00641565463', '00010224545']

The former address type Z7_STRING of the DGGRIDv7 class is deprecated in DGGRID 8.44 and removed in DGGRID 9. The DGGRIDv8 class still accepts it with a DeprecationWarning. The IGEO7 docs describe the background on orientation and ellipsoid, the explicit configuration and the migration.

Portable DGGRID binary

Warning: the precompiled portable DGGRID binaries are still experimental and are built without GDAL support. For a reliable setup, use the pixi or conda-forge installation above.

If DGGRID can neither be installed from conda-forge nor compiled, dggrid4py can download a portable binary from the DGGRID_portables releases (Linux, macOS and Windows, x86_64 and arm64 each):

import tempfile

from dggrid4py import DGGRIDv8, tool

# downloads and unpacks the binary for the current platform into the given folder (only once)
dggrid_exec = tool.get_portable_executable("dggrid_portable")
dggrid_instance_portable = DGGRIDv8(executable=dggrid_exec, working_dir=tempfile.mkdtemp(), capture_logs=False, silent=True, has_gdal=False)

# other lines: "edge" follows the DGGRID development version, or any release tag of DGGRID_portables
dggrid_exec_edge = tool.get_portable_executable("dggrid_portable", line="edge")

The default line stable is the DGGRID release that this version of dggrid4py is tested with (currently DGGRID 8.44). The archive is verified against the SHA256 checksums of the release. The binaries are built without GDAL, thus the instance has to be created with has_gdal=False, and they should be used with the DGGRIDv8 class.

TODO:

  • get parent_for_cell_id at coarser resolution
  • get children_for_cell_id at finer resolution

Remark: with the IGEO7/Z7 index system, the parent of a cell can be derived from the cell identifier. A function that enumerates the index children is still missing.

Originally inspired by dggridR, Richard Barnes’ R interface to DGGRID. However, dggridR is directly linked via Rcpp to DGGRID and calls native C/C++ functions.

After some unsuccessful trials with ctypes, cython, CFFI, pybind11 or cppyy (rather due to lack of experience) I found am2222/pydggrid (on PyPI) which made apparently some initial scaffolding for the transform operation with pybind11 including some sophisticated conda packaging for Windows. This might be worth following up. Interestingly, its todos include "Adding GDAL export Geometry Support" and "Support GridGeneration using DGGRID" which this dggrid4py module supports with integration of GeoPandas.

Bundling for different operating systems

Having to compile DGGRID for Windows can be a bit challenging. We are working on an updated conda package. DGGRID (currently v9.1) is available on conda-forge, which is what the pixi quickstart above uses:

Latest version on conda-forge

greater context DGGS in Earth Sciences and GIS

Some reading to be excited about: discourse.pangeo.io

Metadata

Release files for dggrid4py 0.6.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dggrid4py 0.6.2
File Size Uploaded Provenance Actions
dggrid4py-0.6.2.tar.gz 51.2 kB Without provenance Details for dggrid4py-0.6.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for dggrid4py 0.6.2
File Interpreter ABI Platform Actions
dggrid4py-0.6.2-py3-none-any.whl Python 3 none any Details for dggrid4py-0.6.2-py3-none-any.whl

Total release size: 101.5 kB

Release files / dggrid4py-0.6.2.tar.gz

Download URL dggrid4py-0.6.2.tar.gz
Size 51.2 kB
Tags Source
SHA-256 checksum
How to use checksums
3c84e75254f82a015839a2c1ec48585e6648e54785597f0c699273f0dfdc47aa
BLAKE2b-256 checksum
How to use checksums
97cd104b482716058f4c7c98cd8a68565be52efe3ef22d2c08b1fd109733069f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.25

Release files / dggrid4py-0.6.2-py3-none-any.whl

Download URL dggrid4py-0.6.2-py3-none-any.whl
Size 50.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
54f4772efdf845300e0ac30986a2b4a1e403c4316e33d0a411c59ad81a36a545
BLAKE2b-256 checksum
How to use checksums
7c1801b0617d041c5860bdf7fd8886e70328afd203f6a16827c17b4b438ef442
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.25

Security for dggrid4py 0.6.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page