Skip to content

fix(twin): read a bus's GeoJSON coordinates as [longitude, latitude] - #57

Open
nilsonfh wants to merge 1 commit into
mainfrom
fix/twin-base-coordinate-order
Open

nilsonfh wants to merge 1 commit into
mainfrom
fix/twin-base-coordinate-order

Conversation

@nilsonfh

Copy link
Copy Markdown
Contributor

What

bd syntgrid-06l. Two readers parsed a bus's GeoJSON geo value as [latitude, longitude], so every freshly exported twin transposed every bus.

GeoJSON Point coordinates are [longitude, latitude] (RFC 7946), and that is what pandapower writes into net.bus["geo"] from the builder's x = longitude / y = latitude node attributes (PandapowerGridBuilder.create_bus_geodata, and gridalyn/twin/core/graph.py documents the convention).

  • gridalyn/twin/adapters/network.py:_coords_from_geo — the base export.
  • gridalyn/projects/workflows/scripts/run_digital_twin_ev_powerflow.py:_coords_from_geo — the per-scenario node artifacts the dashboard draws.

How it was found, and why nothing caught it

Rebuilding the Trois-Rivières twin to look at it in the dashboard: gridalyn twin base wrote grid_buses.parquet with lat in [-72.6204, -72.5878] and lon in [46.3315, 46.3544]. The dashboard catalog then reported extent.bbox [-72.62, -72.62, 46.35, 46.35] and centre {lat: -13.133, lon: -13.133}, and viewState.js frames the map from that centre — so the map could not show the network at all.

The committed instances/default/digital_twin/base/grid_buses.parquet (2026-08-12, same adapter_id) has the columns the right way round, so this is a regression against the repo's own artifact, not the original behaviour. It stayed invisible because the committed base predates the pandapower geo column, both fields are floats, and nothing under tests/ referenced either helper.

Verification

  • tests/test_network_adapters.py::GeoJsonCoordinateOrderTest, four tests: what pandapower actually writes (the premise, independent of our readers), the exported bus table, a Québec-range bound that a transposition cannot satisfy whatever the columns are named, and the second reader.
  • Failing-first, measured: re-introducing the exact defect fails 3 of the 4 (the premise test still passes, as it must).
  • 819 passed, 1 skipped across the twin/adapter/catalog/repository/publication/hygiene/public-API/layer-direction files.
  • Full suite: 2211 passed, 76 skipped (the operator-verified heavy studies, whose outputs are gitignored).
  • mypy: gridalyn 116/116, twin 12/12. black, isort, flake8 clean.

Not in this PR

Artifacts already written with the columns transposed are not migrated: outside this repo nothing tracked carries them, and the committed base predates the defect. The issue records that decision.

🤖 Generated with Claude Code

Two readers took coordinates[0] as the latitude, so every freshly exported
twin transposed every bus: a rebuilt Trois-Rivieres base carried lat in
[-72.62, -72.59] and lon in [46.33, 46.35], and the dashboard catalog then
centred the map at lat -13.133 / lon -13.133, where nothing is.

GeoJSON Point coordinates are [longitude, latitude] (RFC 7946), which is what
pandapower writes into net.bus['geo'] from the builder's x=longitude /
y=latitude node attributes. The committed base from 2026-08-12, same adapter,
has the columns the right way round, so this is a regression against the
repo's own artifact.

Nothing under tests/ referenced either helper, which is why it shipped: both
fields are floats, and a swap only shows up as a map centred in the South
Atlantic. GeoJsonCoordinateOrderTest now pins what pandapower writes, both
readers, and a Quebec-range bound a transposition cannot satisfy. Measured
failing-first: re-introducing the defect fails 3 of its 4 tests.

bd 06l

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant