From ca031403895b351c957ef69974a04697804c3cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sylvain=20Herl=C3=A9dan?= Date: Tue, 28 Jul 2020 13:07:48 +0200 Subject: [PATCH] Add CDL examples and rationale for alternative format for describing subsampled/compacted variables. --- .../NDVI_grid_mapping_example_compacted.cdl | 56 +++++++++ .../NDVI_latlon_example_compacted.cdl | 48 ++++++++ alternative_format/README.md | 64 ++++++++++ .../multiband_profile_swath.cdl | 49 ++++++++ .../viirs_m_and_i_band_example.cdl | 115 ++++++++++++++++++ 5 files changed, 332 insertions(+) create mode 100644 alternative_format/NDVI_grid_mapping_example_compacted.cdl create mode 100644 alternative_format/NDVI_latlon_example_compacted.cdl create mode 100644 alternative_format/README.md create mode 100644 alternative_format/multiband_profile_swath.cdl create mode 100644 alternative_format/viirs_m_and_i_band_example.cdl diff --git a/alternative_format/NDVI_grid_mapping_example_compacted.cdl b/alternative_format/NDVI_grid_mapping_example_compacted.cdl new file mode 100644 index 0000000..504a8b9 --- /dev/null +++ b/alternative_format/NDVI_grid_mapping_example_compacted.cdl @@ -0,0 +1,56 @@ +netcdf NDVI_grid_mapping_example_compacted { +dimensions: + // NDVI product grid + y = 6 ; + x = 5 ; + // Tie points (tp) + tp_y = 2 ; + tp_x = 2 ; + +variables: + float ndvi(y, x) ; + ndvi:standard_name = "normalized_difference_vegetation_index" ; + ndvi:subsampled_coordinates = "y x" ; + ndvi:grid_mapping = "crs" ; + + int y_indices(tp_y) ; + y_indices:subsamples_dimension = "y" ; + + int x_indices(tp_x) ; + x_indices:subsamples_dimension = "x" ; + + char crs ; + crs:grid_mapping_name = "lambert_conformal_conic" ; + crs:standard_parallel = 25.0 ; + crs:longitude_of_central_meridian = 265.0 ; + crs:latitude_of_projection_origin = 25.0 ; + + char tp_interpolation ; + tp_interpolation:standard_name = "bi_linear" ; + tp_interpolation:formula_terms = "v1: y v2: x" ; + + float y(tp_y) ; + y:standard_name = "projection_y_coordinate" ; + y:units = "km" ; + y:restore_method = "tp_interpolation" ; + y:restore_indices = "tp_y: y_indices" ; + + float x(tp_x) ; + x:standard_name = "projection_x_coordinate" ; + x:units = "km" ; + x:restore_method = "tp_interpolation" ; + x:restore_indices = "tp_x: x_indices" ; + +data: + ndvi = + 0.5119157, 0.04983568, 0.5414233, 0.3076001, 0.8931185, + 0.8581991, 0.7848567, 0.2485297, 0.9762608, 0.4546139, + 0.1063213, 0.8751125, 0.9819403, 0.9346204, 0.2765055, + 0.2011242, 0.7634977, 0.7657007, 0.3465044, 0.9491135, + 0.9431587, 0.04104269, 0.5652257, 0.5340118, 0.8907427, + 0.3514801, 0.1451995, 0.1523716, 0.1563433, 0.7384073 ; + y_indices = 0, 5 ; + x_indices = 0, 4 ; + y = 10, 20 ; + x = 10, 30 ; +} diff --git a/alternative_format/NDVI_latlon_example_compacted.cdl b/alternative_format/NDVI_latlon_example_compacted.cdl new file mode 100644 index 0000000..7e50e12 --- /dev/null +++ b/alternative_format/NDVI_latlon_example_compacted.cdl @@ -0,0 +1,48 @@ +netcdf NDVI_example_compacted { +dimensions: + // NDVI product grid + lat = 6 ; + lon = 5 ; + // Tie points (tp) + tp_lat = 2 ; + tp_lon = 2 ; + +variables: + float ndvi(lat, lon) ; + ndvi : standard_name = "normalized_difference_vegetation_index" ; + + int lat_indices(tp_lat) ; + lat_indices:subsamples_dimension = "lat" ; + + int lon_indices(tp_lon) ; + lon_indices:subsamples_dimension = "lon" ; + + char tp_interpolation ; + tp_interpolation:standard_name = "latlon_interpolation" ; + tp_interpolation:formula_terms = "lat_var: lat lon_var: lon" ; + + float lat(tp_lat) ; + lat:standard_name = "latitude" ; + lat:units = "degrees_north" ; + lat:restore_method = "tp_interpolation" ; + lat:restore_indices = "tp_lat: lat_indices" ; + + float lon(tp_lon) ; + lon:standard_name = "longitude" ; + lon:units = "degrees_east" ; + lon:restore_method = "tp_interpolation" ; + lon:restore_indices = "tp_lon: lon_indices" ; + +data: + ndvi = + 0.5119157, 0.04983568, 0.5414233, 0.3076001, 0.8931185, + 0.8581991, 0.7848567, 0.2485297, 0.9762608, 0.4546139, + 0.1063213, 0.8751125, 0.9819403, 0.9346204, 0.2765055, + 0.2011242, 0.7634977, 0.7657007, 0.3465044, 0.9491135, + 0.9431587, 0.04104269, 0.5652257, 0.5340118, 0.8907427, + 0.3514801, 0.1451995, 0.1523716, 0.1563433, 0.7384073 ; + lat_indices = 0, 5 ; + lon_indices = 0, 4 ; + lat = 10, 20 ; + lon = 10, 30 ; +} diff --git a/alternative_format/README.md b/alternative_format/README.md new file mode 100644 index 0000000..e3a97d2 --- /dev/null +++ b/alternative_format/README.md @@ -0,0 +1,64 @@ +Rationale +========= + +The subsampling/compaction mechanism should have minimal effect on the data +variables that use subsampled/compacted variables as coordinates. + +All the information required to restore the full content of a +subsampled/compacted variable should be attached to this variable, either +directly (attributes) or by transitivity (other variables pointed by +attributes). + +Using subsampled/compacted coordinates +-------------------------------------- +As subsampled/compacted variables are not supported by the standard yet, they +cannot be included in the "coordinates" attribute of variables (backward +compatibility). Another attribute, "subsampled\_coordinates" shall be used for +these subsampled/compacted coordinates variables. + +Mapping subsampled and full dimensions +-------------------------------------- +The relation between subsampled and full dimensions is expressed through +indices variables. The index values contained in these variables refer to the +full dimension indicated in the "subsamples\_dimension" attribute. + +Methods for reconstructing full variables +----------------------------------------- +A container variable (no data, only attributes) is used to describe methods to +reconstruct full data from subsampled/compacted variables. + +These container variables have one mandatory attribute: "standard\_name". +The value of this attribute is a string that identifies the reconstruction +method. The CF conventions must provide a detailed description of the algorithm +attached to each available method. + +If the method accepts parameters, they must be provided with the +"formula\_terms". + +See Annex D for similar examples already in CF conventions: +http://cfconventions.org/Data/cf-conventions/cf-conventions-1.7/build/apd.html + +Reconstructing fuil variables +----------------------------- +Subsampled/compacted variables need two attributes to provides the means for +reconstructing their full content: + * "restore\_method": this attribute must point to the container variable that + describes the reconstruction method. + * "restore\_indices": this attribute must associate each dimension of the + subsampled variable with an indices variable. + +In case additional parameters must be passed to the reconstruction method, they +should be provided with the "restore\_terms" attribute. + +Extra case: shared subsampled coordinates at multiple resolutions +----------------------------------------------------------------- +Subsampled/compacted variables as they are described above can only be used as +coordinates for data variables that share the same full dimensions. + +In case subsampled/compacted coordinates should be shared by data variables +with different full coordinates, i.e. if reconstruction parameters are specific +to the data variables, then the data variable should have an additional +attribute, "restore\_indices\_override", to define its own mapping between +subsampled coordinates and indices variables. + +See the m\_radiance variable in viirs\_m\_and\_i\_band\_example.cdl diff --git a/alternative_format/multiband_profile_swath.cdl b/alternative_format/multiband_profile_swath.cdl new file mode 100644 index 0000000..856f789 --- /dev/null +++ b/alternative_format/multiband_profile_swath.cdl @@ -0,0 +1,49 @@ +netcdf multiband_profile_swath { +dimensions: + track = 5200 ; + scan = 3600 ; + band = 3 ; + press = 2 ; + tp_track = 250 ; + tp_scan = 600 ; +variables: + float swath_data(track, scan, press, band) ; + swath_data:coordinates = "time" ; + swath_data:subsampled_coordinates = "lat lon" ; + + float band(band) ; + band:standard_name = "sensor_band_central_radiation_wavenumber" ; + band:units = "cm-1" ; + + float press(press) ; + press:standard_name = "air_pressure" ; + press:units = "Pa" ; + press:positive = "up" ; + + double time(track, scan) ; + time:standard_name = "time" ; + time:units = " since " ; + time:calendar = "gregorian" ; + + float lat(tp_track, tp_scan) ; + lat:standard_name = "latitude" ; + lat:units = "degrees_north" ; + lat:restore_method = "restore" ; + lat:restore_indices = "tp_track: sub_track tp_scan: sub_scan" ; + + float lon(tp_track, tp_scan) ; + lon:standard_name = "longitude" ; + lon:units = "degrees_east" ; + lon:restore_method = "restore" ; + lon:restore_indices = "tp_track: sub_track tp_scan: sub_scan" ; + + int sub_track(tp_track) ; + sub_track:subsamples_dimension = "track" ; + + int sub_scan(tp_scan) ; + sub_scan:subsamples_dimension = "scan" ; + + char restore ; + restore:standard_name = "lonlat_interpolation" ; + restore:formula_terms = "v1: lon v2: lat v3: 360" ; +} diff --git a/alternative_format/viirs_m_and_i_band_example.cdl b/alternative_format/viirs_m_and_i_band_example.cdl new file mode 100644 index 0000000..bb5e0bf --- /dev/null +++ b/alternative_format/viirs_m_and_i_band_example.cdl @@ -0,0 +1,115 @@ +netcdf VIIRS_M_and_I_Band_example_compacted { +dimensions: + // VIIRS M-Band (750 m resolution imaging) + m_track = 768 ; + m_scan = 3200 ; + m_channel = 16 ; + + // VIIRS I-Band (375 m resolution imaging) + i_track = 1536 ; + i_scan = 6400 ; + i_channel = 5 ; + + // Tie points and interpolation zones (shared between VIIRS M-Band and I-Band) + tp_track = 96 ; + tp_scan = 205 ; + track_interpolation_zone = 48 ; + scan_interpolation_zone = 200 ; + + // Time, stored at scan-start and scan-end of each scan + time_scan = 2 ; + +variables: + + // VIIRS M-Band + float m_radiance(m_track, m_scan, m_channel) ; + m_radiance:subsampled_coordinates = "lat lon time sen_azi_ang sen_zen_ang sol_azi_ang sol_zen_ang" ; + m_radiance:restore_indices_override = "tp_track: m_track_indices tp_scan: m_scan_indices" ; + + int m_track_indices(tp_track) ; + m_track_indices:subsamples_dimension = "m_track" ; + + int m_scan_indices(tp_scan) ; + m_scan_indices:subsamples_dimension = "m_scan" ; + + // VIIRS I-Band + float i_radiance(i_track, i_scan, i_channel) ; + i_radiance:subsampled_coordinates = "lat lon time sen_azi_ang sen_zen_ang sol_azi_ang sol_zen_ang" ; + + int i_track_indices(tp_track) ; + i_track_indices:subsamples_dimension = "i_track" ; + + int i_scan_indices(tp_scan) ; + i_scan_indices:subsamples_dimension = "i_scan" ; + + + // Tie points + float lat(tp_track, tp_scan) ; + lat:standard_name = "latitude" ; + lat:units = "degrees_north" ; + lat:restore_method = "tp_interpolation" ; + lat:restore_indices = "tp_track: i_track_indices tp_scan: i_scan_indices" ; + lat:restore_terms = "lat_var: lat lon_var: lon" ; + + float lon(tp_track, tp_scan) ; + lon:standard_name = "longitude" ; + lon:units = "degrees_east" ; + lon:restore_method = "tp_interpolation" ; + lon:restore_indices = "tp_track: i_track_indices tp_scan: i_scan_indices" ; + lon:restore_terms = "lat_var: lat lon_var: lon" ; + + float sen_azi_ang(tp_track, tp_scan) ; + sen_azi_ang:standard_name = "sensor_azimuth_angle" ; + sen_azi_ang:units = "degrees" ; + sen_azi_ang:restore_method = "tp_interpolation" ; + sen_azi_ang:restore_indices = "tp_track: i_track_indices tp_scan: i_scan_indices" ; + sen_azi_ang:restore_terms = "sen_azi_var: sen_azi_ang sen_zen_var: sen_zen_ang" ; + + float sen_zen_ang(tp_track, tp_scan) ; + sen_zen_ang:standard_name = "sensor_zenith_angle" ; + sen_zen_ang:units = "degrees" ; + sen_zen_ang:restore_method = "tp_interpolation" ; + sen_zen_ang:restore_indices = "tp_track: i_track_indices tp_scan: i_scan_indices" ; + sen_zen_ang:restore_terms = "sen_azi_var: sen_azi_ang sen_zen_var: sen_zen_ang" ; + + float sol_azi_ang(tp_track, tp_scan) ; + sol_azi_ang:standard_name = "solar_azimuth_angle" ; + sol_azi_ang:units = "degrees" ; + sol_azi_ang:restore_method = "tp_interpolation" ; + sol_azi_ang:restore_indices = "tp_track: i_track_indices tp_scan: i_scan_indices" ; + sol_azi_ang:restore_terms = "sol_azi_var: sol_azi_ang sol_zen_var: sol_zen_ang" ; + + float sol_zen_ang(tp_track, tp_scan) ; + sol_zen_ang:standard_name = "solar_zenith_angle" ; + sol_zen_ang:units = "degrees" ; + sol_zen_ang:restore_method = "tp_interpolation" ; + sol_zen_ang:restore_indices = "tp_track: i_track_indices tp_scan: i_scan_indices" ; + sol_zen_ang:restore_terms = "sol_azi_var: sol_azi_ang sol_zen_var: sol_zen_ang" ; + + // Reusable interpolation containers for space and time, shared by VIIRS M-Band and I-Band + char tp_interpolation ; + tp_interpolation:standard_name = "bi_quadratic" ; + tp_interpolation:formula_terms = "ex_track: expansion_coefficient_track al_track: alignment_coefficient_track ex_scan: expansion_coefficient_scan al_scan: alignment_coefficient_scan flags: interpolation_zone_flags" ; + + // Interpolation coefficients and flags + short expansion_coefficient_track(track_interpolation_zone, tp_scan) ; + short alignment_coefficient_track(track_interpolation_zone, tp_scan) ; + short expansion_coefficient_scan(tp_track, scan_interpolation_zone) ; + short alignment_coefficient_scan(tp_track, scan_interpolation_zone) ; + byte interpolation_zone_flags(track_interpolation_zone, scan_interpolation_zone) ; + interpolation_zone_flags:valid_range = "1b, 7b" ; + interpolation_zone_flags:flag_masks = "1b, 2b, 4b" ; + interpolation_zone_flags:flag_meanings = "location_use_cartesian sensor_direction_use_cartesian solar_direction_use_cartesian" ; + + // Time + double t(tp_track, time_scan) ; + t:long_name = "time" ; + t:units = "days since 1990-1-1 0:0:0" ; + t:restore_method = "time_interpolation" ; + t:restore_indices = "tp_track: i_track_indices" ; + + char time_interpolation ; + time_interpolation:standard_name = "linear" ; + time_interpolation:formula_terms = "range_var: t" ; + +}