mirror of
https://github.com/tomasriveral/ReSSPublica.git
synced 2026-08-11 18:28:38 +02:00
fix: clean up new code
This commit is contained in:
@@ -12,12 +12,12 @@ logger = logging.getLogger("resspublica")
|
|||||||
from .translations import *
|
from .translations import *
|
||||||
from .utils import *
|
from .utils import *
|
||||||
|
|
||||||
start_date = pd.Timestamp("2026-01-01")
|
startDate = pd.Timestamp("2026-01-01")
|
||||||
start_date_datetime = date.fromisoformat("2026-01-01") # a bit dumb we need those two formats
|
startDateDatetimeFormat = date.fromisoformat("2026-01-01") # a bit dumb we need those two formats
|
||||||
end_date = pd.Timestamp((date.today() - timedelta(days=1)).isoformat())
|
endDate = pd.Timestamp((date.today() - timedelta(days=1)).isoformat())
|
||||||
|
|
||||||
|
|
||||||
station_information = {
|
stationInformation = {
|
||||||
"100048": {
|
"100048": {
|
||||||
"name": "Basel Chrischona",
|
"name": "Basel Chrischona",
|
||||||
"coordinates": (47.571709338, 7.687073826)
|
"coordinates": (47.571709338, 7.687073826)
|
||||||
@@ -48,7 +48,7 @@ pollutants = [
|
|||||||
"o3"
|
"o3"
|
||||||
]
|
]
|
||||||
|
|
||||||
pollutant_units = {
|
pollutantUnits = {
|
||||||
"pm10": "µg/m³",
|
"pm10": "µg/m³",
|
||||||
"pm2_5": "µg/m³",
|
"pm2_5": "µg/m³",
|
||||||
"no2": "µg/m³",
|
"no2": "µg/m³",
|
||||||
@@ -57,7 +57,7 @@ pollutant_units = {
|
|||||||
|
|
||||||
|
|
||||||
# Fixed scale per pollutant so colors remain comparable day-to-day
|
# Fixed scale per pollutant so colors remain comparable day-to-day
|
||||||
pollutant_scales = {
|
pollutantScales = {
|
||||||
"pm10": (0, 50),
|
"pm10": (0, 50),
|
||||||
"pm2_5": (0, 30),
|
"pm2_5": (0, 30),
|
||||||
"no2": (0, 100),
|
"no2": (0, 100),
|
||||||
@@ -76,30 +76,24 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
"https://data.bl.ch/api/v2/catalog/datasets/12510/exports/parquet"
|
"https://data.bl.ch/api/v2/catalog/datasets/12510/exports/parquet"
|
||||||
]
|
]
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
# Load data
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
dataframes = []
|
dataframes = []
|
||||||
|
|
||||||
for url in urls:
|
for url in urls:
|
||||||
logger.debug(f"Querying {url}...")
|
logger.debug(f"Querying {url}...")
|
||||||
df = pd.read_parquet(url)
|
df = pd.read_parquet(url)
|
||||||
|
|
||||||
station_id = url.split("/")[-3]
|
stationId = url.split("/")[-3]
|
||||||
|
|
||||||
df["station_id"] = station_id
|
df["stationId"] = stationId
|
||||||
|
|
||||||
# Always define station name
|
# Always define station name
|
||||||
# Use dataset id as fallback until manually mapped
|
# Use dataset id as fallback until manually mapped
|
||||||
df["station_name"] = station_id
|
df["stationName"] = stationId
|
||||||
|
|
||||||
if station_id in station_information:
|
if stationId in stationInformation:
|
||||||
df["station_name"] = station_information[station_id]["name"]
|
df["stationName"] = stationInformation[stationId]["name"]
|
||||||
|
|
||||||
# -----------------------------------------------------
|
possibleVariableNameForDates = [
|
||||||
# Normalize datetime to Swiss time
|
|
||||||
# -----------------------------------------------------
|
|
||||||
possible_dates = [
|
|
||||||
"datum_zeit",
|
"datum_zeit",
|
||||||
"timestamp",
|
"timestamp",
|
||||||
"anfangszeit",
|
"anfangszeit",
|
||||||
@@ -109,7 +103,7 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
date_column = next(
|
date_column = next(
|
||||||
(
|
(
|
||||||
col
|
col
|
||||||
for col in possible_dates
|
for col in possibleVariableNameForDates
|
||||||
if col in df.columns
|
if col in df.columns
|
||||||
),
|
),
|
||||||
None
|
None
|
||||||
@@ -134,23 +128,17 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------
|
if stationId in stationInformation:
|
||||||
# Add coordinates for BL datasets
|
|
||||||
# -----------------------------------------------------
|
|
||||||
if station_id in station_information:
|
|
||||||
|
|
||||||
lat, lon = station_information[station_id]["coordinates"]
|
lat, lon = stationInformation[stationId]["coordinates"]
|
||||||
|
|
||||||
df["latitude"] = lat
|
df["latitude"] = lat
|
||||||
df["longitude"] = lon
|
df["longitude"] = lon
|
||||||
|
|
||||||
df["station_name"] = (
|
df["stationName"] = (
|
||||||
station_information[station_id]["name"]
|
stationInformation[stationId]["name"]
|
||||||
)
|
)
|
||||||
|
|
||||||
# -----------------------------------------------------
|
|
||||||
# Convert long format datasets
|
|
||||||
# -----------------------------------------------------
|
|
||||||
if (
|
if (
|
||||||
"parameter" in df.columns
|
"parameter" in df.columns
|
||||||
and "messwert" in df.columns
|
and "messwert" in df.columns
|
||||||
@@ -167,9 +155,6 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
).reset_index()
|
).reset_index()
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------
|
|
||||||
# Pollutant normalization
|
|
||||||
# -----------------------------------------------------
|
|
||||||
pollutant_mapping = {
|
pollutant_mapping = {
|
||||||
|
|
||||||
"pm10": [
|
"pm10": [
|
||||||
@@ -214,11 +199,6 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------
|
|
||||||
# Melt everything into:
|
|
||||||
# date_time | station_id | pollutant | value | geometry
|
|
||||||
# -----------------------------------------------------
|
|
||||||
parts = []
|
parts = []
|
||||||
|
|
||||||
for pollutant, candidates in pollutant_mapping.items():
|
for pollutant, candidates in pollutant_mapping.items():
|
||||||
@@ -230,8 +210,8 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
|
|
||||||
keep = [
|
keep = [
|
||||||
"date_time",
|
"date_time",
|
||||||
"station_id",
|
"stationId",
|
||||||
"station_name",
|
"stationName",
|
||||||
column
|
column
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -271,20 +251,12 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
|
|
||||||
dataframes.append(df)
|
dataframes.append(df)
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
# Combine datasets
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
dataframe = pd.concat(
|
dataframe = pd.concat(
|
||||||
dataframes,
|
dataframes,
|
||||||
ignore_index=True,
|
ignore_index=True,
|
||||||
sort=False
|
sort=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
# Geometry
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
def safe_load(x):
|
def safe_load(x):
|
||||||
try:
|
try:
|
||||||
geom = wkb.loads(x)
|
geom = wkb.loads(x)
|
||||||
@@ -294,10 +266,8 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
dataframe["geometry"] = None
|
dataframe["geometry"] = None
|
||||||
|
|
||||||
|
|
||||||
if "geo_point_2d" in dataframe.columns:
|
if "geo_point_2d" in dataframe.columns:
|
||||||
|
|
||||||
dataframe["geometry"] = dataframe[
|
dataframe["geometry"] = dataframe[
|
||||||
@@ -325,9 +295,6 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
crs="EPSG:4326"
|
crs="EPSG:4326"
|
||||||
)
|
)
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
# Boundaries
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
gdb = (
|
gdb = (
|
||||||
ASSETS /
|
ASSETS /
|
||||||
"swissBOUNDARIES3D_1_5_LV95_LN02.gdb"
|
"swissBOUNDARIES3D_1_5_LV95_LN02.gdb"
|
||||||
@@ -346,11 +313,8 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
cantons["KANTONSNUMMER"] == 13
|
cantons["KANTONSNUMMER"] == 13
|
||||||
].to_crs("EPSG:4326")
|
].to_crs("EPSG:4326")
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
# Time filter
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
logger.info("Generating daily image...")
|
logger.info("Generating daily image...")
|
||||||
for day in pd.date_range(start_date, end_date, freq="D"):
|
for day in pd.date_range(startDate, endDate, freq="D"):
|
||||||
|
|
||||||
if Path( CACHE / f"baselAirQuality-{day.strftime("%Y-%m-%d")}.png").exists():
|
if Path( CACHE / f"baselAirQuality-{day.strftime("%Y-%m-%d")}.png").exists():
|
||||||
logger.debug(f"Day {day.strftime("%Y-%m-%d")} is already cached. Skipping...")
|
logger.debug(f"Day {day.strftime("%Y-%m-%d")} is already cached. Skipping...")
|
||||||
@@ -365,14 +329,11 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
(geo["date_time"] < next_day)
|
(geo["date_time"] < next_day)
|
||||||
]
|
]
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
# Average per station
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
averaged = (
|
averaged = (
|
||||||
geo_day.groupby(
|
geo_day.groupby(
|
||||||
[
|
[
|
||||||
"station_id",
|
"stationId",
|
||||||
"station_name",
|
"stationName",
|
||||||
"pollutant",
|
"pollutant",
|
||||||
"geometry"
|
"geometry"
|
||||||
],
|
],
|
||||||
@@ -389,12 +350,6 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
crs="EPSG:4326"
|
crs="EPSG:4326"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
# Plot
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
fig, axes = plt.subplots(
|
fig, axes = plt.subplots(
|
||||||
2,
|
2,
|
||||||
2,
|
2,
|
||||||
@@ -418,7 +373,7 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
ax.set_visible(False)
|
ax.set_visible(False)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
vmin, vmax = pollutant_scales[pollutant]
|
vmin, vmax = pollutantScales[pollutant]
|
||||||
|
|
||||||
subset.plot(
|
subset.plot(
|
||||||
ax=ax,
|
ax=ax,
|
||||||
@@ -469,12 +424,12 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
for _, row in subset.iterrows():
|
for _, row in subset.iterrows():
|
||||||
|
|
||||||
dx, dy = label_offsets.get(
|
dx, dy = label_offsets.get(
|
||||||
row["station_name"],
|
row["stationName"],
|
||||||
(0, 8)
|
(0, 8)
|
||||||
)
|
)
|
||||||
|
|
||||||
ax.annotate(
|
ax.annotate(
|
||||||
row["station_name"],
|
row["stationName"],
|
||||||
xy=(
|
xy=(
|
||||||
row.geometry.x,
|
row.geometry.x,
|
||||||
row.geometry.y
|
row.geometry.y
|
||||||
@@ -492,7 +447,7 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
)
|
)
|
||||||
|
|
||||||
ax.set_title(
|
ax.set_title(
|
||||||
f"{pollutant} ({pollutant_units[pollutant]})"
|
f"{pollutant} ({pollutantUnits[pollutant]})"
|
||||||
)
|
)
|
||||||
|
|
||||||
ax.axis("off")
|
ax.axis("off")
|
||||||
@@ -514,7 +469,7 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
}
|
}
|
||||||
|
|
||||||
yesterday = date.today() - timedelta(days=1)
|
yesterday = date.today() - timedelta(days=1)
|
||||||
current = start_date_datetime
|
current = startDateDatetimeFormat
|
||||||
|
|
||||||
while current <= yesterday:
|
while current <= yesterday:
|
||||||
dailyEntry = {}
|
dailyEntry = {}
|
||||||
@@ -523,7 +478,7 @@ def generateBaselLuftqualitat(ASSETS, CACHE):
|
|||||||
dailyEntry["date"] = current.isoformat()
|
dailyEntry["date"] = current.isoformat()
|
||||||
dailyEntry["source"] = "https://luftqualitaet.ch/"
|
dailyEntry["source"] = "https://luftqualitaet.ch/"
|
||||||
dailyEntry["url"] = "https://luftqualitaet.ch/"
|
dailyEntry["url"] = "https://luftqualitaet.ch/"
|
||||||
dailyEntry["text"] = f"<img src\"https://resspublica.tomasrivera.ch/images/baselAirQuality-{current.isoformat()}.png\"alt=\"basel air quality {current.isoformat()}\">"
|
dailyEntry["text"] = f"<img src=\"https://resspublica.tomasrivera.ch/images/baselAirQuality-{current.isoformat()}.png\"alt=\"basel air quality {current.isoformat()}\">"
|
||||||
|
|
||||||
for lang in ["fr", "de", "it", "rm", "en"]:
|
for lang in ["fr", "de", "it", "rm", "en"]:
|
||||||
dailyEntry["title"] = f"{translatedAirQualityInBasel[lang]} {current.isoformat()}"
|
dailyEntry["title"] = f"{translatedAirQualityInBasel[lang]} {current.isoformat()}"
|
||||||
|
|||||||
Reference in New Issue
Block a user