Synthetic Networks From GeoJSON
Gridalyn can build a synthetic distribution network from building-footprint GeoJSON. This path is useful when a utility-grade GIS model is unavailable but you still need a reproducible topology for studies, demos, or early digital twin development.
Data Sources
Two footprint sources are supported by the examples:
| Source | How Gridalyn uses it | Notes |
|---|---|---|
| OpenStreetMap through OSMnx | BuildingDownloader queries OSM features with building=True inside a polygon and writes a local GeoJSON. |
OSMnx returns a GeoPandas GeoDataFrame from the OpenStreetMap Overpass API. The OSM building=* tag describes physical buildings and includes broad categories, so inspect local data quality before treating tags as customer classes. |
| Microsoft Global ML Building Footprints | prepare_microsoft_building_footprints.py converts a local line-delimited GeoJSON partition to regular clipped GeoJSON. |
Microsoft publishes open building footprints derived from imagery under CDLA Permissive 2.0. Many partitions are .csv.gz files whose contents are GeoJSON lines, so convert and clip them before using them as study inputs. |
The repository does not track heavyweight source downloads. Keep raw OSM or
Microsoft source files outside Git, then write filtered outputs under a project
input folder or examples/generated/outputs/ for tutorial work.
Flow
flowchart LR
osm[OSMnx / OSM buildings] --> raw[Raw building footprints]
ms[Microsoft footprint partition] --> raw
raw --> clip[Clip to study polygon]
clip --> geojson[Building GeoJSON]
geojson --> bundle[Gridalyn topology bundle]
bundle --> pp[pandapower network]
pp --> twin[Digital twin base artifacts]
The canonical footprint preparation entry point is gridalyn.twin.adapters.
The canonical network-generation entry point is
gridalyn.simulation.build_synthetic_network_from_geojson.
Project API
Projects should call the SDK builder instead of duplicating the tutorial script steps:
from pathlib import Path
from gridalyn.simulation import build_synthetic_network_from_geojson
result = build_synthetic_network_from_geojson(
footprints_path=Path("projects/my_project/inputs/buildings.geojson"),
config_path=Path("configs/grid/config.json"),
out_dir=Path("projects/my_project/outputs/cache"),
clustering_crs="auto",
write_cache=True,
run_powerflow=True,
)
The function returns:
| Field | Meaning |
|---|---|
power_grid |
Generated topology bundle used by Gridalyn simulation and visualization helpers. |
net |
The generated pandapower network. |
validation_report |
Counts, CRS lineage, source hashes, topology checks, and optional power-flow convergence. |
report_path |
Path to synthetic_network_validation.json when out_dir is provided. |
Use clustering_crs="auto" for normal GeoJSON inputs. It estimates a local
metric CRS for K-Means and MST distances while preserving longitude/latitude on
graph nodes for maps and digital-twin geodata.
Capacity-constrained LV assignment (opt-in)
By default the builder works out how many MV/LV transformers the footprints need, then lets K-Means decide which buildings each one serves. K-Means partitions by geometry alone, so some transformers serve far more buildings than they were sized for: on the shipped Trois-Rivieres footprints, 43 of 193 sit above 100% at the declared envelope.
Pass lv_assignment="capacitated" to cap every transformer at
ceil(buildings / transformers) buildings, the count the transformer number was
sized for. The validation report then gains an lv_assignment block with the
limit, the buildings-per-transformer distribution, and any transformer still
above its rated kVA. Adding block_penalty_km2=0.005 also keeps clusters from
straddling streets; it needs the geo extra and a street-network fetch, because
it works from the blocks the streets enclose.
Both options default off. They change which buildings share a transformer, so turning them on for an existing study is a deliberate re-base, not a display change.
Declaring topology in the grid config
A study pins these choices as data instead of passing arguments. The grid
config accepts a topology block with lv_assignment,
max_customers_per_transformer (a limit the study can cite, which wins over the
sized count), block_penalty_km2, snap_transformers_to_streets and
street_layer, plus an external_grid block whose vm_pu sets the slack
setpoint (1.0 pu when absent). An explicit argument to the builder overrides the
config. A config without either block builds exactly what it built before.
A live fetch from OpenStreetMap is not reproducible, because the map changes.
Write the streets once with python tools/snapshot_streets.py --footprints
<buildings.geojson> --out <streets.geojson>, commit the file beside the
footprints with its OpenStreetMap attribution, and declare
street_layer as its path (relative to the footprints file's directory) and
the printed sha256. The build refuses a layer whose digest no longer matches,
and because the digest lives in the config, a changed layer also changes the
config hash every topology cache keys on.
Offline Smoke Test
Run the synthetic generator example:
It generates fake building footprints, creates LV/MV/HV graphs, and writes the
footprint GeoJSON, the topology/network caches, and
synthetic_network_validation.json under
examples/generated/outputs/basic_grid_creation/. It does not render maps.
Run the bundled real-footprint example:
It reads the packaged Trois-Rivieres tutorial footprint sample, builds a
pandapower model, runs diagnostics, and writes generated tutorial artifacts
under examples/generated/outputs/.
Clip Existing Footprints
Use this when you already have GeoJSON from OSMnx, Microsoft after conversion, or another source:
MPLCONFIGDIR=/tmp/matplotlib-cache \
uv run gridalyn twin clip-buildings \
--buildings-file examples/tutorials/data/example_buildings.geojson \
--polygon-file configs/geography/tr01.json \
--output-file examples/generated/outputs/buildings_inside_polygon.geojson
You can pass a custom polygon file:
uv run gridalyn twin clip-buildings \
--buildings-file path/to/buildings.geojson \
--polygon-file configs/geography/tr01.json \
--output-file projects/my_project/inputs/buildings.geojson
The polygon file can be one of:
- a JSON file with
polygon_coordinates; - a GeoJSON
Polygon; - a GeoJSON
Featurewhose geometry is aPolygon.
Download From OSMnx
Use this only when you want to query OpenStreetMap through Overpass:
uv run gridalyn twin download-osm-buildings \
--polygon-file configs/geography/tr01.json \
--output-file examples/generated/outputs/osmnx_buildings.geojson
Network access and Overpass availability determine whether this command succeeds. For reproducible projects, commit a small input manifest and keep the raw downloaded source outside Git.
Prepare Microsoft Building Footprints
After downloading the relevant Microsoft partition locally, convert and clip it:
uv run gridalyn twin prepare-microsoft-buildings \
--input-file /path/to/microsoft-partition.csv.gz \
--polygon-file configs/geography/tr01.json \
--output-file projects/my_project/inputs/buildings.geojson
Use --limit 1000 for a fast smoke test on a large partition.
Quality Checks
Before using footprints as digital-twin inputs:
- Filter to
PolygonandMultiPolygongeometries. - Validate geometries and repair invalid polygons.
- Clip to the study boundary.
- Inspect the footprint count and map.
- Confirm CRS is WGS84 or explicitly projected before area-sensitive work.
- Store source lineage in the project manifest.