Skip to content

Commit eb6b392

Browse files
Liang YuGitHub Enterprise
authored andcommitted
free function to replace existing doppler LUT2d to LUT1d conversions (#569)
* Added individual getters and setters for primary and secondary doppler for CPU & CUDA crossmul * Replaced LUT1d from LUT2d constructor and operator= with free function avgLUT2dToLUT1d * Averaging can now be done on either axis and matches numpy array convention. Default is along columns.
1 parent f8c2962 commit eb6b392

File tree

24 files changed

+223
-153
lines changed

24 files changed

+223
-153
lines changed

cxx/isce3/core/LUT1d.h

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1-
//-*- C++ -*-
2-
//-*- coding: utf-8 -*-
3-
//
4-
// Source Author: Bryan Riel
5-
// Copyright 2017-2018
6-
//
7-
81
#pragma once
92

103
#include "forward.h"
4+
#include <isce3/core/EMatrix.h>
5+
#include <isce3/except/Error.h>
116

127
#include <valarray>
138

9+
namespace isce3::core {
10+
1411
/** Data structure to hold a 1D Lookup table.
1512
* Suitable for storing data of the form y = f(x)*/
1613
template <typename T>
17-
class isce3::core::LUT1d {
14+
class LUT1d {
1815

1916
public:
2017
/** Default constructor */
@@ -34,19 +31,19 @@ class isce3::core::LUT1d {
3431
_values.resize(size);
3532
}
3633

37-
/** Constructor with coordinates and values
34+
/** Constructor with coordinates and values
3835
* @param[in] coords Valarray for coordinates of LUT
3936
* @param[in] values Valarray for values of LUT
4037
* @param[in] extrapolate Flag for allowing extrapolation beyond bounds */
4138
inline LUT1d(const std::valarray<double> & coords, const std::valarray<T> & values,
42-
bool extrapolate = false) :
39+
bool extrapolate = false) :
4340
_haveData(true),
4441
_refValue(values[0]),
4542
_coords(coords),
4643
_values(values),
4744
_extrapolate{extrapolate} {}
4845

49-
/** Copy constructor.
46+
/** Copy constructor.
5047
* @param[in] lut LUT1d object to copy from */
5148
inline LUT1d(const LUT1d<T> & lut) :
5249
_haveData(lut.haveData()),
@@ -55,7 +52,7 @@ class isce3::core::LUT1d {
5552
_values(lut.values()),
5653
_extrapolate(lut.extrapolate()) {}
5754

58-
/** Assignment operator.
55+
/** Assignment operator.
5956
* @param[in] lut LUT1d object to assign from */
6057
inline LUT1d & operator=(const LUT1d<T> & lut) {
6158
_haveData = lut.haveData();
@@ -66,41 +63,35 @@ class isce3::core::LUT1d {
6663
return *this;
6764
}
6865

69-
/** Constructor from an LUT2d (values averaged in y-direction) */
70-
inline LUT1d(const LUT2d<T> & lut2d);
71-
72-
/** Assignment operator from an LUT2d (values averaged in y-direction) */
73-
inline LUT1d & operator=(const LUT2d<T> & lut2d);
74-
7566
/** Get a reference to the coordinates
7667
* @param[out] coords Reference to valarray for coordinates */
7768
inline std::valarray<double> & coords() { return _coords; }
7869

79-
/** Get a read-only reference to the coordinates
70+
/** Get a read-only reference to the coordinates
8071
* @param[out] coords Copy of valarray for coordinates */
8172
inline const std::valarray<double> & coords() const { return _coords; }
8273

83-
/** Set the coordinates
84-
* @param[in] c Input valarray for coordinates */
74+
/** Set the coordinates
75+
* @param[in] c Input valarray for coordinates */
8576
inline void coords(const std::valarray<double> & c) { _coords = c; }
8677

8778
/** Get a reference to the coordinates
8879
* @param[out] values Reference to valarray for values */
8980
inline std::valarray<T> & values() { return _values; }
9081

91-
/** Get a read-only reference to the values
82+
/** Get a read-only reference to the values
9283
* @param[out] values Copy of valarray for values */
9384
inline const std::valarray<T> & values() const { return _values; }
9485

95-
/** Set the values
86+
/** Set the values
9687
* @param[in] v Input valarray for values */
9788
inline void values(const std::valarray<T> & v) { _values = v; }
9889

99-
/** Get extrapolate flag
90+
/** Get extrapolate flag
10091
* @param[out] flag Extrapolation flag */
10192
inline bool extrapolate() const { return _extrapolate; }
10293

103-
/** Set extrapolate flag
94+
/** Set extrapolate flag
10495
* @param[in] flag Extrapolation flag */
10596
inline void extrapolate(bool flag) { _extrapolate = flag; }
10697

@@ -110,7 +101,7 @@ class isce3::core::LUT1d {
110101
/** Get reference value */
111102
inline T refValue() const { return _refValue; }
112103

113-
/** Get size of LUT
104+
/** Get size of LUT
114105
* @param[out] size Size (number of coordinates) of LUT */
115106
inline size_t size() const { return _coords.size(); }
116107

@@ -126,6 +117,15 @@ class isce3::core::LUT1d {
126117
bool _extrapolate;
127118
};
128119

120+
/** Convert LUT2d to LUT1d by averaging along rows or columns
121+
* @param[out] lut1d LUT1d resulting from averaged LUT2d
122+
* @param[in] lut2d LUT2d to be converted
123+
* @param[in] axis Int Axis to be averaged. 0 for columns and 1 rows */
124+
template <typename T>
125+
LUT1d<T> avgLUT2dToLUT1d(const LUT2d<T> & lut2d, const int axis = 0);
126+
127+
} // namespace isce3::core
128+
129129
// Get inline implementations for LUT1d
130130
#define ISCE_CORE_LUT1D_ICC
131131
#include "LUT1d.icc"

cxx/isce3/core/LUT1d.icc

Lines changed: 48 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,9 @@
1-
//-*- C++ -*-
2-
//-*- coding: utf-8 -*-
3-
//
4-
// Source Author: Bryan Riel
5-
// Copyright 2017-2018
6-
//
7-
81
#if !defined(ISCE_CORE_LUT1D_ICC)
92
#error "LUT1d.icc is an implementation detail of class LUT1d"
103
#endif
114

125
#include <pyre/journal.h>
136

14-
// Constructor from an LUT2d (values averaged in y-direction)
15-
/** @param[in] lut2d LUT2d to copy data from */
16-
template <typename T>
17-
isce3::core::LUT1d<T>::
18-
LUT1d(const isce3::core::LUT2d<T> & lut2d) {
19-
20-
// Check if LUT2d has actual data; if not, just store reference value
21-
if (!lut2d.haveData()) {
22-
_haveData = false;
23-
_refValue = lut2d.refValue();
24-
return;
25-
}
26-
27-
// Get a reference to the LUT2d data
28-
const isce3::core::Matrix<T> & data = lut2d.data();
29-
30-
// Initialize working valarrays for computing mean along y-direction
31-
std::valarray<double> values(lut2d.width()), count(lut2d.width());
32-
values = 0.0;
33-
count = 0.0;
34-
35-
// Compute sum along columns (y-direction)
36-
for (size_t i = 0; i < lut2d.length(); ++i) {
37-
for (size_t j = 0; j < lut2d.width(); ++j) {
38-
values[j] += data(i,j);
39-
count[j] += 1.0;
40-
}
41-
}
42-
43-
// Compute final coordinates and values
44-
std::valarray<double> coords(lut2d.width());
45-
for (size_t j = 0; j < lut2d.width(); ++j) {
46-
coords[j] = lut2d.xStart() + j * lut2d.xSpacing();
47-
values[j] /= count[j];
48-
}
49-
50-
// Save results
51-
_coords = coords;
52-
_values = values;
53-
_extrapolate = true;
54-
_haveData = true;
55-
_refValue = lut2d.refValue();
56-
}
57-
58-
// Assignment operator from an LUT2d (values averaged in y-direction)
59-
/** @param[in] lut2d LUT2d to copy data from */
60-
template <typename T>
61-
isce3::core::LUT1d<T> &
62-
isce3::core::LUT1d<T>::
63-
operator=(const LUT2d<T> & lut2d) {
64-
65-
// Check if LUT2d has actual data; if not, just store reference value
66-
if (!lut2d.haveData()) {
67-
_haveData = false;
68-
_refValue = lut2d.refValue();
69-
return *this;
70-
}
71-
72-
// Get a reference to the LUT2d data
73-
const isce3::core::Matrix<T> & data = lut2d.data();
74-
75-
// Initialize working valarrays for computing mean along y-direction
76-
std::valarray<double> values(lut2d.width()), count(lut2d.width());
77-
values = 0.0;
78-
count = 0.0;
79-
80-
// Compute sum along columns (y-direction)
81-
for (size_t i = 0; i < lut2d.length(); ++i) {
82-
for (size_t j = 0; j < lut2d.width(); ++j) {
83-
values[j] += data(i,j);
84-
count[j] += 1.0;
85-
}
86-
}
87-
88-
// Compute final coordinates and values
89-
std::valarray<double> coords(lut2d.width());
90-
for (size_t j = 0; j < lut2d.width(); ++j) {
91-
coords[j] = lut2d.xStart() + j * lut2d.xSpacing();
92-
values[j] /= count[j];
93-
}
94-
95-
// Save results
96-
_coords = coords;
97-
_values = values;
98-
_extrapolate = true;
99-
return *this;
100-
}
101-
1027
/** @param[in] x Point to evaluate the LUT
1038
* @param[out] result Interpolated value */
1049
template <typename T>
@@ -179,7 +84,7 @@ eval(double x) const {
17984
// The indices of the x bounds
18085
const int j0 = high - 1;
18186
const int j1 = high;
182-
87+
18388
// Get coordinates at bounds
18489
double x1 = _coords[j0];
18590
double x2 = _coords[j1];
@@ -189,4 +94,50 @@ eval(double x) const {
18994
return result;
19095
}
19196

192-
// end of file
97+
template <typename T>
98+
isce3::core::LUT1d<T>
99+
isce3::core::avgLUT2dToLUT1d(const isce3::core::LUT2d<T> & lut2d,
100+
const int axis) {
101+
if (axis != 0 && axis != 1) {
102+
std::string error_msg = "ERROR axis not equal to 0 or 1";
103+
throw isce3::except::InvalidArgument(ISCE_SRCINFO(), error_msg);
104+
}
105+
106+
// Check if LUT2d has actual data; if not, just return LUT1d with reference value
107+
if (!lut2d.haveData()) {
108+
return isce3::core::LUT1d<T>(lut2d.refValue());
109+
}
110+
111+
// Determine lut1d size and number of elements to sum
112+
const auto lut1d_size = (axis == 0) ? lut2d.width() : lut2d.length();
113+
const double n_to_sum_f = (axis == 0) ? static_cast<double>(lut2d.length()) :
114+
static_cast<double>(lut2d.width());
115+
116+
// Get a reference to the LUT2d data
117+
const Matrix<T> & data = lut2d.data();
118+
119+
// Compute sum and average
120+
isce3::core::EArray2D<double> ea_values;
121+
if (axis == 0)
122+
// Sum along rows (x-direction)
123+
ea_values = data.map().colwise().sum();
124+
else
125+
// Sum along columns (y-direction)
126+
ea_values = data.map().rowwise().sum();
127+
ea_values /= n_to_sum_f;
128+
129+
// Initialize working valarrays for computing mean along y-direction
130+
std::valarray<double> values(0.0, lut1d_size);
131+
std::copy(ea_values.data(), ea_values.data() + ea_values.size(), begin(values));
132+
133+
// Compute final coordinates and values
134+
std::valarray<double> coords(lut1d_size);
135+
for (size_t j = 0; j < lut1d_size; ++j) {
136+
if (axis == 0)
137+
coords[j] = lut2d.xStart() + j * lut2d.xSpacing();
138+
else
139+
coords[j] = lut2d.yStart() + j * lut2d.ySpacing();
140+
}
141+
142+
return isce3::core::LUT1d<T>(coords, values, true);
143+
}

cxx/isce3/cuda/geometry/Geo2rdr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ geo2rdr(isce3::io::Raster & topoRaster,
7474
// Cache ISCE objects (use public interface of parent isce3::geometry::Geo2rdr class)
7575
const Ellipsoid & ellipsoid = this->ellipsoid();
7676
const Orbit & orbit = this->orbit();
77-
const LUT1d<double> doppler(this->doppler());
77+
const LUT1d<double> doppler = isce3::core::avgLUT2dToLUT1d<double>(this->doppler());
7878
const RadarGridParameters & radarGrid = this->radarGridParameters();
7979

8080
// Cache sensing start in seconds since reference epoch

cxx/isce3/cuda/geometry/Topo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ topo(Raster & demRaster, TopoLayers & layers) {
159159
// Cache ISCE objects (use public interface of parent isce3::geometry::Topo class)
160160
const Ellipsoid & ellipsoid = this->ellipsoid();
161161
const Orbit & orbit = this->orbit();
162-
const LUT1d<double> doppler(this->doppler());
162+
const LUT1d<double> doppler = isce3::core::avgLUT2dToLUT1d<double>(this->doppler());
163163
const RadarGridParameters & radarGrid = this->radarGridParameters();
164164

165165
// Create and start a timer

cxx/isce3/cuda/geometry/gpuRTC.cu

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
__constant__ double start, r0, pixazm, dr;
3333
__constant__ float xbound, ybound;
3434

35+
using isce3::core::avgLUT2dToLUT1d;
3536
using isce3::core::OrbitInterpBorderMode;
3637
using isce3::core::Vec3;
3738
using isce3::core::Mat3;
@@ -330,7 +331,7 @@ void computeRtc(isce3::product::Product& product, isce3::io::Raster& dem,
330331

331332
// Convert LUT2d doppler to LUT1d
332333
isce3::core::LUT1d<double> dop_h(
333-
product.metadata().procInfo().dopplerCentroid(frequency));
334+
avgLUT2dToLUT1d(product.metadata().procInfo().dopplerCentroid(frequency)));
334335
isce3::cuda::core::gpuLUT1d<double> dop(dop_h);
335336

336337
const size_t xmax = dem_interp.width() * upsample_factor;

cxx/isce3/cuda/image/ResampSlc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ resamp(isce3::io::Raster & inputSlc, isce3::io::Raster & outputSlc,
111111
// Perform interpolation
112112
std::cout << "Interpolating tile " << tileCount << std::endl;
113113
gpuTransformTile(tile, outputSlc, rgOffTile, azOffTile, _rgCarrier, _azCarrier,
114-
_dopplerLUT, interp, inWidth, inLength, this->startingRange(),
114+
isce3::core::avgLUT2dToLUT1d<double>(_dopplerLUT), interp, inWidth, inLength, this->startingRange(),
115115
this->rangePixelSpacing(), this->prf(), this->wavelength(),
116116
this->refStartingRange(), this->refRangePixelSpacing(),
117117
this->refWavelength(), flatten, chipSize);

cxx/isce3/cuda/signal/gpuCrossMul.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,21 @@ class isce3::cuda::signal::gpuCrossmul {
2828
isce3::io::Raster& interferogram,
2929
isce3::io::Raster& coherenceRaster) const;
3030

31-
/** Set doppler LUTs for reference and secondary SLCs*/
32-
void doppler(isce3::core::LUT1d<double>,
33-
isce3::core::LUT1d<double>);
31+
/** Set doppler LUTs for reference and secondary SLCs*/
32+
void doppler(isce3::core::LUT1d<double> refDoppler,
33+
isce3::core::LUT1d<double> secDoppler);
34+
35+
/** Set reference doppler */
36+
inline void refDoppler(isce3::core::LUT1d<double> refDopp) {_refDoppler = refDopp;};
37+
38+
/** Get reference doppler */
39+
inline const isce3::core::LUT1d<double> & refDoppler() const {return _refDoppler;};
40+
41+
/** Set secondary doppler */
42+
inline void secDoppler(isce3::core::LUT1d<double> secDopp) {_secDoppler = secDopp;};
43+
44+
/** Get secondary doppler */
45+
inline const isce3::core::LUT1d<double> & secDoppler() const {return _secDoppler;};
3446

3547
/** Set pulse repetition frequency (PRF) */
3648
inline void prf(double p_r_f) {_prf = p_r_f;};

cxx/isce3/signal/Crossmul.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@ class isce3::signal::Crossmul {
7171
inline void doppler(isce3::core::LUT1d<double>,
7272
isce3::core::LUT1d<double>);
7373

74+
/** Set dopplers LUT for reference SLC */
75+
inline void refDoppler(isce3::core::LUT1d<double> refDopp) { _refDoppler = refDopp; }
76+
77+
/** Get doppler LUT for reference SLC */
78+
inline const isce3::core::LUT1d<double> & refDoppler() const { return _refDoppler; }
79+
80+
/** Set dopplers LUT for secondary SLC */
81+
inline void secDoppler(isce3::core::LUT1d<double> secDopp) { _secDoppler = secDopp; }
82+
83+
/** Get doppler LUT for secondary SLC */
84+
inline const isce3::core::LUT1d<double> & secDoppler() const { return _secDoppler; }
85+
7486
/** Set pulse repetition frequency (PRF) */
7587
inline void prf(double prf) { _prf = prf; }
7688

python/extensions/pybind_isce3/Sources.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ core/Linspace.cpp
1818
core/LookSide.cpp
1919
core/LUT1d.cpp
2020
core/LUT2d.cpp
21+
core/avgLUT2dToLUT1d.cpp
2122
core/Orbit.cpp
2223
core/Projections.cpp
2324
core/Quaternion.cpp

0 commit comments

Comments
 (0)