Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions powerplantmatching/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -2408,8 +2408,12 @@ def MASTR(

cols = ["NutzbareSpeicherkapazitaet", "VerknuepfteEinheit"]
with ZipFile(fn, "r") as file:
fn_storage_units = (
"bnetza_open_mastr_2025-02-09/bnetza_mastr_storage_units_raw.csv"
# Match by suffix rather than a hardcoded dated folder, so newer
# open-mastr dumps (different bnetza_open_mastr_<date>/ prefix) load.
fn_storage_units = next(
name
for name in file.namelist()
if name.endswith("bnetza_mastr_storage_units_raw.csv")
)
storage_units = pd.read_csv(file.open(fn_storage_units), usecols=cols)

Expand Down Expand Up @@ -2473,8 +2477,16 @@ def MASTR(
parse_columns=PARSE_COLUMNS,
)
.assign(
# ThermischeNutzleistung is present in the Zenodo CSV dump but absent
# from the open-mastr bulk export; fall back to KwkMastrNummer alone.
Set=lambda df: df["Set"].where(
df["KwkMastrNummer"].isna() & df["ThermischeNutzleistung"].isna(), "CHP"
df["KwkMastrNummer"].isna()
& (
df["ThermischeNutzleistung"].isna()
if "ThermischeNutzleistung" in df.columns
else True
),
"CHP",
),
)
)
Expand Down
7 changes: 6 additions & 1 deletion powerplantmatching/package_data/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,12 @@ MASTR:
reliability_score: 7
status: ["In Betrieb", "In Planung", "Endgültig stillgelegt", "Vorübergehend stillgelegt"]
capacity_threshold: 0.1 # all values below will be filtered out, given in MW
fn: bnetza_open_mastr_2025-02-09.zip
# fn may be a glob: when it contains a wildcard the most recent matching
# local bnetza_open_mastr_<date>.zip is auto-selected (ISO dates sort
# chronologically, so the newest wins). url is the frozen Zenodo seed,
# downloaded only when no local match exists, so it never clobbers a newer
# local build. Use a literal filename to pin one specific dump instead.
fn: bnetza_open_mastr_*.zip
url: https://zenodo.org/records/14783581/files/bnetza_open_mastr_2025-02-09.zip
EESI:
net_capacity: true
Expand Down
21 changes: 20 additions & 1 deletion powerplantmatching/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import os
import re
from ast import literal_eval as liteval
from glob import glob
from importlib.metadata import version
from urllib.parse import urlparse

import country_converter as coco
import numpy as np
Expand Down Expand Up @@ -76,7 +78,24 @@ def get_raw_file(name, update=False, config=None, skip_retrieve=False):
if config is None:
config = get_config()
df_config = config[name]
path = _data_in(df_config["fn"])
fn = df_config["fn"]

# A glob pattern in `fn` selects the most recent matching local file
# (e.g. a locally built, dated dump). ISO-dated filenames sort
# chronologically, so the last match is the newest. Falls back to
# downloading the URL's basename when nothing local matches.
if any(c in fn for c in "*?["):
matches = sorted(glob(_data_in(fn)))
if matches:
# The newest local dated build is authoritative. The URL is a
# frozen seed (e.g. the last Zenodo dump) that can never be newer
# than a local build, so honour the local match even when
# update=True; otherwise a forced refresh silently regresses to
# stale data.
return matches[-1]
path = _data_in(os.path.basename(urlparse(df_config["url"]).path))
else:
path = _data_in(fn)

if (not os.path.exists(path) or update) and not skip_retrieve:
url = df_config["url"]
Expand Down