s1-denoise 0.0.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- s1_denoise/__init__.py +18 -0
- s1_denoise/__main__.py +36 -0
- s1_denoise/auxiliary_files.py +481 -0
- s1_denoise/baq_decoder.py +203 -0
- s1_denoise/cli.py +118 -0
- s1_denoise/error_calculation.py +262 -0
- s1_denoise/jo_parser.py +295 -0
- s1_denoise/l0_noise_power_calculation.py +399 -0
- s1_denoise/logger.py +81 -0
- s1_denoise/noise_norm_factor.py +291 -0
- s1_denoise/noise_profiles.py +292 -0
- s1_denoise/output.py +551 -0
- s1_denoise/s1safe.py +1415 -0
- s1_denoise/thermal_noise.py +753 -0
- s1_denoise/utils.py +282 -0
- s1_denoise/xml_reader.py +571 -0
- s1_denoise-0.0.0.dev0.dist-info/METADATA +147 -0
- s1_denoise-0.0.0.dev0.dist-info/RECORD +21 -0
- s1_denoise-0.0.0.dev0.dist-info/WHEEL +4 -0
- s1_denoise-0.0.0.dev0.dist-info/entry_points.txt +2 -0
- s1_denoise-0.0.0.dev0.dist-info/licenses/LICENSE +21 -0
s1_denoise/__init__.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Aresys S.r.l. <info@aresys.it>
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Configuration and constants module for the S1 L1N processor.
|
|
6
|
+
|
|
7
|
+
Defines the package version, the processor name used in log records, the reference slant range ``R_REF``
|
|
8
|
+
(in meters) and the noise pulse outlier detection bounds ``NOISE_LOWER_BOUND`` / ``NOISE_UPPER_BOUND`` (in dB).
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
__version__ = '0.0.0.dev0'
|
|
12
|
+
|
|
13
|
+
PROCESSOR_NAME = 's1_l1n_processor'
|
|
14
|
+
|
|
15
|
+
# CONSTANTS
|
|
16
|
+
R_REF = 8e5 # [m]
|
|
17
|
+
|
|
18
|
+
NOISE_LOWER_BOUND, NOISE_UPPER_BOUND = 3.0, 1.0 # [dB] bounds for noise pulse outlier detection
|
s1_denoise/__main__.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Aresys S.r.l. <info@aresys.it>
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
"""Entry point module for the denoising command-line interface."""
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
import click
|
|
8
|
+
|
|
9
|
+
from s1_denoise.cli import denoise_cli
|
|
10
|
+
|
|
11
|
+
def main():
|
|
12
|
+
"""
|
|
13
|
+
Run the denoising CLI, mapping Click errors to exit code 128.
|
|
14
|
+
|
|
15
|
+
The command is invoked with ``standalone_mode=False`` so that Click usage errors and user aborts are
|
|
16
|
+
reported here and terminate the processor with exit code 128 instead of Click's default exit codes.
|
|
17
|
+
|
|
18
|
+
Raises
|
|
19
|
+
------
|
|
20
|
+
SystemExit
|
|
21
|
+
With code 128 on a Click usage error or abort; exit codes raised by the CLI itself are propagated.
|
|
22
|
+
"""
|
|
23
|
+
# standalone_mode=False lets click errors (e.g. invalid arguments) propagate,
|
|
24
|
+
# so that the processor exits with code 128 also in these cases
|
|
25
|
+
try:
|
|
26
|
+
denoise_cli(standalone_mode=False)
|
|
27
|
+
except click.ClickException as e:
|
|
28
|
+
e.show()
|
|
29
|
+
sys.exit(128)
|
|
30
|
+
except click.Abort:
|
|
31
|
+
click.echo("Aborted!", err=True)
|
|
32
|
+
sys.exit(128)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if __name__ == "__main__":
|
|
36
|
+
main()
|
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Aresys S.r.l. <info@aresys.it>
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Provide the AuxiliaryFiles class for parsing and accessing the Sentinel-1 auxiliary files (AUX_CAL, AUX_PP1,
|
|
6
|
+
AUX_INS).
|
|
7
|
+
|
|
8
|
+
Handles the reading of calibration parameters, processing parameters, application LUTs and internal calibration
|
|
9
|
+
references, exposing them through dedicated getter methods for use in the denoising pipeline.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from lxml import etree
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
import numpy as np
|
|
15
|
+
import sys
|
|
16
|
+
|
|
17
|
+
from s1_denoise.logger import denoise_logger
|
|
18
|
+
|
|
19
|
+
class AuxiliaryFiles:
|
|
20
|
+
"""
|
|
21
|
+
Parsed content of the AUX_PP1, AUX_CAL and AUX_INS auxiliary files of a mission.
|
|
22
|
+
|
|
23
|
+
All three files are read at construction time.
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
mission_id : str
|
|
28
|
+
Mission identifier (e.g. ``"S1A"``), used to build the auxiliary file names.
|
|
29
|
+
pp1_path : pathlib.Path
|
|
30
|
+
Path of the AUX_PP1 SAFE directory, containing ``data/<mission>-aux-pp1.xml``.
|
|
31
|
+
cal_path : pathlib.Path
|
|
32
|
+
Path of the AUX_CAL SAFE directory, containing ``data/<mission>-aux-cal.xml``.
|
|
33
|
+
ins_path : pathlib.Path
|
|
34
|
+
Path of the AUX_INS SAFE directory, containing ``data/<mission>-aux-ins.xml``.
|
|
35
|
+
|
|
36
|
+
Attributes
|
|
37
|
+
----------
|
|
38
|
+
mission_id : str
|
|
39
|
+
Mission identifier.
|
|
40
|
+
pp1_filepath, cal_filepath, ins_filepath : pathlib.Path
|
|
41
|
+
Paths of the AUX_PP1, AUX_CAL and AUX_INS XML files.
|
|
42
|
+
calibration_parameters : dict
|
|
43
|
+
AUX_CAL calibration parameters, keyed by ``(swath, polarisation)``.
|
|
44
|
+
processing_parameters : dict
|
|
45
|
+
AUX_PP1 processing parameters (``"gain"`` and ``"alpha_value"``), keyed by ``(product_id, swath)``.
|
|
46
|
+
app_lut_values : dict
|
|
47
|
+
AUX_PP1 scaling LUTs, keyed by application LUT identifier.
|
|
48
|
+
pg_references : dict
|
|
49
|
+
AUX_INS ``pgReference`` XML elements, keyed by ``(swath, polarisation)``.
|
|
50
|
+
expected_noise_values : dict
|
|
51
|
+
AUX_INS expected ``noise`` XML elements, keyed by ``(swath, polarisation)``.
|
|
52
|
+
azimuth_steering_rates : dict
|
|
53
|
+
AUX_INS azimuth steering rates [deg/s], keyed by swath.
|
|
54
|
+
|
|
55
|
+
Raises
|
|
56
|
+
------
|
|
57
|
+
SystemExit
|
|
58
|
+
If any of the auxiliary files contains no usable entries (exit code 128).
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
def __init__(self, mission_id, pp1_path: Path, cal_path: Path, ins_path: Path):
|
|
62
|
+
|
|
63
|
+
self.mission_id = mission_id
|
|
64
|
+
self.pp1_filepath = pp1_path / f'data/{self.mission_id.lower()}-aux-pp1.xml'
|
|
65
|
+
self.cal_filepath = cal_path / f'data/{self.mission_id.lower()}-aux-cal.xml'
|
|
66
|
+
self.ins_filepath = ins_path / f'data/{self.mission_id.lower()}-aux-ins.xml'
|
|
67
|
+
|
|
68
|
+
self.calibration_parameters = {}
|
|
69
|
+
self.read_from_aux_cal()
|
|
70
|
+
|
|
71
|
+
self.processing_parameters = {}
|
|
72
|
+
self.app_lut_values = {}
|
|
73
|
+
self.read_from_aux_pp1()
|
|
74
|
+
|
|
75
|
+
self.pg_references = {}
|
|
76
|
+
self.expected_noise_values = {}
|
|
77
|
+
self.azimuth_steering_rates = {}
|
|
78
|
+
self.read_from_aux_ins()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def read_from_aux_cal(self):
|
|
82
|
+
"""
|
|
83
|
+
Read the calibration parameters from the AUX_CAL file into `calibration_parameters`.
|
|
84
|
+
|
|
85
|
+
For each ``(swath, polarisation)``, the azimuth antenna pattern values and count, the azimuth angle increment, the
|
|
86
|
+
noise calibration factor and the absolute calibration constant are stored.
|
|
87
|
+
|
|
88
|
+
Raises
|
|
89
|
+
------
|
|
90
|
+
SystemExit
|
|
91
|
+
If no calibration parameters are found (exit code 128).
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
tree = etree.parse(self.cal_filepath.resolve())
|
|
95
|
+
root = tree.getroot()
|
|
96
|
+
|
|
97
|
+
for cal_params in root.findall(".//calibrationParams"):
|
|
98
|
+
swath = cal_params.find("swath").text
|
|
99
|
+
polarisation = cal_params.find("polarisation").text
|
|
100
|
+
aap_values = cal_params.find("azimuthAntennaPattern/values")
|
|
101
|
+
aap_values_text = aap_values.text.strip()
|
|
102
|
+
|
|
103
|
+
self.calibration_parameters[(swath, polarisation)] = {
|
|
104
|
+
"aap_gain_count": int(aap_values.attrib['count']),
|
|
105
|
+
"aap_gain": [float(val) for val in aap_values_text.split()],
|
|
106
|
+
"azi_angle_incr": float(cal_params.find("azimuthAntennaPattern/azimuthAngleIncrement").text),
|
|
107
|
+
"noise_calibration_factor": float(cal_params.find("noiseCalibrationFactor").text),
|
|
108
|
+
"absolute_calibration_constant": float(cal_params.find("absoluteCalibrationConstant").text)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
# if no matching swath/polarisation is found
|
|
112
|
+
if not self.calibration_parameters:
|
|
113
|
+
denoise_logger.error(f"Error reading calibration file. Aborting...")
|
|
114
|
+
sys.exit(128)
|
|
115
|
+
|
|
116
|
+
def read_from_aux_pp1(self):
|
|
117
|
+
"""
|
|
118
|
+
Read the application LUTs and the processing parameters from the AUX_PP1 file.
|
|
119
|
+
|
|
120
|
+
Scaling LUTs are stored in `app_lut_values`; the per-swath gains (``swathParams``) and azimuth window coefficients
|
|
121
|
+
(``azimuthParams``) are stored in `processing_parameters`.
|
|
122
|
+
|
|
123
|
+
Raises
|
|
124
|
+
------
|
|
125
|
+
SystemExit
|
|
126
|
+
If no processing parameters are found (exit code 128).
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
tree = etree.parse(self.pp1_filepath.resolve())
|
|
130
|
+
root = tree.getroot()
|
|
131
|
+
|
|
132
|
+
for app_lut in root.findall(".//applicationLut"):
|
|
133
|
+
app_id = app_lut.findtext("applicationLutId")
|
|
134
|
+
scaling_luts = []
|
|
135
|
+
|
|
136
|
+
for lut in app_lut.findall("scalingLutList/scalingLut"):
|
|
137
|
+
output_pixels = lut.findtext("outputPixels")
|
|
138
|
+
inc_angle_start = float(lut.findtext("incidenceAngleStart"))
|
|
139
|
+
angle_increment = float(lut.findtext("angleIncrement"))
|
|
140
|
+
|
|
141
|
+
# Split and convert numeric values
|
|
142
|
+
values_text = lut.findtext("values")
|
|
143
|
+
values = [float(v) for v in values_text.split()] if values_text else []
|
|
144
|
+
|
|
145
|
+
scaling_luts.append({
|
|
146
|
+
"outputPixels": output_pixels,
|
|
147
|
+
"incidenceAngleStart": inc_angle_start,
|
|
148
|
+
"angleIncrement": angle_increment,
|
|
149
|
+
"values": values
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
self.app_lut_values.update({
|
|
153
|
+
app_id: scaling_luts
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
# Find the calibrationParams
|
|
157
|
+
for product in root.findall(".//product"):
|
|
158
|
+
prod_id = product.find("productId").text
|
|
159
|
+
|
|
160
|
+
for swath_param in product.findall(".//swathParams"): # swathParams is present only in slcProcParams
|
|
161
|
+
swath = swath_param.find("swath").text
|
|
162
|
+
|
|
163
|
+
# for pol in pp1_gain_map:
|
|
164
|
+
self.processing_parameters[(prod_id, swath)] = {
|
|
165
|
+
"gain": list(swath_param.find("gain").text.split())
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
for azi_param in product.findall('.//azimuthParams'): # azimuthParams is present only in postProcParams
|
|
169
|
+
swath = azi_param.find("swath").text
|
|
170
|
+
self.processing_parameters[(prod_id, swath)].update({
|
|
171
|
+
"alpha_value": float(azi_param.find('windowCoefficient').text)
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
# if no matching swath/polarisation is found
|
|
176
|
+
if not self.processing_parameters:
|
|
177
|
+
denoise_logger.error(f"Error reading PP1 file. Aborting...")
|
|
178
|
+
sys.exit(128)
|
|
179
|
+
|
|
180
|
+
def read_from_aux_ins(self):
|
|
181
|
+
"""
|
|
182
|
+
Read the internal calibration parameters and azimuth steering rates from the AUX_INS file.
|
|
183
|
+
|
|
184
|
+
PG references and expected noise values are stored in `pg_references` and `expected_noise_values`; azimuth
|
|
185
|
+
steering rates [deg/s] in `azimuth_steering_rates`.
|
|
186
|
+
|
|
187
|
+
Raises
|
|
188
|
+
------
|
|
189
|
+
SystemExit
|
|
190
|
+
If no internal calibration parameters are found (exit code 128).
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
tree = etree.parse(self.ins_filepath.resolve())
|
|
194
|
+
root = tree.getroot()
|
|
195
|
+
|
|
196
|
+
for int_cal_param in root.findall(".//internalCalibrationParams"):
|
|
197
|
+
swath = int_cal_param.findtext("swath")
|
|
198
|
+
pol = int_cal_param.findtext("polarisation")
|
|
199
|
+
pg_ref = int_cal_param.find("pgReference")
|
|
200
|
+
expected_noise = int_cal_param.find("noise")
|
|
201
|
+
|
|
202
|
+
self.pg_references.update({
|
|
203
|
+
(swath, pol): pg_ref
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
self.expected_noise_values.update({
|
|
207
|
+
(swath, pol): expected_noise
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
for swath_param in root.findall(".//swathParams"):
|
|
211
|
+
swath = swath_param.findtext("swath")
|
|
212
|
+
steering_rate = swath_param.findtext("radarParams/azimuthSteeringRate")
|
|
213
|
+
|
|
214
|
+
if steering_rate is not None:
|
|
215
|
+
self.azimuth_steering_rates.update({
|
|
216
|
+
swath: float(steering_rate) # [deg/s]
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
# if no matching swath/polarisation is found
|
|
220
|
+
if not self.pg_references:
|
|
221
|
+
denoise_logger.error(f"Error reading INS file. Aborting...")
|
|
222
|
+
sys.exit(128)
|
|
223
|
+
|
|
224
|
+
def get_gain_from_pp1(self, product_id, subswath, pol):
|
|
225
|
+
"""
|
|
226
|
+
Return the processing gain from AUX_PP1 for a product type, subswath and polarization.
|
|
227
|
+
|
|
228
|
+
Parameters
|
|
229
|
+
----------
|
|
230
|
+
product_id : str
|
|
231
|
+
AUX_PP1 product identifier (e.g. ``"IW_SLC__1"``).
|
|
232
|
+
subswath : str
|
|
233
|
+
Subswath identifier.
|
|
234
|
+
pol : str
|
|
235
|
+
Polarization, one of ``"HH"``, ``"HV"``, ``"VV"``, ``"VH"``.
|
|
236
|
+
|
|
237
|
+
Returns
|
|
238
|
+
-------
|
|
239
|
+
float
|
|
240
|
+
Gain value.
|
|
241
|
+
"""
|
|
242
|
+
|
|
243
|
+
pp1_gain_map = {
|
|
244
|
+
"HH": 0,
|
|
245
|
+
"HV": 1,
|
|
246
|
+
"VV": 2,
|
|
247
|
+
"VH": 3
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
gain_value = float(self.processing_parameters.get((product_id, subswath))['gain'][pp1_gain_map[pol]])
|
|
251
|
+
denoise_logger.debug(f"Gain value from AUX_PP1: {gain_value}")
|
|
252
|
+
|
|
253
|
+
return gain_value
|
|
254
|
+
|
|
255
|
+
def get_alpha_from_pp1(self, product_id, subswath):
|
|
256
|
+
"""
|
|
257
|
+
Return the azimuth window coefficients (``windowCoefficient``) from AUX_PP1.
|
|
258
|
+
|
|
259
|
+
Parameters
|
|
260
|
+
----------
|
|
261
|
+
product_id : str
|
|
262
|
+
AUX_PP1 product identifier (e.g. ``"IW_GRDH_1"``).
|
|
263
|
+
subswath : str
|
|
264
|
+
Subswath identifier.
|
|
265
|
+
|
|
266
|
+
Returns
|
|
267
|
+
-------
|
|
268
|
+
alpha_value : float
|
|
269
|
+
Window coefficient of the given product type.
|
|
270
|
+
slc_alpha_value : float
|
|
271
|
+
Window coefficient of the SLC product of the same mode (``<mode>_SLC__1``).
|
|
272
|
+
"""
|
|
273
|
+
|
|
274
|
+
alpha_value = float(self.processing_parameters.get((product_id, subswath))['alpha_value'])
|
|
275
|
+
slc_alpha_value = float(self.processing_parameters.get((product_id[:2] + '_SLC__1', subswath))['alpha_value'])
|
|
276
|
+
denoise_logger.debug(f"Window coefficient for {product_id}, {subswath}: {alpha_value}")
|
|
277
|
+
|
|
278
|
+
return alpha_value, slc_alpha_value
|
|
279
|
+
|
|
280
|
+
def get_abs_cal(self, swath: str, polarisation: str) -> float:
|
|
281
|
+
"""
|
|
282
|
+
Return the absolute calibration constant from AUX_CAL.
|
|
283
|
+
|
|
284
|
+
Parameters
|
|
285
|
+
----------
|
|
286
|
+
swath : str
|
|
287
|
+
Swath identifier.
|
|
288
|
+
polarisation : str
|
|
289
|
+
Polarization (e.g. ``"VV"``).
|
|
290
|
+
|
|
291
|
+
Returns
|
|
292
|
+
-------
|
|
293
|
+
float
|
|
294
|
+
Absolute calibration constant.
|
|
295
|
+
"""
|
|
296
|
+
|
|
297
|
+
acf = float(self.calibration_parameters.get((swath, polarisation))['absolute_calibration_constant'])
|
|
298
|
+
return acf
|
|
299
|
+
|
|
300
|
+
def get_noise_cal(self, swath: str, polarisation: str) -> float:
|
|
301
|
+
"""
|
|
302
|
+
Return the noise calibration factor k_N from AUX_CAL.
|
|
303
|
+
|
|
304
|
+
Parameters
|
|
305
|
+
----------
|
|
306
|
+
swath : str
|
|
307
|
+
Swath identifier.
|
|
308
|
+
polarisation : str
|
|
309
|
+
Polarization (e.g. ``"VV"``).
|
|
310
|
+
|
|
311
|
+
Returns
|
|
312
|
+
-------
|
|
313
|
+
float
|
|
314
|
+
Noise calibration factor.
|
|
315
|
+
"""
|
|
316
|
+
|
|
317
|
+
k_n = float(self.calibration_parameters.get((swath, polarisation))['noise_calibration_factor'])
|
|
318
|
+
return k_n
|
|
319
|
+
|
|
320
|
+
def get_aap_gain(self, swath, polarisation):
|
|
321
|
+
"""
|
|
322
|
+
Return the azimuth antenna pattern values from AUX_CAL.
|
|
323
|
+
|
|
324
|
+
Parameters
|
|
325
|
+
----------
|
|
326
|
+
swath : str
|
|
327
|
+
Swath identifier.
|
|
328
|
+
polarisation : str
|
|
329
|
+
Polarization (e.g. ``"VV"``).
|
|
330
|
+
|
|
331
|
+
Returns
|
|
332
|
+
-------
|
|
333
|
+
numpy.ndarray
|
|
334
|
+
Azimuth antenna pattern values, as annotated (dB).
|
|
335
|
+
"""
|
|
336
|
+
|
|
337
|
+
aap_gain = np.array(self.calibration_parameters.get((swath, polarisation))['aap_gain'])
|
|
338
|
+
return aap_gain
|
|
339
|
+
|
|
340
|
+
def get_aap_gain_count(self, swath, polarisation):
|
|
341
|
+
"""
|
|
342
|
+
Return the number of azimuth antenna pattern values from AUX_CAL.
|
|
343
|
+
|
|
344
|
+
Parameters
|
|
345
|
+
----------
|
|
346
|
+
swath : str
|
|
347
|
+
Swath identifier.
|
|
348
|
+
polarisation : str
|
|
349
|
+
Polarization (e.g. ``"VV"``).
|
|
350
|
+
|
|
351
|
+
Returns
|
|
352
|
+
-------
|
|
353
|
+
int
|
|
354
|
+
Number of azimuth antenna pattern values.
|
|
355
|
+
"""
|
|
356
|
+
|
|
357
|
+
aap_gain_count = int(self.calibration_parameters.get((swath, polarisation))['aap_gain_count'])
|
|
358
|
+
return aap_gain_count
|
|
359
|
+
|
|
360
|
+
def get_azi_angle_incr(self, swath, polarisation):
|
|
361
|
+
"""
|
|
362
|
+
Return the azimuth angle increment of the azimuth antenna pattern from AUX_CAL.
|
|
363
|
+
|
|
364
|
+
Parameters
|
|
365
|
+
----------
|
|
366
|
+
swath : str
|
|
367
|
+
Swath identifier.
|
|
368
|
+
polarisation : str
|
|
369
|
+
Polarization (e.g. ``"VV"``).
|
|
370
|
+
|
|
371
|
+
Returns
|
|
372
|
+
-------
|
|
373
|
+
float
|
|
374
|
+
Azimuth angle increment, as annotated.
|
|
375
|
+
"""
|
|
376
|
+
|
|
377
|
+
azi_angle_incr = float(self.calibration_parameters.get((swath, polarisation))['azi_angle_incr'])
|
|
378
|
+
return azi_angle_incr
|
|
379
|
+
|
|
380
|
+
def get_dn_value(self, mode, product_type):
|
|
381
|
+
"""
|
|
382
|
+
Return the digital number scaling value (betaNought * calibrationFactor) from the AUX_PP1 application LUT.
|
|
383
|
+
|
|
384
|
+
The first value of the ``<mode>_Default`` scaling LUT matching the output pixel type of the product is returned:
|
|
385
|
+
16 bit signed integer for SLC, 16 bit unsigned integer for GRD, 8 bit unsigned integer otherwise.
|
|
386
|
+
|
|
387
|
+
Parameters
|
|
388
|
+
----------
|
|
389
|
+
mode : str
|
|
390
|
+
Acquisition mode (e.g. ``"IW"``).
|
|
391
|
+
product_type : str
|
|
392
|
+
Product type (e.g. ``"SLC"``, ``"GRDH"``).
|
|
393
|
+
|
|
394
|
+
Returns
|
|
395
|
+
-------
|
|
396
|
+
float
|
|
397
|
+
Digital number value, used to scale the output noise vectors.
|
|
398
|
+
"""
|
|
399
|
+
|
|
400
|
+
if product_type == "SLC":
|
|
401
|
+
output_pixels = "16 bit Signed Integer"
|
|
402
|
+
elif product_type.startswith("GRD"):
|
|
403
|
+
output_pixels = "16 bit Unsigned Integer"
|
|
404
|
+
else:
|
|
405
|
+
output_pixels = "8 bit Unsigned Integer"
|
|
406
|
+
|
|
407
|
+
dn_value = next(
|
|
408
|
+
(d["values"][0] for d in self.app_lut_values[f"{mode}_Default"] if d["outputPixels"] == output_pixels),
|
|
409
|
+
None
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
return float(dn_value)
|
|
414
|
+
|
|
415
|
+
def get_pg_reference(self, swath, polarisation):
|
|
416
|
+
"""
|
|
417
|
+
Return the magnitude of the PG reference from AUX_INS.
|
|
418
|
+
|
|
419
|
+
Parameters
|
|
420
|
+
----------
|
|
421
|
+
swath : str
|
|
422
|
+
Swath identifier.
|
|
423
|
+
polarisation : str
|
|
424
|
+
Polarization (e.g. ``"VV"``).
|
|
425
|
+
|
|
426
|
+
Returns
|
|
427
|
+
-------
|
|
428
|
+
float
|
|
429
|
+
Euclidean norm of the two ``pgReference`` components.
|
|
430
|
+
"""
|
|
431
|
+
|
|
432
|
+
val = np.array([float(self.pg_references.get((swath, polarisation))[0].text),
|
|
433
|
+
float(self.pg_references.get((swath, polarisation))[1].text)])
|
|
434
|
+
|
|
435
|
+
return np.linalg.norm(val)
|
|
436
|
+
|
|
437
|
+
def get_expected_noise_value(self, swath, polarisation):
|
|
438
|
+
"""
|
|
439
|
+
Return the expected noise power from AUX_INS, used as reference for noise pulse outlier rejection.
|
|
440
|
+
|
|
441
|
+
Parameters
|
|
442
|
+
----------
|
|
443
|
+
swath : str
|
|
444
|
+
Swath identifier.
|
|
445
|
+
polarisation : str
|
|
446
|
+
Polarization (e.g. ``"VV"``).
|
|
447
|
+
|
|
448
|
+
Returns
|
|
449
|
+
-------
|
|
450
|
+
float
|
|
451
|
+
Expected noise power (linear scale).
|
|
452
|
+
"""
|
|
453
|
+
|
|
454
|
+
val = float(self.expected_noise_values.get((swath, polarisation)).text)
|
|
455
|
+
|
|
456
|
+
return val
|
|
457
|
+
|
|
458
|
+
def get_azimuth_steering_rate(self, swath):
|
|
459
|
+
"""
|
|
460
|
+
Return the azimuth antenna steering rate from AUX_INS.
|
|
461
|
+
|
|
462
|
+
Parameters
|
|
463
|
+
----------
|
|
464
|
+
swath : str
|
|
465
|
+
Swath identifier.
|
|
466
|
+
|
|
467
|
+
Returns
|
|
468
|
+
-------
|
|
469
|
+
float
|
|
470
|
+
Azimuth steering rate [rad/s].
|
|
471
|
+
|
|
472
|
+
Raises
|
|
473
|
+
------
|
|
474
|
+
ValueError
|
|
475
|
+
If no steering rate is annotated for `swath`.
|
|
476
|
+
"""
|
|
477
|
+
|
|
478
|
+
if swath not in self.azimuth_steering_rates:
|
|
479
|
+
raise ValueError(f"Azimuth steering rate for swath {swath} not found in AUX_INS file")
|
|
480
|
+
|
|
481
|
+
return np.deg2rad(self.azimuth_steering_rates[swath])
|