File: conventions.py

package info (click to toggle)
xarray-sentinel 0.9.5%2Bds-4
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 21,540 kB
  • sloc: xml: 77,744; python: 2,076; makefile: 32; sh: 17
file content (124 lines) | stat: -rw-r--r-- 5,595 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
"""CF representation of metadata according to Sentinel-1 Product Specification.

See: S1-RS-MDA-52-7441, DI-MPC-PB, MPC-0240, 3/7, 27/02/2020
https://sentinel.esa.int/documents/247904/1877131/Sentinel-1-Product-Specification
"""

import xarray as xr

from . import __version__

GROUP_ATTRIBUTES = {
    "orbit": {
        "title": "Orbit information used by the IPF during processing",
        "comment": (
            "The dataset contains a sets of orbit state vectors that are updated along azimuth."
            " The values represent the interpolated values used by the IPF"
            " and are derived from the sub-commutated ancillary data from the ISPs"
            " or from an input auxiliary orbit file"
        ),
    },
    "attitude": {
        "title": "Attitude information used by the IPF during processing",
        "comment": (
            "The dataset contains a sets of attitude data records that are updated along azimuth."
            " The values represent the interpolated values used by the IPF"
            " and are derived from the sub-commutated ancillary data from the ISPs"
            " or from an input auxiliary orbit file"
        ),
    },
    "gcp": {
        "title": "Geolocation grid",
        "comment": (
            "The dataset contains geolocation grid point entries for each line/pixel"
            " combination based on a configured resolution."
            " The list contains an entry for each update made along azimuth"
        ),
    },
    "calibration": {
        "title": "Calibration coefficients",
        "comment": (
            "The dataset contains calibration information and the beta nought, sigma nought,"
            " gamma and digital number (DN) Look-up Tables (LUT) that can be used for"
            " absolute product calibration"
        ),
    },
}

VARIABLE_ATTRIBUTES = {
    "line": {"units": "1", "long_name": "product line number"},
    "pixel": {"units": "1", "long_name": "product pixel number"},
    "azimuth_time": {"long_name": "zero-Doppler azimuth time", "standard_name": "time"},
    # NOTE: `slant_range_time` is not expressed as `np.timedelta64[ns]` in order to keep enough
    #   accuracy for interferometric processing, i.e. c * 1ns / 2 ~= 15cm.
    "slant_range_time": {"units": "s", "long_name": "slant range time / two-way delay"},
    "ground_range": {"units": "m", "long_name": "ground range"},
    "axis": {"units": "1", "long_name": "coordinate index"},
    "degree": {"units": "1", "long_name": "polynomial degree"},
    "latitude": {"units": "degrees_north", "long_name": "geodetic latitude"},
    "longitude": {"units": "degrees_east", "long_name": "geodetic longitude"},
    "height": {"units": "m", "long_name": "height above sea level"},
    "incidenceAngle": {"units": "°", "long_name": "incidence angle"},
    "elevationAngle": {"units": "°", "long_name": "elevation angle"},
    "q0": {"units": "1", "long_name": "Q0 attitude quaternion"},
    "q1": {"units": "1", "long_name": "Q1 attitude quaternion"},
    "q2": {"units": "1", "long_name": "Q2 attitude quaternion"},
    "q3": {"units": "1", "long_name": "Q3 attitude quaternion"},
    "roll": {"units": "°", "long_name": "platform roll"},
    "pitch": {"units": "°", "long_name": "platform pitch"},
    "yaw": {"units": "°", "long_name": "platform yaw"},
    "wx": {"units": "° s-1", "long_name": "X component of angular velocity vector"},
    "wy": {"units": "° s-1", "long_name": "Y component of angular velocity vector"},
    "wz": {"units": "° s-1", "long_name": "Z component of angular velocity vector"},
    "position": {"units": "m", "long_name": "ECEF position"},
    "velocity": {"units": "m s-1", "long_name": "ECEF velocity"},
    "sigmaNought": {"units": "m m-1", "long_name": "sigma nought calibration LUT"},
    "betaNought": {"units": "m m-1", "long_name": "beta nought calibration LUT"},
    "gamma": {"units": "m m-1", "long_name": "gamma calibration LUT"},
    "dn": {"units": "1", "long_name": "original digital number calibration LUT"},
    "noiseRangeLut": {"units": "1", "long_name": "range thermal noise correction LUT"},
    "noiseAzimuthLut": {
        "units": "1",
        "long_name": "azimuth thermal noise correction LUT",
    },
    "gr0": {
        "units": "m",
        "long_name": "ground range origin for slant range calculation",
    },
    "grsrCoefficients": {
        "units": "1",
        "long_name": "polynomial to convert from ground range to slant range",
    },
    "sr0": {
        "units": "m",
        "long_name": "slant range origin for ground range calculation",
    },
    "srgrCoefficients": {
        "units": "1",
        "long_name": "polynomial to convert from slant range to ground range",
    },
    "t0": {
        "units": "s",
        "long_name": "Two-way slant range time origin",
    },
    "data_dc_polynomial": {
        "units": "1",
        "long_name": "Coppler centroid estimated from data",
    },
    "azimuth_fm_rate_polynomial": {
        "units": "1",
        "long_name": "Azimuth FM rate coefficient array",
    },
    "measurement": {"units": "1", "long_name": "digital number"},
}


def update_attributes(ds: xr.Dataset, group: str = "") -> xr.Dataset:
    # NOTE: keep the version in sync with the capabilities of CF compliance checkers
    ds.attrs["Conventions"] = "CF-1.8"
    ds.attrs.update(GROUP_ATTRIBUTES.get(group, {}))
    ds.attrs["history"] = f"created by xarray_sentinel-{__version__}"
    for var in ds.variables:
        attrs = VARIABLE_ATTRIBUTES.get(str(var), {})
        ds.variables[var].attrs.update(attrs)
    return ds