Skip to content

Commit afdf0b0

Browse files
gshiromartburns-jpl
authored andcommitted
Update geocode polygon (#518)
* moving files geocode/Geocode.* to geocode/GeocodeCov.* * moving cython files geocode/Geocode.* to geocode/GeocodeCov.* * updating c++ modules, cython- and pybind11 bindinds to new location for the Geocode module * fixing RTC memory mode in the RTC cython binding * fix bindings and tests * Substitute function getGeoAreaElementMean by class GeocodePolygon and update respective bindings * update branch after Geoff's reviews in #516 * fix unit tests * update search for min. and max. height (to define the geogrid bbox) * update GeocodePolygon geo2rdr threshold defaults * substitute indexes by indices * add pybind11 bindings, remove empty constructor, and refactor c++ code * update docstrings * refactor GeocodePolygon * substitute pairs of std::min/std::max by std::minmax_element * fix GeocodePolygon docstrings * default flag_apply_rtc to false, substitute rtc_min_val_db by rtc_min_value_db * simplify multiplication of abs_cal_factor / nlooks * remove second (unnecessary) validation of GeocodePolygon attributes * revert changes. _ValidatePolygon needs to run inside getPolygonMean because radar_grid may change * separate GeocodePolygon from GeocodeCov compilation unit * remove unnecessary imports * remove unnecessary imports (pybinds) * remove commented code * move geocoded shared function from GeocodeCov.icc to GeocodeHelpers.h * do not remove trailing newline in GeocodeCov.icc * Update cxx/isce3/geocode/GeocodeHelpers.h Co-Authored-By: Ryan Burns <[email protected]> Co-authored-by: Ryan Burns <[email protected]>
1 parent 66d088f commit afdf0b0

File tree

14 files changed

+848
-402
lines changed

14 files changed

+848
-402
lines changed

cxx/isce3/Headers.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ geometry/Geo2rdr.h
8989
geometry/Geo2rdr.icc
9090
geocode/GeocodeCov.h
9191
geocode/GeocodeCov.icc
92+
geocode/GeocodePolygon.h
9293
geometry/geometry.h
9394
geometry/RTC.h
9495
geometry/Topo.h

cxx/isce3/Sources.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ geocode/loadDem.cpp
4343
geometry/DEMInterpolator.cpp
4444
geometry/Geo2rdr.cpp
4545
geocode/GeocodeCov.cpp
46+
geocode/GeocodePolygon.cpp
4647
geometry/geometry.cpp
4748
geometry/RTC.cpp
4849
geometry/Topo.cpp

cxx/isce3/geocode/GeocodeCov.cpp

Lines changed: 3 additions & 350 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "GeocodeCov.h"
2+
#include "GeocodeHelpers.h"
23

34
#include <algorithm>
45
#include <cmath>
@@ -22,48 +23,6 @@ using isce3::core::Vec3;
2223

2324
namespace isce3 { namespace geocode {
2425

25-
template<typename T1, typename T2>
26-
auto operator*(const std::complex<T1>& lhs, const T2& rhs)
27-
{
28-
using U = typename std::common_type_t<T1, T2>;
29-
return std::complex<U>(lhs) * U(rhs);
30-
}
31-
32-
template<typename T1, typename T2>
33-
auto operator*(const T1& lhs, const std::complex<T2>& rhs)
34-
{
35-
using U = typename std::common_type_t<T1, T2>;
36-
return U(lhs) * std::complex<U>(rhs);
37-
}
38-
39-
template<typename T, typename T_out>
40-
void _convertToOutputType(T a, T_out& b)
41-
{
42-
b = a;
43-
}
44-
45-
template<typename T, typename T_out>
46-
void _convertToOutputType(std::complex<T> a, T_out& b)
47-
{
48-
b = std::norm(a);
49-
}
50-
51-
template<typename T, typename T_out>
52-
void _convertToOutputType(std::complex<T> a, std::complex<T_out>& b)
53-
{
54-
b = a;
55-
}
56-
57-
template<typename T, typename T_out>
58-
void _accumulate(T_out& band_value, T a, double b)
59-
{
60-
if (b == 0)
61-
return;
62-
T_out a2;
63-
_convertToOutputType(a, a2);
64-
band_value += a2 * b;
65-
}
66-
6726
template<class T>
6827
void Geocode<T>::updateGeoGrid(
6928
const isce3::product::RadarGridParameters& radar_grid,
@@ -1903,312 +1862,6 @@ template class Geocode<double>;
19031862
template class Geocode<std::complex<float>>;
19041863
template class Geocode<std::complex<double>>;
19051864

1906-
// template <typename T>
1907-
std::vector<float> getGeoAreaElementMean(
1908-
const std::vector<double>& x_vect, const std::vector<double>& y_vect,
1909-
const isce3::product::RadarGridParameters& radar_grid,
1910-
const isce3::core::Orbit& orbit,
1911-
const isce3::core::LUT2d<double>& input_dop,
1912-
isce3::io::Raster& input_raster, isce3::io::Raster& dem_raster,
1913-
bool flag_apply_rtc,
1914-
isce3::geometry::rtcInputTerrainRadiometry input_terrain_radiometry,
1915-
isce3::geometry::rtcOutputTerrainRadiometry output_terrain_radiometry,
1916-
int exponent, geocodeOutputMode output_mode, double geogrid_upsampling,
1917-
float rtc_min_value_db, double abs_cal_factor, float radar_grid_nlooks,
1918-
float* out_nlooks, isce3::core::dataInterpMethod dem_interp_method,
1919-
double threshold, int num_iter, double delta_range)
1920-
{
1921-
1922-
pyre::journal::info_t info("isce.geometry.getGeoAreaElementMean");
1923-
1924-
if (std::isnan(geogrid_upsampling))
1925-
geogrid_upsampling = 1;
1926-
assert(geogrid_upsampling > 0);
1927-
1928-
const double x0 = std::min_element(x_vect.begin(), x_vect.end())[0];
1929-
const double xf = std::max_element(x_vect.begin(), x_vect.end())[0];
1930-
1931-
const double y0 = std::min_element(y_vect.begin(), y_vect.end())[0];
1932-
const double yf = std::max_element(y_vect.begin(), y_vect.end())[0];
1933-
1934-
const double dx = dem_raster.dx();
1935-
const double dy = dem_raster.dy();
1936-
1937-
std::string input_terrain_radiometry_str =
1938-
get_input_terrain_radiometry_str(input_terrain_radiometry);
1939-
1940-
info << "input radiometry: " << input_terrain_radiometry_str
1941-
<< pyre::journal::newline << "look side: " << radar_grid.lookSide()
1942-
<< pyre::journal::newline
1943-
<< "radar_grid length: " << radar_grid.length()
1944-
<< ", width: " << radar_grid.width() << pyre::journal::newline
1945-
<< "RTC min value [dB]: " << rtc_min_value_db << pyre::journal::endl;
1946-
1947-
const double margin_x = std::abs(dx) * 10;
1948-
const double margin_y = std::abs(dy) * 10;
1949-
isce3::geometry::DEMInterpolator dem_interp;
1950-
1951-
dem_interp.loadDEM(dem_raster, x0 - margin_x, xf + margin_x,
1952-
std::min(y0, yf) - margin_y,
1953-
std::max(y0, yf) + margin_y);
1954-
1955-
isce3::core::Ellipsoid ellipsoid =
1956-
isce3::core::Ellipsoid(isce3::core::EarthSemiMajorAxis,
1957-
isce3::core::EarthEccentricitySquared);
1958-
1959-
int epsg = dem_raster.getEPSG();
1960-
std::unique_ptr<isce3::core::ProjectionBase> proj(
1961-
isce3::core::createProj(epsg));
1962-
const double pixazm = radar_grid.azimuthTimeInterval();
1963-
const double start = radar_grid.sensingStart() - 0.5 * pixazm;
1964-
const double dr = radar_grid.rangePixelSpacing();
1965-
double r0 = radar_grid.startingRange() - 0.5 * dr;
1966-
1967-
double a = radar_grid.sensingMid();
1968-
double r = radar_grid.midRange();
1969-
1970-
if (x_vect.size() != y_vect.size()) {
1971-
std::string error_message =
1972-
"ERROR x and y vectors have a different number of elements.";
1973-
throw isce3::except::InvalidArgument(ISCE_SRCINFO(), error_message);
1974-
}
1975-
int n_elements = x_vect.size();
1976-
std::vector<double> a_vect, r_vect;
1977-
a_vect.reserve(n_elements);
1978-
r_vect.reserve(n_elements);
1979-
1980-
info << "polygon indexes (a, r): ";
1981-
1982-
for (int i = 0; i < n_elements; ++i) {
1983-
1984-
const double x = x_vect[i];
1985-
const double y = y_vect[i];
1986-
1987-
const Vec3 dem11 = {x, y, dem_interp.interpolateXY(x, y)};
1988-
int converged = isce3::geometry::geo2rdr(
1989-
proj->inverse(dem11), ellipsoid, orbit, input_dop, a, r,
1990-
radar_grid.wavelength(), radar_grid.lookSide(), threshold,
1991-
num_iter, delta_range);
1992-
if (!converged) {
1993-
info << "WARNING convergence not found for vertex (x, y): " << x
1994-
<< ", " << y << pyre::journal::endl;
1995-
continue;
1996-
}
1997-
double a_index = (a - start) / pixazm;
1998-
double r_index = (r - r0) / dr;
1999-
2000-
info << "(" << a_index << ", " << r_index << "), ";
2001-
2002-
a_vect.emplace_back(a_index);
2003-
r_vect.emplace_back(r_index);
2004-
}
2005-
2006-
info << pyre::journal::endl;
2007-
2008-
const double a_min = std::min_element(a_vect.begin(), a_vect.end())[0];
2009-
const double a_max = std::max_element(a_vect.begin(), a_vect.end())[0];
2010-
2011-
const double r_min = std::min_element(r_vect.begin(), r_vect.end())[0];
2012-
const double r_max = std::max_element(r_vect.begin(), r_vect.end())[0];
2013-
2014-
const int y_min = std::max(0, (int) std::floor(a_min));
2015-
const int x_min = std::max(0, (int) std::floor(r_min));
2016-
const int ysize =
2017-
std::min((int) radar_grid.length(), (int) std::ceil(a_max)) - y_min;
2018-
const int xsize =
2019-
std::min((int) radar_grid.width(), (int) std::ceil(r_max)) - x_min;
2020-
2021-
info << "cropping radar grid from index (a0: " << y_min;
2022-
info << ", r0: " << x_min << ") to index (af: " << y_min + ysize;
2023-
info << ", rf: " << x_min + xsize << ")" << pyre::journal::endl;
2024-
2025-
isce3::product::RadarGridParameters radar_grid_cropped =
2026-
radar_grid.offsetAndResize(y_min, x_min, ysize, xsize);
2027-
2028-
info << "cropped radar_grid length: " << radar_grid_cropped.length()
2029-
<< ", width: " << radar_grid_cropped.width() << pyre::journal::newline;
2030-
2031-
if (output_mode == geocodeOutputMode::INTERP) {
2032-
std::string error_msg = "invalid option";
2033-
throw isce3::except::InvalidArgument(ISCE_SRCINFO(), error_msg);
2034-
}
2035-
2036-
if (abs_cal_factor != 1)
2037-
info << "absolute calibration factor: " << abs_cal_factor
2038-
<< pyre::journal::endl;
2039-
2040-
if (flag_apply_rtc) {
2041-
2042-
std::string input_terrain_radiometry_str =
2043-
get_input_terrain_radiometry_str(input_terrain_radiometry);
2044-
info << "input radiometry: " << input_terrain_radiometry_str
2045-
<< pyre::journal::endl;
2046-
}
2047-
2048-
isce3::core::Matrix<float> rtc_area;
2049-
std::unique_ptr<isce3::io::Raster> rtc_raster_unique_ptr;
2050-
if (flag_apply_rtc) {
2051-
2052-
info << "computing RTC area factor..." << pyre::journal::endl;
2053-
rtc_raster_unique_ptr = std::make_unique<isce3::io::Raster>(
2054-
"/vsimem/dummy", radar_grid_cropped.width(),
2055-
radar_grid_cropped.length(), 1, GDT_Float32, "ENVI");
2056-
isce3::geometry::rtcAreaMode rtc_area_mode =
2057-
isce3::geometry::rtcAreaMode::AREA_FACTOR;
2058-
isce3::geometry::rtcAlgorithm rtc_algorithm =
2059-
isce3::geometry::rtcAlgorithm::RTC_AREA_PROJECTION;
2060-
2061-
isce3::geometry::rtcMemoryMode rtc_memory_mode =
2062-
isce3::geometry::rtcMemoryMode::RTC_SINGLE_BLOCK;
2063-
2064-
computeRtc(radar_grid_cropped, orbit, input_dop, dem_raster,
2065-
*rtc_raster_unique_ptr.get(), input_terrain_radiometry,
2066-
output_terrain_radiometry, rtc_area_mode, rtc_algorithm,
2067-
geogrid_upsampling * 2, rtc_min_value_db, radar_grid_nlooks,
2068-
nullptr, rtc_memory_mode, dem_interp_method, threshold, num_iter,
2069-
delta_range);
2070-
2071-
rtc_area.resize(radar_grid_cropped.length(),
2072-
radar_grid_cropped.width());
2073-
2074-
rtc_raster_unique_ptr->getBlock(rtc_area.data(), 0, 0,
2075-
radar_grid_cropped.width(),
2076-
radar_grid_cropped.length(), 1);
2077-
2078-
info << "... done (RTC) " << pyre::journal::endl;
2079-
}
2080-
2081-
double rtc_min_value = 0;
2082-
if (!std::isnan(rtc_min_value_db) && flag_apply_rtc) {
2083-
rtc_min_value = std::pow(10., (rtc_min_value_db / 10.));
2084-
info << "RTC min. value: " << rtc_min_value_db
2085-
<< " [dB] = " << rtc_min_value << pyre::journal::endl;
2086-
}
2087-
2088-
GDALDataType input_dtype = input_raster.dtype();
2089-
if (exponent == 0 && GDALDataTypeIsComplex(input_dtype))
2090-
exponent = 2;
2091-
2092-
if (input_raster.dtype() == GDT_Float32) {
2093-
info << "dtype: GDT_Float32" << pyre::journal::endl;
2094-
return _getGeoAreaElementMean<float>(
2095-
r_vect, a_vect, x_min, y_min, flag_apply_rtc,
2096-
rtc_area, radar_grid_cropped,
2097-
input_raster, rtc_min_value, out_nlooks,
2098-
abs_cal_factor, radar_grid_nlooks);
2099-
} else if (input_raster.dtype() == GDT_CFloat32) {
2100-
info << "dtype: GDT_CFloat32" << pyre::journal::endl;
2101-
return _getGeoAreaElementMean<std::complex<float>>(
2102-
r_vect, a_vect, x_min, y_min, flag_apply_rtc,
2103-
rtc_area, radar_grid_cropped,
2104-
input_raster, rtc_min_value, out_nlooks,
2105-
abs_cal_factor, radar_grid_nlooks);
2106-
} else
2107-
info << "ERROR not implemented for datatype: " << input_raster.dtype()
2108-
<< pyre::journal::endl;
2109-
2110-
std::vector<float> empty_vector;
2111-
return empty_vector;
2112-
}
2113-
2114-
template<typename T>
2115-
std::vector<float> _getGeoAreaElementMean(
2116-
const std::vector<double>& r_vect, const std::vector<double>& a_vect,
2117-
int x_min, int y_min, bool flag_apply_rtc,
2118-
isce3::core::Matrix<float>& rtc_area,
2119-
const isce3::product::RadarGridParameters& radar_grid,
2120-
isce3::io::Raster& input_raster,
2121-
float rtc_min_value, float* out_nlooks, double abs_cal_factor,
2122-
float radar_grid_nlooks)
2123-
{
2124-
2125-
pyre::journal::info_t info("isce.geometry._getGeoAreaElementMean");
2126-
2127-
// number of bands in the input raster
2128-
const int nbands = input_raster.numBands();
2129-
const int size_y = radar_grid.length();
2130-
const int size_x = radar_grid.width();
2131-
info << "nbands: " << nbands << pyre::journal::endl;
2132-
2133-
std::vector<std::unique_ptr<isce3::core::Matrix<T>>> rdrDataBlock;
2134-
rdrDataBlock.reserve(nbands);
2135-
2136-
for (int band = 0; band < nbands; ++band) {
2137-
if (nbands == 1)
2138-
info << "loading slant-range image..." << pyre::journal::endl;
2139-
else
2140-
info << "loading slant-range band: " << band << pyre::journal::endl;
2141-
rdrDataBlock.emplace_back(
2142-
std::make_unique<isce3::core::Matrix<T>>(size_y, size_x));
2143-
2144-
input_raster.getBlock(rdrDataBlock[band]->data(), x_min, y_min,
2145-
size_x, size_y, band + 1);
2146-
}
2147-
2148-
isce3::core::Matrix<double> w_arr(size_y, size_x);
2149-
w_arr.fill(0);
2150-
2151-
int plane_orientation;
2152-
if (radar_grid.lookSide() == isce3::core::LookSide::Left)
2153-
plane_orientation = -1;
2154-
else
2155-
plane_orientation = 1;
2156-
2157-
double w_total = 0;
2158-
for (int i = 0; i < r_vect.size(); ++i) {
2159-
2160-
double x00, y00, x01, y01;
2161-
y00 = a_vect[i];
2162-
x00 = r_vect[i];
2163-
2164-
if (i < r_vect.size() - 1) {
2165-
y01 = a_vect[i + 1];
2166-
x01 = r_vect[i + 1];
2167-
} else {
2168-
y01 = a_vect[0];
2169-
x01 = r_vect[0];
2170-
}
2171-
isce3::geometry::areaProjIntegrateSegment(
2172-
y00 - y_min, y01 - y_min, x00 - x_min, x01 - x_min, size_y,
2173-
size_x, w_arr, w_total, plane_orientation);
2174-
}
2175-
std::vector<float> cumulative_sum(nbands);
2176-
double nlooks = 0;
2177-
2178-
Geocode<T> geo_obj;
2179-
for (int y = 0; y < size_y; ++y)
2180-
for (int x = 0; x < size_x; ++x) {
2181-
double w = w_arr(y, x);
2182-
if (w == 0)
2183-
continue;
2184-
if (flag_apply_rtc) {
2185-
const float rtc_value = rtc_area(y, x);
2186-
if (std::isnan(rtc_value) || rtc_value < rtc_min_value)
2187-
continue;
2188-
nlooks += w;
2189-
w /= rtc_value;
2190-
} else {
2191-
nlooks += w;
2192-
}
2193-
2194-
for (int band = 0; band < nbands; ++band)
2195-
_accumulate(cumulative_sum[band],
2196-
rdrDataBlock[band]->operator()(y, x), w);
2197-
}
2198-
2199-
info << "nlooks: " << radar_grid_nlooks * std::abs(nlooks)
2200-
<< pyre::journal::endl;
2201-
for (int band = 0; band < nbands; ++band) {
2202-
cumulative_sum[band] = (cumulative_sum[band] * abs_cal_factor / nlooks);
2203-
info << "mean value (band = " << band << "): " << cumulative_sum[band]
2204-
<< pyre::journal::endl;
2205-
}
2206-
2207-
if (out_nlooks != nullptr) {
2208-
*out_nlooks = radar_grid_nlooks * std::abs(nlooks);
2209-
}
2210-
2211-
return cumulative_sum;
2212-
}
22131865

2214-
}} // namespace isce3::geocode
1866+
} // namespace geocode
1867+
} // namespace isce3

0 commit comments

Comments
 (0)