History of pypsa_eur_grid
The changes to the source code of this entry in the repository, newest first, each with the differences it made to the entry's files. They are also listed on GitLab.
[entries] Add the date when each entry was added, and remove icon_hash beff7c9
The dates are those of the commits that first added the entries' files (2020-08-11 for the entries of the initial commit); renamed entries keep the date of their first name. Changed: none
diff --git a/entries/pypsa_eur_grid/__init__.py b/entries/pypsa_eur_grid/__init__.py
index 2d6778b..fa7c59b 100644
--- a/entries/pypsa_eur_grid/__init__.py
+++ b/entries/pypsa_eur_grid/__init__.py
@@ -51,7 +51,7 @@ url = 'https://zenodo.org/records/18619025'
citation = [('B. Xiong, D. Fioriti, F. Neumann, I. Riepin, T. Brown, "Modelling the high-voltage grid using open data for Europe and beyond." Scientific Data 12, 277 (2025)', 'https://doi.org/10.1038/s41597-025-04550-7'),
('B. Xiong, D. Fioriti, F. Neumann, I. Riepin, T. Brown, "Prebuilt Electricity Network for PyPSA-Eur based on OpenStreetMap Data." Zenodo, versions 0.1-0.7 (2024-2026)', 'https://doi.org/10.5281/zenodo.12799201')]
upstream_license = ('Open Data Commons Open Database License (ODbL) v1.0', 'https://opendatacommons.org/licenses/odbl/1-0/')
-icon_hash = None
+date_added = '2026-10-27'
# The Zenodo records of the versions of the dataset
versions = [("12799202", "0.1"), ("13342577", "0.2"), ("13358976", "0.3"),
("13759222", "0.4"), ("13981528", "0.5"), ("14144752", "0.6"),
[entries] Prefix the properties in the descriptions with (Node), (Edge) or (Graph) bc3dbbd
The lists of properties at the end of the descriptions marked edge properties with "Edge" but left node properties unmarked, or grouped them in "Nodes: `a`, ...; `b`, ..." items, so the kind of a property was often unclear. Every item now starts with (Node), (Edge) or (Graph), followed by the property names, a colon and the explanation, one item per property or group of properties; qualifications (kinds of nodes, networks) follow the names in parentheses. Properties that were only named got a short explanation, and a few items that named the wrong kind of property were corrected.
diff --git a/entries/pypsa_eur_grid/__init__.py b/entries/pypsa_eur_grid/__init__.py
index 1e81385..2d6778b 100644
--- a/entries/pypsa_eur_grid/__init__.py
+++ b/entries/pypsa_eur_grid/__init__.py
@@ -27,8 +27,25 @@ The dataset is updated as OSM and the cleaning workflow change; each of its seve
The networks have the following properties (some columns exist only in later versions of the data, as indicated):
-- Nodes: `name`, the bus identifier (derived from the OSM ids of the substation); `voltage`, the voltage level (kV); `dc`, whether the bus is a direct current bus; `symbol`, the kind of bus (e.g. `Substation`); `under_construction`, whether it is under construction; `osm_ids`, the OSM elements of the bus (from version 0.5 on); `latitude` and `longitude`, the geographical position; `country`, the two-letter country code.
-- Edges: `type`, the kind of element (`line`, `link`, `transformer` or `converter`); `name`, the element's identifier (for lines and links derived from the OSM ids, which can be looked up on OpenStreetMap); `voltage`, the voltage of lines, links and converters (kV, from version 0.3 on for converters); `voltage_bus0` and `voltage_bus1`, the voltages of the two sides of transformers (kV); `circuits`, the number of circuits of lines; `length`, the length of lines and links (m); `p_nom`, the nominal power of links (and of converters, from version 0.5 on) (MW); `s_nom`, the nominal apparent power of transformers (from version 0.5 on) and lines (from version 0.6 on) (MVA); `i_nom` (kA), `r` (Ω), `x` (Ω) and `b` (S), the nominal current, resistance, reactance and susceptance of lines, and `line_type`, the standard line type assumed for these parameters (from version 0.6 on); `underground` and `under_construction`, whether the line or link is an underground cable and whether it is under construction; `osm_ids`, the OSM elements making up the line or link (from version 0.5 on). Values that do not apply to an element are NaN (or empty, or false)."""
+- (Node) `name`: the bus identifier (derived from the OSM ids of the substation).
+- (Node) `voltage`: the voltage level (kV).
+- (Node) `dc`: whether the bus is a direct current bus.
+- (Node) `symbol`: the kind of bus (e.g. `Substation`).
+- (Node) `under_construction`: whether it is under construction.
+- (Node) `osm_ids`: the OSM elements of the bus (from version 0.5 on).
+- (Node) `latitude` and `longitude`: the geographical position.
+- (Node) `country`: the two-letter country code.
+- (Edge) `type`: the kind of element (`line`, `link`, `transformer` or `converter`).
+- (Edge) `name`: the element's identifier (for lines and links derived from the OSM ids, which can be looked up on OpenStreetMap).
+- (Edge) `voltage`: the voltage of lines, links and converters (kV, from version 0.3 on for converters).
+- (Edge) `voltage_bus0` and `voltage_bus1`: the voltages of the two sides of transformers (kV).
+- (Edge) `circuits`: the number of circuits of lines.
+- (Edge) `length`: the length of lines and links (m).
+- (Edge) `p_nom`: the nominal power of links (and of converters, from version 0.5 on) (MW).
+- (Edge) `s_nom`: the nominal apparent power of transformers (from version 0.5 on) and lines (from version 0.6 on) (MVA).
+- (Edge) `i_nom` (kA): `r` (Ω), `x` (Ω) and `b` (S), the nominal current, resistance, reactance and susceptance of lines, and `line_type`, the standard line type assumed for these parameters (from version 0.6 on).
+- (Edge) `underground` and `under_construction`: whether the line or link is an underground cable and whether it is under construction.
+- (Edge) `osm_ids`: the OSM elements making up the line or link (from version 0.5 on). Values that do not apply to an element are NaN (or empty, or false)."""
tags = ['Technological', 'Power grid', 'Spatial', 'Weighted', 'Multigraph', 'Metadata']
url = 'https://zenodo.org/records/18619025'
citation = [('B. Xiong, D. Fioriti, F. Neumann, I. Riepin, T. Brown, "Modelling the high-voltage grid using open data for Europe and beyond." Scientific Data 12, 277 (2025)', 'https://doi.org/10.1038/s41597-025-04550-7'),
[entries] Remove unneeded code from the entries 2c69f19
Unneeded "global files" statements, unused imports and variables, f-strings without placeholders, duplicate keys in foodweb_little_rock (keeping the order and the values used), and the second definition of get_lines() in twitter_higgs. Nothing changes in the networks or descriptions. Changed: none
diff --git a/entries/pypsa_eur_grid/__init__.py b/entries/pypsa_eur_grid/__init__.py
index 5a8205d..1e81385 100644
--- a/entries/pypsa_eur_grid/__init__.py
+++ b/entries/pypsa_eur_grid/__init__.py
@@ -86,7 +86,6 @@ def read_table(name, fname):
@coerce_props()
@annotate()
def parse(alts=None):
- global files
name = __name__.split(".")[-1]
for fnames, alt, fmt in files:
if alts is not None and alt not in alts:
[entries] New entry: pypsa_eur_grid 905b898
diff --git a/entries/pypsa_eur_grid/__init__.py b/entries/pypsa_eur_grid/__init__.py
new file mode 100644
index 0000000..5a8205d
--- /dev/null
+++ b/entries/pypsa_eur_grid/__init__.py
@@ -0,0 +1,137 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2026 Tiago de Paula Peixoto <tiago@skewed.de>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from .. import *
+
+title = "European high-voltage grid from OpenStreetMap (PyPSA-Eur, 2024-2026)"
+description = """Networks of the European high-voltage electricity transmission grid (220 kV to 750 kV), built by B. Xiong, D. Fioriti, F. Neumann, I. Riepin and T. Brown from OpenStreetMap (OSM) data, as the prebuilt grid of the open energy system model PyPSA-Eur. The OSM power data (substations, lines, cables and high-voltage direct current links) of 35 European countries (36, with Kosovo, in version 0.7) were retrieved with the Overpass API and cleaned with heuristics that complete missing or ambiguous electrical parameters (e.g. the voltage and the number of circuits of lines); substations close to each other are aggregated into single buses (within 5 km in the first versions, within 500 m from version 0.5 on), and the lines are split and joined so that the grid is topologically connected.
+
+A node is a bus, i.e. a (possibly aggregated) substation at a given voltage level, so that a substation with several voltage levels is represented by several buses, and an edge is one of the elements of the grid joining two buses: an alternating current (AC) line or cable, a direct current (DC) link, a transformer between two voltage levels, or an AC/DC converter (the edge property `type`). The networks are undirected; several elements may join the same pair of buses (parallel edges).
+
+The dataset is updated as OSM and the cleaning workflow change; each of its seven versions, from 0.1 (July 2024) to 0.7 (February 2026), is a separate network, named after the version (`v0.1`, ..., `v0.7`). The geometries of the lines (their courses as polylines) and of the substations are not included, and neither are the interactive maps of the later versions.
+
+The networks have the following properties (some columns exist only in later versions of the data, as indicated):
+
+- Nodes: `name`, the bus identifier (derived from the OSM ids of the substation); `voltage`, the voltage level (kV); `dc`, whether the bus is a direct current bus; `symbol`, the kind of bus (e.g. `Substation`); `under_construction`, whether it is under construction; `osm_ids`, the OSM elements of the bus (from version 0.5 on); `latitude` and `longitude`, the geographical position; `country`, the two-letter country code.
+- Edges: `type`, the kind of element (`line`, `link`, `transformer` or `converter`); `name`, the element's identifier (for lines and links derived from the OSM ids, which can be looked up on OpenStreetMap); `voltage`, the voltage of lines, links and converters (kV, from version 0.3 on for converters); `voltage_bus0` and `voltage_bus1`, the voltages of the two sides of transformers (kV); `circuits`, the number of circuits of lines; `length`, the length of lines and links (m); `p_nom`, the nominal power of links (and of converters, from version 0.5 on) (MW); `s_nom`, the nominal apparent power of transformers (from version 0.5 on) and lines (from version 0.6 on) (MVA); `i_nom` (kA), `r` (Ω), `x` (Ω) and `b` (S), the nominal current, resistance, reactance and susceptance of lines, and `line_type`, the standard line type assumed for these parameters (from version 0.6 on); `underground` and `under_construction`, whether the line or link is an underground cable and whether it is under construction; `osm_ids`, the OSM elements making up the line or link (from version 0.5 on). Values that do not apply to an element are NaN (or empty, or false)."""
+tags = ['Technological', 'Power grid', 'Spatial', 'Weighted', 'Multigraph', 'Metadata']
+url = 'https://zenodo.org/records/18619025'
+citation = [('B. Xiong, D. Fioriti, F. Neumann, I. Riepin, T. Brown, "Modelling the high-voltage grid using open data for Europe and beyond." Scientific Data 12, 277 (2025)', 'https://doi.org/10.1038/s41597-025-04550-7'),
+ ('B. Xiong, D. Fioriti, F. Neumann, I. Riepin, T. Brown, "Prebuilt Electricity Network for PyPSA-Eur based on OpenStreetMap Data." Zenodo, versions 0.1-0.7 (2024-2026)', 'https://doi.org/10.5281/zenodo.12799201')]
+upstream_license = ('Open Data Commons Open Database License (ODbL) v1.0', 'https://opendatacommons.org/licenses/odbl/1-0/')
+icon_hash = None
+# The Zenodo records of the versions of the dataset
+versions = [("12799202", "0.1"), ("13342577", "0.2"), ("13358976", "0.3"),
+ ("13759222", "0.4"), ("13981528", "0.5"), ("14144752", "0.6"),
+ ("18619025", "0.7")]
+tables = ["buses", "lines", "links", "transformers", "converters"]
+upstream_prefix = 'https://zenodo.org/records'
+files = [(tuple(f"{rec}/files/{t}.csv" for t in tables), f"v{v}", None)
+ for rec, v in versions]
+
+def fetch_upstream(force=False):
+ return fetch_upstream_files(__name__.split(".")[-1], upstream_prefix, files,
+ force)
+
+# Columns of the tables: (property name, type); the other columns (the
+# geometries, and the ids and buses of the edges) are handled separately
+# or left out
+vcols = {"voltage": ("voltage", "double"), "dc": ("dc", "bool"),
+ "symbol": ("symbol", "string"),
+ "under_construction": ("under_construction", "bool"),
+ "tags": ("osm_ids", "string"), "y": ("latitude", "double"),
+ "x": ("longitude", "double"), "country": ("country", "string")}
+ecols = {"voltage": ("voltage", "double"),
+ "voltage_bus0": ("voltage_bus0", "double"),
+ "voltage_bus1": ("voltage_bus1", "double"),
+ "circuits": ("circuits", "double"), "length": ("length", "double"),
+ "p_nom": ("p_nom", "double"), "s_nom": ("s_nom", "double"),
+ "i_nom": ("i_nom", "double"), "r": ("r", "double"),
+ "x": ("x", "double"), "b": ("b", "double"),
+ "type": ("line_type", "string"),
+ "underground": ("underground", "bool"),
+ "under_construction": ("under_construction", "bool"),
+ "tags": ("osm_ids", "string")}
+
+def convert(val, t):
+ if t == "double":
+ return float(val) if val != "" else numpy.nan
+ if t == "bool":
+ if val not in ("t", "f", ""):
+ raise ValueError(f"unexpected boolean value: {val}")
+ return val == "t"
+ return val
+
+def read_table(name, fname):
+ with open_upstream_file(name, fname, "r") as f:
+ # The geometries (which contain commas) are quoted with single quotes
+ return list(csv.DictReader(f, quotechar="'"))
+
+@cache_network()
+@coerce_props()
+@annotate()
+def parse(alts=None):
+ global files
+ name = __name__.split(".")[-1]
+ for fnames, alt, fmt in files:
+ if alts is not None and alt not in alts:
+ continue
+ buses, *edge_tables = [read_table(name, fname) for fname in fnames]
+ g = Graph(directed=False)
+ g.add_vertex(len(buses))
+ idx = {r["bus_id"]: i for i, r in enumerate(buses)}
+ if len(idx) != len(buses):
+ raise ValueError("repeated bus ids")
+ g.vp.name = g.new_vp("string", vals=[r["bus_id"] for r in buses])
+ for col, (k, t) in vcols.items():
+ if col not in buses[0]:
+ continue
+ g.vp[k] = g.new_vp(t, vals=[convert(r[col], t) for r in buses])
+
+ present = set()
+ for table in edge_tables:
+ present.update(c for c in table[0].keys() if c in ecols)
+ eprops = {k: [] for k in ["type", "name"] + [ecols[c][0] for c in ecols
+ if c in present]}
+ edges = []
+ for kind, table in zip(["line", "link", "transformer", "converter"],
+ edge_tables):
+ id_col = list(table[0].keys())[0]
+ for r in table:
+ edges.append((idx[r["bus0"]], idx[r["bus1"]]))
+ eprops["type"].append(kind)
+ eprops["name"].append(r[id_col])
+ for c in ecols:
+ if c not in present:
+ continue
+ k, t = ecols[c]
+ eprops[k].append(convert(r.get(c, ""), t))
+ g.add_edge_list(edges)
+ for k, vals in eprops.items():
+ t = "string"
+ for c, (k_, t_) in ecols.items():
+ if k_ == k:
+ t = t_
+ g.ep[k] = g.new_ep(t, vals=vals)
+ yield alt, g
+
+
+def get_pos(g, sbm_fit):
+ # Spatial network: laid out with the default parameters of cfd_layout(),
+ # without the partition of the SBM fit
+ return cfd_layout(g)