Skip to content

Instantly share code, notes, and snippets.

@sfinkens
Last active April 3, 2020 08:44
Show Gist options
  • Save sfinkens/b816d78f9d72e6cdd13ba97921d092c3 to your computer and use it in GitHub Desktop.
Save sfinkens/b816d78f9d72e6cdd13ba97921d092c3 to your computer and use it in GitHub Desktop.

claas Intro

Module, Produkte & Variablen

Ein Modul entspricht irgendeinem Programm (PPS, CPP) und wird angewendet auf einen SEVIRI Scan. Es kann durch module.run_all() gestartet werden und generiert genau ein Produkt (eine netCDF Datei), das über module.product verknüpft ist. Die abstrakte Basisklasse in module.py gibt die Struktur vor, die von den erbenden Klassen in modules.py implementiert werden muss (z.B. die Methoden _init(), _run(), etc). In der Methode run_all() werden dann folgende Methoden aufgerufen:

self.init()                     # Umgebungsvariablen einrichten
self.unpack()                   # Input Daten auspacken (Download muss extern passieren)
self.create_required_dirs()     # Arbeitsverzeichnisse erstellen, in denen das Modul lebt
self.post_dir_init()            # Preprocessing, das Verzeichnisse benötigt (z.B. Config Files schreiben)
self.create_required_links()    # Executables, input daten, ... in den Verzeichnissen verlinken
self.post_link_init()           # Preprocessing, das die Links/Daten benötigt (z.B. NWP Daten remappen)
self.run()                      # Aufruf des Programms im Arbeitsverzeichnis
self.finalize()                 # Postprocessing (z.B. Dateien umbenennen, Attribute setzen)

Der ganze Spaß mit den Links ist nötig, weil die Software mit der wir arbeiten häufig nicht installierbar ist, sondern dort lebt und arbeitet wo sie kompiliert wurde. Durch das Linken klont und isoliert man diesen Lebensraum für jeden SEVIRI Scan.

Die obigen Methoden sind teilweise schon in der Basisklasse implementiert und tun dort die Dinge, die für alle Module gleich sind (z.B. Dateien umbenennen, leeres Produkt generieren). Andere sind mit @abstractmethod dekoriert, d.h. die sind Modul-spezifisch und müssen in den PPS/CPP Klassen implementiert werden. Hier gibts jetzt folgende Aufgaben:

  • Modul-spezifische Methoden in modules.py für PPS mit Leben füllen und für CPP auf den neuesten Stand bringen. Für PPS habe ich einfache Templates erstellt, wo Du sehen kannst, wie es funktioniert (class PPSCmask,class PPSCtth). Ich habe auf meinem Laptop z.B. Dummy Executables für pps-cmask und pps-ctth erstellt, die einfach nur hallo sagen und eine leere Datei mit dem richtigen Namen erzeugen. Damit läuft dann claas-run schonmal komplett durch.
  • Außerdem muss das Postprocessing in module.py aktualisiert werden (Module.create_product und Module._create_empty_product). Sowohl das Umformatieren der PPS/CPP Produkte, als auch das Generieren leerer Produkte wenn es keinen Output gibt (keine Input Daten oder Crash). Ersteres kommt ja von Irina, für letzteres habe ich auch ein Template erstellt. Dort kann man auch gut sehen, wozu die ganzen Produkt- und Variablen Definitionen gut sind.

Damit das alles so schön funktioniert, muss man außerdem

  • Für jedes Modul angeben, welches Produkt es generiert. Produkt-Definitionen liegen in products.py
  • Für jedes Produkt angeben,
    • welche Variablen es enthält (damit man auch ohne PPS/CPP Output ein leeres Produkt erstellen kann; außerdem zum Plotten hilfreich). Variablen-Definitionen liegen in variables.py.
    • mit welchen CM SAF Metadaten es verknüpft ist (im Config File, Abschnitt meta_info). Das bestimmt z.B. den Dateinamen und damit später die Datenbank Kategorie und Anzeige im WUI.

Auch hier habe ich Templates für PPS erstellt, mit denen Du anfangen kannst.

Cleanup: Modul-spezifisches Cleanup ist nur nötig für Dateien, die an nicht-Standard Orten erstellt wurden (s.u.).

Config File

Für einige Pfade und Einstellungen von PPS macht es sicher Sinn, sie im Config File anzugeben. Auch hier habe ich ein Template in config.py hinzugefügt (class PPSConfig), an dem Du Dich orientieren kannst. Es wird auch schon in den PPS Klassen benutzt. Wenn Du neue Einträge zum Config File hinzufügen willst, musst Du sie inklusive Datentyp auch in der Spezifikation claas/data/claas.cfg.spec einfügen. Dann werden sie richtig geparsed und überprüft.

Wer lebt wo

Das Arbeitsverzeichnis wird ja über scratch_dir im Config File angegeben. Dort gibt's folgende Unterordner:

download/  # Heruntergeladene Input Daten (gepackt). claas-get-mars/ecfs schreiben hier rein
upload/    # Hier werden finale Produkte tages-/monatsweise zusammengepackt, um sie ins ECFS hochzuladen (claas-archive)
import/    # ausgepackte Input Daten
work/      # Arbeitsverzeichnisse
    # Hier lebt ein Modul für einen Scan.
    # Hier können nach Belieben Verzeichnisse und Links erstellt
    # werden, um das Modul zu isolieren.
    yyyymmdd/HHMM/module_name/
exch/    # Hierüber können Daten Modul-übergreifend ausgetauscht werden
    intermediate_products/
                          yyyymmdd/    
                          # Zwischenprodukte, die von einem/mehreren nachfolgenden Scan(s)
                          # benötigt werden, z.B. CPP_RTTOV output oder irgendwelche Winkel
                          # für die Mittelung.
                                   HHMM/
                                   # Zwischenprodukte nur von diesem Scan. Hier landen momentan die
                                   # PPS/CPP Produkte.

Cleanup

claas-run löscht automatisch folgende Daten, nachdem alle Module für den Scan durchgelaufen sind (vorausgesetzt cleanup=True im Config File):

  • Arbeitsverzeichnisse work/yyyymmdd/HHMM/[pps,cpp,cpp_rttov]
  • Ausgepackte SEVIRI Daten in import/seviri_data/yyyymmdd/HHMM
  • Zwischenprodukte in exch/intermediate_products/yyyymmdd/HHMM

Wenn ein Modul abstürzt, wird nicht aufgeräumt, damit man debuggen kann. Daten, die außerhalb dieser Verzeichnisse angelegt werden, müssen in Module._cleanup() gelöscht werden. Das betrifft z.B. den CPP_RTTOV Output. CPP_RTTOV muss ja nur ein mal pro NWP File gerechnet werden und kann von mehreren Scans wiederverwendet werden. Der Output wird in exch/intermediate_products/yyyymmdd gespeichert und von CPPRTTOV._cleanup() gelöscht, sobald er out of date ist weil es ein neueres NWP file gibt.

Dann gibt es noch Daten, die ein Modul nicht selbst löschen kann, weil es noch andere Abhängigkeiten gibt. Z.B. werden NWP Daten auch von mehreren Scans benutzt, sogar über die Tagesgrenze hinaus (NWP File von d+1 00:00 ist näher am 23:45 Scan als das NWP File von 23:00). Wenn man dann auf Tagesbasis parallelisiert, dürfen die NWP Daten von Tag n erst aufgeräumt werden, wenn Tag n-1 auch fertig ist. Oder aber L2 Produkte müssen aufgehoben werden, bis das Tagesmittel erstellt wurde. All diese Daten werden von claas-cleanup gelöscht. Es wird von ecflow getriggert, unter Berücksichtigung dieser Abhängigkeiten.

Installation

cd pycmsaf && pip install .
cd claas && pip install .[plot]

Die Plotting Tools brauchen noch Basemap, und das gibt's leider nicht auf pypi.org, deswegen muss man es von Source installieren.

cd basemap-1.2.1rel && GEOS_DIR=/cmsaf/nfshome/routcm/Modules_CentOS/tools/2020.01 pip install .

Quellcode gibt's auf github. Da die Plotting Funktionalität hoffentlich bald in die CM SAF Toolbox eingebaut wird, macht es nicht viel Sinn, die Sachen hier noch auf Cartopy umzuziehen.

TODOs

  • Die NWP Klassen habe ich nur nach ERA5 umbenannt. Da musst Du dir noch was ausdenken, wie Du die am besten an die neue CDS Logik anpasst.
  • claas-get-mars sollte man wohl nach claas-get-nwp umbenennen
  • Bisher war das L2 Gitter (aka area definition) fest verdrahtet (suche nach full_disk) weil statisch. Jetzt ist es zeitabhängig. Das muss berücksichtigt werden.
  • Änderungen am Config File:
    • Die Metadaten für die Produkte (Abschnitt meta_info) müssen noch aktualisiert werden. Im Besten Fall nur Version 003 nach 004 erhöhen.
    • Ebenso müssen die globalen netCDF Attribute (Abschnitt ncattrs) auf den CDOP-3 Standard aktualisiert werden. Das meiste davon hat Irina sicherlich schon recherchiert.
    • In CLAAS-2 hatten wir keinen direkten Zugriff auf die Satelliten-Position jedes Scans. Daher haben wir eine Liste der Maneuver (d.h. permanente Positionsänderungen) im Config File angegeben (Abschnitt platforms). Die brauchen wir jetzt zwar nicht mehr für die eigentliche Prozessierung, aber wir sollten sie trotzem weiter pflegen, denn für einige Tools ist es praktisch die Maneuver offline zu haben ohne alle Daten durchsuchen zu müssen (data availability plots, Aux Daten).
  • Die Reprocessing Datenbank (welcher Satellit welchen Scan aufgenommen hat) muss noch aktualisiert werden (siehe Manual). Zugang zur SKY Datenbank hast Du schon, oder? Die Ursprüngliche Motivation für diese Datenbank war die Reduktion von von ls Aufrufen, weil die bei ECMWF extremst langsam waren. Wenn ich aber weiß, welchen Satellit ich erwarte, kann ich alle Dateinamen vorher bestimmen und direkt drauf zugreifen, anstatt ein ls zu machen. Ich weiß nicht, ob das immer noch ein Problem ist. Falls nicht, könnte man drüber nachdenken, das rauszuwerfen und nur den Teil der Datenbank zu behalten, in dem Prozessierungsfehler gespeichert werden. Das automatische Erkennen der Plattform aus dem Dateinamen ist schon implementiert und wird im ICDR schon verwendet.
  • Ansonsten gibts überall noch #TODO Kommentare im Code, die dich dran erinnern sollen, dass da noch was gemacht werden muss. Wenn was unklar ist einfach fragen!
  • Ich habe in setup.py mal schnell die neuen Requirements reingehackt. Musst mal testen, ob das in Deiner Conda Umgebung Probleme macht und dann die Versionsnummern angeben wo sie noch fehlen.

Scripts

Und noch ein Paar Bemerkungen zu den einzelnen Scripten:

  • claas-domain-bounds: Wird im WUI benutzt, um für eine gegebene lat/lon Box auszurechnen, welche SEVIRI Pixel man ausschneiden muss
  • claas-plot: Wird aktuell im WUI für Quicklooks benutzt. Soll aber von der Toolbox abgelöst werden.
  • claas-cmp: Tool um Produkte verschiedener Runs miteinander zu vergleichen
  • claas-maneuvers: Lädt Orbit Parameter von EUM runter und leitet daraus für jeden Satelliten die Maneuver ab.
  • tools/plot_data_availability.py: Erstellt einen Plot wo man sieht wann welche Plattform auf welcher position operationell war. Wird fürs ATBD gebraucht.

Tips zum Testen

  • cd claas && pip install -e .[plot] . Damit werden nur Links auf Dein Arbeitsverzeichnis installiert. Alle Änderungen am Quellcode werden also sofort wirksam ohne neu installieren zu müssen. Und Du kannst auch direkt testen, wie sich das installierte Paket verhält.
  • Beim Testen nicht vergessen: Du kannst im Config File in der ersten Zeile angeben, welche Abschnitte Du skippen willst. Außerdem kannst Du jedes Script mit --no-checks aufrufen, dann werden die Einträge nicht geprüft.

Dinge, die man bei EUM beachten muss

  • Backup für finale Produkte (~30T) finden, bis der Datensatz released ist und die Produkte in der DWD Datenbank archiviert sind. DWD-ECFS ist leider keine Option.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment