Tiling system#

The core class in the Equi7Grid is the Equi7TilingSystem and represents an Equi7Grid continental subgrid as a regular, multi-level (e.g., zoom, tiling level, …) projected tiling system. A projected tiling system is defined as follows:

  • A projection represented via a CRS definition (EPSG, PROJ4, WKT, …) and a projection zone defining the validity of coordinates.

  • A regular tiling scheme slicing the projection extent into smaller regular tiles with a given tile and pixel size (= sampling); tiling schemes are stacked in a tiling system to form a hierarchy of tiling levels (generic realisation of OGC’s Tile Matrix Set). Equi7Grid’s standard tiling system consists of three tiling levels: T1 (100km tile size), T3 (300km tile size), and T6 (600km tile size).

On a code-level, Equi7TilingSystem inherits from pytileproj’s RegularProjTilingSystem and extends it with a definition of land masses for each continent to decide if a tile is covering land or not.

Lets dive deeper into how an Equi7TilingSystem instance can be used. As an example, we assume we retrieved the instance for the European Equi7Grid tiling system (“EU”).

e7eu = ...
print(e7eu)  # noqa: T201
Equi7TilingSystem 
-----------------
Name: 
EU
Projection: 
+proj=aeqd +lat_0=53 +lon_0=24 +x_0=5837287.82 +y_0=2121415.696 +datum=WGS84 +units=m +no_defs +type=crs
Tilings: 
{0: RegularTiling(T6, 500.0), 1: RegularTiling(T3, 500.0)}

Projection system interactions#

Often it is required to transform coordinates back and forth between different projection systems. Equi7TilingSystem provides several methods to do this in a straighforward way. If you want transform geographic coordinates to projected coordinates, you can use lonlat_to_xy:

lon, lat = 16.3926, 48.1674
proj_coord = e7eu.lonlat_to_xy(lon, lat)
proj_coord
ProjCoord(5271748.127753316, 1613228.4676009014)

The same can be done the other way around:

e7eu.xy_to_lonlat(proj_coord.x, proj_coord.y)
GeogCoord(16.392599999999998, 48.1674)

Note that for coordinates outside the (continental) projection zone, an error will be raised:

lon, lat = -100, 30
e7eu.lonlat_to_xy(lon, lat)
---------------------------------------------------------------------------
GeomOutOfZoneError                        Traceback (most recent call last)
Cell In[6], line 2
      1 lon, lat = -100, 30
----> 2 e7eu.lonlat_to_xy(lon, lat)

File ~/work/Equi7Grid/Equi7Grid/.venv/lib/python3.12/site-packages/pytileproj/tiling_system.py:206, in ProjSystem.lonlat_to_xy(self, lon, lat)
    204     coord = ProjCoord(x, y, self._crs)
    205 else:
--> 206     raise GeomOutOfZoneError(shapely.Point((lon, lat)))
    208 return coord

GeomOutOfZoneError: The given Point ('POINT (-100 30)') is not within the zone boundaries of the projection.

You can check in advance if a point or geometry is within the projection by using Python’s in operator:

from pytileproj import GeogCoord

coord = GeogCoord(lon, lat)
coord in e7eu  # ty: ignore[unsupported-operator]
False

As you have seen in this example pytileproj offers several classes to store geometries along with projection information: ProjCoord and ProjGeom as the core classes and GeogCoord and GeogGeom to represent geographic geometries (more details can be found here).

If you want to know the units of the projection system, you can retrieve this information via:

e7eu.unit
'metre'

Tiles#

Equi7 tiling systems create tile objects on the fly, since their regular tiling scheme allows an efficient computation of tile properties. A tile can be created by providing a location of interest with the following methods: get_tile_from_lonlat, get_tile_from_xy, and get_tile_from_coord. Here is an example:

lon, lat = 16.3926, 48.1674
e7eu.get_tile_from_lonlat(lon, lat, tiling_id="T6")
EU_E048N012T6

If you are interested in retrieving a list of tiles intersecting with a region of interest in geographic coordinates, you can use get_tiles_in_geog_bbox. It returns a generator to enable lazy tile retrieval.

list(e7eu.get_tiles_in_geog_bbox((16, 48, 18, 50), tiling_id="T6"))
[EU_E048N012T6, EU_E048N018T6, EU_E054N012T6, EU_E054N018T6]

Important

For a geographical bounding box the order of longitude coordinates is important. As an example: (-170, 20, 150, 30) is a large bounding box going from -170° west to 150° east and (150, 20, -170, 30) is a small bounding box crossing the antimeridian.

Similar queries can be done with projected/native coordinates

list(e7eu.get_tiles_in_bbox((5155982, 1505898, 6323863, 2140396), tiling_id="T6"))
[EU_E048N012T6,
 EU_E048N018T6,
 EU_E054N012T6,
 EU_E054N018T6,
 EU_E060N012T6,
 EU_E060N018T6]

or by using a geometry object.

from pytileproj import GeogGeom
from shapely import Polygon

geom = Polygon([(16, 48), (18, 48), (18, 50), (16, 50)])
ggeom = GeogGeom(geom=geom)
list(e7eu.get_tiles_in_geom(ggeom, tiling_id="T3"))
[EU_E051N015T3, EU_E051N018T3, EU_E054N015T3, EU_E054N018T3]

Since tiling systems represent an hierarchy of different tilings, Equi7TilingSystem also allows to trace parent and children tiles. You can obtain the parent of a tile with

e7eu.get_parent_from_name("EU_E048N012T3")
EU_E048N012T6

and the children with

list(e7eu.get_children_from_name("EU_E054N012T6"))
[EU_E054N012T3, EU_E054N015T3, EU_E057N012T3, EU_E057N015T3]

Export#

Note

The export methods requires additional dependencies, which are not installed by default. You can install them via uv pip install equi7grid[export].

A tiling system offers several export methods, e.g., an export to a GeoDataFrame (to_geodataframe) or a shapefile (to_shapefile). Here is an example how to generate a GeoDataFrame:

e7eu.to_geodataframe()
crs n_rows n_cols geotrans px_origin name covers_land tiling_name tiling_level geometry
0 EPSG:27704 1200 1200 (0.0, 500.0, 0.0, 3000000.0, 0.0, -500.0) ll EU_E000N024T6 False T6 0 POLYGON ((0 2400000, 600000 2400000, 600000 30...
1 EPSG:27704 1200 1200 (0.0, 500.0, 0.0, 2400000.0, 0.0, -500.0) ll EU_E000N018T6 False T6 0 POLYGON ((0 1800000, 600000 1800000, 600000 24...
2 EPSG:27704 1200 1200 (0.0, 500.0, 0.0, 1800000.0, 0.0, -500.0) ll EU_E000N012T6 False T6 0 POLYGON ((0 1200000, 600000 1200000, 600000 18...
3 EPSG:27704 1200 1200 (600000.0, 500.0, 0.0, 3600000.0, 0.0, -500.0) ll EU_E006N030T6 False T6 0 POLYGON ((600000 3000000, 1200000 3000000, 120...
4 EPSG:27704 1200 1200 (600000.0, 500.0, 0.0, 3000000.0, 0.0, -500.0) ll EU_E006N024T6 False T6 0 POLYGON ((600000 2400000, 1200000 2400000, 120...
... ... ... ... ... ... ... ... ... ... ...
434 EPSG:27704 600 600 (7800000.0, 500.0, 0.0, 1200000.0, 0.0, -500.0) ll EU_E078N009T3 True T3 1 POLYGON ((7800000 900000, 8100000 900000, 8100...
435 EPSG:27704 600 600 (7800000.0, 500.0, 0.0, 900000.0, 0.0, -500.0) ll EU_E078N006T3 True T3 1 POLYGON ((7800000 600000, 8100000 600000, 8100...
436 EPSG:27704 600 600 (8100000.0, 500.0, 0.0, 1500000.0, 0.0, -500.0) ll EU_E081N012T3 False T3 1 POLYGON ((8100000 1200000, 8400000 1200000, 84...
437 EPSG:27704 600 600 (8100000.0, 500.0, 0.0, 1200000.0, 0.0, -500.0) ll EU_E081N009T3 False T3 1 POLYGON ((8100000 900000, 8400000 900000, 8400...
438 EPSG:27704 600 600 (8100000.0, 500.0, 0.0, 900000.0, 0.0, -500.0) ll EU_E081N006T3 False T3 1 POLYGON ((8100000 600000, 8400000 600000, 8400...

439 rows × 10 columns

If you want to share an OGC compliant definition of the tiling system, you can use to_ogc_standard or to_ogc_json:

import json
import pprint
from pathlib import Path

ogc_ts_path = Path("my_equi7_system.json")
e7eu.to_ogc_json(ogc_ts_path)

with ogc_ts_path.open() as f:
    ogc_ts = json.load(f)

pprint.pprint(ogc_ts)  # noqa: T203
{'boundingBox': None,
 'crs': {'wkt': {'$schema': 'https://proj.org/schemas/v0.7/projjson.schema.json',
                 'area': 'Europe including Russia west of the Ural Mountains.',
                 'base_crs': {'coordinate_system': {'axis': [{'abbreviation': 'Lat',
                                                              'direction': 'north',
                                                              'name': 'Geodetic '
                                                                      'latitude',
                                                              'unit': 'degree'},
                                                             {'abbreviation': 'Lon',
                                                              'direction': 'east',
                                                              'name': 'Geodetic '
                                                                      'longitude',
                                                              'unit': 'degree'}],
                                                    'subtype': 'ellipsoidal'},
                              'datum_ensemble': {'accuracy': '2.0',
                                                 'ellipsoid': {'inverse_flattening': 298.257223563,
                                                               'name': 'WGS 84',
                                                               'semi_major_axis': 6378137},
                                                 'id': {'authority': 'EPSG',
                                                        'code': 6326},
                                                 'members': [{'id': {'authority': 'EPSG',
                                                                     'code': 1166},
                                                              'name': 'World '
                                                                      'Geodetic '
                                                                      'System '
                                                                      '1984 '
                                                                      '(Transit)'},
                                                             {'id': {'authority': 'EPSG',
                                                                     'code': 1152},
                                                              'name': 'World '
                                                                      'Geodetic '
                                                                      'System '
                                                                      '1984 '
                                                                      '(G730)'},
                                                             {'id': {'authority': 'EPSG',
                                                                     'code': 1153},
                                                              'name': 'World '
                                                                      'Geodetic '
                                                                      'System '
                                                                      '1984 '
                                                                      '(G873)'},
                                                             {'id': {'authority': 'EPSG',
                                                                     'code': 1154},
                                                              'name': 'World '
                                                                      'Geodetic '
                                                                      'System '
                                                                      '1984 '
                                                                      '(G1150)'},
                                                             {'id': {'authority': 'EPSG',
                                                                     'code': 1155},
                                                              'name': 'World '
                                                                      'Geodetic '
                                                                      'System '
                                                                      '1984 '
                                                                      '(G1674)'},
                                                             {'id': {'authority': 'EPSG',
                                                                     'code': 1156},
                                                              'name': 'World '
                                                                      'Geodetic '
                                                                      'System '
                                                                      '1984 '
                                                                      '(G1762)'},
                                                             {'id': {'authority': 'EPSG',
                                                                     'code': 1309},
                                                              'name': 'World '
                                                                      'Geodetic '
                                                                      'System '
                                                                      '1984 '
                                                                      '(G2139)'},
                                                             {'id': {'authority': 'EPSG',
                                                                     'code': 1383},
                                                              'name': 'World '
                                                                      'Geodetic '
                                                                      'System '
                                                                      '1984 '
                                                                      '(G2296)'}],
                                                 'name': 'World Geodetic '
                                                         'System 1984 '
                                                         'ensemble'},
                              'id': {'authority': 'EPSG', 'code': 4326},
                              'name': 'WGS 84'},
                 'bbox': {'east_longitude': 51.73,
                          'north_latitude': 83.67,
                          'south_latitude': 29.24,
                          'west_longitude': -42.52},
                 'conversion': {'method': {'id': {'authority': 'EPSG',
                                                  'code': 1125},
                                           'name': 'Azimuthal Equidistant'},
                                'name': 'Equi7 projection - Europe',
                                'parameters': [{'id': {'authority': 'EPSG',
                                                       'code': 8801},
                                                'name': 'Latitude of natural '
                                                        'origin',
                                                'unit': 'degree',
                                                'value': 53},
                                               {'id': {'authority': 'EPSG',
                                                       'code': 8802},
                                                'name': 'Longitude of natural '
                                                        'origin',
                                                'unit': 'degree',
                                                'value': 24},
                                               {'id': {'authority': 'EPSG',
                                                       'code': 8806},
                                                'name': 'False easting',
                                                'unit': 'metre',
                                                'value': 5837287.82},
                                               {'id': {'authority': 'EPSG',
                                                       'code': 8807},
                                                'name': 'False northing',
                                                'unit': 'metre',
                                                'value': 2121415.696}]},
                 'coordinate_system': {'axis': [{'abbreviation': 'E',
                                                 'direction': 'east',
                                                 'name': 'Easting',
                                                 'unit': 'metre'},
                                                {'abbreviation': 'N',
                                                 'direction': 'north',
                                                 'name': 'Northing',
                                                 'unit': 'metre'}],
                                       'subtype': 'Cartesian'},
                 'id': {'authority': 'EPSG', 'code': 27704},
                 'name': 'WGS 84 / Equi7 Europe',
                 'scope': 'Continental mapping of raster data.',
                 'type': 'ProjectedCRS'}},
 'description': None,
 'id': None,
 'keywords': None,
 'orderedAxes': None,
 'tileMatrices': [{'cellSize': 500.0,
                   'cornerOfOrigin': 'topLeft',
                   'description': None,
                   'id': '0',
                   'keywords': None,
                   'matrixHeight': 11,
                   'matrixWidth': 14,
                   'pointOfOrigin': [0.0, 6000000.0],
                   'scaleDenominator': 1785714.285714286,
                   'tileHeight': 1200,
                   'tileWidth': 1200,
                   'title': 'T6',
                   'variableMatrixWidths': None},
                  {'cellSize': 500.0,
                   'cornerOfOrigin': 'topLeft',
                   'description': None,
                   'id': '1',
                   'keywords': None,
                   'matrixHeight': 21,
                   'matrixWidth': 28,
                   'pointOfOrigin': [0.0, 5700000.0],
                   'scaleDenominator': 1785714.285714286,
                   'tileHeight': 600,
                   'tileWidth': 600,
                   'title': 'T3',
                   'variableMatrixWidths': None}],
 'title': None,
 'uri': None,
 'wellKnownScaleSet': None}

Visualisation#

A Equi7 tiling systems can be also visualised on a map in a similar manner as a Equi7Tile object, if the optional dependencies matplotlib and cartopy are installed.

import matplotlib.pyplot as plt

plt.figure(figsize=(20, 28))
_ = e7eu.plot(
    tiling_id="T3",
    label_tile=True,
    label_size=5,
    plot_zone=True,
    facecolor="#2cee768f",
    alpha=0.6,
    extent=[-6e5, -6e5, 9e6, 6e6],
)
../_images/334fe84af96cb9747166eebce760c50d94bd2f434e36a80d16a978426ac89088.png