Skip to content

Commit

Permalink
Merge pull request isce-framework#5 from isce-3/develop
Browse files Browse the repository at this point in the history
update
  • Loading branch information
jungkyoJung authored and GitHub Enterprise committed Mar 4, 2022
2 parents aa5b16a + d541a52 commit 1b1b85d
Show file tree
Hide file tree
Showing 269 changed files with 27,759 additions and 3,184 deletions.
1 change: 1 addition & 0 deletions .ci/images/centos/requirements.txt.base
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ scipy
testfixtures
scikit-image
shapely
backoff
1 change: 1 addition & 0 deletions .ci/images/conda/tester/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ RUN conda install -q -y \
shapely \
sphinx \
wget \
backoff \
&& conda install -q -y -c conda-forge \
ruamel.yaml \
yamale \
Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ if (WITH_CUDA)

# check CUDA version
set(CUDA_VERSION ${CMAKE_CUDA_COMPILER_VERSION})
if (CUDA_VERSION VERSION_LESS 9)
message(FATAL_ERROR "CUDA version must be at least 9. Detected ${CUDA_VERSION}")
if (CUDA_VERSION VERSION_LESS 11)
message(FATAL_ERROR "CUDA version must be at least 11. Detected ${CUDA_VERSION}")
endif()

# specify target CUDA device architecture(s)
Expand Down
10 changes: 10 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,13 @@ THE USER HAS THE RESPONSIBILITY TO OBTAIN EXPORT LICENSES, OR OTHER EXPORT
AUTHORITY AS MAY BE REQUIRED BEFORE EXPORTING THIS SOFTWARE TO ANY 'EAR99'
EMBARGOED FOREIGN COUNTRY OR CITIZEN OF THOSE COUNTRIES.

===============================================================================
Software from third parties included in ISCE3:
===============================================================================
ISCE3 contains third party software which is under different license terms. All
such code will be identified clearly using at least one of two mechanisms:
1) It will be in a separate directory tree with its own `LICENSE` or `README`
file at the top containing the specific license and restrictions which apply
to that software, or
2) It will contain specific license and restriction terms at the top of every
file.
2 changes: 1 addition & 1 deletion VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.4.0-dev
0.5.0-dev
2 changes: 1 addition & 1 deletion cxx/isce3/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ target_link_libraries(${LISCE} PRIVATE
)

target_compile_features(${LISCE} INTERFACE
cxx_std_14
cxx_std_17
)

target_include_directories(${LISCE} PUBLIC
Expand Down
15 changes: 10 additions & 5 deletions cxx/isce3/Headers.cmake
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
set(HEADERS
antenna/detail/BinarySearchFunc.h
antenna/detail/WinChirpRgCompPow.h
antenna/detail/WinChirpRgCompPow.icc
antenna/edge_method_cost_func.h
antenna/forward.h
antenna/ElPatternEst.h
antenna/geometryfunc.h
antenna/ElNullAnalyses.h
antenna/ElNullRangeEst.h
antenna/EdgeMethodCostFunc.h
antenna/Frame.h
antenna/Frame.icc
antenna/forward.h
antenna/geometryfunc.h
antenna/SphGridType.h
antenna/SphGridType.icc
container/forward.h
Expand Down Expand Up @@ -80,7 +83,6 @@ focus/Presum.icc
focus/RangeComp.h
geocode/baseband.h
geocode/geocodeSlc.h
geocode/interpolate.h
geocode/loadDem.h
geometry/DEMInterpolator.h
geometry/forward.h
Expand Down Expand Up @@ -124,7 +126,8 @@ io/Raster.h
io/Raster.icc
io/Serialization.h
math/Bessel.h
math/ComplexMultiply.h
math/complexOperations.h
math/Stats.h
math/detail/RootFind1dBase.h
math/polyfunc.h
math/RootFind1dNewton.h
Expand Down Expand Up @@ -183,4 +186,6 @@ unwrap/phass/Point.h
unwrap/phass/RegionMap.h
unwrap/phass/Seed.h
unwrap/phass/sort.h
unwrap/snaphu/snaphu.h
unwrap/snaphu/snaphu_unwrap.h
)
13 changes: 11 additions & 2 deletions cxx/isce3/Sources.cmake
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
set(SRCS
antenna/edge_method_cost_func.cpp
antenna/detail/BinarySearchFunc.cpp
antenna/ElPatternEst.cpp
antenna/ElNullAnalyses.cpp
antenna/ElNullRangeEst.cpp
antenna/EdgeMethodCostFunc.cpp
antenna/geometryfunc.cpp
core/Attitude.cpp
core/Baseline.cpp
Expand Down Expand Up @@ -40,7 +43,6 @@ focus/Presum.cpp
focus/RangeComp.cpp
geocode/baseband.cpp
geocode/geocodeSlc.cpp
geocode/interpolate.cpp
geocode/loadDem.cpp
geometry/DEMInterpolator.cpp
geometry/Geo2rdr.cpp
Expand All @@ -60,6 +62,7 @@ io/IH5.cpp
io/IH5Dataset.cpp
io/Raster.cpp
math/Bessel.cpp
math/Stats.cpp
math/polyfunc.cpp
math/RootFind1dNewton.cpp
math/RootFind1dSecant.cpp
Expand Down Expand Up @@ -99,4 +102,10 @@ unwrap/phass/Point.cc
unwrap/phass/RegionMap.cc
unwrap/phass/Seed.cc
unwrap/phass/sort.cc
unwrap/snaphu/snaphu_cost.cpp
unwrap/snaphu/snaphu.cpp
unwrap/snaphu/snaphu_io.cpp
unwrap/snaphu/snaphu_solver.cpp
unwrap/snaphu/snaphu_tile.cpp
unwrap/snaphu/snaphu_util.cpp
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#include <Eigen/Dense>

#include <isce3/antenna/edge_method_cost_func.h>
#include <isce3/antenna/EdgeMethodCostFunc.h>
#include <isce3/except/Error.h>
#include <isce3/math/RootFind1dNewton.h>
#include <isce3/math/polyfunc.h>
Expand Down Expand Up @@ -137,9 +137,8 @@ std::tuple<double, double, bool, int> rollAngleOffsetFromEdge(
"Near-range look angle shall be smaller than "
"far one by at least one prec!");

const auto ang_size =
static_cast<int>((look_ang_far - look_ang_near) / look_ang_prec) +
1;
const auto ang_size = static_cast<int>(
std::round((look_ang_far - look_ang_near) / look_ang_prec) + 1);
auto look_ang = isce3::core::Linspace<double>::from_interval(
look_ang_near, look_ang_far, ang_size);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/** @file edge_method_cost_func.h
/** @file EdgeMethodCostFunc.h
* Cost functions used in EL antenna pointing estimation via edge method
*/
#pragma once
Expand Down
224 changes: 224 additions & 0 deletions cxx/isce3/antenna/ElNullAnalyses.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
#include "ElNullAnalyses.h"

#include <algorithm>
#include <cmath>
#include <numeric>

#include <isce3/core/Interp1d.h>
#include <isce3/core/Kernels.h>
#include <isce3/except/Error.h>
#include <isce3/focus/RangeComp.h>

namespace isce3 { namespace antenna {

Eigen::ArrayXcd linearInterpComplex1d(
const Eigen::Ref<const Eigen::ArrayXd>& x0, const Linspace_t& x,
const Eigen::Ref<const Eigen::ArrayXcd>& y)
{
// check the input arguments
if (!(x.spacing() > 0.0))
throw isce3::except::InvalidArgument(ISCE_SRCINFO(),
"The argument 'x' must be monotonically increasing!");
if (x.size() != y.size())
throw isce3::except::InvalidArgument(ISCE_SRCINFO(),
"The arguments 'x' and 'y' must have the same size!");
if ((x0.minCoeff() < x.first()) || (x0.maxCoeff() > x.last()))
throw isce3::except::InvalidArgument(
ISCE_SRCINFO(), "The 'x0' values are out of range of 'x'!");

// form the linear kernel
auto linear_kernel = isce3::core::LinearKernel<double>();
// allocate interpolated output vector
Eigen::ArrayXcd y0(x0.size());
#pragma omp parallel for
for (Eigen::Index idx = 0; idx < x0.size(); ++idx) {
auto x_int = (x0(idx) - x.first()) / x.spacing();
y0(idx) = isce3::core::interp1d(
linear_kernel, y.data(), y.size(), 1, x_int, false);
}
return y0;
}

tuple_ant genAntennaPairCoefs(
const Eigen::Ref<const Eigen::ArrayXcd>& el_cut_left,
const Eigen::Ref<const Eigen::ArrayXcd>& el_cut_right,
double el_ang_start, double el_ang_step,
std::optional<double> el_res_max)
{
// check input arguments
if (!(el_ang_step > 0.0))
throw isce3::except::InvalidArgument(
ISCE_SRCINFO(), "EL angle step must be a positive value!");

if (el_res_max) {
if (!(*el_res_max > 0.0))
throw isce3::except::InvalidArgument(ISCE_SRCINFO(),
"Max EL angle resolution must be a positive value!");
} else
*el_res_max = el_ang_step;

const auto cut_size {el_cut_left.size()};
if (el_cut_right.size() != cut_size)
throw isce3::except::InvalidArgument(ISCE_SRCINFO(),
"Size mismatch between two EL-cut vectors left and right!");

// pick EL cut patterns within peak-to-peak power gains of two adjacent
// beams, resample/interpolate the picked values into finer el-resolution if
// necessary based on min (_el_res_max, el_ang_step) and store their
// conjugate versions as final weighting coefs as a function EL angle vector
// "el_ang_vec" in (rad).
Eigen::Index idx_peak_left;
Eigen::Index idx_peak_right;
el_cut_left.abs().maxCoeff(&idx_peak_left);
el_cut_right.abs().maxCoeff(&idx_peak_right);
if (idx_peak_left >= idx_peak_right)
throw isce3::except::InvalidArgument(ISCE_SRCINFO(),
"Wrong order or incorrect EL cuts of left and right beams!");

// take out one sample on each side (that is to exclude the peaks)
idx_peak_left += 1;
idx_peak_right -= 1;
// check to have at least 3 points!
auto num_idx_p2p = idx_peak_right - idx_peak_left + 1;
if (num_idx_p2p < 3)
throw isce3::except::RuntimeError(ISCE_SRCINFO(),
"There is not enough samples/separation "
"between peaks of EL cuts!");

// form output uniform EL angle vector within [idx_peak_left,
// idx_peak_right]
auto el_space = std::min(*el_res_max, el_ang_step);
auto el_start = idx_peak_left * el_ang_step + el_ang_start;
auto el_stop = idx_peak_right * el_ang_step + el_ang_start;
auto num_idx = static_cast<Eigen::Index>(
std::round((el_stop - el_start) / el_space) + 1);

Eigen::ArrayXd el_vec =
Eigen::ArrayXd::LinSpaced(num_idx, el_start, el_stop);

// interpolate the complex coeff within [idx_peak_left, idx_peak_right] if
// necessary
if (*el_res_max < el_ang_step)
// perform linear interpolation of complex coeffs
{
auto el_ang_linspace = Linspace_t(el_ang_start, el_ang_step, cut_size);
Eigen::ArrayXcd coef_left = Eigen::conj(
linearInterpComplex1d(el_vec, el_ang_linspace, el_cut_left));
Eigen::ArrayXcd coef_right = Eigen::conj(
linearInterpComplex1d(el_vec, el_ang_linspace, el_cut_right));
return std::make_tuple(coef_left, coef_right, el_vec);
}
// no interpolation
return std::make_tuple(
Eigen::conj(el_cut_left.segment(idx_peak_left, num_idx)),
Eigen::conj(el_cut_right.segment(idx_peak_left, num_idx)), el_vec);
}

std::tuple<double, Eigen::Index, double> locateAntennaNull(
const Eigen::Ref<const Eigen::ArrayXcd>& coef_left,
const Eigen::Ref<const Eigen::ArrayXcd>& coef_right,
const Eigen::Ref<const Eigen::ArrayXd>& el_ang_vec)
{
// antenna null power pattern = |left**2 - right**2|/(left**2 + right**2)
// Its min is the null location.
auto pow_ant_left = coef_left.abs2();
auto pow_ant_right = coef_right.abs2();
Eigen::ArrayXd pow_null_ant = (pow_ant_left - pow_ant_right).abs() /
(pow_ant_left + pow_ant_right);
// locate the null from power pattern
Eigen::Index idx_null_ant;
double min_val = pow_null_ant.minCoeff(&idx_null_ant);
double max_val = pow_null_ant.maxCoeff();
if (!(max_val > min_val))
throw isce3::except::RuntimeError(ISCE_SRCINFO(),
"The antenna null pattern does not have a dip!");
// get the peak-normalized null value in linear scale
double val_null {min_val / max_val};
// get EL angle of the null in (rad)
double el_null_ant = el_ang_vec(idx_null_ant);
return {el_null_ant, idx_null_ant, val_null};
}

tuple_echo formEchoNull(const std::vector<std::complex<float>>& chirp_ref,
const Eigen::Ref<const RowMatrixXcf>& echo_left,
const Eigen::Ref<const RowMatrixXcf>& echo_right, double sr_start,
double sr_spacing, const Eigen::Ref<const Eigen::ArrayXcd>& coef_left,
const Eigen::Ref<const Eigen::ArrayXcd>& coef_right,
const Eigen::Ref<const Eigen::ArrayXd>& sr_coef)
{
// form rangecomp obj used for all range comp in forming echo null pattern
auto rgc_obj = isce3::focus::RangeComp(chirp_ref, echo_left.cols(), 1,
isce3::focus::RangeComp::Mode::Valid);
// final number of range bins for the echo after range comp
const auto num_rgb_echo = rgc_obj.outputSize();
// form uniform slant range (m) vector for only valid part of final
// rangecomp echo
const auto sr_stop = sr_start + (num_rgb_echo - 1) * sr_spacing;
Eigen::ArrayXd sr_echo_valid =
Eigen::ArrayXd::LinSpaced(num_rgb_echo, sr_start, sr_stop);

// get limited [first, last] indices by intersecting uniform slant ranges
// from only valid-mode rangecomp echo with that of non-uniform one from
// antenna weighting coefs
auto [idx_coef_first, idx_coef_last, idx_echo_first, idx_echo_last] =
detail::intersect_nearest(sr_coef, sr_echo_valid);
const auto size_coef = idx_coef_last - idx_coef_first + 1;
const auto num_rgb_null = idx_echo_last - idx_echo_first + 1;
// now get array of relative indices for mapping uniform sr_echo[first,
// last] to non-uniform sr_coeff[first, last]
auto idx_coef_vec =
detail::locate_nearest(sr_coef.segment(idx_coef_first, size_coef),
sr_echo_valid.segment(idx_echo_first, num_rgb_null));
// add the first index to all values for absolute mapping from echo[first,
// last] to antenna coeff.
idx_coef_vec += idx_coef_first;

// get limited coefs left/right within non-uniform indices "idx_coef_vec"
// related to uniform range bins of echo.
Eigen::ArrayXcd coef_left_limit(num_rgb_null);
Eigen::ArrayXcd coef_right_limit(num_rgb_null);
for (Eigen::Index idx = 0; idx < idx_coef_vec.size(); ++idx) {
coef_left_limit(idx) = coef_left(idx_coef_vec(idx));
coef_right_limit(idx) = coef_right(idx_coef_vec(idx));
}

// initialize the peak-normalized averaged echo null power
Eigen::ArrayXd pow_null_avg = Eigen::ArrayXd::Zero(num_rgb_null);
// allocate rangeline vector for range compression of left/right echoes
Eigen::ArrayXcf rgc_left(num_rgb_echo);
Eigen::ArrayXcf rgc_right(num_rgb_echo);
// allocate double precision lines for left and right weighted rangecomp
// echo within null formation part only
Eigen::ArrayXcd line_left(num_rgb_null);
Eigen::ArrayXcd line_right(num_rgb_null);
// loop over range lines /pulses
for (Eigen::Index pulse = 0; pulse < echo_left.rows(); ++pulse) {
// range compression of echoes left/right
rgc_obj.rangecompress(rgc_left.data(), echo_left.row(pulse).data());
rgc_obj.rangecompress(rgc_right.data(), echo_right.row(pulse).data());

// get the power and add up its double precision version
line_left = rgc_left.segment(idx_echo_first, num_rgb_null)
.cast<std::complex<double>>() *
coef_left_limit;
line_right = rgc_right.segment(idx_echo_first, num_rgb_null)
.cast<std::complex<double>>() *
coef_right_limit;

// form the null power to be averaged over range lines
pow_null_avg +=
(line_left - line_right).abs() / (line_left + line_right).abs();
}
auto max_pow_null = pow_null_avg.maxCoeff();
if (!(max_pow_null > pow_null_avg.minCoeff()))
throw isce3::except::RuntimeError(ISCE_SRCINFO(),
"The echo null power pattern does not have a dip!");
// peak-normalized power pattern
pow_null_avg /= max_pow_null;

// power (linear), slant range (m) , index for EL angles (-)
return std::make_tuple(pow_null_avg,
sr_coef.segment(idx_coef_vec(0), num_rgb_null), idx_coef_vec);
}

}} // namespace isce3::antenna
Loading

0 comments on commit 1b1b85d

Please sign in to comment.