diff --git a/cxx/isce3/geocode/GeocodeCov.cpp b/cxx/isce3/geocode/GeocodeCov.cpp index 09f9e6ce4..7048fc55c 100644 --- a/cxx/isce3/geocode/GeocodeCov.cpp +++ b/cxx/isce3/geocode/GeocodeCov.cpp @@ -27,6 +27,7 @@ using isce3::core::OrbitInterpBorderMode; using isce3::core::Vec3; using isce3::core::GeocodeMemoryMode; +using isce3::geometry::rtcMinValueMode; namespace isce3 { namespace geocode { @@ -131,7 +132,9 @@ void Geocode::geocode(const isce3::product::RadarGridParameters& radar_grid, bool flag_upsample_radar_grid, bool flag_apply_rtc, isce3::geometry::rtcInputTerrainRadiometry input_terrain_radiometry, isce3::geometry::rtcOutputTerrainRadiometry output_terrain_radiometry, - int exponent, float rtc_min_value_db, double rtc_geogrid_upsampling, + int exponent, float rtc_min_value_db, float rtc_transition_value_db, + isce3::geometry::rtcMinValueMode rtc_min_value_mode, + double rtc_geogrid_upsampling, isce3::geometry::rtcAlgorithm rtc_algorithm, isce3::geometry::rtcAreaBetaMode rtc_area_beta_mode, double abs_cal_factor, float clip_min, float clip_max, @@ -161,7 +164,8 @@ void Geocode::geocode(const isce3::product::RadarGridParameters& radar_grid, geocodeInterp(radar_grid, input_raster, output_raster, dem_raster, flag_apply_rtc, flag_az_baseband_doppler, flatten, input_terrain_radiometry, output_terrain_radiometry, - rtc_min_value_db, rtc_geogrid_upsampling, rtc_algorithm, + rtc_min_value_db, rtc_transition_value_db, rtc_min_value_mode, + rtc_geogrid_upsampling, rtc_algorithm, rtc_area_beta_mode, abs_cal_factor, clip_min, clip_max, out_geo_rdr, out_geo_dem, out_geo_rtc, out_geo_rtc_gamma0_to_sigma0, @@ -177,8 +181,8 @@ void Geocode::geocode(const isce3::product::RadarGridParameters& radar_grid, geocodeInterp(radar_grid, input_raster, output_raster, dem_raster, flag_apply_rtc, flag_az_baseband_doppler, flatten, input_terrain_radiometry, output_terrain_radiometry, - rtc_min_value_db, rtc_geogrid_upsampling, rtc_algorithm, - rtc_area_beta_mode, + rtc_min_value_db, rtc_transition_value_db, rtc_min_value_mode, + rtc_geogrid_upsampling, rtc_algorithm, rtc_area_beta_mode, abs_cal_factor, clip_min, clip_max, out_geo_rdr, out_geo_dem, out_geo_rtc, out_geo_rtc_gamma0_to_sigma0, phase_screen_raster, az_time_correction, @@ -191,8 +195,8 @@ void Geocode::geocode(const isce3::product::RadarGridParameters& radar_grid, geocodeInterp(radar_grid, input_raster, output_raster, dem_raster, flag_apply_rtc, flag_az_baseband_doppler, flatten, input_terrain_radiometry, output_terrain_radiometry, - rtc_min_value_db, rtc_geogrid_upsampling, rtc_algorithm, - rtc_area_beta_mode, + rtc_min_value_db, rtc_transition_value_db, rtc_min_value_mode, + rtc_geogrid_upsampling, rtc_algorithm, rtc_area_beta_mode, abs_cal_factor, clip_min, clip_max, out_geo_rdr, out_geo_dem, out_geo_rtc, out_geo_rtc_gamma0_to_sigma0, phase_screen_raster, az_time_correction, @@ -205,8 +209,8 @@ void Geocode::geocode(const isce3::product::RadarGridParameters& radar_grid, geocodeAreaProj(radar_grid, input_raster, output_raster, dem_raster, geogrid_upsampling, flag_upsample_radar_grid, flag_apply_rtc, input_terrain_radiometry, output_terrain_radiometry, - rtc_min_value_db, rtc_geogrid_upsampling, rtc_algorithm, - rtc_area_beta_mode, + rtc_min_value_db, rtc_transition_value_db, rtc_min_value_mode, + rtc_geogrid_upsampling, rtc_algorithm, rtc_area_beta_mode, abs_cal_factor, clip_min, clip_max, min_nlooks, radar_grid_nlooks, out_off_diag_terms, out_geo_rdr, out_geo_dem, out_geo_nlooks, out_geo_rtc, out_geo_rtc_gamma0_to_sigma0, @@ -222,8 +226,9 @@ void Geocode::geocode(const isce3::product::RadarGridParameters& radar_grid, dem_raster, geogrid_upsampling, flag_upsample_radar_grid, flag_apply_rtc, input_terrain_radiometry, output_terrain_radiometry, rtc_min_value_db, - rtc_geogrid_upsampling, rtc_algorithm, rtc_area_beta_mode, - abs_cal_factor, clip_min, + rtc_transition_value_db, rtc_min_value_mode, + rtc_geogrid_upsampling, + rtc_algorithm, rtc_area_beta_mode, abs_cal_factor, clip_min, clip_max, min_nlooks, radar_grid_nlooks, out_off_diag_terms, out_geo_rdr, out_geo_dem, out_geo_nlooks, out_geo_rtc, out_geo_rtc_gamma0_to_sigma0, az_time_correction, @@ -238,8 +243,9 @@ void Geocode::geocode(const isce3::product::RadarGridParameters& radar_grid, dem_raster, geogrid_upsampling, flag_upsample_radar_grid, flag_apply_rtc, input_terrain_radiometry, output_terrain_radiometry, rtc_min_value_db, - rtc_geogrid_upsampling, rtc_algorithm, rtc_area_beta_mode, - abs_cal_factor, clip_min, + rtc_transition_value_db, rtc_min_value_mode, + rtc_geogrid_upsampling, + rtc_algorithm, rtc_area_beta_mode, abs_cal_factor, clip_min, clip_max, min_nlooks, radar_grid_nlooks, out_off_diag_terms, out_geo_rdr, out_geo_dem, out_geo_nlooks, out_geo_rtc, out_geo_rtc_gamma0_to_sigma0, az_time_correction, @@ -260,7 +266,8 @@ void Geocode::geocodeInterp( bool flag_az_baseband_doppler, bool flatten, isce3::geometry::rtcInputTerrainRadiometry input_terrain_radiometry, isce3::geometry::rtcOutputTerrainRadiometry output_terrain_radiometry, - float rtc_min_value_db, double rtc_geogrid_upsampling, + float rtc_min_value_db, float rtc_transition_value_db, isce3::geometry::rtcMinValueMode rtc_min_value_mode, + double rtc_geogrid_upsampling, isce3::geometry::rtcAlgorithm rtc_algorithm, isce3::geometry::rtcAreaBetaMode rtc_area_beta_mode, double abs_cal_factor, @@ -413,13 +420,6 @@ void Geocode::geocodeInterp( info << "clip max: " << clip_max << pyre::journal::newline; // RTC - double rtc_min_value = 0; - if (!std::isnan(rtc_min_value_db) && flag_apply_rtc) { - rtc_min_value = std::pow(10, (rtc_min_value_db / 10)); - info << "RTC min. value: " << rtc_min_value_db - << " [dB] = " << rtc_min_value << pyre::journal::newline; - } - if (abs_cal_factor != 1) info << "absolute calibration factor: " << abs_cal_factor << pyre::journal::newline; @@ -506,6 +506,7 @@ void Geocode::geocodeInterp( input_terrain_radiometry, output_terrain_radiometry, rtc_area_mode, rtc_algorithm, rtc_area_beta_mode, rtc_geogrid_upsampling, rtc_min_value_db, + rtc_transition_value_db, rtc_min_value_mode, out_geo_rdr, out_geo_grid, rtc_sigma0_raster, az_time_correction, slant_range_correction, rtc_memory_mode, dem_interp_method, _threshold, @@ -866,7 +867,7 @@ void Geocode::geocodeInterp( rdrBlockWidth, rdrBlockLength, azimuthFirstLine, rangeFirstPixel, interp.get(), radar_grid, flag_az_baseband_doppler, flatten, phase_screen_raster, - phase_screen_array, rtc_min_value, + phase_screen_array, abs_cal_factor_effective, clip_min, clip_max, flag_apply_rtc, rtc_area_array, rtc_area_sigma0_array, out_geo_rtc_band, out_geo_rtc_array, out_geo_rtc_gamma0_to_sigma0_band, @@ -953,7 +954,6 @@ inline void Geocode::_interpolate( const bool flag_az_baseband_doppler, const bool flatten, isce3::io::Raster* phase_screen_raster, isce3::core::Matrix& phase_screen_array, - float rtc_min_value, double abs_cal_factor_effective, float clip_min, float clip_max, bool flag_apply_rtc, const isce3::core::Matrix& rtc_area, @@ -1086,10 +1086,9 @@ inline void Geocode::_interpolate( float rtc_value = rtc_area(int(rdrY + azimuthFirstLine), int(rdrX + rangeFirstPixel)); - - if (std::isnan(rtc_value) || rtc_value < rtc_min_value) { + + if (std::isnan(rtc_value)) continue; - } /* RTC normalization values are proportional to backscater @@ -1875,7 +1874,9 @@ void Geocode::geocodeAreaProj( bool flag_upsample_radar_grid, bool flag_apply_rtc, isce3::geometry::rtcInputTerrainRadiometry input_terrain_radiometry, isce3::geometry::rtcOutputTerrainRadiometry output_terrain_radiometry, - float rtc_min_value_db, double rtc_geogrid_upsampling, + float rtc_min_value_db, float rtc_transition_value_db, + isce3::geometry::rtcMinValueMode rtc_min_value_mode, + double rtc_geogrid_upsampling, isce3::geometry::rtcAlgorithm rtc_algorithm, isce3::geometry::rtcAreaBetaMode rtc_area_beta_mode, double abs_cal_factor, @@ -1919,7 +1920,8 @@ void Geocode::geocodeAreaProj( output_raster, dem_raster, geogrid_upsampling, flag_upsample_radar_grid, flag_apply_rtc, input_terrain_radiometry, output_terrain_radiometry, - rtc_min_value_db, rtc_geogrid_upsampling, rtc_algorithm, + rtc_min_value_db, rtc_transition_value_db, rtc_min_value_mode, + rtc_geogrid_upsampling, rtc_algorithm, rtc_area_beta_mode, abs_cal_factor, clip_min, clip_max, min_nlooks, upsampled_radar_grid_nlooks, out_off_diag_terms, out_geo_rdr, @@ -2099,6 +2101,7 @@ void Geocode::geocodeAreaProj( input_terrain_radiometry, output_terrain_radiometry, rtc_area_mode, rtc_algorithm, rtc_area_beta_mode, rtc_geogrid_upsampling, rtc_min_value_db, + rtc_transition_value_db, rtc_min_value_mode, out_geo_rdr, out_geo_grid, rtc_sigma0_raster, az_time_correction, slant_range_correction, rtc_memory_mode, dem_interp_method, _threshold, @@ -2197,14 +2200,6 @@ void Geocode::geocodeAreaProj( const long long progress_block = ((long long) imax) * jmax / 100; - double rtc_min_value = 0; - - if (!std::isnan(rtc_min_value_db) && flag_apply_rtc) { - rtc_min_value = std::pow(10., (rtc_min_value_db / 10.)); - info << "RTC min. value: " << rtc_min_value_db - << " [dB] = " << rtc_min_value << pyre::journal::newline; - } - if (abs_cal_factor != 1) info << "absolute calibration factor: " << abs_cal_factor << pyre::journal::newline; @@ -2297,8 +2292,7 @@ void Geocode::geocodeAreaProj( rtc_raster, rtc_sigma0_raster, az_time_correction, slant_range_correction, input_raster, offset_y, offset_x, - output_raster, rtc_area, rtc_area_sigma, - rtc_min_value, abs_cal_factor, + output_raster, rtc_area, rtc_area_sigma, abs_cal_factor, clip_min, clip_max, min_nlooks, radar_grid_nlooks, flag_upsample_radar_grid, input_layover_shadow_mask_raster, input_layover_shadow_mask, sub_swaths, @@ -2325,8 +2319,7 @@ void Geocode::geocodeAreaProj( rtc_raster, rtc_sigma0_raster, az_time_correction, slant_range_correction, input_raster, offset_y, offset_x, - output_raster, rtc_area, rtc_area_sigma, - rtc_min_value, abs_cal_factor, + output_raster, rtc_area, rtc_area_sigma, abs_cal_factor, clip_min, clip_max, min_nlooks, radar_grid_nlooks, flag_upsample_radar_grid, input_layover_shadow_mask_raster, input_layover_shadow_mask, sub_swaths, @@ -2519,7 +2512,7 @@ void Geocode::_runBlock( int raster_offset_y, int raster_offset_x, isce3::io::Raster& output_raster, isce3::core::Matrix& rtc_area, isce3::core::Matrix& rtc_area_sigma, - float rtc_min_value, double abs_cal_factor, float clip_min, + double abs_cal_factor, float clip_min, float clip_max, float min_nlooks, float radar_grid_nlooks, bool flag_upsample_radar_grid, isce3::io::Raster* input_layover_shadow_mask_raster, @@ -3311,8 +3304,10 @@ void Geocode::_runBlock( rtc_value = rtc_area_block(y - offset_y, x - offset_x); } - if (std::isnan(rtc_value) || rtc_value < rtc_min_value) + + if (std::isnan(rtc_value)) { continue; + } nlooks += w; if (isce3::is_complex()) diff --git a/cxx/isce3/geocode/GeocodeCov.h b/cxx/isce3/geocode/GeocodeCov.h index d3c437717..fe238eb95 100644 --- a/cxx/isce3/geocode/GeocodeCov.h +++ b/cxx/isce3/geocode/GeocodeCov.h @@ -33,6 +33,7 @@ enum geocodeOutputMode { }; + template class Geocode { public: @@ -77,7 +78,19 @@ class Geocode { * The value 0 indicates that the the exponent is based on the data type of * the input raster (1 for real and 2 for complex rasters). * @param[in] rtc_min_value_db Minimum value for the RTC area factor. - * Radar data with RTC area factor below this limit will be set to NaN. + * Radar data with RTC area factor below this limit will be considered invalid. + * @param[in] rtc_transition_value_db RTC transition start value in dB used when + * `rtc_min_value_mode = TRANSITION`. Samples with an RTC area factor + * between `rtc_transition_value_db` and `rtc_min_value_db` will have + * a smooth transition applied to the RTC correction. + * @param[in] rtc_min_value_mode Specifies how the RTC minimum value is handled: + * DISABLED - No minimum-value thresholding is applied. + * CLIP - RTC values below the minimum are clipped to the minimum value. + * INVALID - Samples with an RTC factor below the minimum value are marked as invalid. + * BYPASS_RTC - RTC correction is bypassed for samples with an RTC factor below + * the minimum value. + * TRANSITION - Same as BYPASS_RTC, but applies a smooth transition between + * `rtc_transition_value_db` and `rtc_min_value_db`. * @param[in] rtc_geogrid_upsampling Geogrid upsampling to compute * the radiometric terrain correction RTC. * @param[in] rtc_algorithm RTC algorithm @@ -92,7 +105,7 @@ class Geocode { * @param[in] clip_min Clip (limit) minimum output values * @param[in] clip_max Clip (limit) maximum output values * @param[in] min_nlooks Minimum number of looks. Geogrid data - * below this limit will be set to NaN + * below this limit will be considered invalid * @param[in] radar_grid_nlooks Radar grid number of looks. This * parameters determines the multilooking factor used to compute * out_geo_nlooks. @@ -162,6 +175,9 @@ class Geocode { rtcOutputTerrainRadiometry::GAMMA_NAUGHT, int exponent = 0, float rtc_min_value_db = std::numeric_limits::quiet_NaN(), + float rtc_transition_value_db = std::numeric_limits::quiet_NaN(), + isce3::geometry::rtcMinValueMode rtc_min_value_mode = + isce3::geometry::rtcMinValueMode::TRANSITION, double rtc_geogrid_upsampling = std::numeric_limits::quiet_NaN(), isce3::geometry::rtcAlgorithm rtc_algorithm = @@ -230,7 +246,19 @@ class Geocode { * @param[in] input_terrain_radiometry Input terrain radiometry * @param[in] output_terrain_radiometry Output terrain radiometry * @param[in] rtc_min_value_db Minimum value for the RTC area factor. - * Radar data with RTC area factor below this limit will be set to NaN. + * Radar data with RTC area factor below this limit will be considered invalid. + * @param[in] rtc_transition_value_db RTC transition start value in dB used when + * `rtc_min_value_mode = TRANSITION`. Samples with an RTC area factor + * between `rtc_transition_value_db` and `rtc_min_value_db` will have + * a smooth transition applied to the RTC correction. + * @param[in] rtc_min_value_mode Specifies how the RTC minimum value is handled: + * DISABLED - No minimum-value thresholding is applied. + * CLIP - RTC values below the minimum are clipped to the minimum value. + * INVALID - Samples with an RTC factor below the minimum value are marked as invalid. + * BYPASS_RTC - RTC correction is bypassed for samples with an RTC factor below + * the minimum value. + * TRANSITION - Same as BYPASS_RTC, but applies a smooth transition between + * `rtc_transition_value_db` and `rtc_min_value_db`. * @param[in] rtc_geogrid_upsampling Geogrid upsampling to compute the * radiometric terrain correction RTC. * @param[in] rtc_algorithm RTC algorithm @@ -302,6 +330,9 @@ class Geocode { output_terrain_radiometry = isce3::geometry:: rtcOutputTerrainRadiometry::GAMMA_NAUGHT, float rtc_min_value_db = std::numeric_limits::quiet_NaN(), + float rtc_transition_value_db = std::numeric_limits::quiet_NaN(), + isce3::geometry::rtcMinValueMode rtc_min_value_mode = + isce3::geometry::rtcMinValueMode::TRANSITION, double rtc_geogrid_upsampling = std::numeric_limits::quiet_NaN(), isce3::geometry::rtcAlgorithm rtc_algorithm = @@ -368,7 +399,19 @@ class Geocode { * @param[in] input_terrain_radiometry Input terrain radiometry * @param[in] output_terrain_radiometry Output terrain radiometry * @param[in] rtc_min_value_db Minimum value for the RTC area factor. - * Radar data with RTC area factor below this limit will be set to NaN. + * Radar data with RTC area factor below this limit will be considered invalid. + * @param[in] rtc_transition_value_db RTC transition start value in dB used when + * `rtc_min_value_mode = TRANSITION`. Samples with an RTC area factor + * between `rtc_transition_value_db` and `rtc_min_value_db` will have + * a smooth transition applied to the RTC correction. + * @param[in] rtc_min_value_mode Specifies how the RTC minimum value is handled: + * DISABLED - No minimum-value thresholding is applied. + * CLIP - RTC values below the minimum are clipped to the minimum value. + * INVALID - Samples with an RTC factor below the minimum value are marked as invalid. + * BYPASS_RTC - RTC correction is bypassed for samples with an RTC factor below + * the minimum value. + * TRANSITION - Same as BYPASS_RTC, but applies a smooth transition between + * `rtc_transition_value_db` and `rtc_min_value_db`. * @param[in] rtc_geogrid_upsampling Geogrid upsampling to compute the * radiometric terrain correction RTC. * @param[in] rtc_algorithm RTC algorithm @@ -383,7 +426,7 @@ class Geocode { * @param[in] clip_min Clip (limit) minimum output values * @param[in] clip_max Clip (limit) maximum output values * @param[in] min_nlooks Minimum number of looks. Geogrid data - * below this limit will be set to NaN + * below this limit will be considered invalid * @param[in] radar_grid_nlooks Radar grid number of looks. This * parameters determines the multilooking factor used to compute out_nlooks. * @param[out] out_off_diag_terms Output raster containing the @@ -449,6 +492,9 @@ class Geocode { output_terrain_radiometry = isce3::geometry:: rtcOutputTerrainRadiometry::GAMMA_NAUGHT, float rtc_min_value_db = std::numeric_limits::quiet_NaN(), + float rtc_transition_value_db = std::numeric_limits::quiet_NaN(), + isce3::geometry::rtcMinValueMode rtc_min_value_mode = + isce3::geometry::rtcMinValueMode::TRANSITION, double rtc_geogrid_upsampling = std::numeric_limits::quiet_NaN(), isce3::geometry::rtcAlgorithm rtc_algorithm = @@ -647,7 +693,7 @@ class Geocode { isce3::io::Raster& output_raster, isce3::core::Matrix& rtc_area, isce3::core::Matrix& rtc_area_sigma, - float rtc_min_value, double abs_cal_factor, + double abs_cal_factor, float clip_min, float clip_max, float min_nlooks, float radar_grid_nlooks, bool flag_upsample_radar_grid, @@ -682,8 +728,6 @@ class Geocode { * @param[in] flatten flag to flatten the geocoded SLC * @param[in] phase_screen_raster Phase screen raster * @param[in] phase_screen_array Phase screen array - * @param[in] rtc_min_value_db Minimum value for the RTC area factor. - * Radar data with RTC area factor below this limit will be set to NaN. * @param[in] abs_cal_factor Absolute calibration factor applied * to real-valued output datasets (assumed to be proportional to * power/intensity). If the output is complex valued, its considered @@ -734,7 +778,7 @@ class Geocode { const bool flag_az_baseband_doppler, const bool flatten, isce3::io::Raster* phase_screen_raster, isce3::core::Matrix& phase_screen_array, - float rtc_min_value, double abs_cal_factor, + double abs_cal_factor, float clip_min, float clip_max, bool flag_run_rtc, const isce3::core::Matrix& rtc_area, const isce3::core::Matrix& rtc_area_sigma, diff --git a/cxx/isce3/geocode/GeocodePolygon.cpp b/cxx/isce3/geocode/GeocodePolygon.cpp index e7ed3a33e..59b60c251 100644 --- a/cxx/isce3/geocode/GeocodePolygon.cpp +++ b/cxx/isce3/geocode/GeocodePolygon.cpp @@ -3,6 +3,7 @@ #include "GeocodeHelpers.h" #include +#include #include #include @@ -145,7 +146,9 @@ void GeocodePolygon::getPolygonMean( isce3::geometry::rtcInputTerrainRadiometry input_terrain_radiometry, isce3::geometry::rtcOutputTerrainRadiometry output_terrain_radiometry, int exponent, double geogrid_upsampling, - float rtc_min_value_db, double abs_cal_factor, float radar_grid_nlooks, + float rtc_min_value_db, float rtc_transition_value_db, + isce3::geometry::rtcMinValueMode rtc_min_value_mode, + double abs_cal_factor, float radar_grid_nlooks, isce3::io::Raster* output_off_diag_terms, isce3::io::Raster* output_radargrid_data, isce3::io::Raster* output_rtc, isce3::io::Raster* output_weights, isce3::core::dataInterpMethod interp_method) { @@ -157,11 +160,16 @@ void GeocodePolygon::getPolygonMean( geogrid_upsampling = 2; assert(geogrid_upsampling > 0); + std::string rtc_min_value_mode_str = get_rtc_min_value_mode_str( + rtc_min_value_mode); + _info <<"look side: " << radar_grid.lookSide() << pyre::journal::newline << "radar_grid length: " << radar_grid.length() << ", width: " << radar_grid.width() << pyre::journal::newline - << "RTC min value [dB]: " << rtc_min_value_db << pyre::journal::endl; + << "RTC min value [dB]: " << rtc_min_value_db << pyre::journal::newline + << "RTC min value mode: " << rtc_min_value_mode_str + << pyre::journal::endl; _info << "cropping radar grid from index (a0: " << _yoff; _info << ", r0: " << _xoff << ") to index (af: " << _yoff + _ysize; @@ -232,6 +240,7 @@ void GeocodePolygon::getPolygonMean( output_terrain_radiometry, rtc_area_mode, rtc_algorithm, rtc_area_beta_mode, geogrid_upsampling * 2, rtc_min_value_db, + rtc_transition_value_db, rtc_min_value_mode, out_sigma, az_time_correction, slant_range_correction, rtc_memory_mode, interp_method, _threshold, _num_iter, _delta_range); @@ -264,21 +273,24 @@ void GeocodePolygon::getPolygonMean( _info << "output dtype: GDT_Float32" << pyre::journal::endl; _getPolygonMean( rtc_area, radar_grid_cropped, input_raster, output_raster, - flag_apply_rtc, rtc_min_value, abs_cal_factor, radar_grid_nlooks, + flag_apply_rtc, rtc_min_value, rtc_min_value_mode, + abs_cal_factor, radar_grid_nlooks, output_off_diag_terms, output_radargrid_data, output_weights); } else if (input_raster.dtype() == GDT_CFloat32 && exponent == 2) { _info << "input dtype: GDT_CFloat32" << pyre::journal::endl; _info << "output dtype: GDT_Float32" << pyre::journal::endl; _getPolygonMean( rtc_area, radar_grid_cropped, input_raster, output_raster, - flag_apply_rtc, rtc_min_value, abs_cal_factor, radar_grid_nlooks, + flag_apply_rtc, rtc_min_value, rtc_min_value_mode, + abs_cal_factor, radar_grid_nlooks, output_off_diag_terms, output_radargrid_data, output_weights); } else if (input_raster.dtype() == GDT_CFloat32 && exponent == 1) { _info << "input dtype: GDT_CFloat32" << pyre::journal::endl; _info << "output dtype: GDT_CFloat32" << pyre::journal::endl; _getPolygonMean>( rtc_area, radar_grid_cropped, input_raster, output_raster, - flag_apply_rtc, rtc_min_value, abs_cal_factor, radar_grid_nlooks, + flag_apply_rtc, rtc_min_value, rtc_min_value_mode, + abs_cal_factor, radar_grid_nlooks, output_off_diag_terms, output_radargrid_data, output_weights); } else _info << "ERROR not implemented for datatype: " << input_raster.dtype() @@ -294,7 +306,7 @@ void GeocodePolygon::_getPolygonMean( isce3::io::Raster& input_raster, isce3::io::Raster& output_raster, bool flag_apply_rtc, - float rtc_min_value, + float rtc_min_value, isce3::geometry::rtcMinValueMode rtc_min_value_mode, double abs_cal_factor, float radar_grid_nlooks, isce3::io::Raster* output_off_diag_terms, isce3::io::Raster* output_radargrid_data, @@ -397,9 +409,12 @@ void GeocodePolygon::_getPolygonMean( */ w = std::abs(w); if (flag_apply_rtc) { - const float rtc_value = rtc_area(y, x); - if (std::isnan(rtc_value) || rtc_value < rtc_min_value) + float rtc_value = rtc_area(y, x); + if (std::isnan(rtc_value) || + (!rtc_min_value_mode && rtc_value < rtc_min_value)) continue; + else if (rtc_value < rtc_min_value) + rtc_value = rtc_min_value; nlooks += w; w /= rtc_value; } else { diff --git a/cxx/isce3/geocode/GeocodePolygon.h b/cxx/isce3/geocode/GeocodePolygon.h index 98e29c275..1fed4d74c 100644 --- a/cxx/isce3/geocode/GeocodePolygon.h +++ b/cxx/isce3/geocode/GeocodePolygon.h @@ -63,6 +63,18 @@ class GeocodePolygon { * @param[in] geogrid_upsampling Geogrid upsampling (in each direction) * @param[in] rtc_min_value_db Minimum value for the RTC area factor. * Radar data with RTC area factor below this limit are ignored. + * @param[in] rtc_transition_value_db RTC transition start value in dB used when + * `rtc_min_value_mode = TRANSITION`. Samples with an RTC area factor + * between `rtc_transition_value_db` and `rtc_min_value_db` will have + * a smooth transition applied to the RTC correction. + * @param[in] rtc_min_value_mode Specifies how the RTC minimum value is handled: + * DISABLED - No minimum-value thresholding is applied. + * CLIP - RTC values below the minimum are clipped to the minimum value. + * INVALID - Samples with an RTC factor below the minimum value are marked as invalid. + * BYPASS_RTC - RTC correction is bypassed for samples with an RTC factor below + * the minimum value. + * TRANSITION - Same as BYPASS_RTC, but applies a smooth transition between + * `rtc_transition_value_db` and `rtc_min_value_db`. * @param[in] abs_cal_factor Absolute calibration factor. * @param[in] radar_grid_nlooks Radar grid number of looks. This * parameters determines the multilooking factor used to compute out_nlooks. @@ -91,6 +103,9 @@ class GeocodePolygon { double geogrid_upsampling = std::numeric_limits::quiet_NaN(), float rtc_min_value_db = std::numeric_limits::quiet_NaN(), + float rtc_transition_value_db = std::numeric_limits::quiet_NaN(), + isce3::geometry::rtcMinValueMode rtc_min_value_mode = + isce3::geometry::rtcMinValueMode::TRANSITION, double abs_cal_factor = 1, float radar_grid_nlooks = 1, isce3::io::Raster* output_off_diag_terms = nullptr, isce3::io::Raster* output_radargrid_data = nullptr, @@ -137,7 +152,8 @@ class GeocodePolygon { isce3::io::Raster& input_raster, isce3::io::Raster& output_raster, bool flag_apply_rtc = false, - float rtc_min_value = 0, + float rtc_min_value = 0, isce3::geometry::rtcMinValueMode rtc_min_value_mode = + isce3::geometry::rtcMinValueMode::TRANSITION, double abs_cal_factor = 1, float radar_grid_nlooks = 1, isce3::io::Raster* output_off_diag_terms = nullptr, isce3::io::Raster* output_radargrid_data = nullptr, diff --git a/cxx/isce3/geometry/RTC.cpp b/cxx/isce3/geometry/RTC.cpp index 95fe03b37..edf434db3 100644 --- a/cxx/isce3/geometry/RTC.cpp +++ b/cxx/isce3/geometry/RTC.cpp @@ -124,7 +124,7 @@ static int _geo2rdrWrapper(const Vec3& inputLLH, const Ellipsoid& ellipsoid, template void _applyRtc(isce3::io::Raster& input_raster, isce3::io::Raster& input_rtc, - isce3::io::Raster& output_raster, float rtc_min_value, + isce3::io::Raster& output_raster, double abs_cal_factor, float clip_min, float clip_max, pyre::journal::info_t& info, bool flag_complex_to_real_squared) { @@ -138,9 +138,6 @@ void _applyRtc(isce3::io::Raster& input_raster, isce3::io::Raster& input_rtc, getBlockProcessingParametersY(length, width, nbands, sizeof(T), &info, &block_length, &nblocks); - if (std::isnan(rtc_min_value)) - rtc_min_value = 0; - if (!isnan(abs_cal_factor)) { abs_cal_factor = 1.0; } @@ -187,8 +184,7 @@ void _applyRtc(isce3::io::Raster& input_raster, isce3::io::Raster& input_rtc, for (int jj = 0; jj < width; ++jj) { float rtc_ratio_value = rtc_ratio(i, jj); - if (std::isnan(rtc_ratio_value) || - rtc_ratio_value < rtc_min_value) { + if (std::isnan(rtc_ratio_value)) { /* assign NaN by multiplication to cast it to the radar_data_block data type. See comments above (outside for loops) */ @@ -219,8 +215,7 @@ void _applyRtc(isce3::io::Raster& input_raster, isce3::io::Raster& input_rtc, /* assign NaN by multiplication to cast it to the radar_data_block data type. See comments above (outside for loops) */ - if (std::isnan(rtc_ratio_value) || - rtc_ratio_value < rtc_min_value) { + if (std::isnan(rtc_ratio_value)) { radar_data_block(i, jj) *= std::numeric_limits::quiet_NaN(); } @@ -250,24 +245,92 @@ void _applyRtc(isce3::io::Raster& input_raster, isce3::io::Raster& input_rtc, } void _applyRtcMinValueDb(isce3::core::Matrix& out_array, - float rtc_min_value_db, rtcAreaMode rtc_area_mode, + float rtc_min_value_db, float rtc_transition_value_db, + isce3::geometry::rtcMinValueMode rtc_min_value_mode, + rtcAreaMode rtc_area_mode, pyre::journal::info_t& info) { - if (!std::isnan(rtc_min_value_db) && - rtc_area_mode == rtcAreaMode::AREA_FACTOR) { - float rtc_min_value = std::pow(10., (rtc_min_value_db / 10.)); - info << "applying min. RTC value: " << rtc_min_value_db - << " [dB] ~= " << rtc_min_value << pyre::journal::endl; - _Pragma("omp parallel for schedule(dynamic) collapse(2)") - for (int i = 0; i < out_array.length(); ++i) - for (int j = 0; j < out_array.width(); ++j) { - if (out_array(i, j) >= rtc_min_value) - continue; + if (std::isnan(rtc_min_value_db) || + rtc_min_value_mode == rtcMinValueMode::DISABLED || + rtc_area_mode != rtcAreaMode::AREA_FACTOR) + return; + + float rtc_min_value = std::pow(10., (rtc_min_value_db / 10.)); + float rtc_transition_value = std::pow(10., (rtc_transition_value_db / 10.)); + + info << "applying min. RTC value: " << rtc_min_value_db + << " [dB] ~= " << rtc_min_value << pyre::journal::newline; + + if (rtc_min_value_mode == rtcMinValueMode::TRANSITION) { + if (std::isnan(rtc_transition_value_db)) { + info << "RTC transition value not provided. Using RTC min value + 3 dB." + << pyre::journal::newline; + rtc_transition_value_db = rtc_min_value_db + 3.0f; + } + else { + info << "RTC transition value: " << rtc_transition_value_db + << " [dB] ~= " << rtc_transition_value << pyre::journal::newline; + } + if (rtc_min_value_db >= rtc_transition_value_db) { + std::string error_message = + "ERROR rtc_min_value_db must be less than " + "rtc_transition_value_db for TRANSITION mode."; + throw isce3::except::InvalidArgument(ISCE_SRCINFO(), error_message); + } + } + + info << pyre::journal::endl; + + _Pragma("omp parallel for schedule(dynamic) collapse(2)") + for (int i = 0; i < out_array.length(); ++i) + for (int j = 0; j < out_array.width(); ++j) { + // Skip if RTC value is valid, i.e., above min RTC value + if ((out_array(i, j) >= rtc_min_value && + rtc_min_value_mode != rtcMinValueMode::TRANSITION) || + out_array(i, j) >= rtc_transition_value) + continue; + if (rtc_min_value_mode == rtcMinValueMode::TRANSITION) { + /* + float new_rtc_value = rtc_transition_value + + (rtc_transition_value - out_array(i, j)) * + (1 - rtc_transition_value) / + (rtc_transition_value - rtc_min_value); + */ + // Smooth transition using logistic function + + // Steepness parameter for logistic function + const float k = 20.0; + + // Normalized distance between rtc_min_value and + // rtc_transition_value + const float t = (out_array(i, j) - rtc_min_value) / + (rtc_transition_value - rtc_min_value); + + // Logistic in [0, 1] + const float sigmoid = 1.0f / (1.0f + std::exp(-k * (t - 0.5f))); + + // Scale logistic output from: + // - `1.0` at `rtc_min_value` + // - `rtc_transition_value` at `rtc_transition_value` + const float new_rtc_value = (1.0 + (rtc_transition_value - 1.0) * sigmoid); + + _Pragma("omp atomic write") out_array(i, j) = new_rtc_value; + } + else if (rtc_min_value_mode == rtcMinValueMode::CLIP) { + _Pragma("omp atomic write") out_array(i, j) = + rtc_min_value; + } + else if (rtc_min_value_mode == rtcMinValueMode::TRANSITION || + rtc_min_value_mode == rtcMinValueMode::BYPASS_RTC) { + _Pragma("omp atomic write") out_array(i, j) = 1.0f; + } + else if (rtc_min_value_mode == rtcMinValueMode::INVALID) { _Pragma("omp atomic write") out_array(i, j) = std::numeric_limits::quiet_NaN(); - } - info << "... done" << pyre::journal::endl; - } + } + } + info << "... done" << pyre::journal::endl; + } @@ -301,6 +364,8 @@ void applyRtc(const isce3::product::RadarGridParameters& radar_grid, rtcAreaMode rtc_area_mode, rtcAlgorithm rtc_algorithm, rtcAreaBetaMode rtc_area_beta_mode, double geogrid_upsampling, float rtc_min_value_db, + float rtc_transition_value_db, + isce3::geometry::rtcMinValueMode rtc_min_value_mode, double abs_cal_factor, float clip_min, float clip_max, isce3::io::Raster* out_sigma, const isce3::core::LUT2d& az_time_correction, @@ -347,8 +412,9 @@ void applyRtc(const isce3::product::RadarGridParameters& radar_grid, computeRtc(radar_grid, orbit, input_dop, dem_raster, *rtc_raster, input_terrain_radiometry, output_terrain_radiometry, rtc_area_mode, rtc_algorithm, rtc_area_beta_mode, - geogrid_upsampling, rtc_min_value_db, out_sigma, - az_time_correction, slant_range_correction, + geogrid_upsampling, rtc_min_value_db, + rtc_transition_value_db, rtc_min_value_mode, + out_sigma, az_time_correction, slant_range_correction, rtc_memory_mode); } else { info << "reading pre-computed RTC..." << pyre::journal::endl; @@ -375,21 +441,21 @@ void applyRtc(const isce3::product::RadarGridParameters& radar_grid, if (input_raster.dtype() == GDT_Float32 || (input_raster.dtype() == GDT_CFloat32 && flag_complex_to_real)) _applyRtc(input_raster, *rtc_raster, output_raster, - rtc_min_value_db, abs_cal_factor, clip_min, clip_max, info, + abs_cal_factor, clip_min, clip_max, info, flag_complex_to_real); else if (input_raster.dtype() == GDT_Float64 || (input_raster.dtype() == GDT_CFloat64 && flag_complex_to_real)) _applyRtc(input_raster, *rtc_raster, output_raster, - rtc_min_value_db, abs_cal_factor, clip_min, clip_max, info, + abs_cal_factor, clip_min, clip_max, info, flag_complex_to_real); else if (input_raster.dtype() == GDT_CFloat32) _applyRtc>(input_raster, *rtc_raster, output_raster, - rtc_min_value_db, abs_cal_factor, clip_min, clip_max, info, + abs_cal_factor, clip_min, clip_max, info, flag_complex_to_real); else if (input_raster.dtype() == GDT_CFloat64) _applyRtc>(input_raster, *rtc_raster, - output_raster, rtc_min_value_db, abs_cal_factor, clip_min, - clip_max, info, flag_complex_to_real); + output_raster, abs_cal_factor, + clip_min, clip_max, info, flag_complex_to_real); else { std::string error_message = "ERROR not implemented for input raster datatype"; @@ -442,6 +508,8 @@ void computeRtc(const isce3::product::RadarGridParameters& radar_grid, rtcAreaMode rtc_area_mode, rtcAlgorithm rtc_algorithm, rtcAreaBetaMode rtc_area_beta_mode, double geogrid_upsampling, float rtc_min_value_db, + float rtc_transition_value_db, + isce3::geometry::rtcMinValueMode rtc_min_value_mode, isce3::io::Raster* out_sigma, const isce3::core::LUT2d& az_time_correction, const isce3::core::LUT2d& slant_range_correction, @@ -478,8 +546,8 @@ void computeRtc(const isce3::product::RadarGridParameters& radar_grid, x0, dx, geogrid_length, geogrid_width, epsg, input_terrain_radiometry, output_terrain_radiometry, rtc_area_mode, rtc_algorithm, rtc_area_beta_mode, - geogrid_upsampling, rtc_min_value_db, - nullptr, nullptr, out_sigma, az_time_correction, + geogrid_upsampling, rtc_min_value_db, rtc_transition_value_db, + rtc_min_value_mode, nullptr, nullptr, out_sigma, az_time_correction, slant_range_correction, rtc_memory_mode, interp_method, threshold, num_iter, delta_range, min_block_size, max_block_size); @@ -496,6 +564,8 @@ void computeRtc(isce3::io::Raster& dem_raster, isce3::io::Raster& output_raster, rtcAreaMode rtc_area_mode, rtcAlgorithm rtc_algorithm, rtcAreaBetaMode rtc_area_beta_mode, double geogrid_upsampling, float rtc_min_value_db, + float rtc_transition_value_db, + isce3::geometry::rtcMinValueMode rtc_min_value_mode, isce3::io::Raster* out_geo_rdr, isce3::io::Raster* out_geo_grid, isce3::io::Raster* out_sigma, const isce3::core::LUT2d& az_time_correction, @@ -513,7 +583,8 @@ void computeRtc(isce3::io::Raster& dem_raster, isce3::io::Raster& output_raster, input_dop, geogrid, input_terrain_radiometry, output_terrain_radiometry, rtc_area_mode, rtc_area_beta_mode, geogrid_upsampling, - rtc_min_value_db, out_geo_rdr, out_geo_grid, + rtc_min_value_db, rtc_transition_value_db, rtc_min_value_mode, + out_geo_rdr, out_geo_grid, out_sigma, az_time_correction, slant_range_correction, rtc_memory_mode, interp_method, threshold, num_iter, delta_range, min_block_size, max_block_size); @@ -527,8 +598,8 @@ void computeRtc(isce3::io::Raster& dem_raster, isce3::io::Raster& output_raster, computeRtcBilinearDistribution(dem_raster, output_raster, radar_grid, orbit, input_dop, geogrid, input_terrain_radiometry, output_terrain_radiometry, rtc_area_mode, - geogrid_upsampling, rtc_min_value_db, out_sigma, - threshold, num_iter, delta_range, + geogrid_upsampling, rtc_min_value_db, rtc_transition_value_db, rtc_min_value_mode, + out_sigma, threshold, num_iter, delta_range, az_time_correction, slant_range_correction); } } @@ -729,6 +800,8 @@ void computeRtcBilinearDistribution(isce3::io::Raster& dem_raster, rtcOutputTerrainRadiometry output_terrain_radiometry, rtcAreaMode rtc_area_mode, double upsample_factor, float rtc_min_value_db, + float rtc_transition_value_db, + isce3::geometry::rtcMinValueMode rtc_min_value_mode, isce3::io::Raster* out_sigma, double threshold, int num_iter, double delta_range, const isce3::core::LUT2d& az_time_correction, @@ -747,7 +820,8 @@ void computeRtcBilinearDistribution(isce3::io::Raster& dem_raster, rtcAreaBetaMode rtc_area_beta_mode = rtcAreaBetaMode::PIXEL_AREA; print_parameters(info, radar_grid, input_terrain_radiometry, output_terrain_radiometry, rtc_area_mode, rtc_area_beta_mode, - upsample_factor, rtc_min_value_db); + upsample_factor, rtc_min_value_db, + rtc_transition_value_db, rtc_min_value_mode); const double yf = geogrid.startY() + geogrid.length() * geogrid.spacingY(); const double margin_x = std::abs(geogrid.spacingX()) * 20; @@ -1070,7 +1144,8 @@ void computeRtcBilinearDistribution(isce3::io::Raster& dem_raster, } } - _applyRtcMinValueDb(out_array, rtc_min_value_db, rtc_area_mode, info); + _applyRtcMinValueDb(out_array, rtc_min_value_db, rtc_transition_value_db, + rtc_min_value_mode, rtc_area_mode, info); output_raster.setBlock( out_array.data(), 0, 0, radar_grid.width(), radar_grid.length()); @@ -1623,6 +1698,8 @@ void computeRtcAreaProj(isce3::io::Raster& dem_raster, rtcOutputTerrainRadiometry output_terrain_radiometry, rtcAreaMode rtc_area_mode, rtcAreaBetaMode rtc_area_beta_mode, double geogrid_upsampling, float rtc_min_value_db, + float rtc_transition_value_db, + isce3::geometry::rtcMinValueMode rtc_min_value_mode, isce3::io::Raster* out_geo_rdr, isce3::io::Raster* out_geo_grid, isce3::io::Raster* out_sigma, const isce3::core::LUT2d& az_time_correction, @@ -1656,7 +1733,8 @@ void computeRtcAreaProj(isce3::io::Raster& dem_raster, geogrid.print(); print_parameters(info, radar_grid, input_terrain_radiometry, output_terrain_radiometry, rtc_area_mode, rtc_area_beta_mode, - geogrid_upsampling, rtc_min_value_db); + geogrid_upsampling, rtc_min_value_db, + rtc_transition_value_db, rtc_min_value_mode); int epsgcode = dem_raster.getEPSG(); info << "DEM EPSG: " << epsgcode << pyre::journal::endl; @@ -1759,7 +1837,9 @@ void computeRtcAreaProj(isce3::io::Raster& dem_raster, _normalizeRtcArea(out_gamma_array, out_beta_array, info); } - _applyRtcMinValueDb(out_gamma_array, rtc_min_value_db, rtc_area_mode, info); + _applyRtcMinValueDb(out_gamma_array, rtc_min_value_db, + rtc_transition_value_db, rtc_min_value_mode, + rtc_area_mode, info); info << "saving RTC area normalization factor" << pyre::journal::endl; output_raster.setBlock( @@ -1874,6 +1954,34 @@ std::string get_rtc_area_beta_mode_str(rtcAreaBetaMode rtc_area_beta_mode) return rtc_area_beta_mode_str; } +std::string get_rtc_min_value_mode_str( + isce3::geometry::rtcMinValueMode rtc_min_value_mode) +{ + std::string rtc_min_value_mode_str; + switch (rtc_min_value_mode) { + case isce3::geometry::rtcMinValueMode::DISABLED: + rtc_min_value_mode_str = "disabled (no minimum value thresholding applied)"; + break; + case isce3::geometry::rtcMinValueMode::CLIP: + rtc_min_value_mode_str = "clip (to RTC minimum value)"; + break; + case isce3::geometry::rtcMinValueMode::INVALID: + rtc_min_value_mode_str = "invalid (samples with RTC factor below minimum value are considered invalid)"; + break; + case isce3::geometry::rtcMinValueMode::BYPASS_RTC: + rtc_min_value_mode_str = "bypass RTC (no correction applied to samples with RTC factor below minimum value)"; + break; + case isce3::geometry::rtcMinValueMode::TRANSITION: + rtc_min_value_mode_str = "transition (same as bypass RTC, but with smooth transition between 'rtc_transition_value_db' and 'rtc_min_value_db')"; + break; + default: + std::string error_message = "ERROR invalid RTC min value mode"; + throw isce3::except::InvalidArgument(ISCE_SRCINFO(), error_message); + break; + } + return rtc_min_value_mode_str; +} + /** Convert enum output_mode to string */ std::string get_rtc_algorithm_str(rtcAlgorithm rtc_algorithm) @@ -1900,7 +2008,8 @@ void print_parameters(pyre::journal::info_t& channel, rtcOutputTerrainRadiometry output_terrain_radiometry, rtcAreaMode rtc_area_mode, rtcAreaBetaMode rtc_area_beta_mode, double geogrid_upsampling, - float rtc_min_value_db) + float rtc_min_value_db, float rtc_transition_value_db, + isce3::geometry::rtcMinValueMode rtc_min_value_mode) { std::string input_terrain_radiometry_str = get_input_terrain_radiometry_str(input_terrain_radiometry); @@ -1913,6 +2022,9 @@ void print_parameters(pyre::journal::info_t& channel, std::string rtc_area_beta_mode_str = get_rtc_area_beta_mode_str( rtc_area_beta_mode); + std::string rtc_min_value_mode_str = get_rtc_min_value_mode_str( + rtc_min_value_mode); + channel << "input radiometry: " << input_terrain_radiometry_str << pyre::journal::newline << "output radiometry: " << output_terrain_radiometry_str @@ -1926,7 +2038,12 @@ void print_parameters(pyre::journal::info_t& channel, << pyre::journal::newline << "radar-grid length: " << radar_grid.length() << ", width: " << radar_grid.width() << pyre::journal::newline - << "RTC min value [dB]: " << rtc_min_value_db - << pyre::journal::newline << pyre::journal::endl; + << "RTC min value mode: " << rtc_min_value_mode_str + << pyre::journal::newline; + if (rtc_min_value_mode != isce3::geometry::rtcMinValueMode::DISABLED) { + channel << "RTC min value [dB]: " << rtc_min_value_db + << pyre::journal::newline; + } + channel << pyre::journal::endl; } }} // namespace isce3::geometry diff --git a/cxx/isce3/geometry/RTC.h b/cxx/isce3/geometry/RTC.h index cd4275246..8bb95ffa3 100644 --- a/cxx/isce3/geometry/RTC.h +++ b/cxx/isce3/geometry/RTC.h @@ -39,6 +39,15 @@ enum rtcAreaMode { AREA = 0, AREA_FACTOR = 1 }; * RTC_AREA_PROJECTION) */ enum rtcAlgorithm { RTC_BILINEAR_DISTRIBUTION = 0, RTC_AREA_PROJECTION = 1 }; +/** Enumeration type to indicate RTC minimum value mode */ +enum rtcMinValueMode { + DISABLED = 0, + CLIP = 1, + INVALID = 2, + BYPASS_RTC = 3, + TRANSITION = 4 +}; + /**Enumeration type to indicate RTC area beta mode * (option only available for rtcAlgorithm.RTC_AREA_PROJECTION) */ @@ -79,6 +88,18 @@ enum rtcAreaBetaMode { * @param[in] rtc_min_value_db Minimum value for the RTC area normalization * factor. Radar data with RTC area normalization factor below this limit will * be set to NaN. + * @param[in] rtc_transition_value_db RTC transition start value in dB used when + * `rtc_min_value_mode = TRANSITION`. Samples with an RTC area factor + * between `rtc_transition_value_db` and `rtc_min_value_db` will have + * a smooth transition applied to the RTC correction. + * @param[in] rtc_min_value_mode Specifies how the RTC minimum value is handled: + * DISABLED - No minimum-value thresholding is applied. + * CLIP - RTC values below the minimum are clipped to the minimum value. + * INVALID - Samples with an RTC factor below the minimum value are marked as invalid. + * BYPASS_RTC - RTC correction is bypassed for samples with an RTC factor below + * the minimum value. + * TRANSITION - Same as BYPASS_RTC, but applies a smooth transition between + * `rtc_transition_value_db` and `rtc_min_value_db`. * @param[in] abs_cal_factor Absolute calibration factor. * @param[in] clip_min Clip minimum output values * @param[in] clip_max Clip maximum output values @@ -106,6 +127,9 @@ void applyRtc(const isce3::product::RadarGridParameters& radarGrid, rtcAreaBetaMode rtc_area_beta_mode = rtcAreaBetaMode::AUTO, double geogrid_upsampling = std::numeric_limits::quiet_NaN(), float rtc_min_value_db = std::numeric_limits::quiet_NaN(), + float rtc_transition_value_db = std::numeric_limits::quiet_NaN(), + isce3::geometry::rtcMinValueMode rtc_min_value_mode = + isce3::geometry::rtcMinValueMode::TRANSITION, double abs_cal_factor = 1, float clip_min = std::numeric_limits::quiet_NaN(), float clip_max = std::numeric_limits::quiet_NaN(), @@ -136,7 +160,19 @@ void applyRtc(const isce3::product::RadarGridParameters& radarGrid, * @param[in] geogrid_upsampling Geogrid upsampling * @param[in] rtc_min_value_db Minimum value for the RTC area normalization * factor. Radar data with RTC area normalization factor below this limit will - * be set to NaN.. + * be set to NaN. + * @param[in] rtc_transition_value_db RTC transition start value in dB used when + * `rtc_min_value_mode = TRANSITION`. Samples with an RTC area factor + * between `rtc_transition_value_db` and `rtc_min_value_db` will have + * a smooth transition applied to the RTC correction. + * @param[in] rtc_min_value_mode Specifies how the RTC minimum value is handled: + * DISABLED - No minimum-value thresholding is applied. + * CLIP - RTC values below the minimum are clipped to the minimum value. + * INVALID - Samples with an RTC factor below the minimum value are marked as invalid. + * BYPASS_RTC - RTC correction is bypassed for samples with an RTC factor below + * the minimum value. + * TRANSITION - Same as BYPASS_RTC, but applies a smooth transition between + * `rtc_transition_value_db` and `rtc_min_value_db`. * @param[out] out_sigma Output sigma surface area * (rtc_area_mode = AREA) or area factor (rtc_area_mode = AREA_FACTOR) raster * @param[in] az_time_correction Azimuth additive correction, in @@ -164,6 +200,9 @@ void computeRtc(const isce3::product::RadarGridParameters& radarGrid, rtcAreaBetaMode rtc_area_beta_mode = rtcAreaBetaMode::AUTO, double geogrid_upsampling = std::numeric_limits::quiet_NaN(), float rtc_min_value_db = std::numeric_limits::quiet_NaN(), + float rtc_transition_value_db = std::numeric_limits::quiet_NaN(), + isce3::geometry::rtcMinValueMode rtc_min_value_mode = + isce3::geometry::rtcMinValueMode::TRANSITION, isce3::io::Raster* out_sigma = nullptr, const isce3::core::LUT2d& az_time_correction = {}, const isce3::core::LUT2d& slant_range_correction = {}, @@ -203,6 +242,18 @@ void computeRtc(const isce3::product::RadarGridParameters& radarGrid, * @param[in] rtc_min_value_db Minimum value for the RTC area normalization * factor. Radar data with RTC area normalization factor below this limit will * be set to NaN + * @param[in] rtc_transition_value_db RTC transition start value in dB used when + * `rtc_min_value_mode = TRANSITION`. Samples with an RTC area factor + * between `rtc_transition_value_db` and `rtc_min_value_db` will have + * a smooth transition applied to the RTC correction. + * @param[in] rtc_min_value_mode Specifies how the RTC minimum value is handled: + * DISABLED - No minimum-value thresholding is applied. + * CLIP - RTC values below the minimum are clipped to the minimum value. + * INVALID - Samples with an RTC factor below the minimum value are marked as invalid. + * BYPASS_RTC - RTC correction is bypassed for samples with an RTC factor below + * the minimum value. + * TRANSITION - Same as BYPASS_RTC, but applies a smooth transition between + * `rtc_transition_value_db` and `rtc_min_value_db`. * @param[out] out_geo_rdr Raster to which the radar-grid positions * (range and azimuth) of the geogrid pixels vertices will be saved. * @param[out] out_geo_grid Raster to which the radar-grid positions @@ -236,6 +287,9 @@ void computeRtc(isce3::io::Raster& dem_raster, isce3::io::Raster& output_raster, rtcAreaBetaMode rtc_area_beta_mode = rtcAreaBetaMode::AUTO, double geogrid_upsampling = std::numeric_limits::quiet_NaN(), float rtc_min_value_db = std::numeric_limits::quiet_NaN(), + float rtc_transition_value_db = std::numeric_limits::quiet_NaN(), + isce3::geometry::rtcMinValueMode rtc_min_value_mode = + isce3::geometry::rtcMinValueMode::TRANSITION, isce3::io::Raster* out_geo_rdr = nullptr, isce3::io::Raster* out_geo_grid = nullptr, isce3::io::Raster* out_sigma = nullptr, @@ -266,6 +320,18 @@ void computeRtc(isce3::io::Raster& dem_raster, isce3::io::Raster& output_raster, * @param[in] rtc_min_value_db Minimum value for the RTC area normalization * factor. Radar data with RTC area normalization factor below this limit will * be set to NaN + * @param[in] rtc_transition_value_db RTC transition start value in dB used when + * `rtc_min_value_mode = TRANSITION`. Samples with an RTC area factor + * between `rtc_transition_value_db` and `rtc_min_value_db` will have + * a smooth transition applied to the RTC correction. + * @param[in] rtc_min_value_mode Specifies how the RTC minimum value is handled: + * DISABLED - No minimum-value thresholding is applied. + * CLIP - RTC values below the minimum are clipped to the minimum value. + * INVALID - Samples with an RTC factor below the minimum value are marked as invalid. + * BYPASS_RTC - RTC correction is bypassed for samples with an RTC factor below + * the minimum value. + * TRANSITION - Same as BYPASS_RTC, but applies a smooth transition between + * `rtc_transition_value_db` and `rtc_min_value_db`. * @param[out] out_sigma Output sigma surface area * (rtc_area_mode = AREA) or area factor (rtc_area_mode = AREA_FACTOR) raster * @param[in] threshold Azimuth time threshold for convergence (s) @@ -289,6 +355,9 @@ void computeRtcBilinearDistribution(isce3::io::Raster& dem_raster, rtcAreaMode rtc_area_mode = rtcAreaMode::AREA_FACTOR, double geogrid_upsampling = std::numeric_limits::quiet_NaN(), float rtc_min_value_db = std::numeric_limits::quiet_NaN(), + float rtc_transition_value_db = std::numeric_limits::quiet_NaN(), + isce3::geometry::rtcMinValueMode rtc_min_value_mode = + isce3::geometry::rtcMinValueMode::TRANSITION, isce3::io::Raster* out_sigma = nullptr, double threshold = 1e-8, int num_iter = 100, double delta_range = 1e-8, const isce3::core::LUT2d& az_time_correction = {}, @@ -314,7 +383,19 @@ void computeRtcBilinearDistribution(isce3::io::Raster& dem_raster, * @param[in] geogrid_upsampling Geogrid upsampling * @param[in] rtc_min_value_db Minimum value for the RTC area normalization * factor. Radar data with RTC area normalization factor below this limit will - * be set to NaN.. + * be set to NaN. + * @param[in] rtc_transition_value_db RTC transition start value in dB used when + * `rtc_min_value_mode = TRANSITION`. Samples with an RTC area factor + * between `rtc_transition_value_db` and `rtc_min_value_db` will have + * a smooth transition applied to the RTC correction. + * @param[in] rtc_min_value_mode Specifies how the RTC minimum value is handled: + * DISABLED - No minimum-value thresholding is applied. + * CLIP - RTC values below the minimum are clipped to the minimum value. + * INVALID - Samples with an RTC factor below the minimum value are marked as invalid. + * BYPASS_RTC - RTC correction is bypassed for samples with an RTC factor below + * the minimum value. + * TRANSITION - Same as BYPASS_RTC, but applies a smooth transition between + * `rtc_transition_value_db` and `rtc_min_value_db`. * @param[out] out_geo_rdr Raster to which the radar-grid positions * (range and azimuth) of the geogrid pixels vertices will be saved. * @param[out] out_geo_grid Raster to which the radar-grid positions @@ -347,6 +428,9 @@ void computeRtcAreaProj(isce3::io::Raster& dem, rtcAreaBetaMode rtc_area_beta_mode = rtcAreaBetaMode::AUTO, double geogrid_upsampling = std::numeric_limits::quiet_NaN(), float rtc_min_value_db = std::numeric_limits::quiet_NaN(), + float rtc_transition_value_db = std::numeric_limits::quiet_NaN(), + isce3::geometry::rtcMinValueMode rtc_min_value_mode = + isce3::geometry::rtcMinValueMode::TRANSITION, isce3::io::Raster* out_geo_rdr = nullptr, isce3::io::Raster* out_geo_grid = nullptr, isce3::io::Raster* out_sigma = nullptr, @@ -375,6 +459,8 @@ std::string get_output_terrain_radiometry_str( rtcOutputTerrainRadiometry output_terrain_radiometry); std::string get_rtc_area_mode_str(rtcAreaMode rtc_area_mode); std::string get_rtc_area_beta_mode_str(rtcAreaBetaMode rtc_area_beta_mode); +std::string get_rtc_min_value_mode_str( + rtcMinValueMode rtc_min_value_mode); std::string get_rtc_algorithm_str(rtcAlgorithm rtc_algorithm); void print_parameters(pyre::journal::info_t& channel, @@ -384,5 +470,8 @@ void print_parameters(pyre::journal::info_t& channel, rtcAreaMode rtc_area_mode, rtcAreaBetaMode rtc_area_beta_mode, double geogrid_upsampling, - float rtc_min_value_db); + float rtc_min_value_db, + float rtc_transition_value_db, + isce3::geometry::rtcMinValueMode rtc_min_value_mode = + isce3::geometry::rtcMinValueMode::TRANSITION); }} // namespace isce3::geometry diff --git a/python/extensions/pybind_isce3/geocode/GeocodeCov.cpp b/python/extensions/pybind_isce3/geocode/GeocodeCov.cpp index 255df9108..05e12b8c3 100644 --- a/python/extensions/pybind_isce3/geocode/GeocodeCov.cpp +++ b/python/extensions/pybind_isce3/geocode/GeocodeCov.cpp @@ -22,6 +22,7 @@ using isce3::geometry::rtcAlgorithm; using isce3::geometry::rtcAreaBetaMode; using isce3::geometry::rtcInputTerrainRadiometry; using isce3::geometry::rtcOutputTerrainRadiometry; +using isce3::geometry::rtcMinValueMode; using isce3::io::Raster; using isce3::product::RadarGridParameters; @@ -81,6 +82,9 @@ void addbinding(py::class_>& pyGeocode) py::arg("exponent") = 0, py::arg("rtc_min_value_db") = std::numeric_limits::quiet_NaN(), + py::arg("rtc_transition_value_db") = + std::numeric_limits::quiet_NaN(), + py::arg("rtc_min_value_mode") = rtcMinValueMode::DISABLED, py::arg("rtc_upsampling") = std::numeric_limits::quiet_NaN(), py::arg("rtc_algorithm") = @@ -175,7 +179,21 @@ void addbinding(py::class_>& pyGeocode) of the input raster (1 for real and 2 for complex rasters). rtc_min_value_db: float, optional Minimum value for the RTC area factor. Radar data with - RTC area factor below this limit will be set to NaN. + RTC area factor below this limit will be considered invalid. + rtc_transition_value_db : float, optional + RTC transition start value in dB used when + `rtc_min_value_mode = TRANSITION`. Samples with an RTC area factor + between `rtc_transition_value_db` and `rtc_min_value_db` will have + a smooth transition applied to the RTC correction. + rtc_min_value_mode: isce3.geometry.RtcMinValueMode, optional + Specifies how the RTC minimum value is handled: + DISABLED - No minimum-value thresholding is applied. + CLIP - RTC values below the minimum are clipped to the minimum value. + INVALID - Samples with an RTC factor below the minimum value are marked as invalid. + BYPASS_RTC - RTC correction is bypassed for samples with an RTC factor below + the minimum value. + TRANSITION - Same as BYPASS_RTC, but applies a smooth transition between + `rtc_transition_value_db` and `rtc_min_value_db`. rtc_geogrid_upsampling: int, optional Geogrid upsampling to compute the radiometric terrain correction RTC. diff --git a/python/extensions/pybind_isce3/geocode/GeocodePolygon.cpp b/python/extensions/pybind_isce3/geocode/GeocodePolygon.cpp index ee194d5fd..8141e395a 100644 --- a/python/extensions/pybind_isce3/geocode/GeocodePolygon.cpp +++ b/python/extensions/pybind_isce3/geocode/GeocodePolygon.cpp @@ -10,7 +10,7 @@ namespace py = pybind11; using isce3::geocode::GeocodePolygon; using isce3::geometry::rtcInputTerrainRadiometry; using isce3::geometry::rtcOutputTerrainRadiometry; -using isce3::geometry::rtcInputTerrainRadiometry; +using isce3::geometry::rtcMinValueMode; template void addbinding(py::class_> &pyGeocodePolygon) @@ -25,7 +25,7 @@ void addbinding(py::class_> &pyGeocodePolygon) const isce3::core::LUT2d &, isce3::io::Raster &, double, - int, + int, double>(), py::arg("x_vect"), py::arg("y_vect"), @@ -70,6 +70,8 @@ void addbinding(py::class_> &pyGeocodePolygon) py::arg("exponent") = 0, py::arg("geogrid_upsampling") = 1, py::arg("rtc_min_value_db") = std::numeric_limits::quiet_NaN(), + py::arg("rtc_transition_value_db") = std::numeric_limits::quiet_NaN(), + py::arg("rtc_min_value_mode") = rtcMinValueMode::DISABLED, py::arg("abs_cal_factor") = 1, py::arg("radargrid_nlooks") = 1, py::arg("output_off_diag_terms") = nullptr, @@ -80,7 +82,9 @@ void addbinding(py::class_> &pyGeocodePolygon) R"( Calculate the mean value of radar-grid samples using a polygon defined over geographical coordinates. - Arguments: + + Parameters: + ---------- radar_grid Radar grid input_dop Doppler LUT associated with the radar grid input_raster Input raster @@ -95,6 +99,15 @@ void addbinding(py::class_> &pyGeocodePolygon) output_mode Output mode geogrid_upsampling Geogrid upsampling (in each direction) rtc_min_value_db Minimum value for the RTC area factor. + rtc_min_value_mode + Determine whether to clip RTC values + below the minimum RTC value specified by `rtc_min_value_db`, instead of + considering associated radar samples as invalid. + If `true`, RTC values below the minimum threshold are clipped to + that threshold and associated radar samples are considered valid. + If `false`, radar samples corresponding to RTC values below the + minimum threshold are considered invalid, which may result in + NaNs in the output if no valid samples are available. Radar data with RTC area factor below this limit are ignored. abs_cal_factor Absolute calibration factor. radar_grid_nlooks Radar grid number of looks. This diff --git a/python/extensions/pybind_isce3/geometry/RTC.cpp b/python/extensions/pybind_isce3/geometry/RTC.cpp index e8735250d..d967d56c4 100644 --- a/python/extensions/pybind_isce3/geometry/RTC.cpp +++ b/python/extensions/pybind_isce3/geometry/RTC.cpp @@ -13,6 +13,7 @@ namespace py = pybind11; using isce3::geometry::rtcAlgorithm; using isce3::geometry::rtcInputTerrainRadiometry; using isce3::geometry::rtcOutputTerrainRadiometry; +using isce3::geometry::rtcMinValueMode; using isce3::geometry::rtcAreaMode; using isce3::geometry::rtcAreaBetaMode; @@ -32,6 +33,17 @@ void addbinding( .value("GAMMA_NAUGHT", rtcOutputTerrainRadiometry::GAMMA_NAUGHT); } +void addbinding( + py::enum_& pyRtcMinValueMode) +{ + pyRtcMinValueMode + .value("DISABLED", rtcMinValueMode::DISABLED) + .value("CLIP", rtcMinValueMode::CLIP) + .value("INVALID", rtcMinValueMode::INVALID) + .value("BYPASS_RTC", rtcMinValueMode::BYPASS_RTC) + .value("TRANSITION", rtcMinValueMode::TRANSITION); +} + void addbinding(py::enum_ & pyAlgorithm) { pyAlgorithm @@ -87,6 +99,9 @@ void addbinding_apply_rtc(pybind11::module& m) std::numeric_limits::quiet_NaN(), py::arg("rtc_min_value_db") = std::numeric_limits::quiet_NaN(), + py::arg("rtc_transition_value_db") = + std::numeric_limits::quiet_NaN(), + py::arg("rtc_min_value_mode") = rtcMinValueMode::DISABLED, py::arg("abs_cal_factor") = 1, py::arg("clip_min") = std::numeric_limits::quiet_NaN(), py::arg("clip_max") = std::numeric_limits::quiet_NaN(), @@ -133,6 +148,20 @@ void addbinding_apply_rtc(pybind11::module& m) rtc_min_value_db : float, optional Minimum value for the RTC area factor. Radar data with RTC area factor below this limit are ignored. + rtc_transition_value_db : float, optional + RTC transition start value in dB used when + `rtc_min_value_mode = TRANSITION`. Samples with an RTC area factor + between `rtc_transition_value_db` and `rtc_min_value_db` will have + a smooth transition applied to the RTC correction. + rtc_min_value_mode: isce3.geometry.RtcMinValueMode, optional + Specifies how the RTC minimum value is handled: + DISABLED - No minimum-value thresholding is applied. + CLIP - RTC values below the minimum are clipped to the minimum value. + INVALID - Samples with an RTC factor below the minimum value are marked as invalid. + BYPASS_RTC - RTC correction is bypassed for samples with an RTC factor below + the minimum value. + TRANSITION - Same as BYPASS_RTC, but applies a smooth transition between + `rtc_transition_value_db` and `rtc_min_value_db`. abs_cal_factor : double, optional Absolute calibration factor. clip_min : float, optional @@ -167,7 +196,7 @@ void addbinding_compute_rtc(pybind11::module& m) isce3::io::Raster&, rtcInputTerrainRadiometry, rtcOutputTerrainRadiometry, rtcAreaMode, rtcAlgorithm, rtcAreaBetaMode, - double, float, isce3::io::Raster*, + double, float, float, rtcMinValueMode, isce3::io::Raster*, const isce3::core::LUT2d&, const isce3::core::LUT2d&, isce3::core::MemoryModeBlocksY, @@ -189,6 +218,9 @@ void addbinding_compute_rtc(pybind11::module& m) std::numeric_limits::quiet_NaN(), py::arg("rtc_min_value_db") = std::numeric_limits::quiet_NaN(), + py::arg("rtc_transition_value_db") = + std::numeric_limits::quiet_NaN(), + py::arg("rtc_min_value_mode") = rtcMinValueMode::DISABLED, py::arg("out_sigma") = nullptr, py::arg("az_time_correction") = isce3::core::LUT2d(), py::arg("slant_range_correction") = isce3::core::LUT2d(), @@ -233,7 +265,21 @@ void addbinding_compute_rtc(pybind11::module& m) rtc_min_value_db : float, optional Minimum value for the RTC area factor. Radar data with RTC area factor below this limit are ignored. + rtc_transition_value_db : float, optional + RTC transition start value in dB used when + `rtc_min_value_mode = TRANSITION`. Samples with an RTC area factor + between `rtc_transition_value_db` and `rtc_min_value_db` will have + a smooth transition applied to the RTC correction. + rtc_min_value_mode: isce3.geometry.RtcMinValueMode, optional + Specifies how the RTC minimum value is handled: + DISABLED - No minimum-value thresholding is applied. + CLIP - RTC values below the minimum are clipped to the minimum value. + INVALID - Samples with an RTC factor below the minimum value are marked as invalid. + BYPASS_RTC - RTC correction is bypassed for samples with an RTC factor below + the minimum value. + TRANSITION - Same as BYPASS_RTC, but applies a smooth transition between out_sigma : isce3.io.Raster, optional + `rtc_transition_value_db` and `rtc_min_value_db`. Output sigma surface area (rtc_area_mode = AREA) or area factor (rtc_area_mode = AREA_FACTOR) raster az_time_correction: isce3.core.LUT2d @@ -271,7 +317,7 @@ void addbinding_compute_rtc_bbox(pybind11::module& m) const int, const int, rtcInputTerrainRadiometry, rtcOutputTerrainRadiometry, rtcAreaMode, rtcAlgorithm, rtcAreaBetaMode, - double, float, isce3::io::Raster*, + double, float, float, rtcMinValueMode, isce3::io::Raster*, isce3::io::Raster*, isce3::io::Raster*, const isce3::core::LUT2d&, const isce3::core::LUT2d&, @@ -297,6 +343,9 @@ void addbinding_compute_rtc_bbox(pybind11::module& m) std::numeric_limits::quiet_NaN(), py::arg("rtc_min_value_db") = std::numeric_limits::quiet_NaN(), + py::arg("rtc_transition_value_db") = + std::numeric_limits::quiet_NaN(), + py::arg("rtc_min_value_mode") = rtcMinValueMode::DISABLED, py::arg("out_geo_rdr") = nullptr, py::arg("out_geo_grid") = nullptr, py::arg("out_sigma") = nullptr, py::arg("az_time_correction") = isce3::core::LUT2d(), @@ -355,7 +404,21 @@ void addbinding_compute_rtc_bbox(pybind11::module& m) Geogrid upsampling (in each direction) rtc_min_value_db : float, optional Minimum value for the RTC area factor. Radar - data with RTC area factor below this limit are ignored. + data with RTC area factor below this limit are ignored. + rtc_transition_value_db : float, optional + RTC transition start value in dB used when + `rtc_min_value_mode = TRANSITION`. Samples with an RTC area factor + between `rtc_transition_value_db` and `rtc_min_value_db` will have + a smooth transition applied to the RTC correction. + rtc_min_value_mode: isce3.geometry.RtcMinValueMode, optional + Specifies how the RTC minimum value is handled: + DISABLED - No minimum-value thresholding is applied. + CLIP - RTC values below the minimum are clipped to the minimum value. + INVALID - Samples with an RTC factor below the minimum value are marked as invalid. + BYPASS_RTC - RTC correction is bypassed for samples with an RTC factor below + the minimum value. + TRANSITION - Same as BYPASS_RTC, but applies a smooth transition between + `rtc_transition_value_db` and `rtc_min_value_db`. out_geo_rdr : isce3.io.Raster, optional Raster to which the radar-grid positions (range and azimuth) of the geogrid pixels vertices will be saved (output). diff --git a/python/extensions/pybind_isce3/geometry/RTC.h b/python/extensions/pybind_isce3/geometry/RTC.h index ceb1acc08..7658e43eb 100644 --- a/python/extensions/pybind_isce3/geometry/RTC.h +++ b/python/extensions/pybind_isce3/geometry/RTC.h @@ -8,11 +8,14 @@ using isce3::geometry::rtcAreaMode; using isce3::geometry::rtcAreaBetaMode; using isce3::geometry::rtcInputTerrainRadiometry; using isce3::geometry::rtcOutputTerrainRadiometry; +using isce3::geometry::rtcMinValueMode; void addbinding( pybind11::enum_& pyInputTerrainRadiometry); void addbinding( pybind11::enum_& pyOutputTerrainRadiometry); +void addbinding( + pybind11::enum_& pyRtcMinValueMode); void addbinding(pybind11::enum_ & pyRtcAlgorithm); void addbinding(pybind11::enum_ & pyRtcAreaMode); void addbinding(pybind11::enum_ & pyRtcAreaBetaMode); diff --git a/python/extensions/pybind_isce3/geometry/geometry.cpp b/python/extensions/pybind_isce3/geometry/geometry.cpp index 8193aa3bd..012a87bab 100644 --- a/python/extensions/pybind_isce3/geometry/geometry.cpp +++ b/python/extensions/pybind_isce3/geometry/geometry.cpp @@ -38,6 +38,8 @@ void addsubmodule_geometry(py::module & m) pyInputTerrainRadiometry(geometry, "RtcInputTerrainRadiometry"); py::enum_ pyOutputTerrainRadiometry(geometry, "RtcOutputTerrainRadiometry"); + py::enum_ + pyRtcMinValueMode(geometry, "RtcMinValueMode"); py::enum_ pyRtcAlgorithm(geometry, "RtcAlgorithm"); py::enum_ @@ -51,6 +53,7 @@ void addsubmodule_geometry(py::module & m) addbinding(pyRdr2Geo); addbinding(pyInputTerrainRadiometry); addbinding(pyOutputTerrainRadiometry); + addbinding(pyRtcMinValueMode); addbinding(pyRtcAlgorithm); addbinding(pyRtcAreaMode); addbinding(pyRtcAreaBetaMode); diff --git a/python/packages/nisar/products/writers/GcovWriter.py b/python/packages/nisar/products/writers/GcovWriter.py index 3016bd31c..06c0aa654 100644 --- a/python/packages/nisar/products/writers/GcovWriter.py +++ b/python/packages/nisar/products/writers/GcovWriter.py @@ -48,6 +48,8 @@ def run_geocode_cov(cfg, hdf5_obj, root_ds, rtc_algorithm = rtc_dict['algorithm_type_enum'] input_terrain_radiometry = rtc_dict['input_terrain_radiometry_enum'] rtc_min_value_db = rtc_dict['rtc_min_value_db'] + rtc_transition_value_db = rtc_dict['rtc_transition_value_db'] + rtc_min_value_mode = rtc_dict['rtc_min_value_mode_enum'] rtc_upsampling = rtc_dict['dem_upsampling'] rtc_area_beta_mode = \ @@ -221,6 +223,8 @@ def run_geocode_cov(cfg, hdf5_obj, root_ds, input_terrain_radiometry=input_terrain_radiometry, output_terrain_radiometry=output_terrain_radiometry, rtc_min_value_db=rtc_min_value_db, + rtc_transition_value_db=rtc_transition_value_db, + rtc_min_value_mode=rtc_min_value_mode, rtc_upsampling=rtc_upsampling, rtc_algorithm=rtc_algorithm, radargrid_nlooks=radar_grid_nlooks, diff --git a/python/packages/nisar/workflows/gcov_runconfig.py b/python/packages/nisar/workflows/gcov_runconfig.py index 81443c1f5..b18a0b60d 100644 --- a/python/packages/nisar/workflows/gcov_runconfig.py +++ b/python/packages/nisar/workflows/gcov_runconfig.py @@ -102,6 +102,26 @@ def load(self): rtc_dict['output_type_enum'] = \ isce3.geometry.RtcOutputTerrainRadiometry.GAMMA_NAUGHT + rtc_min_value_mode = rtc_dict['rtc_min_value_mode'] + if rtc_min_value_mode == 'disabled': + rtc_dict['rtc_min_value_mode_enum'] = \ + isce3.geometry.RtcMinValueMode.DISABLED + elif rtc_min_value_mode == 'clip': + rtc_dict['rtc_min_value_mode_enum'] = \ + isce3.geometry.RtcMinValueMode.CLIP + elif rtc_min_value_mode == 'invalid': + rtc_dict['rtc_min_value_mode_enum'] = \ + isce3.geometry.RtcMinValueMode.INVALID + elif rtc_min_value_mode == 'bypass_rtc': + rtc_dict['rtc_min_value_mode_enum'] = \ + isce3.geometry.RtcMinValueMode.BYPASS_RTC + elif rtc_min_value_mode == 'transition': + rtc_dict['rtc_min_value_mode_enum'] = \ + isce3.geometry.RtcMinValueMode.TRANSITION + else: + raise ValueError( + f"unexpected rtc_min_value_mode: {rtc_min_value_mode}") + geocode_algorithm = self.cfg['processing']['geocode']['algorithm_type'] geocode_dict['output_mode'] = \ isce3.geocode.normalize_geocode_output_mode(geocode_algorithm) diff --git a/share/nisar/defaults/gcov.yaml b/share/nisar/defaults/gcov.yaml index edca80568..9e92fbe80 100644 --- a/share/nisar/defaults/gcov.yaml +++ b/share/nisar/defaults/gcov.yaml @@ -254,12 +254,28 @@ runconfig: # "sigma0" input_terrain_radiometry: beta0 + # RTC minimum value mode. Options: + # "disabled" - No minimum value enforcement + # "clip" - Clip values below the minimum RTC area factor + # "invalid" - Set output pixels to invalid where RTC area factor is below + # the minimum threshold + # "bypass_rtc" - Bypass RTC correction where RTC area factor is below + # the minimum threshold (i.e., output pixel = input pixel) + # "transition" - Apply a smooth (linear) transition between threshold value + # defined by `rtc_min_value_db` and the bypass RTC value + # defined by `rtc_transition_value_db` + rtc_min_value_mode: transition + # Minimum RTC area factor (in dB). Specifies the lowest # allowable denominator (in dB) for dividing GCOV samples. # If not set, no minimum is enforced, which may lead # to divisions by very small values and result in infinite # or inaccurate outputs. - rtc_min_value_db: + rtc_min_value_db: -30 + + # RTC transition value (in dB). Only relevant if + # rtc_min_value_mode is 'transition' + rtc_transition_value_db: -27 # RTC DEM upsampling factor dem_upsampling: 2 diff --git a/share/nisar/schemas/gcov.yaml b/share/nisar/schemas/gcov.yaml index 398696262..8b2835c7e 100644 --- a/share/nisar/schemas/gcov.yaml +++ b/share/nisar/schemas/gcov.yaml @@ -344,6 +344,17 @@ rtc_options: # Input terrain radiometry convention input_terrain_radiometry: enum('beta0', 'sigma0', required=False) + # RTC minimum value mode. Options: + # "disabled" - No minimum value enforcement + # "clip" - Clip values below the minimum RTC area factor + # "invalid" - Set output pixels to invalid where RTC area factor is below + # the minimum threshold + # "bypass_rtc" - Bypass RTC correction where RTC area factor is below + # the minimum threshold (i.e., output pixel = input pixel) + # "transition" - Same as "bypass_rtc", but with a smooth transition between the + # `rtc_transition_value_db` and `rtc_min_value_db` thresholds + rtc_min_value_mode: enum('disabled', 'clip', 'invalid', 'bypass_rtc', 'transition', required=False) + # Minimum RTC area factor (in dB). Specifies the lowest # allowable denominator (in dB) for dividing GCOV samples. # If not set, no minimum is enforced, which may lead @@ -351,6 +362,10 @@ rtc_options: # or inaccurate outputs. rtc_min_value_db: num(required=False) + # RTC transition value (in dB). Only relevant if + # rtc_min_value_mode is 'transition' + rtc_transition_value_db: num(required=False) + # RTC DEM upsampling factor dem_upsampling: int(min=1, required=False) diff --git a/tests/cxx/isce3/geocode/geocodeCov.cpp b/tests/cxx/isce3/geocode/geocodeCov.cpp index 26e2eb922..e4b294c5d 100644 --- a/tests/cxx/isce3/geocode/geocodeCov.cpp +++ b/tests/cxx/isce3/geocode/geocodeCov.cpp @@ -123,6 +123,9 @@ TEST(GeocodeTest, TestGeocodeCov) { isce3::geometry::rtcOutputTerrainRadiometry::GAMMA_NAUGHT; int exponent = 0; float rtc_min_value_db = std::numeric_limits::quiet_NaN(); + float rtc_transition_value_db = std::numeric_limits::quiet_NaN(); + isce3::geometry::rtcMinValueMode rtc_min_value_mode = + isce3::geometry::rtcMinValueMode::TRANSITION; double rtc_geogrid_upsampling = std::numeric_limits::quiet_NaN(); isce3::geometry::rtcAlgorithm rtc_algorithm = @@ -245,6 +248,7 @@ TEST(GeocodeTest, TestGeocodeCov) { flatten, geogrid_upsampling, flag_upsample_radar_grid, flag_apply_rtc, input_terrain_radiometry, output_terrain_radiometry, exponent, rtc_min_value_db, + rtc_transition_value_db, rtc_min_value_mode, rtc_geogrid_upsampling, rtc_algorithm, rtc_area_beta_mode, abs_cal_factor, clip_min, clip_max, min_nlooks, radar_grid_nlooks, @@ -301,7 +305,8 @@ TEST(GeocodeTest, TestGeocodeCov) { demRaster, output_mode, flag_az_baseband_doppler, flatten, geogrid_upsampling, flag_upsample_radar_grid, flag_apply_rtc, input_terrain_radiometry, output_terrain_radiometry, exponent, - rtc_min_value_db, rtc_geogrid_upsampling, rtc_algorithm, + rtc_min_value_db, rtc_transition_value_db, rtc_min_value_mode, + rtc_geogrid_upsampling, rtc_algorithm, rtc_area_beta_mode, abs_cal_factor, clip_min, clip_max, min_nlooks, radar_grid_nlooks, &geocoded_off_diag_raster, out_geo_rdr, out_geo_dem,