
### ### ### ### ###
'QGIS_Rasterdaten_DWD_export.py'
# Download und entpacken der DWD-Rasterdaten (hier für Sommertage)
# Darstellung der DWD-Rasterdaten in QGIS
# Import des einheitlichen Layerstiels für die Rasterdaten
# Import der Layer "Grenzen" und "Hauptstädte" mit Layerstil
# Export der Karte mit hoher Auflösung als png
#
# Autor: Philipp Weisenburger
# ORCID: 0009-0004-7665-4526
# Zitation: Weisenburger (2026) - Visualisierung von DWD-Rasterdaten mit QGIS und Python
# Lizenz: CC BY-NC 4.0
#
### ### ### ### ###


### ### ### ### ###
'Anwendung'
# Die Abschnitte 1, 2 und 3 sollten nacheinander ausgeführt werden
# 1) Download der DWD-Rasterdaten
# 2) Entpacken der .gz Dateien
# 3) Erzeugen und Export der Karten
### ### ### ### ###

from qgis.core import *
from qgis.gui import QgsMapCanvas
from PyQt5.QtCore import pyqtSignal, QObject, QEventLoop
from pathlib import Path
import os
import gzip
import requests
import shutil



### ### ### ### ###
'1) Alle Geodaten für eine Variable (hier: Sommertage) herunterladen'
### ### ### ### ###

## Download der DWD-Rasterdaten, Platzhalter {} für die Jahre 
url_DWD = "https://opendata.dwd.de/climate_environment/CDC/grids_germany/annual/summer_days/grids_germany_annual_summer_days_{}_17.asc.gz"
file_path = QgsProject.instance().readPath("./")  # lokalen Pfad auflösen
folder = str(file_path + "\\DWD_Download")

for n in range(1951, 2026):
    url = url_DWD.format(n)
    #print(url)
    name = os.path.join(folder, f"{url.split("/")[-1]}")
    name_path = Path(name)
    print(name)
    
    # Abfrage der Daten
    response = requests.get(url)
    request_code = response.status_code
    data = response.content
    print(request_code)
    
    if request_code == 200:
        print(str(request_code) + " - Request succsessfull")
        name_path.write_bytes(data)




# ### ### ### ### ###
'2) .gz Geodaten entpacken'
# ### ### ### ### ###

for file_name in os.listdir(folder):
    if file_name.endswith(".gz"):
        data_path = os.path.join(folder, file_name)
        with gzip.open(data_path, "rb") as f_in:
            with open(os.path.splitext(data_path) [0], "wb") as f_out:
                shutil.copyfileobj(f_in, f_out)
                
print("Entpacken beendet")



### ### ### ### ###
'3) Erzeugen und Export der Karten'
### ### ### ### ###
 
## Leeres Bild in QGIS erzeugen
## Die DWD-Rasterdaten haben eine Auflösung von 654:866 Datenpunkten
## Verhältnis sollte Vielfaches von 654:866 sein
## Gewählt 10x(654:866) +10% (für weißen Rand, Karte wird später wieder auf 10x verkleinert)
##image = QImage(QSize(7194, 9526), QImage.Format_ARGB32_Premultiplied)
image = QImage(QSize(6540, 8660), QImage.Format_ARGB32_Premultiplied)

## Hintergrundfarbe "weiß"
color = QColor(255, 255, 255, 255) # weiß
image.fill(color.rgba())

p = QPainter()


## Eigenschaften der Kartenansicht definieren
ms = QgsMapSettings()
ms.setBackgroundColor(color)
crs = QgsCoordinateReferenceSystem("EPSG:31467") ## Globales Koordinatensystem festlegen
ms.setDestinationCrs(crs)


## Pfade für die Layer und Layerstiel-Dateien festlegen
# Layerstil für die Rasterdaten
style_DWD_path = str(file_path + "\\Aux_files\\Farben_DWD.qml")

## Layer Grenzen
grenzen_path = str(file_path + "\\Aux_files\\Grenzen_Bundesländer.gpkg")
grenzen_style = str(file_path + "\\Aux_files\\Layer_Grenzen.qml")

## Layer Hauptstädte
städte_path = str(file_path + "\\Aux_files\\Hauptstädte.gpkg")
städte_style = str(file_path + "\\Aux_files\\Layer_Städte.qml")


class RefreshCompleteListener(QObject):
    refreshComplete = pyqtSignal()
    
    def __init__(self, iface):
        super().__init__()
        self.iface = iface
        self.iface.mapCanvas().mapCanvasRefreshed.connect(self.emitRefreshComplete)
    
    def emitRefreshComplete(self):
        self.refreshComplete.emit()



## Karte für jedes Jahr (jeden heruntergeladenen Rasterdatensatz) erzeugen
for file_name in os.listdir(folder):
    if file_name.endswith(".asc"):
        p.begin(image)
        p.setRenderHint(QPainter.Antialiasing)
        
        QgsProject.instance().removeAllMapLayers() # Alle bestehenden Layer im Projekt löschen
        
        data_path = os.path.join(folder, file_name)
        layer_name = os.path.splitext(file_name)[0][33:37] # Rasterlayer wird benannt wie das Jahr der Daten
        print(layer_name)
        
        ## Rasterdaten anzeigen und Layerstil anwenden
        raster_layer = QgsRasterLayer(data_path, layer_name)
        raster_layer.setCrs(QgsCoordinateReferenceSystem("EPSG:31467"))
        raster_layer.loadNamedStyle(style_DWD_path)
        QgsProject.instance().addMapLayer(raster_layer)
        
        
        # Einfügen der anderen Kartenbestandteile
        # Layer Grenzen
        grenzen = QgsVectorLayer(grenzen_path, "Grenzen")
        grenzen.setCrs(QgsCoordinateReferenceSystem("EPSG:31467"))
        grenzen.loadNamedStyle(grenzen_style)
        QgsProject.instance().addMapLayer(grenzen)
        
        # Layer Hauptstädte
        städte = QgsVectorLayer(städte_path, "Städte")
        städte.setCrs(QgsCoordinateReferenceSystem("EPSG:3857"))
        städte.loadNamedStyle(städte_style)
        QgsProject.instance().addMapLayer(städte)
        
        
        # Karte nach Einfügen aller Bestandteile aktualisieren
        refreshListener = RefreshCompleteListener(iface)
        loop = QEventLoop()
       
        def onRefreshComplete():
            print("Aktualisierung erfolgreich")
            loop.quit()
        
        refreshListener.refreshComplete.connect(onRefreshComplete)
        iface.mapCanvas().refresh()
                
        loop.exec_()
        
        ## Karte in absteigender Reihenfolge zusammensetzen
        ms.setLayers([städte, grenzen, raster_layer])
        
        ## Zeichenbereich der Karte festlegen
        rect = QgsRectangle(ms.fullExtent())
        ms.setExtent(rect)

        ms.setOutputSize(image.size())

        render = QgsMapRendererCustomPainterJob(ms, p)
        render.start()
        render.waitForFinished()
        p.end()


        # Speichern der fertigen Karte
        Karte_path = str(file_path + "\\QGIS_Karten\\Sommertage_" + layer_name + ".png")
        image.save(Karte_path)
        print("image saved")

print("Alle Karten erstellt und gespeichert")
print("Ende --> Wechsel zu Py: 'Karten_anpassen und GIF.py' ")





