Skip to content

Commit 7ad3ee8

Browse files
gshiromagmgunter
authored andcommitted
Add function to interpolate/reproject a DEM over a given geogrid (#786)
* add interpolateDem at the C++ level * add Python bindings of interpolateDem * add interpolateDem cpp and header to cmake * add Python bindings for interpolateDem (2) * rename interpolateDem to relocateRaster * remove debug prints * add unitest * substitute raster pointer with reference * update RTC loadDemFromProj() margin parameters from geogrid units to DEM pixels * fix upper right coordinates in relocateRaster() * git merge develop into prepare_dem (2) * add new line character to python/extensions/pybind_isce3/geogrid/geogrid.cpp * remove unnecessary space in python/extensions/pybind_isce3/geogrid/relocateRaster.cpp * fix docstrings identation * update relocate_raster pybind docstrings * fix variable name * move loadDemFromProj() from the RTC module to the DEMInterpolator module * move loadDemFromProj() from the RTC module to the DEMInterpolator module (2) * add option to load the DEM from different bands within the DEM raster * add option to relocate raster with multiple bands * remove commented code * add comment that test DEM is in EPSG 4326 * substitute DEM margins from DEM units to pixels * move load DEM functions from geocode namespace to geometry namespace (along with the DEMInterpolator) * update function to validate input and output rasters * update function to validate input and output rasters (2) * refactor code * update docstring * update function to validate input and output rasters (3) * update function to validate input and output rasters (4) * move load DEM functions from geocode namespace to geometry namespace (2) * Update cxx/isce3/geometry/loadDem.h Co-authored-by: Geoffrey M Gunter <[email protected]> * Update python/extensions/pybind_isce3/geogrid/relocateRaster.cpp Co-authored-by: Geoffrey M Gunter <[email protected]> * Update cxx/isce3/geogrid/relocateRaster.cpp Co-authored-by: Geoffrey M Gunter <[email protected]> * Update python/extensions/pybind_isce3/geometry/DEMInterpolator.cpp Co-authored-by: Geoffrey M Gunter <[email protected]> * Update python/extensions/pybind_isce3/geometry/DEMInterpolator.cpp Co-authored-by: Geoffrey M Gunter <[email protected]> * Update cxx/isce3/geogrid/relocateRaster.cpp Co-authored-by: Geoffrey M Gunter <[email protected]> * move getDemCoordsSameEpsg() and getDemCoordsDiffEpsg() from the RTC module to loadDem * update docstrings of function to relocate raster * remove unnecessary pragma omp directive Co-authored-by: Geoffrey M Gunter <[email protected]>
1 parent c2a7172 commit 7ad3ee8

File tree

26 files changed

+561
-189
lines changed

26 files changed

+561
-189
lines changed

cxx/isce3/Headers.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ focus/Presum.icc
8383
focus/RangeComp.h
8484
geocode/baseband.h
8585
geocode/geocodeSlc.h
86-
geocode/loadDem.h
8786
geometry/DEMInterpolator.h
87+
geometry/loadDem.h
8888
geometry/forward.h
8989
geometry/Shapes.h
9090
geometry/boundingbox.h
@@ -99,6 +99,7 @@ geometry/Topo.h
9999
geometry/Topo.icc
100100
geometry/TopoLayers.h
101101
geometry/metadataCubes.h
102+
geogrid/relocateRaster.h
102103
image/forward.h
103104
image/ResampSlc.h
104105
image/ResampSlc.icc

cxx/isce3/Sources.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ focus/Presum.cpp
4343
focus/RangeComp.cpp
4444
geocode/baseband.cpp
4545
geocode/geocodeSlc.cpp
46-
geocode/loadDem.cpp
4746
geometry/DEMInterpolator.cpp
47+
geometry/loadDem.cpp
4848
geometry/Geo2rdr.cpp
4949
geocode/GeocodeCov.cpp
5050
geocode/GeocodePolygon.cpp
@@ -53,6 +53,7 @@ geometry/RTC.cpp
5353
geometry/Topo.cpp
5454
geometry/TopoLayers.cpp
5555
geometry/metadataCubes.cpp
56+
geogrid/relocateRaster.cpp
5657
image/ResampSlc.cpp
5758
io/gdal/Dataset.cpp
5859
io/gdal/detail/MemoryMap.cpp

cxx/isce3/cuda/geocode/Geocode.cu

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
#include <isce3/cuda/geometry/gpuDEMInterpolator.h>
1919
#include <isce3/cuda/geometry/gpuGeometry.h>
2020
#include <isce3/except/Error.h>
21-
#include <isce3/geocode/loadDem.h>
2221
#include <isce3/geometry/DEMInterpolator.h>
22+
#include <isce3/geometry/loadDem.h>
2323
#include <isce3/product/GeoGridParameters.h>
2424

2525
#include "Geocode.h"
@@ -269,7 +269,7 @@ void Geocode::setBlockRdrCoordGrid(const size_t block_number)
269269
_mask.resize(block_size);
270270

271271
// prepare device DEMInterpolator
272-
isce3::geometry::DEMInterpolator host_dem_interp = isce3::geocode::loadDEM(
272+
isce3::geometry::DEMInterpolator host_dem_interp = isce3::geometry::loadDEM(
273273
_dem_raster, _geogrid, _line_start, _geo_block_length,
274274
_geogrid.width(), _dem_margin, _dem_interp_method);
275275
isce3::cuda::geometry::gpuDEMInterpolator dev_dem_interp(host_dem_interp);

cxx/isce3/geocode/GeocodeCov.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
#include <isce3/core/DenseMatrix.h>
1111
#include <isce3/core/Projections.h>
1212
#include <isce3/core/TypeTraits.h>
13-
#include <isce3/geocode/loadDem.h>
1413
#include <isce3/geometry/DEMInterpolator.h>
14+
#include <isce3/geometry/loadDem.h>
1515
#include <isce3/geometry/RTC.h>
1616
#include <isce3/geometry/boundingbox.h>
1717
#include <isce3/geometry/geometry.h>
@@ -450,7 +450,7 @@ void Geocode<T>::geocodeInterp(
450450
}
451451

452452
// load a block of DEM for the current geocoded grid
453-
isce3::geometry::DEMInterpolator demInterp = isce3::geocode::loadDEM(
453+
isce3::geometry::DEMInterpolator demInterp = isce3::geometry::loadDEM(
454454
demRaster, geogrid, lineStart, geoBlockLength, geogrid.width(),
455455
_demBlockMargin, dem_interp_method);
456456

cxx/isce3/geocode/geocodeSlc.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
#include <isce3/core/Poly2d.h>
1010
#include <isce3/core/Projections.h>
1111
#include <isce3/geocode/baseband.h>
12-
#include <isce3/geocode/loadDem.h>
1312
#include <isce3/geometry/DEMInterpolator.h>
13+
#include <isce3/geometry/loadDem.h>
1414
#include <isce3/geometry/geometry.h>
1515
#include <isce3/io/Raster.h>
1616
#include <isce3/product/GeoGridParameters.h>
@@ -362,8 +362,9 @@ void geocodeSlc(
362362

363363
// get a DEM interpolator for a block of DEM for the current geocoded
364364
// grid
365-
isce3::geometry::DEMInterpolator demInterp = loadDEM(demRaster, geoGrid,
366-
lineStart, geoBlockLength, geoGrid.width(), demBlockMargin);
365+
isce3::geometry::DEMInterpolator demInterp = isce3::geometry::loadDEM(
366+
demRaster, geoGrid, lineStart, geoBlockLength, geoGrid.width(),
367+
demBlockMargin);
367368

368369
// X and Y indices (in the radar coordinates) for the
369370
// geocoded pixels (after geo2rdr computation)

cxx/isce3/geocode/loadDem.h

Lines changed: 0 additions & 25 deletions
This file was deleted.
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#include "relocateRaster.h"
2+
3+
#include <string>
4+
#include <isce3/core/Projections.h>
5+
#include <isce3/io/Raster.h>
6+
#include <isce3/geometry/geometry.h>
7+
#include <isce3/geometry/DEMInterpolator.h>
8+
#include <isce3/geometry/loadDem.h>
9+
#include <isce3/product/GeoGridParameters.h>
10+
11+
namespace isce3 {
12+
namespace geogrid {
13+
14+
15+
template<class T>
16+
static isce3::core::Matrix<T>
17+
getNanArray(const isce3::product::GeoGridParameters& geogrid)
18+
{
19+
isce3::core::Matrix<T> data_array(geogrid.length(), geogrid.width());
20+
data_array.fill(std::numeric_limits<T>::quiet_NaN());
21+
return data_array;
22+
}
23+
24+
template<class T>
25+
static void writeArray(isce3::io::Raster& raster,
26+
isce3::core::Matrix<T>& data_array, int band_index)
27+
{
28+
raster.setBlock(data_array.data(), 0, 0, data_array.width(),
29+
data_array.length(), band_index + 1);
30+
}
31+
32+
void _validateRasters(isce3::io::Raster& input_raster,
33+
const isce3::product::GeoGridParameters& geogrid,
34+
isce3::io::Raster& output_raster) {
35+
36+
if (input_raster.getEPSG() < 0) {
37+
std::string error_message =
38+
"ERROR invalid input raster EPSG code: " +
39+
std::to_string(input_raster.getEPSG());
40+
throw isce3::except::RuntimeError(ISCE_SRCINFO(), error_message);
41+
}
42+
43+
if (geogrid.epsg() < 0) {
44+
std::string error_message =
45+
"ERROR invalid geogrid EPSG code: " +
46+
std::to_string(geogrid.epsg());
47+
throw isce3::except::RuntimeError(ISCE_SRCINFO(), error_message);
48+
}
49+
50+
if (geogrid.length() != output_raster.length() or
51+
geogrid.width() != output_raster.width()) {
52+
std::string error_message =
53+
"ERROR geogrid and output rasters have different dimensions";
54+
throw isce3::except::RuntimeError(ISCE_SRCINFO(), error_message);
55+
}
56+
57+
if (input_raster.numBands() != output_raster.numBands()) {
58+
std::string error_message =
59+
"ERROR input and output rasters have different number of bands: " +
60+
std::to_string(input_raster.numBands()) + " (input raster) vs " +
61+
std::to_string(input_raster.numBands()) + " (output raster)";
62+
throw isce3::except::RuntimeError(ISCE_SRCINFO(), error_message);
63+
}
64+
}
65+
66+
void relocateRaster(isce3::io::Raster& input_raster,
67+
const isce3::product::GeoGridParameters& geogrid,
68+
isce3::io::Raster& output_raster,
69+
isce3::core::dataInterpMethod interp_method) {
70+
71+
pyre::journal::info_t info("isce.geogrid.relocateRaster");
72+
73+
_validateRasters(input_raster, geogrid, output_raster);
74+
75+
geogrid.print();
76+
77+
auto proj = isce3::core::makeProjection(geogrid.epsg());
78+
79+
double refheight = 0;
80+
isce3::geometry::DEMInterpolator dem_interp(refheight, interp_method);
81+
const double minX = geogrid.startX();
82+
const double maxX = geogrid.startX() + (geogrid.spacingX() *
83+
geogrid.width());
84+
double minY = geogrid.startY();
85+
double maxY = geogrid.startY() + geogrid.spacingY() * geogrid.length();
86+
87+
const int dem_margin_in_pixels = 100;
88+
89+
for (int band_index = 0; band_index < input_raster.numBands();
90+
++band_index) {
91+
92+
auto error_code = loadDemFromProj(input_raster, minX, maxX, minY,
93+
maxY, &dem_interp, proj.get(),
94+
dem_margin_in_pixels,
95+
dem_margin_in_pixels,
96+
band_index + 1);
97+
98+
if (error_code != isce3::error::ErrorCode::Success) {
99+
std::string error_message =
100+
"ERROR loading raster for given area";
101+
throw isce3::except::RuntimeError(ISCE_SRCINFO(), error_message);
102+
}
103+
104+
/*
105+
Get DEM interpolator and function getDemCoords to convert DEM coordinates
106+
to the geogrid EPSG coordinates:
107+
*/
108+
std::function<isce3::core::Vec3(double, double,
109+
const isce3::geometry::DEMInterpolator&,
110+
isce3::core::ProjectionBase*)> getDemCoords;
111+
112+
if (geogrid.epsg() == input_raster.getEPSG()) {
113+
getDemCoords = isce3::geometry::getDemCoordsSameEpsg;
114+
115+
} else {
116+
getDemCoords = isce3::geometry::getDemCoordsDiffEpsg;
117+
}
118+
119+
auto interpolated_dem_array = getNanArray<float>(geogrid);
120+
121+
#pragma omp parallel for
122+
for (int i = 0; i < geogrid.length(); ++i) {
123+
double pos_y = geogrid.startY() + (0.5 + i) * geogrid.spacingY();
124+
for (int j = 0; j < geogrid.width(); ++j) {
125+
double pos_x =
126+
geogrid.startX() + (0.5 + j) * geogrid.spacingX();
127+
128+
const isce3::core::Vec3 input_dem =
129+
getDemCoords(pos_x, pos_y, dem_interp, proj.get());
130+
131+
interpolated_dem_array(i, j) = input_dem[2];
132+
}
133+
}
134+
135+
writeArray(output_raster, interpolated_dem_array, band_index);
136+
137+
}
138+
139+
double geotransform[] = {
140+
geogrid.startX(), geogrid.spacingX(), 0, geogrid.startY(), 0,
141+
geogrid.spacingY()};
142+
143+
output_raster.setGeoTransform(geotransform);
144+
output_raster.setEPSG(geogrid.epsg());
145+
146+
}
147+
148+
}}

cxx/isce3/geogrid/relocateRaster.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#pragma once
2+
3+
#include <isce3/core/Constants.h>
4+
#include <isce3/core/forward.h>
5+
#include <isce3/io/forward.h>
6+
#include <isce3/product/forward.h>
7+
8+
namespace isce3 { namespace geogrid {
9+
10+
/** Relocate raster
11+
*
12+
* Interpolate a raster file over a given geogrid.
13+
* Invalid pixels are filled with NaN. The output raster is expected to
14+
* have the same length & width as the specified geogrid, and the same
15+
* number of bands as the input raster.
16+
*
17+
* @param[in] input_raster Input raster
18+
* @param[in] geogrid Output DEM geogrid
19+
* @param[out] output_raster Output raster
20+
* @param[in] interp_method Interpolation method
21+
*/
22+
void relocateRaster(
23+
isce3::io::Raster& input_raster,
24+
const isce3::product::GeoGridParameters& geogrid,
25+
isce3::io::Raster& output_raster,
26+
isce3::core::dataInterpMethod interp_method =
27+
isce3::core::dataInterpMethod::BIQUINTIC_METHOD);
28+
29+
}}

cxx/isce3/geometry/DEMInterpolator.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ void isce3::geometry::DEMInterpolator::epsgCode(int epsgcode) {
2828
* Loads a DEM subset given the extents of a bounding box */
2929
isce3::error::ErrorCode isce3::geometry::DEMInterpolator::loadDEM(
3030
isce3::io::Raster& demRaster, double min_x, double max_x, double min_y,
31-
double max_y)
31+
double max_y, const int dem_raster_band)
3232
{
3333

3434
// Initialize journal
@@ -318,7 +318,8 @@ isce3::error::ErrorCode isce3::geometry::DEMInterpolator::loadDEM(
318318

319319
if (!flag_dem_file_discontinuity) {
320320
// Read single block from DEM
321-
demRaster.getBlock(_dem.data(), min_x_idx, min_y_idx, width, length);
321+
demRaster.getBlock(_dem.data(), min_x_idx, min_y_idx, width, length,
322+
dem_raster_band);
322323

323324
} else {
324325

@@ -333,8 +334,9 @@ isce3::error::ErrorCode isce3::geometry::DEMInterpolator::loadDEM(
333334
isce3::core::Matrix<float> dem_discontinuity_left;
334335

335336
dem_discontinuity_left.resize(length, width_discontinuity_left);
336-
demRaster.getBlock(dem_discontinuity_left.data(), min_x_idx, min_y_idx,
337-
width_discontinuity_left, length);
337+
demRaster.getBlock(dem_discontinuity_left.data(), min_x_idx,
338+
min_y_idx, width_discontinuity_left, length,
339+
dem_raster_band);
338340

339341
_Pragma("omp parallel for schedule(dynamic)")
340342
for (long i=0; i < length; ++i) {
@@ -402,8 +404,10 @@ isce3::error::ErrorCode isce3::geometry::DEMInterpolator::loadDEM(
402404
isce3::core::Matrix<float> dem_discontinuity_right;
403405

404406
dem_discontinuity_right.resize(length, width_discontinuity_right);
405-
demRaster.getBlock(dem_discontinuity_right.data(), min_x_idx_discontinuity_right,
406-
min_y_idx, width_discontinuity_right, length);
407+
demRaster.getBlock(dem_discontinuity_right.data(),
408+
min_x_idx_discontinuity_right, min_y_idx,
409+
width_discontinuity_right, length,
410+
dem_raster_band);
407411

408412
_Pragma("omp parallel for schedule(dynamic)")
409413
for (long i=0; i < length; ++i) {
@@ -436,12 +440,13 @@ isce3::error::ErrorCode isce3::geometry::DEMInterpolator::loadDEM(
436440
return isce3::error::ErrorCode::Success;
437441
}
438442

443+
439444
// Load DEM into memory
440445
/** @param[in] demRaster input DEM raster to subset
441446
*
442447
* Loads the entire DEM */
443448
void isce3::geometry::DEMInterpolator::
444-
loadDEM(isce3::io::Raster & demRaster) {
449+
loadDEM(isce3::io::Raster & demRaster, const int dem_raster_band) {
445450

446451
//Get the dimensions of the raster
447452
int width = demRaster.width();
@@ -472,7 +477,7 @@ loadDEM(isce3::io::Raster & demRaster) {
472477
_dem.resize(length, width);
473478

474479
// Read in the DEM
475-
demRaster.getBlock(_dem.data(), 0, 0, width, length);
480+
demRaster.getBlock(_dem.data(), 0, 0, width, length, dem_raster_band);
476481

477482
// Initialize internal interpolator
478483
_interp = std::unique_ptr<isce3::core::Interpolator<float>>(isce3::core::createInterpolator<float>(_interpMethod));

0 commit comments

Comments
 (0)