map_utils
OpenStreetMap data utilities used to download, process, rotate, and persist geospatial layers for the NOMAD library.
- nomad.map_utils.blocks_to_mercator(data, block_size=15.0, false_easting=-4265699.0, false_northing=4392976.0, rotation_deg=0.0, rotation_origin=None)[source]
Convert city block coordinates to Web Mercator coordinates.
This function applies an affine transformation to convert abstract city block coordinates (in units of blocks) to Web Mercator projection coordinates (EPSG:3857) in meters. The transformation is: x_mercator = block_size * x_block + false_easting
- Parameters:
data (pd.DataFrame) – DataFrame with ‘x’, ‘y’ columns in city block coordinates
block_size (float, default 15.0) – Size of one city block in meters
false_easting (float, default -4265699.0) – False easting offset (x-origin) in Web Mercator meters
false_northing (float, default 4392976.0) – False northing offset (y-origin) in Web Mercator meters
rotation_deg (float, default 0.0) – Rotation to undo (degrees counterclockwise). If non-zero, rotates by -rotation_deg around rotation_origin after scaling and translation.
rotation_origin (tuple of (x, y), optional) – Rotation origin in Web Mercator coordinates. If None and rotation_deg != 0, uses (false_easting, false_northing) as origin.
- Returns:
DataFrame with ‘x’, ‘y’ columns updated to Web Mercator coordinates. If ‘ha’ column exists, it is also scaled by block_size.
- Return type:
pd.DataFrame
Examples
>>> import pandas as pd >>> df = pd.DataFrame({'x': [0, 1, 2], 'y': [0, 1, 2]}) >>> result = blocks_to_mercator(df, block_size=15, false_easting=-4265699, false_northing=4392976) >>> result['x'].tolist() [-4265699.0, -4265684.0, -4265669.0]
- nomad.map_utils.blocks_to_mercator_gdf(gdf, block_size, false_easting, false_northing, rotation_deg=0.0, drop_garden_cols=True)[source]
Transform GeoDataFrame from garden city block units to Web Mercator meters.
- Parameters:
gdf (gpd.GeoDataFrame) – Input with geometries in garden city block units
block_size (float) – Block side length in meters
false_easting (float) – Web Mercator origin x in meters
false_northing (float) – Web Mercator origin y in meters
rotation_deg (float, default 0.0) – Rotation applied to input (will be undone by rotating -rotation_deg)
drop_garden_cols (bool, default True) – If True, drop coord_x, coord_y, door_cell_x, door_cell_y columns
- Returns:
Transformed GeoDataFrame with CRS=’EPSG:3857’
- Return type:
gpd.GeoDataFrame
Notes
Transformation sequence: 1. Scale geometries by block_size (blocks → meters) 2. Translate by false_easting, false_northing (move to Web Mercator position) 3. Rotate by -rotation_deg (undo rotation around centroid) 4. Set CRS to EPSG:3857 5. Optionally drop garden city columns
This is the GeoDataFrame equivalent of blocks_to_mercator() for DataFrames.
- nomad.map_utils.download_osm_buildings(bbox_or_city, crs='EPSG:4326', schema='garden_city', clip=False, infer_building_types=False, explode=False)[source]
Download buildings + parks from OSM and categorize them.
Parameters - bbox_or_city: bbox tuple, city name, or shapely polygon - crs: output CRS - schema: category schema name - clip: retained for API parity (bbox path uses Overpass bbox) - infer_building_types: heuristics for building=”yes” - explode: explode MultiPolygons into Polygons
- nomad.map_utils.download_osm_streets(bbox_or_city, crs='EPSG:4326', clip=True, clip_to_gdf=None, explode=False, graphml_path=None)[source]
Download filtered street network from OSM and return edges as GeoDataFrame.
- nomad.map_utils.get_category_for_subtype(subtype, schema='garden_city')[source]
Return the category name for a subtype in the given schema.
If the subtype is not present, returns ‘unknown’ for ‘geolife_plus’ or ‘other’ for all other schemas.
- nomad.map_utils.get_city_boundary_osm(name, simplify=True, crs='EPSG:4326')[source]
Fetch a city’s boundary from OSM.
Returns a tuple of (boundary_multipolygon, center_coordinates, population). If a boundary cannot be retrieved, returns (None, None, None).
- nomad.map_utils.load_geodata(path: str, layer: str = None) GeoDataFrame[source]
Load a GeoDataFrame from disk based on file extension.
Supports .geojson/.json, .parquet/.geoparquet, .shp, .gpkg
- nomad.map_utils.mercator_to_blocks(data, block_size=15.0, false_easting=-4265699.0, false_northing=4392976.0)[source]
Convert Web Mercator coordinates back to city block coordinates.
This function applies the inverse affine transformation to convert Web Mercator projection coordinates (EPSG:3857) in meters back to abstract city block coordinates. The transformation is: x_block = (x_mercator - false_easting) / block_size
- Parameters:
data (pd.DataFrame) – DataFrame with ‘x’, ‘y’ columns in Web Mercator coordinates
block_size (float, default 15.0) – Size of one city block in meters
false_easting (float, default -4265699.0) – False easting offset (x-origin) in Web Mercator meters
false_northing (float, default 4392976.0) – False northing offset (y-origin) in Web Mercator meters
- Returns:
DataFrame with ‘x’, ‘y’ columns updated to city block coordinates. If ‘ha’ column exists, it is also scaled back by dividing by block_size.
- Return type:
pd.DataFrame
Examples
>>> import pandas as pd >>> df = pd.DataFrame({'x': [-4265699.0, -4265684.0], 'y': [4392976.0, 4392991.0]}) >>> result = mercator_to_blocks(df, block_size=15, false_easting=-4265699, false_northing=4392976) >>> result['x'].tolist() [0.0, 1.0]
- nomad.map_utils.mercator_to_blocks_gdf(gdf, block_size, false_easting, false_northing, rotation_deg=0.0)[source]
Transform GeoDataFrame from Web Mercator meters to garden city block units.
- Parameters:
gdf (gpd.GeoDataFrame) – Input with geometries in Web Mercator (EPSG:3857)
block_size (float) – Block side length in meters
false_easting (float) – Web Mercator origin x in meters
false_northing (float) – Web Mercator origin y in meters
rotation_deg (float, default 0.0) – Rotation to apply (degrees counterclockwise)
- Returns:
Transformed GeoDataFrame with CRS=None (garden city units)
- Return type:
gpd.GeoDataFrame
Notes
Transformation sequence (inverse of blocks_to_mercator_gdf): 1. Rotate by rotation_deg around centroid 2. Translate by -false_easting, -false_northing (move from Web Mercator position) 3. Scale geometries by 1/block_size (meters → blocks) 4. Set CRS to None (abstract units)
This is the GeoDataFrame equivalent of mercator_to_blocks() for DataFrames.
- nomad.map_utils.remove_overlaps(gdf, exclude_categories=None)[source]
Remove polygons fully contained within others, keeping one of any identical shapes.
If exclude_categories is provided and a ‘category’ column exists, rows in those categories are not considered for removal. Uses spatial indexing for efficiency.
- nomad.map_utils.rotate(gdf, rotation_deg=0.0, origin='centroid')[source]
Rotate all geometries around a single origin.
Parameters - gdf: input GeoDataFrame - rotation_deg: degrees counterclockwise - origin: ‘centroid’ or a tuple of (x, y)
- nomad.map_utils.rotate_streets_to_align(streets_gdf, k=200)[source]
Estimate grid alignment from street bearings and rotate the network.
Returns a tuple of (rotated_streets_gdf, rotation_degrees).
- nomad.map_utils.save_geodata(gdf: GeoDataFrame, path: str, layer: str = None)[source]
Persist a GeoDataFrame to disk based on file extension.
Supported formats: - .geojson/.json -> GeoJSON - .parquet/.geoparquet -> GeoParquet - .shp -> ESRI Shapefile (multiple files created alongside) - .gpkg -> GeoPackage (layer optional, defaults to ‘data’)