Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 73 additions & 5 deletions python/packages/nisar/workflows/gcov.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ def apply_noise_correction(data_block, noise_product, is_backscatter):

def prepare_rslc(in_file, freq, pol, out_file, lines_per_block,
flag_rslc_to_backscatter, flag_apply_noise_correction,
pol_2=None, format="ENVI"):
pol_2=None, format="ENVI",
radiometric_calibration_lut=None):
'''
Copy RSLC dataset to GDAL format converting RSLC real and
imaginary parts from float16 to float32. If the flag
Expand Down Expand Up @@ -144,6 +145,8 @@ def prepare_rslc(in_file, freq, pol, out_file, lines_per_block,
Polarization associated with the second RSLC
format: str, optional
GDAL-friendly format
radiometric_calibration_lut: isce3.core.LUT2d or None
Radiometric calibration look-up table (LUT)

Returns
-------
Expand All @@ -165,6 +168,8 @@ def prepare_rslc(in_file, freq, pol, out_file, lines_per_block,
f' {flag_symmetrize}')
info_channel.log(' apply noise correction:'
f' {flag_apply_noise_correction}')
info_channel.log(' apply radiometric calibration LUT:'
f' {radiometric_calibration_lut is not None}')

pol_ref = f'HDF5:{in_file}:/{pol_dataset_path}'

Expand Down Expand Up @@ -225,8 +230,9 @@ def prepare_rslc(in_file, freq, pol, out_file, lines_per_block,
lines_per_block = min(rslc_length, lines_per_block)
num_blocks = int(np.ceil(rslc_length / lines_per_block))

# get radar_grid for noise correction
if flag_apply_noise_correction:
# get radar_grid for noise correction and radiometric calibration
if (flag_apply_noise_correction or
radiometric_calibration_lut is not None):
radar_grid = rslc.getRadarGrid(frequency=freq)

for block in range(num_blocks):
Expand Down Expand Up @@ -284,6 +290,27 @@ def prepare_rslc(in_file, freq, pol, out_file, lines_per_block,
# average cross-pol channels
data_block = 0.5 * (data_block + data_block_2)

if radiometric_calibration_lut is not None:
for i in range(block_length):
slant_ranges = radar_grid.slant_ranges
radiometric_calibraton_slant_ranges = \
radiometric_calibration_lut.eval(i + line_start,
slant_ranges)

# apply radiometric calibration by dividing the data block by
# the radiometric calibration slant-range line
if flag_rslc_to_backscatter:

# if the data block is backscatter, convert the
# radiometric calibration LUT to power/intensity
# (square)
data_block[i, :] = (data_block[i, :] /
radiometric_calibraton_slant_ranges **
2)
else:
data_block[i, :] = (data_block[i, :] /
radiometric_calibraton_slant_ranges)

# write to GDAL raster
out_ds.GetRasterBand(1).WriteArray(data_block, yoff=line_start, xoff=0)

Expand Down Expand Up @@ -331,6 +358,7 @@ def _run(cfg, raster_scratch_dir):

'''
info_channel = journal.info("gcov.run")
error_channel = journal.error("gcov.run")
info_channel.log("Starting GCOV workflow")

# pull parameters from cfg
Expand Down Expand Up @@ -392,6 +420,10 @@ def _run(cfg, raster_scratch_dir):
# unpack geocode run parameters
geocode_dict = cfg['processing']['geocode']

radiometric_calibration_lut_name = \
geocode_dict['radiometric_calibration_lut']
flag_apply_rtc = geocode_dict['apply_rtc']

apply_range_ionospheric_delay_correction = \
geocode_dict['apply_range_ionospheric_delay_correction']

Expand All @@ -410,6 +442,10 @@ def _run(cfg, raster_scratch_dir):
min_block_size_mb = cfg["processing"]["geocode"]['min_block_size']
max_block_size_mb = cfg["processing"]["geocode"]['max_block_size']

# unpack RTC run parameters
rtc_dict = cfg['processing']['rtc']
input_terrain_radiometry = rtc_dict['input_terrain_radiometry']

# optional keyword arguments , i.e. arguments that may or may not be
# included in the call to geocode()
optional_geo_kwargs = {}
Expand Down Expand Up @@ -442,6 +478,36 @@ def _run(cfg, raster_scratch_dir):

# init parameters shared between frequencyA and frequencyB sub-bands
slc = SLC(hdf5file=input_hdf5)

radiometric_calibration_lut = None
if (radiometric_calibration_lut_name is not None and
radiometric_calibration_lut_name != 'disabled'):
info_channel.log(' radiometric calibration LUT:'
f' {radiometric_calibration_lut_name}')

if flag_apply_rtc and radiometric_calibration_lut_name == "gamma0":
err_str = ('ERROR radiometric calibration LUT cannot be "gamma0"'
' if RTC is enabled (`apply_rtc is True`)')
error_channel.log(err_str)
raise ValueError(err_str)

# if RTC is enabled, ensure that `radiometric_calibration_lut_name`
# and `input_terrain_radiometry` are the same:
if (flag_apply_rtc and (radiometric_calibration_lut_name !=
input_terrain_radiometry)):
err_str = ('The radiometric calibration LUT'
f' ("{radiometric_calibration_lut_name}")'
' does not match the RTC input terrain radiometry'
f' ("{input_terrain_radiometry}")')
error_channel.log(err_str)
raise ValueError(err_str)

radiometric_calibration_lut = \
slc.getRadiometricCalibrationLUT(
lut_name=radiometric_calibration_lut_name)
else:
info_channel.log(' radiometric calibration LUT: "disabled"')

zero_doppler = isce3.core.LUT2d()
native_doppler = slc.getDopplerCentroid()

Expand Down Expand Up @@ -509,7 +575,8 @@ def _run(cfg, raster_scratch_dir):
symmetrized_hv_temp.name, 2**11, # 2**11 = 2048 lines
flag_rslc_to_backscatter=flag_rslc_to_backscatter,
flag_apply_noise_correction=flag_apply_noise_correction,
pol_2='VH', format=output_gcov_terms_raster_files_format)
pol_2='VH', format=output_gcov_terms_raster_files_format,
radiometric_calibration_lut=radiometric_calibration_lut)

# Since HV and VH were symmetrized into HV, remove VH from
# `pol_list` and `from input_raster_dict`.
Expand Down Expand Up @@ -542,7 +609,8 @@ def _run(cfg, raster_scratch_dir):
temp_pol_file.name, 2**12, # 2**12 = 4096 lines
flag_rslc_to_backscatter=flag_rslc_to_backscatter,
flag_apply_noise_correction=flag_apply_noise_correction,
format=output_gcov_terms_raster_files_format)
format=output_gcov_terms_raster_files_format,
radiometric_calibration_lut=radiometric_calibration_lut)

input_raster_list.append(input_raster)

Expand Down
10 changes: 10 additions & 0 deletions python/packages/nisar/workflows/gcov_runconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ def load(self):
rtc_dict['algorithm_type_enum'] = \
isce3.geometry.normalize_rtc_algorithm(rtc_dict['algorithm_type'])

if (rtc_dict['input_terrain_radiometry'] is None and
(geocode_dict['radiometric_calibration_lut'] == 'beta0' or
geocode_dict['radiometric_calibration_lut'] == 'sigma0')):
rtc_dict['input_terrain_radiometry'] = \
geocode_dict['radiometric_calibration_lut']

# otherwise, the RTC input terrain radiometry defaults to `beta0`
elif rtc_dict['input_terrain_radiometry'] is None:
rtc_dict['input_terrain_radiometry'] = 'beta0'

if rtc_dict['input_terrain_radiometry'] == "sigma0":
rtc_dict['input_terrain_radiometry_enum'] = \
isce3.geometry.RtcInputTerrainRadiometry.SIGMA_NAUGHT_ELLIPSOID
Expand Down
40 changes: 36 additions & 4 deletions share/nisar/defaults/gcov.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,24 @@ runconfig:
# "area_projection" (default)
algorithm_type: area_projection

# Input terrain radiometry convention. Choices:
# "beta0" (default)
# "sigma0"
input_terrain_radiometry: beta0
# OPTIONAL - Choices:
# 'beta0' (default if `radiometric_calibration_lut` == 'beta0' or
# `radiometric_calibration_lut` == 'disabled'))
# 'sigma0' (default if `radiometric_calibration_lut` == 'sigma0')
#
# The field `input_terrain_radiometry` defines the input terrain
# radiometric convention for RTC. Its value should be consistent
# with the field `radiometric_calibration_lut` in the geocode
# group. If that field is set to 'beta0' or 'sigma0',
# the `input_terrain_radiometry` should be assigned to the same
# value.
# For that reason, if `input_terrain_radiometry` is not set and
# `radiometric_calibration_lut is set to either 'beta0' or
# 'sigma0', `input_terrain_radiometry` will default to
# to that value (i.e., 'beta0' or 'sigma0'). Otherwise,
# if `radiometric_calibration_lut` is disabled (default),
# the `input_terrain_radiometry` will default to 'beta0'.
input_terrain_radiometry:

# Minimum RTC area factor (in dB). Specifies the lowest
# allowable denominator (in dB) for dividing GCOV samples.
Expand Down Expand Up @@ -278,6 +292,24 @@ runconfig:
# If `False`, the entire `rtc` group is ignored.
apply_rtc: True

# Radiometric calibration look-up table (LUT)
#
# Determines the type of radiometric calibration to be applied to input
# RLSC values.
#
# The radiometric calibration is applied to the RSLC before RTC.
# Therefore, if `apply_rtc` is enabled, this field should be consistent
# with the RTC group field `input_terrain_radiometry`. Otherwise,
# the software will raise an error.
#
# The value "gamma0" implies that the radiometric calibration will
# be applied instead of RTC. In that case, the field `apply_rtc`
# should be `False`, otherwise the software will raise an error.
#
# The field `abs_rad_cal` provides an additional constant factor
# that can be optionally applied to RSLC
radiometric_calibration_lut: disabled

# NOT YET IMPLEMENTED (it is expected that the RSLC product already
# incorporates static tropospheric delay corrections --
# no additional correction is currently applied)
Expand Down
32 changes: 31 additions & 1 deletion share/nisar/schemas/gcov.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -317,12 +317,24 @@ pre_process_options:

rtc_options:
# Output type (defines the terrain radiometry convention for the output
# It defaults to "gamma0".
output_type: enum('gamma0', 'sigma0', required=False)

# RTC algorithm type
algorithm_type: enum('area_projection', 'bilinear_distribution', required=False)

# Input terrain radiometry convention
# The field `input_terrain_radiometry` defines the input terrain
# radiometric convention for RTC. Its value should be consistent
# with the field `radiometric_calibration_lut` in the geocode
# group. If that field is set to 'beta0' or 'sigma0',
# the `input_terrain_radiometry` should be assigned to the same
# value.
# For that reason, if `input_terrain_radiometry` is not set and
# `radiometric_calibration_lut is set to either 'beta0' or
# 'sigma0', `input_terrain_radiometry` will default to
# to that value (i.e., 'beta0' or 'sigma0'). Otherwise,
# if `radiometric_calibration_lut` is disabled (default),
# the `input_terrain_radiometry` will default to 'beta0'.
input_terrain_radiometry: enum('beta0', 'sigma0', required=False)

# Minimum RTC area factor (in dB). Specifies the lowest
Expand Down Expand Up @@ -354,6 +366,24 @@ geocode_options:
# sinc, bilinear, bicubic, nearest, and biquintic
algorithm_type: enum('area_projection', 'sinc', 'bilinear', 'bicubic', 'nearest', 'biquintic', required=False)

# Radiometric calibration look-up table (LUT)
#
# Determines the type of radiometric calibration to be applied to input
# RLSC values.
#
# The radiometric calibration is applied to the RSLC before RTC.
# Therefore, if `apply_rtc` is enabled, this field should be consistent
# with the RTC group field `input_terrain_radiometry`. Otherwise,
# the software will raise an error.
#
# The value "gamma0" implies that the radiometric calibration will
# be applied instead of RTC. In that case, the field `apply_rtc`
# should be `False`, otherwise the software will raise an error.
#
# The field `abs_rad_cal` provides an additional constant factor
# that can be optionally applied to RSLC
radiometric_calibration_lut: enum('disabled', 'beta0', 'sigma0', 'gamma0', required=False)

# Apply radiometric terrain correction
# If `False`, the entire `rtc` group is ignored.
apply_rtc: bool(required=False)
Expand Down
Loading