Aktionen

NetCDF Kompression von Daten durch Aufsammeln: Unterschied zwischen den Versionen

Aus BAWiki

imported>Lang Guenther
(Die LinkTitles-Erweiterung hat automatisch Links zu anderen Seiten hinzugefügt (<a target="_blank" rel="nofollow noreferrer noopener" class="external free" href="https://github.com/bovender/LinkTitles">https://github.com/bovender/LinkTitles</a>).)
 
(13 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 2: Zeile 2:
=Kurze Beschreibung=
=Kurze Beschreibung=


Kompression von Daten durch Aufsammeln. Darunter versteht man den Vorgang, dauerhaft fehlende Daten eines Datensatzes (einer Variablen) vor dem Schreiben der Daten in eine Datei aus dem Datensatz zu entfernen.
Kompression von Daten durch Aufsammeln. Darunter versteht man den Vorgang, dauerhaft fehlende Daten eines Datensatzes (einer Variablen) vor dem Schreiben der Daten aus dem Datensatz zu entfernen.


=Beispiel=
=Beispiel=
==Unkomprimierte Daten==
double lon(lon) ;
:: double Mesh2_poly_salinity_3d(time,poly_depth_3d,nMesh2_poly) ;  
: lon:long_name = "geografische Laenge" ;
::: Mesh2_poly_salinity_3d:standard_name = "'''sea_water_salinity'''" ;  
: lon:units = "degrees_east" ;
::: Mesh2_poly_salinity_3d:long_name = "salinity for 2D mesh polygons, vertically structured" ;  
: lon:axis = "X" ;
::: Mesh2_poly_salinity_3d:units = "0.001" ;
: lon:standard_name = "longitude" ;
::: Mesh2_poly_salinity_3d:coordinates = "Mesh2_poly_lon Mesh2_poly_lat" ;
double lat(lat) ;
::: Mesh2_poly_salinity_3d:_FillValue = ''fillvalue'' ;
: lat:long_name = "geografische Breite" ;
::: Mesh2_poly_salinity_3d:valid_range = ''valid minimum'', ''valid maximum'' ;
: lat:units = "degrees_north" ;
::: Mesh2_poly_salinity_3d:cell_methods = "poly_depth_3d: mean nMesh2_poly: mean" ;
: lat:axis = "Y" ;
::: Mesh2_poly_salinity_3d:cell_measures = "volume: Mesh2_poly_water_volume_3d" ;  
: lat:standard_name = "latitude" ;
::: Mesh2_poly_salinity_3d:grid_mapping = "crs" ;
double depth(depth) ;
: depth:long_name = "Tiefe der Datenpunkte" ;
: depth:units = "m" ;
: depth:axis = "Z" ;
: depth:positive = "down" ;
: depth:bounds = "depth_bnd" ;
: depth:standard_name = "depth" ;
double depth_bnd(depth,Two) ;
double time(time) ;
: time:long_name = "time" ;
: time:units = "seconds since 2005-07-01 00:00:00 01:00" ;
: time:axis = "T" ;
: time:calendar = "gregorian" ;
: time:standard_name = "time" ;
int datapoint(datapoint) ;
: datapoint:long_name = "Kompressionsliste fuer alle Datenpunkte" ;
: datapoint:compress = "depth lat lon" ;
double salinity_3d(time,datapoint) ;
: salinity_3d:long_name = "tiefengemittelter Salzgehalt" ;
: salinity_3d:units = "0.001" ;
: salinity_3d:valid_range = 0., 40. ;
: salinity_3d:_FillValue = 1.e+30 ;
: salinity_3d:coordinates = "time depth lat lon" ;
: salinity_3d:grid_mapping = "Mesh2_crs" ;
: salinity_3d:standard_name = "sea_water_salinity" ;


Für jeden Zeitschritt werden ''poly_depth_3d'' mal ''nMesh2_poly'' Werte erzeugt. Diese Zahl kann bei Verwendung von z-Schichten sehr viel größer als die Anzahl aktiver Datenpunkte sein, da die Anzahl der über einem Polygon befindlichen (aktiven) Datenpunkte von Polygon zu Polygon bei variabler Topografie sehr stark schwanken kann. Mit dieser Definition der Variablen würden dann unnötig viele, dauerhaft ungültige Datenwerte mit ''_FillValue'' in der Datei abgelegt werden.
Hinweise:
# Unkomprimiert wäre salinity_3d(time,depth,lat,lon) zu verwenden.
# Die Koordinatenvariable "datapoint" enthält die (ein-dimensionalen) Speicherindizes der Positionen mit Daten. Indizes beginnen mit Null!
# An Stelle von depth*lat*lon Datenwerten müssen nur datapoint Werte je Zeitschritt geschrieben werden.
# Diese Form der Kompression scheint bislang nur mit ''echten Koordinatenvariablen'', nicht aber mit ''Hilfskoordinatenvariablen'' zu funktionieren.


==Komprimierte Daten==
=Vorgehensweise=
:: double Mesh2_poly_salinity_3d(time,<font color=blue>nMesh2_cell</font>) ;  
==CDL- und Fortran-Syntax==
::: Mesh2_poly_salinity_3d:standard_name = "'''sea_water_salinity'''" ;   
Es soll die Variable "salinity_3d" betrachtet werden.
::: Mesh2_poly_salinity_3d:long_name = "salinity for 2D mesh polygons, vertically structured" ;   
* Deklaration in CDL-Syntax:  
::: Mesh2_poly_salinity_3d:units = "0.001" ;
*: salinity_3d(time,depth,lat,lon);
::: Mesh2_poly_salinity_3d:coordinates = "Mesh2_poly_lon Mesh2_poly_lat" ;
*: ''Bemerkung: Indizes beginnen mit Null!''
::: Mesh2_poly_salinity_3d:_FillValue = ''fillvalue'' ;
* Deklaration in Fortran-Syntax:  
::: Mesh2_poly_salinity_3d:valid_range = ''valid minimum'', ''valid maximum'' ;
*: salinity_3d(lon,lat,depth,time).
::: Mesh2_poly_salinity_3d:cell_methods = "nMesh2_cell: mean" ;
*: ''Bemerkung: Indizes beginnen mit Null!''
::: Mesh2_poly_salinity_3d:cell_measures = "volume: Mesh2_poly_water_volume_3d" ;
Da die benutzte Syntax für die Werte der Kompressionsliste ohne Bedeutung ist, wird nachfolgend die Fortran-Syntax verwendet.
::: Mesh2_poly_salinity_3d:grid_mapping = "crs" ;


Für jeden Zeitschritt werden nur noch ''nMesh2_cell'' Werte erzeugt. Dies entspricht der maximalen Anzahl aktiver Datenpunkte. Hierdurch wird der Speicherplatzbedarf um typischer Weise 60 bis 80 % reduziert. Der Zusammenhang von ''nMesh2_cell'' mit ''poly_depth_3d'' und ''nMesh2_poly'' wird mit Hilfe der (zusätzliche) Koordinatenvariable ''nMesh2_cell'' beschrieben:
==Komprimieren von Daten==
# Maskenfeld mit identischer Gestalt zu den zu komprimierenden Dimensionen,
#: Mask_3d(lon,lat,depth).
# Initialisierung: Mask_3d(:,:,:) = .false. .
# Setze Mask_3d(i,j,k) auf .true., falls die Daten für Position (i,j,k) geschrieben werden sollen.
# Bilde das Feld Mask_3d(:,:,:) auf das Feld Mask(:) ab (Fortran RESHAPE):
#: Mask(lon*lat*depth).
# Die Indizes i mit Mask(i) = .true. ergeben dann die Werte der Kompressionsliste "datapoint".
# Man subtrahiere den Wert 1 von der Kompressionsliste, da alle Indizes mit Null beginnen müssen.
# Packe die zu komprimierenden Daten in das zu schreibende Feld (Fortran PACK) unter Verwendung von Mask_3d( :, : ).


:: integer <font color=blue>nMesh2_cell</font>(<font color=blue>nMesh2_cell</font>) ;
==Dekomprimieren von Daten==
::: nMesh2_cell:compress = "poly_depth_3d nMesh2_poly" ;
# Maskenfelder Mask und Mask_3d:
#: Mask(lon*lat*depth), und
#: Mask_3d(lon,lat,depth).
# Initialisierung: Mask(:) = .false. .
# Man addiere den Wert 1 zur Kompressionsliste "datapoint" hinzu, da alle Indizes mit Null beginnen müssen.
# Für die Werte der Kompressionsliste setze man Mask(i) = .true. .
# Bilde das Feld Mask(:) auf das Feld Mask_3d(:,:,:) ab (Fortran RESHAPE).
# Entpacke die zu dekomprimierenden Daten (Fortran UNPACK) unter Verwendung von Mask_3d(:,:,:) und ''_FillValue''.


Die Koordinatenvariable ''nMesh2_cell'' enthält die Referenzliste der zu speichernden Daten. Die Länge der Liste entspricht dabei der Anzahl der zu speichernden Werte. Die Präsenz des Attributs ''compress'' zeigt an, dass es sich bei dieser Variablen nicht um eine normale Koordinatenvariable sondern um eine Listenvariable handelt. Mit Hilfe der Angabe der originalen Dimensionen sowie der Listewerte kann der exakte Inhalt des unkomprimierten Feldes rekonstruiert werden. Dauerhaft fehlende Werte werden dabei mit ''_FillValue'' aufgefüllt.
=Bekannte Beschränkungen=


=Vorgehensweise=
* Werden in dem oben angegebenen Beispiel an Stelle von (echten) Koordinatenvariablen statt dessen Hilfs-Koordinatenvariablen benutzt, so entspricht dies nach derzeitiger Kenntnis nicht mehr den [http://cf-pcmdi.llnl.gov/ CF-Metadaten-Konvention].


Es soll die Variable "Mesh2_poly_salinity_3d" betrachtet werden.
=Kompression von Variablen beim Schreiben mit NetCDF-4/HDF5=
* Deklaration in CDL-Syntax:
*: Mesh2_poly_salinity_3d(time,poly_depth_3d,nMesh2_poly);
* Deklaration in Fortran-Syntax:
*: Mesh2_poly_salinity_3d(nMesh2_poly,poly_depth_3d,time).
Da die benutzte Syntax für die Werte der Listenvariable ohne Bedeutung ist, wird nachfolgend die Fortran-Syntax wird verwendet.


==Komprimieren von Daten==
Hinweise:
# Man erzeuge ein Maskenfeld mit identischer Gestalt zu den zu komprimierenden Dimensionen,
# Ab Version [[NetCDF]]-4/HDF5 wird Kompression auf Variablenebene beim Schreiben (durch die Software) unterstützt.
#: Mask_3d(poly_depth_3d,nMesh2_poly).
# Bei der [[Definition]] der Variablen mit z. B. [http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-f90/NF90_005fDEF_005fVAR.html#NF90_005fDEF_005fVAR NF90_DEF_VAR] (in Fortran90), können verschiedene Parameter gesetzt werden, mit deren Hilfe eine effektive Reduktion der Datenmenge erzielt werden kann. Man beachte hierbei insbesondere die Hinweise zu dem Parameter "deflate_level".
# Initialisierung: Mask_3d(:,:) = .false. .
# Um diese Kompressionsmethode einsetzen zu können, muss beim Öffnen mit z. B [http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-f90/NF90_005fCREATE.html#NF90_005fCREATE NF90_CREATE] (in Fortran90) das ''Create Mode Flag'' entsprechend gesetzt werden.
# Setze Mask_3d( i, j ) auf .true., falls die Daten für Position ( i, j ) geschrieben werden sollen.
# Derartige Dateien können nicht durch ältere [[NetCDF]]-Implementierungen verarbeitet werden.
# Bilde das Feld Mask_3d(:,:) auf das Feld Mask(:) ab (Fortran RESHAPE):
# Mit dem Werkzeug [http://www.unidata.ucar.edu/software/netcdf/docs/netcdf/nccopy.html#nccopy nccopy] können allerdings auch Konversionen zwischen verschiedenen [[NetCDF]]-Formaten vorgenommen werden, so z. B. von ''neuen'' in ''alte'' [[NetCDF]]-Formate.
#: Mask(poly_depth_3d*nMesh_poly).
# Die Indizes i mit Mask( i ) = .true. ergeben dann die Werte der Listenvariablen.
# Packe die zu komprimierenden Daten in das Ergebnisfeld (Fortran PACK) unter Verwendung von Mask_3d(:,:).


==Dekomprimieren von Daten==


----
----

Aktuelle Version vom 21. Oktober 2022, 09:30 Uhr

Kurze Beschreibung

Kompression von Daten durch Aufsammeln. Darunter versteht man den Vorgang, dauerhaft fehlende Daten eines Datensatzes (einer Variablen) vor dem Schreiben der Daten aus dem Datensatz zu entfernen.

Beispiel

double lon(lon) ;

lon:long_name = "geografische Laenge" ;
lon:units = "degrees_east" ;
lon:axis = "X" ;
lon:standard_name = "longitude" ;

double lat(lat) ;

lat:long_name = "geografische Breite" ;
lat:units = "degrees_north" ;
lat:axis = "Y" ;
lat:standard_name = "latitude" ;

double depth(depth) ;

depth:long_name = "Tiefe der Datenpunkte" ;
depth:units = "m" ;
depth:axis = "Z" ;
depth:positive = "down" ;
depth:bounds = "depth_bnd" ;
depth:standard_name = "depth" ;

double depth_bnd(depth,Two) ; double time(time) ;

time:long_name = "time" ;
time:units = "seconds since 2005-07-01 00:00:00 01:00" ;
time:axis = "T" ;
time:calendar = "gregorian" ;
time:standard_name = "time" ;

int datapoint(datapoint) ;

datapoint:long_name = "Kompressionsliste fuer alle Datenpunkte" ;
datapoint:compress = "depth lat lon" ;

double salinity_3d(time,datapoint) ;

salinity_3d:long_name = "tiefengemittelter Salzgehalt" ;
salinity_3d:units = "0.001" ;
salinity_3d:valid_range = 0., 40. ;
salinity_3d:_FillValue = 1.e+30 ;
salinity_3d:coordinates = "time depth lat lon" ;
salinity_3d:grid_mapping = "Mesh2_crs" ;
salinity_3d:standard_name = "sea_water_salinity" ;

Hinweise:

  1. Unkomprimiert wäre salinity_3d(time,depth,lat,lon) zu verwenden.
  2. Die Koordinatenvariable "datapoint" enthält die (ein-dimensionalen) Speicherindizes der Positionen mit Daten. Indizes beginnen mit Null!
  3. An Stelle von depth*lat*lon Datenwerten müssen nur datapoint Werte je Zeitschritt geschrieben werden.
  4. Diese Form der Kompression scheint bislang nur mit echten Koordinatenvariablen, nicht aber mit Hilfskoordinatenvariablen zu funktionieren.

Vorgehensweise

CDL- und Fortran-Syntax

Es soll die Variable "salinity_3d" betrachtet werden.

  • Deklaration in CDL-Syntax:
    salinity_3d(time,depth,lat,lon);
    Bemerkung: Indizes beginnen mit Null!
  • Deklaration in Fortran-Syntax:
    salinity_3d(lon,lat,depth,time).
    Bemerkung: Indizes beginnen mit Null!

Da die benutzte Syntax für die Werte der Kompressionsliste ohne Bedeutung ist, wird nachfolgend die Fortran-Syntax verwendet.

Komprimieren von Daten

  1. Maskenfeld mit identischer Gestalt zu den zu komprimierenden Dimensionen,
    Mask_3d(lon,lat,depth).
  2. Initialisierung: Mask_3d(:,:,:) = .false. .
  3. Setze Mask_3d(i,j,k) auf .true., falls die Daten für Position (i,j,k) geschrieben werden sollen.
  4. Bilde das Feld Mask_3d(:,:,:) auf das Feld Mask(:) ab (Fortran RESHAPE):
    Mask(lon*lat*depth).
  5. Die Indizes i mit Mask(i) = .true. ergeben dann die Werte der Kompressionsliste "datapoint".
  6. Man subtrahiere den Wert 1 von der Kompressionsliste, da alle Indizes mit Null beginnen müssen.
  7. Packe die zu komprimierenden Daten in das zu schreibende Feld (Fortran PACK) unter Verwendung von Mask_3d( :, : ).

Dekomprimieren von Daten

  1. Maskenfelder Mask und Mask_3d:
    Mask(lon*lat*depth), und
    Mask_3d(lon,lat,depth).
  2. Initialisierung: Mask(:) = .false. .
  3. Man addiere den Wert 1 zur Kompressionsliste "datapoint" hinzu, da alle Indizes mit Null beginnen müssen.
  4. Für die Werte der Kompressionsliste setze man Mask(i) = .true. .
  5. Bilde das Feld Mask(:) auf das Feld Mask_3d(:,:,:) ab (Fortran RESHAPE).
  6. Entpacke die zu dekomprimierenden Daten (Fortran UNPACK) unter Verwendung von Mask_3d(:,:,:) und _FillValue.

Bekannte Beschränkungen

  • Werden in dem oben angegebenen Beispiel an Stelle von (echten) Koordinatenvariablen statt dessen Hilfs-Koordinatenvariablen benutzt, so entspricht dies nach derzeitiger Kenntnis nicht mehr den CF-Metadaten-Konvention.

Kompression von Variablen beim Schreiben mit NetCDF-4/HDF5

Hinweise:

  1. Ab Version NetCDF-4/HDF5 wird Kompression auf Variablenebene beim Schreiben (durch die Software) unterstützt.
  2. Bei der Definition der Variablen mit z. B. NF90_DEF_VAR (in Fortran90), können verschiedene Parameter gesetzt werden, mit deren Hilfe eine effektive Reduktion der Datenmenge erzielt werden kann. Man beachte hierbei insbesondere die Hinweise zu dem Parameter "deflate_level".
  3. Um diese Kompressionsmethode einsetzen zu können, muss beim Öffnen mit z. B NF90_CREATE (in Fortran90) das Create Mode Flag entsprechend gesetzt werden.
  4. Derartige Dateien können nicht durch ältere NetCDF-Implementierungen verarbeitet werden.
  5. Mit dem Werkzeug nccopy können allerdings auch Konversionen zwischen verschiedenen NetCDF-Formaten vorgenommen werden, so z. B. von neuen in alte NetCDF-Formate.



zurück zu NetCDF


Strukturübersicht